mirror of https://github.com/BOINC/boinc.git
*** empty log message ***
svn path=/trunk/boinc/; revision=10260
This commit is contained in:
parent
3199549ec8
commit
670d121848
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue