From 477677ac5a442e8f81b31a7c6139de33b9d9afd4 Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Thu, 15 Jun 2006 11:11:41 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=10356 --- checkin_notes | 26 ++++ client/check_security.C | 162 ++++++++++++++++++---- client/main.C | 22 ++- clientgui/BOINCGUIApp.cpp | 27 ++-- clientgui/mac/MacGUI.pch | 34 ++--- clientgui/mac/SecurityUtility.cpp | 3 +- clientgui/mac/SetupSecurity.cpp | 145 +++++++++++++------ clientgui/mac/SetupSecurity.h | 9 +- lib/util.h | 2 +- mac_build/boinc.xcodeproj/project.pbxproj | 23 +-- 10 files changed, 332 insertions(+), 121 deletions(-) diff --git a/checkin_notes b/checkin_notes index 20592c5374..35bd8946ac 100755 --- a/checkin_notes +++ b/checkin_notes @@ -6036,3 +6036,29 @@ Rom 15 June 2006 forum_moderate_post_action.php forum_moderate_thread_action.php forum_report_post.php + +Charlie 15 June 2006 + - Mac sandbox: + - GDB can't attach to applications which are running as a diferent user + or group so it ignores the S_ISUID and S_ISGID permisison bits when + launching an application. To work around this, the _DEBUG version + of both the Manager and Client use the current user and group, and + temporarily change the ownership of the BOINC Data hierarchy if + necessary. + - Manager and Client call check_security(); deployment versions notify + the user and quit if they find a problem with ownership or permissions + of either the application or the BOINC Data. + - Better setting of _DEBUG and __WXDEBUG__ in Manager and Client builds. + + client/ + check_security.C + main.C + clientgui/ + BOINCGUIApp.cpp + mac/ + MacGUI.pch + SecurityUtility.cpp + SetupSecurity.cpp,h + mac_build/ + boinc.xcodeproj/ + project.pbxproj diff --git a/client/check_security.C b/client/check_security.C index 6603c61fbd..8564bf486f 100644 --- a/client/check_security.C +++ b/client/check_security.C @@ -28,38 +28,69 @@ #include // for MAXPATHLEN #include "util.h" #include "error_numbers.h" +#include "file_names.h" + +#ifdef _DEBUG +// GDB can't attach to applications which are running as a diferent user or group so +// it ignores the S_ISUID and S_ISGID permisison bits when launching an application. +// 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]; +#else +#define boinc_master_user_name "boinc_master" +#define boinc_master_group_name "boinc_master" +#endif -#define boinc_master_name "boinc_master" #define boinc_project_name "boinc_project" - // Returns FALSE (0) if owners and permissions are OK, else TRUE (1) -int check_security(int isManager) { +int check_security() { passwd *pw; - gid_t egid, rgid, boinc_master_gid, boinc_project_gid; - uid_t euid, ruid, boinc_master_uid, boinc_project_uid; + gid_t egid, boinc_master_gid, boinc_project_gid; + uid_t euid, boinc_master_uid, boinc_project_uid; char *p; group *grp; int i; - char dir_path[MAXPATHLEN]; + char dir_path[MAXPATHLEN], full_path[MAXPATHLEN]; struct stat sbuf; int retval; +#ifdef __WXMAC__ // If Mac BOINC Manager + ProcessSerialNumber ourPSN; + FSRef ourFSRef; +#endif - pw = getpwnam(boinc_master_name); +#ifdef _DEBUG +// GDB can't attach to applications which are running as a diferent user or group so +// it ignores the S_ISUID and S_ISGID permisison bits when launching an application. +// To work around this, the _DEBUG version uses the current user and group. + boinc_master_uid = geteuid(); + pw = getpwuid(boinc_master_uid); + if (pw == NULL) + return ERR_USER_REJECTED; // Should never happen + strlcpy(boinc_master_user_name, pw->pw_name, sizeof(boinc_master_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)); +#else + pw = getpwnam(boinc_master_user_name); if (pw == NULL) return ERR_USER_REJECTED; // User boinc_master does not exist boinc_master_uid = pw->pw_uid; + grp = getgrnam(boinc_master_group_name); + if (grp == NULL) + return ERR_GETGRNAM; // Group boinc_master does not exist + boinc_master_gid = grp->gr_gid; +#endif + pw = getpwnam(boinc_project_name); if (pw == NULL) return ERR_USER_REJECTED; // User boinc_project does not exist boinc_project_uid = pw->pw_uid; - grp = getgrnam(boinc_master_name); - if (grp == NULL) - return ERR_GETGRNAM; // Group boinc_master does not exist - boinc_master_gid = grp->gr_gid; - grp = getgrnam(boinc_project_name); if (grp == NULL) return ERR_GETGRNAM; // Group boinc_project does not exist @@ -69,26 +100,82 @@ int check_security(int isManager) { p = grp->gr_mem[i]; if (p == NULL) return ERR_GETGRNAM; // User boinc_master is not a member of group boinc_project - if (strcmp(p, boinc_master_name) == 0) + if (strcmp(p, boinc_master_user_name) == 0) break; } - rgid = getgid(); +#ifdef __WXMAC__ // If Mac BOINC Manager + // Get the full path to BOINC Manager application's bundle + retval = GetCurrentProcess (&ourPSN); + if (retval) + return retval; // Should never happen + + retval = GetProcessBundleLocation(&ourPSN, &ourFSRef); + if (retval) + return retval; // Should never happen + + retval = FSRefMakePath (&ourFSRef, (UInt8*)dir_path, sizeof(dir_path)); + if (retval) + return retval; // Should never happen + + // Get the full path to BOINC Manager 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)); + p = strrchr(full_path, '.'); // Strip off bundle extension (".app") + if (p) + *p = '\0'; + + retval = stat(dir_path, &sbuf); + if (retval) + return retval; // Should never happen + + if (sbuf.st_gid != boinc_master_gid) + return ERR_USER_PERMISSION; + + if ((sbuf.st_mode & S_ISGID) != S_ISGID) + return ERR_USER_PERMISSION; + + // 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(dir_path, &sbuf); + if (retval) + return retval; // Should never happen + + if (sbuf.st_gid != boinc_master_gid) + return ERR_USER_PERMISSION; + + if (sbuf.st_uid != boinc_master_uid) + return ERR_USER_PERMISSION; + + if ((sbuf.st_mode & S_ISUID | S_ISGID) != S_ISUID | S_ISGID) + return ERR_USER_PERMISSION; +#endif // Mac BOINC Manager + +// rgid = getgid(); +// ruid = getuid(); egid = getegid(); + euid = geteuid(); +#ifndef _DEBUG if (egid != boinc_master_gid) return ERR_USER_PERMISSION; // We should be running setgid boinc_master - ruid = getuid(); - euid = geteuid(); - if (! isManager) { - if (euid != boinc_master_uid) - return ERR_USER_PERMISSION; // BOINC Client should be running setuid boinc_master - } +#ifndef __WXMAC__ // If NOT Mac BOINC Manager + if (euid != boinc_master_uid) + return ERR_USER_PERMISSION; // BOINC Client should be running setuid boinc_master +#endif +#endif getcwd(dir_path, sizeof(dir_path)); retval = stat(dir_path, &sbuf); if (retval) - return retval; + return retval; // Should never happen // The top-level BOINC Data directory can have a different user if created by the Manager, // but it should always have group boinc_master. @@ -99,9 +186,10 @@ int check_security(int isManager) { if ((sbuf.st_mode & 0575) != 0575) return ERR_USER_PERMISSION; - getcwd(dir_path, sizeof(dir_path)); - strlcat(dir_path, "/projects", MAXPATHLEN); - retval = stat(dir_path, &sbuf); + 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 ERR_USER_PERMISSION; @@ -109,13 +197,14 @@ int check_security(int isManager) { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if ((sbuf.st_mode & 0775) != 0775) + if (sbuf.st_mode != 0775) return ERR_USER_PERMISSION; } - getcwd(dir_path, sizeof(dir_path)); - strlcat(dir_path, "/slots", MAXPATHLEN); - retval = stat(dir_path, &sbuf); + strlcpy(full_path, dir_path, sizeof(dir_path)); + strlcat(full_path, "/", sizeof(full_path)); + 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 ERR_USER_PERMISSION; @@ -123,7 +212,22 @@ int check_security(int isManager) { if (sbuf.st_uid != boinc_master_uid) return ERR_USER_PERMISSION; - if ((sbuf.st_mode & 0775) != 0775) + if (sbuf.st_mode != 0775) + return ERR_USER_PERMISSION; + } + + strlcpy(full_path, dir_path, sizeof(full_path)); + strlcat(full_path, "/", sizeof(full_path)); + 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 ERR_USER_PERMISSION; + + if (sbuf.st_uid != boinc_master_uid) + return ERR_USER_PERMISSION; + + if (sbuf.st_mode != 0770) return ERR_USER_PERMISSION; } diff --git a/client/main.C b/client/main.C index 8d357b16fd..9c86b5a237 100644 --- a/client/main.C +++ b/client/main.C @@ -45,13 +45,14 @@ typedef void (CALLBACK* ClientLibraryShutdown)(); #include #include #endif +#include #include #include #include #endif -#ifdef __APPLE__ -#include // for umask() +#if (defined (__APPLE__) && defined(SANDBOX) && defined(_DEBUG)) +#include "SetupSecurity.h" #endif #ifdef __EMX__ @@ -343,11 +344,11 @@ static void init_core_client(int argc, char** argv) { SetCurrentDirectory(szPath); } -#endif - +#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(); @@ -743,6 +744,19 @@ int main(int argc, char** argv) { #else #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 + SetBOINCDataOwnersGroupsAndPermissions(); +#else + printf( "\nBOINC ownership or permissions are not set properly; please reinstall BOINC\n" ); + return ERR_USER_PERMISSION; +#endif // _DEBUG + } +#endif // SANDBOX + // Initialize Mac OS X idle time measurement / idle detection gEventHandle = NXOpenEventStatus(); #endif // __APPLE__ diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 9faee18804..20ccb8bc04 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -25,6 +25,9 @@ #include #include "filesys.h" #include "util.h" +#if (defined(SANDBOX) && defined(_DEBUG)) +#include "SetupSecurity.h" +#endif #endif #include "stdwx.h" @@ -243,7 +246,7 @@ bool CBrandingScheme::OnInit( wxConfigBase *pConfig ) { bool CBOINCGUIApp::OnInit() { -#ifdef SANDBOX +#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 #endif @@ -320,23 +323,30 @@ bool CBOINCGUIApp::OnInit() { strDirectory += wxT("BOINC Data"); // We don't customize BOINC Data directory name for branding if (! wxDirExists(strDirectory)) { #ifdef SANDBOX - gid_t gid; // Create BOINC Data directory writable by group boinc_master only success = wxMkdir(strDirectory, 0575); +#ifndef _DEBUG + gid_t gid; lookup_group("boinc_master", gid); boinc_chown("BOINC Data", gid); -#else +#endif // ! _DEBUG +#else // SANDBOX success = wxMkdir(strDirectory, 0777); // Does nothing if dir exists -#endif +#endif // ! SANDBOX } success = ::wxSetWorkingDirectory(strDirectory); // wxChar *wd = wxGetWorkingDirectory(buf, 1000); // For debugging } -#endif // __WXMAC__ - #ifdef SANDBOX - if (check_security(true)) { +#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(); +#endif // _DEBUG + + if (check_security()) { wxMessageDialog* pDlg = new wxMessageDialog(m_pFrame, _("BOINC ownership or permissions are not set properly; please reinstall BOINC"),wxT(""), wxOK); pDlg->ShowModal(); @@ -344,7 +354,8 @@ bool CBOINCGUIApp::OnInit() { pDlg->Destroy(); return false; } -#endif +#endif // SANDBOX +#endif // __WXMAC__ // Initialize the BOINC Diagnostics Framework int dwDiagnosticsFlags = diff --git a/clientgui/mac/MacGUI.pch b/clientgui/mac/MacGUI.pch index f63989480e..4023801962 100644 --- a/clientgui/mac/MacGUI.pch +++ b/clientgui/mac/MacGUI.pch @@ -32,29 +32,23 @@ #define HAVE_SSIZE_T +#ifdef _DEBUG + +#undef _DEBUG // so we don't have to link wih debug Wx libs +#undef __WXDEBUG__ + #include "stdwx.h" -#include "config.h" - -// We want to define __WXDEBUG__ to enable certain test code within our project, -// but only for Development builds. Unfortunately, XCode allows us to modify -// compiler or linker flags by build style only on a project-wide basis. If we -// do that, then the compiler & linker flags override these settings for all -// targets in the project. But our different targets need different settings. -// XCode does not provide any way to do this on a per-target basis. -// This means that we can neither add -D__WXDEBUG to the compiler flags for only -// Development Builds of the BOINC Manager, but we also cannot link in the debug -// build of wxWidgets for only Development Builds of the BOINC Manager. -// So we use a couple of ugly hacks here: -// (1) We take advantage that __OPTIMIZE__ is defined only for Deployment builds. -// (2) We define __WXDEBUG__ AFTER including stdwx.h, so as not to require the -// debug build of the wxWidgets library. - -// __OPTIMIZE__ is defined in Deployment builds, not in Development builds -#ifndef __OPTIMIZE__ -// Define this AFTER including stdwx.h so we don't have to link wih debug Wx libs +#define _DEBUG // Redefine _DEBUG for the rest of the code #define __WXDEBUG__ -#endif + +#else // _DEBUG + +#include "stdwx.h" + +#endif // ! _DEBUG + +#include "config.h" // Prototypes for Mac_GUI.cpp Boolean Mac_Authorize(void); diff --git a/clientgui/mac/SecurityUtility.cpp b/clientgui/mac/SecurityUtility.cpp index c5357e0a9e..c515265cb2 100644 --- a/clientgui/mac/SecurityUtility.cpp +++ b/clientgui/mac/SecurityUtility.cpp @@ -42,7 +42,8 @@ int main(int argc, char *argv[]) { getwd(boincPath); //ShowSecurityError("Current Working Directory is %s", wd); - err = SetBOINCAppOwnersGroupsAndPermissions(boincPath, "BOINCManager", true); + strlcat(boincPath, "/BOINCManager.app", sizeof(boincPath)); + err = SetBOINCAppOwnersGroupsAndPermissions(boincPath); if (err != noErr) return err; diff --git a/clientgui/mac/SetupSecurity.cpp b/clientgui/mac/SetupSecurity.cpp index 6ae27274c2..7d8f0a204b 100644 --- a/clientgui/mac/SetupSecurity.cpp +++ b/clientgui/mac/SetupSecurity.cpp @@ -31,19 +31,32 @@ #include "SetupSecurity.h" -static OSStatus CreateUserAndGroup(char * name); static OSStatus GetAuthorization(void); OSStatus DoPrivilegedExec(const char *pathToTool, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5); static pascal Boolean ErrorDlgFilterProc(DialogPtr theDialog, EventRecord *theEvent, short *theItemHit); static void SleepTicks(UInt32 ticksToSleep); - +#ifdef _DEBUG +static OSStatus SetFakeMasterNames(void); +#else +static OSStatus CreateUserAndGroup(char * user_name, char * group_name); +#endif static AuthorizationRef gOurAuthRef = NULL; #define DELAY_TICKS 3 #define DELAY_TICKS_R 10 -#define boinc_master_name "boinc_master" +#ifdef _DEBUG +// GDB can't attach to applications which are running as a diferent user or group so +// it ignores the S_ISUID and S_ISGID permisison bits when launching an application. +// 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]; +#else +#define boinc_master_user_name "boinc_master" +#define boinc_master_group_name "boinc_master" +#endif + #define boinc_project_name "boinc_project" #define MIN_ID 25 /* Minimum user ID / Group ID to create */ @@ -53,41 +66,47 @@ static char chmodPath[] = "/bin/chmod"; static char chownPath[] = "/usr/sbin/chown"; #define RIGHTS_COUNT 3 /* Count of the 3 above items */ -OSStatus CreateBOINCUsersAndGroups() { +int CreateBOINCUsersAndGroups() { +#ifndef _DEBUG char buf1[80]; OSStatus err = noErr; - err = CreateUserAndGroup(boinc_master_name); + err = CreateUserAndGroup(boinc_master_user_name, boinc_master_group_name); if (err != noErr) return err; - err = CreateUserAndGroup(boinc_project_name); + err = CreateUserAndGroup(boinc_project_name, boinc_project_name); if (err != noErr) return err; // Add user boinc_master to group boinc_project sprintf(buf1, "/groups/%s", boinc_project_name); // "dscl . -merge /groups/boinc_project users boinc_master" - err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", boinc_master_name); + err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", boinc_master_user_name); if (err != noErr) return err; system("lookupd -flushcache"); system("memberd -r"); - + +#endif // ! _DEBUG return noErr; } -OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Boolean development) { +int SetBOINCAppOwnersGroupsAndPermissions(char *path) { char fullpath[MAXPATHLEN]; char buf1[80]; + char *p; OSStatus err = noErr; +#ifdef _DEBUG + err = SetFakeMasterNames(); + if (err) + return err; +#endif + 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; @@ -101,59 +120,64 @@ OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Bo return err; strlcat(fullpath, "/Contents/MacOS/", MAXPATHLEN); - strlcat(fullpath, managerName, MAXPATHLEN); + // 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 + if (p == NULL) + p = path - 1; + strlcat(fullpath, p, MAXPATHLEN); + 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_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master path/BOINCManager.app/Contents/MacOS/BOINCManager err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) return err; - if (development) { +#ifdef _DEBUG // 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 err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwsx,o=rx", fullpath, NULL, NULL, NULL); - } else { +#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 err = DoPrivilegedExec(chmodPath, "u=rx,g=rsx,o=rx", fullpath, NULL, NULL, NULL); - } +#endif if (err) return err; strlcpy(fullpath, path, MAXPATHLEN); - strlcat(fullpath, "/", MAXPATHLEN); - strlcat(fullpath, managerName, MAXPATHLEN); - strlcat(fullpath, ".app/Contents/Resources/boinc", MAXPATHLEN); + strlcat(fullpath, "/Contents/Resources/boinc", MAXPATHLEN); if (strlen(fullpath) >= (MAXPATHLEN-1)) { ShowSecurityError("SetBOINCAppOwnersGroupsAndPermissions: path to client is too long"); return -1; } - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master path/BOINCManager.app/Contents/Resources/boinc err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) return err; - if (development) { +#ifdef _DEBUG // 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 err = DoPrivilegedExec(chmodPath, "u=rwsx,g=rwsx,o=rx", fullpath, NULL, NULL, NULL); - } else { +#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 err = DoPrivilegedExec(chmodPath, "u=rsx,g=rsx,o=rx", fullpath, NULL, NULL, NULL); - } +#endif if (err) return err; @@ -161,7 +185,7 @@ OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Bo } -OSStatus SetBOINCDataOwnersGroupsAndPermissions() { +int SetBOINCDataOwnersGroupsAndPermissions() { FSRef ref; Boolean isDirectory; char fullpath[MAXPATHLEN]; @@ -169,6 +193,12 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { OSStatus err = noErr; OSStatus result; char *BOINCDataDirPath = "/Library/Application Support/BOINC Data"; + +#ifdef _DEBUG + err = SetFakeMasterNames(); + if (err) + return err; +#endif strlcpy(fullpath, BOINCDataDirPath, MAXPATHLEN); @@ -178,7 +208,7 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { return noErr; // BOINC Data Directory does not exist // Set owner and group of BOINC Data directory's contents - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) @@ -194,7 +224,7 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { #if 0 // Redundant if we already set BOINC Data directory to boinc_master:boinc_master // Set owner and group of BOINC Data directory itself - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -219,7 +249,7 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { // Make gui_rpc_auth.cfg file readable and writable only by user boinc_master and group boinc_master // Set owner and group of gui_rpc_auth.cfg file - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data/gui_rpc_auth.cfg" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -241,14 +271,14 @@ OSStatus 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_name, boinc_project_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_project "/Library/Applications/BOINC Data/projects" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) return err; // Set owner and group of projects directory itself - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data/projects" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -270,14 +300,14 @@ OSStatus 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_name, boinc_project_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_project "/Library/Applications/BOINC Data/slots" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) return err; // Set owner and group of slots directory itself - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data/slots" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -300,7 +330,7 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { result = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory); if ((result == noErr) && (isDirectory)) { // Set owner and group of locale directory and all its contents - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data/locale" err = DoPrivilegedExec(chownPath, "-R", buf1, fullpath, NULL, NULL); if (err) @@ -323,7 +353,7 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { result = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory); if ((result == noErr) && (isDirectory)) { // Set owner and group of switcher directory - sprintf(buf1, "%s:%s", boinc_master_name, boinc_master_name); + sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name); // chown boinc_master:boinc_master "/Library/Applications/BOINC Data/switcher" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) @@ -361,7 +391,8 @@ OSStatus SetBOINCDataOwnersGroupsAndPermissions() { } -static OSStatus CreateUserAndGroup(char * name) { +#ifndef _DEBUG +static OSStatus CreateUserAndGroup(char * user_name, char * group_name) { OSStatus err = noErr; passwd *pw = NULL; group *grp = NULL; @@ -375,13 +406,13 @@ static OSStatus CreateUserAndGroup(char * name) { char buf2[80]; char buf3[80]; - pw = getpwnam(name); + pw = getpwnam(user_name); if (pw) { userid = pw->pw_uid; userExists = true; } - grp = getgrnam(name); + grp = getgrnam(group_name); if (grp) { groupid = grp->gr_gid; groupExists = true; @@ -437,7 +468,7 @@ static OSStatus CreateUserAndGroup(char * name) { } } - sprintf(buf1, "/groups/%s", name); + sprintf(buf1, "/groups/%s", group_name); sprintf(buf2, "%d", groupid); if (! groupExists) { // If we need to create group @@ -452,7 +483,7 @@ static OSStatus CreateUserAndGroup(char * name) { return err; } // if (! groupExists) - sprintf(buf1, "/users/%s", name); + sprintf(buf1, "/users/%s", user_name); sprintf(buf2, "%d", groupid); sprintf(buf3, "%d", userid); @@ -484,16 +515,18 @@ static OSStatus CreateUserAndGroup(char * name) { err = DoPrivilegedExec(dsclPath, ".", "-create", buf1, "gid", buf2); if (err) return err; - + return noErr; } +#endif // ! _DEBUG -OSStatus AddAdminUserToGroups(char *user_name) { +int AddAdminUserToGroups(char *user_name) { +#ifndef _DEBUG char buf1[80]; OSStatus err = noErr; - sprintf(buf1, "/groups/%s", boinc_master_name); + sprintf(buf1, "/groups/%s", boinc_master_group_name); // "dscl . -merge /groups/boinc_master users user_name" err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", user_name); @@ -510,10 +543,38 @@ OSStatus AddAdminUserToGroups(char *user_name) { system("lookupd -flushcache"); system("memberd -r"); +#endif // ! _DEBUG return noErr; } +#ifdef _DEBUG +// GDB can't attach to applications which are running as a diferent user or group so +// it ignores the S_ISUID and S_ISGID permisison bits when launching an application. +// To work around this, the _DEBUG version uses the current user and group. +static OSStatus SetFakeMasterNames() { + passwd *pw; + group *grp; + gid_t boinc_master_gid; + uid_t boinc_master_uid; + + boinc_master_uid = geteuid(); + pw = getpwuid(boinc_master_uid); + if (pw == NULL) + return -1; // Should never happen + strlcpy(boinc_master_user_name, pw->pw_name, sizeof(boinc_master_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)); + + return noErr; +} +#endif + + static OSStatus GetAuthorization (void) { static Boolean sIsAuthorized = false; AuthorizationRights ourAuthRights; diff --git a/clientgui/mac/SetupSecurity.h b/clientgui/mac/SetupSecurity.h index 6849702eaf..90f20b39e5 100644 --- a/clientgui/mac/SetupSecurity.h +++ b/clientgui/mac/SetupSecurity.h @@ -19,11 +19,10 @@ // SetupSecurity.h - -OSStatus CreateBOINCUsersAndGroups(void); -OSStatus SetBOINCAppOwnersGroupsAndPermissions(char *path, char *managerName, Boolean development); -OSStatus SetBOINCDataOwnersGroupsAndPermissions(void); -OSStatus AddAdminUserToGroups(char *user_name); +int CreateBOINCUsersAndGroups(void); +int SetBOINCAppOwnersGroupsAndPermissions(char *path); +int SetBOINCDataOwnersGroupsAndPermissions(void); +int AddAdminUserToGroups(char *user_name); void ShowSecurityError(const char *format, ...); int CheckSecurity(int isManager); diff --git a/lib/util.h b/lib/util.h index c691ba8819..ebe8216ae6 100755 --- a/lib/util.h +++ b/lib/util.h @@ -132,7 +132,7 @@ extern const char* boincerror(int which_error); #ifndef _WIN32 extern int lookup_group(char*, gid_t& gid); -extern int check_security(int isManager); +extern int check_security(void); #endif #endif diff --git a/mac_build/boinc.xcodeproj/project.pbxproj b/mac_build/boinc.xcodeproj/project.pbxproj index f4d2e0bd22..d9cfb73469 100755 --- a/mac_build/boinc.xcodeproj/project.pbxproj +++ b/mac_build/boinc.xcodeproj/project.pbxproj @@ -121,6 +121,9 @@ DD40826307D3076400163EF5 /* reduce_main.C in Sources */ = {isa = PBXBuildFile; fileRef = DD40825807D3076400163EF5 /* reduce_main.C */; }; DD40826507D3076400163EF5 /* x_opengl.C in Sources */ = {isa = PBXBuildFile; fileRef = DD40825A07D3076400163EF5 /* x_opengl.C */; }; DD40D05107F03A030096C645 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + DD431F230A415EDF0060585A /* SetupSecurity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */; }; + DD431F240A415EE70060585A /* SetupSecurity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */; }; + DD431FAA0A41660D0060585A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; DD48091F081A66F100A174AA /* BOINCSaver.nib in Resources */ = {isa = PBXBuildFile; fileRef = DD48091E081A66F100A174AA /* BOINCSaver.nib */; }; DD4DD0A207EAA648008A6468 /* BOINCTaskBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD81C40307C5D1020098A04D /* BOINCTaskBar.cpp */; }; DD4EC61108A0A083009AA08F /* texture.C in Sources */ = {isa = PBXBuildFile; fileRef = DD4EC60F08A0A083009AA08F /* texture.C */; }; @@ -184,7 +187,6 @@ DDA12AA20A369B5500FBDD12 /* SetupSecurity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */; }; DDA12AAE0A369C5800FBDD12 /* SecurityUtility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDA12AAD0A369C5800FBDD12 /* SecurityUtility.cpp */; }; DDA9D3BC09189A8C0060E7A7 /* Mac_GUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDA9D3BB09189A8C0060E7A7 /* Mac_GUI.cpp */; }; - DDADA51508BAC96200053BFB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; DDAEC9FF07FA5A5C00A7BC36 /* SetVersion.C in Sources */ = {isa = PBXBuildFile; fileRef = DDAEC9E707FA58A000A7BC36 /* SetVersion.C */; }; DDB5060E0958247800181B75 /* libwx_mac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDB5060D0958247800181B75 /* libwx_mac.a */; }; DDB506FA0958446900181B75 /* ProxyInfoPage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDB506F80958446900181B75 /* ProxyInfoPage.cpp */; }; @@ -1116,7 +1118,7 @@ buildActionMask = 2147483647; files = ( DD130F320820C47C001A0291 /* IOKit.framework in Frameworks */, - DDADA51508BAC96200053BFB /* Carbon.framework in Frameworks */, + DD431FAA0A41660D0060585A /* Carbon.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1404,6 +1406,7 @@ DD344B4807C5AC4C0043025C /* app_control.C */, DD344B4907C5AC4C0043025C /* app_graphics.C */, DD344B5A07C5AC9F0043025C /* app_start.C */, + DD6617870A3FFD8C00FFEBEB /* check_security.C */, DD344B6B07C5AD270043025C /* check_state.C */, DD344B6C07C5AD270043025C /* client_msgs.C */, DD344B6D07C5AD270043025C /* client_msgs.h */, @@ -1424,7 +1427,6 @@ F54B8FC902AC0A0C01FB7237 /* cs_scheduler.C */, DD344B9307C5AE2E0043025C /* cs_statefile.C */, DD344B9407C5AE2E0043025C /* cs_trickle.C */, - DD6617870A3FFD8C00FFEBEB /* check_security.C */, DD344B9507C5AE2E0043025C /* dhrystone.C */, DD344B9607C5AE2E0043025C /* dhrystone.h */, DD344B9707C5AE2E0043025C /* dhrystone2.C */, @@ -2479,6 +2481,7 @@ DD58C47608F334EA00C1DF66 /* wizardex.cpp in Sources */, DD8DD4A709D9432F0043019E /* BOINCDialupManager.cpp in Sources */, DD6617890A3FFD8C00FFEBEB /* check_security.C in Sources */, + DD431F230A415EDF0060585A /* SetupSecurity.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2690,6 +2693,7 @@ DDD74DD307CF493D0065AC9D /* shmem.C in Sources */, DDD74DD407CF493E0065AC9D /* util.C in Sources */, DD6617880A3FFD8C00FFEBEB /* check_security.C in Sources */, + DD431F240A415EE70060585A /* SetupSecurity.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2807,6 +2811,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; INSTALL_PATH = "$(HOME)/bin"; + OTHER_CFLAGS = "-D_DEBUG"; OTHER_LDFLAGS = ( "-framework", Carbon, @@ -3053,7 +3058,6 @@ MACOSX_DEPLOYMENT_TARGET = 10.4; OTHER_CFLAGS = ( "-D_THREAD_SAFE", - "-D__WXMAC", "-include", ../clientgui/mac/config.h, ); @@ -3062,7 +3066,6 @@ OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( "../../curl-7.15.3/lib/.libs/libcurl.a", - "-framework Carbon", "-lcrypto", "-lssl", "-lz", @@ -3643,14 +3646,15 @@ OTHER_CFLAGS = ( "-DMAC_OS_X_VERSION_MAX_ALLOWED=1040", "-D_THREAD_SAFE", - "-D__WXMAC", + "-D_DEBUG", "-include", ../clientgui/mac/config.h, ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( + "-framework", + Security, "../../curl-7.15.3/lib/.libs/libcurl.a", - "-framework Carbon", "-lcrypto", "-lssl", "-lz", @@ -3688,7 +3692,6 @@ OTHER_CFLAGS = ( "-DMAC_OS_X_VERSION_MAX_ALLOWED=1030", "-D_THREAD_SAFE", - "-D__WXMAC", "fasm-blocks", "-include", ../clientgui/mac/config.h, @@ -3696,7 +3699,6 @@ OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( "../../curl-7.15.3/lib/.libs/libcurl.a", - "-framework Carbon", "-lcrypto", "-lssl", "-lz", @@ -3817,6 +3819,7 @@ "-DNOCLIPBOARD", "-D_THREAD_SAFE", "-D__WXMAC__", + "-D_DEBUG", "-DHAVE_STRCASECMP_IN_STRING_H", ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; @@ -4317,14 +4320,12 @@ MACOSX_DEPLOYMENT_TARGET = 10.4; OTHER_CFLAGS = ( "-D_THREAD_SAFE", - "-D__WXMAC", "-include", ../clientgui/mac/config.h, ); OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( "../../curl-7.15.3/lib/.libs/libcurl.a", - "-framework Carbon", "-lcrypto", "-lssl", "-lz",