Esempio n. 1
0
OSStatus DoPrivilegedExec(const char *pathToTool, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5, char *arg6) {
    short               i;
    char                *args[8];
    OSStatus            err;
    FILE                *ioPipe = NULL;
    char                *p, junk[256];

    err = GetAuthorization();
    if (err != noErr) {
        if (err == errAuthorizationCanceled)
            return err;
        ShowSecurityError("GetAuthorization returned error %d", err);
    } else {
        for (i=0; i<5; i++) {       // Retry 5 times if error
            args[0] = arg1;
            args[1] = arg2;
            args[2] = arg3;
            args[3] = arg4;
            args[4] = arg5;
            args[5] = arg6;
            args[6] = NULL;

            err = AuthorizationExecuteWithPrivileges (gOurAuthRef, pathToTool, 0, args, &ioPipe);
            if (ioPipe) {
                // We use the pipe to signal us when the command has completed
                do {
                    p = fgets(junk, sizeof(junk), ioPipe);
                } while (p);
                
                fclose (ioPipe);
            }

            // AuthorizationExecuteWithPrivileges() does a fork() and so 
            // leaves a zombie process.  Clear these so we don't exceed 
            // the system-imposed limit of processes per user (MAXUPRC).
            while (waitpid(-1, 0, WNOHANG) > 0);
#if 0
            if (strcmp(arg2, "-R") == 0)
                SleepTicks(DELAY_TICKS_R);
            else
                SleepTicks(DELAY_TICKS);
#endif
            if (err == noErr)
                break;
        }
    }
    if (err != noErr)
        ShowSecurityError("\"%s %s %s %s %s %s\" returned error %d", pathToTool, 
                            arg1 ? arg1 : "", arg2 ? arg2 : "", arg3 ? arg3 : "", 
                            arg4 ? arg4 : "", arg5 ? arg5 : "", err);

       return err;
}
Esempio n. 2
0
static OSStatus GetAuthorization (void) {
    static Boolean              sIsAuthorized = false;
    AuthorizationRights         ourAuthRights;
    AuthorizationFlags          ourAuthFlags;
    AuthorizationItem           ourAuthRightsItem[RIGHTS_COUNT];
    AuthorizationEnvironment    ourAuthEnvironment;
    AuthorizationItem           ourAuthEnvItem[1];
    char                        prompt[] = "BOINC needs to have certain permissions set up.\n\n";
    OSStatus                    err = noErr;

    if (sIsAuthorized)
        return noErr;
        
    ourAuthRights.count = 0;
    ourAuthRights.items = NULL;

    err = AuthorizationCreate (&ourAuthRights, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &gOurAuthRef);
    if (err != noErr) {
        ShowSecurityError("AuthorizationCreate returned error %d", err);
        return err;
    }
     
    ourAuthRightsItem[0].name = kAuthorizationRightExecute;
    ourAuthRightsItem[0].value = dsclPath;
    ourAuthRightsItem[0].valueLength = strlen (dsclPath);
    ourAuthRightsItem[0].flags = 0;

    ourAuthRightsItem[1].name = kAuthorizationRightExecute;
    ourAuthRightsItem[1].value = chmodPath;
    ourAuthRightsItem[1].valueLength = strlen (chmodPath);
    ourAuthRightsItem[1].flags = 0;

    ourAuthRightsItem[2].name = kAuthorizationRightExecute;
    ourAuthRightsItem[2].value = chownPath;
    ourAuthRightsItem[2].valueLength = strlen (chownPath);
    ourAuthRightsItem[2].flags = 0;

    ourAuthRights.count = RIGHTS_COUNT;
    ourAuthRights.items = ourAuthRightsItem;

    ourAuthEnvItem[0].name = kAuthorizationEnvironmentPrompt;
    ourAuthEnvItem[0].value = prompt;
    ourAuthEnvItem[0].valueLength = strlen (prompt);
    ourAuthEnvItem[0].flags = 0;

    ourAuthEnvironment.count = 1;
    ourAuthEnvironment.items = ourAuthEnvItem;

    ourAuthFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights;
    
    // When this is called from the installer, the installer has already authenticated.  
    // In that case we are already running with full root privileges so AuthorizationCopyRights() 
    // does not request a password from the user again.
    err = AuthorizationCopyRights (gOurAuthRef, &ourAuthRights, &ourAuthEnvironment, ourAuthFlags, NULL);
    
    if (err == noErr)
        sIsAuthorized = true;
    
    return err;
}
Esempio n. 3
0
// Pass NULL for path when calling this routine from within BOINC Manager
int SetBOINCAppOwnersGroupsAndPermissions(char *path) {
    char                    fullpath[MAXPATHLEN];
    char                    dir_path[MAXPATHLEN];
    char                    buf1[80];
    ProcessSerialNumber     ourPSN;
    FSRef                   ourFSRef, ref;
    char                    *p;
    Boolean                 isDirectory;
    OSStatus                err = noErr;
    
#define NUMBRANDS 3

char *saverName[NUMBRANDS];

saverName[0] = "BOINCSaver";
saverName[1] = "GridRepublic";
saverName[2] = "Progress Thru Processors";

#ifdef _DEBUG
    err = SetFakeMasterNames();
    if (err)
        return err;
#endif

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

    strlcpy(fullpath, dir_path, sizeof(fullpath));

#ifdef _DEBUG
    // chmod -R u=rwx,g=rwx,o=rx path/BOINCManager.app
    // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
    // Set read, write permission for user;  read and execute permission for group and others
    err = DoPrivilegedExec(chmodPath, "-R", "u=rwx,g=rwx,o=rx", fullpath, NULL, NULL, NULL);
#else
    // chmod -R u=rx,g=rx,o=rx path/BOINCManager.app
    // 0555 = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
    // Set read, write permission for user;  read and execute permission for group and others
    err = DoPrivilegedExec(chmodPath, "-R", "u=rx,g=rx,o=rx", fullpath, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    // 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(dir_path, '/');         // Assume name of executable inside bundle is same as name of bundle
    if (p == NULL)
        p = dir_path - 1;
    strlcat(fullpath, p+1, sizeof(fullpath));
    p = strrchr(fullpath, '.');         // Strip off  bundle extension (".app")
    if (p)
        *p = '\0'; 

    sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
    // chown boinc_master:boinc_master path/BOINCManager.app/Contents/MacOS/BOINCManager
    err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
    if (err)
        return err;

#ifdef _DEBUG
        // chmod u=rwx,g=rwx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager
        // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set 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, NULL);
#else
        // chmod u=rx,g=rx,o=rx path/BOINCManager.app/Contents/MacOS/BOINCManager
        // 0555 = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set read and execute permission for user, group & others
        err = DoPrivilegedExec(chmodPath, "u=rx,g=rx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    // 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;
    }
    
    sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
    // chown boinc_master:boinc_master path/BOINCManager.app/Contents/Resources/boinc
    err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
    if (err)
        return err;

#ifdef _DEBUG
        // chmod u=rwsx,g=rwsx,o=rx path/BOINCManager.app/Contents/Resources/boinc
        // 06775 = S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set setuid-on-execution, setgid-on-execution plus read, write and execute permission for user & group, read & execute for others
        err = DoPrivilegedExec(chmodPath, "u=rwsx,g=rwsx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#else
        // chmod u=rsx,g=rsx,o=rx path/BOINCManager.app/Contents/Resources/boinc
        // 06555 = S_ISUID | S_ISGID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
        // Set setuid-on-execution, setgid-on-execution plus read and execute permission for user, group & others
        err = DoPrivilegedExec(chmodPath, "u=rsx,g=rsx,o=rx", fullpath, NULL, NULL, NULL, NULL);
#endif
    if (err)
        return err;

    for (int i=0; i<NUMBRANDS; i++) {
        // Version 6 screensaver has its own embedded switcher application, but older versions don't.
        // We don't allow unauthorized users to run the switcher application in the BOINC Data directory 
        // because they could use it to run as user & group boinc_project and damage project files.
        // The screensaver's switcher application runs as user and group "nobody" to avoid this risk.

        // Does switcher exist in screensaver bundle?
        sprintf(fullpath, "/Library/Screen Savers/%s.saver/Contents/Resources/gfx_switcher", saverName[i]);
        err = FSPathMakeRef((StringPtr)fullpath, &ref, &isDirectory);   // Does it exist?
        if ((err == noErr) && (! isDirectory)) {
#ifdef _DEBUG
            sprintf(buf1, "%s:%s", boinc_master_user_name, boinc_master_group_name);
            // chown boinc_master:boinc_master "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;

            // chmod u=rwx,g=rwx,o=rx "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            // 0775 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH
            // Set 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, NULL);
            if (err)
                return err;
#else
            sprintf(buf1, "root:%s", boinc_master_group_name);
            // chown root:boinc_master "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            err = DoPrivilegedExec(chownPath, buf1, fullpath, NULL, NULL, NULL, NULL);
            if (err)
                return err;

            // chmod u=rsx,g=rx,o=rx "/Library/Screen Savers/BOINCSaver.saver/Contents/Resources/gfx_switcher"
            // 04555 = S_ISUID | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
            // Set 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, NULL);
            if (err)
                return err;
#endif
        }
    }
    
    return noErr;
}