Example #1
0
void DeleteExpArgs(Rlist *args)
{

    RlistDestroy(args);

}
Example #2
0
bool ComparePackageVersionsInternal(const char *v1, const char *v2, PackageVersionComparator cmp)
{
    Rlist *rp_pr, *rp_in;

    int result = true;
    int break_loop = false;
    int cmp_result;
    int version_matched = false;

    Rlist *numbers_pr = NULL, *separators_pr = NULL;
    Rlist *numbers_in = NULL, *separators_in = NULL;

    ParsePackageVersion(CanonifyChar(v1, ','), &numbers_pr, &separators_pr);
    ParsePackageVersion(CanonifyChar(v2, ','), &numbers_in, &separators_in);

/* If the format of the version string doesn't match, we're already doomed */

    Log(LOG_LEVEL_VERBOSE, "Check for compatible versioning model in (%s,%s)", v1, v2);

    for (rp_pr = separators_pr, rp_in = separators_in; (rp_pr != NULL) && (rp_in != NULL);
         rp_pr = rp_pr->next, rp_in = rp_in->next)
    {
        if (strcmp(rp_pr->item, rp_in->item) != 0)
        {
            result = false;
            break;
        }

        if ((rp_pr->next == NULL) && (rp_in->next == NULL))
        {
            result = true;
            break;
        }
    }

    if (result)
    {
        Log(LOG_LEVEL_VERBOSE, "Verified that versioning models are compatible");
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE, "Versioning models for (%s,%s) were incompatible", v1, v2);
    }

    int version_equal = (strcmp(v2, v1) == 0);

    if (result)
    {
        for (rp_pr = numbers_pr, rp_in = numbers_in; (rp_pr != NULL) && (rp_in != NULL);
             rp_pr = rp_pr->next, rp_in = rp_in->next)
        {
            cmp_result = strcmp(rp_pr->item, rp_in->item);

            switch (cmp)
            {
            case PACKAGE_VERSION_COMPARATOR_EQ:
            case PACKAGE_VERSION_COMPARATOR_NONE:
                if (version_equal)
                {
                    version_matched = true;
                }
                break;
            case PACKAGE_VERSION_COMPARATOR_NEQ:
                if (!version_equal)
                {
                    version_matched = true;
                }
                break;
            case PACKAGE_VERSION_COMPARATOR_GT:
                if (cmp_result < 0)
                {
                    version_matched = true;
                }
                else if (cmp_result > 0)
                {
                    break_loop = true;
                }
                break;
            case PACKAGE_VERSION_COMPARATOR_LT:
                if (cmp_result > 0)
                {
                    version_matched = true;
                }
                else if (cmp_result < 0)
                {
                    break_loop = true;
                }
                break;
            case PACKAGE_VERSION_COMPARATOR_GE:
                if ((cmp_result < 0) || version_equal)
                {
                    version_matched = true;
                }
                else if (cmp_result > 0)
                {
                    break_loop = true;
                }
                break;
            case PACKAGE_VERSION_COMPARATOR_LE:
                if ((cmp_result > 0) || version_equal)
                {
                    version_matched = true;
                }
                else if (cmp_result < 0)
                {
                    break_loop = true;
                }
                break;
            default:
                break;
            }

            if ((version_matched == true) || break_loop)
            {
                rp_pr = NULL;
                rp_in = NULL;
                break;
            }
        }

        if (rp_pr != NULL)
        {
            if ((cmp == PACKAGE_VERSION_COMPARATOR_LT) || (cmp == PACKAGE_VERSION_COMPARATOR_LE))
            {
                version_matched = true;
            }
        }
        if (rp_in != NULL)
        {
            if ((cmp == PACKAGE_VERSION_COMPARATOR_GT) || (cmp == PACKAGE_VERSION_COMPARATOR_GE))
            {
                version_matched = true;
            }
        }
    }

    RlistDestroy(numbers_pr);
    RlistDestroy(numbers_in);
    RlistDestroy(separators_pr);
    RlistDestroy(separators_in);

    if (version_matched)
    {
        Log(LOG_LEVEL_VERBOSE, "Verified version constraint promise kept");
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE, "Versions did not match");
    }

    return version_matched;
}
Example #3
0
GenericAgentConfig *CheckOpts(int argc, char **argv)
{
    extern char *optarg;
    int optindex = 0;
    int c;
    GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON);

    while ((c = getopt_long(argc, argv, "dvnIf:D:N:VSrxMb:i:p:s:cg:hW:lC::", OPTIONS, &optindex)) != EOF)
    {
        switch ((char) c)
        {
        case 0:
            switch (optindex)
            {
            case PROMISES_OPTION_EVAL_FUNCTIONS:
                if (!optarg)
                {
                    optarg = "yes";
                }
                config->agent_specific.common.eval_functions = strcmp("yes", optarg) == 0;
                break;

            case PROMISES_OPTION_SHOW_CLASSES:
                if (!optarg)
                {
                    optarg = "yes";
                }
                config->agent_specific.common.show_classes = strcmp("yes", optarg) == 0;
                break;

            case PROMISES_OPTION_SHOW_VARIABLES:
                if (!optarg)
                {
                    optarg = "yes";
                }
                config->agent_specific.common.show_variables = strcmp("yes", optarg) == 0;
                break;

            default:
                break;
            }

        case 'l':
            LEGACY_OUTPUT = true;
            break;

        case 'c':
            config->check_runnable = true;
            break;

        case 'f':

            if (optarg && (strlen(optarg) < 5))
            {
                Log(LOG_LEVEL_ERR, " -f used but argument '%s' incorrect", optarg);
                exit(EXIT_FAILURE);
            }

            GenericAgentConfigSetInputFile(config, GetInputDir(), optarg);
            MINUSF = true;
            break;

        case 'd':
            LogSetGlobalLevel(LOG_LEVEL_DEBUG);
            break;

        case 'b':
            if (optarg)
            {
                Rlist *bundlesequence = RlistFromSplitString(optarg, ',');
                GenericAgentConfigSetBundleSequence(config, bundlesequence);
                RlistDestroy(bundlesequence);
            }
            break;

        case 'p':
            if (strcmp("none", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE;
            }
            else if (strcmp("cf", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF;
            }
            else if (strcmp("json", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON;
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Invalid policy output format: '%s'. Possible values are 'none', 'cf', 'json'", optarg);
                exit(EXIT_FAILURE);
            }
            break;

        case 's':
            if (strcmp("none", optarg) == 0)
            {
                break;
            }
            else if (strcmp("json", optarg) == 0)
            {
                JsonElement *json_syntax = SyntaxToJson();
                Writer *out = FileWriter(stdout);
                JsonWrite(out, json_syntax, 0);
                FileWriterDetach(out);
                JsonDestroy(json_syntax);
                exit(EXIT_SUCCESS);
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Invalid syntax description output format: '%s'. Possible values are 'none', 'json'", optarg);
                exit(EXIT_FAILURE);
            }
            break;

        case 'K':
            config->ignore_locks = true;
            break;

        case 'D':
            config->heap_soft = StringSetFromString(optarg, ',');
            break;

        case 'N':
            config->heap_negated = StringSetFromString(optarg, ',');
            break;

        case 'I':
            LogSetGlobalLevel(LOG_LEVEL_INFO);
            break;

        case 'v':
            LogSetGlobalLevel(LOG_LEVEL_VERBOSE);
            break;

        case 'n':
            DONTDO = true;
            config->ignore_locks = true;
            break;

        case 'V':
            {
                Writer *w = FileWriter(stdout);
                GenericAgentWriteVersion(w);
                FileWriterDetach(w);
            }
            exit(EXIT_SUCCESS);

        case 'h':
            {
                Writer *w = FileWriter(stdout);
                GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true);
                FileWriterDetach(w);
            }
            exit(EXIT_SUCCESS);

        case 'M':
            {
                Writer *out = FileWriter(stdout);
                ManPageWrite(out, "cf-promises", time(NULL),
                             CF_PROMISES_SHORT_DESCRIPTION,
                             CF_PROMISES_MANPAGE_LONG_DESCRIPTION,
                             OPTIONS, HINTS,
                             true);
                FileWriterDetach(out);
                exit(EXIT_SUCCESS);
            }

        case 'r':
            SHOWREPORTS = true;
            break;

        case 'W':
            if (!GenericAgentConfigParseWarningOptions(config, optarg))
            {
                Log(LOG_LEVEL_ERR, "Error parsing warning option");
                exit(EXIT_FAILURE);
            }
            break;

        case 'x':
            Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired.");
            exit(EXIT_SUCCESS);

        case 'C':
            if (!GenericAgentConfigParseColor(config, optarg))
            {
                exit(EXIT_FAILURE);
            }
            break;

        default:
            {
                Writer *w = FileWriter(stdout);
                GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true);
                FileWriterDetach(w);
            }
            exit(EXIT_FAILURE);

        }
    }

    if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind))
    {
        Log(LOG_LEVEL_ERR, "Too many arguments");
        exit(EXIT_FAILURE);
    }

    return config;
}
Example #4
0
GenericAgentConfig *CheckOpts(int argc, char **argv)
{
    extern char *optarg;
    int c;
    GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON, GetTTYInteractive());
    config->tag_release_dir = NULL;

    while ((c = getopt_long(argc, argv, "dvnIw:f:D:N:VSrxMb:i:p:s:cg:hW:C::T:l",
                            OPTIONS, NULL))
           != -1)
    {
        switch (c)
        {
        case OPT_EVAL_FUNCTIONS:
            if (!optarg)
            {
                optarg = "yes";
            }
            config->agent_specific.common.eval_functions = strcmp("yes", optarg) == 0;
            break;

        case OPT_SHOW_CLASSES:
            config->agent_specific.common.show_classes = true;
            break;

        case OPT_SHOW_VARS:
            config->agent_specific.common.show_variables = true;
            break;

        case 'w':
            Log(LOG_LEVEL_INFO, "Setting workdir to '%s'", optarg);
            putenv(StringConcatenate(2, "CFENGINE_TEST_OVERRIDE_WORKDIR=", optarg));
            break;

        case 'c':
            config->check_runnable = true;
            break;

        case 'f':
            GenericAgentConfigSetInputFile(config, GetInputDir(), optarg);
            MINUSF = true;
            break;

        case 'd':
            LogSetGlobalLevel(LOG_LEVEL_DEBUG);
            break;

        case 'b':
            if (optarg)
            {
                Rlist *bundlesequence = RlistFromSplitString(optarg, ',');
                GenericAgentConfigSetBundleSequence(config, bundlesequence);
                RlistDestroy(bundlesequence);
            }
            break;

        case 'p':
            if (strcmp("none", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE;
            }
            else if (strcmp("cf", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF;
            }
            else if (strcmp("json", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON;
            }
             else if (strcmp("cf-full", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF_FULL;
            }
            else if (strcmp("json-full", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON_FULL;
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Invalid policy output format: '%s'. Possible values are 'none', 'cf', 'json', 'cf-full', 'json-full'", optarg);
                exit(EXIT_FAILURE);
            }
            break;

        case 's':
            if (strcmp("none", optarg) == 0)
            {
                break;
            }
            else if (strcmp("json", optarg) == 0)
            {
                JsonElement *json_syntax = SyntaxToJson();
                Writer *out = FileWriter(stdout);
                JsonWrite(out, json_syntax, 0);
                FileWriterDetach(out);
                JsonDestroy(json_syntax);
                exit(EXIT_SUCCESS);
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Invalid syntax description output format: '%s'. Possible values are 'none', 'json'", optarg);
                exit(EXIT_FAILURE);
            }
            break;

        case 'K':
            config->ignore_locks = true;
            break;

        case 'D':
            {
                StringSet *defined_classes = StringSetFromString(optarg, ',');
                if (! config->heap_soft)
                {
                    config->heap_soft = defined_classes;
                }
                else
                {
                    StringSetJoin(config->heap_soft, defined_classes);
                    free(defined_classes);
                }
            }
            break;

        case 'N':
            {
                StringSet *negated_classes = StringSetFromString(optarg, ',');
                if (! config->heap_negated)
                {
                    config->heap_negated = negated_classes;
                }
                else
                {
                    StringSetJoin(config->heap_negated, negated_classes);
                    free(negated_classes);
                }
            }
            break;

        case 'I':
            LogSetGlobalLevel(LOG_LEVEL_INFO);
            break;

        case 'v':
            LogSetGlobalLevel(LOG_LEVEL_VERBOSE);
            break;

        case 'n':
            DONTDO = true;
            config->ignore_locks = true;
            break;

        case 'V':
        {
            Writer *w = FileWriter(stdout);
            GenericAgentWriteVersion(w);
            FileWriterDetach(w);
        }
        exit(EXIT_SUCCESS);

        case 'h':
        {
            Writer *w = FileWriter(stdout);
            GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true);
            FileWriterDetach(w);
        }
        exit(EXIT_SUCCESS);

        case 'M':
        {
            Writer *out = FileWriter(stdout);
            ManPageWrite(out, "cf-promises", time(NULL),
                         CF_PROMISES_SHORT_DESCRIPTION,
                         CF_PROMISES_MANPAGE_LONG_DESCRIPTION,
                         OPTIONS, HINTS,
                         true);
            FileWriterDetach(out);
            exit(EXIT_SUCCESS);
        }

        case 'r':
            Log(LOG_LEVEL_ERR, "Option '-r' has been deprecated");
            exit(EXIT_FAILURE);
            break;

        case 'W':
            if (!GenericAgentConfigParseWarningOptions(config, optarg))
            {
                Log(LOG_LEVEL_ERR, "Error parsing warning option");
                exit(EXIT_FAILURE);
            }
            break;

        case 'x':
            Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired.");
            exit(EXIT_SUCCESS);

        case 'C':
            if (!GenericAgentConfigParseColor(config, optarg))
            {
                exit(EXIT_FAILURE);
            }
            break;

        case 'T':
            GenericAgentConfigSetInputFile(config, optarg, "promises.cf");
            MINUSF = true;
            config->tag_release_dir = xstrdup(optarg);
            break;

        case 'l':
            LoggingEnableTimestamps(true);
            break;

        default:
        {
            Writer *w = FileWriter(stdout);
            GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true);
            FileWriterDetach(w);
        }
        exit(EXIT_FAILURE);

        }
    }

    if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind))
    {
        Log(LOG_LEVEL_ERR, "Too many arguments");
        exit(EXIT_FAILURE);
    }

    return config;
}
Example #5
0
FnCallResult FnCallEvaluate(EvalContext *ctx, const Policy *policy, FnCall *fp, const Promise *caller)
{
    assert(ctx);
    assert(policy);
    assert(fp);
    fp->caller = caller;

    if (!EvalContextGetEvalOption(ctx, EVAL_OPTION_EVAL_FUNCTIONS))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because evaluation was turned off in the evaluator",
            fp->name);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    const FnCallType *fp_type = FnCallTypeGet(fp->name);

    if (!fp_type)
    {
        if (caller)
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s' in promise '%s' near line %zd",
                  fp->name, PromiseGetBundle(caller)->source_path, caller->offset.line);
        }
        else
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s', context info unavailable", fp->name);
        }

        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    Rlist *expargs = NewExpArgs(ctx, policy, fp);

    Writer *fncall_writer;
    const char *fncall_string;
    if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
    {
        fncall_writer = StringWriter();
        FnCallWrite(fncall_writer, fp);
        fncall_string = StringWriterData(fncall_writer);
    }

    if (RlistIsUnresolved(expargs))
    {
        if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
        {
            Log(LOG_LEVEL_DEBUG, "Skipping function evaluation for now,"
                " arguments contain unresolved variables: %s",
                fncall_string);
            WriterClose(fncall_writer);
        }
        RlistDestroy(expargs);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    Rval cached_rval;
    if ((fp_type->options & FNCALL_OPTION_CACHED) && EvalContextFunctionCacheGet(ctx, fp, expargs, &cached_rval))
    {
        if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
        {
            Log(LOG_LEVEL_DEBUG,
                "Using previously cached result for function: %s",
                fncall_string);
            WriterClose(fncall_writer);
        }
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        WriterClose(w);
        RlistDestroy(expargs);

        return (FnCallResult) { FNCALL_SUCCESS, RvalCopy(cached_rval) };
    }

    if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
    {
        Log(LOG_LEVEL_DEBUG, "Evaluating function: %s",
            fncall_string);
        WriterClose(fncall_writer);
    }

    FnCallResult result = CallFunction(ctx, policy, fp, expargs);

    if (result.status == FNCALL_FAILURE)
    {
        RlistDestroy(expargs);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }
    else if (result.rval.type == RVAL_TYPE_LIST && !result.rval.item)
    {
        Rlist *seq = NULL;
        // don't pass NULL items to evaluator
        RlistPrepend(&seq, CF_NULL_VALUE, RVAL_TYPE_SCALAR);
        result.rval.item = seq;
    }

    if (fp_type->options & FNCALL_OPTION_CACHED)
    {
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        Log(LOG_LEVEL_VERBOSE, "Caching result for function '%s'", StringWriterData(w));
        WriterClose(w);

        EvalContextFunctionCachePut(ctx, fp, expargs, &result.rval);
    }

    RlistDestroy(expargs);

    return result;
}
Example #6
0
static void Apoptosis(void)
{
    char promiser_buf[CF_SMALLBUF];
    snprintf(promiser_buf, sizeof(promiser_buf), "%s%cbin%ccf-execd",
             GetWorkDir(), FILE_SEPARATOR, FILE_SEPARATOR);

    if (LoadProcessTable())
    {
        char myuid[PRINTSIZE(unsigned)];
        xsnprintf(myuid, sizeof(myuid), "%u", (unsigned) getuid());

        Rlist *owners = NULL;
        RlistPrepend(&owners, myuid, RVAL_TYPE_SCALAR);

        ProcessSelect process_select = {
            .owner = owners,
            .process_result = "process_owner",
        };

        Item *killlist = SelectProcesses(promiser_buf, process_select, true);
        RlistDestroy(owners);

        for (Item *ip = killlist; ip != NULL; ip = ip->next)
        {
            pid_t pid = ip->counter;

            if (pid != getpid() && kill(pid, SIGTERM) < 0)
            {
                if (errno == ESRCH)
                {
                    /* That's ok, process exited voluntarily */
                }
                else
                {
                    Log(LOG_LEVEL_ERR, "Unable to kill stale cf-execd process pid=%d. (kill: %s)",
                        (int)pid, GetErrorStr());
                }
            }
        }
    }

    ClearProcessTable();

    Log(LOG_LEVEL_VERBOSE, "Pruning complete");
}

#endif

typedef enum
{
    RELOAD_ENVIRONMENT,
    RELOAD_FULL
} Reload;

static Reload CheckNewPromises(GenericAgentConfig *config)
{
    Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file);

    time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL);

    bool reload_config = false;

    if (config->agent_specific.daemon.last_validated_at < validated_at)
    {
        Log(LOG_LEVEL_VERBOSE, "New promises detected...");
        reload_config = true;
    }
    if (ReloadConfigRequested())
    {
        Log(LOG_LEVEL_VERBOSE, "Force reload of inputs files...");
        reload_config = true;
    }

    if (reload_config)
    {
        ClearRequestReloadConfig();

        /* Rereading policies now, so update timestamp. */
        config->agent_specific.daemon.last_validated_at = validated_at;

        if (GenericAgentArePromisesValid(config))
        {
            return RELOAD_FULL;
        }
        else
        {
            Log(LOG_LEVEL_INFO, "New promises file contains syntax errors -- ignoring");
        }
    }
    else
    {
        Log(LOG_LEVEL_DEBUG, "No new promises found");
    }

    return RELOAD_ENVIRONMENT;
}
Example #7
0
static int AuthorizeRoles(EvalContext *ctx, ServerConnectionState *conn, char *args)
{
    char *sp;
    Auth *ap;
    char userid1[CF_MAXVARSIZE], userid2[CF_MAXVARSIZE];
    Rlist *rp, *defines = NULL;
    int permitted = false;

    snprintf(userid1, CF_MAXVARSIZE, "%s@%s", conn->username, conn->hostname);
    snprintf(userid2, CF_MAXVARSIZE, "%s@%s", conn->username, conn->ipaddr);

    Log(LOG_LEVEL_VERBOSE, "Checking authorized roles in %s", args);

    if (strncmp(args, "--define", strlen("--define")) == 0)
    {
        sp = args + strlen("--define");
    }
    else
    {
        sp = args + strlen("-D");
    }

    while (*sp == ' ')
    {
        sp++;
    }

    defines = RlistFromSplitRegex(ctx, sp, "[,:;]", 99, false);

/* For each user-defined class attempt, check RBAC */

    for (rp = defines; rp != NULL; rp = rp->next)
    {
        Log(LOG_LEVEL_VERBOSE, "Verifying %s", RlistScalarValue(rp));

        for (ap = SV.roles; ap != NULL; ap = ap->next)
        {
            if (FullTextMatch(ctx, ap->path, RlistScalarValue(rp)))
            {
                /* We have a pattern covering this class - so are we allowed to activate it? */
                if ((IsMatchItemIn(ctx, ap->accesslist, MapAddress(conn->ipaddr))) ||
                    (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, userid1)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, userid2)) ||
                    (IsRegexItemIn(ctx, ap->accesslist, conn->username)))
                {
                    Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is permitted", RlistScalarValue(rp));
                    permitted = true;
                }
                else
                {
                    Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is denied", RlistScalarValue(rp));
                    RlistDestroy(defines);
                    return false;
                }
            }
        }

    }

    if (permitted)
    {
        Log(LOG_LEVEL_VERBOSE, "Role activation allowed");
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE, "Role activation disallowed - abort execution");
    }

    RlistDestroy(defines);
    return permitted;
}
Example #8
0
File: fncall.c Project: awsiv/core
FnCallResult FnCallEvaluate(EvalContext *ctx, const Policy *policy, FnCall *fp, const Promise *caller)
{
    assert(ctx);
    assert(policy);
    assert(fp);
    fp->caller = caller;

    if (!EvalContextGetEvalOption(ctx, EVAL_OPTION_EVAL_FUNCTIONS))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because evaluation was turned off in the evaluator",
            fp->name);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }
    else if (caller && !EvalContextPromiseIsActive(ctx, caller))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because it was excluded by classes", fp->name);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    const FnCallType *fp_type = FnCallTypeGet(fp->name);

    if (!fp_type)
    {
        if (caller)
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s' in promise '%s' near line %llu",
                fp->name, PromiseGetBundle(caller)->source_path,
                (unsigned long long)caller->offset.line);
        }
        else
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s', context info unavailable", fp->name);
        }

        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    Rlist *expargs = NewExpArgs(ctx, policy, fp);

    if (RlistIsUnresolved(expargs))
    {
        RlistDestroy(expargs);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    Rval cached_rval;
    if ((fp_type->options & FNCALL_OPTION_CACHED) && EvalContextFunctionCacheGet(ctx, fp, expargs, &cached_rval))
    {
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        Log(LOG_LEVEL_DEBUG, "Using previously cached result for function '%s'", StringWriterData(w));
        WriterClose(w);
        RlistDestroy(expargs);

        return (FnCallResult) { FNCALL_SUCCESS, RvalCopy(cached_rval) };
    }

    FnCallResult result = CallFunction(ctx, policy, fp, expargs);

    if (result.status == FNCALL_FAILURE)
    {
        RlistDestroy(expargs);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    if (fp_type->options & FNCALL_OPTION_CACHED)
    {
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        Log(LOG_LEVEL_VERBOSE, "Caching result for function '%s'", StringWriterData(w));
        WriterClose(w);

        EvalContextFunctionCachePut(ctx, fp, expargs, &result.rval);
    }

    RlistDestroy(expargs);

    return result;
}
Example #9
0
static int HailServer(char *host, Attributes a, Promise *pp)
{
    AgentConnection *conn;
    char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], peer[CF_MAXVARSIZE], ipv4[CF_MAXVARSIZE],
        digest[CF_MAXVARSIZE], user[CF_SMALLBUF];
    bool gotkey;
    char reply[8];

    a.copy.portnumber = (short) ParseHostname(host, peer);

    snprintf(ipv4, CF_MAXVARSIZE, "%s", Hostname2IPString(peer));
    Address2Hostkey(ipv4, digest);
    GetCurrentUserName(user, CF_SMALLBUF);

    if (INTERACTIVE)
    {
        CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Using interactive key trust...\n");

        gotkey = HavePublicKey(user, peer, digest) != NULL;

        if (!gotkey)
        {
            gotkey = HavePublicKey(user, ipv4, digest) != NULL;
        }

        if (!gotkey)
        {
            printf("WARNING - You do not have a public key from host %s = %s\n", host, ipv4);
            printf("          Do you want to accept one on trust? (yes/no)\n\n--> ");

            while (true)
            {
                if (fgets(reply, 8, stdin) == NULL)
                {
                    FatalError("EOF trying to read answer from terminal");
                }

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

                if (strcmp(reply, "yes") == 0)
                {
                    printf(" -> Will trust the key...\n");
                    a.copy.trustkey = true;
                    break;
                }
                else if (strcmp(reply, "no") == 0)
                {
                    printf(" -> Will not trust the key...\n");
                    a.copy.trustkey = false;
                    break;
                }
                else
                {
                    printf(" !! Please reply yes or no...(%s)\n", reply);
                }
            }
        }
    }

/* Continue */

#ifdef __MINGW32__

    CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
    CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, a.copy.portnumber,
          REMOTE_AGENT_OPTIONS);
    CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");

#else /* !__MINGW32__ */

    if (BACKGROUND)
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Hailing %s : %u, with options \"%s\" (parallel)\n", peer, a.copy.portnumber,
              REMOTE_AGENT_OPTIONS);
    }
    else
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
        CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, a.copy.portnumber,
              REMOTE_AGENT_OPTIONS);
        CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
    }

#endif /* !__MINGW32__ */

    a.copy.servers = RlistFromSplitString(peer, '*');

    if (a.copy.servers == NULL || strcmp(a.copy.servers->item, "localhost") == 0)
    {
        cfPS(OUTPUT_LEVEL_INFORM, CF_NOP, "", pp, a, "No hosts are registered to connect to");
        return false;
    }
    else
    {
        conn = NewServerConnection(a, pp);

        if (conn == NULL)
        {
            RlistDestroy(a.copy.servers);
            CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> No suitable server responded to hail\n");
            return false;
        }
    }

/* Check trust interaction*/

    pp->cache = NULL;

    if (strlen(MENU) > 0)
    {
#if defined(HAVE_NOVA)
        if (!ExecuteRunagent(conn, MENU))
        {
            DisconnectServer(conn);
            RlistDestroy(a.copy.servers);
            return false;
        }
#endif
    }
    else
    {
        HailExec(conn, peer, recvbuffer, sendbuffer);
    }

    RlistDestroy(a.copy.servers);

    return true;
}
Example #10
0
static int HailServer(EvalContext *ctx, char *host)
{
    AgentConnection *conn;
    char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], peer[CF_MAXVARSIZE],
        digest[CF_MAXVARSIZE], user[CF_SMALLBUF];
    bool gotkey;
    char reply[8];

    FileCopy fc = {
        .portnumber = (unsigned short) ParseHostname(host, peer),
    };

    char ipaddr[CF_MAX_IP_LEN];
    if (Hostname2IPString(ipaddr, peer, sizeof(ipaddr)) == -1)
    {
        Log(LOG_LEVEL_ERR,
            "HailServer: ERROR, could not resolve '%s'", peer);
        return false;
    }

    Address2Hostkey(ipaddr, digest);
    GetCurrentUserName(user, CF_SMALLBUF);

    if (INTERACTIVE)
    {
        Log(LOG_LEVEL_VERBOSE, "Using interactive key trust...");

        gotkey = HavePublicKey(user, peer, digest) != NULL;

        if (!gotkey)
        {
            gotkey = HavePublicKey(user, ipaddr, digest) != NULL;
        }

        if (!gotkey)
        {
            printf("WARNING - You do not have a public key from host %s = %s\n",
                   host, ipaddr);
            printf("          Do you want to accept one on trust? (yes/no)\n\n--> ");

            while (true)
            {
                if (fgets(reply, sizeof(reply), stdin) == NULL)
                {
                    FatalError(ctx, "EOF trying to read answer from terminal");
                }

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

                if (strcmp(reply, "yes") == 0)
                {
                    printf("Will trust the key...\n");
                    fc.trustkey = true;
                    break;
                }
                else if (strcmp(reply, "no") == 0)
                {
                    printf("Will not trust the key...\n");
                    fc.trustkey = false;
                    break;
                }
                else
                {
                    printf("Please reply yes or no...(%s)\n", reply);
                }
            }
        }
    }

/* Continue */

#ifdef __MINGW32__

    if (LEGACY_OUTPUT)
    {
        Log(LOG_LEVEL_INFO, "...........................................................................");
        Log(LOG_LEVEL_INFO, " * Hailing %s : %u, with options \"%s\" (serial)", peer, fc.portnumber,
              REMOTE_AGENT_OPTIONS);
        Log(LOG_LEVEL_INFO, "...........................................................................");
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (serial)", peer, fc.portnumber,
            REMOTE_AGENT_OPTIONS);
    }


#else /* !__MINGW32__ */

    if (BACKGROUND)
    {
        Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (parallel)", peer, fc.portnumber,
              REMOTE_AGENT_OPTIONS);
    }
    else
    {
        if (LEGACY_OUTPUT)
        {
            Log(LOG_LEVEL_INFO, "...........................................................................");
            Log(LOG_LEVEL_INFO, " * Hailing %s : %u, with options \"%s\" (serial)", peer, fc.portnumber,
                  REMOTE_AGENT_OPTIONS);
            Log(LOG_LEVEL_INFO, "...........................................................................");
        }
        else
        {
            Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (serial)", peer, fc.portnumber,
                  REMOTE_AGENT_OPTIONS);
        }
    }

#endif /* !__MINGW32__ */

    fc.servers = RlistFromSplitString(peer, '*');

    if (fc.servers == NULL || strcmp(RlistScalarValue(fc.servers), "localhost") == 0)
    {
        Log(LOG_LEVEL_INFO, "No hosts are registered to connect to");
        return false;
    }
    else
    {
        int err = 0;
        conn = NewServerConnection(fc, false, &err, -1);

        if (conn == NULL)
        {
            RlistDestroy(fc.servers);
            Log(LOG_LEVEL_VERBOSE, "No suitable server responded to hail");
            return false;
        }
    }

/* Check trust interaction*/

    HailExec(conn, peer, recvbuffer, sendbuffer);

    RlistDestroy(fc.servers);

    return true;
}

/********************************************************************/
/* Level 2                                                          */
/********************************************************************/

static void KeepControlPromises(EvalContext *ctx, const Policy *policy)
{
    Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT);
    if (constraints)
    {
        for (size_t i = 0; i < SeqLength(constraints); i++)
        {
            Constraint *cp = SeqAt(constraints, i);

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

            VarRef *ref = VarRefParseFromScope(cp->lval, "control_runagent");
            const void *value = EvalContextVariableGet(ctx, ref, NULL);
            VarRefDestroy(ref);

            if (!value)
            {
                Log(LOG_LEVEL_ERR, "Unknown lval '%s' in runagent control body", cp->lval);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0)
            {
                /*
                 * Only process this option if are is no -b or -i options specified on
                 * command line.
                 */
                if (BACKGROUND || INTERACTIVE)
                {
                    Log(LOG_LEVEL_WARNING,
                          "'background_children' setting from 'body runagent control' is overridden by command-line option.");
                }
                else
                {
                    BACKGROUND = BooleanFromString(value);
                }
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0)
            {
                MAXCHILD = (short) IntFromString(value);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0)
            {
                OUTPUT_TO_FILE = BooleanFromString(value);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0)
            {
                if (IsAbsPath(value))
                {
                    strncpy(OUTPUT_DIRECTORY, value, CF_BUFSIZE - 1);
                    Log(LOG_LEVEL_VERBOSE, "Setting output direcory to '%s'", OUTPUT_DIRECTORY);
                }
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0)
            {
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0)
            {
                if (HOSTLIST == NULL)       // Don't override if command line setting
                {
                    HOSTLIST = value;
                }

                continue;
            }
        }
    }

    const char *expire_after = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER);
    if (expire_after)
    {
        LASTSEENEXPIREAFTER = IntFromString(expire_after) * 60;
    }

}
Example #11
0
GenericAgentConfig *CheckOpts(EvalContext *ctx, int argc, char **argv)
{
    extern char *optarg;
    int optindex = 0;
    int c;
    GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON);

    while ((c = getopt_long(argc, argv, "dvnIf:D:N:VSrxMb:i:p:cg:h", OPTIONS, &optindex)) != EOF)
    {
        switch ((char) c)
        {
        case 'c':
            config->check_runnable = true;
            break;

        case 'f':

            if (optarg && (strlen(optarg) < 5))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " -f used but argument \"%s\" incorrect", optarg);
                exit(EXIT_FAILURE);
            }

            GenericAgentConfigSetInputFile(config, optarg);
            MINUSF = true;
            break;

        case 'd':
            config->debug_mode = true;
            break;

        case 'b':
            if (optarg)
            {
                Rlist *bundlesequence = RlistFromSplitString(optarg, ',');
                GenericAgentConfigSetBundleSequence(config, bundlesequence);
                RlistDestroy(bundlesequence);
                CBUNDLESEQUENCE_STR = optarg; // TODO: wtf is this
            }
            break;

        case 'p':
            if (strcmp("none", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE;
            }
            else if (strcmp("cf", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF;
            }
            else if (strcmp("json", optarg) == 0)
            {
                config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON;
            }
            else
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", "Invalid policy output format: '%s'. Possible values are 'none', 'cf', 'json'", optarg);
                exit(EXIT_FAILURE);
            }
            break;

        case 'K':
            IGNORELOCK = true;
            break;

        case 'D':
            config->heap_soft = StringSetFromString(optarg, ',');
            break;

        case 'N':
            config->heap_negated = StringSetFromString(optarg, ',');
            break;

        case 'I':
            INFORM = true;
            break;

        case 'v':
            VERBOSE = true;
            break;

        case 'n':
            DONTDO = true;
            IGNORELOCK = true;
            LOOKUP = true;
            EvalContextHeapAddHard(ctx, "opt_dry_run");
            break;

        case 'V':
            PrintVersionBanner("cf-promises");
            exit(0);

        case 'h':
            Syntax("cf-promises - cfengine's promise analyzer", OPTIONS, HINTS, ID);
            exit(0);

        case 'M':
            ManPage("cf-promises - cfengine's promise analyzer", OPTIONS, HINTS, ID);
            exit(0);

        case 'r':
            SHOWREPORTS = true;
            break;

        case 'x':
            CfOut(OUTPUT_LEVEL_ERROR, "", "Self-diagnostic functionality is retired.");
            exit(0);

        default:
            Syntax("cf-promises - cfengine's promise analyzer", OPTIONS, HINTS, ID);
            exit(1);

        }
    }

    if (argv[optind] != NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "Unexpected argument: %s\n", argv[optind]);
    }

    CfDebug("Set debugging\n");

    return config;
}
Example #12
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;
}
Example #13
0
static int NewSQLColumns(char *table, Rlist *columns, char ***name_table, char ***type_table, int **size_table,
                         int **done)
{
    int i, no_of_cols = RlistLen(columns);
    Rlist *cols, *rp;

    *name_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1));
    *type_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1));
    *size_table = (int *) xmalloc(sizeof(int) * (no_of_cols + 1));
    *done = (int *) xmalloc(sizeof(int) * (no_of_cols + 1));

    for (i = 0, rp = columns; rp != NULL; rp = rp->next, i++)
    {
        (*done)[i] = 0;

        cols = RlistFromSplitString((char *) rp->item, ',');

        if (!cols)
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "No columns promised for table \"%s\" - makes no sense", table);
            return false;
        }

        if (cols->item == NULL)
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "Malformed column promise for table \"%s\" - found not even a name", table);
            free(*name_table);
            free(*type_table);
            free(*size_table);
            free(*done);
            return false;
        }

        (*name_table)[i] = xstrdup((char *) cols->item);

        if (cols->next == NULL)
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "Malformed column \"%s\" promised for table \"%s\" - missing a type", (*name_table)[i],
                  table);
            free(*name_table);
            free(*type_table);
            free(*size_table);
            free(*done);
            return false;
        }

        (*type_table)[i] = xstrdup(cols->next->item);

        if (cols->next->next == NULL)
        {
            (*size_table)[i] = 0;
        }
        else
        {
            if (cols->next->next->item)
            {
                (*size_table)[i] = IntFromString(cols->next->next->item);
            }
            else
            {
                (*size_table)[i] = 0;
            }
        }

        RlistDestroy(cols);
    }

    return true;
}
Example #14
0
static void ParserStateReset(ParserState *p, bool discard)
{
    p->agent_type = AGENT_TYPE_COMMON;
    p->warnings = PARSER_WARNING_ALL;
    p->policy = NULL;

    int i = CF_MAX_NESTING;
    while (i-- > 0) /* Clear stacks from top down */
    {
        if (discard)
        {
            free(p->currentfnid[i]);
            RlistDestroy(p->giveargs[i]);
            FnCallDestroy(p->currentfncall[i]);
        }
        else
        {
            assert(!p->currentfnid[i]);
            assert(!p->giveargs[i]);
            assert(!p->currentfncall[i]);
        }
        p->currentfnid[i] = NULL;
        p->giveargs[i] = NULL;
        p->currentfncall[i] = NULL;
    }

    free(p->current_line);
    p->current_line = NULL;
    p->line_no = 1;
    p->line_pos = 1;
    p->error_count = 0;
    p->warning_count = 0;
    p->list_nesting = 0;
    p->arg_nesting = 0;

    free(p->current_namespace);
    p->current_namespace = xstrdup("default");

    p->currentid[0] = '\0';
    if (p->currentstring)
    {
        free(p->currentstring);
    }
    p->currentstring = NULL;
    p->currenttype[0] = '\0';
    if (p->currentclasses)
    {
        free(p->currentclasses);
    }
    p->currentclasses = NULL;
    p->currentRlist = NULL;
    p->currentpromise = NULL;
    p->currentbody = NULL;
    if (p->promiser)
    {
        free(p->promiser);
    }
    p->promiser = NULL;
    p->blockid[0] = '\0';
    p->blocktype[0] = '\0';
    p->rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE);
}
Example #15
0
static void TexinfoVariables(const char *source_dir, FILE *fout, char *scope)
{
    char filename[CF_BUFSIZE], varname[CF_BUFSIZE];
    Rlist *rp, *list = NULL;
    int i;

    char *extra_mon[] = { "listening_udp4_ports", "listening_tcp4_ports", "listening_udp6_ports", "listening_tcp6_ports", NULL };
    
    HashToList(GetScope(scope), &list);
    list = AlphaSortRListNames(list);

    fprintf(fout, "\n\n@node Variable context %s\n@section Variable context @code{%s}\n\n", scope, scope);
    snprintf(filename, CF_BUFSIZE - 1, "varcontexts/%s_intro.texinfo", scope);
    IncludeManualFile(source_dir, fout, filename);

    fprintf(fout, "@menu\n");

    if (strcmp(scope, "mon") != 0)
    {
        for (rp = list; rp != NULL; rp = rp->next)
        {
            fprintf(fout, "* Variable %s.%s::\n", scope, (char *) rp->item);
        }
    }
    else
    {
        for (i = 0; extra_mon[i] != NULL; i++)        
        {
            fprintf(fout, "* Variable %s.%s::\n", "mon", extra_mon[i]);
        }

        for (i = 0; i < CF_OBSERVABLES; ++i)
        {
            if (strcmp(OBS[i][0], "spare") == 0)
            {
                break;
            }

            fprintf(fout, "* Variable mon.value_%s::\n", OBS[i][0]);
            fprintf(fout, "* Variable mon.av_%s::\n", OBS[i][0]);
            fprintf(fout, "* Variable mon.dev_%s::\n", OBS[i][0]);
        }
    }

    fprintf(fout, "@end menu\n");

    if (strcmp(scope, "mon") != 0)
    {
        for (rp = list; rp != NULL; rp = rp->next)
        {
            fprintf(fout, "@node Variable %s.%s\n@subsection Variable %s.%s \n\n", scope, (char *) rp->item, scope,
                    (char *) rp->item);
            snprintf(filename, CF_BUFSIZE - 1, "vars/%s_%s.texinfo", scope, (char *) rp->item);
            IncludeManualFile(source_dir, fout, filename);
        }
    }
    else
    {
        for (i = 0; extra_mon[i] != NULL; i++)        
        {
            fprintf(fout, "\n@node Variable %s.%s\n@subsection Variable %s.%s \n\n", "mon", extra_mon[i], "mon", extra_mon[i]);
            fprintf(fout, "List variable containing an observational measure collected every 2.5 minutes from cf-monitord, description: port numbers that were observed to be set up to receive connections on the host concerned");

        }

    
        for (i = 0; i < CF_OBSERVABLES; i++)
        {
            if (strcmp(OBS[i][0], "spare") == 0)
            {
                break;
            }

            snprintf(varname, CF_MAXVARSIZE, "value_%s", OBS[i][0]);
            fprintf(fout, "\n@node Variable %s.%s\n@subsection Variable %s.%s \n\n", scope, varname, scope, varname);
            fprintf(fout, "Observational measure collected every 2.5 minutes from cf-monitord, description: @var{%s}.",
                    OBS[i][1]);

            snprintf(varname, CF_MAXVARSIZE, "av_%s", OBS[i][0]);
            fprintf(fout, "\n@node Variable %s.%s\n@subsection Variable %s.%s \n\n", scope, varname, scope, varname);
            fprintf(fout, "Observational measure collected every 2.5 minutes from cf-monitord, description: @var{%s}.",
                    OBS[i][1]);

            snprintf(varname, CF_MAXVARSIZE, "dev_%s", OBS[i][0]);
            fprintf(fout, "\n@node Variable %s.%s\n@subsection Variable %s.%s \n\n", scope, varname, scope, varname);
            fprintf(fout, "Observational measure collected every 2.5 minutes from cf-monitord, description: @var{%s}.",
                    OBS[i][1]);
        }
    }

    RlistDestroy(list);
}
Example #16
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);
}
Example #17
0
void RlistDestroy_untyped(void *rl)
{
    RlistDestroy(rl);
}
Example #18
0
File: rlist.c Project: cduclos/core
/**
 @brief parse elements in a list passed through use_module
 
 @param[in] str: is the string to parse
 @param[out] newlist: rlist of elements found

 @retval 0: successful >0: failed
 */
static int LaunchParsingMachine(const char *str, Rlist **newlist)
{
    const char *s = str;
    state current_state = ST_OPENED;
    int ret;

    char snatched[CF_MAXVARSIZE];
    snatched[0]='\0';
    char *sn = NULL;

    while (current_state != ST_CLOSED && *s)
    {
        switch(current_state) {
            case ST_ERROR:
                Log(LOG_LEVEL_ERR, "Parsing error : Malformed string");
                ret = 1;
                goto clean;
            case ST_OPENED:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_OPENED;
                }
                else if (CLASS_BRA1(*s)) 
                {
                    current_state = ST_IO;
                }
                else if (CLASS_ANY0(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_IO:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_IO;
                }
                else if (CLASS_START1(*s))
                {
                    sn=snatched;
                    current_state = ST_ELM1;
                }
                else if (CLASS_START2(*s))
                {
                      sn=snatched; 
                      current_state = ST_ELM2;
                }
                else if (CLASS_ANY1(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_ELM1:
                if (CLASS_END1(*s))
                {
                    if (sn==NULL)
                    {
                        sn=snatched;
                    }
                    *sn='\0'; 
                    RlistAppendScalar(newlist, snatched);
                    sn=NULL;
                    current_state = ST_END1;
                }
                else if (CLASS_ANY2(*s))
                {
                    if (sn==NULL)
                    {
                        sn=snatched;
                    }
                    *sn=*s;
                    sn++; 
                    current_state = ST_ELM1;
                }
                s++;
                break;
            case ST_ELM2:
                if (CLASS_END2(*s))
                {
                    if (sn==NULL)
                    {
                        sn=snatched;
                    }
                    *sn='\0'; 
                    RlistAppendScalar(newlist, snatched);
                    sn=NULL; 
                    current_state = ST_END2;
                }
                else if (CLASS_ANY3(*s))
                {
                    if (sn==NULL) 
                    {
                        sn=snatched;
                    }
                    *sn=*s;
                    sn++;
                    current_state = ST_ELM2;
                }
                s++;
                break;
            case ST_END1:
                if (CLASS_SEP(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_BRA2(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_BLANK(*s))
                {
                    current_state = ST_END1;
                }
                else if (CLASS_ANY4(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_END2:
                if (CLASS_SEP(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_BRA2(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_BLANK(*s))
                {
                    current_state = ST_END2;
                }
                else if (CLASS_ANY5(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_SEP:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_START1(*s))
                {
                    current_state = ST_ELM1;
                }
                else if (CLASS_START2(*s))
                {
                    current_state = ST_ELM2;
                }
                else if (CLASS_ANY6(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_PRECLOSED:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_EOL(*s))
                {
                    current_state = ST_CLOSED;
                }
                else if (CLASS_ANY7(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            default:
                Log(LOG_LEVEL_ERR, "Parsing logic error: unknown state");
                ret = 2;
                goto clean;
                break;
        }
    }

    if (current_state != ST_CLOSED && current_state != ST_PRECLOSED )
    {
        Log(LOG_LEVEL_ERR, "Parsing error : Malformed string (unexpected end of input)");
        ret = 3;
        goto clean;
    }

    return 0;

clean:
    if (newlist)
    {
        RlistDestroy(*newlist);
    }
    return ret;
}
Example #19
0
/**
 @brief parse elements in a list passed through use_module

 @param[in] str: is the string to parse
 @param[out] newlist: rlist of elements found

 @retval 0: successful > 0: failed
 */
static int LaunchParsingMachine(const char *str, Rlist **newlist)
{
    const char *s = str;
    state current_state = ST_OPENED;
    int ret;

    Buffer *buf = BufferNewWithCapacity(CF_MAXVARSIZE);

    assert(newlist);

    while (current_state != ST_CLOSED && *s)
    {
        switch(current_state)
        {
            case ST_ERROR:
                Log(LOG_LEVEL_ERR, "Parsing error : Malformed string");
                ret = 1;
                goto clean;
            case ST_OPENED:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_OPENED;
                }
                else if (CLASS_BRA1(*s))
                {
                    current_state = ST_IO;
                }
                else if (CLASS_ANY0(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_IO:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_IO;
                }
                else if (CLASS_START1(*s))
                {
                    BufferClear(buf);
                    current_state = ST_ELM1;
                }
                else if (CLASS_START2(*s))
                {
                    BufferClear(buf);
                    current_state = ST_ELM2;
                }
                else if (CLASS_ANY1(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_ELM1:
                if (CLASS_END1(*s))
                {
                    RlistAppendScalar(newlist, BufferData(buf));
                    BufferClear(buf);
                    current_state = ST_END1;
                }
                else if (CLASS_ANY2(*s))
                {
                    BufferAppendChar(buf, *s);
                    current_state = ST_ELM1;
                }
                s++;
                break;
            case ST_ELM2:
                if (CLASS_END2(*s))
                {
                    RlistAppendScalar(newlist, BufferData(buf));
                    BufferClear(buf);
                    current_state = ST_END2;
                }
                else if (CLASS_ANY3(*s))
                {
                    BufferAppendChar(buf, *s);
                    current_state = ST_ELM2;
                }
                s++;
                break;
            case ST_END1:
                if (CLASS_SEP(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_BRA2(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_BLANK(*s))
                {
                    current_state = ST_END1;
                }
                else if (CLASS_ANY4(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_END2:
                if (CLASS_SEP(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_BRA2(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_BLANK(*s))
                {
                    current_state = ST_END2;
                }
                else if (CLASS_ANY5(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_SEP:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_SEP;
                }
                else if (CLASS_START1(*s))
                {
                    current_state = ST_ELM1;
                }
                else if (CLASS_START2(*s))
                {
                    current_state = ST_ELM2;
                }
                else if (CLASS_ANY6(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            case ST_PRECLOSED:
                if (CLASS_BLANK(*s))
                {
                    current_state = ST_PRECLOSED;
                }
                else if (CLASS_EOL(*s))
                {
                    current_state = ST_CLOSED;
                }
                else if (CLASS_ANY7(*s))
                {
                    current_state = ST_ERROR;
                }
                s++;
                break;
            default:
                Log(LOG_LEVEL_ERR, "Parsing logic error: unknown state");
                ret = 2;
                goto clean;
                break;
        }
    }

    if (current_state != ST_CLOSED && current_state != ST_PRECLOSED )
    {
        Log(LOG_LEVEL_ERR, "Parsing error : Malformed string (unexpected end of input)");
        ret = 3;
        goto clean;
    }

    BufferDestroy(buf);
    return 0;

clean:
    BufferDestroy(buf);
    RlistDestroy(*newlist);
    assert(ret != 0);
    return ret;
}
Example #20
0
void GetInterfacesInfo(AgentType ag)
{
    int fd, len, i, j, first_address = false, ipdefault = false;
    struct ifreq ifbuf[CF_IFREQ], ifr, *ifp;
    struct ifconf list;
    struct sockaddr_in *sin;
    struct hostent *hp;
    char *sp, workbuf[CF_BUFSIZE];
    char ip[CF_MAXVARSIZE];
    char name[CF_MAXVARSIZE];
    char last_name[CF_BUFSIZE];
    Rlist *interfaces = NULL, *hardware = NULL, *ips = NULL;

    CfDebug("GetInterfacesInfo()\n");

    // Long-running processes may call this many times
    DeleteItemList(IPADDRESSES);
    IPADDRESSES = NULL;

    memset(ifbuf, 0, sizeof(ifbuf));

    InitIgnoreInterfaces();
    
    last_name[0] = '\0';

    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "socket", "Couldn't open socket");
        exit(1);
    }

    list.ifc_len = sizeof(ifbuf);
    list.ifc_req = ifbuf;

# ifdef SIOCGIFCONF
    if (ioctl(fd, SIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq))))
# else
    if ((ioctl(fd, OSIOCGIFCONF, &list) == -1) || (list.ifc_len < (sizeof(struct ifreq))))
# endif
    {
        CfOut(OUTPUT_LEVEL_ERROR, "ioctl", "Couldn't get interfaces - old kernel? Try setting CF_IFREQ to 1024");
        exit(1);
    }

    last_name[0] = '\0';

    for (j = 0, len = 0, ifp = list.ifc_req; len < list.ifc_len;
         len += SIZEOF_IFREQ(*ifp), j++, ifp = (struct ifreq *) ((char *) ifp + SIZEOF_IFREQ(*ifp)))
    {

        if (ifp->ifr_addr.sa_family == 0)
        {
            continue;
        }

        if ((ifp->ifr_name == NULL) || (strlen(ifp->ifr_name) == 0))
        {
            continue;
        }

        /* Skip virtual network interfaces for Linux, which seems to be a problem */

        if (IgnoreInterface(ifp->ifr_name))
        {
            continue;
        }
        
        if (strstr(ifp->ifr_name, ":"))
        {
#ifdef __linux__
            CfOut(OUTPUT_LEVEL_VERBOSE, "", "Skipping apparent virtual interface %d: %s\n", j + 1, ifp->ifr_name);
            continue;
#endif
        }
        else
        {
            CfOut(OUTPUT_LEVEL_VERBOSE, "", "Interface %d: %s\n", j + 1, ifp->ifr_name);
        }

        // Ignore the loopback

        if (strcmp(ifp->ifr_name, "lo") == 0)
        {
            continue;
        }

        if (strncmp(last_name, ifp->ifr_name, sizeof(ifp->ifr_name)) == 0)
        {
            first_address = false;
        }
        else
        {
            strncpy(last_name, ifp->ifr_name, sizeof(ifp->ifr_name));

            if (!first_address)
            {
                NewScalar("sys", "interface", last_name, DATA_TYPE_STRING);
                first_address = true;
            }
        }

        snprintf(workbuf, CF_BUFSIZE, "net_iface_%s", CanonifyName(ifp->ifr_name));

        HardClass(workbuf);

        if (ifp->ifr_addr.sa_family == AF_INET)
        {
            strncpy(ifr.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));

            if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
            {
                CfOut(OUTPUT_LEVEL_ERROR, "ioctl", "No such network device");
                continue;
            }

            if ((ifr.ifr_flags & IFF_UP) && (!(ifr.ifr_flags & IFF_LOOPBACK)))
            {
                sin = (struct sockaddr_in *) &ifp->ifr_addr;

                if (IgnoreJailInterface(j + 1, sin))
                {
                    CfOut(OUTPUT_LEVEL_VERBOSE, "", "Ignoring interface %d", j + 1);
                    continue;
                }

                CfDebug("Adding hostip %s..\n", inet_ntoa(sin->sin_addr));
                HardClass(inet_ntoa(sin->sin_addr));

                if ((hp =
                     gethostbyaddr((char *) &(sin->sin_addr.s_addr), sizeof(sin->sin_addr.s_addr), AF_INET)) == NULL)
                {
                    CfDebug("No hostinformation for %s found\n", inet_ntoa(sin->sin_addr));
                }
                else
                {
                    if (hp->h_name != NULL)
                    {
                        CfDebug("Adding hostname %s..\n", hp->h_name);
                        HardClass(hp->h_name);

                        if (hp->h_aliases != NULL)
                        {
                            for (i = 0; hp->h_aliases[i] != NULL; i++)
                            {
                                CfOut(OUTPUT_LEVEL_VERBOSE, "", "Adding alias %s..\n", hp->h_aliases[i]);
                                HardClass(hp->h_aliases[i]);
                            }
                        }
                    }
                }

                if (strcmp(inet_ntoa(sin->sin_addr), "0.0.0.0") == 0)
                {
                    // Maybe we need to do something windows specific here?
                    CfOut(OUTPUT_LEVEL_VERBOSE, "", " !! Cannot discover hardware IP, using DNS value");
                    strcpy(ip, "ipv4_");
                    strcat(ip, VIPADDRESS);
                    AppendItem(&IPADDRESSES, VIPADDRESS, "");
                    RlistAppend(&ips, VIPADDRESS, RVAL_TYPE_SCALAR);

                    for (sp = ip + strlen(ip) - 1; (sp > ip); sp--)
                    {
                        if (*sp == '.')
                        {
                            *sp = '\0';
                            HardClass(ip);
                        }
                    }

                    strcpy(ip, VIPADDRESS);
                    i = 3;

                    for (sp = ip + strlen(ip) - 1; (sp > ip); sp--)
                    {
                        if (*sp == '.')
                        {
                            *sp = '\0';
                            snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[%s]", i--, CanonifyName(VIPADDRESS));
                            NewScalar("sys", name, ip, DATA_TYPE_STRING);
                        }
                    }
                    continue;
                }

                strncpy(ip, "ipv4_", CF_MAXVARSIZE);
                strncat(ip, inet_ntoa(sin->sin_addr), CF_MAXVARSIZE - 6);
                HardClass(ip);

                if (!ipdefault)
                {
                    ipdefault = true;
                    NewScalar("sys", "ipv4", inet_ntoa(sin->sin_addr), DATA_TYPE_STRING);

                    strcpy(VIPADDRESS, inet_ntoa(sin->sin_addr));
                }

                AppendItem(&IPADDRESSES, inet_ntoa(sin->sin_addr), "");
                RlistAppend(&ips, inet_ntoa(sin->sin_addr), RVAL_TYPE_SCALAR);

                for (sp = ip + strlen(ip) - 1; (sp > ip); sp--)
                {
                    if (*sp == '.')
                    {
                        *sp = '\0';
                        HardClass(ip);
                    }
                }

                // Set the IPv4 on interface array

                strcpy(ip, inet_ntoa(sin->sin_addr));

                if ((ag != AGENT_TYPE_KNOW) && (ag != AGENT_TYPE_GENDOC))
                {
                    snprintf(name, CF_MAXVARSIZE - 1, "ipv4[%s]", CanonifyName(ifp->ifr_name));
                }
                else
                {
                    snprintf(name, CF_MAXVARSIZE - 1, "ipv4[interface_name]");
                }

                NewScalar("sys", name, ip, DATA_TYPE_STRING);

                i = 3;

                for (sp = ip + strlen(ip) - 1; (sp > ip); sp--)
                {
                    if (*sp == '.')
                    {
                        *sp = '\0';

                        if ((ag != AGENT_TYPE_KNOW) && (ag != AGENT_TYPE_GENDOC))
                        {
                            snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[%s]", i--, CanonifyName(ifp->ifr_name));
                        }
                        else
                        {
                            snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[interface_name]", i--);
                        }

                        NewScalar("sys", name, ip, DATA_TYPE_STRING);
                    }
                }
            }

            // Set the hardware/mac address array
            GetMacAddress(ag, fd, &ifr, ifp, &interfaces, &hardware);
        }
    }

    close(fd);

    NewList("sys", "interfaces", interfaces, DATA_TYPE_STRING_LIST);
    NewList("sys", "hardware_addresses", hardware, DATA_TYPE_STRING_LIST);
    NewList("sys", "ip_addresses", ips, DATA_TYPE_STRING_LIST);

    RlistDestroy(interfaces);
    RlistDestroy(hardware);
    RlistDestroy(ips);

    FindV6InterfacesInfo();
}
Example #21
0
bool EvalContextVariablePut(EvalContext *ctx, VarRef lval, Rval rval, DataType type)
{
    assert(type != DATA_TYPE_NONE);

    if (lval.lval == NULL || lval.scope == NULL)
    {
        ProgrammingError("Bad variable or scope in a variable assignment. scope.value = %s.%s", lval.scope, lval.lval);
    }

    if (rval.item == NULL)
    {
        return false;
    }

    if (strlen(lval.lval) > CF_MAXVARSIZE)
    {
        char *lval_str = VarRefToString(lval, true);
        Log(LOG_LEVEL_ERR, "Variable '%s'' cannot be added because its length exceeds the maximum length allowed '%d' characters", lval_str, CF_MAXVARSIZE);
        free(lval_str);
        return false;
    }

    // If we are not expanding a body template, check for recursive singularities
    if (strcmp(lval.scope, "body") != 0)
    {
        switch (rval.type)
        {
        case RVAL_TYPE_SCALAR:
            if (StringContainsVar((char *) rval.item, lval.lval))
            {
                Log(LOG_LEVEL_ERR, "Scalar variable %s.%s contains itself (non-convergent): %s", lval.scope, lval.lval,
                      (char *) rval.item);
                return false;
            }
            break;

        case RVAL_TYPE_LIST:
            for (const Rlist *rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (StringContainsVar(rp->item, lval.lval))
                {
                    Log(LOG_LEVEL_ERR, "List variable %s contains itself (non-convergent)", lval.lval);
                    return false;
                }
            }
            break;

        default:
            break;
        }
    }
    else
    {
        assert(STACK_FRAME_TYPE_BODY == LastStackFrame(ctx, 0)->type);
    }

    Scope *put_scope = ScopeGet(lval.scope);
    if (!put_scope)
    {
        put_scope = ScopeNew(lval.scope);
        if (!put_scope)
        {
            return false;
        }
    }

// Look for outstanding lists in variable rvals

    if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON)
    {
        Rlist *listvars = NULL;
        Rlist *scalars = NULL; // TODO what do we do with scalars?

        if (ScopeGetCurrent() && strcmp(ScopeGetCurrent()->scope, "this") != 0)
        {
            MapIteratorsFromRval(ctx, ScopeGetCurrent()->scope, &listvars, &scalars, rval);

            if (listvars != NULL)
            {
                Log(LOG_LEVEL_ERR, "Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"",
                      lval.lval, ScopeGetCurrent()->scope);
            }

            RlistDestroy(listvars);
            RlistDestroy(scalars);
        }
    }

    // FIX: lval is stored with array params as part of the lval for legacy reasons.
    char *final_lval = VarRefToString(lval, false);

    CfAssoc *assoc = HashLookupElement(put_scope->hashtable, final_lval);
    if (assoc)
    {
        if (CompareVariableValue(rval, assoc) != 0)
        {
            /* Different value, bark and replace */
            if (!UnresolvedVariables(assoc, rval.type))
            {
                Log(LOG_LEVEL_INFO, "Replaced value of variable '%s' in scope '%s'", lval.lval, put_scope->scope);
            }
            RvalDestroy(assoc->rval);
            assoc->rval = RvalCopy(rval);
            assoc->dtype = type;
        }
    }
    else
    {
        if (!HashInsertElement(put_scope->hashtable, final_lval, rval, type))
        {
            ProgrammingError("Hash table is full");
        }
    }

    free(final_lval);
    return true;
}
Example #22
0
static Rlist *RlistParseStringBounded(char *left,
                                      char *right, int *n)
{
    Rlist *newlist = NULL;
    char str2[CF_MAXVARSIZE];
    char *s = left;
    char *s2 = str2;
    bool precede = false;  //set if we just encountred escaping character
    bool ignore = true;    //set if we're outside quotation marks
    bool skipped = true;   //set if a separating comma is behind us
    char *extract = NULL;

    if (n!=NULL)
    {
        *n = 0;
    }

    memset(str2, 0, CF_MAXVARSIZE);

    while (*s && s < right)
    {
        if (*s != '\\')
        {
            if (precede)
            {
                if (*s != '\\' && *s != '"')
                {
                    Log(LOG_LEVEL_ERR, "Presence of illegal %c after escaping character", *s);
                    goto clean;
                }
                else
                {
                    *s2++ = *s;
                }
                precede = false;
            }
            else
            {
                if (*s == '"')
                {
                    if (ignore)
                    {
                        if (skipped != true)
                        {
                            Log(LOG_LEVEL_ERR, "Quotation marks \" should follow commas");
                            goto clean;
                        }
                        ignore = false;
                        extract = s2;
                    }
                    else
                    {
                        *s2='\0';
                        Log(LOG_LEVEL_VERBOSE, "Extracted string [%s] of length (%d)", extract,
                               (size_t) (s2 - extract));
                        RlistAppendScalar(&newlist, extract);
                        ignore = true;
                        extract = NULL;
                        if (n != NULL)
                        {
                            *n += 1;
                        }
                    }
                    skipped = false;
                }
                else if (*s == ',')
                {
                    if (ignore)
                    {
                        if (skipped == false)
                        {
                            skipped = true;
                        }
                        else
                        {
                            Log(LOG_LEVEL_ERR, "Only one comma should separate different list elements");
                            goto clean;
                        }
                    }
                    else
                    {
                        *s2++ = *s;
                    }
                }
                else
                {
                    if (ignore == true && *s != ' ')
                    {
                        Log(LOG_LEVEL_ERR, "Only white characters are permitted outside of list elements. Character %c is illegal.", *s);
                        goto clean;
                    }
                    *s2++ = *s;
                }
            }
        }
        else
        {
            if (precede)
            {
                *s2++ = '\\';
                precede = false;
            }
            else
            {
                precede = true;
            }
        }
        s++;
    }
    if (ignore)
    {
        return newlist;
    }
    else
    {
        goto clean;
    }
  clean:
    if (newlist)
    {
        RlistDestroy(newlist);
    }
    return NULL;
}
Example #23
0
static int HailServer(EvalContext *ctx, char *host)
{
    AgentConnection *conn;
    char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], peer[CF_MAXVARSIZE], ipv4[CF_MAXVARSIZE],
        digest[CF_MAXVARSIZE], user[CF_SMALLBUF];
    bool gotkey;
    char reply[8];

    FileCopy fc = {
        .portnumber = (short) ParseHostname(host, peer),
    };

    snprintf(ipv4, CF_MAXVARSIZE, "%s", Hostname2IPString(peer));
    Address2Hostkey(ipv4, digest);
    GetCurrentUserName(user, CF_SMALLBUF);

    if (INTERACTIVE)
    {
        CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Using interactive key trust...\n");

        gotkey = HavePublicKey(user, peer, digest) != NULL;

        if (!gotkey)
        {
            gotkey = HavePublicKey(user, ipv4, digest) != NULL;
        }

        if (!gotkey)
        {
            printf("WARNING - You do not have a public key from host %s = %s\n", host, ipv4);
            printf("          Do you want to accept one on trust? (yes/no)\n\n--> ");

            while (true)
            {
                if (fgets(reply, 8, stdin) == NULL)
                {
                    FatalError(ctx, "EOF trying to read answer from terminal");
                }

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

                if (strcmp(reply, "yes") == 0)
                {
                    printf(" -> Will trust the key...\n");
                    fc.trustkey = true;
                    break;
                }
                else if (strcmp(reply, "no") == 0)
                {
                    printf(" -> Will not trust the key...\n");
                    fc.trustkey = false;
                    break;
                }
                else
                {
                    printf(" !! Please reply yes or no...(%s)\n", reply);
                }
            }
        }
    }

/* Continue */

#ifdef __MINGW32__

    CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
    CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, fc.portnumber,
          REMOTE_AGENT_OPTIONS);
    CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");

#else /* !__MINGW32__ */

    if (BACKGROUND)
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Hailing %s : %u, with options \"%s\" (parallel)\n", peer, fc.portnumber,
              REMOTE_AGENT_OPTIONS);
    }
    else
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
        CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, fc.portnumber,
              REMOTE_AGENT_OPTIONS);
        CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n");
    }

#endif /* !__MINGW32__ */

    fc.servers = RlistFromSplitString(peer, '*');

    if (fc.servers == NULL || strcmp(fc.servers->item, "localhost") == 0)
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "No hosts are registered to connect to");
        return false;
    }
    else
    {
        int err = 0;
        conn = NewServerConnection(fc, false, &err);

        if (conn == NULL)
        {
            RlistDestroy(fc.servers);
            CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> No suitable server responded to hail\n");
            return false;
        }
    }

/* Check trust interaction*/

    HailExec(conn, peer, recvbuffer, sendbuffer);

    RlistDestroy(fc.servers);

    return true;
}

/********************************************************************/
/* Level 2                                                          */
/********************************************************************/

static void KeepControlPromises(EvalContext *ctx, Policy *policy)
{
    Rval retval;

    RUNATTR.copy.trustkey = false;
    RUNATTR.copy.encrypt = true;
    RUNATTR.copy.force_ipv4 = false;
    RUNATTR.copy.portnumber = SHORT_CFENGINEPORT;

/* Keep promised agent behaviour - control bodies */

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

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

            if (!EvalContextVariableGet(ctx, (VarRef) { NULL, "control_runagent", cp->lval }, &retval, NULL))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in runagent control body", cp->lval);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0)
            {
                RUNATTR.copy.force_ipv4 = BooleanFromString(retval.item);
                CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET force_ipv4 = %d\n", RUNATTR.copy.force_ipv4);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0)
            {
                RUNATTR.copy.trustkey = BooleanFromString(retval.item);
                CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET trustkey = %d\n", RUNATTR.copy.trustkey);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0)
            {
                RUNATTR.copy.encrypt = BooleanFromString(retval.item);
                CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET encrypt = %d\n", RUNATTR.copy.encrypt);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0)
            {
                RUNATTR.copy.portnumber = (short) IntFromString(retval.item);
                CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET default portnumber = %u\n", (int) RUNATTR.copy.portnumber);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0)
            {
                /*
                 * Only process this option if are is no -b or -i options specified on
                 * command line.
                 */
                if (BACKGROUND || INTERACTIVE)
                {
                    CfOut(OUTPUT_LEVEL_ERROR, "",
                          "Warning: 'background_children' setting from 'body runagent control' is overriden by command-line option.");
                }
                else
                {
                    BACKGROUND = BooleanFromString(retval.item);
                }
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0)
            {
                MAXCHILD = (short) IntFromString(retval.item);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0)
            {
                OUTPUT_TO_FILE = BooleanFromString(retval.item);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0)
            {
                if (IsAbsPath(retval.item))
                {
                    strncpy(OUTPUT_DIRECTORY, retval.item, CF_BUFSIZE - 1);
                    CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET output direcory to = %s\n", OUTPUT_DIRECTORY);
                }
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0)
            {
                RUNATTR.copy.timeout = (short) IntFromString(retval.item);
                continue;
            }

            if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0)
            {
                if (HOSTLIST == NULL)       // Don't override if command line setting
                {
                    HOSTLIST = retval.item;
                }

                continue;
            }
        }
    }

    if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER, &retval))
    {
        LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60;
    }

}
Example #24
0
File: expand.c Project: 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);
}
Example #25
0
static int NewSQLColumns(char *table, Rlist *columns, char ***name_table, char ***type_table, int **size_table,
                         int **done)
{
    int i, no_of_cols = RlistLen(columns);
    Rlist *cols, *rp;

    *name_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1));
    *type_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1));
    *size_table = (int *) xmalloc(sizeof(int) * (no_of_cols + 1));
    *done = (int *) xmalloc(sizeof(int) * (no_of_cols + 1));

    for (i = 0, rp = columns; rp != NULL; rp = rp->next, i++)
    {
        (*done)[i] = 0;

        cols = RlistFromSplitString(RlistScalarValue(rp), ',');

        if (!cols)
        {
            Log(LOG_LEVEL_ERR, "No columns promised for table '%s' - makes no sense", table);
            return false;
        }

        if (cols->val.item == NULL)
        {
            Log(LOG_LEVEL_ERR, "Malformed column promise for table '%s' - found not even a name", table);
            free(*name_table);
            free(*type_table);
            free(*size_table);
            free(*done);
            return false;
        }

        (*name_table)[i] = xstrdup(RlistScalarValue(cols));

        if (cols->next == NULL)
        {
            Log(LOG_LEVEL_ERR, "Malformed column '%s' promised for table '%s' - missing a type", (*name_table)[i],
                  table);
            free(*name_table);
            free(*type_table);
            free(*size_table);
            free(*done);
            return false;
        }

        (*type_table)[i] = xstrdup(RlistScalarValue(cols->next));

        if (cols->next->next == NULL)
        {
            (*size_table)[i] = 0;
        }
        else
        {
            if (cols->next->next->val.item)
            {
                (*size_table)[i] = IntFromString(RlistScalarValue(cols->next->next));
            }
            else
            {
                (*size_table)[i] = 0;
            }
        }

        RlistDestroy(cols);
    }

    return true;
}