void LoadSystemConstants(EvalContext *ctx) { ScopeNewSpecialScalar(ctx, "const", "dollar", "$", DATA_TYPE_STRING); ScopeNewSpecialScalar(ctx, "const", "n", "\n", DATA_TYPE_STRING); ScopeNewSpecialScalar(ctx, "const", "r", "\r", DATA_TYPE_STRING); ScopeNewSpecialScalar(ctx, "const", "t", "\t", DATA_TYPE_STRING); ScopeNewSpecialScalar(ctx, "const", "endl", "\n", DATA_TYPE_STRING); /* NewScalar("const","0","\0",cf_str); - this cannot work */ }
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); }
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; } ScopeDeleteSpecialScalar("this", "promiser"); ScopeNewSpecialScalar(ctx, "this", "promiser", pp->promiser, DATA_TYPE_STRING); PromiseBanner(pp); VerifyProcessOp(ctx, PROCESSTABLE, a, pp); ScopeDeleteSpecialScalar("this", "promiser"); YieldCurrentLock(thislock); }
void ScopeNewList(EvalContext *ctx, VarRef lval, void *rval, DataType dt) { assert(!ScopeIsReserved(lval.scope)); if (ScopeIsReserved(lval.scope)) { ScopeNewSpecialScalar(ctx, lval.scope, lval.lval, rval, dt); } Rval rvald; if (EvalContextVariableGet(ctx, lval, &rvald, NULL)) { ScopeDeleteVariable(lval.scope, lval.lval); } EvalContextVariablePut(ctx, lval, (Rval) {rval, RVAL_TYPE_LIST }, dt); }
void ScopeNewScalar(EvalContext *ctx, VarRef lval, const char *rval, DataType dt) { CfDebug("NewScalar(%s,%s,%s)\n", lval.scope, lval.lval, rval); assert(!ScopeIsReserved(lval.scope)); if (ScopeIsReserved(lval.scope)) { ScopeNewSpecialScalar(ctx, lval.scope, lval.lval, rval, dt); } Rval rvald; if (EvalContextVariableGet(ctx, lval, &rvald, NULL)) { ScopeDeleteScalar(lval); } /* * We know AddVariableHash does not change passed Rval structure or its * contents, but we have no easy way to express it in C type system, hence cast. */ EvalContextVariablePut(ctx, lval, (Rval) {(char *) rval, RVAL_TYPE_SCALAR }, dt); }
static bool ScheduleRun(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, ExecConfig *exec_config) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Sleeping for pulse time %d seconds...\n", CFPULSETIME); sleep(CFPULSETIME); /* 1 Minute resolution is enough */ /* * FIXME: this logic duplicates the one from cf-serverd.c. Unify ASAP. */ if (CheckNewPromises(ctx, config, InputFiles(ctx, *policy)) == RELOAD_FULL) { /* Full reload */ CfOut(OUTPUT_LEVEL_INFORM, "", "Re-reading promise file %s..\n", config->input_file); EvalContextHeapClear(ctx); DeleteItemList(IPADDRESSES); IPADDRESSES = NULL; ScopeDeleteAll(); strcpy(VDOMAIN, "undefined.domain"); POLICY_SERVER[0] = '\0'; PolicyDestroy(*policy); *policy = NULL; SetPolicyServer(ctx, POLICY_SERVER); ScopeNewSpecialScalar(ctx, "sys", "policy_hub", POLICY_SERVER, DATA_TYPE_STRING); GetNameInfo3(ctx, AGENT_TYPE_EXECUTOR); GetInterfacesInfo(ctx, AGENT_TYPE_EXECUTOR); Get3Environment(ctx, AGENT_TYPE_EXECUTOR); BuiltinClasses(ctx); OSClasses(ctx); EvalContextHeapAddHard(ctx, CF_AGENTTYPES[AGENT_TYPE_EXECUTOR]); SetReferenceTime(ctx, true); GenericAgentConfigSetBundleSequence(config, NULL); *policy = GenericAgentLoadPolicy(ctx, config); ExecConfigUpdate(ctx, *policy, exec_config); SetFacility(exec_config->log_facility); } else { /* Environment reload */ EvalContextHeapClear(ctx); DeleteItemList(IPADDRESSES); IPADDRESSES = NULL; ScopeClear("this"); ScopeClear("mon"); ScopeClear("sys"); GetInterfacesInfo(ctx, AGENT_TYPE_EXECUTOR); Get3Environment(ctx, AGENT_TYPE_EXECUTOR); BuiltinClasses(ctx); OSClasses(ctx); SetReferenceTime(ctx, true); } { StringSetIterator it = StringSetIteratorInit(exec_config->schedule); const char *time_context = NULL; while ((time_context = StringSetIteratorNext(&it))) { if (IsDefinedClass(ctx, time_context, NULL)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Waking up the agent at %s ~ %s \n", cf_ctime(&CFSTARTTIME), time_context); return true; } } } CfOut(OUTPUT_LEVEL_VERBOSE, "", "Nothing to do at %s\n", cf_ctime(&CFSTARTTIME)); return false; }
int OpenReceiverChannel(void) { struct addrinfo *response, *ap; struct addrinfo query = { .ai_flags = AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; /* Listen to INADDR(6)_ANY if BINDINTERFACE unset. */ char *ptr = NULL; if (BINDINTERFACE[0] != '\0') { ptr = BINDINTERFACE; } /* Resolve listening interface. */ if (getaddrinfo(ptr, STR_CFENGINEPORT, &query, &response) != 0) { CfOut(OUTPUT_LEVEL_ERROR, "getaddrinfo", "DNS/service lookup failure"); return -1; } int sd = -1; for (ap = response; ap != NULL; ap = ap->ai_next) { if ((sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol)) == -1) { continue; } int yes = 1; if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "setsockopt", "Socket option SO_REUSEADDR was not accepted"); exit(1); } struct linger cflinger = { .l_onoff = 1, .l_linger = 60 }; if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &cflinger, sizeof(cflinger)) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "setsockopt", "Socket option SO_LINGER was not accepted"); exit(1); } if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1) { if (DEBUG) { /* Convert IP address to string, no DNS lookup performed. */ char txtaddr[CF_MAX_IP_LEN] = ""; getnameinfo(ap->ai_addr, ap->ai_addrlen, txtaddr, sizeof(txtaddr), NULL, 0, NI_NUMERICHOST); printf("Bound to address %s on %s=%d\n", txtaddr, CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS); } break; } else { CfOut(OUTPUT_LEVEL_ERROR, "bind", "Could not bind server address"); cf_closesocket(sd); } } if (sd < 0) { CfOut(OUTPUT_LEVEL_ERROR, "", "Couldn't open/bind a socket\n"); exit(1); } freeaddrinfo(response); return sd; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { CfDebug("Checking file updates on %s\n", config->input_file); if (NewPromiseProposals(ctx, config, InputFiles(ctx, *policy))) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> New promises detected...\n"); if (CheckPromises(config)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Rereading config files %s..\n", config->input_file); /* Free & reload -- lock this to avoid access errors during reload */ EvalContextHeapClear(ctx); DeleteItemList(IPADDRESSES); IPADDRESSES = NULL; DeleteItemList(SV.trustkeylist); DeleteItemList(SV.skipverify); DeleteItemList(SV.attackerlist); DeleteItemList(SV.nonattackerlist); DeleteItemList(SV.multiconnlist); DeleteAuthList(SV.admit); DeleteAuthList(SV.deny); DeleteAuthList(SV.varadmit); DeleteAuthList(SV.vardeny); DeleteAuthList(SV.roles); //DeleteRlist(VINPUTLIST); This is just a pointer, cannot free it ScopeDeleteAll(); strcpy(VDOMAIN, "undefined.domain"); POLICY_SERVER[0] = '\0'; SV.admit = NULL; SV.admittop = NULL; SV.varadmit = NULL; SV.varadmittop = NULL; SV.deny = NULL; SV.denytop = NULL; SV.vardeny = NULL; SV.vardenytop = NULL; SV.roles = NULL; SV.rolestop = NULL; SV.trustkeylist = NULL; SV.skipverify = NULL; SV.attackerlist = NULL; SV.nonattackerlist = NULL; SV.multiconnlist = NULL; PolicyDestroy(*policy); *policy = NULL; SetPolicyServer(ctx, POLICY_SERVER); ScopeNewSpecialScalar(ctx, "sys", "policy_hub", POLICY_SERVER, DATA_TYPE_STRING); GetNameInfo3(ctx, AGENT_TYPE_SERVER); GetInterfacesInfo(ctx, AGENT_TYPE_SERVER); Get3Environment(ctx, AGENT_TYPE_SERVER); BuiltinClasses(ctx); OSClasses(ctx); KeepHardClasses(ctx); EvalContextHeapAddHard(ctx, CF_AGENTTYPES[config->agent_type]); SetReferenceTime(ctx, true); *policy = GenericAgentLoadPolicy(ctx, config); KeepPromises(ctx, *policy, config); Summarize(); } else { CfOut(OUTPUT_LEVEL_INFORM, "", " !! File changes contain errors -- ignoring"); PROMISETIME = time(NULL); } } else { CfDebug(" -> No new promises found\n"); } }
void SetPolicyServer(EvalContext *ctx, char *name) /* * If name contains a string, it's written to file, * if not, name is filled with the contents of file. */ { char file[CF_BUFSIZE]; FILE *fout, *fin; char fileContents[CF_MAXVARSIZE] = { 0 }; snprintf(file, CF_BUFSIZE - 1, "%s/policy_server.dat", CFWORKDIR); MapName(file); if ((fin = fopen(file, "r")) != NULL) { if (fscanf(fin, "%1023s", fileContents) != 1) { CfDebug("Couldn't read string from policy_server.dat"); } fclose(fin); } // update file if different and we know what to put there if ((NULL_OR_EMPTY(name)) && (!NULL_OR_EMPTY(fileContents))) { snprintf(name, CF_MAXVARSIZE, "%s", fileContents); } else if ((!NULL_OR_EMPTY(name)) && (strcmp(name, fileContents) != 0)) { if ((fout = fopen(file, "w")) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Unable to write policy server file! (%s)", file); return; } fprintf(fout, "%s", name); fclose(fout); } if (NULL_OR_EMPTY(name)) { // avoids "Scalar item in servers => { } in rvalue is out of bounds ..." // when NovaBase is checked with unprivileged (not bootstrapped) cf-promises ScopeNewSpecialScalar(ctx, "sys", "policy_hub", "undefined", DATA_TYPE_STRING); } else { ScopeNewSpecialScalar(ctx, "sys", "policy_hub", name, DATA_TYPE_STRING); } // Get the timestamp on policy update snprintf(file, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR); MapName(file); struct stat sb; if ((cfstat(file, &sb)) != 0) { return; } char timebuf[26]; cf_strtimestamp_local(sb.st_mtime, timebuf); ScopeNewSpecialScalar(ctx, "sys", "last_policy_update", timebuf, DATA_TYPE_STRING); }