diff --git a/checkin_notes b/checkin_notes index ac1c80e2c6..17744be060 100644 --- a/checkin_notes +++ b/checkin_notes @@ -617,3 +617,16 @@ Charlie Jan 15 2008 clientgui/ sg_DlgMessages.cpp ViewMessages.cpp + +Charlie Jan 16 2008 + Mac Sandbox: make BOINC Data directory and files not world-readable to + hide account keys from unauthorized users. + + client/ + check_security.C + client_types.C + file_names.C + main.C + clientgui/ + mac/ + SetupSecurity.cpp diff --git a/client/check_security.C b/client/check_security.C index 202955a921..7e1707a91d 100644 --- a/client/check_security.C +++ b/client/check_security.C @@ -313,8 +313,8 @@ int use_sandbox, int isManager 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) + // The top-level BOINC Data directory should have permission 771 or 571 + if ((sbuf.st_mode & 0577) != 0571) return -1023; } else { diff --git a/client/client_types.C b/client/client_types.C index 067e0aac6e..f8e26b9582 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -656,26 +656,26 @@ int FILE_INFO::set_permissions() { char pathname[256]; get_pathname(this, pathname, sizeof(pathname)); - // give read/exec permissions for user, group and others - // in case someone runs BOINC from different user - if (g_use_sandbox) { + // give exec permissions for user, group and others but give + // read permissions only for user and group to protect account keys 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 + |S_IXOTH ); } else { retval = chmod(pathname, S_IRUSR|S_IWUSR |S_IRGRP|S_IWGRP - |S_IROTH ); } } else { + // give read/exec permissions for user, group and others + // in case someone runs BOINC from different user if (executable) { retval = chmod(pathname, S_IRUSR|S_IWUSR|S_IXUSR diff --git a/client/file_names.C b/client/file_names.C index 92a4a2c48e..d95269906b 100644 --- a/client/file_names.C +++ b/client/file_names.C @@ -109,27 +109,32 @@ void get_slot_dir(int slot, char* path, int len) { // int make_project_dir(PROJECT& p) { char buf[1024]; + mode_t old_mask; int retval; boinc_mkdir(PROJECTS_DIR); #ifndef _WIN32 if (g_use_sandbox) { - chmod(PROJECTS_DIR, + old_mask = umask(2); // Project directories must be world-readable + chmod(PROJECTS_DIR, S_IRUSR|S_IWUSR|S_IXUSR |S_IRGRP|S_IWGRP|S_IXGRP |S_IROTH|S_IXOTH ); + umask(old_mask); } #endif get_project_dir(&p, buf, sizeof(buf)); retval = boinc_mkdir(buf); #ifndef _WIN32 if (g_use_sandbox) { + old_mask = umask(2); // Project directories must be world-readable chmod(buf, S_IRUSR|S_IWUSR|S_IXUSR |S_IRGRP|S_IWGRP|S_IXGRP |S_IROTH|S_IXOTH ); + umask(old_mask); set_to_project_group(buf); } #endif @@ -153,6 +158,8 @@ int remove_project_dir(PROJECT& p) { // int make_slot_dir(int slot) { char buf[1024]; + mode_t old_mask; + if (slot<0) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Bad slot number %d", slot); return ERR_NEG; @@ -160,22 +167,26 @@ int make_slot_dir(int slot) { boinc_mkdir(SLOTS_DIR); #ifndef _WIN32 if (g_use_sandbox) { + old_mask = umask(2); // Slot directories must be world-readable chmod(SLOTS_DIR, S_IRUSR|S_IWUSR|S_IXUSR |S_IRGRP|S_IWGRP|S_IXGRP |S_IROTH|S_IXOTH ); + umask(old_mask); } #endif get_slot_dir(slot, buf, sizeof(buf)); int retval = boinc_mkdir(buf); #ifndef _WIN32 if (g_use_sandbox) { + old_mask = umask(2); // Slot directories must be world-readable chmod(buf, S_IRUSR|S_IWUSR|S_IXUSR |S_IRGRP|S_IWGRP|S_IXGRP |S_IROTH|S_IXOTH ); + umask(old_mask); set_to_project_group(buf); } #endif diff --git a/client/main.C b/client/main.C index 805c487680..4a7132cfa8 100644 --- a/client/main.C +++ b/client/main.C @@ -324,10 +324,11 @@ static void init_core_client(int argc, char** argv) { #ifndef _WIN32 if (g_use_sandbox) - // Set file creation mask to be writable by both user and group + // Set file creation mask to be writable by both user and group and + // world-executable but neither world-readable nor world-writable // Our umask will be inherited by all our child processes // - umask (2); + umask (6); #endif // Initialize the BOINC Diagnostics Framework diff --git a/clientgui/mac/SetupSecurity.cpp b/clientgui/mac/SetupSecurity.cpp index 5be730e1a4..ce5656b3b9 100644 --- a/clientgui/mac/SetupSecurity.cpp +++ b/clientgui/mac/SetupSecurity.cpp @@ -244,7 +244,7 @@ int SetBOINCAppOwnersGroupsAndPermissions(char *path) { return err; // chmod u=rsx,g=rx,o=rx "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher" - // 04055 = S_ISUID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + // 04555 = S_ISUID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH // setuid-on-execution plus read and execute permission for user, group & others err = DoPrivilegedExec(chmodPath, "u=rsx,g=rx,o=rx", fullpath, NULL, NULL, NULL); if (err) @@ -287,9 +287,9 @@ int SetBOINCDataOwnersGroupsAndPermissions() { // Set permissions of BOINC Data directory's contents // chmod -R u+rw,g+rw,o-rw "/Library/Application Support/BOINC Data" - // 0664 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH + // 0660 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP // set read and write permission for user and group, no access for others (leaves execute bits unchanged) - err = DoPrivilegedExec(chmodPath, "-R", "u+rw,g+rw,o+r-w", fullpath, NULL, NULL); + err = DoPrivilegedExec(chmodPath, "-R", "u+rw,g+rw,o-rw", fullpath, NULL, NULL); if (err) return err; @@ -303,13 +303,16 @@ int SetBOINCDataOwnersGroupsAndPermissions() { #endif // Set permissions of BOINC Data directory itself - // chmod u=rwx,g=rwx,o=rx "/Library/Application Support/BOINC Data" - // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH + // chmod u=rwx,g=rwx,o=x "/Library/Application Support/BOINC Data" + // 0771 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IXOTH // read, write and execute permission for user & group; read and execute permission for others - err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL); + err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=x", fullpath, NULL, NULL, NULL); if (err) return err; - + + // Since we no longer allow read access for others (S_IROTH), setting ownership + // and permissions for gui_rpc_auth.cfg file is probably now redundant + // Does gui_rpc_auth.cfg file exist? strlcpy(fullpath, BOINCDataDirPath, MAXPATHLEN); strlcat(fullpath, "/gui_rpc_auth.cfg", MAXPATHLEN); @@ -504,13 +507,13 @@ int SetBOINCDataOwnersGroupsAndPermissions() { if ((result == noErr) && (! isDirectory)) { // Set owner and group of AppStats application (must be setuid root) sprintf(buf1, "root:%s", boinc_master_group_name); - // chown root:boinc_project "/Library/Application Support/BOINC Data/switcher/setprojectgrp" + // chown root:boinc_project "/Library/Application Support/BOINC Data/switcher/AppStats" err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL); if (err) return err; // Set permissions of AppStats application - // chmod u=rsx,g=rx,o= "/Library/Application Support/BOINC Data/switcher/setprojectgrp" + // chmod u=rsx,g=rx,o= "/Library/Application Support/BOINC Data/switcher/AppStats" // 04550 = S_ISUID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP // setuid-on-execution plus read and execute permission for user and group err = DoPrivilegedExec(chmodPath, "u=rsx,g=rx,o=", fullpath, NULL, NULL, NULL); @@ -555,7 +558,7 @@ static OSStatus UpdateNestedDirectories(char * basepath) { isDirectory = S_ISDIR(sbuf.st_mode); if (isDirectory) { - // chmod u+x,g+x,o+x fullpath + // chmod u=rwx,g=rwx,o=rx fullpath // 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 retval = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL);