static void KeepServerPromise(Promise *pp) { char *sp = NULL; if (!IsDefinedClass(pp->classes)) { CfOut(cf_verbose, "", "Skipping whole promise, as context is %s\n", pp->classes); return; } if (VarClassExcluded(pp, &sp)) { CfOut(cf_verbose, "", "\n"); CfOut(cf_verbose, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); CfOut(cf_verbose, "", "Skipping whole next promise (%s), as var-context %s is not relevant\n", pp->promiser, sp); CfOut(cf_verbose, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); return; } if (strcmp(pp->agentsubtype, "classes") == 0) { KeepClassContextPromise(pp); return; } sp = (char *) GetConstraintValue("resource_type", pp, CF_SCALAR); if (strcmp(pp->agentsubtype, "access") == 0 && sp && strcmp(sp, "literal") == 0) { KeepLiteralAccessPromise(pp, "literal"); return; } if (strcmp(pp->agentsubtype, "access") == 0 && sp && strcmp(sp, "query") == 0) { KeepQueryAccessPromise(pp, "query"); return; } if (strcmp(pp->agentsubtype, "access") == 0 && sp && strcmp(sp, "context") == 0) { KeepLiteralAccessPromise(pp, "context"); return; } /* Default behaviour is file access */ if (strcmp(pp->agentsubtype, "access") == 0) { KeepFileAccessPromise(pp); return; } if (strcmp(pp->agentsubtype, "roles") == 0) { KeepServerRolePromise(pp); return; } }
void DefaultVarPromise(Promise *pp) { char *regex = GetConstraintValue("if_match_regex", pp, CF_SCALAR); Rval rval; enum cfdatatype dt; Rlist *rp; bool okay = true; dt = GetVariable("this", pp->promiser, &rval); switch (dt) { case cf_str: case cf_int: case cf_real: if (regex && !FullTextMatch(regex,rval.item)) { return; } if (regex == NULL) { return; } break; case cf_slist: case cf_ilist: case cf_rlist: if (regex) { for (rp = (Rlist *) rval.item; rp != NULL; rp = rp->next) { if (FullTextMatch(regex,rp->item)) { okay = false; break; } } if (okay) { return; } } break; default: break; } DeleteScalar(pp->bundle, pp->promiser); ConvergeVarHashPromise(pp->bundle, pp, true); }
void EndMeasurePromise(struct timespec start, Promise *pp) { char id[CF_BUFSIZE], *mid = NULL; mid = GetConstraintValue("measurement_class", pp, CF_SCALAR); if (mid) { snprintf(id, CF_BUFSIZE, "%s:%s:%.100s", (char *) mid, pp->agentsubtype, pp->promiser); Chop(id); EndMeasure(id, start); } }
void PromiseBanner(Promise *pp) { char handle[CF_MAXVARSIZE]; const char *sp; if ((sp = GetConstraintValue("handle", pp, RVAL_TYPE_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(enterprise only)"); } CfOut(cf_verbose, "", "\n"); CfOut(cf_verbose, "", " .........................................................\n"); if (VERBOSE || DEBUG) { printf("%s> Promise's handle: %s\n", VPREFIX, handle); printf("%s> Promise made by: \"%s\"", VPREFIX, pp->promiser); } if (pp->promisee.item) { if (VERBOSE) { printf("\n%s> Promise made to (stakeholders): ", VPREFIX); ShowRval(stdout, pp->promisee); } } if (VERBOSE) { printf("\n"); } if (pp->ref) { CfOut(cf_verbose, "", "\n"); CfOut(cf_verbose, "", " Comment: %s\n", pp->ref); } CfOut(cf_verbose, "", " .........................................................\n"); CfOut(cf_verbose, "", "\n"); }
void KeepLiteralAccessPromise(Promise *pp, char *type) { Constraint *cp; Rlist *rp; Auth *ap, *dp; char *handle = GetConstraintValue("handle", pp, CF_SCALAR); if (handle == NULL) { CfOut(cf_error, "", "Access to literal server data requires you to define a promise handle for reference"); return; } if (!GetAuthPath(handle, VARADMIT)) { InstallServerAuthPath(handle, &VARADMIT, &VARADMITTOP); } RegisterLiteralServerData(handle, pp); if (!GetAuthPath(handle, VARDENY)) { InstallServerAuthPath(handle, &VARDENY, &VARDENYTOP); } ap = GetAuthPath(handle, VARADMIT); dp = GetAuthPath(handle, VARDENY); if (strcmp(type, "literal") == 0) { ap->literal = true; } if (strcmp(type, "context") == 0) { ap->classpattern = true; } for (cp = pp->conlist; cp != NULL; cp = cp->next) { if (!IsDefinedClass(cp->classes)) { continue; } switch (cp->rval.rtype) { case CF_SCALAR: if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_encrypted].lval) == 0) { ap->encrypt = true; } break; case CF_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_admit].lval) == 0) { PrependItem(&(ap->accesslist), rp->item, NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_deny].lval) == 0) { PrependItem(&(dp->accesslist), rp->item, NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_maproot].lval) == 0) { PrependItem(&(ap->maproot), rp->item, NULL); continue; } } break; case CF_FNCALL: /* Shouldn't happen */ break; } } }
int VerifyMethod(char *attrname, Attributes a, Promise *pp) { Bundle *bp; void *vp; FnCall *fp; char method_name[CF_EXPANDSIZE]; Rlist *params = NULL; int retval = false; CfLock thislock; char lockname[CF_BUFSIZE]; if (a.havebundle) { if ((vp = GetConstraintValue(attrname, pp, CF_FNCALL))) { fp = (FnCall *) vp; ExpandScalar(fp->name, method_name); params = fp->args; } else if ((vp = GetConstraintValue(attrname, pp, CF_SCALAR))) { ExpandScalar((char *) vp, method_name); params = NULL; } else { return false; } } GetLockName(lockname, "method", pp->promiser, params); thislock = AcquireLock(lockname, VUQNAME, CFSTARTTIME, a, pp, false); if (thislock.lock == NULL) { return false; } PromiseBanner(pp); if ((bp = GetBundle(method_name, "agent"))) { char *bp_stack = THIS_BUNDLE; BannerSubBundle(bp, params); DeleteScope(bp->name); NewScope(bp->name); HashVariables(bp->name); AugmentScope(bp->name, bp->args, params); THIS_BUNDLE = bp->name; PushPrivateClassContext(); retval = ScheduleAgentOperations(bp); PopPrivateClassContext(); THIS_BUNDLE = bp_stack; if (retval) { cfPS(cf_verbose, CF_NOP, "", pp, a, " -> Method invoked successfully\n"); } else { cfPS(cf_inform, CF_FAIL, "", pp, a, " !! Method could not be invoked successfully\n"); } DeleteFromScope(bp->name, bp->args); } else { if (IsCf3VarString(method_name)) { CfOut(cf_error, "", " !! A variable seems to have been used for the name of the method. In this case, the promiser also needs to contain the uique name of the method"); } if (bp && bp->name) { cfPS(cf_error, CF_FAIL, "", pp, a, " !! Method \"%s\" was used but was not defined!\n", bp->name); } else { cfPS(cf_error, CF_FAIL, "", pp, a, " !! A method attempted to use a bundle \"%s\" that was apparently not defined!\n", method_name); } } YieldCurrentLock(thislock); return retval; }
static void DoVerifyServices(Attributes a, Promise *pp, const ReportContext *report_context) { FnCall *default_bundle = NULL; Rlist *args = NULL; // Need to set up the default service pack to eliminate syntax if (GetConstraintValue("service_bundle", pp, CF_SCALAR) == NULL) { switch (a.service.service_policy) { case cfsrv_start: AppendRlist(&args, pp->promiser, CF_SCALAR); AppendRlist(&args, "start", CF_SCALAR); break; case cfsrv_restart: AppendRlist(&args, pp->promiser, CF_SCALAR); AppendRlist(&args, "restart", CF_SCALAR); break; case cfsrv_reload: AppendRlist(&args, pp->promiser, CF_SCALAR); AppendRlist(&args, "restart", CF_SCALAR); break; case cfsrv_stop: case cfsrv_disable: default: AppendRlist(&args, pp->promiser, CF_SCALAR); AppendRlist(&args, "stop", CF_SCALAR); break; } default_bundle = NewFnCall("default:standard_services", args); ConstraintAppendToPromise(pp, "service_bundle", (Rval) {default_bundle, CF_FNCALL}, "any", false); a.havebundle = true; } // Set $(this.service_policy) for flexible bundle adaptation switch (a.service.service_policy) { case cfsrv_start: NewScalar("this", "service_policy", "start", cf_str); break; case cfsrv_restart: NewScalar("this", "service_policy", "restart", cf_str); break; case cfsrv_reload: NewScalar("this", "service_policy", "reload", cf_str); break; case cfsrv_stop: case cfsrv_disable: default: NewScalar("this", "service_policy", "stop", cf_str); break; } if (default_bundle && GetBundle(PolicyFromPromise(pp), default_bundle->name, "agent") == NULL) { cfPS(cf_inform, CF_FAIL, "", pp, a, " !! Service %s could not be invoked successfully\n", pp->promiser); } if (!DONTDO) { VerifyMethod("service_bundle", a, pp, report_context); // Send list of classes to set privately? } }
static void VerifyTopicPromise(Promise *pp) { char id[CF_BUFSIZE]; Attributes a = { {0} }; Topic *tp = NULL, *otp; Rlist *rp, *rps, *contexts; char *handle = (char *) GetConstraintValue("handle", pp, CF_SCALAR); a = GetTopicsAttributes(pp); CfOut(cf_verbose, "", " -> Attempting to install topic %s::%s \n", pp->classes, pp->promiser); // Add a standard reserved word contexts = SplitContextExpression(pp->classes, pp); for (rp = contexts; rp != NULL; rp = rp->next) { if ((tp = InsertTopic(pp->promiser, rp->item)) == NULL) { return; } CfOut(cf_verbose, "", " -> New topic promise for \"%s\" about context \"%s\"", pp->promiser, ScalarValue(rp)); if (a.fwd_name && a.bwd_name) { AddTopicAssociation(tp, &(tp->associations), a.fwd_name, a.bwd_name, a.associates, true, rp->item, pp->promiser); } // Handle all synonyms as associations if (a.synonyms) { for (rps = a.synonyms; rps != NULL; rps = rps->next) { otp = IdempInsertTopic(rps->item); CfOut(cf_verbose, "", " ---> %s is a synonym for %s", ScalarValue(rps), tp->topic_name); } AddTopicAssociation(tp, &(tp->associations), KM_SYNONYM, KM_SYNONYM, a.synonyms, true, rp->item, pp->promiser); } // Handle all generalizations as associations if (a.general) { for (rps = a.general; rps != NULL; rps = rps->next) { otp = IdempInsertTopic(rps->item); CfOut(cf_verbose, "", " ---> %s is a generalization for %s", ScalarValue(rps), tp->topic_name); } AddTopicAssociation(tp, &(tp->associations), KM_GENERALIZES_B, KM_GENERALIZES_F, a.general, true, rp->item, pp->promiser); } if (handle) { char synonym[CF_BUFSIZE]; snprintf(synonym, CF_BUFSIZE - 1, "handles::%s", handle); otp = IdempInsertTopic(synonym); PrependRScalar(&(a.synonyms), otp->topic_name, CF_SCALAR); } // Treat comments as occurrences of information. if (pp->ref) { Rlist *list = NULL; snprintf(id, CF_MAXVARSIZE, "%s.%s", pp->classes, CanonifyName(pp->promiser)); PrependRScalar(&list, "description", CF_SCALAR); AddOccurrence(&OCCURRENCES, pp->ref, list, cfk_literal, id); DeleteRlist(list); } if (handle) { Rlist *list = NULL; PrependRScalar(&list, handle, CF_SCALAR); AddTopicAssociation(tp, &(tp->associations), "is the promise of", "stands for", list, true, rp->item, pp->promiser); DeleteRlist(list); list = NULL; snprintf(id, CF_MAXVARSIZE, "%s.%s", pp->classes, handle); PrependRScalar(&list, "description", CF_SCALAR); AddOccurrence(&OCCURRENCES, pp->ref, list, cfk_literal, id); DeleteRlist(list); } } DeleteRlist(contexts); }
void cfPS(enum cfreport level, char status, char *errstr, const Promise *pp, Attributes attr, char *fmt, ...) { va_list ap; char buffer[CF_BUFSIZE], output[CF_BUFSIZE], *v, handle[CF_MAXVARSIZE]; const char *sp; Item *ip, *mess = NULL; int verbose; Rval retval; if ((fmt == NULL) || (strlen(fmt) == 0)) { return; } va_start(ap, fmt); vsnprintf(buffer, CF_BUFSIZE - 1, fmt, ap); va_end(ap); Chop(buffer); AppendItem(&mess, buffer, NULL); if ((errstr == NULL) || (strlen(errstr) > 0)) { snprintf(output, CF_BUFSIZE - 1, " !!! System reports error for %s: \"%s\"", errstr, GetErrorStr()); AppendItem(&mess, output, NULL); } if (level == cf_error) { if (GetVariable("control_common", "version", &retval) != cf_notype) { v = (char *) retval.item; } else { v = "not specified"; } if ((sp = GetConstraintValue("handle", pp, CF_SCALAR)) || (sp = PromiseID(pp))) { strncpy(handle, sp, CF_MAXVARSIZE - 1); } else { strcpy(handle, "(unknown)"); } if (INFORM || VERBOSE || DEBUG) { snprintf(output, CF_BUFSIZE - 1, "I: Report relates to a promise with handle \"%s\"", handle); AppendItem(&mess, output, NULL); } if (pp && pp->audit) { snprintf(output, CF_BUFSIZE - 1, "I: Made in version \'%s\' of \'%s\' near line %zu", v, pp->audit->filename, pp->offset.line); } else { snprintf(output, CF_BUFSIZE - 1, "I: Promise is made internally by cfengine"); } AppendItem(&mess, output, NULL); if (pp != NULL) { switch (pp->promisee.rtype) { case CF_SCALAR: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to: \'%s\'", (char *) pp->promisee.item); AppendItem(&mess, output, NULL); break; case CF_LIST: snprintf(output, CF_BUFSIZE - 1, "I: The promise was made to (stakeholders): "); PrintRlist(output+strlen(output), CF_BUFSIZE, (Rlist *)pp->promisee.item); AppendItem(&mess, output, NULL); break; } if (pp->ref) { snprintf(output, CF_BUFSIZE - 1, "I: Comment: %s\n", pp->ref); AppendItem(&mess, output, NULL); } } } verbose = (attr.transaction.report_level == cf_verbose) || VERBOSE; switch (level) { case cf_inform: if (INFORM || verbose || DEBUG || attr.transaction.report_level == cf_inform) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_inform) { MakeLog(mess, level); } break; case cf_reporting: case cf_cmdout: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_inform) { MakeLog(mess, level); } break; case cf_verbose: if (verbose || DEBUG) { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_verbose) { MakeLog(mess, level); } break; case cf_error: if (attr.report.to_file) { FileReport(mess, verbose, attr.report.to_file); } else { LogList(stdout, mess, verbose); } if (attr.transaction.log_level == cf_error) { MakeLog(mess, level); } break; case cf_log: MakeLog(mess, level); break; default: break; } if (pp != NULL) { LogPromiseResult(pp->promiser, pp->promisee.rtype, pp->promisee.item, status, attr.transaction.log_level, mess); } /* Now complete the exits status classes and auditing */ if (pp != NULL) { for (ip = mess; ip != NULL; ip = ip->next) { ClassAuditLog(pp, attr, ip->name, status, buffer); } } DeleteItemList(mess); }