Пример #1
0
static bool DoRemoveUser (const char *puser, enum cfopaction action)
{
    char cmd[CF_BUFSIZE];

    strcpy (cmd, USERDEL);

    StringAppend(cmd, " ", sizeof(cmd));
    StringAppend(cmd, puser, sizeof(cmd));

    if (action == cfa_warn || DONTDO)
    {
        Log(LOG_LEVEL_WARNING, "Need to remove user '%s'.", puser);
        return false;
    }

    return ExecuteUserCommand(puser, cmd, sizeof(cmd), "removing", "Removing");
}
Пример #2
0
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;
}
Пример #3
0
static bool DoCreateUser(const char *puser, User u, enum cfopaction action,
                         EvalContext *ctx, const Attributes *a, const Promise *pp)
{
    char cmd[CF_BUFSIZE];
    if (puser == NULL || !strcmp (puser, ""))
    {
        return false;
    }
    strcpy (cmd, USERADD);

    if (u.uid != NULL && strcmp (u.uid, ""))
    {
        StringAppend(cmd, " -u \"", sizeof(cmd));
        StringAppend(cmd, u.uid, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

    if (u.description != NULL)
    {
        StringAppend(cmd, " -c \"", sizeof(cmd));
        StringAppend(cmd, u.description, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

    if (u.group_primary != NULL && strcmp (u.group_primary, ""))
    {
        // TODO: Should check that group exists
        StringAppend(cmd, " -g \"", sizeof(cmd));
        StringAppend(cmd, u.group_primary, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }
    if (u.groups_secondary != NULL)
    {
        // TODO: Should check that groups exist
        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 (u.home_dir != NULL && strcmp (u.home_dir, ""))
    {
        StringAppend(cmd, " -d \"", sizeof(cmd));
        StringAppend(cmd, u.home_dir, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }
    if (u.shell != NULL && strcmp (u.shell, ""))
    {
        StringAppend(cmd, " -s \"", sizeof(cmd));
        StringAppend(cmd, u.shell, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }
    if (SupportsOption(USERADD, "-M"))
    {
        // Prevents creation of home_dir.
        // We want home_bundle to do that.
        StringAppend(cmd, " -M", sizeof(cmd));
    }
    StringAppend(cmd, " ", sizeof(cmd));
    StringAppend(cmd, puser, sizeof(cmd));

    if (action == cfa_warn || DONTDO)
    {
        Log(LOG_LEVEL_NOTICE, "Need to create user '%s'.", puser);
        return false;
    }
    else
    {
        if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "creating", "Creating"))
        {
            return false;
        }

        // Initially, "useradd" may set the password to '!', which confuses our detection for
        // locked accounts. So reset it to 'x' hash instead, which will never match anything.
        if (!ChangePassword(puser, "x", PASSWORD_FORMAT_HASH))
        {
            return false;
        }

        if (u.policy == USER_STATE_LOCKED)
        {
            if (!SetAccountLocked(puser, "", true))
            {
                return false;
            }
        }

        if (a->havebundle)
        {
            const Constraint *method_attrib = PromiseGetConstraint(pp, "home_bundle");
            VerifyMethod(ctx, method_attrib->rval, *a, pp);
        }

        if (u.policy != USER_STATE_LOCKED && u.password != NULL && strcmp (u.password, ""))
        {
            if (!ChangePassword(puser, u.password, u.password_format))
            {
                return false;
            }
        }
    }

    return true;
}
Пример #4
0
static bool DoCreateUser(const char *puser, const User *u, enum cfopaction action,
                         EvalContext *ctx, const Attributes *a, const Promise *pp)
{
    assert(u != NULL);
    char cmd[CF_BUFSIZE];
    char sec_group_args[CF_BUFSIZE];
    if (puser == NULL || !strcmp (puser, ""))
    {
        return false;
    }
    strcpy (cmd, USERADD);

    if (u->uid != NULL && strcmp (u->uid, ""))
    {
        StringAppend(cmd, " -u \"", sizeof(cmd));
        StringAppend(cmd, u->uid, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

    if (u->description != NULL)
    {
        StringAppend(cmd, " -c \"", sizeof(cmd));
        StringAppend(cmd, u->description, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

    if (u->group_primary != NULL && strcmp (u->group_primary, ""))
    {
        // TODO: Should check that group exists
        StringAppend(cmd, " -g \"", sizeof(cmd));
        StringAppend(cmd, u->group_primary, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

    if (u->groups_secondary_given)
    {
        // TODO: Should check that groups exist
        strlcpy(sec_group_args, " -G \"", sizeof(sec_group_args));
        char sep[2] = { '\0', '\0' };
        for (Rlist *i = u->groups_secondary; i; i = i->next)
        {
            StringAppend(sec_group_args, sep, sizeof(sec_group_args));
            StringAppend(sec_group_args, RvalScalarValue(i->val), sizeof(sec_group_args));
            sep[0] = ',';
        }
        StringAppend(sec_group_args, "\"", sizeof(sec_group_args));
        StringAppend(cmd, sec_group_args, sizeof(cmd));
    }

    if (u->home_dir != NULL && strcmp (u->home_dir, ""))
    {
        StringAppend(cmd, " -d \"", sizeof(cmd));
        StringAppend(cmd, u->home_dir, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }
    if (u->shell != NULL && strcmp (u->shell, ""))
    {
        StringAppend(cmd, " -s \"", sizeof(cmd));
        StringAppend(cmd, u->shell, sizeof(cmd));
        StringAppend(cmd, "\"", sizeof(cmd));
    }

#ifndef __hpux
    // HP-UX has two variants of useradd, the normal one which does
    // not support -M and one variant to modify default values which
    // does take -M and yes or no
    // Since both are output with -h SupportOption incorrectly reports
    // -M as supported
    if (SupportsOption(USERADD, "-M"))
    {
        // Prevents creation of home_dir.
        // We want home_bundle to do that.
        StringAppend(cmd, " -M", sizeof(cmd));
    }
#endif
    StringAppend(cmd, " ", sizeof(cmd));
    StringAppend(cmd, puser, sizeof(cmd));

    if (action == cfa_warn || DONTDO)
    {
        Log(LOG_LEVEL_WARNING, "Need to create user '%s'.", puser);
        return false;
    }
    else
    {
        if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "creating", "Creating"))
        {
            return false;
        }

        if (u->groups_secondary_given)
        {
            // Work around issue on AIX. Always set secondary groups a second time, because AIX
            // likes to assign the primary group as the secondary group as well, even if we didn't
            // ask for it.
            strlcpy(cmd, USERMOD, sizeof(cmd));
            StringAppend(cmd, sec_group_args, sizeof(cmd));
            StringAppend(cmd, " ", sizeof(cmd));
            StringAppend(cmd, puser, sizeof(cmd));
            if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying"))
            {
                return false;
            }
        }

        // Initially, "useradd" may set the password to '!', which confuses our detection for
        // locked accounts. So reset it to 'x' hash instead, which will never match anything.
        if (!ChangePassword(puser, "x", PASSWORD_FORMAT_HASH))
        {
            return false;
        }

        if (u->policy == USER_STATE_LOCKED)
        {
            if (!SetAccountLocked(puser, "x", true))
            {
                return false;
            }
        }

        if (a->havebundle)
        {
            const Constraint *method_attrib = PromiseGetConstraint(pp, "home_bundle");
            if (method_attrib == NULL)
            {
                Log(LOG_LEVEL_ERR, "Cannot create user (home_bundle not found)");
                return false;
            }
            VerifyMethod(ctx, method_attrib->rval, a, pp);
        }

        if (u->policy != USER_STATE_LOCKED && u->password != NULL && strcmp (u->password, ""))
        {
            if (!ChangePassword(puser, u->password, u->password_format))
            {
                return false;
            }
        }
    }

    return true;
}
Пример #5
0
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;
}