Exemple #1
0
int VarClassExcluded(EvalContext *ctx, Promise *pp, char **classes)
{
    Constraint *cp = PromiseGetConstraint(ctx, pp, "ifvarclass");

    if (cp == NULL)
    {
        return false;
    }

    *classes = (char *) ConstraintGetRvalValue(ctx, "ifvarclass", pp, RVAL_TYPE_SCALAR);

    if (*classes == NULL)
    {
        return true;
    }

    if (strchr(*classes, '$') || strchr(*classes, '@'))
    {
        CfDebug("Class expression did not evaluate");
        return true;
    }

    if (*classes && IsDefinedClass(ctx, *classes, PromiseGetNamespace(pp)))
    {
        return false;
    }
    else
    {
        return true;
    }
}
PromiseResult VerifyMethodsPromise(EvalContext *ctx, const Promise *pp)
{
    Attributes a = GetMethodAttributes(ctx, pp);

    const Constraint *cp;
    Rval method_name;
    bool destroy_name;

    if ((cp = PromiseGetConstraint(pp, "usebundle")))
    {
        method_name = cp->rval;
        destroy_name = false;
    }
    else
    {
        method_name = RvalNew(pp->promiser, RVAL_TYPE_SCALAR);
        destroy_name = true;
    }

    PromiseResult result = VerifyMethod(ctx, method_name, a, pp);

    if (destroy_name)
    {
        RvalDestroy(method_name);
    }

    return result;
}
Exemple #3
0
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp)
{
    Rval call;
    {
        const Constraint *cp = PromiseGetConstraint(pp, "service_bundle");
        if (cp)
        {
            call = RvalCopy(cp->rval);
        }
        else
        {
            call = (Rval) { DefaultServiceBundleCall(pp, a.service.service_policy), RVAL_TYPE_FNCALL };
        }
    }
    a.havebundle = true;

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", a.service.service_policy, CF_DATA_TYPE_STRING, "source=promise");

    PromiseResult result = PROMISE_RESULT_NOOP;
    result = PromiseResultUpdate(result, VerifyMethod(ctx, call, a, pp));  // Send list of classes to set privately?

    RvalDestroy(call);

    return result;
}
PromiseResult VerifyMethodsPromise(EvalContext *ctx, const Promise *pp)
{
    Attributes a = GetMethodAttributes(ctx, pp);

    const Constraint *cp = PromiseGetConstraint(pp, "usebundle");
    if (!cp)
    {
        Log(LOG_LEVEL_VERBOSE, "Promise had no attribute 'usebundle', cannot call method");
        return PROMISE_RESULT_FAIL;
    }

    PromiseResult result = VerifyMethod(ctx, cp->rval, a, pp);

    return result;
}
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp)
{
    Rval call;
    {
        const Constraint *cp = PromiseGetConstraint(pp, "service_bundle");
        if (cp)
        {
            call = RvalCopy(cp->rval);
        }
        else
        {
            call = (Rval) { DefaultServiceBundleCall(pp, a.service.service_policy), RVAL_TYPE_FNCALL };
        }
    }
    a.havebundle = true;

    switch (a.service.service_policy)
    {
    case SERVICE_POLICY_START:
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "start", CF_DATA_TYPE_STRING, "source=promise");
        break;

    case SERVICE_POLICY_RESTART:
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "restart", CF_DATA_TYPE_STRING, "source=promise");
        break;

    case SERVICE_POLICY_RELOAD:
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "reload", CF_DATA_TYPE_STRING, "source=promise");
        break;
        
    case SERVICE_POLICY_STOP:
    case SERVICE_POLICY_DISABLE:
    default:
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "stop", CF_DATA_TYPE_STRING, "source=promise");
        break;
    }

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (!DONTDO)
    {
        result = PromiseResultUpdate(result, VerifyMethod(ctx, call, a, pp));  // Send list of classes to set privately?
    }

    RvalDestroy(call);

    return result;
}
Exemple #6
0
PromiseResult VerifyMethodsPromise(EvalContext *ctx, const Promise *pp)
{
    Attributes a = GetMethodAttributes(ctx, pp);

    const Constraint *cp;
    Rval method_name;

    if ((cp = PromiseGetConstraint(pp, "usebundle")))
    {
        method_name = cp->rval;
    }
    else
    {
        method_name = DefaultBundleConstraint(pp, "method");
    }

    PromiseResult result = VerifyMethod(ctx, method_name, a, pp);

    return result;
}
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;
}
Exemple #8
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));
    }
    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 (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 creating user '%s'", puser);
            return false;
        }

        Log(LOG_LEVEL_VERBOSE, "Creating 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 creating user '%s'. (Command line: '%s')", puser, cmd);
            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;
}
Exemple #9
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;
}
static void test_policy_json_to_from(void)
{
    EvalContext *ctx = EvalContextNew();
    Policy *policy = NULL;
    {
        Policy *original = LoadPolicy("benchmark.cf");
        JsonElement *json = PolicyToJson(original);
        PolicyDestroy(original);
        policy = PolicyFromJson(json);
        JsonDestroy(json);
    }
    assert_true(policy);

    assert_int_equal(1, SeqLength(policy->bundles));
    assert_int_equal(2, SeqLength(policy->bodies));

    {
        Bundle *main_bundle = PolicyGetBundle(policy, NULL, "agent", "main");
        assert_true(main_bundle);
        {
            {
                PromiseType *files = BundleGetPromiseType(main_bundle, "files");
                assert_true(files);
                assert_int_equal(1, SeqLength(files->promises));

                for (size_t i = 0; i < SeqLength(files->promises); i++)
                {
                    Promise *promise = SeqAt(files->promises, i);

                    if (strcmp("/tmp/stuff", promise->promiser) == 0)
                    {
                        assert_string_equal("any", promise->classes);

                        assert_int_equal(2, SeqLength(promise->conlist));

                        {
                            Constraint *create = PromiseGetConstraint(ctx, promise, "create");
                            assert_true(create);
                            assert_string_equal("create", create->lval);
                            assert_string_equal("true", RvalScalarValue(create->rval));
                        }

                        {
                            Constraint *create = PromiseGetConstraint(ctx, promise, "perms");
                            assert_true(create);
                            assert_string_equal("perms", create->lval);
                            assert_string_equal("myperms", RvalScalarValue(create->rval));
                        }
                    }
                    else
                    {
                        fprintf(stderr, "Found unknown promise");
                        fail();
                    }
                }
            }

            {
                const char* reportOutput[2] = { "Hello, CFEngine", "Hello, world" };
                const char* reportClass[2] = { "cfengine", "any" };
                PromiseType *reports = BundleGetPromiseType(main_bundle, "reports");
                assert_true(reports);
                assert_int_equal(2, SeqLength(reports->promises));

                for (size_t i = 0; i < SeqLength(reports->promises); i++)
                {
                    Promise *promise = SeqAt(reports->promises, i);

                    if (strcmp(reportOutput[i], promise->promiser) == 0)
                    {
                        assert_string_equal(reportClass[i], promise->classes);

                        assert_int_equal(1, SeqLength(promise->conlist));

                        {
                            Constraint *friend_pattern = SeqAt(promise->conlist, 0);
                            assert_true(friend_pattern);
                            assert_string_equal("friend_pattern", friend_pattern->lval);
                            assert_int_equal(RVAL_TYPE_FNCALL, friend_pattern->rval.type);
                            FnCall *fn = RvalFnCallValue(friend_pattern->rval);
                            assert_string_equal("hash", fn->name);
                            assert_int_equal(2, RlistLen(fn->args));
                        }
                    }
                    else
                    {
                        fprintf(stderr, "Found unknown promise");
                        fail();
                    }
                }
            }
        }
    }

    {
        Body *myperms = PolicyGetBody(policy, NULL, "perms", "myperms");
        assert_true(myperms);

        {
            Seq *mode_cps = BodyGetConstraint(myperms, "mode");
            assert_int_equal(1, SeqLength(mode_cps));

            Constraint *mode = SeqAt(mode_cps, 0);
            assert_string_equal("mode", mode->lval);
            assert_string_equal("555", RvalScalarValue(mode->rval));
        }
    }

    PolicyDestroy(policy);
    EvalContextDestroy(ctx);
}