Beispiel #1
0
static void test_sort(void)
{
    Seq *seq = SeqNew(5, NULL);

    size_t one = 1;
    size_t two = 2;
    size_t three = 3;
    size_t four = 4;
    size_t five = 5;

    SeqAppend(seq, &three);
    SeqAppend(seq, &two);
    SeqAppend(seq, &five);
    SeqAppend(seq, &one);
    SeqAppend(seq, &four);

    SeqSort(seq, CompareNumbers, NULL);

    assert_int_equal(seq->data[0], &one);
    assert_int_equal(seq->data[1], &two);
    assert_int_equal(seq->data[2], &three);
    assert_int_equal(seq->data[3], &four);
    assert_int_equal(seq->data[4], &five);

    SeqDestroy(seq);
}
Beispiel #2
0
// TODO: should be replaced by something not complected with loading
static void ShowContext(EvalContext *ctx)
{
    Seq *hard_contexts = SeqNew(1000, NULL);
    Seq *soft_contexts = SeqNew(1000, NULL);

    {
        ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true);
        Class *cls = NULL;
        while ((cls = ClassTableIteratorNext(iter)))
        {
            if (cls->is_soft)
            {
                SeqAppend(soft_contexts, cls->name);
            }
            else
            {
                SeqAppend(hard_contexts, cls->name);
            }
        }

        ClassTableIteratorDestroy(iter);
    }

    SeqSort(soft_contexts, (SeqItemComparator)strcmp, NULL);
    SeqSort(hard_contexts, (SeqItemComparator)strcmp, NULL);

    Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");

    {
        Log(LOG_LEVEL_VERBOSE, "BEGIN Discovered hard classes:");

        for (size_t i = 0; i < SeqLength(hard_contexts); i++)
        {
            const char *context = SeqAt(hard_contexts, i);
            Log(LOG_LEVEL_VERBOSE, "C: discovered hard class %s", context);
        }

        Log(LOG_LEVEL_VERBOSE, "END Discovered hard classes");
    }

    Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");

    if (SeqLength(soft_contexts))
    {
        Log(LOG_LEVEL_VERBOSE, "BEGIN initial soft classes:");

        for (size_t i = 0; i < SeqLength(soft_contexts); i++)
        {
            const char *context = SeqAt(soft_contexts, i);
            Log(LOG_LEVEL_VERBOSE, "C: added soft class %s", context);
        }

        Log(LOG_LEVEL_VERBOSE, "END initial soft classes");
    }

    SeqDestroy(hard_contexts);
    SeqDestroy(soft_contexts);
}
Beispiel #3
0
static bool AppendIterationVariable(PromiseIterator *iter, CfAssoc *new_var)
{
    Rlist *state = RvalRlistValue(new_var->rval);
    // move to the first non-null value
    state = FirstRealEntry(state);
    SeqAppend(iter->vars, new_var);
    SeqAppend(iter->var_states, state);
    return state != NULL;
}
Beispiel #4
0
static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

    for (size_t i = 0; i < SeqLength(pp->conlist); i++)
    {
        const Constraint *cp = SeqAt(pp->conlist, i);

        // ensure: if call and callee are resolved, then they have matching arity
        if (StringSafeEqual(cp->lval, "usebundle"))
        {
            if (cp->rval.type == RVAL_TYPE_FNCALL)
            {
                const FnCall *call = (const FnCall *)cp->rval.item;
                const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", call->name);
                if (!callee)
                {
                    callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", call->name);
                }

                if (callee)
                {
                    if (RlistLen(call->args) != RlistLen(callee->args))
                    {
                        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp,
                                                         POLICY_ERROR_METHODS_BUNDLE_ARITY,
                                                         call->name, RlistLen(callee->args), RlistLen(call->args)));
                        success = false;
                    }
                }
            }
        }
    }
    return success;
}
Beispiel #5
0
static void ShowContextsFormatted(EvalContext *ctx)
{
    ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true);
    Class *cls = NULL;

    Seq *seq = SeqNew(1000, free);

    while ((cls = ClassTableIteratorNext(iter)))
    {
        char *class_name = ClassRefToString(cls->ns, cls->name);
        StringSet *tagset = EvalContextClassTags(ctx, cls->ns, cls->name);
        Buffer *tagbuf = StringSetToBuffer(tagset, ',');

        char *line;
        xasprintf(&line, "%-60s %-40s", class_name, BufferData(tagbuf));
        SeqAppend(seq, line);

        BufferDestroy(tagbuf);
        free(class_name);
    }

    SeqSort(seq, (SeqItemComparator)strcmp, NULL);

    printf("%-60s %-40s\n", "Class name", "Meta tags");

    for (size_t i = 0; i < SeqLength(seq); i++)
    {
        const char *context = SeqAt(seq, i);
        printf("%s\n", context);
    }

    SeqDestroy(seq);

    ClassTableIteratorDestroy(iter);
}
Beispiel #6
0
void SeqAppendSeq(Seq *seq, const Seq *items)
{
    for (size_t i = 0; i < SeqLength(items); i++)
    {
        SeqAppend(seq, SeqAt(items, i));
    }
}
Beispiel #7
0
static void AugmentMountInfo(Seq *list, char *host, char *source, char *mounton, char *options)
{
    Mount *entry = xcalloc(1, sizeof(Mount));

    if (host)
    {
        entry->host = xstrdup(host);
    }

    if (source)
    {
        entry->source = xstrdup(source);
    }

    if (mounton)
    {
        entry->mounton = xstrdup(mounton);
    }

    if (options)
    {
        entry->options = xstrdup(options);
    }

    SeqAppend(list, entry);
}
Beispiel #8
0
static void ShowVariablesFormatted(EvalContext *ctx)
{
    VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL);
    Variable *v = NULL;

    Seq *seq = SeqNew(2000, free);

    while ((v = VariableTableIteratorNext(iter)))
    {
        char *varname = VarRefToString(v->ref, true);

        Writer *w = StringWriter();

        switch (DataTypeToRvalType(v->type))
        {
        case RVAL_TYPE_CONTAINER:
            JsonWriteCompact(w, RvalContainerValue(v->rval));
            break;

        default:
            RvalWrite(w, v->rval);
        }

        const char *var_value;
        if (StringIsPrintable(StringWriterData(w)))
        {
            var_value = StringWriterData(w);
        }
        else
        {
            var_value = "<non-printable>";
        }


        StringSet *tagset = EvalContextVariableTags(ctx, v->ref);
        Buffer *tagbuf = StringSetToBuffer(tagset, ',');

        char *line;
        xasprintf(&line, "%-40s %-60s %-40s", varname, var_value, BufferData(tagbuf));

        SeqAppend(seq, line);

        BufferDestroy(tagbuf);
        WriterClose(w);
        free(varname);
    }

    SeqSort(seq, (SeqItemComparator)strcmp, NULL);

    printf("%-40s %-60s %-40s\n", "Variable name", "Variable value", "Meta tags");

    for (size_t i = 0; i < SeqLength(seq); i++)
    {
        const char *variable = SeqAt(seq, i);
        printf("%s\n", variable);
    }

    SeqDestroy(seq);
    VariableTableIteratorDestroy(iter);
}
Beispiel #9
0
static bool AclCheck(const Body *body, Seq *errors)
{
    bool success = true;

    if (BodyHasConstraint(body, "acl_directory_inherit")
        && BodyHasConstraint(body, "acl_default"))
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both acl_directory_inherit and acl_default. Please use acl_default only"));
        success = false;
    }
    if (BodyHasConstraint(body, "specify_inherit_aces")
        && BodyHasConstraint(body, "specify_default_aces"))
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both specify_inherit_aces and specify_default_aces. Please use specify_default_aces only"));
        success = false;
    }

    return success;
}
Beispiel #10
0
static bool VarsParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

    if (!CheckIdentifierNotPurelyNumerical(pp->promiser))
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp,
                                         POLICY_ERROR_VARS_PROMISER_NUMERICAL));
        success = false;
    }

    if (!CheckParseVariableName(pp->promiser))
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp,
                                         POLICY_ERROR_VARS_PROMISER_RESERVED));
        success = false;
    }

    // ensure variables are declared with only one type.
    {
        char *data_type = NULL;

        for (size_t i = 0; i < SeqLength(pp->conlist); i++)
        {
            Constraint *cp = SeqAt(pp->conlist, i);

            if (DataTypeFromString(cp->lval) != CF_DATA_TYPE_NONE)
            {
                if (data_type != NULL)
                {
                    SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp,
                                                     POLICY_ERROR_VARS_CONSTRAINT_DUPLICATE_TYPE,
                                                     data_type, cp->lval));
                    success = false;
                }
                data_type = cp->lval;
            }
        }
    }

    return success;
}
Beispiel #11
0
static void test_len(void)
{
    Seq *seq = SeqNew(5, NULL);

    size_t one = 1;
    size_t two = 2;
    size_t three = 3;
    size_t four = 4;
    size_t five = 5;

    SeqAppend(seq, &three);
    SeqAppend(seq, &two);
    SeqAppend(seq, &five);
    SeqAppend(seq, &one);
    SeqAppend(seq, &four);

    assert_int_equal(SeqLength(seq),5);

    SeqDestroy(seq);
}
Beispiel #12
0
static bool ClassesParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

    if (!CheckIdentifierNotPurelyNumerical(pp->promiser))
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp,
                                         POLICY_ERROR_CLASSES_PROMISER_NUMERICAL));
        success = false;
    }

    return success;
}
Beispiel #13
0
static Seq *SequenceCreateRange(size_t initialCapacity, size_t start, size_t end)
{
    Seq *seq = SeqNew(initialCapacity, free);

    for (size_t i = start; i <= end; i++)
    {
        size_t *item = xmalloc(sizeof(size_t));

        *item = i;
        SeqAppend(seq, item);
    }

    return seq;
}
Beispiel #14
0
static void MailFilterFill(const char *str,
                           Seq **output, Seq **output_regex,
                           const char *filter_type)
{
    const char *errorstr;
    int erroffset;
    pcre *rx = pcre_compile(str,
                            PCRE_MULTILINE | PCRE_DOTALL | PCRE_ANCHORED,
                            &errorstr, &erroffset, NULL);
    if (!rx)
    {
        Log(LOG_LEVEL_ERR,
            "Invalid regular expression in mailfilter_%s: "
            "pcre_compile() '%s' in expression '%s' (offset: %d). "
            "Ignoring expression.", filter_type,
            errorstr, str, erroffset);
    }
    else
    {
        SeqAppend(*output, xstrdup(str));
        SeqAppend(*output_regex, rx);
    }
}
Beispiel #15
0
static void PopulateAvailable(const char *arg)
{
    Package *p = DeserializePackage(arg);
    PackagePattern *pattern = MatchSame(p);

    if (SeqLength(FindPackages(AVAILABLE_PACKAGES_FILE_NAME, pattern)) > 0)
    {
        fprintf(stderr, "Skipping already available package %s\n", SerializePackage(p));
        return;
    }

    Seq *available_packages = ReadPackageEntries(AVAILABLE_PACKAGES_FILE_NAME);

    SeqAppend(available_packages, p);
    SavePackages(AVAILABLE_PACKAGES_FILE_NAME, available_packages);
}
Beispiel #16
0
static bool ActionCheck(const Body *body, Seq *errors)
{
    bool success = true;

    if (BodyHasConstraint(body, "log_kept")
        || BodyHasConstraint(body, "log_repaired")
        || BodyHasConstraint(body, "log_failed"))
    {
        if (!BodyHasConstraint(body, "log_string"))
        {
            SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An action body with log_kept, log_repaired or log_failed is required to have a log_string attribute"));
            success = false;
        }
    }

    return success;
}
Beispiel #17
0
static Seq *FindPackages(const char *database_filename, PackagePattern *pattern)
{
    Seq *db = ReadPackageEntries(database_filename);
    Seq *matching = SeqNew(1000, NULL);

    for (size_t i = 0; i < SeqLength(db); i++)
    {
        Package *package = SeqAt(db, i);

        if (MatchPackage(pattern, package))
        {
            SeqAppend(matching, package);
        }
    }

    return matching;
}
Beispiel #18
0
static void test_append(void)
{
    Seq *seq = SeqNew(2, free);

    for (size_t i = 0; i < 1000; i++)
    {
        SeqAppend(seq, xstrdup("snookie"));
    }

    assert_int_equal(seq->length, 1000);

    for (size_t i = 0; i < 1000; i++)
    {
        assert_string_equal(seq->data[i], "snookie");
    }

    SeqDestroy(seq);
}
Beispiel #19
0
static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

    for (size_t i = 0; i < SeqLength(pp->conlist); i++)
    {
        const Constraint *cp = SeqAt(pp->conlist, i);

        // ensure: if call and callee are resolved, then they have matching arity
        if (StringSafeEqual(cp->lval, "usebundle"))
        {
            if (cp->rval.type == RVAL_TYPE_FNCALL)
            {
                // HACK: exploiting the fact that class-references and call-references are similar
                FnCall *call = RvalFnCallValue(cp->rval);
                ClassRef ref = ClassRefParse(call->name);
                if (!ClassRefIsQualified(ref))
                {
                    ClassRefQualify(&ref, PromiseGetNamespace(pp));
                }

                const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "agent", ref.name);
                if (!callee)
                {
                    callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "common", ref.name);
                }

                ClassRefDestroy(ref);

                if (callee)
                {
                    if (RlistLen(call->args) != RlistLen(callee->args))
                    {
                        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp,
                                                         POLICY_ERROR_METHODS_BUNDLE_ARITY,
                                                         call->name, RlistLen(callee->args), RlistLen(call->args)));
                        success = false;
                    }
                }
            }
        }
    }
    return success;
}
Beispiel #20
0
bool MustacheRender(Buffer *out, const char *input, const JsonElement *hash)
{
    char delim_start[MUSTACHE_MAX_DELIM_SIZE] = "{{";
    size_t delim_start_len = strlen(delim_start);

    char delim_end[MUSTACHE_MAX_DELIM_SIZE] = "}}";
    size_t delim_end_len = strlen(delim_end);

    Seq *hash_stack = SeqNew(10, NULL);
    SeqAppend(hash_stack, (JsonElement*)hash);

    bool success = Render(out, input, input,
                         hash_stack,
                         delim_start, &delim_start_len,
                         delim_end, &delim_end_len,
                         false, NULL, NULL);

    SeqDestroy(hash_stack);

    return success;
}
Beispiel #21
0
static Seq *ReadPackageEntries(const char *database_filename)
{
    FILE *packages_file = fopen(database_filename, "r");
    Seq *packages = SeqNew(1000, NULL);

    if (packages_file != NULL)
    {
        char serialized_package[MAX_PACKAGE_ENTRY_LENGTH];

        while (fscanf(packages_file, "%s\n", serialized_package) != EOF)
        {
            Package *package = DeserializePackage(serialized_package);

            SeqAppend(packages, package);
        }

        fclose(packages_file);
    }

    return packages;
}
Beispiel #22
0
static bool AccessParseTreeCheck(const Promise *pp, Seq *errors)
{
    bool success = true;

    bool isResourceType = false;
    bool isReportDataSelect = false;
    Constraint *data_select_const = NULL;

    for (size_t i = 0; i <SeqLength(pp->conlist); i++)
    {
        Constraint *con = SeqAt(pp->conlist, i);

        if (StringSafeCompare("resource_type", con->lval) == 0)
        {
            if (con->rval.type == RVAL_TYPE_SCALAR)
            {
                if (StringSafeCompare("query", (char*)con->rval.item) == 0)
                {
                    isResourceType = true;
                }
            }
        }
        else if (StringSafeCompare("report_data_select", con->lval) == 0)
        {
            data_select_const = con;
            isReportDataSelect = true;
        }

    }

    if (isReportDataSelect && !isResourceType)
    {
        SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, data_select_const,
                                         POLICY_ERROR_WRONG_RESOURCE_FOR_DATA_SELECT));
        success = false;
    }

    return success;
}
Beispiel #23
0
static void AddPackage(PackagePattern *pattern)
{
    fprintf(stderr, "Trying to install all packages matching pattern %s\n", SerializePackagePattern(pattern));

    Seq *matching_available = FindPackages(AVAILABLE_PACKAGES_FILE_NAME, pattern);

    if (SeqLength(matching_available) == 0)
    {
        fprintf(stderr, "Unable to find any package matching %s\n", SerializePackagePattern(pattern));
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < SeqLength(matching_available); i++)
    {
        Package *p = SeqAt(matching_available, i);

        PackagePattern *pat = MatchAllVersions(p);

        if (SeqLength(FindPackages(INSTALLED_PACKAGES_FILE_NAME, pat)) > 0)
        {
            fprintf(stderr, "Package %s is already installed.\n", SerializePackage(p));
            exit(EXIT_FAILURE);
        }
    }

    Seq *installed_packages = ReadPackageEntries(INSTALLED_PACKAGES_FILE_NAME);

    for (size_t i = 0; i < SeqLength(matching_available); i++)
    {
        Package *p = SeqAt(matching_available, i);

        SeqAppend(installed_packages, p);
        fprintf(stderr, "Successfully installed package %s\n", SerializePackage(p));
    }

    SavePackages(INSTALLED_PACKAGES_FILE_NAME, installed_packages);
    exit(EXIT_SUCCESS);
}
Beispiel #24
0
static JsonElement *BundleTypesToJson(void)
{
 JsonElement *bundle_types = JsonObjectCreate(50);

 Seq *common_promise_types = SeqNew(50, free);

 for (int module_index = 0; module_index < CF3_MODULES; module_index++)
    {
    for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++)
       {
       const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index];

       // skip global constraints
       if (strcmp("*", promise_type_syntax->promise_type) == 0)
          {
          continue;
          }

       // collect common promise types to be appended at the end
       if (strcmp("*", promise_type_syntax->bundle_type) == 0)
          {
          SeqAppend(common_promise_types, xstrdup(promise_type_syntax->promise_type));
          continue;
          }

       if (promise_type_syntax->status == SYNTAX_STATUS_REMOVED)
          {
          continue;
          }

       JsonElement *bundle_type = JsonObjectGet(bundle_types, promise_type_syntax->bundle_type);
       if (!bundle_type)
          {
          bundle_type = JsonBundleTypeNew();
          JsonObjectAppendObject(bundle_types, promise_type_syntax->bundle_type, bundle_type);
          }
       assert(bundle_type);

       JsonElement *promise_types = JsonObjectGet(bundle_type, "promiseTypes");
       assert(promise_types);

       JsonArrayAppendString(promise_types, promise_type_syntax->promise_type);
       }
    }

 // Append the common bundle, which has only common promise types, but is not declared in syntax
 {
 JsonElement *bundle_type = JsonBundleTypeNew();
 JsonObjectAppendObject(bundle_types, "common", bundle_type);
 }

 JsonIterator it = JsonIteratorInit(bundle_types);
 const char *bundle_type = NULL;
 while ((bundle_type = JsonIteratorNextKey(&it)))
    {
    JsonElement *promise_types = JsonObjectGetAsArray(JsonObjectGetAsObject(bundle_types, bundle_type), "promiseTypes");
    for (int i = 0; i < SeqLength(common_promise_types); i++)
       {
       const char *common_promise_type = SeqAt(common_promise_types, i);
       JsonArrayAppendString(promise_types, common_promise_type);
       }
    }

 SeqDestroy(common_promise_types);
 return bundle_types;
}
Beispiel #25
0
bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx)
{
    StringMap *lastseen_db = LoadDatabaseToStringMap(dbid_lastseen);
    if (!lastseen_db)
    {
        return false;
    }
    MapIterator it = MapIteratorInit(lastseen_db->impl);
    MapKeyValue *item;

    Seq *hostkeys = SeqNew(100, free);
    while ((item = MapIteratorNext(&it)) != NULL)
    {
        char *key = item->key;
        /* Only look for "keyhost" entries */
        if (key[0] != 'k')
        {
            continue;
        }

        SeqAppend(hostkeys, xstrdup(key + 1));
    }
    for (int i = 0; i < SeqLength(hostkeys); ++i)
    {
        const char *hostkey = SeqAt(hostkeys, i);

        char keyhost_key[CF_BUFSIZE];
        snprintf(keyhost_key, CF_BUFSIZE, "k%s", hostkey);
        char *address = NULL;
        address = (char*)StringMapGet(lastseen_db, keyhost_key);
        if (!address)
        {
            Log(LOG_LEVEL_ERR, "Failed to read address for key '%s'.", hostkey);
            continue;
        }

        char incoming_key[CF_BUFSIZE];
        snprintf(incoming_key, CF_BUFSIZE, "qi%s", hostkey);
        KeyHostSeen *incoming = NULL;
        incoming = (KeyHostSeen*)StringMapGet(lastseen_db, incoming_key);
        if (incoming)
        {
            if (!(*callback)(hostkey, address, true, incoming, ctx))
            {
                break;
            }
        }

        char outgoing_key[CF_BUFSIZE];
        snprintf(outgoing_key, CF_BUFSIZE, "qo%s", hostkey);
        KeyHostSeen *outgoing = NULL;
        outgoing = (KeyHostSeen*)StringMapGet(lastseen_db, outgoing_key);
        if (outgoing)
        {
            if (!(*callback)(hostkey, address, false, outgoing, ctx))
            {
                break;
            }
        }
    }

    StringMapDestroy(lastseen_db);
    SeqDestroy(hostkeys);

    return true;
}
Beispiel #26
0
static void ShowContext(EvalContext *ctx)
{
    {
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Hard classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Discovered hard classes:");
        }

        Seq *hard_contexts = SeqNew(1000, NULL);
        SetIterator it = EvalContextHeapIteratorHard(ctx);
        char *context = NULL;
        while ((context = SetIteratorNext(&it)))
        {
            if (!EvalContextHeapContainsNegated(ctx, context))
            {
                SeqAppend(hard_contexts, context);
            }
        }

        SeqSort(hard_contexts, (SeqItemComparator)strcmp, NULL);

        for (size_t i = 0; i < SeqLength(hard_contexts); i++)
        {
            const char *context = SeqAt(hard_contexts, i);

            WriterWriteF(w, " %s", context);
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            WriterClose(w);
        }


        SeqDestroy(hard_contexts);
    }

    {
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Additional classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Additional classes:");
        }

        Seq *soft_contexts = SeqNew(1000, NULL);
        SetIterator it = EvalContextHeapIteratorSoft(ctx);
        char *context = NULL;
        while ((context = SetIteratorNext(&it)))
        {
            if (!EvalContextHeapContainsNegated(ctx, context))
            {
                SeqAppend(soft_contexts, context);
            }
        }

        SeqSort(soft_contexts, (SeqItemComparator)strcmp, NULL);

        for (size_t i = 0; i < SeqLength(soft_contexts); i++)
        {
            const char *context = SeqAt(soft_contexts, i);
            WriterWriteF(w, " %s", context);
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            if (SeqLength(soft_contexts) > 0)
            {
                Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            }
            WriterClose(w);
        }
        SeqDestroy(soft_contexts);
    }

    {
        bool have_negated_classes = false;
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Negated classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Negated classes:");
        }

        StringSetIterator it = EvalContextHeapIteratorNegated(ctx);
        const char *context = NULL;
        while ((context = StringSetIteratorNext(&it)))
        {
            WriterWriteF(w, " %s", context);
            have_negated_classes = true;
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            if (have_negated_classes)
            {
                Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            }
            WriterClose(w);
        }
    }
}
Beispiel #27
0
static bool Render(Buffer *out, const char *start, const char *input, Seq *hash_stack,
                   char *delim_start, size_t *delim_start_len,
                   char *delim_end, size_t *delim_end_len,
                   bool skip_content,
                   const char *section,
                   const char **section_end)
{
    while (true)
    {
        if (!input)
        {
            Log(LOG_LEVEL_ERR, "Unexpected end to Mustache template");
            return false;
        }

        Mustache tag = NextTag(input, delim_start, *delim_start_len, delim_end, *delim_end_len);

        {
            const char *line_begin = NULL;
            const char *line_end = NULL;
            if (!IsTagTypeRenderable(tag.type) && IsTagStandalone(start, tag.begin, tag.end, &line_begin, &line_end))
            {
                RenderContent(out, input, line_begin - input, false, skip_content);
                input = line_end;
            }
            else
            {
                RenderContent(out, input, tag.begin - input, false, skip_content);
                input = tag.end;
            }
        }

        switch (tag.type)
        {
        case TAG_TYPE_ERR:
            return false;

        case TAG_TYPE_DELIM:
            if (!SetDelimiters(tag.content, tag.content_len,
                               delim_start, delim_start_len,
                               delim_end, delim_end_len))
            {
                return false;
            }
            continue;

        case TAG_TYPE_COMMENT:
            continue;

        case TAG_TYPE_NONE:
            return true;

        case TAG_TYPE_VAR_SERIALIZED:
        case TAG_TYPE_VAR_SERIALIZED_COMPACT:
        case TAG_TYPE_VAR_UNESCAPED:
        case TAG_TYPE_VAR:
            if (!skip_content)
            {
                if (tag.content_len > 0)
                {
                    if (!RenderVariable(out, tag.content, tag.content_len, tag.type, hash_stack))
                    {
                        return false;
                    }
                }
                else
                {
                    RenderContent(out, delim_start, *delim_start_len, false, false);
                    RenderContent(out, delim_end, *delim_end_len, false, false);
                }
            }
            continue;

        case TAG_TYPE_INVERTED:
        case TAG_TYPE_SECTION:
            {
                char *section = xstrndup(tag.content, tag.content_len);
                JsonElement *var = LookupVariable(hash_stack, tag.content, tag.content_len);
                SeqAppend(hash_stack, var);

                if (!var)
                {
                    const char *cur_section_end = NULL;
                    if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                skip_content || tag.type != TAG_TYPE_INVERTED, section, &cur_section_end))
                    {
                        free(section);
                        return false;
                    }
                    free(section);
                    input = cur_section_end;
                    continue;
                }

                switch (JsonGetElementType(var))
                {
                case JSON_ELEMENT_TYPE_PRIMITIVE:
                    switch (JsonGetPrimitiveType(var))
                    {
                    case JSON_PRIMITIVE_TYPE_BOOL:
                        {
                            bool skip = skip_content || (!JsonPrimitiveGetAsBool(var) ^ (tag.type == TAG_TYPE_INVERTED));

                            const char *cur_section_end = NULL;
                            if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                        skip, section, &cur_section_end))
                            {
                                free(section);
                                return false;
                            }
                            free(section);
                            input = cur_section_end;
                        }
                        continue;

                    default:
                        Log(LOG_LEVEL_WARNING, "Mustache sections can only take a boolean or a container (array or map) value, but section '%s' isn't getting one of those.",
                            section);
                        return false;
                    }
                    break;

                case JSON_ELEMENT_TYPE_CONTAINER:
                    switch (JsonGetContainerType(var))
                    {
                    case JSON_CONTAINER_TYPE_OBJECT:
                    case JSON_CONTAINER_TYPE_ARRAY:
                        if (JsonLength(var) > 0)
                        {
                            const char *cur_section_end = NULL;
                            for (size_t i = 0; i < JsonLength(var); i++)
                            {
                                JsonElement *child_hash = JsonAt(var, i);
                                SeqAppend(hash_stack, child_hash);


                                if (!Render(out, start, input,
                                            hash_stack,
                                            delim_start, delim_start_len, delim_end, delim_end_len,
                                            skip_content || tag.type == TAG_TYPE_INVERTED, section, &cur_section_end))
                                {
                                    free(section);
                                    return false;
                                }
                            }
                            input = cur_section_end;
                            free(section);
                        }
                        else
                        {
                            const char *cur_section_end = NULL;
                            if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len,
                                        tag.type != TAG_TYPE_INVERTED, section, &cur_section_end))
                            {
                                free(section);
                                return false;
                            }
                            free(section);
                            input = cur_section_end;
                        }
                        break;
                    }
                    break;
                }
            }
            continue;
        case TAG_TYPE_SECTION_END:
            if (!section)
            {
                char *varname = xstrndup(tag.content, tag.content_len);
                Log(LOG_LEVEL_WARNING, "Unknown section close in mustache template '%s'", varname);
                free(varname);
                return false;
            }
            else
            {
                SeqRemove(hash_stack, SeqLength(hash_stack) - 1);
                *section_end = input;
                return true;
            }
            break;

        default:
            assert(false);
            return false;
        }
    }

    assert(false);
}
Beispiel #28
0
static void EvalContextStackPushFrame(EvalContext *ctx, StackFrame *frame)
{
    SeqAppend(ctx->stack, frame);
}
Beispiel #29
0
static void *CFTestD_ServeReport(void *config_arg)
{
    CFTestD_Config *config = (CFTestD_Config *) config_arg;

    /* Set prefix for all Log()ging: */
    LoggingPrivContext *prior = LoggingPrivGetContext();
    LoggingPrivContext log_ctx = {
        .log_hook = LogAddPrefix,
        .param = config->address
    };
    LoggingPrivSetContext(&log_ctx);

    char *priv_key_path = NULL;
    char *pub_key_path = NULL;
    if (config->key_file != NULL)
    {
        priv_key_path = config->key_file;
        pub_key_path = xstrdup(priv_key_path);
        StringReplace(pub_key_path, strlen(pub_key_path) + 1,
                      "priv", "pub");
    }

    LoadSecretKeys(priv_key_path, pub_key_path, &(config->priv_key), &(config->pub_key));
    free(pub_key_path);

    char *report_file = config->report_file;

    if (report_file != NULL)
    {
        Log(LOG_LEVEL_NOTICE, "Got file argument: '%s'", report_file);
        if (!FileCanOpen(report_file, "r"))
        {
            Log(LOG_LEVEL_ERR,
                "Can't open file '%s' for reading",
                report_file);
            exit(EXIT_FAILURE);
        }

        Writer *contents = FileRead(report_file, SIZE_MAX, NULL);
        if (!contents)
        {
            Log(LOG_LEVEL_ERR, "Error reading report file '%s'", report_file);
            exit(EXIT_FAILURE);
        }

        size_t report_data_len = StringWriterLength(contents);
        config->report_data = StringWriterClose(contents);

        Seq *report = SeqNew(64, NULL);
        size_t report_len = 0;

        StringRef ts_ref = StringGetToken(config->report_data, report_data_len, 0, "\n");
        char *ts = (char *) ts_ref.data;
        *(ts + ts_ref.len) = '\0';
        SeqAppend(report, ts);

        /* start right after the newline after the timestamp header */
        char *position = ts + ts_ref.len + 1;
        char *report_line;
        size_t report_line_len;
        while (CFTestD_GetReportLine(position, &report_line, &report_line_len))
        {
            *(report_line + report_line_len) = '\0';
            SeqAppend(report, report_line);
            report_len += report_line_len;
            position = report_line + report_line_len + 1; /* there's an extra newline after each report_line */
        }

        config->report = report;
        config->report_len = report_len;

        Log(LOG_LEVEL_NOTICE,
            "Read %d bytes for report contents",
            config->report_len);

        if (config->report_len <= 0)
        {
            Log(LOG_LEVEL_ERR, "Report file contained no bytes");
            exit(EXIT_FAILURE);
        }
    }

    Log(LOG_LEVEL_INFO, "Starting server at %s...", config->address);
    fflush(stdout); // for debugging startup

    config->ret = CFTestD_StartServer(config);

    free(config->report_data);

    /* we don't really need to do this here because the process is about the
     * terminate, but it's a good way the cleanup actually works and doesn't
     * cause a segfault or something */
    ServerTLSDeInitialize(&(config->priv_key), &(config->pub_key), &(config->ssl_ctx));

    LoggingPrivSetContext(prior);

    return NULL;
}

static void HandleSignal(int signum)
{
    switch (signum)
    {
    case SIGTERM:
    case SIGINT:
        // flush all logging before process ends.
        fflush(stdout);
        fprintf(stderr, "Terminating...\n");
        TERMINATE = true;
        break;
    default:
        break;
    }
}

/**
 * @param ip_str string representation of an IPv4 address (the usual one, with
 *               4 octets separated by dots)
 * @return a new string representing the incremented IP address (HAS TO BE FREED)
 */
static char *IncrementIPaddress(const char *ip_str)
{
    uint32_t ip = (uint32_t) inet_addr(ip_str);
    if (ip == INADDR_NONE)
    {
        Log(LOG_LEVEL_ERR, "Failed to parse address: '%s'", ip_str);
        return NULL;
    }

    int step = 1;
    char *last_dot = strrchr(ip_str, '.');
    assert(last_dot != NULL);   /* the doc comment says there must be dots! */
    if (StringSafeEqual(last_dot + 1, "255"))
    {
        /* avoid the network address (ending with 0) */
        step = 2;
    }
    else if (StringSafeEqual(last_dot + 1, "254"))
    {
        /* avoid the broadcast address and the network address */
        step = 3;
    }

    uint32_t ip_num = ntohl(ip);
    ip_num += step;
    ip = htonl(ip_num);

    struct in_addr ip_struct;
    ip_struct.s_addr = ip;

    return xstrdup(inet_ntoa(ip_struct));
}
Beispiel #30
0
// If return_names is not set, only the captured data is returned (so
// for N captures you can expect N elements in the Sequence).
Seq *StringMatchCapturesWithPrecompiledRegex(const pcre *pattern, const char *str, const bool return_names)
{
    int captures;
    int res = pcre_fullinfo(pattern, NULL, PCRE_INFO_CAPTURECOUNT, &captures);
    if (res != 0)
    {
        return NULL;
    }

    // Get the table of named captures.
    unsigned char *name_table = NULL; // Doesn't have to be freed as per docs.
    int namecount = 0;
    int name_entry_size = 0;
    unsigned char *tabptr;

    pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMECOUNT, &namecount);

    const bool have_named_captures = (namecount > 0 && return_names);

    if (have_named_captures)
    {
        pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMETABLE, &name_table);
        pcre_fullinfo(pattern, NULL, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size);
    }

    int *ovector = xmalloc(sizeof(int) * (captures + 1) * 3);

    int result = pcre_exec(pattern, NULL, str, strlen(str),
                           0, 0, ovector, (captures + 1) * 3);

    if (result <= 0)
    {
        free(ovector);
        return NULL;
    }

    Seq *ret = SeqNew(captures + 1, BufferDestroy);
    for (int i = 0; i <= captures; ++i)
    {
        Buffer *capture = NULL;

        if (have_named_captures)
        {
            // The overhead of doing a nested name scan is negligible.
            tabptr = name_table;
            for (int namepos = 0; namepos < namecount; namepos++)
            {
                int n = (tabptr[0] << 8) | tabptr[1];
                if (n == i) // We found the position
                {
                    capture = BufferNewFrom(tabptr + 2, name_entry_size - 3);
                    break;
                }
                tabptr += name_entry_size;
            }
        }

        if (return_names)
        {
            if (NULL == capture)
            {
                capture = BufferNew();
                BufferAppendF(capture, "%zd", i);
            }

            SeqAppend(ret, capture);
        }

        Buffer *data = BufferNewFrom(str + ovector[2*i],
                                     ovector[2*i + 1] - ovector[2 * i]);
        Log(LOG_LEVEL_DEBUG, "StringMatchCaptures: return_names = %d, have_named_captures = %d, offset %d, name '%s', data '%s'", return_names, have_named_captures, i, capture == NULL ? "no_name" : BufferData(capture), BufferData(data));
        SeqAppend(ret, data);
    }

    free(ovector);
    return ret;
}