From 6ecd5de4d956468b513030523c30179abab93184 Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Tue, 1 Aug 2006 12:36:19 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=10803 --- checkin_notes | 37 +++ client/app_start.C | 39 ++- client/check_security.C | 378 +++++++++++++++++------------ client/client_state.C | 19 +- client/client_types.C | 58 ++--- client/cs_cmdline.C | 3 + client/file_names.C | 75 +++--- client/gui_rpc_server.C | 12 +- client/main.C | 25 +- clientgui/BOINCGUIApp.cpp | 54 ++++- clientgui/BOINCGUIApp.h | 1 - clientgui/MainDocument.cpp | 77 +++--- clientgui/mac/Mac_GUI.cpp | 19 +- clientgui/mac/mac_saver_module.cpp | 2 + lib/boinc_cmd.C | 3 + lib/filesys.C | 44 ++-- lib/util.h | 10 +- mac_build/Mac_SA_Insecure.sh | 13 +- mac_build/Mac_SA_Secure.sh | 11 + mac_installer/PostInstall.cpp | 4 +- 20 files changed, 535 insertions(+), 349 deletions(-) diff --git a/checkin_notes b/checkin_notes index 8f702760fe..0bebc871d8 100755 --- a/checkin_notes +++ b/checkin_notes @@ -8203,3 +8203,40 @@ Bruce 31 July 2006 doc/ project_options.php +Charlie 1 Aug 2006 + - Sandbox: extend security to all UNIX and Linux platforms. To + enable this feature, add the compiler flag -DSANDBOX and add + check_security.C to the source file list for both Manager and + Client. + - Manager and Client both accept command-line argument -insecure + which runs without special boinc users and groups. Both + Manager and Client check owners and permissions and refuse + to run unless they are set correctly for the selected secure + or insecure mode. If Manager is called with -insecure, it + runs the Client with -insecure. + - Added code to Mac_SA_Secure.sh and Mac_SA_Insecure.sh scripts. + + client/ + app_start.C + check_security.C + client_state.C + client_types.C + cs_cmdline.C + file_names.C + gui_rpc_server.C + main.C + clientGUI/ + BOINCGUIApp.cpp,h + MainDocument.cpp + mac/ + Mac_GUI.cpp + mac_saver_module.cpp + lib/ + boinc_cmd.C + filesys.C + util.h + mac_build/ + Mac_SA_Insecure.sh + Mac_SA_Secure.sh + mac_installer/ + PostInstall.cpp diff --git a/client/app_start.C b/client/app_start.C index 0d9049cd41..d6cce6f47a 100644 --- a/client/app_start.C +++ b/client/app_start.C @@ -90,11 +90,10 @@ static int make_link(const char *existing, const char *new_link) { if (!fp) return ERR_FOPEN; fprintf(fp, "%s\n", existing); fclose(fp); -#ifdef SANDBOX - return set_to_project_group(new_link); -#else - return 0; -#endif + if (g_use_sandbox) + return set_to_project_group(new_link); + else + return 0; } int ACTIVE_TASK::link_user_files() { @@ -603,22 +602,22 @@ int ACTIVE_TASK::start(bool first_time) { char cmdline[8192]; strcpy(cmdline, wup->command_line.c_str()); sprintf(buf, "../../%s", exec_path ); -#ifdef SANDBOX - char switcher_path[100]; - sprintf(switcher_path, "../../%s/%s", SWITCHER_DIR, SWITCHER_FILE_NAME); - argv[0] = SWITCHER_FILE_NAME; - argv[1] = buf; - argv[2] = exec_name; - parse_command_line(cmdline, argv+3); - if (log_flags.task_debug) { - debug_print_argv(argv); + if (g_use_sandbox) { + char switcher_path[100]; + sprintf(switcher_path, "../../%s/%s", SWITCHER_DIR, SWITCHER_FILE_NAME); + argv[0] = SWITCHER_FILE_NAME; + argv[1] = buf; + argv[2] = exec_name; + parse_command_line(cmdline, argv+3); + if (log_flags.task_debug) { + debug_print_argv(argv); + } + retval = execv(switcher_path, argv); + } else { + argv[0] = exec_name; + parse_command_line(cmdline, argv+1); + retval = execv(buf, argv); } - retval = execv(switcher_path, argv); -#else - argv[0] = exec_name; - parse_command_line(cmdline, argv+1); - retval = execv(buf, argv); -#endif msg_printf(wup->project, MSG_ERROR, "Process creation (%s) failed: %s, errno=%d\n", buf, boincerror(retval), errno ); diff --git a/client/check_security.C b/client/check_security.C index cf5b17ad2d..d09d1f6d62 100644 --- a/client/check_security.C +++ b/client/check_security.C @@ -31,7 +31,11 @@ #include "error_numbers.h" #include "file_names.h" -static int CheckNestedDirectories(char * basepath, int depth); +static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox); + +#if (! defined(__WXMAC__) && ! defined(_MAC_INSTALLER)) +static void GetPathToThisProcess(char* outbuf, size_t maxLen); +#endif #define REAL_BOINC_MASTER_NAME "boinc_master" #define REAL_BOINC_PROJECT_NAME "boinc_project" @@ -50,8 +54,9 @@ static uid_t boinc_master_uid, boinc_project_uid; // Returns FALSE (0) if owners and permissions are OK, else TRUE (1) int check_security( #ifdef _MAC_INSTALLER -char *bundlePath, char *dataPath +char *bundlePath, char *dataPath, #endif +int use_sandbox, int isManager ) { passwd *pw; group *grp; @@ -60,6 +65,7 @@ char *bundlePath, char *dataPath char dir_path[MAXPATHLEN], full_path[MAXPATHLEN]; struct stat sbuf; int retval; + int useFakeProjectUserAndGroup = 0; #ifdef __WXMAC__ // If Mac BOINC Manager ProcessSerialNumber ourPSN; ProcessInfoRec pInfo; @@ -68,7 +74,12 @@ char *bundlePath, char *dataPath #endif #ifdef _MAC_INSTALLER char *p; -#else +#endif + +#if (defined(_DEBUG) && defined(DEBUG_WITH_FAKE_PROJECT_USER_AND_GROUP)) + useFakeProjectUserAndGroup = 1; +#else + useFakeProjectUserAndGroup = ! use_sandbox; #endif // GDB can't attach to applications which are running as a diferent user or group so @@ -97,32 +108,38 @@ char *bundlePath, char *dataPath retval = FSRefMakePath (&ourFSRef, (UInt8*)dir_path, sizeof(dir_path)); if (retval) return -1003; // Should never happen -#endif - -#ifdef _MAC_INSTALLER +#elif defined (_MAC_INSTALLER) strlcpy(dir_path, bundlePath, sizeof(dir_path)); #endif -#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer - // Get the full path to BOINC Clients inside this application's bundle - strlcpy(full_path, dir_path, sizeof(full_path)); - strlcat(full_path, "/Contents/Resources/boinc", sizeof(full_path)); - - retval = stat(full_path, &sbuf); - if (retval) - return -1004; // Should never happen - - if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != (S_ISUID | S_ISGID)) - return -1005; - - boinc_master_uid = sbuf.st_gid; - boinc_master_gid = sbuf.st_uid; + if (use_sandbox) { +#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If called from Mac BOINC Manager or installer + // Get the full path to BOINC Client inside this application's bundle + strlcpy(full_path, dir_path, sizeof(full_path)); + strlcat(full_path, "/Contents/Resources/boinc", sizeof(full_path)); #else - boinc_master_uid = geteuid(); - boinc_master_gid = getegid(); - + if (isManager) { // If called from BOINC Manager but not on Mac + getcwd(full_path, sizeof(full_path)); // Assume Client is in current directory + strlcat(full_path, "/boinc", sizeof(full_path)); + } else // If called from BOINC Client + GetPathToThisProcess(full_path, sizeof(full_path)); #endif + retval = stat(full_path, &sbuf); + if (retval) + return -1004; // Should never happen + + if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != (S_ISUID | S_ISGID)) + return -1005; + + boinc_master_uid = sbuf.st_gid; + boinc_master_gid = sbuf.st_uid; + } else { + boinc_master_uid = geteuid(); + boinc_master_gid = getegid(); + + } + #ifdef _MAC_INSTALLER // Require absolute owner and group boinc_master:boinc_master strlcpy(boinc_master_user_name, REAL_BOINC_MASTER_NAME, sizeof(boinc_master_user_name)); @@ -151,25 +168,25 @@ char *bundlePath, char *dataPath #endif -#if (defined(_DEBUG) && defined(DEBUG_WITH_FAKE_PROJECT_USER_AND_GROUP)) - // For easier debugging of project applications - strlcpy(boinc_project_user_name, boinc_master_user_name, sizeof(boinc_project_user_name)); - strlcpy(boinc_project_group_name, boinc_master_group_name, sizeof(boinc_project_group_name)); - boinc_project_uid = boinc_master_uid; - boinc_project_gid = boinc_master_gid; -#else - strlcpy(boinc_project_user_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_user_name)); - pw = getpwnam(boinc_project_user_name); - if (pw == NULL) - return -1010; // User boinc_project does not exist - boinc_project_uid = pw->pw_uid; + if (useFakeProjectUserAndGroup) { + // For easier debugging of project applications + strlcpy(boinc_project_user_name, boinc_master_user_name, sizeof(boinc_project_user_name)); + strlcpy(boinc_project_group_name, boinc_master_group_name, sizeof(boinc_project_group_name)); + boinc_project_uid = boinc_master_uid; + boinc_project_gid = boinc_master_gid; + } else { + strlcpy(boinc_project_user_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_user_name)); + pw = getpwnam(boinc_project_user_name); + if (pw == NULL) + return -1010; // User boinc_project does not exist + boinc_project_uid = pw->pw_uid; - strlcpy(boinc_project_group_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_group_name)); - grp = getgrnam(boinc_project_group_name); - if (grp == NULL) - return -1011; // Group boinc_project does not exist - boinc_project_gid = grp->gr_gid; -#endif + strlcpy(boinc_project_group_name, REAL_BOINC_PROJECT_NAME, sizeof(boinc_project_group_name)); + grp = getgrnam(boinc_project_group_name); + if (grp == NULL) + return -1011; // Group boinc_project does not exist + boinc_project_gid = grp->gr_gid; + } #if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer // Get the full path to BOINC Manager executable inside this application's bundle @@ -191,13 +208,15 @@ char *bundlePath, char *dataPath if (sbuf.st_gid != boinc_master_gid) return -1014; - if ((sbuf.st_mode & S_ISGID) != S_ISGID) - return -1015; + if (use_sandbox) { + if ((sbuf.st_mode & S_ISGID) != S_ISGID) + return -1015; + } #endif #ifdef _MAC_INSTALLER // Require absolute owner and group boinc_master:boinc_master - // Get the full path to BOINC Clients inside this application's bundle + // Get the full path to BOINC Client inside this application's bundle strlcpy(full_path, dir_path, sizeof(full_path)); strlcat(full_path, "/Contents/Resources/boinc", sizeof(full_path)); @@ -217,49 +236,59 @@ char *bundlePath, char *dataPath egid = getegid(); euid = geteuid(); -#ifndef _MAC_INSTALLER +#ifdef _MAC_INSTALLER + strlcpy(dir_path, dataPath, sizeof(dir_path)); // Installer +#else // _MAC_INSTALLER + getcwd(dir_path, sizeof(dir_path)); // Client or Manager + if (egid != boinc_master_gid) return -1019; // Client or Manager should be running setgid boinc_master -#ifndef __WXMAC__ // If BOINC Client - if (euid != boinc_master_uid) - return -1020; // BOINC Client should be running setuid boinc_master + if (! isManager) // If BOINC Client + if (euid != boinc_master_uid) + return -1020; // BOINC Client should be running setuid boinc_master #endif - getcwd(dir_path, sizeof(dir_path)); // Client or Manager -#else // _MAC_INSTALLER - strlcpy(dir_path, dataPath, sizeof(dir_path)); // Installer -#endif // _MAC_INSTALLER - retval = stat(dir_path, &sbuf); if (retval) return -1021; // Should never happen + + if (use_sandbox) { + + // The top-level BOINC Data directory can have a different user if created by the Manager, + // but it should always have group boinc_master. + if (sbuf.st_gid != boinc_master_gid) + return -1022; - // The top-level BOINC Data directory can have a different user if created by the Manager, - // but it should always have group boinc_master. - if (sbuf.st_gid != boinc_master_gid) - return -1022; - - // The top-level BOINC Data directory should have permission 775 or 575 - if ((sbuf.st_mode & 0577) != 0575) - return -1023; + // The top-level BOINC Data directory should have permission 775 or 575 + if ((sbuf.st_mode & 0577) != 0575) + return -1023; + + } else { + + if (sbuf.st_uid != boinc_master_uid) + return -1022; + + } strlcpy(full_path, dir_path, sizeof(full_path)); strlcat(full_path, "/", sizeof(full_path)); strlcat(full_path, PROJECTS_DIR, sizeof(full_path)); retval = stat(full_path, &sbuf); if (! retval) { // Client can create projects directory if it does not yet exist. - if (sbuf.st_gid != boinc_master_gid) - return -1024; - - if (sbuf.st_uid != boinc_master_uid) - return -1025; + if (use_sandbox) { + if (sbuf.st_gid != boinc_master_gid) + return -1024; if ((sbuf.st_mode & 0777) != 0775) + return -1025; + } + + if (sbuf.st_uid != boinc_master_uid) return -1026; // Step through project directories - retval = CheckNestedDirectories(full_path, 1); + retval = CheckNestedDirectories(full_path, 1, use_sandbox); if (retval) return retval; } @@ -269,17 +298,19 @@ char *bundlePath, char *dataPath strlcat(full_path, SLOTS_DIR, sizeof(full_path)); retval = stat(full_path, &sbuf); if (! retval) { // Client can create slots directory if it does not yet exist. - if (sbuf.st_gid != boinc_master_gid) - return -1027; + if (use_sandbox) { + if (sbuf.st_gid != boinc_master_gid) + return -1027; + if ((sbuf.st_mode & 0777) != 0775) + return -1028; + } + if (sbuf.st_uid != boinc_master_uid) - return -1028; - - if ((sbuf.st_mode & 0777) != 0775) return -1029; // Step through slot directories - retval = CheckNestedDirectories(full_path, 1); + retval = CheckNestedDirectories(full_path, 1, use_sandbox); if (retval) return retval; } @@ -289,71 +320,78 @@ char *bundlePath, char *dataPath strlcat(full_path, GUI_RPC_PASSWD_FILE, sizeof(full_path)); retval = stat(full_path, &sbuf); if (! retval) { // Client can create RPC password file if it does not yet exist. - if (sbuf.st_gid != boinc_master_gid) - return -1030; + if (use_sandbox) { + if (sbuf.st_gid != boinc_master_gid) + return -1030; + if ((sbuf.st_mode & 0777) != 0660) + return -1032; + } else { + if ((sbuf.st_mode & 0717) != 0600) + return -1032; + } + if (sbuf.st_uid != boinc_master_uid) return -1031; - - if ((sbuf.st_mode & 0777) != 0660) - return -1032; } - strlcpy(full_path, dir_path, sizeof(dir_path)); - strlcat(full_path, "/", sizeof(full_path)); - strlcat(full_path, SWITCHER_DIR, sizeof(full_path)); - retval = stat(full_path, &sbuf); - if (retval) - return -1033; - - if (sbuf.st_gid != boinc_master_gid) - return -1034; + if (use_sandbox) { + strlcpy(full_path, dir_path, sizeof(dir_path)); + strlcat(full_path, "/", sizeof(full_path)); + strlcat(full_path, SWITCHER_DIR, sizeof(full_path)); + retval = stat(full_path, &sbuf); + if (retval) + return -1033; + + if (sbuf.st_gid != boinc_master_gid) + return -1034; - if (sbuf.st_uid != boinc_master_uid) - return -1035; + if (sbuf.st_uid != boinc_master_uid) + return -1035; - if ((sbuf.st_mode & 0777) != 0550) - return -1036; + if ((sbuf.st_mode & 0777) != 0550) + return -1036; - strlcat(full_path, "/", sizeof(full_path)); - strlcat(full_path, SWITCHER_FILE_NAME, sizeof(full_path)); - retval = stat(full_path, &sbuf); - if (retval) - return -1037; + strlcat(full_path, "/", sizeof(full_path)); + strlcat(full_path, SWITCHER_FILE_NAME, sizeof(full_path)); + retval = stat(full_path, &sbuf); + if (retval) + return -1037; + + if (sbuf.st_gid != boinc_project_gid) + return -1038; + + if (sbuf.st_uid != boinc_project_uid) + return -1039; + + if ((sbuf.st_mode & 07777) != 06551) + return -1040; + + strlcpy(full_path, dir_path, sizeof(dir_path)); + strlcat(full_path, "/", sizeof(full_path)); + strlcat(full_path, SWITCHER_DIR, sizeof(full_path)); + + strlcat(full_path, "/", sizeof(full_path)); + strlcat(full_path, SETPROJECTGRP_FILE_NAME, sizeof(full_path)); + retval = stat(full_path, &sbuf); + if (retval) + return -1041; + + if (sbuf.st_gid != boinc_project_gid) + return -1042; + + if (sbuf.st_uid != boinc_master_uid) + return -1043; + + if ((sbuf.st_mode & 07777) != 02500) + return -1044; + } // if (use_sandbox) - if (sbuf.st_gid != boinc_project_gid) - return -1038; - - if (sbuf.st_uid != boinc_project_uid) - return -1039; - - if ((sbuf.st_mode & 07777) != 06551) - return -1040; - - strlcpy(full_path, dir_path, sizeof(dir_path)); - strlcat(full_path, "/", sizeof(full_path)); - strlcat(full_path, SWITCHER_DIR, sizeof(full_path)); - - strlcat(full_path, "/", sizeof(full_path)); - strlcat(full_path, SETPROJECTGRP_FILE_NAME, sizeof(full_path)); - retval = stat(full_path, &sbuf); - if (retval) - return -1041; - - if (sbuf.st_gid != boinc_project_gid) - return -1042; - - if (sbuf.st_uid != boinc_master_uid) - return -1043; - - if ((sbuf.st_mode & 07777) != 02500) - return -1044; - return 0; } -static int CheckNestedDirectories(char * basepath, int depth) { +static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox) { int isDirectory; char full_path[MAXPATHLEN]; struct stat sbuf; @@ -383,11 +421,6 @@ static int CheckNestedDirectories(char * basepath, int depth) { isDirectory = S_ISDIR(sbuf.st_mode); - if (sbuf.st_gid != boinc_project_gid) { - retval = -1201; - break; - } - if (depth > 1) { // files and subdirectories created by projects may have owner boinc_master or boinc_project if ( (sbuf.st_uid != boinc_master_uid) && (sbuf.st_uid != boinc_project_uid) ) { @@ -395,7 +428,7 @@ static int CheckNestedDirectories(char * basepath, int depth) { break; } } else { - // project & slot directories (projets/setiathome.berkeley.edu, slots/0 etc.) + // project & slot directories (projects/setiathome.berkeley.edu, slots/0 etc.) // must have owner boinc_master if (sbuf.st_uid != boinc_master_uid) { retval = -1202; @@ -403,38 +436,45 @@ static int CheckNestedDirectories(char * basepath, int depth) { } } - if (isDirectory) { - if (depth == 1) { - // project & slot directories (projets/setiathome.berkeley.edu, slots/0 etc.) - // must be readable & executable by other - if ((sbuf.st_mode & 0777) != 0775) { - retval = -1203; + if (use_sandbox) { + if (sbuf.st_gid != boinc_project_gid) { + retval = -1201; break; } -#if 0 // We may enforce permissions later for subdirectories written by project applications - } else { - // subdirectories created by projects may be executable by other or not - if ((sbuf.st_mode & 0770) != 0770) { - retval = -1203; + + if (isDirectory) { + if (depth == 1) { + // project & slot directories (projects/setiathome.berkeley.edu, slots/0 etc.) + // must be readable & executable by other + if ((sbuf.st_mode & 0777) != 0775) { + retval = -1203; + break; + } +#if 0 // We may enforce permissions later for subdirectories written by project applications + } else { + // subdirectories created by projects may be executable by other or not + if ((sbuf.st_mode & 0770) != 0770) { + retval = -1203; + break; + } +#endif + } +#if 0 // We may enforce permissions later for files written by project applications + } else { // ! isDirectory + if ((sbuf.st_mode & 0666) != 0660) { + retval = -1204; break; } #endif } -#if 0 // We may enforce permissions later for files written by project applications - } else { // ! isDirectory - if ((sbuf.st_mode & 0666) != 0660) { - retval = -1204; - break; - } -#endif - } + } // if (use_sandbox) if (isDirectory) { - if (depth > 1) + if (use_sandbox && (depth > 1)) if ((sbuf.st_uid != boinc_master_uid) && (sbuf.st_gid != boinc_master_gid)) continue; // We can't check subdirectories owned by boinc_project - retval = CheckNestedDirectories(full_path, depth + 1); + retval = CheckNestedDirectories(full_path, depth + 1, use_sandbox); if (retval) break; } @@ -445,3 +485,37 @@ static int CheckNestedDirectories(char * basepath, int depth) { return retval; } + + +#if (! defined(__WXMAC__) && ! defined(_MAC_INSTALLER)) +static void GetPathToThisProcess(char* outbuf, size_t maxLen) { + FILE *f; + char buf[256], *p, *q; + pid_t aPID = getpid(); + + *outbuf = '\0'; + + sprintf(buf, "ps -xwo command -p %d", (int)aPID); + f = popen(buf, "r"); + if (f == NULL) + return; + + fgets (outbuf, maxLen, f); // Discard header line + fgets (outbuf, maxLen, f); + pclose(f); + + // Strip off any arguments + p = strstr(outbuf, " -"); + q = p; + if (p) { + while (*p == ' ') { + q = p; + if (--p < outbuf) + break; + } + } + + if (q) + *q = '\0'; +} +#endif diff --git a/client/client_state.C b/client/client_state.C index c199c14a5e..35a99402d3 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -106,6 +106,11 @@ CLIENT_STATE::CLIENT_STATE() { have_tentative_project = false; new_version_check_time = 0; detach_console = false; +#ifdef SANDBOX + g_use_sandbox = true; // User can override with -insecure command-line arg +#else + g_use_sandbox = false; +#endif } void CLIENT_STATE::show_host_info() { @@ -309,16 +314,16 @@ int CLIENT_STATE::init() { } #ifndef _WIN32 -#ifdef SANDBOX + if (g_use_sandbox) { #ifdef _DEBUG - boinc_project_gid = getegid(); + boinc_project_gid = getegid(); #else - retval = lookup_group(BOINC_PROJECT_GROUP_NAME, boinc_project_gid); - if (retval) return retval; + retval = lookup_group(BOINC_PROJECT_GROUP_NAME, boinc_project_gid); + if (retval) return retval; #endif // _DEBUG -#else - boinc_project_gid = 0; -#endif + } else { + boinc_project_gid = 0; + } #endif check_file_existence(); diff --git a/client/client_types.C b/client/client_types.C index 1b431734c3..7d22b33f23 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -613,37 +613,37 @@ int FILE_INFO::set_permissions() { // give read/exec permissions for user, group and others // in case someone runs BOINC from different user -#ifdef SANDBOX - retval = set_to_project_group(pathname); - if (retval) return retval; - if (executable) { - retval = chmod(pathname, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); + if (g_use_sandbox) { + retval = set_to_project_group(pathname); + if (retval) return retval; + if (executable) { + retval = chmod(pathname, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + } else { + retval = chmod(pathname, + S_IRUSR|S_IWUSR + |S_IRGRP|S_IWGRP + |S_IROTH + ); + } } else { - retval = chmod(pathname, - S_IRUSR|S_IWUSR - |S_IRGRP|S_IWGRP - |S_IROTH - ); + if (executable) { + retval = chmod(pathname, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + } else { + retval = chmod(pathname, + S_IRUSR|S_IWUSR + |S_IRGRP + |S_IROTH + ); + } } -#else - if (executable) { - retval = chmod(pathname, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); - } else { - retval = chmod(pathname, - S_IRUSR|S_IWUSR - |S_IRGRP - |S_IROTH - ); - } -#endif return retval; #endif } diff --git a/client/cs_cmdline.C b/client/cs_cmdline.C index 4d9609da12..8e09f5cdf2 100644 --- a/client/cs_cmdline.C +++ b/client/cs_cmdline.C @@ -53,6 +53,7 @@ static void print_options(char* prog) { " -dir use given dir as BOINC home\n" " -no_gui_rpc don't allow GUI RPC, don't make socket\n" " -daemon run as daemon (Unix)\n" + " -insecure disable BOINC security users and permissions (Unix, Linux)\n" , prog ); @@ -174,6 +175,8 @@ void CLIENT_STATE::parse_cmdline(int argc, char** argv) { } } else if (ARG(no_gui_rpc)) { no_gui_rpc = true; + } else if (ARG(insecure)) { + g_use_sandbox = false; } else { printf("Unknown option: %s\n", argv[i]); show_options = true; diff --git a/client/file_names.C b/client/file_names.C index 4781c034d1..1110315026 100644 --- a/client/file_names.C +++ b/client/file_names.C @@ -95,23 +95,23 @@ int make_project_dir(PROJECT& p) { int retval; boinc_mkdir(PROJECTS_DIR); -#ifdef SANDBOX - chmod(PROJECTS_DIR, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); -#endif + if (g_use_sandbox) { + chmod(PROJECTS_DIR, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + } get_project_dir(&p, buf); retval = boinc_mkdir(buf); -#ifdef SANDBOX - chmod(buf, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); - set_to_project_group(buf); -#endif + if (g_use_sandbox) { + chmod(buf, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + set_to_project_group(buf); + } return retval; } @@ -137,23 +137,23 @@ int make_slot_dir(int slot) { return ERR_NEG; } boinc_mkdir(SLOTS_DIR); -#ifdef SANDBOX - chmod(SLOTS_DIR, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); -#endif + if (g_use_sandbox) { + chmod(SLOTS_DIR, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + } get_slot_dir(slot, buf); int retval = boinc_mkdir(buf); -#ifdef SANDBOX - chmod(buf, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IXOTH - ); - set_to_project_group(buf); -#endif + if (g_use_sandbox) { + chmod(buf, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IXOTH + ); + set_to_project_group(buf); + } return retval; } @@ -261,17 +261,14 @@ bool is_image_file(const char* filename) { } int set_to_project_group(const char* path) { -#ifdef SANDBOX char buf[1024]; - sprintf(buf, "%s/%s %s", SWITCHER_DIR, SETPROJECTGRP_FILE_NAME, path); - if (system(buf)) - return ERR_CHOWN; - - return 0; -#else - return ERR_CHOWN; -#endif + if (g_use_sandbox) { + sprintf(buf, "%s/%s %s", SWITCHER_DIR, SETPROJECTGRP_FILE_NAME, path); + if (system(buf)) + return ERR_CHOWN; + } + return 0; } const char *BOINC_RCSID_7d362a6a52 = "$Id$"; diff --git a/client/gui_rpc_server.C b/client/gui_rpc_server.C index df248e42ac..bbb4406b9a 100644 --- a/client/gui_rpc_server.C +++ b/client/gui_rpc_server.C @@ -104,12 +104,12 @@ int GUI_RPC_CONN_SET::get_password() { // they can cause code to execute as this user. // So better protect it. // -#ifdef SANDBOX - // Allow group access so authorized administrator can modify it - chmod(GUI_RPC_PASSWD_FILE, S_IRUSR|S_IWUSR | S_IRGRP | S_IWGRP); -#else - chmod(GUI_RPC_PASSWD_FILE, S_IRUSR|S_IWUSR); -#endif + if (g_use_sandbox) { + // Allow group access so authorized administrator can modify it + chmod(GUI_RPC_PASSWD_FILE, S_IRUSR|S_IWUSR | S_IRGRP | S_IWGRP); + } else { + chmod(GUI_RPC_PASSWD_FILE, S_IRUSR|S_IWUSR); + } #endif } } diff --git a/client/main.C b/client/main.C index 0ca53f24a4..a6c22a5f9c 100644 --- a/client/main.C +++ b/client/main.C @@ -78,6 +78,12 @@ typedef void (CALLBACK* ClientLibraryShutdown)(); int finalize(); +// Ideally, we would access this using wxGetApp().m_use_sandbox in the Manager +// and gstate.m_use_sandbox in the Client, but it is used by some source files +// (filesys.C, check_security.C) that are linked with both Manager and Client +// so the most practical solution is to use a global. +int g_use_sandbox; + static bool boinc_cleanup_completed = false; // Used on Windows 95/98/ME to determine when it is safe to leave // the WM_ENDSESSION message handler and allow Windows to finish @@ -335,15 +341,17 @@ static void init_core_client(int argc, char** argv) { } #else -#ifdef SANDBOX - umask (2); // Set file creation mask to be writable by both user and group - // Our umask will be inherited by all our child processes -#endif #endif read_config_file(); gstate.parse_cmdline(argc, argv); +#ifndef _WIN32 + if (g_use_sandbox) + umask (2); // Set file creation mask to be writable by both user and group + // Our umask will be inherited by all our child processes +#endif + // Initialize the BOINC Diagnostics Framework int dwDiagnosticsFlags = BOINC_DIAG_DUMPCALLSTACKENABLED | @@ -752,13 +760,14 @@ int main(int argc, char** argv) { #else #ifdef SANDBOX + // Make sure owners, groups and permissions are correct for the current setting of g_use_sandbox #if defined(_DEBUG) && defined(__APPLE__) - // GDB can't attach to applications which are running as a diferent user - // or group, so fix up data with current user and group during debugging - if (check_security()) + // GDB can't attach to applications which are running as a diferent user + // or group, so fix up data with current user and group during debugging + if (check_security(g_use_sandbox, false)) SetBOINCDataOwnersGroupsAndPermissions(); #endif // _DEBUG && __APPLE__ - int i = check_security(); + int i = check_security(g_use_sandbox, false); if (i) { printf( "\nBOINC ownership or permissions are not set properly; please reinstall BOINC. (Error code %d)\n", i); return ERR_USER_PERMISSION; diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index bcefb44775..fb163d36f2 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -87,6 +87,13 @@ EXTERN_C DWORD BOINCGetIdleTickCount(); IMPLEMENT_APP(CBOINCGUIApp) IMPLEMENT_DYNAMIC_CLASS(CBOINCGUIApp, wxApp) +// Ideally, we would access this using wxGetApp().m_use_sandbox in the Manager +// and gstate.m_use_sandbox in the Client, but it is used by some source files +// (filesys.C, check_security.C) that are linked with both Manager and Client +// so the most practical solution is to use a global. +int g_use_sandbox; + + bool CBrandingScheme::OnInit( wxConfigBase *pConfig ) { wxString strBaseConfigLocation = wxEmptyString; @@ -260,9 +267,19 @@ bool CBOINCGUIApp::OnInit() { int errCode = 0; #endif -#if (defined(SANDBOX) && !defined(_WIN32)) - umask (2); // Set file creation mask to be writable by both user and group - // Our umask will be inherited by all our child processes +#ifdef SANDBOX + g_use_sandbox = true; + // Commandline parsing is done in wxApp::OnInit() + if (!wxApp::OnInit()) { // Command line arg -insecure sets g_use_sandbox to false + return false; + } +#ifndef _WIN32 + if (g_use_sandbox) + umask (2); // Set file creation mask to be writable by both user and group + // Our umask will be inherited by all our child processes +#endif +#else + g_use_sandbox = false; #endif // Setup variables with default values @@ -341,10 +358,10 @@ bool CBOINCGUIApp::OnInit() { if (success) { // If SetWD failed, don't create a directory in wrong place strDirectory += wxT("BOINC Data"); // We don't customize BOINC Data directory name for branding -#ifndef SANDBOX - if (! wxDirExists(strDirectory)) - success = wxMkdir(strDirectory, 0777); // Does nothing if dir exists -#endif // ! SANDBOX + if (! g_use_sandbox) { + if (! wxDirExists(strDirectory)) + success = wxMkdir(strDirectory, 0777); // Does nothing if dir exists + } success = ::wxSetWorkingDirectory(strDirectory); // wxChar *wd = wxGetWorkingDirectory(buf, 1000); // For debugging } @@ -354,17 +371,18 @@ bool CBOINCGUIApp::OnInit() { #endif // __WXMAC__ #ifdef SANDBOX + // Make sure owners, groups and permissions are correct for the current setting of g_use_sandbox if (!errCode) { #if (defined(__WXMAC__) && defined(_DEBUG)) // TODO: implement this for other platforms // GDB can't attach to applications which are running as a different user // or group, so fix up data with current user and group during debugging - if (check_security()) { + if (check_security(g_use_sandbox, true)) { CreateBOINCUsersAndGroups(); SetBOINCDataOwnersGroupsAndPermissions(); SetBOINCAppOwnersGroupsAndPermissions(NULL); } #endif // __WXMAC__ && _DEBUG - errCode = check_security(); + errCode = check_security(g_use_sandbox, true); } if (errCode) { @@ -424,10 +442,12 @@ bool CBOINCGUIApp::OnInit() { // help if you use this help provider: wxHelpProvider::Set(new wxHelpControllerHelpProvider()); +#ifndef SANDBOX // Commandline parsing is done in wxApp::OnInit() if (!wxApp::OnInit()) { return false; } +#endif // Initialize the main document m_pDocument = new CMainDocument(); @@ -543,6 +563,9 @@ void CBOINCGUIApp::OnInitCmdLine(wxCmdLineParser &parser) { wxApp::OnInitCmdLine(parser); static const wxCmdLineEntryDesc cmdLineDesc[] = { { wxCMD_LINE_SWITCH, wxT("s"), wxT("systray"), _("Startup BOINC so only the system tray icon is visible")}, +#if (defined(SANDBOX) && ! defined(_WIN32)) + { wxCMD_LINE_SWITCH, wxT("insecure"), wxT("insecure"), _("disable BOINC security users and permissions")}, +#endif { wxCMD_LINE_NONE} //DON'T forget this line!! }; parser.SetDesc(cmdLineDesc); @@ -555,6 +578,9 @@ bool CBOINCGUIApp::OnCmdLineParsed(wxCmdLineParser &parser) { if (parser.Found(wxT("systray"))) { m_bGUIVisible = false; } + if (parser.Found(wxT("insecure"))) { + g_use_sandbox = false; + } return true; } @@ -686,7 +712,7 @@ void CBOINCGUIApp::StartupBOINCCore() { { wxChar buf[1024]; - wxChar *argv[3]; + wxChar *argv[4]; ProcessSerialNumber ourPSN; FSRef ourFSRef; OSErr err; @@ -710,6 +736,12 @@ void CBOINCGUIApp::StartupBOINCCore() { argv[0] = buf; argv[1] = "-redirectio"; argv[2] = NULL; +#ifdef SANDBOX + if (! g_use_sandbox) { + argv[2] = "-insecure"; + argv[3] = NULL; + } +#endif m_lBOINCCoreProcessId = ::wxExecute(argv); #endif } else { @@ -772,6 +804,8 @@ void CBOINCGUIApp::StartupBOINCCore() { // Append boinc.exe to the end of the strExecute string and get ready to rock strExecute = wxT("./boinc -redirectio"); + if (! g_use_sandbox) + strExecute += wxT(" -insecure"); m_lBOINCCoreProcessId = ::wxExecute(strExecute); #endif // ! __WXMAC__ diff --git a/clientgui/BOINCGUIApp.h b/clientgui/BOINCGUIApp.h index f62ddf5d5e..95a857de1a 100644 --- a/clientgui/BOINCGUIApp.h +++ b/clientgui/BOINCGUIApp.h @@ -37,7 +37,6 @@ #define BOINC_ADVANCEDGUI 1 #define BOINC_SIMPLEGUI 2 - class CBrandingScheme : public wxObject { private: bool m_bIsBranded; diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index 65be78fc8e..05b1b92f48 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -21,16 +21,17 @@ #pragma implementation "MainDocument.h" #endif -#ifdef SANDBOX -#include -#endif - #include "stdwx.h" #include "BOINCGUIApp.h" #include "BOINCBaseFrame.h" #include "MainDocument.h" #include "error_numbers.h" +#ifdef SANDBOX +#include +#include "util.h" // For g_use_sandbox +#endif + using std::string; CNetworkConnection::CNetworkConnection(CMainDocument* pDocument) : @@ -594,43 +595,47 @@ int CMainDocument::CoreClientQuit() { bool CMainDocument::IsUserAuthorized() { -#ifdef SANDBOX #ifdef _WIN32 return true; #else // ! _WIN32 - group *grp; - gid_t rgid, boinc_master_gid; - char *userName, *groupMember; - int i; static bool sIsAuthorized = false; if (sIsAuthorized) return true; // We already checked and OK'd current user - grp = getgrnam(BOINC_MASTER_GROUP_NAME); - if (grp) { - boinc_master_gid = grp->gr_gid; +#ifdef SANDBOX + group *grp; + gid_t rgid, boinc_master_gid; + char *userName, *groupMember; + int i; - rgid = getgid(); - if (rgid == boinc_master_gid) { - sIsAuthorized = true; // User's primary group is boinc_master - return true; - } + if (g_use_sandbox) { + + grp = getgrnam(BOINC_MASTER_GROUP_NAME); + if (grp) { + boinc_master_gid = grp->gr_gid; - userName = getlogin(); - if (userName) { - for (i=0; ; i++) { // Step through all users in group boinc_master - groupMember = grp->gr_mem[i]; - if (groupMember == NULL) - break; // User is not a member of group boinc_master - if (strcmp(userName, groupMember) == 0) { - sIsAuthorized = true; // User is a member of group boinc_master - return true; - } - } // for (i) - } // if (userName) - } // if grp + rgid = getgid(); + if (rgid == boinc_master_gid) { + sIsAuthorized = true; // User's primary group is boinc_master + return true; + } + userName = getlogin(); + if (userName) { + for (i=0; ; i++) { // Step through all users in group boinc_master + groupMember = grp->gr_mem[i]; + if (groupMember == NULL) + break; // User is not a member of group boinc_master + if (strcmp(userName, groupMember) == 0) { + sIsAuthorized = true; // User is a member of group boinc_master + return true; + } + } // for (i) + } // if (userName) + } // if grp + } +#endif // SANDBOX #endif // ! _WIN32 #ifdef __WXMAC__ @@ -640,17 +645,11 @@ bool CMainDocument::IsUserAuthorized() { } #endif // __WXMAC__ +#ifdef SANDBOX return false; - -#else // ! SANDBOX - -#ifdef __WXMAC__ - return Mac_Authorize(); // Run Mac Authentication dialog -#else // ! __WXMAC__ +#else return true; -#endif // ! __WXMAC__ - -#endif // ! SANDBOX +#endif } diff --git a/clientgui/mac/Mac_GUI.cpp b/clientgui/mac/Mac_GUI.cpp index d52085d007..1ed99378ef 100644 --- a/clientgui/mac/Mac_GUI.cpp +++ b/clientgui/mac/Mac_GUI.cpp @@ -23,6 +23,7 @@ #include #include +#include "util.h" // For g_use_sandbox // Determine if the currently logged-in user is auhorized to @@ -45,18 +46,18 @@ Boolean Mac_Authorize() if (sIsAuthorized) return true; -#ifndef SANDBOX uid_t effectiveUserID, realUserID; - effectiveUserID = geteuid(); - realUserID = getuid(); - if (effectiveUserID == realUserID) - { - // Logged in user is also the owner - sIsAuthorized = true; - return true; + if (g_use_sandbox) { + effectiveUserID = geteuid(); + realUserID = getuid(); + if (effectiveUserID == realUserID) + { + // Logged in user is also the owner + sIsAuthorized = true; + return true; + } } -#endif // User is not the owner, so require admin authorization ourAuthItem[0].name = kAuthorizationRightExecute; diff --git a/clientgui/mac/mac_saver_module.cpp b/clientgui/mac/mac_saver_module.cpp index 833463fe03..30876550b9 100755 --- a/clientgui/mac/mac_saver_module.cpp +++ b/clientgui/mac/mac_saver_module.cpp @@ -147,6 +147,8 @@ const char * BOINCUnrecoverableErrorMsg = "Sorry, an unrecoverable error occurr const char * BOINCTestmodeMg = "This BOINC screensaver does not support Test mode"; //const char * BOINCExitedSaverMode = "BOINC is no longer in screensaver mode."; +int g_use_sandbox = 0; + // Returns desired Animation Frequency (per second) or 0 for no change int initBOINCSaver(Boolean ispreview) { diff --git a/lib/boinc_cmd.C b/lib/boinc_cmd.C index 3e11b7bbf9..173f3ef317 100644 --- a/lib/boinc_cmd.C +++ b/lib/boinc_cmd.C @@ -43,6 +43,9 @@ using std::string; #include "util.h" #include "version.h" +int g_use_sandbox = 0; + + void usage() { fprintf(stderr, "\ Usage: boinc_cmd [--host hostname] [--passwd passwd] command\n\ diff --git a/lib/filesys.C b/lib/filesys.C index fe676a448a..d044091c6f 100755 --- a/lib/filesys.C +++ b/lib/filesys.C @@ -258,13 +258,10 @@ int boinc_delete_file(const char* path) { } #else retval = unlink(path); -#ifdef SANDBOX - if (retval) - // We may not have permission to read subdirectories created by projects - if (errno == EACCES) { - return remove_project_owned_file_or_dir(path); - } -#endif + if (retval && g_use_sandbox && (errno == EACCES)) { + // We may not have permission to read subdirectories created by projects + return remove_project_owned_file_or_dir(path); + } return retval; #endif if (retval) { @@ -313,14 +310,14 @@ int clean_out_dir(const char* dirpath) { DIRREF dirp; dirp = dir_open(dirpath); - if (!dirp) -#ifdef SANDBOX - // We may not have permission to read subdirectories created by projects - if (errno == EACCES) { - return remove_project_owned_file_or_dir(dirpath); - } else -#endif + if (!dirp) { + if (g_use_sandbox && (errno == EACCES)) { + // We may not have permission to read subdirectories created by projects + return remove_project_owned_file_or_dir(dirpath); + } return 0; // if dir doesn't exist, it's empty + } + while (1) { strcpy(filename, ""); retval = dir_scan(filename, dirp, sizeof(filename)); @@ -488,13 +485,9 @@ int boinc_rmdir(const char* name) { #else int retval; retval = rmdir(name); -#ifdef SANDBOX - if (retval) // We may not have permission to read subdirectories created by projects - if (errno == EACCES) { - return remove_project_owned_file_or_dir(name); - } -#endif + if (retval && g_use_sandbox && (errno == EACCES)) + retval = remove_project_owned_file_or_dir(name); return retval; #endif } @@ -502,12 +495,13 @@ int boinc_rmdir(const char* name) { int remove_project_owned_file_or_dir(const char* path) { #ifdef SANDBOX char cmd[1024]; - - sprintf(cmd, "%s/%s /bin/rm rm -fR \"%s\"", SWITCHER_DIR, SWITCHER_FILE_NAME, path); - return system(cmd); -#else - return ERR_UNLINK; + + if (g_use_sandbox) { + sprintf(cmd, "%s/%s /bin/rm rm -fR \"%s\"", SWITCHER_DIR, SWITCHER_FILE_NAME, path); + return system(cmd); + } #endif + return ERR_UNLINK; } #ifndef _WIN32 diff --git a/lib/util.h b/lib/util.h index 06484ce90c..3c00405050 100755 --- a/lib/util.h +++ b/lib/util.h @@ -34,6 +34,14 @@ #endif +// Ideally, we would access this using wxGetApp().m_use_sandbox in the Manager +// and gstate.m_use_sandbox in the Client, but it is used by some source files +// (filesys.C, check_security.C) that are linked with both Manager and Client +// so the most practical solution is to use a global. +extern int g_use_sandbox; + + + #if !defined(HAVE_STRLCPY) extern size_t strlcpy(char*, const char*, size_t); #endif @@ -143,7 +151,7 @@ extern pthread_mutex_t getrusage_mutex; #ifndef _WIN32 extern int lookup_group(char*, gid_t& gid); -extern int check_security(void); +extern int check_security(int use_sandbox, int isManager); #endif #endif diff --git a/mac_build/Mac_SA_Insecure.sh b/mac_build/Mac_SA_Insecure.sh index fb394db3e9..67096aac4a 100755 --- a/mac_build/Mac_SA_Insecure.sh +++ b/mac_build/Mac_SA_Insecure.sh @@ -65,7 +65,7 @@ then exit fi -if [ ! -f "boinc" ] +if [ ! -x "boinc" ] then echo "Can't find boinc Client in directory $(pwd); exiting" exit @@ -74,4 +74,15 @@ fi chown -R ${user}:${group} . chmod -R u+rw-s,g+r-w-s,o+r-w . chmod 600 gui_rpc_auth.cfg + +if [ -x /Applications/BOINCManager.app/Contents/MacOS/BOINCManager ] ; then + chown ${user}:${group} /Applications/BOINCManager.app/Contents/MacOS/BOINCManager + chmod -R u+r-w+s,g+r-ws,o+r-ws /Applications/BOINCManager.app/Contents/MacOS/BOINCManager +fi + +if [ -x /Applications/BOINCManager.app/Contents/Resources/boinc ] ; then +chown ${user}:${group} /Applications/BOINCManager.app/Contents/Resources/boinc + chmod -R u+r-ws,g+r-ws,o+r-ws /Applications/BOINCManager.app/Contents/Resources/boinc +fi + remove_boinc_users diff --git a/mac_build/Mac_SA_Secure.sh b/mac_build/Mac_SA_Secure.sh index 7cbc54ab75..10e823daf8 100755 --- a/mac_build/Mac_SA_Secure.sh +++ b/mac_build/Mac_SA_Secure.sh @@ -189,3 +189,14 @@ set_perm switcher boinc_master boinc_master 0550 set_perm_recursive locale boinc_master boinc_master u+r-w,g+r-w,o-rwx set_perm boinc boinc_master boinc_master 6555 # boinc client + + +if [ -x /Applications/BOINCManager.app/Contents/MacOS/BOINCManager ] ; then + set_perm /Applications/BOINCManager.app/Contents/MacOS/BOINCManager boinc_master boinc_master 2555 +fi + +if [ -x /Applications/BOINCManager.app/Contents/Resources/boinc ] ; then + set_perm /Applications/BOINCManager.app/Contents/Resources/boinc boinc_master boinc_master 6555 +fi + + diff --git a/mac_installer/PostInstall.cpp b/mac_installer/PostInstall.cpp index 34a2109f76..68f0d4b9cc 100755 --- a/mac_installer/PostInstall.cpp +++ b/mac_installer/PostInstall.cpp @@ -56,7 +56,7 @@ static OSErr QuitAppleEventHandler(const AppleEvent *appleEvt, AppleEvent* reply void print_to_log_file(const char *format, ...); void strip_cr(char *buf); -extern int check_security(char *bundlePath, char *dataPath); +extern int check_security(char *bundlePath, char *dataPath, int use_sandbox, int isManager); static Boolean gQuitFlag = false; /* global */ @@ -173,7 +173,7 @@ int main(int argc, char *argv[]) continue; } - err = check_security(p, "/Library/Application Support/BOINC Data"); + err = check_security(p, "/Library/Application Support/BOINC Data", true, false); if (err == noErr) break; // print_to_log_file("check_security returned %d (repetition=%d)", err, i);