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; } } }
void PolicyResolve(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) == 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); EvalContextStackPopFrame(ctx); } } for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) != 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); EvalContextStackPopFrame(ctx); } } for (size_t i = 0; i < SeqLength(policy->bodies); i++) { Body *bdp = SeqAt(policy->bodies, i); if (strcmp(bdp->name, "control") == 0) { ResolveControlBody(ctx, config, bdp); } } }
static bool VariableStateIncrement(PromiseIterator *iter, size_t index) { assert(index < SeqLength(iter->var_states)); CfAssoc *var = SeqAt(iter->vars, index); switch (var->rval.type) { case RVAL_TYPE_LIST: { Rlist *state = SeqAt(iter->var_states, index); assert(state); // find the next valid value, return false if there is none state = FirstRealEntry(state->next); SeqSet(iter->var_states, index, state); return state != NULL; } break; default: ProgrammingError("Unhandled case in switch"); } return false; }
void BundleResolve(EvalContext *ctx, const Bundle *bundle) { Log(LOG_LEVEL_DEBUG, "Resolving variables in bundle '%s' '%s'", bundle->type, bundle->name); for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *sp = SeqAt(bundle->promise_types, j); if (strcmp(bundle->type, "common") == 0 && strcmp(sp->name, "classes") == 0) { ResolveCommonClassPromises(ctx, sp); } } for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *sp = SeqAt(bundle->promise_types, j); if (strcmp(sp->name, "vars") == 0) { ResolveVariablesPromises(ctx, sp); } } }
// Returns true if line is filtered, IOW should not be included. static bool LineIsFiltered(const ExecConfig *config, const char *line) { // Check whether the line matches mail filters int include_filter_len = SeqLength(config->mailfilter_include_regex); int exclude_filter_len = SeqLength(config->mailfilter_exclude_regex); // Count messages as matched in include set if there is no include set. bool included = (include_filter_len == 0); bool excluded = false; if (include_filter_len > 0) { for (int i = 0; i < include_filter_len; i++) { if (StringMatchFullWithPrecompiledRegex(SeqAt(config->mailfilter_include_regex, i), line)) { included = true; } } } if (exclude_filter_len > 0) { for (int i = 0; i < exclude_filter_len; i++) { if (StringMatchFullWithPrecompiledRegex(SeqAt(config->mailfilter_exclude_regex, i), line)) { excluded = true; } } } return !included || excluded; }
// TODO: should be replaced by something not complected with loading static void ShowContext(EvalContext *ctx) { Seq *hard_contexts = SeqNew(1000, NULL); Seq *soft_contexts = SeqNew(1000, NULL); { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { if (cls->is_soft) { SeqAppend(soft_contexts, cls->name); } else { SeqAppend(hard_contexts, cls->name); } } ClassTableIteratorDestroy(iter); } SeqSort(soft_contexts, (SeqItemComparator)strcmp, NULL); SeqSort(hard_contexts, (SeqItemComparator)strcmp, NULL); Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------"); { Log(LOG_LEVEL_VERBOSE, "BEGIN Discovered hard classes:"); for (size_t i = 0; i < SeqLength(hard_contexts); i++) { const char *context = SeqAt(hard_contexts, i); Log(LOG_LEVEL_VERBOSE, "C: discovered hard class %s", context); } Log(LOG_LEVEL_VERBOSE, "END Discovered hard classes"); } Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------"); if (SeqLength(soft_contexts)) { Log(LOG_LEVEL_VERBOSE, "BEGIN initial soft classes:"); for (size_t i = 0; i < SeqLength(soft_contexts); i++) { const char *context = SeqAt(soft_contexts, i); Log(LOG_LEVEL_VERBOSE, "C: added soft class %s", context); } Log(LOG_LEVEL_VERBOSE, "END initial soft classes"); } SeqDestroy(hard_contexts); SeqDestroy(soft_contexts); }
static void EvaluateBundle(EvalContext *ctx, const Bundle *bp, const char * const *seq) { EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (int type = 0; seq[type] != NULL; type++) { const PromiseType *sp = BundleGetPromiseType((Bundle *)bp, seq[type]); /* Some promise types might not be there. */ if (!sp || SeqLength(sp->promises) == 0) { Log(LOG_LEVEL_DEBUG, "No promise type %s in bundle %s", seq[type], bp->name); continue; } EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } /* Check if we are having some other promise types which we * should evaluate. THIS IS ONLY FOR BACKWARD COMPATIBILITY! */ for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); /* Skipping evaluation of promise as this was evaluated in * loop above. */ if (!IsPromiseTypeNotInTypeSequence(sp->name, seq)) { Log(LOG_LEVEL_DEBUG, "Skipping subsequent evaluation of " "promise type %s in bundle %s", sp->name, bp->name); continue; } Log(LOG_LEVEL_WARNING, "Trying to evaluate unsupported/obsolete " "promise type %s in %s bundle %s", sp->name, bp->type, bp->name); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); }
void PolicyResolve(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { /* PRE-EVAL: common bundles: classes,vars. */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) == 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); /* PRE-EVAL classes,vars */ EvalContextStackPopFrame(ctx); } } /* * HACK: yet another pre-eval pass here, WHY? TODO remove, but test fails: * 00_basics/03_bodies/dynamic_inputs_findfiles.cf */ #if 1 /* PRE-EVAL: non-common bundles: only vars. */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) != 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); /* PRE-EVAL vars */ EvalContextStackPopFrame(ctx); } } #endif for (size_t i = 0; i < SeqLength(policy->bodies); i++) { Body *bdp = SeqAt(policy->bodies, i); if (strcmp(bdp->name, "control") == 0) { ResolveControlBody(ctx, config, bdp); } /* Collect all package managers data from policy as we don't know yet * which ones we will use. */ else if (strcmp(bdp->type, "package_module") == 0) { ResolvePackageManagerBody(ctx, bdp); } } }
static void RemoveRemotelyInjectedVars(const EvalContext *ctx, const Bundle *bundle) { const Seq *remote_var_promises = EvalContextGetRemoteVarPromises(ctx, bundle->name); if ((remote_var_promises == NULL) || SeqLength(remote_var_promises) == 0) { /* nothing to do here */ return; } size_t promises_length = SeqLength(remote_var_promises); Seq *remove_vars = SeqNew(promises_length, NULL); /* remove variables that have been attempted to be inserted into this * bundle */ /* TODO: this is expensive and should be removed! */ for (size_t i = 0; i < promises_length; i++) { const Promise *pp = (Promise *) SeqAt(remote_var_promises, i); VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, bundle->name, NULL); const Variable *var = VariableTableIteratorNext(iter); while (var != NULL) { /* variables are stored together with their original promises (org_pp) */ if (var->promise && var->promise->org_pp == pp) { Log(LOG_LEVEL_ERR, "Ignoring remotely-injected variable '%s'", var->ref->lval); /* avoid modifications of the variable table being iterated * over and avoid trying to remove the same variable twice */ SeqAppendOnce(remove_vars, (void *) var, PointerCmp); } var = VariableTableIteratorNext(iter); } VariableTableIteratorDestroy(iter); } /* iteration over the variable table done, time to remove the variables */ size_t remove_vars_length = SeqLength(remove_vars); for (size_t i = 0; i < remove_vars_length; i++) { Variable *var = (Variable *) SeqAt(remove_vars, i); if (var->ref != NULL) { EvalContextVariableRemove(ctx, var->ref); } } SeqDestroy(remove_vars); }
static void ShowPackages(FILE *out, Seq *package_entries) { for (size_t i = 0; i < SeqLength(package_entries); i++) { fprintf(out, "%s\n", SerializePackage(SeqAt(package_entries, i))); } }
void DeleteMountInfo(Seq *list) { for (size_t i = 0; i < SeqLength(list); i++) { Mount *entry = SeqAt(list, i); if (entry->host) { free(entry->host); } if (entry->source) { free(entry->source); } if (entry->mounton) { free(entry->mounton); } if (entry->options) { free(entry->options); } } SeqClear(list); }
static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); // ensure: if call and callee are resolved, then they have matching arity if (StringSafeEqual(cp->lval, "usebundle")) { if (cp->rval.type == RVAL_TYPE_FNCALL) { const FnCall *call = (const FnCall *)cp->rval.item; const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", call->name); if (!callee) { callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", call->name); } if (callee) { if (RlistLen(call->args) != RlistLen(callee->args)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, POLICY_ERROR_METHODS_BUNDLE_ARITY, call->name, RlistLen(callee->args), RlistLen(call->args))); success = false; } } } } } return success; }
static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ CleanReportBookFilterSet(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); bool server_bundle = strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0; bool common_bundle = strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0; if (server_bundle || common_bundle) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } } if (server_bundle) { EvaluateBundle(ctx, bp, SERVER_TYPESEQUENCE); } else if (common_bundle) { EvaluateBundle(ctx, bp, COMMON_TYPESEQUENCE); } } }
static bool RenderVariable(Writer *out, const char *content, size_t content_len, bool escaped, Seq *hash_stack) { JsonElement *var = NULL; if (strncmp(content, ".", content_len) == 0) { var = SeqAt(hash_stack, SeqLength(hash_stack) - 1); } else { var = LookupVariable(hash_stack, content, content_len); } if (!var) { return true; } switch (JsonGetElementType(var)) { case JSON_ELEMENT_TYPE_PRIMITIVE: return RenderVariablePrimitive(out, var, escaped); case JSON_ELEMENT_TYPE_CONTAINER: assert(false); return false; } assert(false); return false; }
static void ShowVariablesFormatted(EvalContext *ctx) { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL); Variable *v = NULL; Seq *seq = SeqNew(2000, free); while ((v = VariableTableIteratorNext(iter))) { char *varname = VarRefToString(v->ref, true); Writer *w = StringWriter(); switch (DataTypeToRvalType(v->type)) { case RVAL_TYPE_CONTAINER: JsonWriteCompact(w, RvalContainerValue(v->rval)); break; default: RvalWrite(w, v->rval); } const char *var_value; if (StringIsPrintable(StringWriterData(w))) { var_value = StringWriterData(w); } else { var_value = "<non-printable>"; } StringSet *tagset = EvalContextVariableTags(ctx, v->ref); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; xasprintf(&line, "%-40s %-60s %-40s", varname, var_value, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); WriterClose(w); free(varname); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-40s %-60s %-40s\n", "Variable name", "Variable value", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *variable = SeqAt(seq, i); printf("%s\n", variable); } SeqDestroy(seq); VariableTableIteratorDestroy(iter); }
static Body *IsBody(Seq *bodies, const char *ns, const char *key) { char fqname[CF_BUFSIZE]; for (size_t i = 0; i < SeqLength(bodies); i++) { Body *bp = SeqAt(bodies, i); // bp->namespace is where the body belongs, namespace is where we are now if (strchr(key, CF_NS) || strcmp(ns,"default") == 0) { if (strncmp(key,"default:",strlen("default:")) == 0) // CF_NS == ':' { strcpy(fqname,strchr(key,CF_NS)+1); } else { strcpy(fqname,key); } } else { snprintf(fqname,CF_BUFSIZE-1, "%s%c%s", ns, CF_NS, key); } if (strcmp(bp->name, fqname) == 0) { return bp; } } return NULL; }
char *EvalContextStackPath(const EvalContext *ctx) { Writer *path = StringWriter(); for (size_t i = 0; i < SeqLength(ctx->stack); i++) { StackFrame *frame = SeqAt(ctx->stack, i); switch (frame->type) { case STACK_FRAME_TYPE_BODY: WriterWriteF(path, "/%s", frame->data.body.owner->name); break; case STACK_FRAME_TYPE_BUNDLE: WriterWriteF(path, "/%s", frame->data.bundle.owner->name); break; case STACK_FRAME_TYPE_PROMISE_ITERATION: WriterWriteF(path, "/%s", frame->data.promise.owner->parent_promise_type->name); WriterWriteF(path, "/'%s'", frame->data.promise.owner->promiser); break; case STACK_FRAME_TYPE_PROMISE: break; } } return StringWriterClose(path); }
static void ResolveCommonClassPromises(EvalContext *ctx, PromiseType *pt) { assert(strcmp("classes", pt->name) == 0); assert(strcmp(pt->parent_bundle->type, "common") == 0); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); char *sp = NULL; if (VarClassExcluded(ctx, pp, &sp)) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as var-context %s is not relevant", pp->promiser, sp); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); } else { Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as var-context '%s' is not relevant", pp->promiser, sp); } continue; } ExpandPromise(ctx, pp, VerifyClassPromise, NULL); } }
void SeqAppendSeq(Seq *seq, const Seq *items) { for (size_t i = 0; i < SeqLength(items); i++) { SeqAppend(seq, SeqAt(items, i)); } }
PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp, PromiseActuator *ActOnPromise, void *param) { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; Promise *pcopy = DeRefCopyPromise(ctx, pp); MapIteratorsFromRval(ctx, PromiseGetBundle(pp), (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); if (pcopy->promisee.item != NULL) { MapIteratorsFromRval(ctx, PromiseGetBundle(pp), pp->promisee, &scalars, &lists, &containers); } for (size_t i = 0; i < SeqLength(pcopy->conlist); i++) { Constraint *cp = SeqAt(pcopy->conlist, i); MapIteratorsFromRval(ctx, PromiseGetBundle(pp), cp->rval, &scalars, &lists, &containers); } CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), lists); CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), scalars); CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), containers); PromiseResult result = ExpandPromiseAndDo(ctx, pcopy, lists, containers, ActOnPromise, param); PromiseDestroy(pcopy); RlistDestroy(lists); RlistDestroy(scalars); RlistDestroy(containers); return result; }
static void ShowContextsFormatted(EvalContext *ctx) { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; Seq *seq = SeqNew(1000, free); while ((cls = ClassTableIteratorNext(iter))) { char *class_name = ClassRefToString(cls->ns, cls->name); StringSet *tagset = EvalContextClassTags(ctx, cls->ns, cls->name); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; xasprintf(&line, "%-60s %-40s", class_name, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); free(class_name); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-60s %-40s\n", "Class name", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *context = SeqAt(seq, i); printf("%s\n", context); } SeqDestroy(seq); ClassTableIteratorDestroy(iter); }
bool CFTestD_GetServerQuery( ServerConnectionState *conn, char *recvbuffer, CFTestD_Config *config) { char query[CF_BUFSIZE]; Seq *report = config->report; const int report_len = config->report_len; ConnectionInfo *const conn_info = conn->conn_info; query[0] = '\0'; sscanf(recvbuffer, "QUERY %255[^\n]", query); if (strlen(query) == 0) { return false; } if (report_len == 0) { Log(LOG_LEVEL_INFO, "No report file argument so returning canned data from enterprise plugin server\n"); return CFTestD_ReturnQueryData(conn, query); } Log(LOG_LEVEL_INFO, "Report file argument specified. Returning report of length %d", report_len); const size_t n_report_lines = SeqLength(report); assert(n_report_lines > 1); char *ts = SeqAt(report, 0); char *header = StringFormat("CFR: 0 %s %d\n", ts, report_len); SendTransaction(conn_info, header, SafeStringLength(header), CF_MORE); free(header); for (size_t i = 1; i < n_report_lines; i++) { const char *report_line = SeqAt(report, i); SendTransaction(conn_info, report_line, SafeStringLength(report_line), CF_MORE); } const char end_reply[] = "QUERY complete"; SendTransaction(conn_info, end_reply, SafeStringLength(end_reply), CF_DONE); return true; }
static StackFrame *LastStackFrame(const EvalContext *ctx, size_t offset) { if (SeqLength(ctx->stack) <= offset) { return NULL; } return SeqAt(ctx->stack, SeqLength(ctx->stack) - 1 - offset); }
static JsonElement *LookupVariable(Seq *hash_stack, const char *name, size_t name_len) { assert(SeqLength(hash_stack) > 0); size_t num_comps = StringCountTokens(name, name_len, "."); JsonElement *base_var = NULL; { StringRef base_comp = StringGetToken(name, name_len, 0, "."); char *base_comp_str = xstrndup(base_comp.data, base_comp.len); for (ssize_t i = SeqLength(hash_stack) - 1; i >= 0; i--) { JsonElement *hash = SeqAt(hash_stack, i); if (!hash) { continue; } if (JsonGetElementType(hash) == JSON_ELEMENT_TYPE_CONTAINER && JsonGetContainerType(hash) == JSON_CONTAINER_TYPE_OBJECT) { JsonElement *var = JsonObjectGet(hash, base_comp_str); if (var) { base_var = var; break; } } } free(base_comp_str); } if (!base_var) { return NULL; } for (size_t i = 1; i < num_comps; i++) { if (JsonGetElementType(base_var) != JSON_ELEMENT_TYPE_CONTAINER || JsonGetContainerType(base_var) != JSON_CONTAINER_TYPE_OBJECT) { return NULL; } StringRef comp = StringGetToken(name, name_len, i, "."); char *comp_str = xstrndup(comp.data, comp.len); base_var = JsonObjectGet(base_var, comp_str); free(comp_str); if (!base_var) { return NULL; } } assert(base_var); return base_var; }
void BundleResolvePromiseType(EvalContext *ctx, const Bundle *bundle, const char *type, PromiseActuator *actuator) { for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, type) == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, actuator, NULL); } EvalContextStackPopFrame(ctx); } } }
static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ CleanReportBookFilterSet(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "access") != 0) && (strcmp(sp->name, "roles") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } } }
static void KeepPromiseBundles(EvalContext *ctx, Policy *policy, const ReportContext *report_context) { /* Dial up the generic promise expansion with a callback */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { CfOut(OUTPUT_LEVEL_ERROR, "", "Cannot implicitly evaluate bundle %s %s, as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "access") != 0) && (strcmp(sp->name, "roles") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushBundleFrame(ctx, bp, false); ScopeAugment(ctx, bp, NULL); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, report_context); } EvalContextStackPopFrame(ctx); } } } }
Promise *ExpandDeRefPromise(EvalContext *ctx, const char *scopeid, const Promise *pp) { Promise *pcopy; Rval returnval, final; CfDebug("ExpandDerefPromise()\n"); pcopy = xcalloc(1, sizeof(Promise)); returnval = ExpandPrivateRval(ctx, "this", (Rval) {pp->promiser, RVAL_TYPE_SCALAR }); pcopy->promiser = (char *) returnval.item; if (pp->promisee.item) { pcopy->promisee = EvaluateFinalRval(ctx, scopeid, pp->promisee, true, pp); } else { pcopy->promisee = (Rval) {NULL, RVAL_TYPE_NOPROMISEE }; } if (pp->classes) { pcopy->classes = xstrdup(pp->classes); } else { pcopy->classes = xstrdup("any"); } if (pcopy->promiser == NULL) { ProgrammingError("ExpandPromise returned NULL"); } pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; /* No further type checking should be necessary here, already done by CheckConstraintTypeMatch */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); Rval returnval; if (ExpectedDataType(cp->lval) == DATA_TYPE_BUNDLE) { final = ExpandBundleReference(ctx, scopeid, cp->rval); } else {
/** * The "roles" access promise is for remote class activation by means of * cf-runagent -D: * * pp->promiser is a regex to match classes. * pp->conlist is an slist of usernames. */ static void KeepServerRolePromise(EvalContext *ctx, const Promise *pp) { size_t pos = acl_SortedInsert(&roles_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } size_t i = SeqLength(pp->conlist); while (i > 0) { i--; Constraint *cp = SeqAt(pp->conlist, i); char const * const authorizer = CF_REMROLE_BODIES[REMOTE_ROLE_AUTHORIZE].lval; if (strcmp(cp->lval, authorizer) == 0) { if (cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "Right-hand side of authorize promise for '%s' should be a list", pp->promiser); } else if (IsDefinedClass(ctx, cp->classes)) { for (const Rlist *rp = cp->rval.item; rp != NULL; rp = rp->next) { /* The "roles" access promise currently only supports * listing usernames to admit access to, nothing more. */ struct resource_acl *racl = &roles_acl->acls[pos]; size_t zret = StrList_Append(&racl->admit.usernames, RlistScalarValue(rp)); if (zret == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "StrList_Append: %s", GetErrorStr()); exit(255); } } } } else if (strcmp(cp->lval, "comment") != 0 && strcmp(cp->lval, "handle") != 0 && /* Are there other known list constraints ? if not, skip this: */ cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_WARNING, "Unrecognised promise '%s' for %s", cp->lval, pp->promiser); } } }
static void SavePackages(const char *database_filename, Seq *package_entries) { FILE *packages_file = fopen(database_filename, "w"); for (size_t i = 0; i < SeqLength(package_entries); i++) { fprintf(packages_file, "%s\n", SerializePackage(SeqAt(package_entries, i))); } fclose(packages_file); }