static bool DoModifyUser (const char *puser, User u, const struct passwd *passwd_info, uint32_t changemap, enum cfopaction action) { char cmd[CF_BUFSIZE]; strcpy (cmd, USERMOD); if (CFUSR_CHECKBIT (changemap, i_uid) != 0) { StringAppend(cmd, " -u \"", sizeof(cmd)); StringAppend(cmd, u.uid, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_comment) != 0) { StringAppend(cmd, " -c \"", sizeof(cmd)); StringAppend(cmd, u.description, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_group) != 0) { StringAppend(cmd, " -g \"", sizeof(cmd)); StringAppend(cmd, u.group_primary, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { StringAppend(cmd, " -G \"", sizeof(cmd)); char sep[2] = { '\0', '\0' }; for (Rlist *i = u.groups_secondary; i; i = i->next) { if (strcmp(RvalScalarValue(i->val), CF_NULL_VALUE) != 0) { StringAppend(cmd, sep, sizeof(cmd)); StringAppend(cmd, RvalScalarValue(i->val), sizeof(cmd)); sep[0] = ','; } } StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_home) != 0) { StringAppend(cmd, " -d \"", sizeof(cmd)); StringAppend(cmd, u.home_dir, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_shell) != 0) { StringAppend(cmd, " -s \"", sizeof(cmd)); StringAppend(cmd, u.shell, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (CFUSR_CHECKBIT (changemap, i_password) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to change password for user '%s'.", puser); return false; } else { if (!ChangePassword(puser, u.password, u.password_format)) { return false; } } } if (CFUSR_CHECKBIT (changemap, i_locked) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to %s account for user '%s'.", (u.policy == USER_STATE_LOCKED) ? "lock" : "unlock", puser); return false; } else { const char *hash; if (!GetPasswordHash(puser, passwd_info, &hash)) { return false; } if (!SetAccountLocked(puser, hash, (u.policy == USER_STATE_LOCKED))) { return false; } } } // If password and locking were the only things changed, don't run the command. CFUSR_CLEARBIT(changemap, i_password); CFUSR_CLEARBIT(changemap, i_locked); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to update user attributes (command '%s').", cmd); return false; } else if (changemap != 0) { if (strlen(cmd) >= sizeof(cmd) - 1) { // Instead of checking every string call above, assume that a maxed out // string length overflowed the string. Log(LOG_LEVEL_ERR, "Command line too long while modifying user '%s'", puser); return false; } Log(LOG_LEVEL_VERBOSE, "Modifying user '%s'. (command: '%s')", puser, cmd); int status; status = system(cmd); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { Log(LOG_LEVEL_ERR, "Command returned error while modifying user '%s'. (Command line: '%s')", puser, cmd); return false; } } return true; }
static bool DoModifyUser (const char *puser, const User *u, const struct passwd *passwd_info, uint32_t changemap, enum cfopaction action) { assert(u != NULL); char cmd[CF_BUFSIZE]; strcpy (cmd, USERMOD); if (CFUSR_CHECKBIT (changemap, i_uid) != 0) { StringAppend(cmd, " -u \"", sizeof(cmd)); StringAppend(cmd, u->uid, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_comment) != 0) { StringAppend(cmd, " -c \"", sizeof(cmd)); StringAppend(cmd, u->description, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_group) != 0) { StringAppend(cmd, " -g \"", sizeof(cmd)); StringAppend(cmd, u->group_primary, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } #ifndef __hpux // HP-UX does not support -G with empty argument if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { /* Work around bug on SUSE. If secondary groups contain a group that is the same group as the primary group, the secondary group is not set. This happens even if the primary group is changed in the same call. Therefore, set an empty group list first, and then set it to the real list later. */ StringAppend(cmd, " -G \"\"", sizeof(cmd)); } #endif if (CFUSR_CHECKBIT (changemap, i_home) != 0) { StringAppend(cmd, " -d \"", sizeof(cmd)); StringAppend(cmd, u->home_dir, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_shell) != 0) { StringAppend(cmd, " -s \"", sizeof(cmd)); StringAppend(cmd, u->shell, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (CFUSR_CHECKBIT (changemap, i_password) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_WARNING, "Need to change password for user '%s'.", puser); return false; } else { if (!ChangePassword(puser, u->password, u->password_format)) { return false; } } } if (CFUSR_CHECKBIT (changemap, i_locked) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_WARNING, "Need to %s account for user '%s'.", (u->policy == USER_STATE_LOCKED) ? "lock" : "unlock", puser); return false; } else { const char *hash; if (CFUSR_CHECKBIT(changemap, i_password) == 0) { if (!GetPasswordHash(puser, passwd_info, &hash)) { return false; } } else { // Don't unlock the hash if we already set the password. Our // cached value in passwd_info->pw_passwd will be wrong, and the // account will already have been unlocked anyway. hash = NULL; } if (!SetAccountLocked(puser, hash, (u->policy == USER_STATE_LOCKED))) { return false; } } } // If password and locking were the only things changed, don't run the command. CFUSR_CLEARBIT(changemap, i_password); CFUSR_CLEARBIT(changemap, i_locked); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_WARNING, "Need to update user attributes (command '%s').", cmd); return false; } else if (changemap != 0) { #ifdef __hpux // This is to overcome the Suse hack above which does not work on HP-UX and thus we // risk getting an empty command if change of secondary groups is the only change // Only run for other changes than i_groups, otherwise the command will be empty uint32_t changemap_without_groups = changemap; CFUSR_CLEARBIT(changemap_without_groups, i_groups); if(changemap_without_groups != 0) #endif { if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { // Set real group list (see -G comment earlier). strcpy(cmd, USERMOD); StringAppend(cmd, " -G \"", sizeof(cmd)); char sep[2] = { '\0', '\0' }; for (Rlist *i = u->groups_secondary; i; i = i->next) { StringAppend(cmd, sep, sizeof(cmd)); StringAppend(cmd, RvalScalarValue(i->val), sizeof(cmd)); sep[0] = ','; } StringAppend(cmd, "\" ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } } } return true; }
static bool DoModifyUser (const char *puser, User u, const struct passwd *passwd_info, uint32_t changemap, enum cfopaction action) { char cmd[CF_BUFSIZE]; strcpy (cmd, USERMOD); if (CFUSR_CHECKBIT (changemap, i_uid) != 0) { StringAppend(cmd, " -u \"", sizeof(cmd)); StringAppend(cmd, u.uid, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_comment) != 0) { StringAppend(cmd, " -c \"", sizeof(cmd)); StringAppend(cmd, u.description, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_group) != 0) { StringAppend(cmd, " -g \"", sizeof(cmd)); StringAppend(cmd, u.group_primary, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { /* Work around bug on SUSE. If secondary groups contain a group that is the same group as the primary group, the secondary group is not set. This happens even if the primary group is changed in the same call. Therefore, set an empty group list first, and then set it to the real list later. */ StringAppend(cmd, " -G \"\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_home) != 0) { StringAppend(cmd, " -d \"", sizeof(cmd)); StringAppend(cmd, u.home_dir, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_shell) != 0) { StringAppend(cmd, " -s \"", sizeof(cmd)); StringAppend(cmd, u.shell, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (CFUSR_CHECKBIT (changemap, i_password) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to change password for user '%s'.", puser); return false; } else { if (!ChangePassword(puser, u.password, u.password_format)) { return false; } } } if (CFUSR_CHECKBIT (changemap, i_locked) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to %s account for user '%s'.", (u.policy == USER_STATE_LOCKED) ? "lock" : "unlock", puser); return false; } else { const char *hash; if (!GetPasswordHash(puser, passwd_info, &hash)) { return false; } if (!SetAccountLocked(puser, hash, (u.policy == USER_STATE_LOCKED))) { return false; } } } // If password and locking were the only things changed, don't run the command. CFUSR_CLEARBIT(changemap, i_password); CFUSR_CLEARBIT(changemap, i_locked); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to update user attributes (command '%s').", cmd); return false; } else if (changemap != 0) { if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { // Set real group list (see -G comment earlier). strcpy(cmd, USERMOD); StringAppend(cmd, " -G \"", sizeof(cmd)); char sep[2] = { '\0', '\0' }; for (Rlist *i = u.groups_secondary; i; i = i->next) { if (strcmp(RvalScalarValue(i->val), CF_NULL_VALUE) != 0) { StringAppend(cmd, sep, sizeof(cmd)); StringAppend(cmd, RvalScalarValue(i->val), sizeof(cmd)); sep[0] = ','; } } StringAppend(cmd, "\" ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } } } return true; }