Esempio n. 1
0
void PromiseIteratorUpdateVariable(EvalContext *ctx, const PromiseIterator *iter)
{
    for (size_t i = 0; i < SeqLength(iter->vars); i++)
    {
        CfAssoc *iter_var = SeqAt(iter->vars, i);

        const Rlist *state = SeqAt(iter->var_states, i);

        if (!state || state->val.type == RVAL_TYPE_FNCALL)
        {
            continue;
        }

        assert(state->val.type == RVAL_TYPE_SCALAR);

        switch (iter_var->dtype)
        {
        case CF_DATA_TYPE_STRING_LIST:
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_STRING, "source=promise");
            break;
        case CF_DATA_TYPE_INT_LIST:
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_INT, "source=promise");
            break;
        case CF_DATA_TYPE_REAL_LIST:
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_REAL, "source=promise");
            break;
        default:
            assert(false);
            break;
        }
    }
}
Esempio n. 2
0
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp)
{
    FnCall *service_bundle = PromiseGetConstraintAsRval(pp, "service_bundle", RVAL_TYPE_FNCALL);
    PromiseResult result = PROMISE_RESULT_NOOP;
    if (!service_bundle)
    {
        service_bundle = PromiseGetConstraintAsRval(pp, "service_bundle", RVAL_TYPE_SCALAR);
    }

    if (!service_bundle)
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' cannot be resolved as a bundle", pp->promiser);
        return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

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

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

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

    const Bundle *bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", service_bundle->name);
    if (!bp)
    {
        bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", service_bundle->name);
    }

    if (!bp)
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' could not be invoked successfully", pp->promiser);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

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

    return result;
}
Esempio n. 3
0
File: expand.c Progetto: awsiv/core
static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp,
                                        Rlist *lists, Rlist *containers,
                                        PromiseActuator *ActOnPromise, void *param)
{
    const char *handle = PromiseGetHandle(pp);

    EvalContextStackPushPromiseFrame(ctx, pp, true);

    PromiseIterator *iter_ctx = NULL;
    size_t i = 0;
    PromiseResult result = PROMISE_RESULT_NOOP;
    Buffer *expbuf = BufferNew();
    for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); i++, PromiseIteratorNext(iter_ctx))
    {
        if (handle)
        {
            // This ordering is necessary to get automated canonification
            BufferClear(expbuf);
            ExpandScalar(ctx, NULL, "this", handle, expbuf);
            CanonifyNameInPlace(BufferGet(expbuf));
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", BufferData(expbuf), CF_DATA_TYPE_STRING, "source=promise");
        }
        else
        {
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), CF_DATA_TYPE_STRING, "source=promise");
        }

        const Promise *pexp = EvalContextStackPushPromiseIterationFrame(ctx, i, iter_ctx);
        if (!pexp)
        {
            // excluded
            result = PromiseResultUpdate(result, PROMISE_RESULT_SKIPPED);
            continue;
        }

        PromiseResult iteration_result = ActOnPromise(ctx, pexp, param);

        NotifyDependantPromises(ctx, pexp, iteration_result);
        result = PromiseResultUpdate(result, iteration_result);

        if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0)
        {
            VerifyVarPromise(ctx, pexp, true);
        }

        EvalContextStackPopFrame(ctx);
    }

    BufferDestroy(expbuf);
    PromiseIteratorDestroy(iter_ctx);
    EvalContextStackPopFrame(ctx);

    return result;
}
Esempio n. 4
0
static void VerifyProcesses(EvalContext *ctx, Attributes a, Promise *pp)
{
    CfLock thislock;
    char lockname[CF_BUFSIZE];

    if (a.restart_class)
    {
        snprintf(lockname, CF_BUFSIZE - 1, "proc-%s-%s", pp->promiser, a.restart_class);
    }
    else
    {
        snprintf(lockname, CF_BUFSIZE - 1, "proc-%s-norestart", pp->promiser);
    }

    thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false);

    if (thislock.lock == NULL)
    {
        return;
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING);
    PromiseBanner(pp);
    VerifyProcessOp(ctx, PROCESSTABLE, a, pp);
    EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");

    YieldCurrentLock(thislock);
}
Esempio n. 5
0
static PromiseResult VerifyServices(EvalContext *ctx, Attributes a, const Promise *pp)
{
    CfLock thislock;

    thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    if (thislock.lock == NULL)
    {
        return PROMISE_RESULT_SKIPPED;
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, CF_DATA_TYPE_STRING, "source=promise");
    PromiseBanner(pp);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (strcmp(a.service.service_type, "windows") == 0)
    {
#ifdef __MINGW32__
        result = PromiseResultUpdate(result, VerifyWindowsService(ctx, a, pp));
#else
        Log(LOG_LEVEL_INFO, "Service type windows not supported on this platform.");
#endif
    }
    else
    {
        result = PromiseResultUpdate(result, DoVerifyServices(ctx, a, pp));
    }

    EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
    YieldCurrentLock(thislock);

    return result;
}
Esempio n. 6
0
static PromiseResult VerifyServices(EvalContext *ctx, Attributes a, Promise *pp)
{
    CfLock thislock;

    thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    if (thislock.lock == NULL)
    {
        return PROMISE_RESULT_SKIPPED;
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING, "goal=state,source=promise");
    PromiseBanner(pp);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (strcmp(a.service.service_type, "windows") == 0)
    {
        result = PromiseResultUpdate(result, VerifyWindowsService(ctx, a, pp));
    }
    else
    {
        result = PromiseResultUpdate(result, DoVerifyServices(ctx, a, pp));
    }

    EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
    YieldCurrentLock(thislock);

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

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

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

    RvalDestroy(call);

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

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

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

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

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

    RvalDestroy(call);

    return result;
}
Esempio n. 9
0
/**
 * @brief Sets both internal C variables as well as policy sys variables.
 *
 * Called at bootstrap and after reading policy_server.dat.
 * Changes sys.policy_hub and sys.policy_hub_port.
 * NULL is an acceptable value for new_policy_server. Could happen when an
 * already bootstrapped server re-parses its policies, and the
 * policy_server.dat file has been removed. Then this function will be called
 * with NULL as new_policy_server, and cf-serverd will keep running even
 * without a policy server set.
 *
 * @param ctx EvalContext is used to set related variables
 * @param new_policy_server can be 'host:port', same as policy_server.dat
 */
void EvalContextSetPolicyServer(EvalContext *ctx, const char *new_policy_server)
{
    // Remove variables if undefined policy server:
    if ( NULL_OR_EMPTY(new_policy_server) )
    {
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub" );
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub_port" );
        return;
    }

    PolicyServerSet(new_policy_server);
    const char *ip = PolicyServerGetIP();

    // Set the sys.policy_hub variable:
    if ( ip != NULL )
    {
        EvalContextVariablePutSpecial(  ctx,  SPECIAL_SCOPE_SYS,
                                        "policy_hub", ip,
                                        CF_DATA_TYPE_STRING,
                                        "source=bootstrap" );
    }
    else
    {
        EvalContextVariableRemoveSpecial(   ctx, SPECIAL_SCOPE_SYS,
                                            "policy_hub" );
    }

    // Set the sys.policy_hub_port variable:
    if (PolicyServerGetPort() != NULL)
    {
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS,
                                      "policy_hub_port", PolicyServerGetPort(),
                                      CF_DATA_TYPE_STRING,
                                      "source=bootstrap" );
    }
    else // Default value (CFENGINE_PORT_STR = "5308") is set
    {
        EvalContextVariablePutSpecial( ctx, SPECIAL_SCOPE_SYS,
                                       "policy_hub_port",
                                       CFENGINE_PORT_STR,
                                       CF_DATA_TYPE_STRING,
                                       "source=bootstrap" );
    }
}
Esempio n. 10
0
void VerifyExecPromise(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };

    a = GetExecAttributes(ctx, pp);

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING);

    if (!SyntaxCheckExec(a, pp))
    {
        // cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "");
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return;
    }

    if (PromiseKeptExec(a, pp))
    {
        // cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "");
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return;
    }

    char *lock_name = GetLockNameExec(a, pp);
    CfLock thislock = AcquireLock(ctx, lock_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    free(lock_name);

    if (thislock.lock == NULL)
    {
        // cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "");
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return;
    }

    PromiseBanner(pp);

    switch (RepairExec(ctx, a, pp))
    {
    case ACTION_RESULT_OK:
        // cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "");
        break;

    case ACTION_RESULT_TIMEOUT:
        // cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_TIMEOUT, pp, a, "");
        break;

    case ACTION_RESULT_FAILED:
        // cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "");
        break;

    default:
        ProgrammingError("Unexpected ActionResult value");
    }

    YieldCurrentLock(thislock);
    EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
}
Esempio n. 11
0
PromiseResult VerifyExecPromise(EvalContext *ctx, const Promise *pp)
{
    Attributes a = GetExecAttributes(ctx, pp);

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING, "source=promise");

    if (!SyntaxCheckExec(a, pp))
    {
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return PROMISE_RESULT_FAIL;
    }

    if (PromiseKeptExec(a, pp))
    {
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return PROMISE_RESULT_NOOP;
    }

    char *lock_name = GetLockNameExec(a, pp);
    CfLock thislock = AcquireLock(ctx, lock_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    free(lock_name);
    if (thislock.lock == NULL)
    {
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");
        return PROMISE_RESULT_SKIPPED;
    }

    PromiseBanner(pp);

    PromiseResult result = PROMISE_RESULT_NOOP;
    switch (RepairExec(ctx, a, pp, &result))
    {
    case ACTION_RESULT_OK:
        result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
        break;

    case ACTION_RESULT_TIMEOUT:
        result = PromiseResultUpdate(result, PROMISE_RESULT_TIMEOUT);
        break;

    case ACTION_RESULT_FAILED:
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        break;

    default:
        ProgrammingError("Unexpected ActionResult value");
    }

    YieldCurrentLock(thislock);
    EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser");

    return result;
}
Esempio n. 12
0
/* NULL is an acceptable value for new_policy_server. Could happen when an
 * already bootstrapped server re-parses its policies, and the
 * policy_server.dat file has been removed. Then this function will be called
 * with NULL as new_policy_server, and cf-serverd will keep running even
 * without a policy server set." */
void SetPolicyServer(EvalContext *ctx, const char *new_policy_server)
{
    if (new_policy_server)
    {
        snprintf(POLICY_SERVER, CF_MAX_IP_LEN, "%s", new_policy_server);
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "policy_hub", new_policy_server, DATA_TYPE_STRING, "source=bootstrap");
    }
    else
    {
        strcpy(POLICY_SERVER, "");
        EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "policy_hub");
    }
}
Esempio n. 13
0
void UpdateLastPolicyUpdateTime(EvalContext *ctx)
{
    // Get the timestamp on policy update
    struct stat sb;
    {
        char cf_promises_validated_filename[CF_MAXVARSIZE];
        snprintf(cf_promises_validated_filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
        MapName(cf_promises_validated_filename);

        if ((stat(cf_promises_validated_filename, &sb)) != 0)
        {
            return;
        }
    }
    
    char timebuf[26];
    cf_strtimestamp_local(sb.st_mtime, timebuf);
    
    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "last_policy_update", timebuf, DATA_TYPE_STRING, "source=agent");
}
Esempio n. 14
0
static PromiseResult FindFilePromiserObjects(EvalContext *ctx, Promise *pp)
{
    char *val = ConstraintGetRvalValue(ctx, "pathtype", pp, RVAL_TYPE_SCALAR);
    int literal = (PromiseGetConstraintAsBoolean(ctx, "copy_from", pp)) || ((val != NULL) && (strcmp(val, "literal") == 0));

/* Check if we are searching over a regular expression */

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (literal)
    {
        // Prime the promiser temporarily, may override later
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING);
        result = PromiseResultUpdate(result, VerifyFilePromise(ctx, pp->promiser, pp));
    }
    else                        // Default is to expand regex paths
    {
        result = PromiseResultUpdate(result, LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyFilePromise));
    }

    return result;
}
Esempio n. 15
0
static void PutHandleVariable(EvalContext *ctx, const Promise *pp)
{
    char *handle_s;
    const char *existing_handle = PromiseGetHandle(pp);

    if (existing_handle != NULL)
    {
        // This ordering is necessary to get automated canonification
        handle_s = ExpandScalar(ctx, NULL, "this", existing_handle, NULL);
        CanonifyNameInPlace(handle_s);
    }
    else
    {
        handle_s = xstrdup(PromiseID(pp));                /* default handle */
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS,
                                  "handle", handle_s,
                                  CF_DATA_TYPE_STRING, "source=promise");
    free(handle_s);
}
Esempio n. 16
0
/* Sets variables */
static int RegExMatchSubString(EvalContext *ctx, pcre *rx, const char *teststring, int *start, int *end)
{
    int ovector[OVECCOUNT];
    int rc = 0;

    if ((rc = pcre_exec(rx, NULL, teststring, strlen(teststring), 0, 0, ovector, OVECCOUNT)) >= 0)
    {
        *start = ovector[0];
        *end = ovector[1];

        EvalContextVariableClearMatch(ctx);

        for (int i = 0; i < rc; i++)        /* make backref vars $(1),$(2) etc */
        {
            const char *backref_start = teststring + ovector[i * 2];
            int backref_len = ovector[i * 2 + 1] - ovector[i * 2];

            if (backref_len < CF_MAXVARSIZE)
            {
                char substring[CF_MAXVARSIZE];
                char *index = StringFromLong(i);
                strlcpy(substring, backref_start, MIN(CF_MAXVARSIZE, backref_len + 1));
                EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_MATCH, index, substring, CF_DATA_TYPE_STRING, "source=regex");
                free(index);
            }
        }
    }
    else
    {
        *start = 0;
        *end = 0;
    }

    pcre_free(rx);
    return rc >= 0;
}
Esempio n. 17
0
static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, Promise *pp)
{
    struct stat osb, oslb, dsb;
    Attributes a = { {0} };
    CfLock thislock;
    int exists;

    a = GetFilesAttributes(ctx, pp);

    if (!FileSanityChecks(ctx, path, a, pp))
    {
        return PROMISE_RESULT_NOOP;
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", path, DATA_TYPE_STRING);

    thislock = AcquireLock(ctx, path, VUQNAME, CFSTARTTIME, a.transaction, pp, false);

    if (thislock.lock == NULL)
    {
        return PROMISE_RESULT_NOOP;
    }

    LoadSetuid(a);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (lstat(path, &oslb) == -1)       /* Careful if the object is a link */
    {
        if ((a.create) || (a.touch))
        {
            if (!CfCreateFile(ctx, path, pp, a, &result))
            {
                goto exit;
            }
            else
            {
                exists = (lstat(path, &oslb) != -1);
            }
        }

        exists = false;
    }
    else
    {
        if ((a.create) || (a.touch))
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' exists as promised", path);
        }
        exists = true;
    }

    if ((a.havedelete) && (!exists))
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' does not exist as promised", path);
        goto exit;
    }

    if (!a.havedepthsearch)     /* if the search is trivial, make sure that we are in the parent dir of the leaf */
    {
        char basedir[CF_BUFSIZE];

        Log(LOG_LEVEL_DEBUG, "Direct file reference '%s', no search implied", path);
        snprintf(basedir, sizeof(basedir), "%s", path);

        if (strcmp(ReadLastNode(basedir), ".") == 0)
        {
            // Handle /.  notation for deletion of directories
            ChopLastNode(basedir);
            ChopLastNode(path);
        }

        ChopLastNode(basedir);
        if (chdir(basedir))
        {
            Log(LOG_LEVEL_ERR, "Failed to chdir into '%s'", basedir);
        }
    }

    if (exists && (!VerifyFileLeaf(ctx, path, &oslb, a, pp, &result)))
    {
        if (!S_ISDIR(oslb.st_mode))
        {
            goto exit;
        }
    }

    if (stat(path, &osb) == -1)
    {
        if ((a.create) || (a.touch))
        {
            if (!CfCreateFile(ctx, path, pp, a, &result))
            {
                goto exit;
            }
            else
            {
                exists = true;
            }
        }
        else
        {
            exists = false;
        }
    }
    else
    {
        if (!S_ISDIR(osb.st_mode))
        {
            if (a.havedepthsearch)
            {
                Log(LOG_LEVEL_WARNING,
                    "depth_search (recursion) is promised for a base object '%s' that is not a directory",
                      path);
                goto exit;
            }
        }

        exists = true;
    }

    if (a.link.link_children)
    {
        if (stat(a.link.source, &dsb) != -1)
        {
            if (!S_ISDIR(dsb.st_mode))
            {
                Log(LOG_LEVEL_ERR, "Cannot promise to link the children of '%s' as it is not a directory!",
                      a.link.source);
                goto exit;
            }
        }
    }

/* Phase 1 - */

    if (exists && ((a.havedelete) || (a.haverename) || (a.haveperms) || (a.havechange) || (a.transformer)))
    {
        lstat(path, &oslb);     /* if doesn't exist have to stat again anyway */

        DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result);

        /* normally searches do not include the base directory */

        if (a.recursion.include_basedir)
        {
            int save_search = a.havedepthsearch;

            /* Handle this node specially */

            a.havedepthsearch = false;
            DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result);
            a.havedepthsearch = save_search;
        }
        else
        {
            /* unless child nodes were repaired, set a promise kept class */
            if (!IsDefinedClass(ctx, "repaired" , PromiseGetNamespace(pp)))
            {
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Basedir '%s' not promising anything", path);
            }
        }

        if (((a.change.report_changes) == FILE_CHANGE_REPORT_CONTENT_CHANGE) || ((a.change.report_changes) == FILE_CHANGE_REPORT_ALL))
        {
            if (a.havedepthsearch)
            {
                PurgeHashes(ctx, NULL, a, pp);
            }
            else
            {
                PurgeHashes(ctx, path, a, pp);
            }
        }
    }

/* Phase 2a - copying is potentially threadable if no followup actions */

    if (a.havecopy)
    {
        result = PromiseResultUpdate(result, ScheduleCopyOperation(ctx, path, a, pp));
    }

/* Phase 2b link after copy in case need file first */

    if ((a.havelink) && (a.link.link_children))
    {
        result = PromiseResultUpdate(result, ScheduleLinkChildrenOperation(ctx, path, a.link.source, 1, a, pp));
    }
    else if (a.havelink)
    {
        result = PromiseResultUpdate(result, ScheduleLinkOperation(ctx, path, a.link.source, a, pp));
    }

/* Phase 3 - content editing */

    if (a.haveedit)
    {
        result = PromiseResultUpdate(result, ScheduleEditOperation(ctx, path, a, pp));
    }

// Once more in case a file has been created as a result of editing or copying

    exists = (stat(path, &osb) != -1);

    if (exists && (S_ISREG(osb.st_mode)))
    {
        VerifyFileLeaf(ctx, path, &osb, a, pp, &result);
    }

    if (!exists && a.havechange)
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to monitor '%s' for changes, but file does not exist", path);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

exit:
    result = PromiseResultUpdate(result, SaveSetuid(ctx, a, pp));
    YieldCurrentLock(thislock);

    return result;
}
Esempio n. 18
0
/**
 * Evaluate the relevant control body, and set the
 * relevant fields in #ctx and #config.
 */
static void ResolveControlBody(EvalContext *ctx, GenericAgentConfig *config,
                               const Body *control_body)
{
    const char *filename = control_body->source_path;

    assert(CFG_CONTROLBODY[COMMON_CONTROL_MAX].lval == NULL);

    const ConstraintSyntax *body_syntax = NULL;
    for (int i = 0; CONTROL_BODIES[i].constraints != NULL; i++)
    {
        body_syntax = CONTROL_BODIES[i].constraints;

        if (strcmp(control_body->type, CONTROL_BODIES[i].body_type) == 0)
        {
            break;
        }
    }
    if (body_syntax == NULL)
    {
        FatalError(ctx, "Unknown control body: %s", control_body->type);
    }

    char *scope;
    assert(strcmp(control_body->name, "control") == 0);
    xasprintf(&scope, "control_%s", control_body->type);

    Log(LOG_LEVEL_DEBUG, "Initiate control variable convergence for scope '%s'", scope);

    EvalContextStackPushBodyFrame(ctx, NULL, control_body, NULL);

    for (size_t i = 0; i < SeqLength(control_body->conlist); i++)
    {
        const char *lval;
        Rval evaluated_rval;
        size_t lineno;

        /* Use nested scope to constrain cp. */
        {
            Constraint *cp = SeqAt(control_body->conlist, i);
            lval   = cp->lval;
            lineno = cp->offset.line;

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

            if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_BUNDLESEQUENCE].lval) == 0)
            {
                evaluated_rval = ExpandPrivateRval(ctx, NULL, scope,
                                                   cp->rval.item, cp->rval.type);
            }
            else
            {
                evaluated_rval = EvaluateFinalRval(ctx, control_body->parent_policy,
                                                   NULL, scope, cp->rval,
                                                   true, NULL);
            }

        } /* Close scope: assert we only use evaluated_rval, not cp->rval. */

        VarRef *ref = VarRefParseFromScope(lval, scope);
        EvalContextVariableRemove(ctx, ref);

        DataType rval_proper_datatype =
            ConstraintSyntaxGetDataType(body_syntax, lval);
        if (evaluated_rval.type != DataTypeToRvalType(rval_proper_datatype))
        {
            Log(LOG_LEVEL_ERR,
                "Attribute '%s' in %s:%zu is of wrong type, skipping",
                lval, filename, lineno);
            VarRefDestroy(ref);
            RvalDestroy(evaluated_rval);
            continue;
        }

        bool success = EvalContextVariablePut(
            ctx, ref, evaluated_rval.item, rval_proper_datatype,
            "source=promise");
        if (!success)
        {
            Log(LOG_LEVEL_ERR,
                "Attribute '%s' in %s:%zu can't be added, skipping",
                lval, filename, lineno);
            VarRefDestroy(ref);
            RvalDestroy(evaluated_rval);
            continue;
        }

        VarRefDestroy(ref);

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_OUTPUT_PREFIX].lval) == 0)
        {
            strlcpy(VPREFIX, RvalScalarValue(evaluated_rval),
                    sizeof(VPREFIX));
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_DOMAIN].lval) == 0)
        {
            strlcpy(VDOMAIN, RvalScalarValue(evaluated_rval),
                    sizeof(VDOMAIN));
            Log(LOG_LEVEL_VERBOSE, "SET domain = %s", VDOMAIN);

            EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "domain");
            EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost");
            snprintf(VFQNAME, CF_MAXVARSIZE, "%s.%s", VUQNAME, VDOMAIN);
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost",
                                          VFQNAME, CF_DATA_TYPE_STRING,
                                          "inventory,source=agent,attribute_name=Host name");
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain",
                                          VDOMAIN, CF_DATA_TYPE_STRING,
                                          "source=agent");
            EvalContextClassPutHard(ctx, VDOMAIN, "source=agent");
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_INPUTS].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_inputs %s",
                RvalScalarValue(evaluated_rval));
            config->ignore_missing_inputs = BooleanFromString(
                RvalScalarValue(evaluated_rval));
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_BUNDLES].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_bundles %s",
                RvalScalarValue(evaluated_rval));
            config->ignore_missing_bundles = BooleanFromString(
                RvalScalarValue(evaluated_rval));
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET cache_system_functions %s",
                RvalScalarValue(evaluated_rval));
            bool cache_system_functions = BooleanFromString(
                RvalScalarValue(evaluated_rval));
            EvalContextSetEvalOption(ctx, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS,
                                     cache_system_functions);
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PROTOCOL_VERSION].lval) == 0)
        {
            config->protocol_version = ProtocolVersionParse(
                RvalScalarValue(evaluated_rval));
            Log(LOG_LEVEL_VERBOSE, "SET common protocol_version: %s",
                PROTOCOL_VERSION_STRING[config->protocol_version]);
        }

        /* Those are package_inventory and package_module common control body options */
        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PACKAGE_INVENTORY].lval) == 0)
        {
            AddDefaultInventoryToContext(ctx, RvalRlistValue(evaluated_rval));
            Log(LOG_LEVEL_VERBOSE, "SET common package_inventory list");
        }
        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PACKAGE_MODULE].lval) == 0)
        {
            AddDefaultPackageModuleToContext(ctx, RvalScalarValue(evaluated_rval));
            Log(LOG_LEVEL_VERBOSE, "SET common package_module: %s",
                RvalScalarValue(evaluated_rval));
        }

        if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_GOALPATTERNS].lval) == 0)
        {
            /* Ignored */
        }

        RvalDestroy(evaluated_rval);
    }

    EvalContextStackPopFrame(ctx);
    free(scope);
}
Esempio n. 19
0
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, Promise *pp)
{
    FnCall *default_bundle = NULL;
    Rlist *args = NULL;

// Need to set up the default service pack to eliminate syntax

    if (ConstraintGetRvalValue(ctx, "service_bundle", pp, RVAL_TYPE_SCALAR) == NULL)
    {
        switch (a.service.service_policy)
        {
        case SERVICE_POLICY_START:
            RlistAppendScalar(&args, pp->promiser);
            RlistAppendScalar(&args, "start");
            break;

        case SERVICE_POLICY_RESTART:
            RlistAppendScalar(&args, pp->promiser);
            RlistAppendScalar(&args, "restart");
            break;

        case SERVICE_POLICY_RELOAD:
            RlistAppendScalar(&args, pp->promiser);
            RlistAppendScalar(&args, "reload");
            break;
            
        case SERVICE_POLICY_STOP:
        case SERVICE_POLICY_DISABLE:
        default:
            RlistAppendScalar(&args, pp->promiser);
            RlistAppendScalar(&args, "stop");
            break;

        }

        default_bundle = FnCallNew("standard_services", args);

        PromiseAppendConstraint(pp, "service_bundle", (Rval) {default_bundle, RVAL_TYPE_FNCALL }, "any", false);
        a.havebundle = true;
    }

// Set $(this.service_policy) for flexible bundle adaptation

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

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

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

    const Bundle *bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", default_bundle->name);
    if (!bp)
    {
        bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", default_bundle->name);
    }

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (default_bundle && bp == NULL)
    {
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' could not be invoked successfully", pp->promiser);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

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

    return result;
}
Esempio n. 20
0
static void ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param)
{
    const char *handle = PromiseGetHandle(pp);
    char v[CF_MAXVARSIZE];

    EvalContextStackPushPromiseFrame(ctx, pp, true);

    PromiseIterator *iter_ctx = NULL;
    for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); PromiseIteratorNext(iter_ctx))
    {
        EvalContextStackPushPromiseIterationFrame(ctx, iter_ctx);
        char number[CF_SMALLBUF];

        /* Allow $(this.handle) etc variables */

        if (PromiseGetBundle(pp)->source_path)
        {
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_filename",PromiseGetBundle(pp)->source_path, DATA_TYPE_STRING);
            snprintf(number, CF_SMALLBUF, "%zu", pp->offset.line);
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_linenumber", number, DATA_TYPE_STRING);
        }

        snprintf(v, CF_MAXVARSIZE, "%d", (int) getuid());
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_uid", v, DATA_TYPE_INT);
        snprintf(v, CF_MAXVARSIZE, "%d", (int) getgid());
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_gid", v, DATA_TYPE_INT);

        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "bundle", PromiseGetBundle(pp)->name, DATA_TYPE_STRING);
        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "namespace", PromiseGetNamespace(pp), DATA_TYPE_STRING);

        /* Must expand $(this.promiser) here for arg dereferencing in things
           like edit_line and methods, but we might have to
           adjust again later if the value changes  -- need to qualify this
           so we don't expand too early for some other promsies */

        if (pp->has_subbundles)
        {
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pp->promiser, DATA_TYPE_STRING);
        }

        if (handle)
        {
            char tmp[CF_EXPANDSIZE];
            // This ordering is necessary to get automated canonification
            ExpandScalar(ctx, NULL, "this", handle, tmp);
            CanonifyNameInPlace(tmp);
            Log(LOG_LEVEL_DEBUG, "Expanded handle to '%s'", tmp);
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", tmp, DATA_TYPE_STRING);
        }
        else
        {
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), DATA_TYPE_STRING);
        }

        Promise *pexp = ExpandDeRefPromise(ctx, pp);

        assert(ActOnPromise);
        ActOnPromise(ctx, pexp, param);

        if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0)
        {
            VerifyVarPromise(ctx, pexp, true);
        }

        PromiseDestroy(pexp);

        EvalContextStackPopFrame(ctx);
    }

    PromiseIteratorDestroy(iter_ctx);
    EvalContextStackPopFrame(ctx);
}
Esempio n. 21
0
File: expand.c Progetto: tzz/core
static void ResolveControlBody(EvalContext *ctx, GenericAgentConfig *config, const Body *control_body)
{
    const ConstraintSyntax *body_syntax = NULL;
    Rval returnval;

    assert(strcmp(control_body->name, "control") == 0);

    for (int i = 0; CONTROL_BODIES[i].constraints != NULL; i++)
    {
        body_syntax = CONTROL_BODIES[i].constraints;

        if (strcmp(control_body->type, CONTROL_BODIES[i].body_type) == 0)
        {
            break;
        }
    }

    if (body_syntax == NULL)
    {
        FatalError(ctx, "Unknown agent");
    }

    char scope[CF_BUFSIZE];
    snprintf(scope, CF_BUFSIZE, "%s_%s", control_body->name, control_body->type);
    Log(LOG_LEVEL_DEBUG, "Initiate control variable convergence for scope '%s'", scope);

    EvalContextStackPushBodyFrame(ctx, NULL, control_body, NULL);

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

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

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_BUNDLESEQUENCE].lval) == 0)
        {
            returnval = ExpandPrivateRval(ctx, NULL, scope, cp->rval.item, cp->rval.type);
        }
        else
        {
            returnval = EvaluateFinalRval(ctx, control_body->parent_policy, NULL, scope, cp->rval, true, NULL);
        }

        VarRef *ref = VarRefParseFromScope(cp->lval, scope);
        EvalContextVariableRemove(ctx, ref);

        if (!EvalContextVariablePut(ctx, ref, returnval.item, ConstraintSyntaxGetDataType(body_syntax, cp->lval), "source=promise"))
        {
            Log(LOG_LEVEL_ERR, "Rule from %s at/before line %zu", control_body->source_path, cp->offset.line);
        }

        VarRefDestroy(ref);

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_OUTPUT_PREFIX].lval) == 0)
        {
            strncpy(VPREFIX, returnval.item, CF_MAXVARSIZE);
        }

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_DOMAIN].lval) == 0)
        {
            strcpy(VDOMAIN, cp->rval.item);
            Log(LOG_LEVEL_VERBOSE, "SET domain = %s", VDOMAIN);
            EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "domain");
            EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost");
            snprintf(VFQNAME, CF_MAXVARSIZE, "%s.%s", VUQNAME, VDOMAIN);
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost", VFQNAME, DATA_TYPE_STRING, "inventory,source=agent,group=Host name");
            EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain", VDOMAIN, DATA_TYPE_STRING, "source=agent");
            EvalContextClassPutHard(ctx, VDOMAIN, "source=agent");
        }

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_INPUTS].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_inputs %s", RvalScalarValue(cp->rval));
            config->ignore_missing_inputs = BooleanFromString(cp->rval.item);
        }

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_BUNDLES].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_bundles %s", RvalScalarValue(cp->rval));
            config->ignore_missing_bundles = BooleanFromString(cp->rval.item);
        }

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS].lval) == 0)
        {
            Log(LOG_LEVEL_VERBOSE, "SET cache_system_functions %s", RvalScalarValue(cp->rval));
            bool cache_system_functions = BooleanFromString(RvalScalarValue(cp->rval));
            EvalContextSetEvalOption(ctx, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS,
                                     cache_system_functions);
        }

        if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_GOALPATTERNS].lval) == 0)
        {
            /* Ignored */
            continue;
        }

        RvalDestroy(returnval);
    }

    EvalContextStackPopFrame(ctx);
}
Esempio n. 22
0
static bool ScheduleRun(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, ExecConfig *exec_config)
{
    Log(LOG_LEVEL_VERBOSE, "Sleeping for pulse time %d seconds...", CFPULSETIME);
    sleep(CFPULSETIME);         /* 1 Minute resolution is enough */

    /*
     * FIXME: this logic duplicates the one from cf-serverd.c. Unify ASAP.
     */

    if (CheckNewPromises(config, *policy) == RELOAD_FULL)
    {
        /* Full reload */

        Log(LOG_LEVEL_INFO, "Re-reading promise file '%s'", config->input_file);

        EvalContextClear(ctx);

        strcpy(VDOMAIN, "undefined.domain");

        PolicyDestroy(*policy);
        *policy = NULL;

        {
            char *existing_policy_server = ReadPolicyServerFile(GetWorkDir());
            SetPolicyServer(ctx, existing_policy_server);
            free(existing_policy_server);
        }

        EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "policy_hub", POLICY_SERVER, DATA_TYPE_STRING, "goal=update,source=bootstrap");

        DetectEnvironment(ctx, false, true);

        EvalContextClassPutHard(ctx, CF_AGENTTYPES[AGENT_TYPE_EXECUTOR], "goal=state,cfe_internal,source=agent");

        time_t t = SetReferenceTime();
        UpdateTimeClasses(ctx, t);

        GenericAgentConfigSetBundleSequence(config, NULL);

        *policy = GenericAgentLoadPolicy(ctx, config);
        ExecConfigUpdate(ctx, *policy, exec_config);

        SetFacility(exec_config->log_facility);
    }
    else
    {
        /* Environment reload */

        EvalContextClear(ctx);

        DetectEnvironment(ctx, false, false);

        time_t t = SetReferenceTime();
        UpdateTimeClasses(ctx, t);
    }

    {
        StringSetIterator it = StringSetIteratorInit(exec_config->schedule);
        const char *time_context = NULL;
        while ((time_context = StringSetIteratorNext(&it)))
        {
            if (IsDefinedClass(ctx, time_context, NULL))
            {
                Log(LOG_LEVEL_VERBOSE, "Waking up the agent at %s ~ %s", ctime(&CFSTARTTIME), time_context);
                return true;
            }
        }
    }

    Log(LOG_LEVEL_VERBOSE, "Nothing to do at %s", ctime(&CFSTARTTIME));
    return false;
}