diff --git a/checkin_notes b/checkin_notes index 55beb190d1..48100c860f 100755 --- a/checkin_notes +++ b/checkin_notes @@ -6100,8 +6100,17 @@ Rom 16 June 2006 (HEAD) boinc_core_release_5_5_1 Charlie 15 June 2006 - - Mac sandbox: fix errors in SetupSecurity() + - Mac sandbox: bug fixes + client/ + check_security.C + client_state.C + file_names.C + main.C clientgui/ + BOINCGUIApp.cpp mac/ SetupSecurity.cpp + lib/ + filesys.C + \ No newline at end of file diff --git a/client/check_security.C b/client/check_security.C index 8564bf486f..07022ccf5a 100644 --- a/client/check_security.C +++ b/client/check_security.C @@ -36,21 +36,26 @@ // To work around this, the _DEBUG version uses the current user and group. static char boinc_master_user_name[64]; static char boinc_master_group_name[64]; +static char boinc_project_user_name[64]; +static char boinc_project_group_name[64]; #else #define boinc_master_user_name "boinc_master" #define boinc_master_group_name "boinc_master" +#define boinc_project_user_name "boinc_project" +#define boinc_project_group_name "boinc_project" #endif -#define boinc_project_name "boinc_project" - // Returns FALSE (0) if owners and permissions are OK, else TRUE (1) int check_security() { passwd *pw; - gid_t egid, boinc_master_gid, boinc_project_gid; - uid_t euid, boinc_master_uid, boinc_project_uid; - char *p; group *grp; + gid_t egid, boinc_master_gid; + uid_t euid, boinc_master_uid; +#ifndef _DEBUG + gid_t boinc_project_gid; + uid_t boinc_project_uid; int i; +#endif char dir_path[MAXPATHLEN], full_path[MAXPATHLEN]; struct stat sbuf; int retval; @@ -58,6 +63,9 @@ int check_security() { ProcessSerialNumber ourPSN; FSRef ourFSRef; #endif +#if (defined(__WXMAC__) || (! defined(_DEBUG))) + char *p; +#endif #ifdef _DEBUG // GDB can't attach to applications which are running as a diferent user or group so @@ -68,12 +76,14 @@ int check_security() { if (pw == NULL) return ERR_USER_REJECTED; // Should never happen strlcpy(boinc_master_user_name, pw->pw_name, sizeof(boinc_master_user_name)); + strlcpy(boinc_project_user_name, pw->pw_name, sizeof(boinc_project_user_name)); boinc_master_gid = getegid(); grp = getgrgid(boinc_master_gid); if (grp == NULL) return ERR_GETGRNAM; strlcpy(boinc_master_group_name, grp->gr_name, sizeof(boinc_master_group_name)); + strlcpy(boinc_project_group_name, grp->gr_name, sizeof(boinc_project_group_name)); #else pw = getpwnam(boinc_master_user_name); if (pw == NULL) @@ -84,14 +94,13 @@ int check_security() { if (grp == NULL) return ERR_GETGRNAM; // Group boinc_master does not exist boinc_master_gid = grp->gr_gid; -#endif - pw = getpwnam(boinc_project_name); + pw = getpwnam(boinc_project_user_name); if (pw == NULL) return ERR_USER_REJECTED; // User boinc_project does not exist boinc_project_uid = pw->pw_uid; - grp = getgrnam(boinc_project_name); + grp = getgrnam(boinc_project_group_name); if (grp == NULL) return ERR_GETGRNAM; // Group boinc_project does not exist boinc_project_gid = grp->gr_gid; @@ -103,6 +112,7 @@ int check_security() { if (strcmp(p, boinc_master_user_name) == 0) break; } +#endif #ifdef __WXMAC__ // If Mac BOINC Manager // Get the full path to BOINC Manager application's bundle @@ -118,19 +128,19 @@ int check_security() { if (retval) return retval; // Should never happen - // Get the full path to BOINC Manager inside this application's bundle + // Get the full path to BOINC Manager executable inside this application's bundle strlcpy(full_path, dir_path, sizeof(full_path)); strlcat(full_path, "/Contents/MacOS/", sizeof(full_path)); // To allow for branding, assume name of executable inside bundle is same as name of bundle p = strrchr(dir_path, '/'); // Assume name of executable inside bundle is same as name of bundle if (p == NULL) p = dir_path - 1; - strlcat(full_path, p, sizeof(full_path)); + strlcat(full_path, p+1, sizeof(full_path)); p = strrchr(full_path, '.'); // Strip off bundle extension (".app") if (p) *p = '\0'; - retval = stat(dir_path, &sbuf); + retval = stat(full_path, &sbuf); if (retval) return retval; // Should never happen @@ -144,7 +154,7 @@ int check_security() { strlcpy(full_path, dir_path, sizeof(full_path)); strlcat(full_path, "/Contents/Resources/boinc", sizeof(full_path)); - retval = stat(dir_path, &sbuf); + retval = stat(full_path, &sbuf); if (retval) return retval; // Should never happen @@ -154,7 +164,7 @@ int check_security() { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if ((sbuf.st_mode & S_ISUID | S_ISGID) != S_ISUID | S_ISGID) + if ((sbuf.st_mode & (S_ISUID | S_ISGID)) != (S_ISUID | S_ISGID)) return ERR_USER_PERMISSION; #endif // Mac BOINC Manager @@ -183,7 +193,7 @@ int check_security() { return ERR_USER_PERMISSION; // The top-level BOINC Data directory should have permission 775 or 575 - if ((sbuf.st_mode & 0575) != 0575) + if ((sbuf.st_mode & 0577) != 0575) return ERR_USER_PERMISSION; strlcpy(full_path, dir_path, sizeof(full_path)); @@ -197,7 +207,7 @@ int check_security() { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if (sbuf.st_mode != 0775) + if ((sbuf.st_mode & 0777) != 0775) return ERR_USER_PERMISSION; } @@ -212,7 +222,7 @@ int check_security() { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if (sbuf.st_mode != 0775) + if ((sbuf.st_mode & 0777) != 0775) return ERR_USER_PERMISSION; } @@ -227,7 +237,7 @@ int check_security() { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if (sbuf.st_mode != 0770) + if ((sbuf.st_mode & 0777) != 0660) return ERR_USER_PERMISSION; } diff --git a/client/client_state.C b/client/client_state.C index 22437e1c47..99b7dc6e52 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -313,8 +313,12 @@ int CLIENT_STATE::init() { #ifndef _WIN32 #ifdef SANDBOX +#ifdef _DEBUG + boinc_project_gid = getegid(); +#else retval = lookup_group(BOINC_PROJECT_GROUP_NAME, boinc_project_gid); if (retval) return retval; +#endif // _DEBUG #else boinc_project_gid = 0; #endif diff --git a/client/file_names.C b/client/file_names.C index 9d2a0f93b9..24f8443de4 100644 --- a/client/file_names.C +++ b/client/file_names.C @@ -107,7 +107,7 @@ int make_project_dir(PROJECT& p) { #ifdef SANDBOX chmod(PROJECTS_DIR, S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP||S_IWGRP|S_IXGRP + |S_IRGRP|S_IWGRP|S_IXGRP |S_IROTH|S_IXOTH ); #endif diff --git a/client/main.C b/client/main.C index 9c86b5a237..5ec1c7d983 100644 --- a/client/main.C +++ b/client/main.C @@ -745,15 +745,16 @@ int main(int argc, char** argv) { #ifdef __APPLE__ #ifdef SANDBOX - if (check_security()) { #ifdef _DEBUG // 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()) SetBOINCDataOwnersGroupsAndPermissions(); -#else +#endif // _DEBUG + + if (check_security()) { printf( "\nBOINC ownership or permissions are not set properly; please reinstall BOINC\n" ); return ERR_USER_PERMISSION; -#endif // _DEBUG } #endif // SANDBOX diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 20ccb8bc04..bf050b199e 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -342,8 +342,10 @@ bool CBOINCGUIApp::OnInit() { #ifdef _DEBUG // 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()) + if (check_security()) { SetBOINCDataOwnersGroupsAndPermissions(); + SetBOINCAppOwnersGroupsAndPermissions(NULL); + } #endif // _DEBUG if (check_security()) { diff --git a/clientgui/mac/SetupSecurity.cpp b/clientgui/mac/SetupSecurity.cpp index dd369b370b..96e8c7b63d 100644 --- a/clientgui/mac/SetupSecurity.cpp +++ b/clientgui/mac/SetupSecurity.cpp @@ -52,13 +52,15 @@ static AuthorizationRef gOurAuthRef = NULL; // To work around this, the _DEBUG version uses the current user and group. static char boinc_master_user_name[64]; static char boinc_master_group_name[64]; +static char boinc_project_user_name[64]; +static char boinc_project_group_name[64]; #else #define boinc_master_user_name "boinc_master" #define boinc_master_group_name "boinc_master" +#define boinc_project_user_name "boinc_project" +#define boinc_project_group_name "boinc_project" #endif -#define boinc_project_name "boinc_project" - #define MIN_ID 25 /* Minimum user ID / Group ID to create */ static char dsclPath[] = "/usr/bin/dscl"; @@ -75,12 +77,12 @@ int CreateBOINCUsersAndGroups() { if (err != noErr) return err; - err = CreateUserAndGroup(boinc_project_name, boinc_project_name); + err = CreateUserAndGroup(boinc_project_user_name, boinc_project_group_name); if (err != noErr) return err; // Add user boinc_master to group boinc_project - sprintf(buf1, "/groups/%s", boinc_project_name); + sprintf(buf1, "/groups/%s", boinc_project_group_name); // "dscl . -merge /groups/boinc_project users boinc_master" err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", boinc_master_user_name); if (err != noErr) @@ -94,44 +96,62 @@ int CreateBOINCUsersAndGroups() { } +// Pass NULL for path when calling this routine from within BOINC Manager int SetBOINCAppOwnersGroupsAndPermissions(char *path) { - char fullpath[MAXPATHLEN]; - char buf1[80]; - char *p; - OSStatus err = noErr; + char fullpath[MAXPATHLEN]; + char dir_path[MAXPATHLEN]; + char buf1[80]; + ProcessSerialNumber ourPSN; + FSRef ourFSRef; + char *p; + OSStatus err = noErr; #ifdef _DEBUG err = SetFakeMasterNames(); if (err) return err; #endif - - strlcpy(fullpath, path, MAXPATHLEN); + + if (path == NULL) { // NULL means we were called from within BOINC Manager + // Get the full path to this application's bundle (BOINC Manager's bundle) + err = GetCurrentProcess (&ourPSN); + if (err) + return err; // Should never happen + + err = GetProcessBundleLocation(&ourPSN, &ourFSRef); + if (err) + return err; // Should never happen + + err = FSRefMakePath (&ourFSRef, (UInt8*)dir_path, sizeof(dir_path)); + if (err) + return err; // Should never happen + } else + strlcpy(dir_path, path, MAXPATHLEN); // Path to BOINC Manager's bundle was passed as argument + if (strlen(fullpath) >= (MAXPATHLEN-1)) { ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to Manager is too long"); return -1; } - // chmod -R u=rwsx,g=rwsx,o=rx path/BOINCManager.app + strlcpy(fullpath, dir_path, sizeof(fullpath)); + + // chmod -R u=rwsx,g=rwsx,o=rx path/BOINCManager.app // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH // read, write and execute permission for user & group; read and execute permission for others err = DoPrivilegedExec(chmodPath, "-R", "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL); if (err) return err; - strlcat(fullpath, "/Contents/MacOS/", MAXPATHLEN); + // Get the full path to BOINC Manager executable inside this application's bundle + strlcat(fullpath, "/Contents/MacOS/", sizeof(fullpath)); // To allow for branding, assume name of executable inside bundle is same as name of bundle - p = strrchr(path, '/'); // Assume name of executable inside bundle is same as name of bundle + p = strrchr(dir_path, '/'); // Assume name of executable inside bundle is same as name of bundle if (p == NULL) - p = path - 1; - strlcat(fullpath, p, MAXPATHLEN); + p = dir_path - 1; + strlcat(fullpath, p+1, sizeof(fullpath)); p = strrchr(fullpath, '.'); // Strip off bundle extension (".app") if (p) *p = '\0'; - if (strlen(fullpath) >= (MAXPATHLEN-1)) { - ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to Manager is too long"); - return -1; - } sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master path/BOINCManager.app/Contents/MacOS/BOINCManager @@ -153,9 +173,9 @@ int SetBOINCAppOwnersGroupsAndPermissions(char *path) { if (err) return err; - - strlcpy(fullpath, path, MAXPATHLEN); - strlcat(fullpath, "/Contents/Resources/boinc", MAXPATHLEN); + // Get the full path to BOINC Clients inside this application's bundle + strlcpy(fullpath, dir_path, sizeof(fullpath)); + strlcat(fullpath, "/Contents/Resources/boinc", sizeof(fullpath)); if (strlen(fullpath) >= (MAXPATHLEN-1)) { ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to client is too long"); return -1; @@ -271,7 +291,7 @@ int SetBOINCDataOwnersGroupsAndPermissions() { result = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory); if ((result == noErr) && (isDirectory)) { // Set owner and group of projects directory's contents - sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_project_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_project_group_name); // chown boinc_master:boinc_project "/Library/Applications/BOINC Data/projects" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) @@ -300,7 +320,7 @@ int SetBOINCDataOwnersGroupsAndPermissions() { result = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory); if ((result == noErr) && (isDirectory)) { // Set owner and group of slots directory's contents - sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_project_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_project_group_name); // chown boinc_master:boinc_project "/Library/Applications/BOINC Data/slots" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) @@ -372,7 +392,7 @@ int SetBOINCDataOwnersGroupsAndPermissions() { result = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory); if ((result == noErr) && (! isDirectory)) { // Set owner and group of switcher application - sprintf(buf1, "%s:%s", boinc_project_name, boinc_project_name); + sprintf(buf1, "%s:%s", boinc_project_user_name, boinc_project_group_name); // chown boinc_project:boinc_project "/Library/Applications/BOINC Data/switcher/switcher" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -533,7 +553,7 @@ int AddAdminUserToGroups(char *user_name) { if (err) return err; - sprintf(buf1, "/groups/%s", boinc_project_name); + sprintf(buf1, "/groups/%s", boinc_project_group_name); // "dscl . -merge /groups/boinc_project users user_name" err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", user_name); @@ -563,12 +583,14 @@ static OSStatus SetFakeMasterNames() { if (pw == NULL) return -1; // Should never happen strlcpy(boinc_master_user_name, pw->pw_name, sizeof(boinc_master_user_name)); + strlcpy(boinc_project_user_name, pw->pw_name, sizeof(boinc_project_user_name)); boinc_master_gid = getegid(); grp = getgrgid(boinc_master_gid); if (grp == NULL) return -1; strlcpy(boinc_master_group_name, grp->gr_name, sizeof(boinc_master_group_name)); + strlcpy(boinc_project_group_name, grp->gr_name, sizeof(boinc_project_group_name)); return noErr; } diff --git a/lib/filesys.C b/lib/filesys.C index 4b56ae51b9..21d708e206 100755 --- a/lib/filesys.C +++ b/lib/filesys.C @@ -474,8 +474,9 @@ int boinc_rmdir(const char* name) { #ifndef _WIN32 int boinc_chown(const char* path, gid_t gid) { - if (chown(path, (uid_t)-1, gid)) { - return ERR_CHOWN; + if (gid) + if (chown(path, (uid_t)-1, gid)) { + return ERR_CHOWN; } return 0; }