示例#1
0
文件: set.c 项目: cfengine/core
void StringSetAddSplit(StringSet *set, const char *str, char delimiter)
{
    assert(set != NULL);
    if (str) // TODO: remove this inconsistency, add assert(str)
    {
        const char *prev = str;
        const char *cur = str;

        while (*cur != '\0')
        {
            if (*cur == delimiter)
            {
                size_t len = cur - prev;
                if (len > 0)
                {
                    StringSetAdd(set, xstrndup(prev, len));
                }
                else
                {
                    StringSetAdd(set, xstrdup(""));
                }
                prev = cur + 1;
            }

            cur++;
        }

        if (cur > prev)
        {
            StringSetAdd(set, xstrndup(prev, cur - prev));
        }
    }
}
示例#2
0
static int SelectOwnerMatch(EvalContext *ctx, char *path, struct stat *lstatptr, Rlist *crit)
{
    Rlist *rp;
    char ownerName[CF_BUFSIZE];
    int gotOwner;

    StringSet *leafattrib = StringSetNew();

#ifndef __MINGW32__                   // no uids on Windows
    char buffer[CF_SMALLBUF];
    snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_uid);
    StringSetAdd(leafattrib, xstrdup(buffer));
#endif /* __MINGW32__ */

    gotOwner = GetOwnerName(path, lstatptr, ownerName, sizeof(ownerName));

    if (gotOwner)
    {
        StringSetAdd(leafattrib, xstrdup(ownerName));
    }
    else
    {
        StringSetAdd(leafattrib, xstrdup("none"));
    }

    for (rp = crit; rp != NULL; rp = rp->next)
    {
        if (EvalFileResult((char *) rp->item, leafattrib))
        {
            Log(LOG_LEVEL_DEBUG, "Select owner match");
            StringSetDestroy(leafattrib);
            return true;
        }

        if (gotOwner && (FullTextMatch(ctx, RlistScalarValue(rp), ownerName)))
        {
            Log(LOG_LEVEL_DEBUG, "Select owner match");
            StringSetDestroy(leafattrib);
            return true;
        }

#ifndef __MINGW32__
        if (FullTextMatch(ctx, RlistScalarValue(rp), buffer))
        {
            Log(LOG_LEVEL_DEBUG, "Select owner match");
            StringSetDestroy(leafattrib);
            return true;
        }
#endif /* !__MINGW32__ */
    }

    StringSetDestroy(leafattrib);
    return false;
}
示例#3
0
static void TransformGidsToGroups(StringSet **list)
{
    StringSet *new_list = StringSetNew();
    StringSetIterator i = StringSetIteratorInit(*list);
    const char *data;
    for (data = StringSetIteratorNext(&i); data; data = StringSetIteratorNext(&i))
    {
        if (strlen(data) != strspn(data, "0123456789"))
        {
            // Cannot possibly be a gid.
            StringSetAdd(new_list, xstrdup(data));
            continue;
        }
        // In groups vs gids, groups take precedence. So check if it exists.
        struct group *group_info = GetGrEntry(data, &EqualGroupName);
        if (!group_info)
        {
            if (errno == 0)
            {
                group_info = GetGrEntry(data, &EqualGid);
                if (!group_info)
                {
                    if (errno != 0)
                    {
                        Log(LOG_LEVEL_ERR, "Error while checking group name '%s': %s", data, GetErrorStr());
                        StringSetDestroy(new_list);
                        return;
                    }
                    // Neither group nor gid is found. This will lead to an error later, but we don't
                    // handle that here.
                }
                else
                {
                    // Replace gid with group name.
                    StringSetAdd(new_list, xstrdup(group_info->gr_name));
                }
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Error while checking group name '%s': '%s'", data, GetErrorStr());
                StringSetDestroy(new_list);
                return;
            }
        }
        else
        {
            StringSetAdd(new_list, xstrdup(data));
        }
    }
    StringSet *old_list = *list;
    *list = new_list;
    StringSetDestroy(old_list);
}
示例#4
0
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files, StringSet *failed_files)
{
    Policy *policy = Cf3ParseFile(config, policy_file);
    StringSetAdd(parsed_files, xstrdup(policy_file));

    if (!policy)
    {
        StringSetAdd(failed_files, xstrdup(policy_file));
        return NULL;
    }

    PolicyResolve(ctx, policy, config);

    Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control");
    Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control");

    if (body_common_control)
    {
        Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs");
        Constraint *cp = EffectiveConstraint(ctx, potential_inputs);
        SeqDestroy(potential_inputs);

        if (cp)
        {
            Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files, failed_files);
            if (aux_policy)
            {
                policy = PolicyMerge(policy, aux_policy);
            }
        }
    }

    PolicyResolve(ctx, policy, config);

    if (body_file_control)
    {
        Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs");
        Constraint *cp = EffectiveConstraint(ctx, potential_inputs);
        SeqDestroy(potential_inputs);

        if (cp)
        {
            Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files, failed_files);
            if (aux_policy)
            {
                policy = PolicyMerge(policy, aux_policy);
            }
        }
    }

    return policy;
}
示例#5
0
/**
 * @param #tags is a comma separated string of words.
 *              Both "" or NULL are equivalent.
 */
static void ClassInit(Class *cls,
                      const char *ns, const char *name,
                      bool is_soft, ContextScope scope, const char *tags)
{
    if (ns == NULL || strcmp(ns, "default") == 0)
    {
        cls->ns = NULL;
    }
    else
    {
        cls->ns = xstrdup(ns);
    }

    cls->name = xstrdup(name);
    CanonifyNameInPlace(cls->name);

    cls->is_soft = is_soft;
    cls->scope = scope;

    cls->tags = StringSetFromString(tags, ',');
    if (!is_soft && !StringSetContains(cls->tags, "hardclass"))
    {
        StringSetAdd(cls->tags, xstrdup("hardclass"));
    }
}
示例#6
0
static bool GroupGetUserMembership (const char *user, StringSet *result)
{
    bool ret = true;
    struct group *group_info;

    setgrent();
    while (true)
    {
        errno = 0;
        group_info = getgrent();
        if (!group_info)
        {
            if (errno)
            {
                Log(LOG_LEVEL_ERR, "Error while getting group list. (getgrent: '%s')", GetErrorStr());
                ret = false;
            }
            break;
        }
        for (int i = 0; group_info->gr_mem[i] != NULL; i++)
        {
            if (strcmp(user, group_info->gr_mem[i]) == 0)
            {
                StringSetAdd(result, xstrdup(group_info->gr_name));
                break;
            }
        }
    }
    endgrent();

    return ret;
}
示例#7
0
void EvalContextStackFrameAddNegated(EvalContext *ctx, const char *context)
{
    StackFrame *frame = LastStackFrameBundle(ctx);
    assert(frame);

    StringSetAdd(frame->data.bundle.contexts_negated, xstrdup(context));
}
示例#8
0
static int SelectGroupMatch(EvalContext *ctx, struct stat *lstatptr, Rlist *crit)
{
    char buffer[CF_SMALLBUF];
    struct group *gr;
    Rlist *rp;

    StringSet *leafattrib = StringSetNew();

    snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_gid);
    StringSetAdd(leafattrib, xstrdup(buffer));

    if ((gr = getgrgid(lstatptr->st_gid)) != NULL)
    {
        StringSetAdd(leafattrib, xstrdup(gr->gr_name));
    }
    else
    {
        StringSetAdd(leafattrib, xstrdup("none"));
    }

    for (rp = crit; rp != NULL; rp = rp->next)
    {
        if (EvalFileResult((char *) rp->item, leafattrib))
        {
            Log(LOG_LEVEL_DEBUG, "Select group match");
            StringSetDestroy(leafattrib);
            return true;
        }

        if (gr && (FullTextMatch(ctx, (char *) rp->item, gr->gr_name)))
        {
            Log(LOG_LEVEL_DEBUG, "Select group match");
            StringSetDestroy(leafattrib);
            return true;
        }

        if (FullTextMatch(ctx, (char *) rp->item, buffer))
        {
            Log(LOG_LEVEL_DEBUG, "Select group match");
            StringSetDestroy(leafattrib);
            return true;
        }
    }

    StringSetDestroy(leafattrib);
    return false;
}
示例#9
0
void EvalContextHeapAddHard(EvalContext *ctx, const char *context)
{
    char context_copy[CF_MAXVARSIZE];

    strcpy(context_copy, context);
    if (Chop(context_copy, CF_EXPANDSIZE) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator");
    }
    CanonifyNameInPlace(context_copy);

    CfDebug("EvalContextHeapAddHard(%s)\n", context_copy);

    if (strlen(context_copy) == 0)
    {
        return;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, context_copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle aborted on defined class \"%s\"\n", context_copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, context_copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\"\n", context_copy);
        exit(1);
    }

    if (EvalContextHeapContainsHard(ctx, context_copy))
    {
        return;
    }

    StringSetAdd(ctx->heap_hard, xstrdup(context_copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, NULL))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", ip->name, StackFrameOwnerName(LastStackFrame(ctx, 0)));
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, NULL))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -> Setting abort for \"%s\" when setting \"%s\"", ip->name, context_copy);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
示例#10
0
StringSet *StringSetAddAllMatchingIterator(StringSet* base, StringSetIterator it, const char *filter_regex)
{
    const char *element = NULL;
    while ((element = SetIteratorNext(&it)))
    {
        if (StringMatch(filter_regex, element))
        {
            StringSetAdd(base, xstrdup(element));
        }
    }
    return base;
}
示例#11
0
void MarkPromiseHandleDone(EvalContext *ctx, const Promise *pp)
{
    char name[CF_BUFSIZE];
    const char *handle = PromiseGetHandle(pp);

    if (handle == NULL)
    {
       return;
    }

    snprintf(name, CF_BUFSIZE, "%s:%s", PromiseGetNamespace(pp), handle);
    StringSetAdd(ctx->dependency_handles, xstrdup(name));
}
示例#12
0
static bool GroupGetUserMembership (const char *user, StringSet *result)
{
    bool ret = true;
    struct group *group_info;

    FILE *fptr = fopen("/etc/group", "r");
    if (!fptr)
    {
        Log(LOG_LEVEL_ERR, "Could not open '/etc/group': %s", GetErrorStr());
        return false;
    }

    while (true)
    {
        errno = 0;
        // Use fgetgrent() instead of getgrent(), to guarantee that the
        // returned group is a local group, and not for example from LDAP.
        group_info = fgetgrent(fptr);
        if (!group_info)
        {
            // Documentation among Unices is conflicting on return codes. When there
            // are no more entries, this happens:
            // Linux = ENOENT
            // AIX = ESRCH
            if (errno && errno != ENOENT && errno != ESRCH)
            {
                Log(LOG_LEVEL_ERR, "Error while getting group list. (fgetgrent: '%s')", GetErrorStr());
                ret = false;
            }
            break;
        }
        for (int i = 0; group_info->gr_mem[i] != NULL; i++)
        {
            if (strcmp(user, group_info->gr_mem[i]) == 0)
            {
                StringSetAdd(result, xstrdup(group_info->gr_name));
                break;
            }
        }
    }

    fclose(fptr);

    return ret;
}
示例#13
0
文件: set.c 项目: chrishiestand/core
StringSet *StringSetFromString(const char *str, char delimiter)
{
    StringSet *set = StringSetNew();

    char delimiters[2] = { 0 };
    delimiters[0] = delimiter;

    char *copy = xstrdup(str);
    char *curr = NULL;

    while ((curr = strsep(&copy, delimiters)))
    {
        StringSetAdd(set, xstrdup(curr));
    }

    free(copy);
    return set;
}
示例#14
0
void MarkPromiseHandleDone(EvalContext *ctx, const Promise *pp)
{
    if (pp == NULL)
    {
        return;
    }

    char name[CF_BUFSIZE];
    char *handle = ConstraintGetRvalValue(ctx, "handle", pp, RVAL_TYPE_SCALAR);

    if (handle == NULL)
    {
       return;
    }
    
    snprintf(name, CF_BUFSIZE, "%s:%s", PromiseGetNamespace(pp), handle);
    StringSetAdd(ctx->dependency_handles, xstrdup(name));
}
示例#15
0
int SelectLeaf(EvalContext *ctx, char *path, struct stat *sb, FileSelect fs)
{
    int result = true;
    Rlist *rp;

    StringSet *leaf_attr = StringSetNew();

#ifdef __MINGW32__
    if (fs.issymlinkto != NULL)
    {
        Log(LOG_LEVEL_VERBOSE,
              "files_select.issymlinkto is ignored on Windows (symbolic links are not supported by Windows)");
    }

    if (fs.groups != NULL)
    {
        Log(LOG_LEVEL_VERBOSE,
              "files_select.search_groups is ignored on Windows (file groups are not supported by Windows)");
    }

    if (fs.bsdflags != NULL)
    {
        Log(LOG_LEVEL_VERBOSE, "files_select.search_bsdflags is ignored on Windows");
    }
#endif /* __MINGW32__ */

    if (fs.name == NULL)
    {
        StringSetAdd(leaf_attr, xstrdup("leaf_name"));
    }

    for (rp = fs.name; rp != NULL; rp = rp->next)
    {
        if (SelectNameRegexMatch(ctx, path, rp->item))
        {
            StringSetAdd(leaf_attr, xstrdup("leaf_name"));
            break;
        }
    }

    if (fs.path == NULL)
    {
        StringSetAdd(leaf_attr, xstrdup("leaf_path"));
    }

    for (rp = fs.path; rp != NULL; rp = rp->next)
    {
        if (SelectPathRegexMatch(ctx, path, rp->item))
        {
            StringSetAdd(leaf_attr, xstrdup("path_name"));
            break;
        }
    }

    if (SelectTypeMatch(sb, fs.filetypes))
    {
        StringSetAdd(leaf_attr, xstrdup("file_types"));
    }

    if ((fs.owners) && (SelectOwnerMatch(ctx, path, sb, fs.owners)))
    {
        StringSetAdd(leaf_attr, xstrdup("owner"));
    }

    if (fs.owners == NULL)
    {
        StringSetAdd(leaf_attr, xstrdup("owner"));
    }

#ifdef __MINGW32__
    StringSetAdd(leaf_attr, xstrdup("group"));

#else /* !__MINGW32__ */
    if ((fs.groups) && (SelectGroupMatch(ctx, sb, fs.groups)))
    {
        StringSetAdd(leaf_attr, xstrdup("group"));
    }

    if (fs.groups == NULL)
    {
        StringSetAdd(leaf_attr, xstrdup("group"));
    }
#endif /* !__MINGW32__ */

    if (SelectModeMatch(sb, fs.perms))
    {
        StringSetAdd(leaf_attr, xstrdup("mode"));
    }

#if defined HAVE_CHFLAGS
    if (SelectBSDMatch(sb, fs.bsdflags))
    {
        StringSetAdd(leaf_attr, xstrdup("bsdflags"));
    }
#endif

    if (SelectTimeMatch(sb->st_atime, fs.min_atime, fs.max_atime))
    {
        StringSetAdd(leaf_attr, xstrdup("atime"));
    }

    if (SelectTimeMatch(sb->st_ctime, fs.min_ctime, fs.max_ctime))
    {
        StringSetAdd(leaf_attr, xstrdup("ctime"));
    }

    if (SelectSizeMatch(sb->st_size, fs.min_size, fs.max_size))
    {
        StringSetAdd(leaf_attr, xstrdup("size"));
    }

    if (SelectTimeMatch(sb->st_mtime, fs.min_mtime, fs.max_mtime))
    {
        StringSetAdd(leaf_attr, xstrdup("mtime"));
    }

    if ((fs.issymlinkto) && (SelectIsSymLinkTo(ctx, path, fs.issymlinkto)))
    {
        StringSetAdd(leaf_attr, xstrdup("issymlinkto"));
    }

    if ((fs.exec_regex) && (SelectExecRegexMatch(ctx, path, fs.exec_regex, fs.exec_program)))
    {
        StringSetAdd(leaf_attr, xstrdup("exec_regex"));
    }

    if ((fs.exec_program) && (SelectExecProgram(path, fs.exec_program)))
    {
        StringSetAdd(leaf_attr, xstrdup("exec_program"));
    }

    result = EvalFileResult(fs.result, leaf_attr);

    Log(LOG_LEVEL_DEBUG, "Select result '%s' on '%s' was %d", fs.result, path, result);

    StringSetDestroy(leaf_attr);

    return result;
}
示例#16
0
文件: verify_vars.c 项目: awsiv/core
PromiseResult VerifyVarPromise(EvalContext *ctx, const Promise *pp, bool allow_duplicates)
{
    ConvergeVariableOptions opts = CollectConvergeVariableOptions(ctx, pp, allow_duplicates);
    if (!opts.should_converge)
    {
        return PROMISE_RESULT_NOOP;
    }

    Attributes a = { {0} };
    // More consideration needs to be given to using these
    //a.transaction = GetTransactionConstraints(pp);
    a.classes = GetClassDefinitionConstraints(ctx, pp);

    VarRef *ref = VarRefParseFromBundle(pp->promiser, PromiseGetBundle(pp));
    if (strcmp("meta", pp->parent_promise_type->name) == 0)
    {
        VarRefSetMeta(ref, true);
    }

    DataType existing_value_type = CF_DATA_TYPE_NONE;
    const void *const existing_value =
        IsExpandable(pp->promiser) ? NULL : EvalContextVariableGet(ctx, ref, &existing_value_type);

    PromiseResult result = PROMISE_RESULT_NOOP;
    Rval rval = opts.cp_save->rval;

    if (rval.item != NULL)
    {
        DataType data_type = DataTypeFromString(opts.cp_save->lval);

        if (opts.cp_save->rval.type == RVAL_TYPE_FNCALL)
        {
            FnCall *fp = RvalFnCallValue(rval);
            const FnCallType *fn = FnCallTypeGet(fp->name);
            if (!fn)
            {
                assert(false && "Canary: should have been caught before this point");
                FatalError(ctx, "While setting variable '%s' in bundle '%s', unknown function '%s'",
                           pp->promiser, PromiseGetBundle(pp)->name, fp->name);
            }

            if (fn->dtype != DataTypeFromString(opts.cp_save->lval))
            {
                FatalError(ctx, "While setting variable '%s' in bundle '%s', variable declared type '%s' but function '%s' returns type '%s'",
                           pp->promiser, PromiseGetBundle(pp)->name, opts.cp_save->lval,
                           fp->name, DataTypeToString(fn->dtype));
            }

            if (existing_value_type != CF_DATA_TYPE_NONE)
            {
                // Already did this
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }

            FnCallResult res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), fp, pp);

            if (res.status == FNCALL_FAILURE)
            {
                /* We do not assign variables to failed fn calls */
                RvalDestroy(res.rval);
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }
            else
            {
                rval = res.rval;
            }
        }
        else
        {
            Buffer *conv = BufferNew();
            bool malformed = false, misprint = false;

            if (strcmp(opts.cp_save->lval, "int") == 0)
            {
                long int asint = IntFromString(opts.cp_save->rval.item);
                if (asint == CF_NOINT)
                {
                    malformed = true;
                }
                else if (0 > BufferPrintf(conv, "%ld", asint))
                {
                    misprint = true;
                }
                else
                {
                    rval = RvalNew(BufferData(conv), opts.cp_save->rval.type);
                }
            }
            else if (strcmp(opts.cp_save->lval, "real") == 0)
            {
                double real_value;
                if (!DoubleFromString(opts.cp_save->rval.item, &real_value))
                {
                    malformed = true;
                }
                else if (0 > BufferPrintf(conv, "%lf", real_value))
                {
                    misprint = true;
                }
                else
                {
                    rval = RvalNew(BufferData(conv), opts.cp_save->rval.type);
                }
            }
            else
            {
                rval = RvalCopy(opts.cp_save->rval);
            }
            BufferDestroy(conv);

            if (malformed)
            {
                /* Arises when opts->cp_save->rval.item isn't yet expanded. */
                /* Has already been logged by *FromString */
                VarRefDestroy(ref);
                return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
            }
            else if (misprint)
            {
                /* Even though no problems with memory allocation can
                 * get here, there might be other problems. */
                UnexpectedError("Problems writing to buffer");
                VarRefDestroy(ref);
                return PROMISE_RESULT_NOOP;
            }
            else if (rval.type == RVAL_TYPE_LIST)
            {
                Rlist *rval_list = RvalRlistValue(rval);
                RlistFlatten(ctx, &rval_list);
                rval.item = rval_list;
            }
        }

        if (Epimenides(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, pp->promiser, rval, 0))
        {
            Log(LOG_LEVEL_ERR, "Variable '%s' contains itself indirectly - an unkeepable promise", pp->promiser);
            exit(EXIT_FAILURE);
        }
        else
        {
            /* See if the variable needs recursively expanding again */

            Rval returnval = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), ref->ns, ref->scope, rval, true, pp);

            RvalDestroy(rval);

            // freed before function exit
            rval = returnval;
        }

        if (existing_value_type != CF_DATA_TYPE_NONE)
        {
            if (!opts.ok_redefine)    /* only on second iteration, else we ignore broken promises */
            {
                if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON &&
                     !CompareRval(existing_value, DataTypeToRvalType(existing_value_type),
                                  rval.item, rval.type))
                {
                    switch (rval.type)
                    {
                    case RVAL_TYPE_SCALAR:
                        Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant scalar '%s', was '%s' now '%s'",
                            pp->promiser, (const char *)existing_value, RvalScalarValue(rval));
                        PromiseRef(LOG_LEVEL_VERBOSE, pp);
                        break;

                    case RVAL_TYPE_LIST:
                        {
                            Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant list '%s'", pp->promiser);
                            Writer *w = StringWriter();
                            RlistWrite(w, existing_value);
                            char *oldstr = StringWriterClose(w);
                            Log(LOG_LEVEL_VERBOSE, "Old value '%s'", oldstr);
                            free(oldstr);

                            w = StringWriter();
                            RlistWrite(w, rval.item);
                            char *newstr = StringWriterClose(w);
                            Log(LOG_LEVEL_VERBOSE, " New value '%s'", newstr);
                            free(newstr);
                            PromiseRef(LOG_LEVEL_VERBOSE, pp);
                        }
                        break;

                    case RVAL_TYPE_CONTAINER:
                    case RVAL_TYPE_FNCALL:
                    case RVAL_TYPE_NOPROMISEE:
                        break;
                    }
                }

                RvalDestroy(rval);
                VarRefDestroy(ref);
                return result;
            }
        }

        if (IsCf3VarString(pp->promiser))
        {
            // Unexpanded variables, we don't do anything with
            RvalDestroy(rval);
            VarRefDestroy(ref);
            return result;
        }

        if (!IsValidVariableName(pp->promiser))
        {
            Log(LOG_LEVEL_ERR, "Variable identifier contains illegal characters");
            PromiseRef(LOG_LEVEL_ERR, pp);
            RvalDestroy(rval);
            VarRefDestroy(ref);
            return result;
        }

        if (rval.type == RVAL_TYPE_LIST)
        {
            if (opts.drop_undefined)
            {
                for (Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next)
                {
                    if (IsNakedVar(RlistScalarValue(rp), '@'))
                    {
                        free(rp->val.item);
                        rp->val.item = xstrdup(CF_NULL_VALUE);
                    }
                }
            }

            for (const Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next)
            {
                switch (rp->val.type)
                {
                case RVAL_TYPE_SCALAR:
                    break;

                default:
                    // Cannot assign variable because value is a list containing a non-scalar item
                    VarRefDestroy(ref);
                    RvalDestroy(rval);
                    return result;
                }
            }
        }

        if (ref->num_indices > 0)
        {
            if (data_type == CF_DATA_TYPE_CONTAINER)
            {
                char *lval_str = VarRefToString(ref, true);
                Log(LOG_LEVEL_ERR, "Cannot assign a container to an indexed variable name '%s'. Should be assigned to '%s' instead",
                    lval_str, ref->lval);
                free(lval_str);
                VarRefDestroy(ref);
                RvalDestroy(rval);
                return result;
            }
            else
            {
                DataType existing_type = CF_DATA_TYPE_NONE;
                VarRef *base_ref = VarRefCopyIndexless(ref);
                if (EvalContextVariableGet(ctx, ref, &existing_type) && existing_type == CF_DATA_TYPE_CONTAINER)
                {
                    char *lval_str = VarRefToString(ref, true);
                    char *base_ref_str = VarRefToString(base_ref, true);
                    Log(LOG_LEVEL_ERR, "Cannot assign value to indexed variable name '%s', because a container is already assigned to the base name '%s'",
                        lval_str, base_ref_str);
                    free(lval_str);
                    free(base_ref_str);
                    VarRefDestroy(base_ref);
                    VarRefDestroy(ref);
                    RvalDestroy(rval);
                    return result;
                }
                VarRefDestroy(base_ref);
            }
        }


        DataType required_datatype = DataTypeFromString(opts.cp_save->lval);
        if (rval.type != DataTypeToRvalType(required_datatype))
        {
            char *ref_str = VarRefToString(ref, true);
            char *value_str = RvalToString(rval);
            Log(LOG_LEVEL_ERR, "Variable '%s' expected a variable of type '%s', but was given incompatible value '%s'",
                ref_str, DataTypeToString(required_datatype), value_str);
            PromiseRef(LOG_LEVEL_ERR, pp);
            free(ref_str);
            free(value_str);
            VarRefDestroy(ref);
            RvalDestroy(rval);
            return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }

        if (!EvalContextVariablePut(ctx, ref, rval.item, required_datatype, "source=promise"))
        {
            Log(LOG_LEVEL_VERBOSE,
                "Unable to converge %s.%s value (possibly empty or infinite regression)",
                ref->scope, pp->promiser);
            PromiseRef(LOG_LEVEL_VERBOSE, pp);
            result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }
        else
        {
            Rlist *promise_meta = PromiseGetConstraintAsList(ctx, "meta", pp);
            if (promise_meta)
            {
                StringSet *class_meta = EvalContextVariableTags(ctx, ref);
                Buffer *print;
                for (const Rlist *rp = promise_meta; rp; rp = rp->next)
                {
                    StringSetAdd(class_meta, xstrdup(RlistScalarValue(rp)));
                    print = StringSetToBuffer(class_meta, ',');
                    Log(LOG_LEVEL_DEBUG,
                        "Added tag %s to class %s, tags now [%s]",
                        RlistScalarValue(rp), pp->promiser, BufferData(print));
                    BufferDestroy(print);
                }
            }
        }
    }
    else
    {
        Log(LOG_LEVEL_ERR, "Variable %s has no promised value", pp->promiser);
        Log(LOG_LEVEL_ERR, "Rule from %s at/before line %llu",
            PromiseGetBundle(pp)->source_path,
            (unsigned long long)opts.cp_save->offset.line);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

    /*
     * FIXME: Variable promise are exempt from normal evaluation logic still, so
     * they are not pushed to evaluation stack before being evaluated. Due to
     * this reason, we cannot call cfPS here to set classes, as it will error
     * out with ProgrammingError.
     *
     * In order to support 'classes' body for variables as well, we call
     * ClassAuditLog explicitly.
     */
    ClassAuditLog(ctx, pp, a, result);

    VarRefDestroy(ref);
    RvalDestroy(rval);

    return result;
}
示例#17
0
void EvalContextStackFrameAddSoft(EvalContext *ctx, const char *context)
{
    assert(SeqLength(ctx->stack) > 0);

    StackFrameBundle frame;
    {
        StackFrame *last_frame = LastStackFrameBundle(ctx);
        if (!last_frame)
        {
            ProgrammingError("Attempted to add a soft class on the stack, but stack had no bundle frame");
        }
        frame = last_frame->data.bundle;
    }

    char copy[CF_BUFSIZE];
    if (strcmp(frame.owner->ns, "default") != 0)
    {
         snprintf(copy, CF_MAXVARSIZE, "%s:%s", frame.owner->ns, context);
    }
    else
    {
         strncpy(copy, context, CF_MAXVARSIZE);
    }

    if (Chop(copy, CF_EXPANDSIZE) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator");
    }

    if (strlen(copy) == 0)
    {
        return;
    }

    CfDebug("NewBundleClass(%s)\n", copy);
    
    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle %s aborted on defined class \"%s\"\n", frame.owner->name, copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, frame.owner->name);
        exit(1);
    }

    if (EvalContextHeapContainsSoft(ctx, copy))
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "WARNING - private class \"%s\" in bundle \"%s\" shadows a global class - you should choose a different name to avoid conflicts",
              copy, frame.owner->name);
    }

    if (EvalContextStackFrameContainsSoft(ctx, copy))
    {
        return;
    }

    StringSetAdd(frame.contexts, xstrdup(copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, frame.owner->ns))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "cf-agent aborted on defined class \"%s\" defined in bundle %s\n", copy, frame.owner->name);
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, frame.owner->ns))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -> Setting abort for \"%s\" when setting \"%s\"", ip->name, context);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
示例#18
0
void EvalContextStackFrameAddSoft(EvalContext *ctx, const char *context)
{
    StringSetAdd(EvalContextStackFrame(ctx)->contexts, xstrdup(context));
}
示例#19
0
void EvalContextStackFrameAddNegated(EvalContext *ctx, const char *context)
{
    StringSetAdd(EvalContextStackFrame(ctx)->contexts_negated, xstrdup(context));
}
示例#20
0
void EvalContextHeapAddNegated(EvalContext *ctx, const char *context)
{
    StringSetAdd(ctx->heap_negated, xstrdup(context));
}
示例#21
0
文件: loading.c 项目: lra/core
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files)
{
    Policy *policy = NULL;
    unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 };
    char hashbuffer[EVP_MAX_MD_SIZE * 4] = { 0 };
    char hashprintbuffer[CF_BUFSIZE] = { 0 };

    HashFile(policy_file, digest, CF_DEFAULT_DIGEST);
    snprintf(hashprintbuffer, CF_BUFSIZE - 1, "{checksum}%s",
             HashPrintSafe(CF_DEFAULT_DIGEST, true, digest, hashbuffer));

    Log(LOG_LEVEL_DEBUG, "Hashed policy file %s to %s", policy_file, hashprintbuffer);

    if (StringSetContains(parsed_files_and_checksums, policy_file))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate policy file %s", policy_file);
        return NULL;
    }
    else if (StringSetContains(parsed_files_and_checksums, hashprintbuffer))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate (detected by hash) policy file %s", policy_file);
        return NULL;
    }
    else
    {
        Log(LOG_LEVEL_DEBUG, "Loading policy file %s", policy_file);
    }

    policy = Cf3ParseFile(config, policy_file);
    // we keep the checksum and the policy file name to help debugging
    StringSetAdd(parsed_files_and_checksums, xstrdup(policy_file));
    StringSetAdd(parsed_files_and_checksums, xstrdup(hashprintbuffer));

    if (policy)
    {
        Seq *errors = SeqNew(10, free);
        if (!PolicyCheckPartial(policy, errors))
        {
            Writer *writer = FileWriter(stderr);
            for (size_t i = 0; i < errors->length; i++)
            {
                PolicyErrorWrite(writer, errors->data[i]);
            }
            WriterClose(writer);
            SeqDestroy(errors);

            StringSetAdd(failed_files, xstrdup(policy_file));
            return NULL;
        }

        SeqDestroy(errors);
    }
    else
    {
        StringSetAdd(failed_files, xstrdup(policy_file));
        return NULL;
    }

    PolicyResolve(ctx, policy, config);

    Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control");
    Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control");

    if (body_common_control)
    {
        Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs");
        Constraint *cp = EffectiveConstraint(ctx, potential_inputs);
        SeqDestroy(potential_inputs);

        if (cp)
        {
            Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files);
            if (aux_policy)
            {
                policy = PolicyMerge(policy, aux_policy);
            }
        }
    }

    if (body_file_control)
    {
        Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs");
        Constraint *cp = EffectiveConstraint(ctx, potential_inputs);
        SeqDestroy(potential_inputs);

        if (cp)
        {
            Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files);
            if (aux_policy)
            {
                policy = PolicyMerge(policy, aux_policy);
            }
        }
    }

    return policy;
}
示例#22
0
static void ExecConfigResetDefault(ExecConfig *exec_config)
{
    free(exec_config->log_facility);
    exec_config->log_facility = xstrdup("LOG_USER");

    free(exec_config->exec_command);
    exec_config->exec_command = xstrdup("");

    free(exec_config->mail_server);
    exec_config->mail_server = xstrdup("");

    free(exec_config->mail_from_address);
    exec_config->mail_from_address = xstrdup("");

    free(exec_config->mail_to_address);
    exec_config->mail_to_address = xstrdup("");

    free(exec_config->mail_subject);
    exec_config->mail_subject = xstrdup("");

    exec_config->mail_max_lines = 30;
    exec_config->agent_expireafter = 10800;
    exec_config->splay_time = 0;

    StringSetClear(exec_config->schedule);
    StringSetAdd(exec_config->schedule, xstrdup("Min00"));
    StringSetAdd(exec_config->schedule, xstrdup("Min05"));
    StringSetAdd(exec_config->schedule, xstrdup("Min10"));
    StringSetAdd(exec_config->schedule, xstrdup("Min15"));
    StringSetAdd(exec_config->schedule, xstrdup("Min20"));
    StringSetAdd(exec_config->schedule, xstrdup("Min25"));
    StringSetAdd(exec_config->schedule, xstrdup("Min30"));
    StringSetAdd(exec_config->schedule, xstrdup("Min35"));
    StringSetAdd(exec_config->schedule, xstrdup("Min40"));
    StringSetAdd(exec_config->schedule, xstrdup("Min45"));
    StringSetAdd(exec_config->schedule, xstrdup("Min50"));
    StringSetAdd(exec_config->schedule, xstrdup("Min55"));
}
示例#23
0
void ExecConfigUpdate(const EvalContext *ctx, const Policy *policy, ExecConfig *exec_config)
{
    ExecConfigResetDefault(exec_config);

    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);

            if (!IsDefinedClass(ctx, cp->classes, NULL))
            {
                continue;
            }

            VarRef *ref = VarRefParseFromScope(cp->lval, "control_executor");

            Rval retval;
            if (!EvalContextVariableGet(ctx, ref, &retval, NULL))
            {
                // TODO: should've been checked before this point. change to programming error
                Log(LOG_LEVEL_ERR, "Unknown lval '%s' in exec control body", cp->lval);
                VarRefDestroy(ref);
                continue;
            }

            VarRefDestroy(ref);

            if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFROM].lval) == 0)
            {
                free(exec_config->mail_from_address);
                exec_config->mail_from_address = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "mailfrom '%s'", exec_config->mail_from_address);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILTO].lval) == 0)
            {
                free(exec_config->mail_to_address);
                exec_config->mail_to_address = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "mailto '%s'", exec_config->mail_to_address);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILSUBJECT].lval) == 0)
            {
                free(exec_config->mail_subject);
                exec_config->mail_subject = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "mailsubject '%s'", exec_config->mail_subject);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SMTPSERVER].lval) == 0)
            {
                free(exec_config->mail_server);
                exec_config->mail_server = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "smtpserver '%s'", exec_config->mail_server);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECCOMMAND].lval) == 0)
            {
                free(exec_config->exec_command);
                exec_config->exec_command = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "exec_command '%s'", exec_config->exec_command);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_AGENT_EXPIREAFTER].lval) == 0)
            {
                exec_config->agent_expireafter = IntFromString(retval.item);
                Log(LOG_LEVEL_DEBUG, "agent_expireafter %d", exec_config->agent_expireafter);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECUTORFACILITY].lval) == 0)
            {
                exec_config->log_facility = xstrdup(retval.item);
                Log(LOG_LEVEL_DEBUG, "executorfacility '%s'", exec_config->log_facility);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILMAXLINES].lval) == 0)
            {
                exec_config->mail_max_lines = IntFromString(retval.item);
                Log(LOG_LEVEL_DEBUG, "maxlines %d", exec_config->mail_max_lines);
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SPLAYTIME].lval) == 0)
            {
                int time = IntFromString(RvalScalarValue(retval));
                exec_config->splay_time = (int) (time * SECONDS_PER_MINUTE * GetSplay());
            }
            else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SCHEDULE].lval) == 0)
            {
                Log(LOG_LEVEL_DEBUG, "Loading user-defined schedule...");
                StringSetClear(exec_config->schedule);

                for (const Rlist *rp = retval.item; rp; rp = rp->next)
                {
                    StringSetAdd(exec_config->schedule, xstrdup(RlistScalarValue(rp)));
                    Log(LOG_LEVEL_DEBUG, "Adding '%s'", RlistScalarValue(rp));
                }
            }
        }
    }

    char ipbuf[CF_MAXVARSIZE] = "";
    for (Item *iptr = EvalContextGetIpAddresses(ctx); iptr != NULL; iptr = iptr->next)
    {
        if ((SafeStringLength(ipbuf) + SafeStringLength(iptr->name)) < sizeof(ipbuf))
        {
            strcat(ipbuf, iptr->name);
            strcat(ipbuf, " ");
        }
        else
        {
            break;
        }
    }
    Chop(ipbuf, sizeof(ipbuf));
    free(exec_config->ip_addresses);
    exec_config->ip_addresses = xstrdup(ipbuf);
}
示例#24
0
static int SelectTypeMatch(struct stat *lstatptr, Rlist *crit)
{
    Rlist *rp;

    StringSet *leafattrib = StringSetNew();

    if (S_ISREG(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("reg"));
        StringSetAdd(leafattrib, xstrdup("plain"));
    }

    if (S_ISDIR(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("dir"));
    }

#ifndef __MINGW32__
    if (S_ISLNK(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("symlink"));
    }

    if (S_ISFIFO(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("fifo"));
    }

    if (S_ISSOCK(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("socket"));
    }

    if (S_ISCHR(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("char"));
    }

    if (S_ISBLK(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("block"));
    }
#endif /* !__MINGW32__ */

#ifdef HAVE_DOOR_CREATE
    if (S_ISDOOR(lstatptr->st_mode))
    {
        StringSetAdd(leafattrib, xstrdup("door"));
    }
#endif

    for (rp = crit; rp != NULL; rp = rp->next)
    {
        if (EvalFileResult((char *) rp->item, leafattrib))
        {
            StringSetDestroy(leafattrib);
            return true;
        }
    }

    StringSetDestroy(leafattrib);
    return false;
}
示例#25
0
static int SelectProcess(char *procentry, char **names, int *start, int *end, ProcessSelect a)
{
    int result = true, i;
    char *column[CF_PROCCOLS];
    Rlist *rp;

    StringSet *proc_attr = StringSetNew();

    if (!SplitProcLine(procentry, names, start, end, column))
    {
        return false;
    }

    for (i = 0; names[i] != NULL; i++)
    {
        Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]);
    }

    for (rp = a.owner; rp != NULL; rp = rp->next)
    {
        if (SelectProcRegexMatch("USER", "UID", (char *) rp->item, names, column))
        {
            StringSetAdd(proc_attr, xstrdup("process_owner"));
            break;
        }
    }

    if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("pid"));
    }

    if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("ppid"));
    }

    if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("pgid"));
    }

    if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("vsize"));
    }

    if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("rsize"));
    }

    if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("ttime"));
    }

    if (SelectProcTimeAbsRangeMatch
        ("STIME", "START", a.min_stime, a.max_stime, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("stime"));
    }

    if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("priority"));
    }

    if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("threads"));
    }

    if (SelectProcRegexMatch("S", "STAT", a.status, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("status"));
    }

    if (SelectProcRegexMatch("CMD", "COMMAND", a.command, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("command"));
    }

    if (SelectProcRegexMatch("TTY", "TTY", a.tty, names, column))
    {
        StringSetAdd(proc_attr, xstrdup("tty"));
    }

    result = EvalProcessResult(a.process_result, proc_attr);

    StringSetDestroy(proc_attr);

    for (i = 0; column[i] != NULL; i++)
    {
        free(column[i]);
    }

    return result;
}
示例#26
0
void EvalContextHeapAddSoft(EvalContext *ctx, const char *context, const char *ns)
{
    char context_copy[CF_MAXVARSIZE];
    char canonified_context[CF_MAXVARSIZE];

    strcpy(canonified_context, context);
    if (Chop(canonified_context, CF_EXPANDSIZE) == -1)
    {
        Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator");
    }
    CanonifyNameInPlace(canonified_context);
    
    if (ns && strcmp(ns, "default") != 0)
    {
        snprintf(context_copy, CF_MAXVARSIZE, "%s:%s", ns, canonified_context);
    }
    else
    {
        strncpy(context_copy, canonified_context, CF_MAXVARSIZE);
    }

    if (strlen(context_copy) == 0)
    {
        return;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, context_copy))
    {
        Log(LOG_LEVEL_ERR, "Bundle aborted on defined class '%s'", context_copy);
        ABORTBUNDLE = true;
    }

    if (IsRegexItemIn(ctx, ctx->heap_abort, context_copy))
    {
        Log(LOG_LEVEL_ERR, "cf-agent aborted on defined class '%s'", context_copy);
        exit(1);
    }

    if (EvalContextHeapContainsSoft(ctx, context_copy))
    {
        return;
    }

    StringSetAdd(ctx->heap_soft, xstrdup(context_copy));

    for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next)
    {
        if (IsDefinedClass(ctx, ip->name, ns))
        {
            Log(LOG_LEVEL_ERR, "cf-agent aborted on defined class '%s' defined in bundle '%s'", ip->name, StackFrameOwnerName(LastStackFrame(ctx, 0)));
            exit(1);
        }
    }

    if (!ABORTBUNDLE)
    {
        for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next)
        {
            if (IsDefinedClass(ctx, ip->name, ns))
            {
                Log(LOG_LEVEL_ERR, "Setting abort for '%s' when setting '%s'", ip->name, context_copy);
                ABORTBUNDLE = true;
                break;
            }
        }
    }
}
示例#27
0
static void TransformGidsToGroups(StringSet **list)
{
    StringSet *new_list = StringSetNew();
    StringSetIterator i = StringSetIteratorInit(*list);
    const char *data;
    for (data = StringSetIteratorNext(&i); data; data = StringSetIteratorNext(&i))
    {
        if (strlen(data) != strspn(data, "0123456789"))
        {
            // Cannot possibly be a gid.
            StringSetAdd(new_list, xstrdup(data));
            continue;
        }
        // In groups vs gids, groups take precedence. So check if it exists.
        errno = 0;
        struct group *group_info = getgrnam(data);
        if (!group_info)
        {
            switch (errno)
            {
            case 0:
            case ENOENT:
            case EBADF:
            case ESRCH:
            case EWOULDBLOCK:
            case EPERM:
                // POSIX is apparently ambiguous here. All values mean "not found".
                errno = 0;
                group_info = getgrgid(atoi(data));
                if (!group_info)
                {
                    switch (errno)
                    {
                    case 0:
                    case ENOENT:
                    case EBADF:
                    case ESRCH:
                    case EWOULDBLOCK:
                    case EPERM:
                        // POSIX is apparently ambiguous here. All values mean "not found".
                        //
                        // Neither group nor gid is found. This will lead to an error later, but we don't
                        // handle that here.
                        break;
                    default:
                        Log(LOG_LEVEL_ERR, "Error while checking group name '%s'. (getgrgid: '%s')", data, GetErrorStr());
                        StringSetDestroy(new_list);
                        return;
                    }
                }
                else
                {
                    // Replace gid with group name.
                    StringSetAdd(new_list, xstrdup(group_info->gr_name));
                }
                break;
            default:
                Log(LOG_LEVEL_ERR, "Error while checking group name '%s'. (getgrnam: '%s')", data, GetErrorStr());
                StringSetDestroy(new_list);
                return;
            }
        }
        else
        {
            StringSetAdd(new_list, xstrdup(data));
        }
    }
    StringSet *old_list = *list;
    *list = new_list;
    StringSetDestroy(old_list);
}
示例#28
0
static bool SelectProcess(const char *procentry,
                          time_t pstime,
                          char **names,
                          int *start,
                          int *end,
                          const char *process_regex,
                          ProcessSelect a,
                          bool attrselect)
{
    bool result = true;
    char *column[CF_PROCCOLS];
    Rlist *rp;

    assert(process_regex);

    StringSet *process_select_attributes = StringSetNew();

    memset(column, 0, sizeof(column));

    if (!SplitProcLine(procentry, pstime, names, start, end,
                       PS_COLUMN_ALGORITHM[VPSHARDCLASS], column))
    {
        result = false;
        goto cleanup;
    }

    ApplyPlatformExtraTable(names, column);

    for (int i = 0; names[i] != NULL; i++)
    {
        Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]);
    }

    if (!SelectProcRegexMatch("CMD", "COMMAND", process_regex, false, names, column))
    {
        result = false;
        goto cleanup;
    }

    if (!attrselect)
    {
        // If we are not considering attributes, then the matching is done.
        goto cleanup;
    }

    for (rp = a.owner; rp != NULL; rp = rp->next)
    {
        if (SelectProcRegexMatch("USER", "UID", RlistScalarValue(rp), true, names, column))
        {
            StringSetAdd(process_select_attributes, xstrdup("process_owner"));
            break;
        }
    }

    if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("pid"));
    }

    if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("ppid"));
    }

    if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("pgid"));
    }

    if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("vsize"));
    }

    if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("rsize"));
    }

    if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("ttime"));
    }

    if (SelectProcTimeAbsRangeMatch
        ("STIME", "START", a.min_stime, a.max_stime, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("stime"));
    }

    if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("priority"));
    }

    if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("threads"));
    }

    if (SelectProcRegexMatch("S", "STAT", a.status, true, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("status"));
    }

    if (SelectProcRegexMatch("CMD", "COMMAND", a.command, true, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("command"));
    }

    if (SelectProcRegexMatch("TTY", "TTY", a.tty, true, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("tty"));
    }

    if (!a.process_result)
    {
        if (StringSetSize(process_select_attributes) == 0)
        {
            result = EvalProcessResult("", process_select_attributes);
        }
        else
        {
            Writer *w = StringWriter();
            StringSetIterator iter = StringSetIteratorInit(process_select_attributes);
            char *attr = StringSetIteratorNext(&iter);
            WriterWrite(w, attr);

            while ((attr = StringSetIteratorNext(&iter)))
            {
                WriterWriteChar(w, '.');
                WriterWrite(w, attr);
            }

            result = EvalProcessResult(StringWriterData(w), process_select_attributes);
            WriterClose(w);
        }
    }
    else
    {
        result = EvalProcessResult(a.process_result, process_select_attributes);
    }

cleanup:
    StringSetDestroy(process_select_attributes);

    for (int i = 0; column[i] != NULL; i++)
    {
        free(column[i]);
    }

    return result;
}
示例#29
0
static bool VerifyIfUserNeedsModifs (const char *puser, const User *u, const struct passwd *passwd_info,
                             uint32_t *changemap)
{
    assert(u != NULL);
    if (u->description != NULL && strcmp (u->description, passwd_info->pw_gecos))
    {
        CFUSR_SETBIT (*changemap, i_comment);
    }
    if (u->uid != NULL && (atoi (u->uid) != passwd_info->pw_uid))
    {
        CFUSR_SETBIT (*changemap, i_uid);
    }
    if (u->home_dir != NULL && strcmp (u->home_dir, passwd_info->pw_dir))
    {
        CFUSR_SETBIT (*changemap, i_home);
    }
    if (u->shell != NULL && strcmp (u->shell, passwd_info->pw_shell))
    {
        CFUSR_SETBIT (*changemap, i_shell);
    }
    bool account_is_locked = IsAccountLocked(puser, passwd_info);
    if ((!account_is_locked && u->policy == USER_STATE_LOCKED)
        || (account_is_locked && u->policy != USER_STATE_LOCKED))
    {
        CFUSR_SETBIT(*changemap, i_locked);
    }
    // Don't bother with passwords if the account is going to be locked anyway.
    if (u->password != NULL && strcmp (u->password, "")
        && u->policy != USER_STATE_LOCKED)
    {
        if (!IsPasswordCorrect(puser, u->password, u->password_format, passwd_info))
        {
            CFUSR_SETBIT (*changemap, i_password);
        }
    }

    if (SafeStringLength(u->group_primary))
    {
        bool group_could_be_gid = (strlen(u->group_primary) == strspn(u->group_primary, "0123456789"));
        int gid;

        // We try name first, even if it looks like a gid. Only fall back to gid.
        struct group *group_info;
        errno = 0;
        group_info = GetGrEntry(u->group_primary, &EqualGroupName);
        if (!group_info && errno != 0)
        {
            Log(LOG_LEVEL_ERR, "Could not obtain information about group '%s': %s", u->group_primary, GetErrorStr());
            gid = -1;
        }
        else if (!group_info)
        {
            if (group_could_be_gid)
            {
                gid = atoi(u->group_primary);
            }
            else
            {
                Log(LOG_LEVEL_ERR, "No such group '%s'.", u->group_primary);
                gid = -1;
            }
        }
        else
        {
            gid = group_info->gr_gid;
        }

        if (gid != passwd_info->pw_gid)
        {
            CFUSR_SETBIT (*changemap, i_group);
        }
    }

    if (u->groups_secondary_given)
    {
        StringSet *wanted_groups = StringSetNew();
        for (Rlist *ptr = u->groups_secondary; ptr; ptr = ptr->next)
        {
            StringSetAdd(wanted_groups, xstrdup(RvalScalarValue(ptr->val)));
        }
        TransformGidsToGroups(&wanted_groups);
        StringSet *current_groups = StringSetNew();
        if (!GroupGetUserMembership (puser, current_groups))
        {
            CFUSR_SETBIT (*changemap, i_groups);
        }
        else if (!StringSetIsEqual (current_groups, wanted_groups))
        {
            CFUSR_SETBIT (*changemap, i_groups);
        }
        StringSetDestroy(current_groups);
        StringSetDestroy(wanted_groups);
    }

    ////////////////////////////////////////////
    if (*changemap == 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}
示例#30
0
static int SelectProcess(EvalContext *ctx, char *procentry, char **names, int *start, int *end, ProcessSelect a)
{
    int result = true, i;
    char *column[CF_PROCCOLS];
    Rlist *rp;

    StringSet *process_select_attributes = StringSetNew();

    if (!SplitProcLine(procentry, names, start, end, column))
    {
        return false;
    }

    for (i = 0; names[i] != NULL; i++)
    {
        Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]);
    }

    for (rp = a.owner; rp != NULL; rp = rp->next)
    {
        if (SelectProcRegexMatch(ctx, "USER", "UID", RlistScalarValue(rp), names, column))
        {
            StringSetAdd(process_select_attributes, xstrdup("process_owner"));
            break;
        }
    }

    if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("pid"));
    }

    if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("ppid"));
    }

    if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("pgid"));
    }

    if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("vsize"));
    }

    if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("rsize"));
    }

    if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("ttime"));
    }

    if (SelectProcTimeAbsRangeMatch
        ("STIME", "START", a.min_stime, a.max_stime, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("stime"));
    }

    if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("priority"));
    }

    if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("threads"));
    }

    if (SelectProcRegexMatch(ctx, "S", "STAT", a.status, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("status"));
    }

    if (SelectProcRegexMatch(ctx, "CMD", "COMMAND", a.command, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("command"));
    }

    if (SelectProcRegexMatch(ctx, "TTY", "TTY", a.tty, names, column))
    {
        StringSetAdd(process_select_attributes, xstrdup("tty"));
    }

    if (!a.process_result)
    {
        if (StringSetSize(process_select_attributes) == 0)
        {
            result = EvalProcessResult("", process_select_attributes);
        }
        else
        {
            Writer *w = StringWriter();
            StringSetIterator iter = StringSetIteratorInit(process_select_attributes);
            char *attr = StringSetIteratorNext(&iter);
            WriterWrite(w, attr);

            while ((attr = StringSetIteratorNext(&iter)))
            {
                WriterWriteChar(w, '.');
                WriterWrite(w, attr);
            }

            result = EvalProcessResult(StringWriterData(w), process_select_attributes);
            WriterClose(w);
        }
    }
    else
    {
        result = EvalProcessResult(a.process_result, process_select_attributes);
    }

    StringSetDestroy(process_select_attributes);

    for (i = 0; column[i] != NULL; i++)
    {
        free(column[i]);
    }

    return result;
}