Exemplo n.º 1
0
static void test_expand_list_nested(void **state)
{
    EvalContext *ctx = *state;
    {
        VarRef *lval = VarRefParse("default:bundle.i");
        EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }
    {
        VarRef *lval = VarRefParse("default:bundle.inner[one]");
        Rlist *list = NULL;
        RlistAppendScalar(&list, "foo");
        EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL);
        RlistDestroy(list);
        VarRefDestroy(lval);
    }

    Rlist *outer = NULL;
    RlistAppendScalar(&outer, "@{inner[$(i)]}");

    Rlist *expanded = ExpandList(ctx, "default", "bundle", outer, true);

    assert_int_equal(1, RlistLen(expanded));
    assert_string_equal("foo", RlistScalarValue(expanded));

    RlistDestroy(outer);
    RlistDestroy(expanded);
}
Exemplo n.º 2
0
static void test_expand_promise_array_with_scalar_arg(void **state)
{
    EvalContext *ctx = *state;
    {
        VarRef *lval = VarRefParse("default:bundle.foo[one]");
        EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }
    {
        VarRef *lval = VarRefParse("default:bundle.bar");
        EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }

    Policy *policy = PolicyNew();
    Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL);
    PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy");
    Promise *promise = PromiseTypeAppendPromise(promise_type, "$(foo[$(bar)])", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL);

    EvalContextStackPushBundleFrame(ctx, bundle, NULL, false);
    EvalContextStackPushPromiseTypeFrame(ctx, promise_type);
    ExpandPromise(ctx, promise, actuator_expand_promise_array_with_scalar_arg, NULL);
    EvalContextStackPopFrame(ctx);
    EvalContextStackPopFrame(ctx);

    PolicyDestroy(policy);
}
Exemplo n.º 3
0
static void test_remove(void)
{
    VariableTable *t = ReferenceTable();

    {
        VarRef *ref = VarRefParse("scope1.array[one]");
        assert_true(VariableTableRemove(t, ref));
        assert_true(VariableTableGet(t, ref) == NULL);
        assert_false(VariableTableRemove(t, ref));

        assert_int_equal(11, VariableTableCount(t, NULL, NULL, NULL));

        VarRefDestroy(ref);
    }

    {
        VarRef *ref = VarRefParse("ns1:scope1.lval1");
        assert_true(VariableTableRemove(t, ref));
        assert_true(VariableTableGet(t, ref) == NULL);
        assert_false(VariableTableRemove(t, ref));

        assert_int_equal(10, VariableTableCount(t, NULL, NULL, NULL));

        VarRefDestroy(ref);
    }

    VariableTableDestroy(t);
}
Exemplo n.º 4
0
static void test_iterate_indices(void)
{
    VariableTable *t = ReferenceTable();

    {
        VarRef *ref = VarRefParse("default:scope1.array");
        VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref);
        
        unsigned short number_of_entries = 0;
        while (VariableTableIteratorNext(iter))
        {
            number_of_entries++;
        }
        assert_int_equal(4, number_of_entries);
        
        VariableTableIteratorDestroy(iter);
        VarRefDestroy(ref);
    }
    
    {
        VarRef *ref = VarRefParse("default:scope1.array[two]");
        VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref);

        unsigned short number_of_entries = 0;
        while (VariableTableIteratorNext(iter))
        {
            number_of_entries++;
        }
        
        assert_int_equal(3, number_of_entries);
        
        VariableTableIteratorDestroy(iter);
        VarRefDestroy(ref);
    }
}
Exemplo n.º 5
0
static void test_expand_promise_slist(void **state)
{
    actuator_state = 0;

    EvalContext *ctx = *state;
    {
        VarRef *lval = VarRefParse("default:bundle.foo");
        Rlist *list = NULL;
        RlistAppendScalar(&list, "a");
        RlistAppendScalar(&list, "b");

        EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL);

        RlistDestroy(list);
        VarRefDestroy(lval);
    }


    Policy *policy = PolicyNew();
    Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL);
    PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy");
    Promise *promise = PromiseTypeAppendPromise(promise_type, "$(foo)", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL);

    EvalContextStackPushBundleFrame(ctx, bundle, NULL, false);
    EvalContextStackPushPromiseTypeFrame(ctx, promise_type);
    ExpandPromise(ctx, promise, actuator_expand_promise_slist, NULL);
    EvalContextStackPopFrame(ctx);
    EvalContextStackPopFrame(ctx);

    assert_int_equal(2, actuator_state);

    PolicyDestroy(policy);
}
Exemplo n.º 6
0
static bool PutVar(VariableTable *table, char *var_str)
{
    VarRef *ref = VarRefParse(var_str);
    Rval rval = (Rval) { var_str, RVAL_TYPE_SCALAR };
    bool ret = VariableTablePut(table, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL);
    VarRefDestroy(ref);
    return ret;
}
Exemplo n.º 7
0
static void CheckToString(const char *str)
{
    VarRef ref = VarRefParse(str);
    char *out = VarRefToString(ref);
    assert_string_equal(str, out);
    free(out);
    VarRefDestroy(ref);
}
Exemplo n.º 8
0
static VariableTable *ReferenceTable(void)
{
    VariableTable *t = VariableTableNew();

    assert_false(PutVar(t, "scope1.lval1"));
    assert_false(PutVar(t, "scope1.lval2"));
    assert_false(PutVar(t, "scope2.lval1"));
    {
        VarRef *ref = VarRefParse("scope1.array[one]");
        Rval rval = (Rval) {
            "scope1.array[one]", RVAL_TYPE_SCALAR
        };
        assert_false(VariableTablePut(t, ref, &rval, DATA_TYPE_STRING, NULL, NULL));
        VarRefDestroy(ref);
    }
    {
        VarRef *ref = VarRefParse("scope1.array[two]");
        Rval rval = (Rval) {
            "scope1.array[two]", RVAL_TYPE_SCALAR
        };
        assert_false(VariableTablePut(t, ref, &rval, DATA_TYPE_STRING, NULL, NULL));
        VarRefDestroy(ref);
    }
    {
        VarRef *ref = VarRefParse("scope1.array[two][three]");
        Rval rval = (Rval) {
            "scope1.array[two][three]", RVAL_TYPE_SCALAR
        };
        assert_false(VariableTablePut(t, ref, &rval, DATA_TYPE_STRING, NULL, NULL));
        VarRefDestroy(ref);
    }
    {
        VarRef *ref = VarRefParse("scope1.array[two][four]");
        Rval rval = (Rval) {
            "scope1.array[two][four]", RVAL_TYPE_SCALAR
        };
        assert_false(VariableTablePut(t, ref, &rval, DATA_TYPE_STRING, NULL, NULL));
        VarRefDestroy(ref);
    }

    assert_false(PutVar(t, "ns1:scope1.lval1"));
    assert_false(PutVar(t, "ns1:scope1.lval2"));
    assert_false(PutVar(t, "ns1:scope2.lval1"));

    return t;
}
Exemplo n.º 9
0
static void TestGet(VariableTable *t, const char *ref_str)
{
    VarRef *ref = VarRefParse(ref_str);
    Variable *v = VariableTableGet(t, ref);
    assert_true(v != NULL);
    assert_int_equal(0, VarRefCompare(ref, v->ref));
    assert_string_equal(ref_str, RvalScalarValue(v->rval));
    VarRefDestroy(ref);
}
Exemplo n.º 10
0
static void test_full(void **state)
{
    VarRef ref = VarRefParse("ns:scope.lval");
    assert_string_equal("ns", ref.ns);
    assert_string_equal("scope", ref.scope);
    assert_string_equal("lval", ref.lval);
    assert_int_equal(0, ref.num_indices);
    assert_false(ref.indices);
    VarRefDestroy(ref);
}
Exemplo n.º 11
0
static void test_qualified_array(void **state)
{
    VarRef ref = VarRefParse("scope.lval[x]");
    assert_false(ref.ns);
    assert_string_equal("scope", ref.scope);
    assert_string_equal("lval", ref.lval);
    assert_int_equal(1, ref.num_indices);
    assert_string_equal("x", ref.indices[0]);
    VarRefDestroy(ref);
}
Exemplo n.º 12
0
static void test_dotted_array(void **state)
{
    VarRef ref = VarRefParse("ns:scope.lval[la.la]");
    assert_string_equal("ns", ref.ns);
    assert_string_equal("scope", ref.scope);
    assert_string_equal("lval", ref.lval);
    assert_int_equal(1, ref.num_indices);
    assert_string_equal("la.la", ref.indices[0]);
    VarRefDestroy(ref);
}
Exemplo n.º 13
0
static void test_plain_variable_with_no_stuff_in_it(void **state)
{
    VarRef ref = VarRefParse("foo");
    assert_false(ref.ns);
    assert_false(ref.scope);
    assert_string_equal("foo", ref.lval);
    assert_int_equal(0, ref.num_indices);
    assert_false(ref.indices);
    VarRefDestroy(ref);
}
Exemplo n.º 14
0
static void test_expand_scalar_array_with_scalar_arg(void **state)
{
    EvalContext *ctx = *state;
    {
        VarRef *lval = VarRefParse("default:bundle.foo[one]");
        EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }
    {
        VarRef *lval = VarRefParse("default:bundle.bar");
        EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }

    Buffer *res = BufferNew();
    ExpandScalar(ctx, "default", "bundle", "a$(foo[$(bar)])b", res);

    assert_string_equal("afirstb", BufferData(res));
    BufferDestroy(res);
}
Exemplo n.º 15
0
static void test_expand_scalar_two_scalars_nested(void **state)
{
    EvalContext *ctx = *state;
    {
        VarRef *lval = VarRefParse("default:bundle.one");
        EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }
    {
        VarRef *lval = VarRefParse("default:bundle.two");
        EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }

    Buffer *res = BufferNew();
    ExpandScalar(ctx, "default", "bundle", "a $($(two))b", res);

    assert_string_equal("a firstb", BufferData(res));
    BufferDestroy(res);
}
Exemplo n.º 16
0
VarRef *VarRefParseFromBundle(const char *var_ref_string, const Bundle *bundle)
{
    if (bundle)
    {
        return VarRefParseFromNamespaceAndScope(var_ref_string, bundle->ns, bundle->name, CF_NS, '.');
    }
    else
    {
        return VarRefParse(var_ref_string);
    }
}
Exemplo n.º 17
0
static void test_levels(void **state)
{
    VarRef ref = VarRefParse("ns:scope.lval[x][y][z]");
    assert_string_equal("ns", ref.ns);
    assert_string_equal("scope", ref.scope);
    assert_string_equal("lval", ref.lval);
    assert_int_equal(3, ref.num_indices);
    assert_string_equal("x", ref.indices[0]);
    assert_string_equal("y", ref.indices[1]);
    assert_string_equal("z", ref.indices[2]);
    VarRefDestroy(ref);
}
Exemplo n.º 18
0
Arquivo: rlist.c Projeto: cduclos/core
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    for (Rlist *rp = *list; rp != NULL;)
    {
        if (rp->val.type != RVAL_TYPE_SCALAR)
        {
            rp = rp->next;
            continue;
        }

        char naked[CF_BUFSIZE] = "";
        if (IsNakedVar(RlistScalarValue(rp), '@'))
        {
            GetNaked(naked, RlistScalarValue(rp));

            if (!IsExpandable(naked))
            {
                Rval rv;
                VarRef *ref = VarRefParse(naked);

                bool var_found = EvalContextVariableGet(ctx, ref, &rv, NULL);

                VarRefDestroy(ref);

                if (var_found)
                {
                    switch (rv.type)
                    {
                    case RVAL_TYPE_LIST:
                        for (const Rlist *srp = rv.item; srp != NULL; srp = srp->next)
                        {
                            RlistAppendRval(list, RvalCopy(srp->val));
                        }
                        Rlist *next = rp->next;
                        RlistDestroyEntry(list, rp);
                        rp = next;
                        continue;

                    default:
                        ProgrammingError("List variable does not resolve to a list");
                        RlistAppendRval(list, RvalCopy(rp->val));
                        break;
                    }
                }
            }
        }
        rp = rp->next;
    }
}
Exemplo n.º 19
0
static void test_replace(void)
{
    VariableTable *t = ReferenceTable();

    VarRef *ref = VarRefParse("scope1.lval1");
    TestGet(t, "scope1.lval1");

    Rval rval = (Rval) { "foo", RVAL_TYPE_SCALAR };
    assert_true(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL));

    Variable *v = VariableTableGet(t, ref);
    assert_true(v != NULL);
    assert_string_equal("foo", RvalScalarValue(v->rval));

    VarRefDestroy(ref);

    VariableTableDestroy(t);
}
Exemplo n.º 20
0
DataType StringDataType(EvalContext *ctx, const char *string)
{
 int islist = false;
 DataType dtype = CF_DATA_TYPE_NONE;

/*-------------------------------------------------------
  What happens if we embed vars in a literal string
  "$(list)withending" - a list?
  "$(list1)$(list2)"  - not a simple list
  Disallow these manual concatenations as ambiguous.
  Demand this syntax to work around

  vars:

  "listvar" slist => EmbellishList("prefix$(list)suffix");
  ---------------------------------------------------------*/

 size_t len = strlen(string);

 if (*string == '$')
    {
    Buffer *inner_value = BufferNew();
    if (ExtractScalarReference(inner_value, string, len, true))
       {
       if (!IsExpandable(BufferData(inner_value)))
          {
          VarRef *ref = VarRefParse(BufferData(inner_value));
          if (EvalContextVariableGet(ctx, ref, &dtype))
             {
             if (DataTypeToRvalType(dtype) == RVAL_TYPE_LIST)
                {
                if (!islist)
                   {
                   islist = true;
                   }
                else
                   {
                   islist = false;
                   }
                }
             }

          VarRefDestroy(ref);
          }

       if (BufferSize(inner_value) == strlen(string))
          {
          BufferDestroy(inner_value);
          return dtype;
          }
       else
          {
          BufferDestroy(inner_value);
          return CF_DATA_TYPE_STRING;
          }
       }

    BufferDestroy(inner_value);
    }

 return CF_DATA_TYPE_STRING;
}
Exemplo n.º 21
0
/**
 * @brief Flattens an Rlist by expanding naked scalar list-variable
 *        members. Flattening is only one-level deep.
 */
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    Rlist *next;
    for (Rlist *rp = *list; rp != NULL; rp = next)
    {
        next = rp->next;

        if (rp->val.type == RVAL_TYPE_SCALAR      &&
            IsNakedVar(RlistScalarValue(rp), '@'))
        {
            char naked[CF_MAXVARSIZE];
            GetNaked(naked, RlistScalarValue(rp));

            /* Make sure there are no inner expansions to take place, like if
             * rp was "@{blah_$(blue)}".  */
            if (!IsExpandable(naked))
            {
                Log(LOG_LEVEL_DEBUG,
                    "Flattening slist: %s", RlistScalarValue(rp));

                VarRef *ref = VarRefParse(naked);
                DataType value_type;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value_type == CF_DATA_TYPE_NONE)
                {
                    assert(value == NULL);
                    continue;                         /* undefined variable */
                }

                if (DataTypeToRvalType(value_type) != RVAL_TYPE_LIST)
                {
                    Log(LOG_LEVEL_WARNING,
                        "'%s' failed - variable is not list but %s",
                        RlistScalarValue(rp), DataTypeToString(value_type));
                    continue;
                }

                /* NOTE: Remember that value can be NULL as an empty Rlist. */

                /* at_node: just a mnemonic name for the
                            list node with @{blah}. */
                Rlist *at_node      = rp;
                Rlist *insert_after = at_node;
                for (const Rlist *rp2 = value; rp2 != NULL; rp2 = rp2->next)
                {
                    assert(insert_after != NULL);

                    RlistInsertAfter(insert_after, RvalCopy(rp2->val));
                    insert_after = insert_after->next;
                }

                /* Make sure we won't miss any element. */
                assert(insert_after->next == next);
                RlistDestroyEntry(list, at_node);   /* Delete @{blah} entry */

                char *list_s = RlistToString(*list);
                Log(LOG_LEVEL_DEBUG, "Flattened slist: %s", list_s);
                free(list_s);
            }
        }
    }
}
Exemplo n.º 22
0
// Below test relies on the ordering items in RB tree which is strongly
// related to the hash function used.
static void test_iterate_indices_ordering_related(void)
{
    VariableTable *t = ReferenceTable();
    
    {    
        VarRef *ref = VarRefParse("default:scope1.array");
        VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref);

        Variable *v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(1, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);

        v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(2, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);
        assert_string_equal("three", v->ref->indices[1]);
        
        v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(2, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);
        assert_string_equal("four", v->ref->indices[1]);

        v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(1, v->ref->num_indices);
        assert_string_equal("one", v->ref->indices[0]);

        assert_false(VariableTableIteratorNext(iter) != NULL);

        VariableTableIteratorDestroy(iter);
        VarRefDestroy(ref);
    }

    {
        VarRef *ref = VarRefParse("default:scope1.array[two]");
        VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref);

        Variable *v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(1, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);
        
        v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(2, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);
        assert_string_equal("three", v->ref->indices[1]);

        v = VariableTableIteratorNext(iter);
        assert_true(v != NULL);
        assert_int_equal(2, v->ref->num_indices);
        assert_string_equal("two", v->ref->indices[0]);
        assert_string_equal("four", v->ref->indices[1]);

        assert_false(VariableTableIteratorNext(iter) != NULL);

        VariableTableIteratorDestroy(iter);
        VarRefDestroy(ref);
    }

    VariableTableDestroy(t);
}
Exemplo n.º 23
0
static void test_map_iterators_from_rval_naked_list_var_namespace(void **state)
{
    EvalContext *ctx = *state;
    Policy *p = PolicyNew();
    Bundle *bp = PolicyAppendBundle(p, "ns", "scope", "agent", NULL, NULL);

    {
        Rlist *list = NULL;
        RlistAppend(&list, "jersey", RVAL_TYPE_SCALAR);
        VarRef *lval = VarRefParse("ns:scope.jwow");

        EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL);

        VarRefDestroy(lval);
        RlistDestroy(list);
    }

    EvalContextStackPushBundleFrame(ctx, bp, NULL, false);

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        MapIteratorsFromRval(ctx, bp, (Rval) { "${jwow}", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        char *str = xstrdup("${scope.jwow}");
        MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_string_equal("${scope#jwow}", str);
        free(str);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("scope#jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        char *str = xstrdup("${ns:scope.jwow}");
        MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_string_equal("${ns*scope#jwow}", str);
        free(str);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("ns*scope#jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    EvalContextStackPopFrame(ctx);
    PolicyDestroy(p);
}
Exemplo n.º 24
0
DataType StringDataType(EvalContext *ctx, const char *string)
{
    DataType dtype;
    Rval rval;
    int islist = false;
    char var[CF_BUFSIZE];

/*-------------------------------------------------------
What happens if we embed vars in a literal string
       "$(list)withending" - a list?
       "$(list1)$(list2)"  - not a simple list
Disallow these manual concatenations as ambiguous.
Demand this syntax to work around

vars:

   "listvar" slist => EmbellishList("prefix$(list)suffix");
---------------------------------------------------------*/

    var[0] = '\0';

    if (*string == '$')
    {
        if (ExtractInnerCf3VarString(string, var))
        {
            if (!IsExpandable(var))
            {
                VarRef *ref = VarRefParse(var);

                if (EvalContextVariableGet(ctx, ref, &rval, &dtype))
                {
                    if (rval.type == RVAL_TYPE_LIST)
                    {
                        if (!islist)
                        {
                            islist = true;
                        }
                        else
                        {
                            islist = false;
                        }
                    }
                }

                VarRefDestroy(ref);
            }

            if (strlen(var) == strlen(string))
            {
                /* Can trust variables own datatype  */
                return dtype;
            }
            else
            {
                /* Must force non-pure substitution to be generic type CF_SCALAR.cf_str */
                return DATA_TYPE_STRING;
            }
        }
    }

    return DATA_TYPE_STRING;
}
Exemplo n.º 25
0
Arquivo: expand.c Projeto: tzz/core
static void ExpandAndMapIteratorsFromScalar(EvalContext *ctx, const Bundle *bundle, char *string, size_t length,
                                            int level, Rlist **scalars, Rlist **lists,
                                            Rlist **containers, Rlist **full_expansion)
{
    assert(string);
    if (!string)
    {
        return;
    }

    Buffer *value = BufferNew();

    for (size_t i = 0; i < length; i++)
    {
        const char *sp = string + i;

        Rlist *tmp_list = NULL;
        BufferZero(value);
        if (ExtractScalarPrefix(value, sp, length - i))
        {
            if (full_expansion)
            {
                RlistConcatInto(&tmp_list, *full_expansion, BufferData(value));
                RlistDestroy(*full_expansion);
                *full_expansion = tmp_list;
                tmp_list = NULL;
            }

            sp += BufferSize(value);
            i += BufferSize(value);

            BufferZero(value);

            if (i >= length)
            {
                break;
            }
        }

        if (*sp == '$')
        {
            BufferZero(value);
            ExtractScalarReference(value, sp, length - i, true);
            if (BufferSize(value) > 0)
            {
                Rlist *inner_expansion = NULL;
                Rlist *exp = NULL;
                int success = 0;

                VarRef *ref = VarRefParse(BufferData(value));

                int increment = BufferSize(value) - 1 + 3;

                // Handle any embedded variables
                char *substring = string + i + 2;
                ExpandAndMapIteratorsFromScalar(ctx, bundle, substring, BufferSize(value), level+1, scalars, lists, containers, &inner_expansion);

                for (exp = inner_expansion; exp != NULL; exp = exp->next)
                {
                    // If a list is non-local, i.e. $(bundle.var), map it to local $(bundle#var)

                    // NB without modifying variables as we map them, it's not
                    // possible to handle remote lists referenced by a variable
                    // scope. For example:
                    //  scope => "test."; var => "somelist"; $($(scope)$(var)) fails
                    //  varname => "test.somelist"; $($(varname)) also fails
                    // TODO Unless the consumer handles it?

                    const char *inner_ref_str = RlistScalarValue(exp);
                    VarRef *inner_ref = VarRefParseFromBundle(inner_ref_str, bundle);

                    // var is the expanded name of the variable in its native context
                    // finalname will be the mapped name in the local context "this."

                    DataType value_type = DATA_TYPE_NONE;
                    const void *value = EvalContextVariableGet(ctx, inner_ref, &value_type);
                    if (value)
                    {
                        char *mangled_inner_ref = xstrdup(inner_ref_str);
                        MangleVarRefString(mangled_inner_ref, strlen(mangled_inner_ref));

                        success++;
                        switch (DataTypeToRvalType(value_type))
                        {
                        case RVAL_TYPE_LIST:
                            if (level > 0)
                            {
                                RlistPrependScalarIdemp(lists, mangled_inner_ref);
                            }
                            else
                            {
                                RlistAppendScalarIdemp(lists, mangled_inner_ref);
                            }

                            if (full_expansion)
                            {
                                for (const Rlist *rp = value; rp != NULL; rp = rp->next)
                                {
                                    // append each slist item to each of full_expansion
                                    RlistConcatInto(&tmp_list, *full_expansion, RlistScalarValue(rp));
                                }
                            }
                            break;

                        case RVAL_TYPE_SCALAR:
                            RlistAppendScalarIdemp(scalars, mangled_inner_ref);

                            if (full_expansion)
                            {
                                // append the scalar value to each of full_expansion
                                RlistConcatInto(&tmp_list, *full_expansion, value);
                            }
                            break;

                        case RVAL_TYPE_CONTAINER:
                            if (level > 0)
                            {
                                RlistPrependScalarIdemp(containers, mangled_inner_ref);
                            }
                            else
                            {
                                RlistAppendScalarIdemp(containers, mangled_inner_ref);
                            }
                            break;

                        case RVAL_TYPE_FNCALL:
                        case RVAL_TYPE_NOPROMISEE:
                            break;
                        }

                        free(mangled_inner_ref);
                    }

                    VarRefDestroy(inner_ref);
                }
                RlistDestroy(inner_expansion);

                if (full_expansion)
                {
                    RlistDestroy(*full_expansion);
                    *full_expansion = tmp_list;
                    tmp_list = NULL;
                }

                // No need to map this.* even though it's technically qualified
                if (success && IsQualifiedVariable(BufferData(value)) && strcmp(ref->scope, "this") != 0)
                {
                    char *dotpos = strchr(substring, '.');
                    if (dotpos)
                    {
                        *dotpos = CF_MAPPEDLIST;    // replace '.' with '#'
                    }

                    if (strchr(BufferData(value), ':'))
                    {
                        char *colonpos = strchr(substring, ':');
                        if (colonpos)
                        {
                            *colonpos = '*';
                        }
                    }
                }

                VarRefDestroy(ref);

                sp += increment;
                i += increment;
            }
        }
    }

    BufferDestroy(value);
}
Exemplo n.º 26
0
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files)
{
    unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 };
    char hashbuffer[CF_HOSTKEY_STRING_SIZE] = { 0 };
    char hashprintbuffer[CF_BUFSIZE] = { 0 };

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

    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 *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));
            PolicyDestroy(policy);
            return NULL;
        }

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

    PolicyResolve(ctx, policy, config);

    DataType def_inputs_type = CF_DATA_TYPE_NONE;
    VarRef *inputs_ref = VarRefParse("def.augment_inputs");
    const void *def_inputs = EvalContextVariableGet(ctx, inputs_ref, &def_inputs_type);
    VarRefDestroy(inputs_ref);

    if (RVAL_TYPE_CONTAINER == DataTypeToRvalType(def_inputs_type) && NULL != def_inputs)
    {
        const JsonElement *el;
        JsonIterator iter = JsonIteratorInit((JsonElement*) def_inputs);
        while ((el = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true)))
        {
            char *input = JsonPrimitiveToString(el);

            Log(LOG_LEVEL_VERBOSE, "Loading augments from def.augment_inputs: %s", input);

            Rlist* inputs_rlist = NULL;
            RlistAppendScalar(&inputs_rlist, input);
            Policy *aux_policy = LoadPolicyInputFiles(ctx, config, inputs_rlist,
                                                      parsed_files_and_checksums, failed_files);
            if (aux_policy)
            {
                policy = PolicyMerge(policy, aux_policy);
            }

            RlistDestroy(inputs_rlist);
            free(input);
        }
    }

    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;
}
Exemplo n.º 27
0
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    Rlist *prev = NULL, *next;
    for (Rlist *rp = *list; rp != NULL; rp = next)
    {
        next = rp->next;
        if (rp->val.type != RVAL_TYPE_SCALAR)
        {
            prev = rp;
            continue;
        }

        char naked[CF_BUFSIZE] = "";
        if (IsNakedVar(RlistScalarValue(rp), '@'))
        {
            GetNaked(naked, RlistScalarValue(rp));

            if (!IsExpandable(naked))
            {
                VarRef *ref = VarRefParse(naked);
                DataType value_type = CF_DATA_TYPE_NONE;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value)
                {
                    switch (DataTypeToRvalType(value_type))
                    {
                    case RVAL_TYPE_LIST:
                        {
                            RlistDestroyEntry(list, rp);

                            for (const Rlist *srp = value; srp != NULL; srp = srp->next)
                            {
                                Rlist *nrp = xmalloc(sizeof(Rlist));
                                nrp->val = RvalCopy(srp->val);
                                nrp->next = next;

                                if (prev)
                                {
                                    prev->next = nrp;
                                }
                                else
                                {
                                    *list = nrp;
                                }

                                prev = nrp;
                            }
                        }
                        continue;

                    default:
                        Log(LOG_LEVEL_WARNING, "Attempted to dereference variable '%s' using @ but variable did not resolve to a list",
                            RlistScalarValue(rp));
                        break;
                    }
                }
            }
        }

        prev = rp;
    }
}
Exemplo n.º 28
0
static void test_load(void)
{
    GenericAgentConfig *agent_config = GenericAgentConfigNewDefault(AGENT_TYPE_EXECUTOR);
    ExecConfig *c = ExecConfigNewDefault(true, "host", "ip");

    assert_true(c->scheduled_run);
    assert_string_equal("host", c->fq_name);
    assert_string_equal("ip", c->ip_address);

    TestCheckConfigIsDefault(c);

    EvalContext *ctx = EvalContextNew();
    {
        VarRef *lval = VarRefParse("g.host");
        EvalContextVariablePut(ctx, lval, "snookie", DATA_TYPE_STRING, NULL);
        VarRefDestroy(lval);
    }

    // provide a full body executor control and check that all options are collected
    {
        Policy *p = LoadPolicy("body_executor_control_full.cf");
        PolicyResolve(ctx, p, agent_config);

        ExecConfigUpdate(ctx, p, c);

        assert_true(c->scheduled_run);
        assert_string_equal("host", c->fq_name);
        assert_string_equal("ip", c->ip_address);

        assert_int_equal(120, c->agent_expireafter);
        assert_string_equal("/bin/echo", c->exec_command);
        assert_string_equal("LOG_LOCAL6",c->log_facility);
        assert_string_equal("*****@*****.**",c->mail_from_address);
        assert_int_equal(50, c->mail_max_lines);
        assert_string_equal("localhost", c->mail_server);
        assert_string_equal("*****@*****.**",c->mail_to_address);
        assert_string_equal("Test [localhost/127.0.0.1]",c->mail_subject);

        // splay time hard to test (pseudo random)

        assert_int_equal(2, StringSetSize(c->schedule));
        assert_true(StringSetContains(c->schedule, "Min00_05"));
        assert_true(StringSetContains(c->schedule, "Min05_10"));

        PolicyDestroy(p);
    }

    // provide a small policy and check that missing settings are being reverted to default
    {
        {
            Policy *p = LoadPolicy("body_executor_control_agent_expireafter_only.cf");
            PolicyResolve(ctx, p, agent_config);

            ExecConfigUpdate(ctx, p, c);

            assert_true(c->scheduled_run);
            assert_string_equal("host", c->fq_name);
            assert_string_equal("ip", c->ip_address);

            assert_int_equal(121, c->agent_expireafter);

            // rest should be default
            assert_string_equal("", c->exec_command);
            assert_string_equal("LOG_USER",c->log_facility);
            assert_string_equal("",c->mail_from_address);
            assert_int_equal(30, c->mail_max_lines);
            assert_string_equal("", c->mail_server);
            assert_string_equal("",c->mail_to_address);
            assert_string_equal("",c->mail_subject);
            assert_int_equal(0, c->splay_time);

            assert_int_equal(12, StringSetSize(c->schedule));

            PolicyDestroy(p);
        }
    }

    EvalContextDestroy(ctx);
    GenericAgentConfigDestroy(agent_config);

}