Пример #1
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);
}
Пример #2
0
void *FindAndVerifyStoragePromises(EvalContext *ctx, Promise *pp)
{
    PromiseBanner(pp);
    FindStoragePromiserObjects(ctx, pp);

    return (void *) NULL;
}
Пример #3
0
PromiseResult VerifyDatabasePromises(EvalContext *ctx, const Promise *pp)
{
    PromiseBanner(ctx, pp);

    Attributes a = GetDatabaseAttributes(ctx, pp);

    if (!CheckDatabaseSanity(&a, pp))
    {
        return PROMISE_RESULT_FAIL;
    }

    if (strcmp(a.database.type, "sql") == 0)
    {
        return VerifySQLPromise(ctx, &a, pp);
    }
    else if (strcmp(a.database.type, "ms_registry") == 0)
    {
#if defined(__MINGW32__)
        return VerifyRegistryPromise(ctx, &a, pp);
#endif
        return PROMISE_RESULT_NOOP;
    }
    else
    {
        ProgrammingError("Unknown database type '%s'", a.database.type);
    }
}
Пример #4
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;
}
Пример #5
0
void VerifyDatabasePromises(Promise *pp)
{
    Attributes a = { {0} };

    if (pp->done)
    {
        return;
    }

    PromiseBanner(pp);

    a = GetDatabaseAttributes(pp);

    if (!CheckDatabaseSanity(a, pp))
    {
        return;
    }

    if (strcmp(a.database.type, "sql") == 0)
    {
        VerifySQLPromise(a, pp);
        return;
    }

    if (strcmp(a.database.type, "ms_registry") == 0)
    {
#if defined(__MINGW32__)
        VerifyRegistryPromise(a, pp);
#endif
        return;
    }
}
Пример #6
0
void *FindAndVerifyStoragePromises(EvalContext *ctx, Promise *pp, const ReportContext *report_context)
{
    PromiseBanner(pp);
    FindStoragePromiserObjects(ctx, pp, report_context);

    return (void *) NULL;
}
Пример #7
0
void VerifyDatabasePromises(struct Promise *pp)

{ struct Attributes a = {{0}};

if (pp->done)
   {
   return;
   }
 
PromiseBanner(pp);
 
a = GetDatabaseAttributes(pp);

if (!CheckDatabaseSanity(a,pp))
   {
   return;
   }

if (strcmp(a.database.type,"sql") == 0)
   {
   VerifySQLPromise(a,pp);
   return;
   }

if (strcmp(a.database.type,"ms_registry") == 0)
   {
   VerifyRegistryPromise(a,pp);
   return;
   }
}
Пример #8
0
void VerifyEnvironmentsPromise(Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    Promise *pexp;

    a = GetEnvironmentsAttributes(pp);

    if (EnvironmentsSanityChecks(a, pp))
    {
        thislock = AcquireLock("virtual", VUQNAME, CFSTARTTIME, a, pp, false);

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

        CF_OCCUR++;

        PromiseBanner(pp);
        NewScalar("this", "promiser", pp->promiser, cf_str);

        pexp = ExpandDeRefPromise("this", pp);
        VerifyEnvironments(a, pp);
        DeletePromise(pexp);
    }

    YieldCurrentLock(thislock);
}
Пример #9
0
void VerifyEnvironmentsPromise(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    Promise *pexp;

    a = GetEnvironmentsAttributes(ctx, pp);

    if (EnvironmentsSanityChecks(a, pp))
    {
        thislock = AcquireLock(ctx, "virtual", VUQNAME, CFSTARTTIME, a.transaction, pp, false);

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

        PromiseBanner(pp);
        ScopeNewSpecialScalar(ctx, "this", "promiser", pp->promiser, DATA_TYPE_STRING);

        pexp = ExpandDeRefPromise(ctx, "this", pp);
        VerifyEnvironments(ctx, a, pp);
        PromiseDestroy(pexp);
    }

    YieldCurrentLock(thislock);
}
Пример #10
0
PromiseResult VerifyMeasurementPromise(EvalContext *ctx, double *measurement, const Promise *pp)
{
    if (EvalContextPromiseIsDone(ctx, pp))
    {
        if (pp->comment)
        {
            Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s' (comment: %s), already done", pp->promiser, pp->comment);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s', already done", pp->promiser);
        }

        return PROMISE_RESULT_NOOP;
    }

    PromiseBanner(pp);

    Attributes a = GetMeasurementAttributes(ctx, pp);

    if (!CheckMeasureSanity(a.measure, pp))
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Measurement promise is not valid");
        return PROMISE_RESULT_INTERRUPTED;
    }

    return VerifyMeasurement(ctx, measurement, a, pp);
}
Пример #11
0
static PromiseResult VerifyProcesses(EvalContext *ctx, Attributes a, const 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 PROMISE_RESULT_SKIPPED;
    }

    PromiseBanner(pp);
    PromiseResult result = VerifyProcessOp(ctx, PROCESSTABLE, a, pp);

    YieldCurrentLock(thislock);

    return result;
}
Пример #12
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;
}
Пример #13
0
void VerifyProcesses(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(lockname, VUQNAME, CFSTARTTIME, a, pp, false);

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

    DeleteScalar("this", "promiser");
    NewScalar("this", "promiser", pp->promiser, cf_str);
    PromiseBanner(pp);
    VerifyProcessOp(PROCESSTABLE, a, pp);
    DeleteScalar("this", "promiser");

    YieldCurrentLock(thislock);
}
Пример #14
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;
    }

    PromiseBanner(ctx, pp);

    PromiseResult result = PROMISE_RESULT_SKIPPED;
    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));
    }

    YieldCurrentLock(thislock);

    return result;
}
Пример #15
0
static PromiseResult KeepServerPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param)
{
    assert(!param);
    PromiseBanner(ctx, pp);

    if (strcmp(pp->parent_promise_type->name, "vars") == 0)
    {
        return VerifyVarPromise(ctx, pp, NULL);
    }
    
    if (strcmp(pp->parent_promise_type->name, "classes") == 0)
    {
        return VerifyClassPromise(ctx, pp, NULL);
    }

    if (strcmp(pp->parent_promise_type->name, "access") == 0)
    {
        const char *resource_type =
            PromiseGetConstraintAsRval(pp, "resource_type", RVAL_TYPE_SCALAR);

        /* Default resource_type in access_rules is "path" */
        if (resource_type == NULL ||
            strcmp(resource_type, "path") == 0)
        {
            KeepFileAccessPromise(ctx, pp);
            return PROMISE_RESULT_NOOP;
        }
        else if (strcmp(resource_type, "literal") == 0)
        {
            KeepLiteralAccessPromise(ctx, pp, "literal");
            return PROMISE_RESULT_NOOP;
        }
        else if (strcmp(resource_type, "variable") == 0)
        {
            KeepLiteralAccessPromise(ctx, pp, "variable");
            return PROMISE_RESULT_NOOP;
        }
        else if (strcmp(resource_type, "query") == 0)
        {
            KeepQueryAccessPromise(ctx, pp);
            KeepReportDataSelectAccessPromise(pp);
            return PROMISE_RESULT_NOOP;
        }
        else if (strcmp(resource_type, "context") == 0)
        {
            KeepLiteralAccessPromise(ctx, pp, "context");
            return PROMISE_RESULT_NOOP;
        }
    }
    else if (strcmp(pp->parent_promise_type->name, "roles") == 0)
    {
        KeepServerRolePromise(ctx, pp);
        return PROMISE_RESULT_NOOP;
    }

    return PROMISE_RESULT_NOOP;
}
Пример #16
0
void VerifyExecPromise(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };

    a = GetExecAttributes(ctx, pp);

    ScopeNewSpecial(ctx, "this", "promiser", pp->promiser, DATA_TYPE_STRING);

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

    if (PromiseKeptExec(a, pp))
    {
        // cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "");
        ScopeDeleteSpecial("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, "");
        ScopeDeleteSpecial("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);
    ScopeDeleteSpecial("this", "promiser");
}
Пример #17
0
void VerifyReportPromise(struct Promise *pp)

{ struct Attributes a = {{0}};
  struct CfLock thislock;
  struct Rlist *rp;
  char unique_name[CF_EXPANDSIZE];

a = GetReportsAttributes(pp);

if (strcmp(pp->classes,"any") == 0)
   {
   CfOut(cf_verbose,""," --> Reports promises may not be in class \"any\"");
   return;
   }

snprintf(unique_name,CF_EXPANDSIZE-1,"%s_%d",pp->promiser,pp->lineno);
thislock = AcquireLock(unique_name,VUQNAME,CFSTARTTIME,a,pp,false);

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

PromiseBanner(pp);

cfPS(cf_verbose,CF_CHG,"",pp,a,"Report: %s", pp->promiser);

if (a.report.to_file)
   {
   CfFOut(a.report.to_file,cf_error,"","%s",pp->promiser);
   }
else
   {
   CfOut(cf_reporting,"","R: %s",pp->promiser);
   }

if (a.report.haveprintfile)
   {
   PrintFile(a,pp);
   }

if (a.report.showstate)
   {
   for (rp = a.report.showstate; rp != NULL; rp=rp->next)
      {
      ShowState(rp->item,a,pp);
      }
   }

if (a.report.havelastseen)
   {
   FriendStatus(a,pp);
   }
    
YieldCurrentLock(thislock);
}
Пример #18
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;
}
Пример #19
0
void VerifyReportPromise(Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    Rlist *rp;
    char unique_name[CF_EXPANDSIZE];

    a = GetReportsAttributes(pp);

    snprintf(unique_name, CF_EXPANDSIZE - 1, "%s_%zu", pp->promiser, pp->offset.line);
    thislock = AcquireLock(unique_name, VUQNAME, CFSTARTTIME, a, pp, false);

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

    PromiseBanner(pp);

    cfPS(cf_verbose, CF_CHG, "", pp, a, "Report: %s", pp->promiser);

    if (a.report.to_file)
    {
        CfFOut(a.report.to_file, cf_error, "", "%s", pp->promiser);
    }
    else
    {
        CfOut(cf_reporting, "", "R: %s", pp->promiser);
    }

    if (a.report.haveprintfile)
    {
        PrintFile(a, pp);
    }

    if (a.report.showstate)
    {
        for (rp = a.report.showstate; rp != NULL; rp = rp->next)
        {
            ShowState(rp->item);
        }
    }

    if (a.report.havelastseen)
    {
        /* Do nothing. Deprecated. */
    }

    YieldCurrentLock(thislock);
}
Пример #20
0
PromiseResult VerifyUsersPromise(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    char lockname[CF_BUFSIZE];

    a = GetUserAttributes(ctx, pp);

    if (!UserSanityCheck(a, pp))
    {
        return PROMISE_RESULT_FAIL;
    }

    PromiseBanner(pp);

    snprintf(lockname, CF_BUFSIZE - 1, "user-%s-%d", pp->promiser, a.users.policy);

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

    PromiseResult result = PROMISE_RESULT_NOOP;
    VerifyOneUsersPromise(pp->promiser, a.users, &result, a.transaction.action, ctx, &a, pp);

    switch (result) {
    case PROMISE_RESULT_NOOP:
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "User promise kept");
        break;
    case PROMISE_RESULT_FAIL:
    case PROMISE_RESULT_DENIED:
    case PROMISE_RESULT_TIMEOUT:
    case PROMISE_RESULT_INTERRUPTED:
    case PROMISE_RESULT_WARN:
        cfPS(ctx, LOG_LEVEL_INFO, result, pp, a, "User promise not kept");
        break;
    case PROMISE_RESULT_CHANGE:
        cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "User promise repaired");
        break;
    default:
        ProgrammingError("Unknown promise result");
        break;
    }
 

    YieldCurrentLock(thislock);
    return result;
}
Пример #21
0
void VerifyServices(EvalContext *ctx, Attributes a, Promise *pp, const ReportContext *report_context)
{
    CfLock thislock;

    // allow to start Cfengine windows executor without license
#ifdef __MINGW32__

    if ((LICENSES == 0) && (strcmp(WINSERVICE_NAME, pp->promiser) != 0))
    {
        return;
    }

#endif

    thislock = AcquireLock(pp->promiser, VUQNAME, CFSTARTTIME, a, pp, false);

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

    ScopeNewScalar("this", "promiser", pp->promiser, DATA_TYPE_STRING);
    PromiseBanner(ctx, pp);

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

    ScopeDeleteScalar("this", "promiser");
    YieldCurrentLock(thislock);
}
Пример #22
0
PromiseResult VerifyEnvironmentsPromise(EvalContext *ctx, const Promise *pp)
{
    CfLock thislock;

    Attributes a = GetEnvironmentsAttributes(ctx, pp);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (EnvironmentsSanityChecks(a, pp))
    {
        thislock = AcquireLock(ctx, "virtual", VUQNAME, CFSTARTTIME, a.transaction, pp, false);

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

        PromiseBanner(ctx, pp);

        bool excluded = false;
        Promise *pexp = ExpandDeRefPromise(ctx, pp, &excluded);
        if (excluded)
        {
            result = PROMISE_RESULT_SKIPPED;
        }
        else
        {
            result = VerifyEnvironments(ctx, a, pp);
        }

        PromiseDestroy(pexp);
    }

    YieldCurrentLock(thislock);

    return result;
}
Пример #23
0
static void VerifyExec(Attributes a, Promise *pp)
{
    CfLock thislock;
    char unsafeLine[CF_BUFSIZE], line[sizeof(unsafeLine) * 2], eventname[CF_BUFSIZE];
    char comm[20];
    char execstr[CF_EXPANDSIZE];
    int outsourced, count = 0;
    mode_t maskval = 0;
    FILE *pfp;
    char cmdOutBuf[CF_BUFSIZE];
    int cmdOutBufPos = 0;
    int lineOutLen;

    if (!IsExecutable(GetArg0(pp->promiser)))
    {
        cfPS(cf_error, CF_FAIL, "", pp, a, "%s promises to be executable but isn't\n", pp->promiser);

        if (strchr(pp->promiser, ' '))
        {
            CfOut(cf_verbose, "", "Paths with spaces must be inside escaped quoutes (e.g. \\\"%s\\\")", pp->promiser);
        }

        return;
    }
    else
    {
        CfOut(cf_verbose, "", " -> Promiser string contains a valid executable (%s) - ok\n", GetArg0(pp->promiser));
    }

    DeleteScalar("this", "promiser");
    NewScalar("this", "promiser", pp->promiser, cf_str);

    if (a.args)
    {
        snprintf(execstr, CF_EXPANDSIZE - 1, "%s %s", pp->promiser, a.args);
    }
    else
    {
        strncpy(execstr, pp->promiser, CF_BUFSIZE);
    }

    thislock = AcquireLock(execstr, VUQNAME, CFSTARTTIME, a, pp, false);

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

    PromiseBanner(pp);

    CfOut(cf_inform, "", " -> Executing \'%s\' ...(timeout=%d,owner=%ju,group=%ju)\n", execstr, a.contain.timeout,
          (uintmax_t)a.contain.owner, (uintmax_t)a.contain.group);

    BeginMeasure();

    if (DONTDO && !a.contain.preview)
    {
        CfOut(cf_error, "", "-> Would execute script %s\n", execstr);
    }
    else if (a.transaction.action != cfa_fix)
    {
        cfPS(cf_error, CF_WARN, "", pp, a, " !! Command \"%s\" needs to be executed, but only warning was promised",
             execstr);
    }
    else
    {
        CommPrefix(execstr, comm);

        if (a.transaction.background)
        {
#ifdef MINGW
            outsourced = true;
#else
            CfOut(cf_verbose, "", " -> Backgrounding job %s\n", execstr);
            outsourced = fork();
#endif
        }
        else
        {
            outsourced = false;
        }

        if (outsourced || !a.transaction.background)    // work done here: either by child or non-background parent
        {
            if (a.contain.timeout != CF_NOINT)
            {
                SetTimeOut(a.contain.timeout);
            }

#ifndef MINGW
            CfOut(cf_verbose, "", " -> (Setting umask to %jo)\n", (uintmax_t)a.contain.umask);
            maskval = umask(a.contain.umask);

            if (a.contain.umask == 0)
            {
                CfOut(cf_verbose, "", " !! Programming %s running with umask 0! Use umask= to set\n", execstr);
            }
#endif /* NOT MINGW */

            if (a.contain.useshell)
            {
                pfp =
                    cf_popen_shsetuid(execstr, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot,
                                      a.transaction.background);
            }
            else
            {
                pfp =
                    cf_popensetuid(execstr, "r", a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot,
                                   a.transaction.background);
            }

            if (pfp == NULL)
            {
                cfPS(cf_error, CF_FAIL, "cf_popen", pp, a, "!! Couldn't open pipe to command %s\n", execstr);
                YieldCurrentLock(thislock);
                return;
            }

            while (!feof(pfp))
            {
                if (ferror(pfp))        /* abortable */
                {
                    cfPS(cf_error, CF_TIMEX, "ferror", pp, a, "!! Command pipe %s\n", execstr);
                    cf_pclose(pfp);
                    YieldCurrentLock(thislock);
                    return;
                }

                CfReadLine(unsafeLine, CF_BUFSIZE - 1, pfp);
                ReplaceStr(unsafeLine, line, sizeof(line), "%", "%%");  // escape format char

                if (strstr(line, "cfengine-die"))
                {
                    break;
                }

                if (ferror(pfp))        /* abortable */
                {
                    cfPS(cf_error, CF_TIMEX, "ferror", pp, a, "!! Command pipe %s\n", execstr);
                    cf_pclose(pfp);
                    YieldCurrentLock(thislock);
                    return;
                }

                if (a.contain.preview)
                {
                    PreviewProtocolLine(line, execstr);
                }

                if (a.module)
                {
                    ModuleProtocol(execstr, line, !a.contain.nooutput);
                }
                else if (!a.contain.nooutput && NonEmptyLine(line))
                {
                    lineOutLen = strlen(comm) + strlen(line) + 12;

                    // if buffer is to small for this line, output it directly
                    if (lineOutLen > sizeof(cmdOutBuf))
                    {
                        CfOut(cf_cmdout, "", "Q: \"...%s\": %s\n", comm, line);
                    }
                    else
                    {
                        if (cmdOutBufPos + lineOutLen > sizeof(cmdOutBuf))
                        {
                            CfOut(cf_cmdout, "", "%s", cmdOutBuf);
                            cmdOutBufPos = 0;
                        }
                        sprintf(cmdOutBuf + cmdOutBufPos, "Q: \"...%s\": %s\n", comm, line);
                        cmdOutBufPos += (lineOutLen - 1);
                    }
                    count++;
                }
            }
#ifdef MINGW
            if (outsourced)     // only get return value if we waited for command execution
            {
                cf_pclose(pfp);
            }
            else
            {
                cf_pclose_def(pfp, a, pp);
            }
#else /* NOT MINGW */
            cf_pclose_def(pfp, a, pp);
#endif
        }

        if (count)
        {
            if (cmdOutBufPos)
            {
                CfOut(cf_cmdout, "", "%s", cmdOutBuf);
            }

            CfOut(cf_cmdout, "", "I: Last %d quoted lines were generated by promiser \"%s\"\n", count, execstr);
        }

        if (a.contain.timeout != CF_NOINT)
        {
            alarm(0);
            signal(SIGALRM, SIG_DFL);
        }

        CfOut(cf_inform, "", " -> Completed execution of %s\n", execstr);
#ifndef MINGW
        umask(maskval);
#endif
        YieldCurrentLock(thislock);

        snprintf(eventname, CF_BUFSIZE - 1, "Exec(%s)", execstr);

#ifndef MINGW
        if (a.transaction.background && outsourced)
        {
            CfOut(cf_verbose, "", " -> Backgrounded command (%s) is done - exiting\n", execstr);
            exit(0);
        }
#endif /* NOT MINGW */
    }
}
Пример #24
0
PromiseResult FindAndVerifyFilesPromises(EvalContext *ctx, Promise *pp)
{
    PromiseBanner(pp);
    return FindFilePromiserObjects(ctx, pp);
}
Пример #25
0
PromiseResult VerifyReportPromise(EvalContext *ctx, const Promise *pp)
{
    CfLock thislock;
    char unique_name[CF_EXPANDSIZE];

    Attributes a = GetReportsAttributes(ctx, pp);

    // We let AcquireLock worry about making a unique name
    snprintf(unique_name, CF_EXPANDSIZE - 1, "%s", pp->promiser);
    thislock = AcquireLock(ctx, unique_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false);

    // Handle return values before locks, as we always do this

    if (a.report.result)
    {
        // User-unwritable value last-result contains the useresult
        if (strlen(a.report.result) > 0)
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result[%s]", a.report.result);
        }
        else
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result");
        }

        VarRef *ref = VarRefParseFromBundle(unique_name, PromiseGetBundle(pp));
        EvalContextVariablePut(ctx, ref, pp->promiser, CF_DATA_TYPE_STRING, "source=bundle");
        VarRefDestroy(ref);

        if (thislock.lock)
        {
            YieldCurrentLock(thislock);
        }
        return PROMISE_RESULT_NOOP;
    }

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

    PromiseBanner(ctx, pp);

    if (a.transaction.action == cfa_warn)
    {
        cfPS(ctx, LOG_LEVEL_WARNING, PROMISE_RESULT_WARN, pp, a, "Need to repair reports promise: %s", pp->promiser);
        YieldCurrentLock(thislock);
        return PROMISE_RESULT_WARN;
    }

    if (a.report.to_file)
    {
        ReportToFile(a.report.to_file, pp->promiser);
    }
    else
    {
        ReportToLog(pp->promiser);
    }

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (a.report.haveprintfile)
    {
        if (!PrintFile(a.report.filename, a.report.numlines))
        {
            result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }
    }

    YieldCurrentLock(thislock);

    ClassAuditLog(ctx, pp, a, result);
    return result;
}
Пример #26
0
int VerifyMethod(EvalContext *ctx, char *attrname, Attributes a, Promise *pp)
{
    Bundle *bp;
    void *vp;
    FnCall *fp;
    char method_name[CF_EXPANDSIZE], qualified_method[CF_BUFSIZE], *method_deref;
    Rlist *params = NULL;
    int retval = false;
    CfLock thislock;
    char lockname[CF_BUFSIZE];

    if (a.havebundle)
    {
        if ((vp = ConstraintGetRvalValue(ctx, attrname, pp, RVAL_TYPE_FNCALL)))
        {
            fp = (FnCall *) vp;
            ExpandScalar(ctx, PromiseGetBundle(pp)->name, fp->name, method_name);
            params = fp->args;
        }
        else if ((vp = ConstraintGetRvalValue(ctx, attrname, pp, RVAL_TYPE_SCALAR)))
        {
            ExpandScalar(ctx, PromiseGetBundle(pp)->name, (char *) vp, method_name);
            params = NULL;
        }
        else
        {
            return false;
        }
    }

    GetLockName(lockname, "method", pp->promiser, params);

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

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

    PromiseBanner(pp);

    if (strncmp(method_name,"default:",strlen("default:")) == 0) // CF_NS == ':'
    {
        method_deref = strchr(method_name, CF_NS) + 1;
    }
    else if ((strchr(method_name, CF_NS) == NULL) && (strcmp(PromiseGetNamespace(pp), "default") != 0))
    {
        snprintf(qualified_method, CF_BUFSIZE, "%s%c%s", PromiseGetNamespace(pp), CF_NS, method_name);
        method_deref = qualified_method;
    }
    else
    {
         method_deref = method_name;
    }
    
    bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", method_deref);
    if (!bp)
    {
        bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", method_deref);
    }

    if (bp)
    {
        BannerSubBundle(bp, params);

        EvalContextStackPushBundleFrame(ctx, bp, a.inherit);

        ScopeClear(bp->name);
        BundleHashVariables(ctx, bp);

        ScopeAugment(ctx, bp, pp, params);

        retval = ScheduleAgentOperations(ctx, bp);

        GetReturnValue(ctx, bp->name, pp);

        EvalContextStackPopFrame(ctx);

        switch (retval)
        {
        case PROMISE_RESULT_FAIL:
            cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Method failed in some repairs or aborted");
            break;

        case PROMISE_RESULT_CHANGE:
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Method invoked repairs");
            break;

        default:
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Method verified");
            break;

        }

        for (const Rlist *rp = bp->args; rp; rp = rp->next)
        {
            const char *lval = rp->item;
            ScopeDeleteScalar((VarRef) { NULL, bp->name, lval });
        }
    }
    else
    {
        if (IsCf3VarString(method_name))
        {
            Log(LOG_LEVEL_ERR,
                  "A variable seems to have been used for the name of the method. In this case, the promiser also needs to contain the unique name of the method");
        }
        if (bp && (bp->name))
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Method '%s' was used but was not defined", bp->name);
        }
        else
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a,
                 "A method attempted to use a bundle '%s' that was apparently not defined", method_name);
        }
    }

    
    YieldCurrentLock(thislock);
    return retval;
}
Пример #27
0
void VerifyReportPromise(Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    Rlist *rp;
    char unique_name[CF_EXPANDSIZE];

    a = GetReportsAttributes(pp);

    snprintf(unique_name, CF_EXPANDSIZE - 1, "%s_%zu", pp->promiser, pp->offset.line);
    thislock = AcquireLock(unique_name, VUQNAME, CFSTARTTIME, a, pp, false);

    // Handle return values before locks, as we always do this

    if (a.report.result)
    {
        // User-unwritable value last-result contains the useresult
        if (strlen(a.report.result) > 0)
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result[%s]", a.report.result);
        }
        else
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result");
        }

        NewScalar(pp->bundle, unique_name, pp->promiser, cf_str);
        return;
    }
       
    // Now do regular human reports
    
    if (thislock.lock == NULL)
    {
        return;
    }

    PromiseBanner(pp);

    cfPS(cf_verbose, CF_CHG, "", pp, a, "Report: %s", pp->promiser);

    if (a.report.to_file)
    {
        CfFOut(a.report.to_file, cf_error, "", "%s", pp->promiser);
    }
    else
    {
        CfOut(cf_reporting, "", "R: %s", pp->promiser);
    }

    if (a.report.haveprintfile)
    {
        PrintFile(a, pp);
    }

    if (a.report.showstate)
    {
        for (rp = a.report.showstate; rp != NULL; rp = rp->next)
        {
            ShowState(rp->item);
        }
    }

    if (a.report.havelastseen)
    {
        /* Do nothing. Deprecated. */
    }

    YieldCurrentLock(thislock);
}
Пример #28
0
PromiseResult VerifyMethod(EvalContext *ctx, const Rval call, Attributes a, const Promise *pp)
{
    const Rlist *args = NULL;
    Buffer *method_name = BufferNew();
    switch (call.type)
    {
    case RVAL_TYPE_FNCALL:
    {
        const FnCall *fp = RvalFnCallValue(call);
        ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, fp->name, method_name);
        args = fp->args;
        int arg_index = 0;
        while (args)
        {
           ++arg_index;
           if (strcmp(args->val.item, CF_NULL_VALUE) == 0)
           {
               Log(LOG_LEVEL_DEBUG, "Skipping invokation of method '%s' due to null-values in argument '%d'",
                   fp->name, arg_index);
               BufferDestroy(method_name);
               return PROMISE_RESULT_SKIPPED;
           }
           args = args->next;
        }
        args = fp->args;
        EvalContextSetBundleArgs(ctx, args);
    }
    break;

    case RVAL_TYPE_SCALAR:
    {
        ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name,
                     RvalScalarValue(call), method_name);
        args = NULL;
    }
    break;

    default:
        BufferDestroy(method_name);
        return PROMISE_RESULT_NOOP;
    }

    char lockname[CF_BUFSIZE];
    GetLockName(lockname, "method", pp->promiser, args);

    CfLock thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    if (thislock.lock == NULL)
    {
        BufferDestroy(method_name);
        return PROMISE_RESULT_SKIPPED;
    }

    PromiseBanner(ctx, pp);

    const Bundle *bp = EvalContextResolveBundleExpression(ctx, PromiseGetPolicy(pp), BufferData(method_name), "agent");

    if (!bp)
    {
        bp = EvalContextResolveBundleExpression(ctx, PromiseGetPolicy(pp), BufferData(method_name), "common");
    }

    PromiseResult result = PROMISE_RESULT_NOOP;

    if (bp)
    {
        if (a.transaction.action == cfa_warn) // don't skip for dry-runs (ie ignore DONTDO)
        {
            result = PROMISE_RESULT_WARN;
            cfPS(ctx, LOG_LEVEL_WARNING, result, pp, a, "Bundle '%s' should be invoked, but only a warning was promised!", BufferData(method_name));
        }
        else
        {
            BundleBanner(bp, args);
            EvalContextStackPushBundleFrame(ctx, bp, args, a.inherit);

            /* Clear all array-variables that are already set in the sub-bundle.
               Otherwise, array-data accumulates between multiple bundle evaluations.
               Note: for bundles invoked multiple times via bundlesequence, array
               data *does* accumulate. */
            VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, bp->ns, bp->name, NULL);
            Variable *var;
            while ((var = VariableTableIteratorNext(iter)))
            {
                if (!var->ref->num_indices)
                {
                    continue;
                }
                EvalContextVariableRemove(ctx, var->ref);
            }
            VariableTableIteratorDestroy(iter);

            BundleResolve(ctx, bp);

            result = ScheduleAgentOperations(ctx, bp);

            GetReturnValue(ctx, bp, pp);

            EvalContextStackPopFrame(ctx);
            switch (result)
            {
            case PROMISE_RESULT_SKIPPED:
                // if a bundle returns 'skipped', meaning that all promises were locked in the bundle,
                // we explicitly consider the method 'kept'
                result = PROMISE_RESULT_NOOP;
                // intentional fallthru

            case PROMISE_RESULT_NOOP:
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Method '%s' verified", bp->name);
                break;

            case PROMISE_RESULT_WARN:
                cfPS(ctx, LOG_LEVEL_WARNING, PROMISE_RESULT_WARN, pp, a, "Method '%s' invoked repairs, but only warnings promised", bp->name);
                break;

            case PROMISE_RESULT_CHANGE:
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Method '%s' invoked repairs", bp->name);
                break;

            case PROMISE_RESULT_FAIL:
            case PROMISE_RESULT_DENIED:
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Method '%s' failed in some repairs", bp->name);
                break;

            default: // PROMISE_RESULT_INTERRUPTED, TIMEOUT
                cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Method '%s' aborted in some repairs", bp->name);
                break;
            }
        }

        for (const Rlist *rp = bp->args; rp; rp = rp->next)
        {
            const char *lval = RlistScalarValue(rp);
            VarRef *ref = VarRefParseFromBundle(lval, bp);
            EvalContextVariableRemove(ctx, ref);
            VarRefDestroy(ref);
        }
    }
    else
    {
        if (IsCf3VarString(BufferData(method_name)))
        {
            Log(LOG_LEVEL_ERR,
                "A variable seems to have been used for the name of the method. In this case, the promiser also needs to contain the unique name of the method");
        }

        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a,
             "A method attempted to use a bundle '%s' that was apparently not defined",
             BufferData(method_name));
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

    YieldCurrentLock(thislock);
    BufferDestroy(method_name);
    EndBundleBanner(bp);

    return result;
}
Пример #29
0
void VerifyReportPromise(EvalContext *ctx, Promise *pp)
{
    Attributes a = { {0} };
    CfLock thislock;
    char unique_name[CF_EXPANDSIZE];

    a = GetReportsAttributes(ctx, pp);

    snprintf(unique_name, CF_EXPANDSIZE - 1, "%s_%zu", pp->promiser, pp->offset.line);
    thislock = AcquireLock(ctx, unique_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false);

    // Handle return values before locks, as we always do this

    if (a.report.result)
    {
        // User-unwritable value last-result contains the useresult
        if (strlen(a.report.result) > 0)
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result[%s]", a.report.result);
        }
        else
        {
            snprintf(unique_name, CF_BUFSIZE, "last-result");
        }

        VarRef *ref = VarRefParseFromBundle(unique_name, PromiseGetBundle(pp));
        EvalContextVariablePut(ctx, ref, (Rval) {
            pp->promiser, RVAL_TYPE_SCALAR
        }, DATA_TYPE_STRING);
        VarRefDestroy(ref);
        return;
    }

    // Now do regular human reports

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

    PromiseBanner(pp);

    if (a.transaction.action == cfa_warn)
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_WARN, pp, a, "Need to repair reports promise: %s", pp->promiser);
        YieldCurrentLock(thislock);
        return;
    }

    cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Report: %s", pp->promiser);

    if (a.report.to_file)
    {
        ReportToFile(a.report.to_file, pp->promiser);
    }
    else
    {
        Log(LOG_LEVEL_NOTICE, "R: %s", pp->promiser);
    }

    if (a.report.haveprintfile)
    {
        PrintFile(ctx, a, pp);
    }

    if (a.report.showstate)
    {
        /* Do nothing. Deprecated. */
    }

    if (a.report.havelastseen)
    {
        /* Do nothing. Deprecated. */
    }

    YieldCurrentLock(thislock);
}
Пример #30
0
PromiseResult FindAndVerifyStoragePromises(EvalContext *ctx, const Promise *pp)
{
    PromiseBanner(pp);
    return FindStoragePromiserObjects(ctx, pp);
}