static void KeepPromises(EvalContext *ctx, const Policy *policy) { Rval retval; Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_MONITOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes, NULL)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_monitor"); if (!EvalContextVariableGet(ctx, ref, &retval, NULL)) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in monitor control body", cp->lval); VarRefDestroy(ref); continue; } VarRefDestroy(ref); if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_HISTOGRAMS].lval) == 0) { /* Keep accepting this option for backward compatibility. */ } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_TCP_DUMP].lval) == 0) { MonNetworkSnifferEnable(BooleanFromString(retval.item)); } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_FORGET_RATE].lval) == 0) { sscanf(retval.item, "%lf", &FORGETRATE); Log(LOG_LEVEL_DEBUG, "forget rate %f", FORGETRATE); } } } }
static void KeepPromises(EvalContext *ctx, Policy *policy) { Rval retval; Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_MONITOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes, NULL)) { continue; } if (!EvalContextVariableGet(ctx, (VarRef) { NULL, "control_monitor", cp->lval }, &retval, NULL)) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in monitor control body", cp->lval); continue; } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_HISTOGRAMS].lval) == 0) { /* Keep accepting this option for backward compatibility. */ } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_TCP_DUMP].lval) == 0) { MonNetworkSnifferEnable(BooleanFromString(retval.item)); } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_FORGET_RATE].lval) == 0) { sscanf(retval.item, "%lf", &FORGETRATE); CfDebug("forget rate = %f\n", FORGETRATE); } } } }
void EndAudit(const EvalContext *ctx, int background_tasks) { if (!END_AUDIT_REQUIRED) { return; } char *sp, string[CF_BUFSIZE]; Rval retval = { 0 }; Promise dummyp = { 0 }; Attributes dummyattr = { {0} }; memset(&dummyp, 0, sizeof(dummyp)); memset(&dummyattr, 0, sizeof(dummyattr)); { Rval track_value_rval = { 0 }; bool track_value = false; if (EvalContextVariableGet(ctx, (VarRef) { NULL, "control_agent", CFA_CONTROLBODY[AGENT_CONTROL_TRACK_VALUE].lval }, &track_value_rval, NULL)) { track_value = BooleanFromString(track_value_rval.item); } if (track_value) { FILE *fout; char name[CF_MAXVARSIZE], datestr[CF_MAXVARSIZE]; time_t now = time(NULL); CfOut(OUTPUT_LEVEL_INFORM, "", " -> Recording promise valuations"); snprintf(name, CF_MAXVARSIZE, "%s/state/%s", CFWORKDIR, CF_VALUE_LOG); snprintf(datestr, CF_MAXVARSIZE, "%s", cf_ctime(&now)); if ((fout = fopen(name, "a")) == NULL) { CfOut(OUTPUT_LEVEL_INFORM, "", " !! Unable to write to the value log %s\n", name); return; } if (Chop(datestr, CF_EXPANDSIZE) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator"); } fprintf(fout, "%s,%.4lf,%.4lf,%.4lf\n", datestr, VAL_KEPT, VAL_REPAIRED, VAL_NOTKEPT); TrackValue(datestr, VAL_KEPT, VAL_REPAIRED, VAL_NOTKEPT); fclose(fout); } } double total = (double) (PR_KEPT + PR_NOTKEPT + PR_REPAIRED) / 100.0; if (ScopeControlCommonGet(ctx, COMMON_CONTROL_VERSION, &retval) != DATA_TYPE_NONE) { sp = (char *) retval.item; } else { sp = "(not specified)"; } if (total == 0) { *string = '\0'; CfOut(OUTPUT_LEVEL_VERBOSE, "", "Outcome of version %s: No checks were scheduled\n", sp); return; } else { LogTotalCompliance(sp, background_tasks); } }
/** * Add access rules to the given ACL #acl according to the constraints in the * particular access promise. * * For legacy reasons (non-TLS connections), build also the #ap (access Auth) * and #dp (deny Auth). */ static void AccessPromise_AddAccessConstraints(const EvalContext *ctx, const Promise *pp, struct resource_acl *racl, Auth *ap, Auth *dp) { for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); size_t ret = -2; if (!IsDefinedClass(ctx, cp->classes)) { continue; } switch (cp->rval.type) { #define IsAccessBody(e) (strcmp(cp->lval, CF_REMACCESS_BODIES[e].lval) == 0) case RVAL_TYPE_SCALAR: if (IsAccessBody(REMOTE_ACCESS_IFENCRYPTED)) { ap->encrypt = BooleanFromString(cp->rval.item); } else if (IsAccessBody(REMOTE_ACCESS_SHORTCUT)) { const char *shortcut = cp->rval.item; if (strchr(shortcut, FILE_SEPARATOR) != NULL) { Log(LOG_LEVEL_ERR, "slashes are forbidden in ACL shortcut: %s", shortcut); } else if (StringMapHasKey(SV.path_shortcuts, shortcut)) { Log(LOG_LEVEL_WARNING, "Already existing shortcut for path '%s' was replaced", pp->promiser); } else { StringMapInsert(SV.path_shortcuts, xstrdup(shortcut), xstrdup(pp->promiser)); Log(LOG_LEVEL_DEBUG, "Added shortcut '%s' for path: %s", shortcut, pp->promiser); } } break; case RVAL_TYPE_LIST: for (const Rlist *rp = (const Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { /* TODO keys, ips, hostnames are valid such strings. */ if (IsAccessBody(REMOTE_ACCESS_ADMITIPS)) { ret = StrList_Append(&racl->admit.ips, RlistScalarValue(rp)); PrependItem(&(ap->accesslist), RlistScalarValue(rp), NULL); } else if (IsAccessBody(REMOTE_ACCESS_DENYIPS)) { ret = StrList_Append(&racl->deny.ips, RlistScalarValue(rp)); PrependItem(&(dp->accesslist), RlistScalarValue(rp), NULL); } else if (IsAccessBody(REMOTE_ACCESS_ADMITHOSTNAMES)) { ret = StrList_Append(&racl->admit.hostnames, RlistScalarValue(rp)); /* If any hostname rule got added, * turn on reverse DNS lookup in the new protocol. */ if (ret != (size_t) -1) { TurnOnReverseLookups(); } NewHostToOldACL(ap, RlistScalarValue(rp)); } else if (IsAccessBody(REMOTE_ACCESS_DENYHOSTNAMES)) { ret = StrList_Append(&racl->deny.hostnames, RlistScalarValue(rp)); /* If any hostname rule got added, * turn on reverse DNS lookup in the new protocol. */ if (ret != (size_t) -1) { TurnOnReverseLookups(); } NewHostToOldACL(dp, RlistScalarValue(rp)); } else if (IsAccessBody(REMOTE_ACCESS_ADMITKEYS)) { ret = StrList_Append(&racl->admit.keys, RlistScalarValue(rp)); } else if (IsAccessBody(REMOTE_ACCESS_DENYKEYS)) { ret = StrList_Append(&racl->deny.keys, RlistScalarValue(rp)); } /* Legacy stuff */ else if (IsAccessBody(REMOTE_ACCESS_ADMIT)) { ret = racl_SmartAppend(&racl->admit, RlistScalarValue(rp)); PrependItem(&(ap->accesslist), RlistScalarValue(rp), NULL); } else if (IsAccessBody(REMOTE_ACCESS_DENY)) { ret = racl_SmartAppend(&racl->deny, RlistScalarValue(rp)); PrependItem(&(dp->accesslist), RlistScalarValue(rp), NULL); } else if (IsAccessBody(REMOTE_ACCESS_MAPROOT)) { PrependItem(&(ap->maproot), RlistScalarValue(rp), NULL); } } if (ret == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "StrList_Append: %s", GetErrorStr()); exit(255); } break; default: UnexpectedError("Unknown constraint type!"); break; #undef IsAccessBody } } StrList_Finalise(&racl->admit.ips); StrList_Sort(racl->admit.ips, string_Compare); StrList_Finalise(&racl->admit.hostnames); StrList_Sort(racl->admit.hostnames, string_CompareFromEnd); StrList_Finalise(&racl->admit.keys); StrList_Sort(racl->admit.keys, string_Compare); StrList_Finalise(&racl->deny.ips); StrList_Sort(racl->deny.ips, string_Compare); StrList_Finalise(&racl->deny.hostnames); StrList_Sort(racl->deny.hostnames, string_CompareFromEnd); StrList_Finalise(&racl->deny.keys); StrList_Sort(racl->deny.keys, string_Compare); }
static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { CFD_MAXPROCESSES = 30; MAXTRIES = 5; DENYBADCLOCKS = true; CFRUNCOMMAND[0] = '\0'; SetChecksumUpdatesDefault(ctx, true); /* Keep promised agent behaviour - control bodies */ Banner("Server control promises.."); PolicyResolve(ctx, policy, config); /* Now expand */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); #define IsControlBody(e) (strcmp(cp->lval, CFS_CONTROLBODY[e].lval) == 0) if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_server"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in server control body", cp->lval); } else if (IsControlBody(SERVER_CONTROL_SERVER_FACILITY)) { SetFacility(value); } else if (IsControlBody(SERVER_CONTROL_DENY_BAD_CLOCKS)) { DENYBADCLOCKS = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting denybadclocks to '%s'", DENYBADCLOCKS ? "true" : "false"); } else if (IsControlBody(SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS)) { LOGENCRYPT = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logencrypt to '%s'", LOGENCRYPT ? "true" : "false"); } else if (IsControlBody(SERVER_CONTROL_LOG_ALL_CONNECTIONS)) { SV.logconns = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns); } else if (IsControlBody(SERVER_CONTROL_MAX_CONNECTIONS)) { CFD_MAXPROCESSES = (int) IntFromString(value); MAXTRIES = CFD_MAXPROCESSES / 3; Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFD_MAXPROCESSES); /* The handling of max_readers in LMDB is not ideal, but * here is how it is right now: We know that both cf-serverd and * cf-hub will access the lastseen database. Worst case every * single thread and process will do it at the same time, and * this has in fact been observed. So we add the maximum of * those two values together to provide a safe ceiling. In * addition, cf-agent can access the database occasionally as * well, so add a few extra for that too. */ DBSetMaximumConcurrentTransactions(CFD_MAXPROCESSES + EnterpriseGetMaxCfHubProcesses() + 10); continue; } else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_INTERVAL)) { COLLECT_INTERVAL = (int) 60 * IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting call_collect_interval to %d (seconds)", COLLECT_INTERVAL); } else if (IsControlBody(SERVER_CONTROL_LISTEN)) { SERVER_LISTEN = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting server listen to '%s' ", SERVER_LISTEN ? "true" : "false"); } else if (IsControlBody(SERVER_CONTROL_CALL_COLLECT_WINDOW)) { COLLECT_WINDOW = (int) IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting collect_window to %d (seconds)", COLLECT_INTERVAL); } else if (IsControlBody(SERVER_CONTROL_CF_RUN_COMMAND)) { strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND)); Log(LOG_LEVEL_VERBOSE, "Setting cfruncommand to '%s'", CFRUNCOMMAND); } else if (IsControlBody(SERVER_CONTROL_ALLOW_CONNECTS)) { Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp))) { PrependItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_DENY_CONNECTS)) { Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp))) { PrependItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_SKIP_VERIFY)) { /* Skip. */ } else if (IsControlBody(SERVER_CONTROL_ALLOW_ALL_CONNECTS)) { Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp))) { PrependItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_ALLOW_USERS)) { Log(LOG_LEVEL_VERBOSE, "SET Allowing users ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp))) { PrependItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_TRUST_KEYS_FROM)) { Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp))) { PrependItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_ALLOWLEGACYCONNECTS)) { Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp))) { PrependItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes); } } } else if (IsControlBody(SERVER_CONTROL_PORT_NUMBER)) { CFENGINE_PORT = IntFromString(value); strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR)); Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d", CFENGINE_PORT); } else if (IsControlBody(SERVER_CONTROL_BIND_TO_INTERFACE)) { strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE)); Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE); } else if (IsControlBody(SERVER_CONTROL_ALLOWCIPHERS)) { SV.allowciphers = xstrdup(value); Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers); } #undef IsControlBody } } const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST); if (value) { /* Don't resolve syslog_host now, better do it per log request. */ if (!SetSyslogHost(value)) { Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value); } else { Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value); } } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT); if (value) { SetSyslogPort(IntFromString(value)); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE); if (value) { FIPS_MODE = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false"); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (value) { LASTSEENEXPIREAFTER = IntFromString(value) * 60; } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BWLIMIT); if (value) { double bval; if (DoubleFromString(value, &bval)) { bwlimit_kbytes = (uint32_t) ( bval / 1000.0); Log(LOG_LEVEL_VERBOSE, "Setting rate limit to %d kBytes/sec", bwlimit_kbytes); } } }
static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { CFD_MAXPROCESSES = 30; MAXTRIES = 5; DENYBADCLOCKS = true; CFRUNCOMMAND[0] = '\0'; SetChecksumUpdatesDefault(ctx, true); /* Keep promised agent behaviour - control bodies */ Banner("Server control promises.."); PolicyResolve(ctx, policy, config); /* Now expand */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_server"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in server control body", cp->lval); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SERVER_FACILITY].lval) == 0) { SetFacility(value); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_BAD_CLOCKS].lval) == 0) { DENYBADCLOCKS = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting denybadclocks to '%s'", DENYBADCLOCKS ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS].lval) == 0) { LOGENCRYPT = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logencrypt to '%s'", LOGENCRYPT ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ALL_CONNECTIONS].lval) == 0) { SV.logconns = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_MAX_CONNECTIONS].lval) == 0) { CFD_MAXPROCESSES = (int) IntFromString(value); MAXTRIES = CFD_MAXPROCESSES / 3; Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFD_MAXPROCESSES); #ifdef LMDB static int LSD_MAXREADERS = 0; if (LSD_MAXREADERS < CFD_MAXPROCESSES) { int rc = UpdateLastSeenMaxReaders(CFD_MAXPROCESSES); if (rc == 0) { LSD_MAXREADERS = CFD_MAXPROCESSES; } } #endif continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_INTERVAL].lval) == 0) { COLLECT_INTERVAL = (int) 60 * IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting call_collect_interval to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LISTEN].lval) == 0) { SERVER_LISTEN = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting server listen to '%s' ", (SERVER_LISTEN)? "true":"false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_WINDOW].lval) == 0) { COLLECT_WINDOW = (int) IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting collect_window to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CF_RUN_COMMAND].lval) == 0) { strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND)); Log(LOG_LEVEL_VERBOSE, "Setting cfruncommand to '%s'", CFRUNCOMMAND); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp))) { AppendItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp))) { AppendItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SKIP_VERIFY].lval) == 0) { continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_ALL_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp))) { AppendItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_USERS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET Allowing users ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp))) { AppendItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_TRUST_KEYS_FROM].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp))) { AppendItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWLEGACYCONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp))) { AppendItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_PORT_NUMBER].lval) == 0) { CFENGINE_PORT = IntFromString(value); strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR)); Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d", CFENGINE_PORT); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_BIND_TO_INTERFACE].lval) == 0) { strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE)); Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWCIPHERS].lval) == 0) { SV.allowciphers = xstrdup(value); Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers); continue; } } } const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST); if (value) { /* Don't resolve syslog_host now, better do it per log request. */ if (!SetSyslogHost(value)) { Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value); } else { Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value); } } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT); if (value) { SetSyslogPort(IntFromString(value)); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE); if (value) { FIPS_MODE = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false"); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (value) { LASTSEENEXPIREAFTER = IntFromString(value) * 60; } }
static void ResolveControlBody(EvalContext *ctx, GenericAgentConfig *config, const Body *control_body) { const ConstraintSyntax *body_syntax = NULL; Rval returnval; assert(strcmp(control_body->name, "control") == 0); for (int i = 0; CONTROL_BODIES[i].constraints != NULL; i++) { body_syntax = CONTROL_BODIES[i].constraints; if (strcmp(control_body->type, CONTROL_BODIES[i].body_type) == 0) { break; } } if (body_syntax == NULL) { FatalError(ctx, "Unknown agent"); } char scope[CF_BUFSIZE]; snprintf(scope, CF_BUFSIZE, "%s_%s", control_body->name, control_body->type); Log(LOG_LEVEL_DEBUG, "Initiate control variable convergence for scope '%s'", scope); EvalContextStackPushBodyFrame(ctx, NULL, control_body, NULL); for (size_t i = 0; i < SeqLength(control_body->conlist); i++) { Constraint *cp = SeqAt(control_body->conlist, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_BUNDLESEQUENCE].lval) == 0) { returnval = ExpandPrivateRval(ctx, NULL, scope, cp->rval.item, cp->rval.type); } else { returnval = EvaluateFinalRval(ctx, control_body->parent_policy, NULL, scope, cp->rval, true, NULL); } VarRef *ref = VarRefParseFromScope(cp->lval, scope); EvalContextVariableRemove(ctx, ref); if (!EvalContextVariablePut(ctx, ref, returnval.item, ConstraintSyntaxGetDataType(body_syntax, cp->lval), "source=promise")) { Log(LOG_LEVEL_ERR, "Rule from %s at/before line %zu", control_body->source_path, cp->offset.line); } VarRefDestroy(ref); if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_OUTPUT_PREFIX].lval) == 0) { strncpy(VPREFIX, returnval.item, CF_MAXVARSIZE); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_DOMAIN].lval) == 0) { strcpy(VDOMAIN, cp->rval.item); Log(LOG_LEVEL_VERBOSE, "SET domain = %s", VDOMAIN); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "domain"); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost"); snprintf(VFQNAME, CF_MAXVARSIZE, "%s.%s", VUQNAME, VDOMAIN); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost", VFQNAME, DATA_TYPE_STRING, "inventory,source=agent,group=Host name"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain", VDOMAIN, DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, VDOMAIN, "source=agent"); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_INPUTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_inputs %s", RvalScalarValue(cp->rval)); config->ignore_missing_inputs = BooleanFromString(cp->rval.item); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_BUNDLES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_bundles %s", RvalScalarValue(cp->rval)); config->ignore_missing_bundles = BooleanFromString(cp->rval.item); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET cache_system_functions %s", RvalScalarValue(cp->rval)); bool cache_system_functions = BooleanFromString(RvalScalarValue(cp->rval)); EvalContextSetEvalOption(ctx, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS, cache_system_functions); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_GOALPATTERNS].lval) == 0) { /* Ignored */ continue; } RvalDestroy(returnval); } EvalContextStackPopFrame(ctx); }
/** * Evaluate the relevant control body, and set the * relevant fields in #ctx and #config. */ static void ResolveControlBody(EvalContext *ctx, GenericAgentConfig *config, const Body *control_body) { const char *filename = control_body->source_path; assert(CFG_CONTROLBODY[COMMON_CONTROL_MAX].lval == NULL); const ConstraintSyntax *body_syntax = NULL; for (int i = 0; CONTROL_BODIES[i].constraints != NULL; i++) { body_syntax = CONTROL_BODIES[i].constraints; if (strcmp(control_body->type, CONTROL_BODIES[i].body_type) == 0) { break; } } if (body_syntax == NULL) { FatalError(ctx, "Unknown control body: %s", control_body->type); } char *scope; assert(strcmp(control_body->name, "control") == 0); xasprintf(&scope, "control_%s", control_body->type); Log(LOG_LEVEL_DEBUG, "Initiate control variable convergence for scope '%s'", scope); EvalContextStackPushBodyFrame(ctx, NULL, control_body, NULL); for (size_t i = 0; i < SeqLength(control_body->conlist); i++) { const char *lval; Rval evaluated_rval; size_t lineno; /* Use nested scope to constrain cp. */ { Constraint *cp = SeqAt(control_body->conlist, i); lval = cp->lval; lineno = cp->offset.line; if (!IsDefinedClass(ctx, cp->classes)) { continue; } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_BUNDLESEQUENCE].lval) == 0) { evaluated_rval = ExpandPrivateRval(ctx, NULL, scope, cp->rval.item, cp->rval.type); } else { evaluated_rval = EvaluateFinalRval(ctx, control_body->parent_policy, NULL, scope, cp->rval, true, NULL); } } /* Close scope: assert we only use evaluated_rval, not cp->rval. */ VarRef *ref = VarRefParseFromScope(lval, scope); EvalContextVariableRemove(ctx, ref); DataType rval_proper_datatype = ConstraintSyntaxGetDataType(body_syntax, lval); if (evaluated_rval.type != DataTypeToRvalType(rval_proper_datatype)) { Log(LOG_LEVEL_ERR, "Attribute '%s' in %s:%zu is of wrong type, skipping", lval, filename, lineno); VarRefDestroy(ref); RvalDestroy(evaluated_rval); continue; } bool success = EvalContextVariablePut( ctx, ref, evaluated_rval.item, rval_proper_datatype, "source=promise"); if (!success) { Log(LOG_LEVEL_ERR, "Attribute '%s' in %s:%zu can't be added, skipping", lval, filename, lineno); VarRefDestroy(ref); RvalDestroy(evaluated_rval); continue; } VarRefDestroy(ref); if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_OUTPUT_PREFIX].lval) == 0) { strlcpy(VPREFIX, RvalScalarValue(evaluated_rval), sizeof(VPREFIX)); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_DOMAIN].lval) == 0) { strlcpy(VDOMAIN, RvalScalarValue(evaluated_rval), sizeof(VDOMAIN)); Log(LOG_LEVEL_VERBOSE, "SET domain = %s", VDOMAIN); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "domain"); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost"); snprintf(VFQNAME, CF_MAXVARSIZE, "%s.%s", VUQNAME, VDOMAIN); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost", VFQNAME, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=Host name"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain", VDOMAIN, CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, VDOMAIN, "source=agent"); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_INPUTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_inputs %s", RvalScalarValue(evaluated_rval)); config->ignore_missing_inputs = BooleanFromString( RvalScalarValue(evaluated_rval)); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_BUNDLES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_bundles %s", RvalScalarValue(evaluated_rval)); config->ignore_missing_bundles = BooleanFromString( RvalScalarValue(evaluated_rval)); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET cache_system_functions %s", RvalScalarValue(evaluated_rval)); bool cache_system_functions = BooleanFromString( RvalScalarValue(evaluated_rval)); EvalContextSetEvalOption(ctx, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS, cache_system_functions); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PROTOCOL_VERSION].lval) == 0) { config->protocol_version = ProtocolVersionParse( RvalScalarValue(evaluated_rval)); Log(LOG_LEVEL_VERBOSE, "SET common protocol_version: %s", PROTOCOL_VERSION_STRING[config->protocol_version]); } /* Those are package_inventory and package_module common control body options */ if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PACKAGE_INVENTORY].lval) == 0) { AddDefaultInventoryToContext(ctx, RvalRlistValue(evaluated_rval)); Log(LOG_LEVEL_VERBOSE, "SET common package_inventory list"); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_PACKAGE_MODULE].lval) == 0) { AddDefaultPackageModuleToContext(ctx, RvalScalarValue(evaluated_rval)); Log(LOG_LEVEL_VERBOSE, "SET common package_module: %s", RvalScalarValue(evaluated_rval)); } if (strcmp(lval, CFG_CONTROLBODY[COMMON_CONTROL_GOALPATTERNS].lval) == 0) { /* Ignored */ } RvalDestroy(evaluated_rval); } EvalContextStackPopFrame(ctx); free(scope); }
static void KeepControlPromises(EvalContext *ctx, Policy *policy, GenericAgentConfig *config) { Rval retval; CFD_MAXPROCESSES = 30; MAXTRIES = 5; DENYBADCLOCKS = true; CFRUNCOMMAND[0] = '\0'; SetChecksumUpdates(true); /* Keep promised agent behaviour - control bodies */ Banner("Server control promises.."); PolicyResolve(ctx, policy, config); /* Now expand */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes, NULL)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_server"); if (!EvalContextVariableGet(ctx, ref, &retval, NULL)) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in server control body", cp->lval); VarRefDestroy(ref); continue; } VarRefDestroy(ref); if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SERVER_FACILITY].lval) == 0) { SetFacility(retval.item); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_BAD_CLOCKS].lval) == 0) { DENYBADCLOCKS = BooleanFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting denybadclocks to '%s'", DENYBADCLOCKS ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS].lval) == 0) { LOGENCRYPT = BooleanFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting logencrypt to '%s'", LOGENCRYPT ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ALL_CONNECTIONS].lval) == 0) { SV.logconns = BooleanFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_MAX_CONNECTIONS].lval) == 0) { CFD_MAXPROCESSES = (int) IntFromString(retval.item); MAXTRIES = CFD_MAXPROCESSES / 3; Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFD_MAXPROCESSES); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_INTERVAL].lval) == 0) { COLLECT_INTERVAL = (int) 60 * IntFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting call_collect_interval to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LISTEN].lval) == 0) { SERVER_LISTEN = BooleanFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting server listen to '%s' ", (SERVER_LISTEN)? "true":"false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_WINDOW].lval) == 0) { COLLECT_WINDOW = (int) IntFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting collect_window to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CF_RUN_COMMAND].lval) == 0) { strncpy(CFRUNCOMMAND, retval.item, CF_BUFSIZE - 1); Log(LOG_LEVEL_VERBOSE, "Setting cfruncommand to '%s'", CFRUNCOMMAND); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_CONNECTS].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.nonattackerlist, rp->item)) { AppendItem(&SV.nonattackerlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_CONNECTS].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.attackerlist, rp->item)) { AppendItem(&SV.attackerlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SKIP_VERIFY].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "Setting skip verify connections from ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.skipverify, rp->item)) { AppendItem(&SV.skipverify, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_ALL_CONNECTS].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.multiconnlist, rp->item)) { AppendItem(&SV.multiconnlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_USERS].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "SET Allowing users ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowuserlist, rp->item)) { AppendItem(&SV.allowuserlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_TRUST_KEYS_FROM].lval) == 0) { Rlist *rp; Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ..."); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.trustkeylist, rp->item)) { AppendItem(&SV.trustkeylist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_PORT_NUMBER].lval) == 0) { SHORT_CFENGINEPORT = (short) IntFromString(retval.item); strncpy(STR_CFENGINEPORT, retval.item, 15); Log(LOG_LEVEL_VERBOSE, "Setting default portnumber to %u = %s = %s", (int) SHORT_CFENGINEPORT, STR_CFENGINEPORT, RvalScalarValue(retval)); SHORT_CFENGINEPORT = htons((short) IntFromString(retval.item)); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_BIND_TO_INTERFACE].lval) == 0) { strncpy(BINDINTERFACE, retval.item, CF_BUFSIZE - 1); Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE); continue; } } } if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST, &retval)) { /* Don't resolve syslog_host now, better do it per log request. */ if (!SetSyslogHost(retval.item)) { Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (char *) retval.item); } else { Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (char *) retval.item); } } if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT, &retval)) { SetSyslogPort(IntFromString(retval.item)); } if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE, &retval)) { FIPS_MODE = BooleanFromString(retval.item); Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false"); } if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER, &retval)) { LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60; } }
static void KeepControlPromises(EvalContext *ctx, Policy *policy, GenericAgentConfig *config) { Rval retval; CFD_MAXPROCESSES = 30; MAXTRIES = 5; DENYBADCLOCKS = true; CFRUNCOMMAND[0] = '\0'; SetChecksumUpdates(true); /* Keep promised agent behaviour - control bodies */ Banner("Server control promises.."); HashControls(ctx, policy, config); /* Now expand */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes, NULL)) { continue; } if (!EvalContextVariableGet(ctx, (VarRef) { NULL, "control_server", cp->lval }, &retval, NULL)) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in server control body", cp->lval); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SERVER_FACILITY].lval) == 0) { SetFacility(retval.item); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_BAD_CLOCKS].lval) == 0) { DENYBADCLOCKS = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET denybadclocks = %d\n", DENYBADCLOCKS); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS].lval) == 0) { LOGENCRYPT = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET LOGENCRYPT = %d\n", LOGENCRYPT); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ALL_CONNECTIONS].lval) == 0) { SV.logconns = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET logconns = %d\n", SV.logconns); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_MAX_CONNECTIONS].lval) == 0) { CFD_MAXPROCESSES = (int) IntFromString(retval.item); MAXTRIES = CFD_MAXPROCESSES / 3; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET maxconnections = %d\n", CFD_MAXPROCESSES); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_INTERVAL].lval) == 0) { COLLECT_INTERVAL = (int) 60 * IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET call_collect_interval = %d (seconds)\n", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LISTEN].lval) == 0) { SERVER_LISTEN = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET server listen = %s \n", (SERVER_LISTEN)? "true":"false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_WINDOW].lval) == 0) { COLLECT_WINDOW = (int) IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET collect_window = %d (seconds)\n", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CF_RUN_COMMAND].lval) == 0) { strncpy(CFRUNCOMMAND, retval.item, CF_BUFSIZE - 1); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET cfruncommand = %s\n", CFRUNCOMMAND); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_CONNECTS].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Allowing connections from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.nonattackerlist, rp->item)) { AppendItem(&SV.nonattackerlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_CONNECTS].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Denying connections from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.attackerlist, rp->item)) { AppendItem(&SV.attackerlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SKIP_VERIFY].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Skip verify connections from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.skipverify, rp->item)) { AppendItem(&SV.skipverify, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_ALL_CONNECTS].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Allowing multiple connections from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.multiconnlist, rp->item)) { AppendItem(&SV.multiconnlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_USERS].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Allowing users ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowuserlist, rp->item)) { AppendItem(&SV.allowuserlist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_TRUST_KEYS_FROM].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Trust keys from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.trustkeylist, rp->item)) { AppendItem(&SV.trustkeylist, rp->item, cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_PORT_NUMBER].lval) == 0) { SHORT_CFENGINEPORT = (short) IntFromString(retval.item); strncpy(STR_CFENGINEPORT, retval.item, 15); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET default portnumber = %u = %s = %s\n", (int) SHORT_CFENGINEPORT, STR_CFENGINEPORT, RvalScalarValue(retval)); SHORT_CFENGINEPORT = htons((short) IntFromString(retval.item)); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_KEY_TTL].lval) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Ignoring deprecated option keycacheTTL"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_BIND_TO_INTERFACE].lval) == 0) { strncpy(BINDINTERFACE, retval.item, CF_BUFSIZE - 1); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET bindtointerface = %s\n", BINDINTERFACE); continue; } } } if (ScopeControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST, &retval) != DATA_TYPE_NONE) { SetSyslogHost(Hostname2IPString(retval.item)); } if (ScopeControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT, &retval) != DATA_TYPE_NONE) { SetSyslogPort(IntFromString(retval.item)); } if (ScopeControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE, &retval) != DATA_TYPE_NONE) { FIPS_MODE = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET FIPS_MODE = %d\n", FIPS_MODE); } if (ScopeControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER, &retval) != DATA_TYPE_NONE) { LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60; } }
static int HailServer(EvalContext *ctx, char *host) { AgentConnection *conn; char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], peer[CF_MAXVARSIZE], ipv4[CF_MAXVARSIZE], digest[CF_MAXVARSIZE], user[CF_SMALLBUF]; bool gotkey; char reply[8]; FileCopy fc = { .portnumber = (short) ParseHostname(host, peer), }; snprintf(ipv4, CF_MAXVARSIZE, "%s", Hostname2IPString(peer)); Address2Hostkey(ipv4, digest); GetCurrentUserName(user, CF_SMALLBUF); if (INTERACTIVE) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Using interactive key trust...\n"); gotkey = HavePublicKey(user, peer, digest) != NULL; if (!gotkey) { gotkey = HavePublicKey(user, ipv4, digest) != NULL; } if (!gotkey) { printf("WARNING - You do not have a public key from host %s = %s\n", host, ipv4); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { if (fgets(reply, 8, stdin) == NULL) { FatalError(ctx, "EOF trying to read answer from terminal"); } if (Chop(reply, CF_EXPANDSIZE) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "", "Chop was called on a string that seemed to have no terminator"); } if (strcmp(reply, "yes") == 0) { printf(" -> Will trust the key...\n"); fc.trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf(" -> Will not trust the key...\n"); fc.trustkey = false; break; } else { printf(" !! Please reply yes or no...(%s)\n", reply); } } } } /* Continue */ #ifdef __MINGW32__ CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); #else /* !__MINGW32__ */ if (BACKGROUND) { CfOut(OUTPUT_LEVEL_INFORM, "", "Hailing %s : %u, with options \"%s\" (parallel)\n", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); } else { CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); } #endif /* !__MINGW32__ */ fc.servers = RlistFromSplitString(peer, '*'); if (fc.servers == NULL || strcmp(fc.servers->item, "localhost") == 0) { CfOut(OUTPUT_LEVEL_INFORM, "", "No hosts are registered to connect to"); return false; } else { int err = 0; conn = NewServerConnection(fc, false, &err); if (conn == NULL) { RlistDestroy(fc.servers); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> No suitable server responded to hail\n"); return false; } } /* Check trust interaction*/ HailExec(conn, peer, recvbuffer, sendbuffer); RlistDestroy(fc.servers); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ static void KeepControlPromises(EvalContext *ctx, Policy *policy) { Rval retval; RUNATTR.copy.trustkey = false; RUNATTR.copy.encrypt = true; RUNATTR.copy.force_ipv4 = false; RUNATTR.copy.portnumber = SHORT_CFENGINEPORT; /* Keep promised agent behaviour - control bodies */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes, NULL)) { continue; } if (!EvalContextVariableGet(ctx, (VarRef) { NULL, "control_runagent", cp->lval }, &retval, NULL)) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { RUNATTR.copy.force_ipv4 = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET force_ipv4 = %d\n", RUNATTR.copy.force_ipv4); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { RUNATTR.copy.trustkey = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET trustkey = %d\n", RUNATTR.copy.trustkey); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { RUNATTR.copy.encrypt = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET encrypt = %d\n", RUNATTR.copy.encrypt); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { RUNATTR.copy.portnumber = (short) IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET default portnumber = %u\n", (int) RUNATTR.copy.portnumber); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { CfOut(OUTPUT_LEVEL_ERROR, "", "Warning: 'background_children' setting from 'body runagent control' is overriden by command-line option."); } else { BACKGROUND = BooleanFromString(retval.item); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(retval.item)) { strncpy(OUTPUT_DIRECTORY, retval.item, CF_BUFSIZE - 1); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET output direcory to = %s\n", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { RUNATTR.copy.timeout = (short) IntFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = retval.item; } continue; } } } if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER, &retval)) { LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60; } }
static int HailServer(const EvalContext *ctx, const GenericAgentConfig *config, char *host) { assert(host != NULL); AgentConnection *conn; char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], hostkey[CF_HOSTKEY_STRING_SIZE], user[CF_SMALLBUF]; bool gotkey; char reply[8]; bool trustkey = false; char *hostname, *port; ParseHostPort(host, &hostname, &port); if (hostname == NULL || strcmp(hostname, "localhost") == 0) { Log(LOG_LEVEL_INFO, "No remote hosts were specified to connect to"); return false; } if (port == NULL) { port = "5308"; } char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, hostname, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "HailServer: ERROR, could not resolve '%s'", hostname); return false; } Address2Hostkey(hostkey, sizeof(hostkey), ipaddr); GetCurrentUserName(user, CF_SMALLBUF); if (INTERACTIVE) { Log(LOG_LEVEL_VERBOSE, "Using interactive key trust..."); gotkey = HavePublicKey(user, ipaddr, hostkey) != NULL; if (!gotkey) { /* TODO print the hash of the connecting host. But to do that we * should open the connection first, and somehow pass that hash * here! redmine#7212 */ printf("WARNING - You do not have a public key from host %s = %s\n", hostname, ipaddr); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { if (fgets(reply, sizeof(reply), stdin) == NULL) { FatalError(ctx, "EOF trying to read answer from terminal"); } if (Chop(reply, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } if (strcmp(reply, "yes") == 0) { printf("Will trust the key...\n"); trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf("Will not trust the key...\n"); trustkey = false; break; } else { printf("Please reply yes or no...(%s)\n", reply); } } } } #ifndef __MINGW32__ if (BACKGROUND) { Log(LOG_LEVEL_INFO, "Hailing %s : %s (in the background)", hostname, port); } else #endif { Log(LOG_LEVEL_INFO, "........................................................................"); Log(LOG_LEVEL_INFO, "Hailing %s : %s", hostname, port); Log(LOG_LEVEL_INFO, "........................................................................"); } ConnectionFlags connflags = { .protocol_version = config->protocol_version, .trust_server = trustkey }; int err = 0; conn = ServerConnection(hostname, port, CONNTIMEOUT, connflags, &err); if (conn == NULL) { Log(LOG_LEVEL_ERR, "Failed to connect to host: %s", hostname); return false; } /* Send EXEC command. */ HailExec(conn, hostname, recvbuffer, sendbuffer); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_runagent"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { Log(LOG_LEVEL_WARNING, "'background_children' setting from 'body runagent control' is overridden by command-line option."); } else { BACKGROUND = BooleanFromString(value); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(value)) { strlcpy(OUTPUT_DIRECTORY, value, CF_BUFSIZE); Log(LOG_LEVEL_VERBOSE, "Setting output direcory to '%s'", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = value; } continue; } } } const char *expire_after = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (expire_after) { LASTSEENEXPIREAFTER = IntFromString(expire_after) * 60; } }
static int HailServer(EvalContext *ctx, char *host) { AgentConnection *conn; char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], peer[CF_MAXVARSIZE], digest[CF_MAXVARSIZE], user[CF_SMALLBUF]; bool gotkey; char reply[8]; FileCopy fc = { .portnumber = (unsigned short) ParseHostname(host, peer), }; char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, peer, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "HailServer: ERROR, could not resolve '%s'", peer); return false; } Address2Hostkey(ipaddr, digest); GetCurrentUserName(user, CF_SMALLBUF); if (INTERACTIVE) { Log(LOG_LEVEL_VERBOSE, "Using interactive key trust..."); gotkey = HavePublicKey(user, peer, digest) != NULL; if (!gotkey) { gotkey = HavePublicKey(user, ipaddr, digest) != NULL; } if (!gotkey) { printf("WARNING - You do not have a public key from host %s = %s\n", host, ipaddr); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { if (fgets(reply, sizeof(reply), stdin) == NULL) { FatalError(ctx, "EOF trying to read answer from terminal"); } if (Chop(reply, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } if (strcmp(reply, "yes") == 0) { printf("Will trust the key...\n"); fc.trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf("Will not trust the key...\n"); fc.trustkey = false; break; } else { printf("Please reply yes or no...(%s)\n", reply); } } } } /* Continue */ #ifdef __MINGW32__ if (LEGACY_OUTPUT) { Log(LOG_LEVEL_INFO, "..........................................................................."); Log(LOG_LEVEL_INFO, " * Hailing %s : %u, with options \"%s\" (serial)", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); Log(LOG_LEVEL_INFO, "..........................................................................."); } else { Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (serial)", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); } #else /* !__MINGW32__ */ if (BACKGROUND) { Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (parallel)", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); } else { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_INFO, "..........................................................................."); Log(LOG_LEVEL_INFO, " * Hailing %s : %u, with options \"%s\" (serial)", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); Log(LOG_LEVEL_INFO, "..........................................................................."); } else { Log(LOG_LEVEL_INFO, "Hailing '%s' : %u, with options '%s' (serial)", peer, fc.portnumber, REMOTE_AGENT_OPTIONS); } } #endif /* !__MINGW32__ */ fc.servers = RlistFromSplitString(peer, '*'); if (fc.servers == NULL || strcmp(RlistScalarValue(fc.servers), "localhost") == 0) { Log(LOG_LEVEL_INFO, "No hosts are registered to connect to"); return false; } else { int err = 0; conn = NewServerConnection(fc, false, &err, -1); if (conn == NULL) { RlistDestroy(fc.servers); Log(LOG_LEVEL_VERBOSE, "No suitable server responded to hail"); return false; } } /* Check trust interaction*/ HailExec(conn, peer, recvbuffer, sendbuffer); RlistDestroy(fc.servers); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_runagent"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { Log(LOG_LEVEL_WARNING, "'background_children' setting from 'body runagent control' is overridden by command-line option."); } else { BACKGROUND = BooleanFromString(value); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(value)) { strncpy(OUTPUT_DIRECTORY, value, CF_BUFSIZE - 1); Log(LOG_LEVEL_VERBOSE, "Setting output direcory to '%s'", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = value; } continue; } } } const char *expire_after = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (expire_after) { LASTSEENEXPIREAFTER = IntFromString(expire_after) * 60; } }
void KeepControlPromises(Policy *policy) { Rval retval; Rlist *rp; Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_AGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (IsExcluded(cp->classes, NULL)) { continue; } if (GetVariable("control_common", cp->lval, &retval) != DATA_TYPE_NONE) { /* Already handled in generic_agent */ continue; } if (GetVariable("control_agent", cp->lval, &retval) == DATA_TYPE_NONE) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in agent control body", cp->lval); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_maxconnections].lval) == 0) { CFA_MAXTHREADS = (int) IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET maxconnections = %d\n", CFA_MAXTHREADS); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_checksum_alert_time].lval) == 0) { CF_PERSISTENCE = (int) IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET checksum_alert_time = %d\n", CF_PERSISTENCE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_agentfacility].lval) == 0) { SetFacility(retval.item); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_agentaccess].lval) == 0) { ACCESSLIST = (Rlist *) retval.item; CheckAgentAccess(ACCESSLIST, InputFiles(policy)); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_refresh_processes].lval) == 0) { Rlist *rp; if (VERBOSE) { printf("%s> SET refresh_processes when starting: ", VPREFIX); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { printf(" %s", (char *) rp->item); PrependItem(&PROCESSREFRESH, rp->item, NULL); } printf("\n"); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_abortclasses].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Abort classes from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strncpy(name, rp->item, CF_MAXVARSIZE - 1); AddAbortClass(name, cp->classes); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_abortbundleclasses].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET Abort bundle classes from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strncpy(name, rp->item, CF_MAXVARSIZE - 1); if (!IsItemIn(ABORTBUNDLEHEAP, name)) { AppendItem(&ABORTBUNDLEHEAP, name, cp->classes); } } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_addclasses].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "-> Add classes ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> ... %s\n", RlistScalarValue(rp)); NewClass(rp->item, NULL); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_auditing].lval) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "This option does nothing and is retained for compatibility reasons"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_alwaysvalidate].lval) == 0) { ALWAYS_VALIDATE = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET alwaysvalidate = %d\n", ALWAYS_VALIDATE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_allclassesreport].lval) == 0) { ALLCLASSESREPORT = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET allclassesreport = %d\n", ALLCLASSESREPORT); } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_secureinput].lval) == 0) { CFPARANOID = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET secure input = %d\n", CFPARANOID); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_binarypaddingchar].lval) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "binarypaddingchar is obsolete and does nothing\n"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_bindtointerface].lval) == 0) { strncpy(BINDINTERFACE, retval.item, CF_BUFSIZE - 1); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET bindtointerface = %s\n", BINDINTERFACE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_hashupdates].lval) == 0) { bool enabled = BooleanFromString(retval.item); SetChecksumUpdates(enabled); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET ChecksumUpdates %d\n", enabled); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_exclamation].lval) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "exclamation control is deprecated and does not do anything\n"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_childlibpath].lval) == 0) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "LD_LIBRARY_PATH=%s", (char *) retval.item); if (putenv(xstrdup(output)) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Setting %s\n", output); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_defaultcopytype].lval) == 0) { DEFAULT_COPYTYPE = (char *) retval.item; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET defaultcopytype = %s\n", DEFAULT_COPYTYPE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_fsinglecopy].lval) == 0) { SINGLE_COPY_LIST = (Rlist *) retval.item; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET file single copy list\n"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_fautodefine].lval) == 0) { SetFileAutoDefineList(RvalRlistValue(retval)); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET file auto define list\n"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_dryrun].lval) == 0) { DONTDO = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET dryrun = %c\n", DONTDO); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_inform].lval) == 0) { INFORM = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET inform = %c\n", INFORM); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_verbose].lval) == 0) { VERBOSE = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET inform = %c\n", VERBOSE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_repository].lval) == 0) { SetRepositoryLocation(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET repository = %s\n", RvalScalarValue(retval)); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_skipidentify].lval) == 0) { bool enabled = BooleanFromString(retval.item); SetSkipIdentify(enabled); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET skipidentify = %d\n", (int) enabled); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_suspiciousnames].lval) == 0) { for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { AddFilenameToListOfSuspicious(RlistScalarValue(rp)); CfOut(OUTPUT_LEVEL_VERBOSE, "", "-> Considering %s as suspicious file", RlistScalarValue(rp)); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_repchar].lval) == 0) { char c = *(char *) retval.item; SetRepositoryChar(c); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET repchar = %c\n", c); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_mountfilesystems].lval) == 0) { CF_MOUNTALL = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET mountfilesystems = %d\n", CF_MOUNTALL); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_editfilesize].lval) == 0) { EDITFILESIZE = IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET EDITFILESIZE = %d\n", EDITFILESIZE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_ifelapsed].lval) == 0) { VIFELAPSED = IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET ifelapsed = %d\n", VIFELAPSED); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_expireafter].lval) == 0) { VEXPIREAFTER = IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET ifelapsed = %d\n", VEXPIREAFTER); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_timeout].lval) == 0) { CONNTIMEOUT = IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET timeout = %jd\n", (intmax_t) CONNTIMEOUT); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_max_children].lval) == 0) { CFA_BACKGROUND_LIMIT = IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET MAX_CHILDREN = %d\n", CFA_BACKGROUND_LIMIT); if (CFA_BACKGROUND_LIMIT > 10) { CfOut(OUTPUT_LEVEL_ERROR, "", "Silly value for max_children in agent control promise (%d > 10)", CFA_BACKGROUND_LIMIT); CFA_BACKGROUND_LIMIT = 1; } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_syslog].lval) == 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET syslog = %d\n", BooleanFromString(retval.item)); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[cfa_environment].lval) == 0) { Rlist *rp; CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET environment variables from ...\n"); for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { if (putenv(rp->item) != 0) { CfOut(OUTPUT_LEVEL_ERROR, "putenv", "Failed to set environment variable %s", RlistScalarValue(rp)); } } continue; } } } if (GetVariable("control_common", CFG_CONTROLBODY[cfg_lastseenexpireafter].lval, &retval) != DATA_TYPE_NONE) { LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60; } if (GetVariable("control_common", CFG_CONTROLBODY[cfg_fips_mode].lval, &retval) != DATA_TYPE_NONE) { FIPS_MODE = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET FIPS_MODE = %d\n", FIPS_MODE); } if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_port].lval, &retval) != DATA_TYPE_NONE) { SetSyslogPort(IntFromString(retval.item)); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET syslog_port to %s", RvalScalarValue(retval)); } if (GetVariable("control_common", CFG_CONTROLBODY[cfg_syslog_host].lval, &retval) != DATA_TYPE_NONE) { SetSyslogHost(Hostname2IPString(retval.item)); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET syslog_host to %s", Hostname2IPString(retval.item)); } #ifdef HAVE_NOVA Nova_Initialize(); #endif }
static void KeepControlPromises(Policy *policy) { Rval retval; RUNATTR.copy.trustkey = false; RUNATTR.copy.encrypt = true; RUNATTR.copy.force_ipv4 = false; RUNATTR.copy.portnumber = SHORT_CFENGINEPORT; /* Keep promised agent behaviour - control bodies */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (IsExcluded(cp->classes, NULL)) { continue; } if (GetVariable("control_runagent", cp->lval, &retval) == DATA_TYPE_NONE) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unknown lval %s in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { RUNATTR.copy.force_ipv4 = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET force_ipv4 = %d\n", RUNATTR.copy.force_ipv4); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { RUNATTR.copy.trustkey = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET trustkey = %d\n", RUNATTR.copy.trustkey); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { RUNATTR.copy.encrypt = BooleanFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET encrypt = %d\n", RUNATTR.copy.encrypt); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { RUNATTR.copy.portnumber = (short) IntFromString(retval.item); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET default portnumber = %u\n", (int) RUNATTR.copy.portnumber); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { CfOut(OUTPUT_LEVEL_ERROR, "", "Warning: 'background_children' setting from 'body runagent control' is overriden by command-line option."); } else { BACKGROUND = BooleanFromString(retval.item); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(retval.item)) { strncpy(OUTPUT_DIRECTORY, retval.item, CF_BUFSIZE - 1); CfOut(OUTPUT_LEVEL_VERBOSE, "", "SET output direcory to = %s\n", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { RUNATTR.copy.timeout = (short) IntFromString(retval.item); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = retval.item; } continue; } } } if (GetVariable("control_common", CFG_CONTROLBODY[cfg_lastseenexpireafter].lval, &retval) != DATA_TYPE_NONE) { LASTSEENEXPIREAFTER = IntFromString(retval.item) * 60; } }