Exemple #1
0
int AddAdminUserToGroups(char *user_name, bool add_to_boinc_project) {        
#ifndef _DEBUG
    char            buf1[80];
    OSStatus        err = noErr;

    sprintf(buf1, "/groups/%s", boinc_master_group_name);

    // "dscl . -merge /groups/boinc_master users user_name"
    err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", user_name, NULL);
    if (err)
        return err;

    if (add_to_boinc_project)  {
        sprintf(buf1, "/groups/%s", boinc_project_group_name);

        // "dscl . -merge /groups/boinc_project users user_name"
        err = DoPrivilegedExec(dsclPath, ".", "-merge", buf1, "users", user_name, NULL);
        if (err)
            return err;
    }
    
    err = ResynchSystem();
    if (err != noErr)
        return err;

#endif          // ! _DEBUG    
    return noErr;
}
Exemple #2
0
int CreateBOINCUsersAndGroups() {
    OSStatus        err = noErr;

    err = CreateUserAndGroup(REAL_BOINC_MASTER_NAME, REAL_BOINC_MASTER_NAME);
    if (err != noErr)
        return err;

    err = CreateUserAndGroup(REAL_BOINC_PROJECT_NAME, REAL_BOINC_PROJECT_NAME);
    if (err != noErr)
        return err;
        
    err = ResynchSystem();
    if (err != noErr)
        return err;
    
    return noErr;
}
// Find all visible users.
// If user is a member of group admin, add user to groups boinc_master and boinc_project.
// Optionally add non-admin users to group boinc_master but not to group boinc_project.
// Set login item for all members of group boinc_master to launch BOINC Manager.
// If our install package included a skin, set those user's preferences to use that skin.
// Optionally set BOINC as screensaver for all users running BOINC.
OSErr UpdateAllVisibleUsers(long brandID)
{
    DIR                 *dirp;
    dirent              *dp;
    passwd              *pw;
    uid_t               saved_uid;
    Boolean             deleteLoginItem;
    char                skinName[256];
    char                s[256];
    group               grpAdmin, *grpAdminPtr;
    char                adminBuf[32768];
    group               grpBOINC_master, *grpBOINC_masterPtr;
    char                bmBuf[32768];
    Boolean             saverAlreadySetForAll = true;
    Boolean             setSaverForAllUsers = false;
    Boolean             allNonAdminUsersAreSet = true;
    Boolean             allowNonAdminUsersToRunBOINC = false;
    Boolean             found = false;
    FILE                *f;
    OSStatus            err;
    Boolean             isGroupMember;
#ifdef SANDBOX
    char                *p;
    short               i;

    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  // SANDBOX

    FindSkinName(skinName, sizeof(skinName));

    // Step through all users
    puts("Beginning first pass through all users\n");

    dirp = opendir("/Users");
    if (dirp == NULL) {      // Should never happen
        puts("[1] opendir(\"/Users\") failed\n");
        return -1;
    }
    
    while (true) {
        dp = readdir(dirp);
        if (dp == NULL)
            break;                  // End of list

        printf("[1] Checking user %s\n", dp->d_name);
            
        if (dp->d_name[0] == '.')
            continue;               // Ignore names beginning with '.'
    
        // getpwnam works with either the full / login name (pw->pw_gecos) 
        // or the short / Posix name (pw->pw_name)
        pw = getpwnam(dp->d_name);
        if (pw == NULL) {           // "Deleted Users", "Shared", etc.
            printf("[1] %s not in getpwnam data base\n", dp->d_name);
            continue;
        }

        printf("[1] User %s: Posix name=%s, Full name=%s\n", dp->d_name, pw->pw_name, pw->pw_gecos);
        
#ifdef SANDBOX
        isGroupMember = false;
        i = 0;
        while ((p = grpAdmin.gr_mem[i]) != NULL) {  // Step through all users in group admin
            if (strcmp(p, pw->pw_name) == 0) {
                // User is a member of group admin, so add user to groups boinc_master and boinc_project
                printf("[1] User %s is a member of group admin\n", pw->pw_name);
                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, pw->pw_name) == 0) {
                    // User is a member of group boinc_master
                    printf("[1] User %s is a member of group boinc_master\n", pw->pw_name);
                    isGroupMember = true;
                    break;
                }
                ++i;
            }
        }
        if (!isGroupMember) {
            allNonAdminUsersAreSet = false;
        }
#else   // SANDBOX
        isGroupMember = true;
#endif  // SANDBOX

        if (isGroupMember) {
            if ((strcmp(loginName, dp->d_name) == 0) || (strcmp(loginName, pw->pw_name) == 0)) {
                currentUserCanRunBOINC = true;
            }
            
            saved_uid = geteuid();
            seteuid(pw->pw_uid);                        // Temporarily set effective uid to this user
            
            if (OSVersion < 0x1060) {
                f = popen("defaults -currentHost read com.apple.screensaver moduleName", "r");
            } else {
                sprintf(s, "sudo -u %s defaults -currentHost read com.apple.screensaver moduleDict -dict", 
                        pw->pw_name); 
                f = popen(s, "r");
            }
            
            if (f) {
                found = false;
                while (PersistentFGets(s, sizeof(s), f)) {
                    if (strstr(s, saverName[brandID])) {
                        found = true;
                        break;
                    }
                }
                pclose(f);
                if (!found) {
                    saverAlreadySetForAll = false;
                }
            }
            
            seteuid(saved_uid);                         // Set effective uid back to privileged user
        }       // End if (isGroupMember)
    }           // End while (true)
    
    closedir(dirp);

    ResynchSystem();

    if (! allNonAdminUsersAreSet) {
        if (ShowMessage(true, 
            "Users who are permitted to administer this computer will automatically be allowed to "
            "run and control %s.\n\n"
            "Do you also want non-administrative users to be able to run and control %s on this Mac?",
            brandName[brandID], brandName[brandID])
        ) {
            allowNonAdminUsersToRunBOINC = true;
            currentUserCanRunBOINC = true;
            saverAlreadySetForAll = false;
            printf("[2] User answered Yes to allowing non-admin users to run %s\n", brandName[brandID]);
        } else {
            printf("[2] User answered No to allowing non-admin users to run %s\n", brandName[brandID]);
        }
    } else {
        puts("[2] All non-admin users are already members of group boinc_master\n");
    }
    
    if (! saverAlreadySetForAll) {
        setSaverForAllUsers = ShowMessage(true, 
                    "Do you want to set %s as the screensaver for all %s users on this Mac?", 
                    brandName[brandID], brandName[brandID]);    
    }

    // Step through all users a second time, setting non-admin users and / or our screensaver
    puts("Beginning second pass through all users\n");

    dirp = opendir("/Users");
    if (dirp == NULL) {      // Should never happen
        puts("[2] opendir(\"/Users\") failed\n");
        return -1;
    }
    
    while (true) {
        dp = readdir(dirp);
        if (dp == NULL)
            break;                  // End of list

        printf("[2] Checking user %s\n", dp->d_name);
            
        if (dp->d_name[0] == '.')
            continue;               // Ignore names beginning with '.'
    
        pw = getpwnam(dp->d_name);
        if (pw == NULL) {           // "Deleted Users", "Shared", etc.
            printf("[2] %s not in getpwnam data base\n", dp->d_name);
            continue;
        }

        printf("[2] User %s: Posix name=%s, Full name=%s\n", dp->d_name, pw->pw_name, pw->pw_gecos);
        
#ifdef SANDBOX
        isGroupMember = false;

        i = 0;
        while ((p = grpAdmin.gr_mem[i]) != NULL) {  // Step through all users in group admin
            if (strcmp(p, pw->pw_name) == 0) {
                // User is a member of group admin
                printf("[2] User %s is a member of group admin\n", pw->pw_name);
                isGroupMember = true;
                break;
            }
            ++i;
        }

        // If allNonAdminUsersAreSet, some older versions added non-admin users only to group 
        // boinc_master; ensure all permitted BOINC users are also members of group boinc_project
        if (isGroupMember || allowNonAdminUsersToRunBOINC || allNonAdminUsersAreSet) {
            // Add to group boinc_master but not group boinc_project
            err = AddAdminUserToGroups(pw->pw_name);
            printf("[2] Calling AddAdminUserToGroups(%s)\n", pw->pw_name);
            isGroupMember = true;
        }
        
#else   // SANDBOX
        isGroupMember = true;
#endif  // SANDBOX

        saved_uid = geteuid();
        seteuid(pw->pw_uid);                        // Temporarily set effective uid to this user
        deleteLoginItem = CheckDeleteFile(dp->d_name);
        if (CheckDeleteFile(pw->pw_name)) {
            deleteLoginItem = true;
        }
        if (!isGroupMember) {
            deleteLoginItem = true;
        }

        SetLoginItem(brandID, deleteLoginItem);     // Set login item for this user

        if (isGroupMember) {
            SetSkinInUserPrefs(dp->d_name, skinName);
        
            if (setSaverForAllUsers) {
                if (OSVersion < 0x1060) {
                    sprintf(s, "defaults -currentHost write com.apple.screensaver moduleName %s", saverNameEscaped[brandID]);
                    system (s);
                    sprintf(s, "defaults -currentHost write com.apple.screensaver modulePath /Library/Screen\\ Savers/%s.saver", 
                                saverNameEscaped[brandID]);
                } else {
                    sprintf(s, "sudo -u %s defaults -currentHost write com.apple.screensaver moduleDict -dict moduleName %s path /Library/Screen\\ Savers/%s.saver", 
                            pw->pw_name, saverNameEscaped[brandID], saverNameEscaped[brandID]);
                }
                system (s);
            }
        }
        
        seteuid(saved_uid);                         // Set effective uid back to privileged user
    }
    
    closedir(dirp);

    ResynchSystem();

    return noErr;
}
Exemple #4
0
static OSStatus CreateUserAndGroup(char * user_name, char * group_name) {
    OSStatus        err = noErr;
    passwd          *pw = NULL;
    group           *grp = NULL;
    uid_t           userid = 0;
    gid_t           groupid = 0;
    gid_t           usergid = 0;
    Boolean         userExists = false;
    Boolean         groupExists = false;
    short           i;
    static short    start_id = MIN_ID;
    char            buf1[80];
    char            buf2[80];
    char            buf3[80];
    char            buf4[80];
   
    // OS 10.4 has problems with Accounts pane if we create uid or gid > 501
    pw = getpwnam(user_name);
    if (pw) {
        userid = pw->pw_uid;
        userExists = true;
    }

    grp = getgrnam(group_name);
    if (grp) {
        groupid = grp->gr_gid;
        groupExists = true;
    }
    
    sprintf(buf1, "/groups/%s", group_name);
    sprintf(buf2, "/users/%s", user_name);

    if ( userExists && groupExists )
        goto setRealName;       // User and group already exist

    // 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;
        if (usergid) {
            grp = getgrgid(usergid);
            if (grp == NULL)    // Set the group ID = users existing group if this group ID is available
                groupid = usergid;
        }
        if (groupid == 0) {
            grp = getgrgid(userid);
            if (grp == NULL)    // Set the group ID = user ID if this group ID is available
                groupid = userid;
        }
    } else {
        if (groupExists) {      // Group exists but user does not
           pw = getpwuid(groupid);
            if (pw == NULL)    // Set the user ID = group ID if this user ID is available
                userid = groupid;
        }
    }
    
    // We need to find an available user ID, group ID, or both.  Find a value that is currently 
    // neither a user ID or a group ID.
    // If we need both a new user ID and a new group ID, finds a value that can be used for both.
    if ( (userid == 0) || (groupid == 0) ) {
        for(i=start_id; ; i++) {
           if ((uid_t)i != userid) {
                pw = getpwuid((uid_t)i);
                if (pw)
                    continue;               // Already exists as a user ID of a different user
            }
            
            if ((gid_t)i != groupid) {
                grp = getgrgid((gid_t)i);
                if (grp)
                    continue;               // Already exists as a group ID of a different group
            }
            
            if (! userExists)
                userid = (uid_t)i;
            if (! groupExists)
                groupid = (gid_t)i;

            start_id = i + 1;               // Start with next higher value next time
                
            break;                          // Success!
        }
    }
    
    sprintf(buf3, "%d", groupid);
    sprintf(buf4, "%d", userid);

    if (! groupExists) {             // If we need to create group
        // Something like "dscl . -create /groups/boinc_master"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf1, NULL, NULL, NULL);
        if (err)
            return err;
 
        // Something like "dscl . -create /groups/boinc_master gid 33"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf1, "gid", buf3, NULL);
        if (err)
            return err;
    }           // if (! groupExists)
        
    if (! userExists) {             // If we need to create user
        // Something like "dscl . -create /users/boinc_master"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, NULL, NULL, NULL);
        if (err)
            return err;

        // Something like "dscl . -create /users/boinc_master uid 33"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, "uid", buf4, NULL);
        if (err)
            return err;

        // Prevent a security hole by not allowing a login from this user
        // Something like "dscl . -create /users/boinc_master shell /usr/bin/false"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, "shell", "/usr/bin/false", NULL);
        if (err)
            return err;

        // Something like "dscl . -create /users/boinc_master home /var/empty"
        err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, "home", "/var/empty", NULL);
        if (err)
            return err;
    }           // if (! userExists)

    // 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"
    err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, "gid", buf3, NULL);
    if (err)
        return err;

setRealName:
    // Always set the RealName field to an empty string
    // Note: create RealName with empty string fails under OS 10.7, but 
    // creating it with non-empty string and changing to empty string does work.
    //
    // Something like "dscl . -create /users/boinc_master RealName tempName"
    err = DoPrivilegedExec(dsclPath, ".", "-create", buf2, "RealName", user_name, NULL);
    if (err)
        return err;

    // Something like 'dscl . -change /users/boinc_master RealName ""'
    err = DoPrivilegedExec(dsclPath, ".", "-change", buf2, "RealName", user_name, "");
    if (err)
        return err;

    err = ResynchSystem();
    if (err != noErr)
        return err;

    SleepTicks(120);

    return noErr;
}
// NOTE: getgrnam and getgrgid use one static memory area to return their results, 
//  so each call to getgrnam or getgrgid overwrites the data from any previous calls.
void CheckUserAndGroupConflicts()
{
#ifdef SANDBOX
    passwd          *pw = NULL;
    group           *grp = NULL;
    gid_t           boinc_master_gid = 0, boinc_project_gid = 0;
    uid_t           boinc_master_uid = 0, boinc_project_uid = 0;
    
    FILE            *f;
    char            cmd[256], buf[256];
    int             entryCount;

    entryCount = 0;
    grp = getgrnam(boinc_master_group_name);
    if (grp) {
        boinc_master_gid = grp->gr_gid;
        sprintf(cmd, "dscl . -search /Groups PrimaryGroupID %d", boinc_master_gid);
        f = popen(cmd, "r");
        if (f) {
            while (PersistentFGets(buf, sizeof(buf), f)) {
                if (strstr(buf, "PrimaryGroupID")) {
                    ++entryCount;
                }
            }
            pclose(f);
        }    
    }
        
    if (entryCount > 1) {
        system ("dscl . -delete /groups/boinc_master");
        // User boinc_master must have group boinc_master as its primary group.
        // Since this group no longer exists, delete the user as well.
        system ("dscl . -delete /users/boinc_master");
        ResynchSystem();
    }

    entryCount = 0;
    grp = getgrnam(boinc_project_group_name);
    if (grp) {
        boinc_project_gid = grp->gr_gid;
        sprintf(cmd, "dscl . -search /Groups PrimaryGroupID %d", boinc_project_gid);
        f = popen(cmd, "r");
        if (f) {
            while (PersistentFGets(buf, sizeof(buf), f)) {
                if (strstr(buf, "PrimaryGroupID")) {
                    ++entryCount;
                }
            }
            pclose(f);
        }    
    }

    if (entryCount > 1) {
       system ("dscl . -delete /groups/boinc_project");
        // User boinc_project must have group boinc_project as its primary group.
        // Since this group no longer exists, delete the user as well.
        system ("dscl . -delete /users/boinc_project");
        ResynchSystem();
    }

    entryCount = 0;
    pw = getpwnam(boinc_master_user_name);
    if (pw) {
        boinc_master_uid = pw->pw_uid;
        sprintf(cmd, "dscl . -search /Users UniqueID %d", boinc_master_uid);
        f = popen(cmd, "r");
        if (f) {
            while (PersistentFGets(buf, sizeof(buf), f)) {
                if (strstr(buf, "UniqueID")) {
                    ++entryCount;
                }
            }
            pclose(f);
        }    
    }

    if (entryCount > 1) {
        system ("dscl . -delete /users/boinc_master");
        ResynchSystem();
    }
        
    entryCount = 0;
    pw = getpwnam(boinc_project_user_name);
    if (pw) {
        boinc_project_uid = pw->pw_uid;
        sprintf(cmd, "dscl . -search /Users UniqueID %d", boinc_project_uid);
        f = popen(cmd, "r");
        if (f) {
            while (PersistentFGets(buf, sizeof(buf), f)) {
                if (strstr(buf, "UniqueID")) {
                    ++entryCount;
                }
            }
            pclose(f);
        }    
    }

    if (entryCount > 1) {
        system ("dscl . -delete /users/boinc_project");
        ResynchSystem();
    }
#endif  // SANDBOX
}