diff --git a/checkin_notes b/checkin_notes index e7dec0920c..6420d40d4d 100755 --- a/checkin_notes +++ b/checkin_notes @@ -5539,7 +5539,7 @@ Charlie 6 June 2006 clientgui/ mac/ - SecurityUtility.cpp (new + SecurityUtility.cpp (new) SetupSecurity.h (new) SetupSecurity.cpp mac_build/ @@ -5565,3 +5565,16 @@ Rom 7 June 2006 boinc_win.h diagnostics.C diagnostics_win.C + +Charlie 7 June 2006 + - Mac: SetUpSecurity sets owner=boinc_master, group=boinc_master and + permissions of BOINC Manager bundle and its contents. + When run standalone (from XCode), it assists the development / debug + cycle by making everything group writeable and adds logged in user + to group boinc_master. When run from Installer, Manager or Client, + makes everything non-writeable by owner, group and other for security. + + clientgui/ + mac/ + SecurityUtility.cpp + SetupSecurity.cpp diff --git a/clientgui/mac/SecurityUtility.cpp b/clientgui/mac/SecurityUtility.cpp index 2471dc016b..649ff68bc8 100644 --- a/clientgui/mac/SecurityUtility.cpp +++ b/clientgui/mac/SecurityUtility.cpp @@ -19,14 +19,27 @@ // SecurityUtility.cpp +#include // for MAXPATHLEN +#include // for getwd + #include "SetupSecurity.h" // Standalone utility to set up BOINC security owners, groups, permissions int main(int argc, char *argv[]) { OSStatus err; + char boincPath[MAXPATHLEN]; err = CreateBOINCUsersAndGroups(); + if (err != noErr) + return err; + + boincPath[0] = 0; + getwd(boincPath); + //ShowSecurityError("Current Working Directory is %s", wd); + + err = SetBOINCAppOwnersGroupsAndPermissions(boincPath, "BOINCManager", true); + return err; } diff --git a/clientgui/mac/SetupSecurity.cpp b/clientgui/mac/SetupSecurity.cpp index a5178d85ab..e7dde14c80 100644 --- a/clientgui/mac/SetupSecurity.cpp +++ b/clientgui/mac/SetupSecurity.cpp @@ -25,6 +25,8 @@ #include // getgrname, getgrgid #include // getpwname, getpwuid, getuid #include +#include // for MAXPATHLEN +#include // for umask() #include @@ -32,7 +34,6 @@ static OSStatus CreateUserAndGroup(char * name, Boolean * createdNew); static OSStatus GetAuthorization(void); -static void ShowSecurityError(const char *format, ...); static pascal Boolean ErrorDlgFilterProc(DialogPtr theDialog, EventRecord *theEvent, short *theItemHit); static AuthorizationRef gOurAuthRef = NULL; @@ -75,6 +76,177 @@ OSStatus CreateBOINCUsersAndGroups() { } +OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Boolean development) { + char fullpath[MAXPATHLEN]; + char buf1[80]; + char *args[8]; + short i; + mode_t old_mask; + unsigned long endSleep; + OSStatus err = noErr; + + strlcpy(fullpath, path, MAXPATHLEN); + strlcat(fullpath, "/", MAXPATHLEN); + strlcat(fullpath, managerName, MAXPATHLEN); + strlcat(fullpath, ".app", MAXPATHLEN); + if (strlen(fullpath) >= (MAXPATHLEN-1)) { + ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to Manager is too long"); + return -1; + } + + err = GetAuthorization(); + if (err != noErr) { + ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: GetAuthorization returned error %d", err); + return err; + } + + sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + for (i=0; i<5; i++) { // Retry 5 times if error + // chown boinc_master:boinc_master path/BOINCManager.app + args[0] = "-R"; + args[1] = buf1; + args[2] = fullpath; + args[3] = NULL; + err = AuthorizationExecuteWithPrivileges (gOurAuthRef, chownPath, 0, args, NULL); + if (err == noErr) + break; + } + if (err != noErr) { + ShowSecurityError("\"chown %s %s\" returned error %d", buf1, fullpath, err); + return err; + } + + if (development) { + old_mask = umask(0); + + for (i=0; i<5; i++) { // Retry 5 times if error + // 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 & others + args[0] = "-R"; + args[1] = "u=rwx,g=rwx,o=rx"; + args[2] = fullpath; + args[3] = NULL; + err = AuthorizationExecuteWithPrivileges (gOurAuthRef, chmodPath, 0, args, NULL); + if (err == noErr) + break; + } + + umask(old_mask); + + if (err != noErr) { + ShowSecurityError("\"chmod -R %s %s\" returned error %d", args[1], fullpath, err); + return err; + } + + endSleep = TickCount() + (1*60); + while (TickCount() < endSleep) { + sleep (1); + } + } // End if (development) + + strlcat(fullpath, "/Contents/MacOS/", MAXPATHLEN); + strlcat(fullpath, managerName, MAXPATHLEN); + if (strlen(fullpath) >= (MAXPATHLEN-1)) { + ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to Manager is too long"); + return -1; + } + + old_mask = umask(0); + + for (i=0; i<5; i++) { // Retry 5 times if error + if (development) { + // chmod u=rwx,g=rwsx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager + // 02775 = S_ISGID | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH + // setgid-on-execution plus read, write and execute permission for user, group & others + args[0] = "u=rwx,g=rwsx,o=rx"; + } else { + // chmod u=rx,g=rsx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager + // 02555 = S_ISGID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + // setgid-on-execution plus read and execute permission for user, group & others + args[0] = "u=rx,g=rsx,o=rx"; + } + args[1] = fullpath; + args[2] = NULL; + err = AuthorizationExecuteWithPrivileges (gOurAuthRef, chmodPath, 0, args, NULL); + if (err == noErr) + break; + } + + umask(old_mask); + + if (err != noErr) { + ShowSecurityError("\"chmod %s %s\" returned error %d", args[0], fullpath, err); + return err; + } + + endSleep = TickCount() + (1*60); + while (TickCount() < endSleep) { + sleep (1); + } + + strlcpy(fullpath, path, MAXPATHLEN); + strlcat(fullpath, "/", MAXPATHLEN); + strlcat(fullpath, managerName, MAXPATHLEN); + strlcat(fullpath, ".app/Contents/Resources/boinc", MAXPATHLEN); + if (strlen(fullpath) >= (MAXPATHLEN-1)) { + ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to client is too long"); + return -1; + } + + old_mask = umask(0); + + for (i=0; i<5; i++) { // Retry 5 times if error + if (development) { + // chmod u=rwsx,g=rwsx,o=rx path/BOINCManager.app/Contents/Resources/boinc + // 06775 = S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH + // setuid-on-execution, setgid-on-execution plus read, write and execute permission for user, group & others + args[0] = "u=rwsx,g=rwsx,o=rx"; + } else { + // chmod u=rsx,g=rsx,o=rx path/BOINCManager.app/Contents/Resources/boinc + // 06555 = S_ISUID | S_ISGID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + // setuid-on-execution, setgid-on-execution plus read and execute permission for user, group & others + args[0] = "u=rsx,g=rsx,o=rx"; + } + args[1] = fullpath; + args[2] = NULL; + err = AuthorizationExecuteWithPrivileges (gOurAuthRef, chmodPath, 0, args, NULL); + if (err == noErr) + break; + } + + umask(old_mask); + + if (err != noErr) { + ShowSecurityError("\"chmod %s %s\" returned error %d", args[0], fullpath, err); + return err; + } + + if (development) { + sprintf(buf1, "/groups/%s", boinc_master_name); + + // Something like "dscl . -merge /groups/boinc_master users login_name" + for (i=0; i<5; i++) { // Retry 5 times if error + args[0] = "."; + args[1] = "-merge"; // "-append"; + args[2] = buf1; + args[3] = "users"; + args[4] = getlogin(); + args[5] = NULL; + err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL); + if (err == noErr) + break; + } + + if (err != noErr) { + ShowSecurityError("\"dscl . -create -merge %s users %s\" returned error %d", buf1, getlogin(), err); + return err; + } + } // End if (development) + + return err; +} + static OSStatus CreateUserAndGroup(char * name, Boolean * createdNew) { OSStatus err = noErr; @@ -161,7 +333,7 @@ static OSStatus CreateUserAndGroup(char * name, Boolean * createdNew) { err = GetAuthorization(); if (err != noErr) { - ShowSecurityError("GetAuthorization returned error %d", err); + ShowSecurityError("CreateUserAndGroup: GetAuthorization returned error %d", err); return err; } @@ -374,7 +546,7 @@ static OSStatus GetAuthorization (void) { } -static void ShowSecurityError(const char *format, ...) { +void ShowSecurityError(const char *format, ...) { va_list args; char s[1024]; short itemHit; diff --git a/clientgui/mac/SetupSecurity.h b/clientgui/mac/SetupSecurity.h index 53e05eb1e6..f588555987 100644 --- a/clientgui/mac/SetupSecurity.h +++ b/clientgui/mac/SetupSecurity.h @@ -21,4 +21,6 @@ OSStatus CreateBOINCUsersAndGroups(void); +OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Boolean development); +void ShowSecurityError(const char *format, ...); diff --git a/mac_build/boinc.xcodeproj/project.pbxproj b/mac_build/boinc.xcodeproj/project.pbxproj index 9a70900030..1526131ce1 100755 --- a/mac_build/boinc.xcodeproj/project.pbxproj +++ b/mac_build/boinc.xcodeproj/project.pbxproj @@ -627,7 +627,7 @@ isa = PBXContainerItemProxy; containerPortal = 20286C28FDCF999611CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = DD7748970A356C880025D05E /* SetUpSecurity */; + remoteGlobalIDString = DD7748970A356C880025D05E; remoteInfo = SetUpSecurity; }; DDAD19CC09090824004E7DD0 /* PBXContainerItemProxy */ = { @@ -885,7 +885,7 @@ DD73E36208A06ED400656EB1 /* gui_rpc_server_ops.C */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = gui_rpc_server_ops.C; path = ../client/gui_rpc_server_ops.C; sourceTree = SOURCE_ROOT; }; DD73E3A308A078AF00656EB1 /* Localization.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Localization.cpp; path = ../clientgui/Localization.cpp; sourceTree = SOURCE_ROOT; }; DD73E3A408A078AF00656EB1 /* Localization.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Localization.h; path = ../clientgui/Localization.h; sourceTree = SOURCE_ROOT; }; - DD7748980A356C880025D05E /* SetUpSecurity */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = SetUpSecurity; sourceTree = BUILT_PRODUCTS_DIR; }; + DD7748980A356C880025D05E /* SetUpSecurity */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SetUpSecurity; sourceTree = BUILT_PRODUCTS_DIR; }; DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SetupSecurity.cpp; path = ../clientgui/mac/SetupSecurity.cpp; sourceTree = SOURCE_ROOT; }; DD7C5E7508110AE3002FCE1E /* ScreenSaver.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScreenSaver.framework; path = /System/Library/Frameworks/ScreenSaver.framework; sourceTree = ""; }; DD81C3D507C5CEB50098A04D /* cpp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = cpp.h; path = ../client/cpp.h; sourceTree = SOURCE_ROOT; };