*** empty log message ***

svn path=/trunk/boinc/; revision=10372
This commit is contained in:
Charlie Fenton 2006-06-16 13:40:30 +00:00
parent c000f180ac
commit 9797277532
8 changed files with 100 additions and 51 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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;
}