static void Cf3ParseFiles() { struct Rlist *rp,*sl; PARSING = true; PROMISETIME = time(NULL); Cf3ParseFile(VINPUTFILE); // Expand any lists in this list now HashVariables(NULL); HashControls(); if (VINPUTLIST != NULL) { for (rp = VINPUTLIST; rp != NULL; rp=rp->next) { if (rp->type != CF_SCALAR) { CfOut(cf_error,"","Non-file object in inputs list\n"); } else { struct Rval returnval; if (strcmp(rp->item,CF_NULL_VALUE) == 0) { continue; } returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL); switch (returnval.rtype) { case CF_SCALAR: Cf3ParseFile((char *)returnval.item); break; case CF_LIST: for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next) { Cf3ParseFile((char *)sl->item); } break; } DeleteRvalItem(returnval.item,returnval.rtype); } HashVariables(NULL); HashControls(); } } HashVariables(NULL); PARSING = false; }
void DeleteAssoc(CfAssoc *ap) { if (ap == NULL) { return; } CfDebug(" ----> Delete variable association %s\n", ap->lval); free(ap->lval); DeleteRvalItem(ap->rval); free(ap); }
Rlist *NewExpArgs(const FnCall *fp, const Promise *pp) { int len; Rval rval; Rlist *newargs = NULL; FnCall *subfp; const FnCallType *fn = FindFunction(fp->name); len = RlistLen(fp->args); if (!fn->varargs) { if (len != FnNumArgs(fn)) { CfOut(cf_error, "", "Arguments to function %s(.) do not tally. Expect %d not %d", fp->name, FnNumArgs(fn), len); PromiseRef(cf_error, pp); exit(1); } } for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->type) { case CF_FNCALL: subfp = (FnCall *) rp->item; rval = EvaluateFunctionCall(subfp, pp).rval; break; default: rval = ExpandPrivateRval(CONTEXTID, (Rval) {rp->item, rp->type}); break; } CfDebug("EXPARG: %s.%s\n", CONTEXTID, (char *) rval.item); AppendRlist(&newargs, rval.item, rval.rtype); DeleteRvalItem(rval); } return newargs; }
void DeRefListsInHashtable(char *scope, Rlist *namelist, Rlist *dereflist) // Go through scope and for each variable in name-list, replace with a // value from the deref "lol" (list of lists) clock { int len; Scope *ptr; Rlist *rp; CfAssoc *cplist; HashIterator i; CfAssoc *assoc; if ((len = RlistLen(namelist)) != RlistLen(dereflist)) { CfOut(cf_error, "", " !! Name list %d, dereflist %d\n", len, RlistLen(dereflist)); FatalError("Software Error DeRefLists... correlated lists not same length"); } if (len == 0) { return; } ptr = GetScope(scope); i = HashIteratorInit(ptr->hashtable); while ((assoc = HashIteratorNext(&i))) { for (rp = dereflist; rp != NULL; rp = rp->next) { cplist = (CfAssoc *) rp->item; if (strcmp(cplist->lval, assoc->lval) == 0) { /* Link up temp hash to variable lol */ if (rp->state_ptr == NULL || rp->state_ptr->type == CF_FNCALL) { /* Unexpanded function, or blank variable must be skipped. */ return; } if (rp->state_ptr) { CfDebug("Rewriting expanded type for %s from %s to %s\n", assoc->lval, CF_DATATYPES[assoc->dtype], (char *) rp->state_ptr->item); // must first free existing rval in scope, then allocate new (should always be string) DeleteRvalItem(assoc->rval); // avoids double free - borrowing value from lol (freed in DeleteScope()) assoc->rval.item = xstrdup(rp->state_ptr->item); } switch (assoc->dtype) { case cf_slist: assoc->dtype = cf_str; assoc->rval.rtype = CF_SCALAR; break; case cf_ilist: assoc->dtype = cf_int; assoc->rval.rtype = CF_SCALAR; break; case cf_rlist: assoc->dtype = cf_real; assoc->rval.rtype = CF_SCALAR; break; default: /* Only lists need to be converted */ break; } CfDebug(" to %s\n", CF_DATATYPES[assoc->dtype]); } } } }
int AddVariableHash(const char *scope, const char *lval, Rval rval, enum cfdatatype dtype, const char *fname, int lineno) { Scope *ptr; const Rlist *rp; CfAssoc *assoc; if (rval.rtype == CF_SCALAR) { CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", scope, lval, (const char *) rval.item, CF_DATATYPES[dtype], rval.rtype); } else { CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", scope, lval, CF_DATATYPES[dtype], rval.rtype); } if (lval == NULL || scope == NULL) { CfOut(cf_error, "", "scope.value = %s.%s", scope, lval); ReportError("Bad variable or scope in a variable assignment"); FatalError("Should not happen - forgotten to register a function call in fncall.c?"); } if (rval.item == NULL) { CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n"); return false; } if (strlen(lval) > CF_MAXVARSIZE) { ReportError("variable lval too long"); return false; } /* If we are not expanding a body template, check for recursive singularities */ if (strcmp(scope, "body") != 0) { switch (rval.rtype) { case CF_SCALAR: if (StringContainsVar((char *) rval.item, lval)) { CfOut(cf_error, "", "Scalar variable %s.%s contains itself (non-convergent): %s", scope, lval, (char *) rval.item); return false; } break; case CF_LIST: for (rp = rval.item; rp != NULL; rp = rp->next) { if (StringContainsVar((char *) rp->item, lval)) { CfOut(cf_error, "", "List variable %s contains itself (non-convergent)", lval); return false; } } break; } } ptr = GetScope(scope); if (ptr == NULL) { return false; } // Look for outstanding lists in variable rvals if (THIS_AGENT_TYPE == cf_common) { Rlist *listvars = NULL, *scalarvars = NULL; if (strcmp(CONTEXTID, "this") != 0) { MapIteratorsFromRval(CONTEXTID, &scalarvars, &listvars, rval, NULL); if (listvars != NULL) { CfOut(cf_error, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"", lval, CONTEXTID); } DeleteRlist(scalarvars); DeleteRlist(listvars); } } assoc = HashLookupElement(ptr->hashtable, lval); if (assoc) { if (CompareVariableValue(rval, assoc) == 0) { /* Identical value, keep as is */ } else { /* Different value, bark and replace */ if (!UnresolvedVariables(assoc, rval.rtype)) { CfOut(cf_inform, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval, ptr->scope); if (fname) { CfOut(cf_inform, "", " !! Rule from %s at/before line %d\n", fname, lineno); } else { CfOut(cf_inform, "", " !! in bundle parameterization\n"); } } DeleteRvalItem(assoc->rval); assoc->rval = CopyRvalItem(rval); assoc->dtype = dtype; CfDebug("Stored \"%s\" in context %s\n", lval, scope); } } else { if (!HashInsertElement(ptr->hashtable, lval, rval, dtype)) { FatalError("Hash table is full"); } } CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval, scope); return true; }
int NewPromiseProposals() { struct Rlist *rp,*sl; struct stat sb; int result = false; char filename[CF_MAXVARSIZE]; if (MINUSF) { snprintf(filename,CF_MAXVARSIZE,"%s/state/validated_%s",CFWORKDIR,CanonifyName(VINPUTFILE)); MapName(filename); } else { snprintf(filename,CF_MAXVARSIZE,"%s/masterfiles/cf_promises_validated",CFWORKDIR); MapName(filename); } if (stat(filename,&sb) != -1) { PROMISETIME = sb.st_mtime; } else { PROMISETIME = 0; } // sanity check if(PROMISETIME > time(NULL)) { CfOut(cf_inform, "", "!! Clock seems to have jumped back in time - mtime of %s is newer than current time - touching it", filename); if(utime(filename,NULL) == -1) { CfOut(cf_error, "utime", "!! Could not touch %s", filename); } PROMISETIME = 0; return true; } if (cfstat(InputLocation(VINPUTFILE),&sb) == -1) { CfOut(cf_verbose,"stat","There is no readable input file at %s",VINPUTFILE); return true; } if (sb.st_mtime > PROMISETIME) { CfOut(cf_verbose,""," -> Promises seem to change"); return true; } // Check the directories first for speed and because non-input/data files should trigger an update snprintf(filename,CF_MAXVARSIZE,"%s/inputs",CFWORKDIR); MapName(filename); if (IsNewerFileTree(filename,PROMISETIME)) { CfOut(cf_verbose,""," -> Quick search detected file changes"); return true; } // Check files in case there are any abs paths if (VINPUTLIST != NULL) { for (rp = VINPUTLIST; rp != NULL; rp=rp->next) { if (rp->type != CF_SCALAR) { CfOut(cf_error,"","Non file object %s in list\n",(char *)rp->item); } else { struct Rval returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL); switch (returnval.rtype) { case CF_SCALAR: if (cfstat(InputLocation((char *)returnval.item),&sb) == -1) { CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)returnval.item); result = true; break; } if (sb.st_mtime > PROMISETIME) { result = true; } break; case CF_LIST: for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next) { if (cfstat(InputLocation((char *)sl->item),&sb) == -1) { CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)sl->item); result = true; break; } if (sb.st_mtime > PROMISETIME) { result = true; break; } } break; } DeleteRvalItem(returnval.item,returnval.rtype); if (result) { break; } } } } // did policy server change (used in $(sys.policy_hub))? snprintf(filename,CF_MAXVARSIZE,"%s/policy_server.dat",CFWORKDIR); MapName(filename); if ((cfstat(filename,&sb) != -1) && (sb.st_mtime > PROMISETIME)) { result = true; } return result | ALWAYS_VALIDATE; }
static void CheckControlPromises(char *scope,char *agent,struct Constraint *controllist) { struct Constraint *cp; struct BodySyntax *bp = NULL; struct Rlist *rp; int i = 0; struct Rval returnval; char rettype; void *retval; Debug("CheckControlPromises(%s)\n",agent); for (i = 0; CF_ALL_BODIES[i].bs != NULL; i++) { bp = CF_ALL_BODIES[i].bs; if (strcmp(agent,CF_ALL_BODIES[i].btype) == 0) { break; } } if (bp == NULL) { FatalError("Unknown agent"); } for (cp = controllist; cp != NULL; cp=cp->next) { if (IsExcluded(cp->classes)) { continue; } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_bundlesequence].lval) == 0) { returnval = ExpandPrivateRval(CONTEXTID,cp->rval,cp->type); } else { returnval = EvaluateFinalRval(CONTEXTID,cp->rval,cp->type,true,NULL); } DeleteVariable(scope,cp->lval); if (!AddVariableHash(scope,cp->lval,returnval.item,returnval.rtype,GetControlDatatype(cp->lval,bp),cp->audit->filename,cp->lineno)) { CfOut(cf_error,""," !! Rule from %s at/before line %d\n",cp->audit->filename,cp->lineno); } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_output_prefix].lval) == 0) { strncpy(VPREFIX,returnval.item,CF_MAXVARSIZE); } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_domain].lval) == 0) { strcpy(VDOMAIN,cp->rval); CfOut(cf_verbose,"","SET domain = %s\n",VDOMAIN); DeleteScalar("sys","domain"); DeleteScalar("sys","fqhost"); snprintf(VFQNAME,CF_MAXVARSIZE,"%s.%s",VUQNAME,VDOMAIN); NewScalar("sys","fqhost",VFQNAME,cf_str); NewScalar("sys","domain",VDOMAIN,cf_str); DeleteClass("undefined_domain"); NewClass(VDOMAIN); } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_inputs].lval) == 0) { CfOut(cf_verbose,"","SET ignore_missing_inputs %s\n",cp->rval); IGNORE_MISSING_INPUTS = GetBoolean(cp->rval); } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_bundles].lval) == 0) { CfOut(cf_verbose,"","SET ignore_missing_bundles %s\n",cp->rval); IGNORE_MISSING_BUNDLES = GetBoolean(cp->rval); } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_goalpatterns].lval) == 0) { GOALS = NULL; for (rp = (struct Rlist *)returnval.item; rp != NULL; rp=rp->next) { PrependRScalar(&GOALS,rp->item,CF_SCALAR); } CfOut(cf_verbose,"","SET goal_patterns list\n"); continue; } if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_goalcategories].lval) == 0) { GOALCATEGORIES = NULL; for (rp = (struct Rlist *)returnval.item; rp != NULL; rp=rp->next) { PrependRScalar(&GOALCATEGORIES,rp->item,CF_SCALAR); } CfOut(cf_verbose,"","SET goal_categories list\n"); continue; } DeleteRvalItem(returnval.item,returnval.rtype); } }
static int EvalClassExpression(struct Constraint *cp,struct Promise *pp) { int result_and = true; int result_or = false; int result_xor = 0; int result = 0,total = 0; char buffer[CF_MAXVARSIZE]; struct Rlist *rp; double prob,cum = 0,fluct; struct Rval newret; struct FnCall *fp; if (cp == NULL) { CfOut(cf_error,""," !! EvalClassExpression internal diagnostic discovered an ill-formed condition"); } if (!IsDefinedClass(pp->classes)) { return false; } if (pp->done) { return false; } if (IsDefinedClass(pp->promiser)) { return false; } switch (cp->type) { case CF_FNCALL: fp = (struct FnCall *)cp->rval; /* Special expansion of functions for control, best effort only */ newret = EvaluateFunctionCall(fp,pp); DeleteFnCall(fp); cp->rval = newret.item; cp->type = newret.rtype; break; case CF_LIST: for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { newret = EvaluateFinalRval("this",rp->item,rp->type,true,pp); DeleteRvalItem(rp->item,rp->type); rp->item = newret.item; rp->type = newret.rtype; } break; default: newret = ExpandPrivateRval("this",cp->rval,cp->type); DeleteRvalItem(cp->rval,cp->type); cp->rval = newret.item; cp->type = newret.rtype; break; } if (strcmp(cp->lval,"expression") == 0) { if (cp->type != CF_SCALAR) { return false; } if (IsDefinedClass((char *)cp->rval)) { return true; } else { return false; } } if (strcmp(cp->lval,"not") == 0) { if (cp->type != CF_SCALAR) { return false; } if (IsDefinedClass((char *)cp->rval)) { return false; } else { return true; } } // Class selection if (strcmp(cp->lval,"select_class") == 0) { char splay[CF_MAXVARSIZE]; int i,n; double hash; total = 0; for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { total++; } if (total == 0) { CfOut(cf_error,""," !! No classes to select on RHS"); PromiseRef(cf_error,pp); return false; } snprintf(splay,CF_MAXVARSIZE,"%s+%s+%d",VFQNAME,VIPADDRESS,getuid()); hash = (double)GetHash(splay); n = (int)(total*hash/(double)CF_HASHTABLESIZE); for (rp = (struct Rlist *)cp->rval,i = 0; rp != NULL; rp = rp->next,i++) { if (i == n) { NewClass(rp->item); return true; } } } // Class distributions if (strcmp(cp->lval,"dist") == 0) { for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { result = Str2Int(rp->item); if (result < 0) { CfOut(cf_error,""," !! Non-positive integer in class distribution"); PromiseRef(cf_error,pp); return false; } total += result; } if (total == 0) { CfOut(cf_error,""," !! An empty distribution was specified on RHS"); PromiseRef(cf_error,pp); return false; } } fluct = drand48(); /* Get random number 0-1 */ cum = 0.0; /* If we get here, anything remaining on the RHS must be a clist */ if (cp->type != CF_LIST) { CfOut(cf_error,""," !! RHS of promise body attribute \"%s\" is not a list\n",cp->lval); PromiseRef(cf_error,pp); return true; } for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { if (rp->type != CF_SCALAR) { return false; } result = IsDefinedClass((char *)(rp->item)); result_and = result_and && result; result_or = result_or || result; result_xor ^= result; if (total > 0) // dist class { prob = ((double)Str2Int(rp->item))/((double)total); cum += prob; if ((fluct < cum) || rp->next == NULL) { snprintf(buffer,CF_MAXVARSIZE-1,"%s_%s",pp->promiser,rp->item); *(pp->donep) = true; if (strcmp(pp->bundletype,"common") == 0) { NewClass(buffer); } else { NewBundleClass(buffer,pp->bundle); } Debug(" ?? \'Strategy\' distribution class interval -> %s\n",buffer); return true; } } } // Class combinations if (strcmp(cp->lval,"or") == 0) { return result_or; } if (strcmp(cp->lval,"xor") == 0) { return (result_xor == 1) ? true : false; } if (strcmp(cp->lval,"and") == 0) { return result_and; } return false; }