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); }
void *FindAndVerifyStoragePromises(EvalContext *ctx, Promise *pp) { PromiseBanner(pp); FindStoragePromiserObjects(ctx, pp); return (void *) NULL; }
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); } }
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; }
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; } }
void *FindAndVerifyStoragePromises(EvalContext *ctx, Promise *pp, const ReportContext *report_context) { PromiseBanner(pp); FindStoragePromiserObjects(ctx, pp, report_context); return (void *) NULL; }
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; } }
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); }
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); }
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); }
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; }
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; }
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); }
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; }
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; }
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"); }
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); }
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; }
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); }
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; }
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); }
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; }
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 */ } }
PromiseResult FindAndVerifyFilesPromises(EvalContext *ctx, Promise *pp) { PromiseBanner(pp); return FindFilePromiserObjects(ctx, pp); }
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; }
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; }
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); }
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; }
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); }
PromiseResult FindAndVerifyStoragePromises(EvalContext *ctx, const Promise *pp) { PromiseBanner(pp); return FindStoragePromiserObjects(ctx, pp); }