*** empty log message ***

svn path=/trunk/boinc/; revision=10260
This commit is contained in:
Charlie Fenton 2006-06-07 00:59:52 +00:00
parent 3199549ec8
commit 670d121848
1 changed files with 160 additions and 64 deletions

View File

@ -28,18 +28,24 @@
#include <Carbon/Carbon.h>
static OSStatus CreateUserAndGroup(char * name);
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;
#define AUTHORIZE_LOOKUPD_MEMBERD false
static char dsclPath[] = "/usr/bin/dscl";
static char chmodPath[] = "/bin/chmod";
static char chownPath[] = "/usr/sbin/chown";
#if AUTHORIZE_LOOKUPD_MEMBERD
static char lookupdPath[] = "/usr/sbin/lookupd";
static char memberdPath[] = "/usr/sbin/memberd";
#define RIGHTS_COUNT 5
#else
#define RIGHTS_COUNT 3
#endif
#define boinc_master_name "boinc_master"
#define boinc_project_name "boinc_project"
@ -47,18 +53,27 @@ static char memberdPath[] = "/usr/sbin/memberd";
#define MIN_ID 25 /* Minimum user ID / Group ID to create */
int main(int argc, char *argv[]) {
unsigned long endSleep;
Boolean createdNew;
OSStatus err = noErr;
err = CreateUserAndGroup(boinc_master_name);
err = CreateUserAndGroup(boinc_master_name, &createdNew);
if (err != noErr)
return err;
err = CreateUserAndGroup(boinc_project_name);
if (createdNew) {
endSleep = TickCount() + (2*60);
while (TickCount() < endSleep) {
sleep (1);
}
}
err = CreateUserAndGroup(boinc_project_name, &createdNew);
return err;
}
static OSStatus CreateUserAndGroup(char * name) {
static OSStatus CreateUserAndGroup(char * name, Boolean * createdNew) {
OSStatus err = noErr;
passwd *pw = NULL;
group *grp = NULL;
@ -73,6 +88,7 @@ static OSStatus CreateUserAndGroup(char * name) {
char buf2[80];
char buf3[80];
*createdNew = false;
pw = getpwnam(name);
if (pw) {
@ -89,6 +105,8 @@ static OSStatus CreateUserAndGroup(char * name) {
if ( userExists && groupExists )
return noErr; // User and group already exist
*createdNew = true;
// If only user or only group exists, try to use the same ID for the one we create
if (userExists) { // User exists but group does not
usergid = pw->pw_gid;
@ -148,18 +166,23 @@ static OSStatus CreateUserAndGroup(char * name) {
sprintf(buf2, "%d", groupid);
if (! groupExists) { // If we need to create group
for (i=0; i<5; i++) { // Retry 5 times if error
// Something like "dscl . -create /groups/boinc_master"
args[0] = ".";
args[1] = "-create";
args[2] = buf1;
args[3] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s\" returned error %d", buf1, err);
return err;
}
// Something like "dscl . -create /groups/boinc_master gid 33"
for (i=0; i<5; i++) { // Retry 5 times if error
args[0] = ".";
args[1] = "-create"; // "-append";
args[2] = buf1;
@ -167,6 +190,9 @@ static OSStatus CreateUserAndGroup(char * name) {
args[4] = buf2;
args[5] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s gid %s\" returned error %d", buf1, buf2, err);
return err;
@ -178,17 +204,22 @@ static OSStatus CreateUserAndGroup(char * name) {
sprintf(buf3, "%d", userid);
if (! userExists) { // If we need to create user
for (i=0; i<5; i++) { // Retry 5 times if error
// Something like "dscl . -create /users/boinc_master"
args[0] = ".";
args[1] = "-create";
args[2] = buf1;
args[3] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s\" returned error %d", buf1, err);
return err;
}
for (i=0; i<5; i++) { // Retry 5 times if error
// Something like "dscl . -create /users/boinc_master uid 33"
args[0] = ".";
args[1] = "-create"; // "-append";
@ -197,12 +228,34 @@ static OSStatus CreateUserAndGroup(char * name) {
args[4] = buf3;
args[5] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s uid %s\" returned error %d", buf1, buf3, err);
return err;
}
for (i=0; i<5; i++) { // Retry 5 times if error
// Prevent a security hole by not allowing a login from this user
// Something like "dscl . -create /users/boinc_master shell /sbin/nologin"
args[0] = ".";
args[1] = "-create";
args[2] = buf1;
args[3] = "shell";
args[4] = "/sbin/nologin";
args[5] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s shell /sbin/nologin\" returned error %d", buf1, err);
return err;
}
}
for (i=0; i<5; i++) { // Retry 5 times if error
// Always set the user gid if we created either the user or the group or both
// Something like "dscl . -create /users/boinc_master gid 33"
args[0] = ".";
@ -212,41 +265,54 @@ static OSStatus CreateUserAndGroup(char * name) {
args[4] = buf2;
args[5] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, dsclPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"dscl . -create %s gid %s\" returned error %d", buf1, buf2, err);
return err;
}
#if 0
#if AUTHORIZE_LOOKUPD_MEMBERD
for (i=0; i<5; i++) { // Retry 5 times if error
// "lookupd -flushcache"
args[0] = "-flushcache";
args[1] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, lookupdPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"lookupdPath -flushcache\" returned error %d", err);
return err;
}
#endif
for (i=0; i<5; i++) { // Retry 5 times if error
// "memberd -r"
args[0] = "-r";
args[1] = NULL;
err = AuthorizationExecuteWithPrivileges (gOurAuthRef, memberdPath, 0, args, NULL);
if (err == noErr)
break;
}
if (err != noErr) {
ShowSecurityError("\"memberd -r\" returned error %d", err);
return err;
}
#else
system("lookupd -flushcache");
system("memberd -r");
#endif
return noErr;
}
static OSStatus GetAuthorization (void)
{
static OSStatus GetAuthorization (void) {
static Boolean sIsAuthorized = false;
AuthorizationRights ourAuthRights;
AuthorizationFlags ourAuthFlags;
AuthorizationItem ourAuthItem[5];
AuthorizationItem ourAuthItem[RIGHTS_COUNT];
OSErr err = noErr;
if (sIsAuthorized)
@ -276,6 +342,7 @@ static OSStatus GetAuthorization (void)
ourAuthItem[2].valueLength = strlen (chownPath);
ourAuthItem[2].flags = 0;
#if AUTHORIZE_LOOKUPD_MEMBERD
ourAuthItem[3].name = kAuthorizationRightExecute;
ourAuthItem[3].value = lookupdPath;
ourAuthItem[3].valueLength = strlen (lookupdPath);
@ -285,8 +352,9 @@ static OSStatus GetAuthorization (void)
ourAuthItem[4].value = memberdPath;
ourAuthItem[4].valueLength = strlen (memberdPath);
ourAuthItem[4].flags = 0;
#endif
ourAuthRights.count = 5;
ourAuthRights.count = RIGHTS_COUNT;
ourAuthRights.items = ourAuthItem;
ourAuthFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
@ -300,19 +368,47 @@ static OSStatus GetAuthorization (void)
}
static void ShowSecurityError(const char *format, ...)
{
static void ShowSecurityError(const char *format, ...) {
va_list args;
char s[1024];
short itemHit;
AlertStdAlertParamRec alertParams;
ModalFilterUPP ErrorDlgFilterProcUPP;
ProcessSerialNumber ourProcess;
va_start(args, format);
s[0] = vsprintf(s+1, format, args);
va_end(args);
ErrorDlgFilterProcUPP = NewModalFilterUPP(ErrorDlgFilterProc);
alertParams.movable = true;
alertParams.helpButton = false;
alertParams.filterProc = ErrorDlgFilterProcUPP;
alertParams.defaultText = "\pOK";
alertParams.cancelText = NULL;
alertParams.otherText = NULL;
alertParams.defaultButton = kAlertStdAlertOKButton;
alertParams.cancelButton = 0;
alertParams.position = kWindowDefaultPosition;
::GetCurrentProcess (&ourProcess);
::SetFrontProcess(&ourProcess);
StandardAlert (kAlertStopAlert, (StringPtr)s, NULL, NULL, &itemHit);
StandardAlert (kAlertStopAlert, (StringPtr)s, NULL, &alertParams, &itemHit);
DisposeModalFilterUPP(ErrorDlgFilterProcUPP);
}
static pascal Boolean ErrorDlgFilterProc(DialogPtr theDialog, EventRecord *theEvent, short *theItemHit) {
// We need this because this is a command-line application so it does not get normal events
if (Button()) {
*theItemHit = kStdOkItemIndex;
return true;
}
return StdFilterProc(theDialog, theEvent, theItemHit);
}