mirror of https://github.com/BOINC/boinc.git
Mac Sandbox: Security fixes for Mac OS 10.6 Snow Leopard
svn path=/trunk/boinc/; revision=18978
This commit is contained in:
parent
e82aad226a
commit
d34c522d74
|
@ -7412,3 +7412,28 @@ Rom 1 Sept 2009
|
|||
|
||||
client/
|
||||
http_curl.cpp,h
|
||||
|
||||
Charlie 1 Sept 2009
|
||||
- Mac Sandbox: Security fixes for Mac OS 10.6 Snow Leopard.
|
||||
Mac OS 10.6 requires administrator authorization to run setgid
|
||||
applications if they use the AppKit (Cocoa) framework. The Mac
|
||||
installer adds all users with admin privileges (members of group
|
||||
admin) to group boinc_master. Since the Manager doesn't need to
|
||||
run setgid boinc_master if the user is a member of that group,
|
||||
we eliminate the setgid.
|
||||
This means that non-admin users will be able to run the Manager
|
||||
only if the sysadmin adds them to group boinc_master, so we now
|
||||
create a login item or set the screensaver only for those users
|
||||
who are members of group boinc_master.
|
||||
If a user who is not a member of that group runs the Manager, it
|
||||
displays an alert saying that in order to administer BOINC, he
|
||||
needs to ask the sysadmin to add him to group boinc_master.
|
||||
|
||||
client/
|
||||
check_security.cpp
|
||||
clientgui/
|
||||
BOINCGUIApp.cpp
|
||||
mac/
|
||||
SetupSecurity.cpp
|
||||
mac_installer/
|
||||
PostInstall.cpp
|
||||
|
|
|
@ -32,10 +32,13 @@
|
|||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include "str_replace.h"
|
||||
#include "error_numbers.h"
|
||||
#include "file_names.h"
|
||||
|
||||
#ifdef __WXMAC__ // If Mac BOINC Manager
|
||||
bool IsUserInGroupBM();
|
||||
#endif
|
||||
|
||||
static int CheckNestedDirectories(char * basepath, int depth, int use_sandbox);
|
||||
|
||||
#if (! defined(__WXMAC__) && ! defined(_MAC_INSTALLER))
|
||||
|
@ -81,10 +84,6 @@ int use_sandbox, int isManager
|
|||
ProcessSerialNumber ourPSN;
|
||||
ProcessInfoRec pInfo;
|
||||
FSRef ourFSRef;
|
||||
char *p;
|
||||
#endif
|
||||
#ifdef _MAC_INSTALLER
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
#define NUMBRANDS 3
|
||||
|
@ -159,10 +158,14 @@ saverName[2] = "Progress Thru Processors";
|
|||
|
||||
boinc_master_uid = sbuf.st_uid;
|
||||
boinc_master_gid = sbuf.st_gid;
|
||||
|
||||
#ifdef __WXMAC__
|
||||
if (!IsUserInGroupBM())
|
||||
return -1099;
|
||||
#endif
|
||||
} else {
|
||||
boinc_master_uid = geteuid();
|
||||
boinc_master_gid = getegid();
|
||||
|
||||
}
|
||||
|
||||
#ifdef _MAC_INSTALLER
|
||||
|
@ -213,6 +216,7 @@ saverName[2] = "Progress Thru Processors";
|
|||
boinc_project_gid = grp->gr_gid;
|
||||
}
|
||||
|
||||
#if 0 // Manager is no longer setgid
|
||||
#if (defined(__WXMAC__) || defined(_MAC_INSTALLER)) // If Mac BOINC Manager or installer
|
||||
// Get the full path to BOINC Manager executable inside this application's bundle
|
||||
strlcpy(full_path, dir_path, sizeof(full_path));
|
||||
|
@ -238,6 +242,8 @@ saverName[2] = "Progress Thru Processors";
|
|||
return -1015;
|
||||
}
|
||||
#endif
|
||||
#endif // Manager is no longer setgid
|
||||
|
||||
|
||||
#ifdef _MAC_INSTALLER
|
||||
// Require absolute owner and group boinc_master:boinc_master
|
||||
|
@ -304,12 +310,13 @@ saverName[2] = "Progress Thru Processors";
|
|||
#else // _MAC_INSTALLER
|
||||
getcwd(dir_path, sizeof(dir_path)); // Client or Manager
|
||||
|
||||
if (! isManager) { // If BOINC Client
|
||||
if (egid != boinc_master_gid)
|
||||
return -1019; // Client or Manager should be running setgid boinc_master
|
||||
return -1019; // Client should be running setgid boinc_master
|
||||
|
||||
if (! isManager) // If BOINC Client
|
||||
if (euid != boinc_master_uid)
|
||||
return -1020; // BOINC Client should be running setuid boinc_master
|
||||
}
|
||||
#endif
|
||||
|
||||
retval = stat(dir_path, &sbuf);
|
||||
|
@ -650,3 +657,36 @@ static void GetPathToThisProcess(char* outbuf, size_t maxLen) {
|
|||
*q = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __WXMAC__ // If Mac BOINC Manager
|
||||
bool IsUserInGroupBM() {
|
||||
group *grp;
|
||||
gid_t rgid;
|
||||
char *userName, *groupMember;
|
||||
int i;
|
||||
|
||||
grp = getgrgid(boinc_master_gid);
|
||||
if (grp) {
|
||||
|
||||
rgid = getgid();
|
||||
if (rgid == boinc_master_gid) {
|
||||
return true; // User's primary group is boinc_master
|
||||
}
|
||||
|
||||
userName = getlogin();
|
||||
if (userName) {
|
||||
for (i=0; ; i++) { // Step through all users in group boinc_master
|
||||
groupMember = grp->gr_mem[i];
|
||||
if (groupMember == NULL)
|
||||
return false; // User is not a member of group boinc_master
|
||||
if (strcmp(userName, groupMember) == 0) {
|
||||
return true; // User is a member of group boinc_master
|
||||
}
|
||||
} // for (i)
|
||||
} // if (userName)
|
||||
} // if grp
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // __WXMAC__
|
||||
|
|
|
@ -304,11 +304,16 @@ bool CBOINCGUIApp::OnInit() {
|
|||
|
||||
ShowApplication(true);
|
||||
|
||||
if (iErrorCode == -1099) {
|
||||
strDialogMessage =
|
||||
_("You currently are not authorized to manage the client.\nPlease contact your administrator to add you to the 'boinc_master' user group.");
|
||||
} else {
|
||||
strDialogMessage.Printf(
|
||||
wxT("BOINC ownership or permissions are not set properly; please reinstall BOINC.\n(Error code %d)\n"),
|
||||
_("BOINC ownership or permissions are not set properly; please reinstall BOINC.\n(Error code %d)\n"),
|
||||
iErrorCode
|
||||
);
|
||||
|
||||
}
|
||||
wxMessageDialog* pDlg = new wxMessageDialog(NULL, strDialogMessage, wxT("BOINC Manager"), wxOK);
|
||||
|
||||
pDlg->ShowModal();
|
||||
|
|
|
@ -179,14 +179,14 @@ saverName[2] = "Progress Thru Processors";
|
|||
|
||||
#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, read & execute for others
|
||||
err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwsx,o=rx", fullpath, NULL, NULL, NULL);
|
||||
// 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 & execute for others
|
||||
err = DoPrivilegedExec(chmodPath, "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL);
|
||||
#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);
|
||||
// 0555 = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
|
||||
// read and execute permission for user, group & others
|
||||
err = DoPrivilegedExec(chmodPath, "u=rx,g=rx,o=rx", fullpath, NULL, NULL, NULL);
|
||||
#endif
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -657,12 +657,16 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
Boolean deleteLoginItem;
|
||||
char skinName[256];
|
||||
char s[256];
|
||||
group *grp;
|
||||
group grpAdmin, *grpAdminPtr;
|
||||
char adminBuf[32768];
|
||||
group grpBOINC_master, *grpBOINC_masterPtr;
|
||||
char bmBuf[32768];
|
||||
Boolean saverAlreadySet = true;
|
||||
Boolean found = false;
|
||||
FILE *f;
|
||||
OSStatus err;
|
||||
long response;
|
||||
Boolean isGroupMember;
|
||||
#ifdef SANDBOX
|
||||
char *p;
|
||||
short i;
|
||||
|
@ -671,11 +675,17 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
grp = getgrnam("admin");
|
||||
if (grp == NULL) { // Should never happen
|
||||
err = getgrnam_r("admin", &grpAdmin, adminBuf, sizeof(adminBuf), &grpAdminPtr);
|
||||
if (err) { // Should never happen unless buffer too small
|
||||
puts("getgrnam(\"admin\") failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = getgrnam_r("boinc_master", &grpBOINC_master, bmBuf, sizeof(bmBuf), &grpBOINC_masterPtr);
|
||||
if (err) { // Should never happen unless buffer too small
|
||||
puts("getgrnam(\"boinc_master\") failed\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
FindSkinName(skinName, sizeof(skinName));
|
||||
|
@ -699,25 +709,45 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
continue;
|
||||
|
||||
#ifdef SANDBOX
|
||||
isGroupMember = false;
|
||||
i = 0;
|
||||
while ((p = grp->gr_mem[i]) != NULL) { // Step through all users in group admin
|
||||
while ((p = grpAdmin.gr_mem[i]) != NULL) { // Step through all users in group admin
|
||||
if (strcmp(p, dp->d_name) == 0) {
|
||||
// User is a member of group admin, so add user to groups boinc_master and boinc_project
|
||||
err = AddAdminUserToGroups(p);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
isGroupMember = true;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!isGroupMember) {
|
||||
i = 0;
|
||||
while ((p = grpBOINC_master.gr_mem[i]) != NULL) { // Step through all users in group boinc_master
|
||||
if (strcmp(p, dp->d_name) == 0) {
|
||||
// User is a member of group boinc_master
|
||||
isGroupMember = true;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#else
|
||||
isGroupMember = true;
|
||||
#endif
|
||||
|
||||
deleteLoginItem = CheckDeleteFile(dp->d_name);
|
||||
if (!isGroupMember) {
|
||||
deleteLoginItem = true;
|
||||
}
|
||||
saved_uid = geteuid();
|
||||
seteuid(pw->pw_uid); // Temporarily set effective uid to this user
|
||||
|
||||
SetLoginItem(brandID, deleteLoginItem); // Set login item for this user
|
||||
|
||||
if (isGroupMember) {
|
||||
SetSkinInUserPrefs(dp->d_name, skinName);
|
||||
|
||||
if (response < 0x1060) {
|
||||
|
@ -739,6 +769,7 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
pclose(f);
|
||||
if (!found) {
|
||||
saverAlreadySet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,8 +782,8 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
return noErr;
|
||||
}
|
||||
|
||||
if (!ShowMessage(true, "Do you want to set %s as the screensaver for all users on this Mac?",
|
||||
brandName[brandID])) {
|
||||
if (!ShowMessage(true, "Do you want to set %s as the screensaver for all %s users on this Mac?",
|
||||
brandName[brandID], brandName[brandID])) {
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
@ -775,6 +806,24 @@ OSErr UpdateAllVisibleUsers(long brandID)
|
|||
if (pw == NULL) // "Deleted Users", "Shared", etc.
|
||||
continue;
|
||||
|
||||
#ifdef SANDBOX
|
||||
isGroupMember = false;
|
||||
|
||||
i = 0;
|
||||
while ((p = grpBOINC_master.gr_mem[i]) != NULL) { // Step through all users in group boinc_master
|
||||
if (strcmp(p, dp->d_name) == 0) {
|
||||
// User is a member of group boinc_master
|
||||
isGroupMember = true;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (!isGroupMember) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
saved_uid = geteuid();
|
||||
seteuid(pw->pw_uid); // Temporarily set effective uid to this user
|
||||
|
||||
|
|
Loading…
Reference in New Issue