static Reload CheckNewPromises(GenericAgentConfig *config) { Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); if (config->agent_specific.daemon.last_validated_at < validated_at) { /* Rereading policies now, so update timestamp. */ config->agent_specific.daemon.last_validated_at = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { return RELOAD_FULL; } else { Log(LOG_LEVEL_INFO, "New promises file contains syntax errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } return RELOAD_ENVIRONMENT; }
static Reload CheckNewPromises(const GenericAgentConfig *config, time_t *last_policy_reload) { time_t validated_at; Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config); if (*last_policy_reload < validated_at) { *last_policy_reload = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { return RELOAD_FULL; } else { Log(LOG_LEVEL_INFO, "New promises file contains syntax errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } return RELOAD_ENVIRONMENT; }
bool GenericAgentCheckPolicy(GenericAgentConfig *config, bool force_validation, bool write_validated_file) { if (!MissingInputFile(config->input_file)) { { if (config->agent_type == AGENT_TYPE_SERVER || config->agent_type == AGENT_TYPE_MONITOR || config->agent_type == AGENT_TYPE_EXECUTOR) { time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); config->agent_specific.daemon.last_validated_at = validated_at; } } if (IsPolicyPrecheckNeeded(config, force_validation)) { bool policy_check_ok = GenericAgentArePromisesValid(config); if (policy_check_ok && write_validated_file) { GenericAgentTagReleaseDirectory(config, NULL, // use GetAutotagDir write_validated_file, // true GetAmPolicyHub(GetWorkDir())); // write release ID? } if (config->agent_specific.agent.bootstrap_policy_server && !policy_check_ok) { Log(LOG_LEVEL_VERBOSE, "Policy is not valid, but proceeding with bootstrap"); return true; } return policy_check_ok; } else { Log(LOG_LEVEL_VERBOSE, "Policy is already validated"); return true; } } return false; }
static void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); bool reload_config = false; if (config->agent_specific.daemon.last_validated_at < validated_at) { Log(LOG_LEVEL_VERBOSE, "New promises detected..."); reload_config = true; } if (ReloadConfigRequested()) { Log(LOG_LEVEL_VERBOSE, "Force reload of inputs files..."); reload_config = true; } if (reload_config) { ClearRequestReloadConfig(); /* Rereading policies now, so update timestamp. */ config->agent_specific.daemon.last_validated_at = validated_at; if (GenericAgentArePromisesValid(config)) { Log(LOG_LEVEL_NOTICE, "Rereading policy file '%s'", config->input_file); /* STEP 1: Free everything */ EvalContextClear(ctx); strcpy(VDOMAIN, "undefined.domain"); ClearAuthAndACLs(); PolicyDestroy(*policy); *policy = NULL; /* STEP 2: Set Environment, Parse and Evaluate policy */ /* * TODO why is this done separately here? What's the difference to * calling the same steps as in cf-serverd.c:main()? Those are: * GenericAgentConfigApply(); // not here! * GenericAgentDiscoverContext(); // not here! * EvalContextClassPutHard("server"); // only here! * if (GenericAgentCheckPolicy()) // not here! * policy = LoadPolicy(); * ThisAgentInit(); // not here, only calls umask() * ReloadHAConfig(); // only here! * KeepPromises(); * Summarize(); * Plus the following from within StartServer() which is only * called during startup: * InitSignals(); // not here * ServerTLSInitialize(); // not here * SetServerListenState(); // not here * InitServer() // not here * PolicyNew()+AcquireServerLock() // not here * PrepareServer(sd); // not here * CollectCallStart(); // both */ EvalContextSetPolicyServerFromFile(ctx, GetWorkDir()); UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); KeepHardClasses(ctx); LoadAugments(ctx, config); /* During startup this is done in GenericAgentDiscoverContext(). */ EvalContextClassPutHard(ctx, CF_AGENTTYPES[AGENT_TYPE_SERVER], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); /* TODO BUG: this modifies config, but previous config has not * been reset/free'd. Ideally we would want LoadPolicy to not * modify config at all, but only modify ctx. */ *policy = LoadPolicy(ctx, config); /* Reload HA related configuration */ ReloadHAConfig(); KeepPromises(ctx, *policy, config); Summarize(); } else { Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } }
static void Apoptosis(void) { char promiser_buf[CF_SMALLBUF]; snprintf(promiser_buf, sizeof(promiser_buf), "%s%cbin%ccf-execd", GetWorkDir(), FILE_SEPARATOR, FILE_SEPARATOR); if (LoadProcessTable()) { char myuid[PRINTSIZE(unsigned)]; xsnprintf(myuid, sizeof(myuid), "%u", (unsigned) getuid()); Rlist *owners = NULL; RlistPrepend(&owners, myuid, RVAL_TYPE_SCALAR); ProcessSelect process_select = { .owner = owners, .process_result = "process_owner", }; Item *killlist = SelectProcesses(promiser_buf, process_select, true); RlistDestroy(owners); for (Item *ip = killlist; ip != NULL; ip = ip->next) { pid_t pid = ip->counter; if (pid != getpid() && kill(pid, SIGTERM) < 0) { if (errno == ESRCH) { /* That's ok, process exited voluntarily */ } else { Log(LOG_LEVEL_ERR, "Unable to kill stale cf-execd process pid=%d. (kill: %s)", (int)pid, GetErrorStr()); } } } } ClearProcessTable(); Log(LOG_LEVEL_VERBOSE, "Pruning complete"); } #endif typedef enum { RELOAD_ENVIRONMENT, RELOAD_FULL } Reload; static Reload CheckNewPromises(GenericAgentConfig *config) { Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); bool reload_config = false; if (config->agent_specific.daemon.last_validated_at < validated_at) { Log(LOG_LEVEL_VERBOSE, "New promises detected..."); reload_config = true; } if (ReloadConfigRequested()) { Log(LOG_LEVEL_VERBOSE, "Force reload of inputs files..."); reload_config = true; } if (reload_config) { ClearRequestReloadConfig(); /* Rereading policies now, so update timestamp. */ config->agent_specific.daemon.last_validated_at = validated_at; if (GenericAgentArePromisesValid(config)) { return RELOAD_FULL; } else { Log(LOG_LEVEL_INFO, "New promises file contains syntax errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } return RELOAD_ENVIRONMENT; }
void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, time_t *last_policy_reload) { time_t validated_at; Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config); if (*last_policy_reload < validated_at) { *last_policy_reload = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { Log(LOG_LEVEL_INFO, "Rereading policy file '%s'", config->input_file); /* Free & reload -- lock this to avoid access errors during reload */ EvalContextClear(ctx); free(SV.allowciphers); SV.allowciphers = NULL; DeleteItemList(SV.trustkeylist); DeleteItemList(SV.attackerlist); DeleteItemList(SV.nonattackerlist); DeleteItemList(SV.multiconnlist); DeleteAuthList(&SV.admit, &SV.admittail); DeleteAuthList(&SV.deny, &SV.denytail); DeleteAuthList(&SV.varadmit, &SV.varadmittail); DeleteAuthList(&SV.vardeny, &SV.vardenytail); DeleteAuthList(&SV.roles, &SV.rolestail); strcpy(VDOMAIN, "undefined.domain"); SV.trustkeylist = NULL; SV.attackerlist = NULL; SV.nonattackerlist = NULL; SV.multiconnlist = NULL; acl_Free(paths_acl); paths_acl = NULL; acl_Free(classes_acl); classes_acl = NULL; acl_Free(vars_acl); vars_acl = NULL; acl_Free(literals_acl); literals_acl = NULL; acl_Free(query_acl); query_acl = NULL; StringMapDestroy(SV.path_shortcuts); SV.path_shortcuts = NULL; PolicyDestroy(*policy); *policy = NULL; { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); } UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); KeepHardClasses(ctx); EvalContextClassPutHard(ctx, CF_AGENTTYPES[AGENT_TYPE_SERVER], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); *policy = GenericAgentLoadPolicy(ctx, config); KeepPromises(ctx, *policy, config); Summarize(); } else { Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } }
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; } char servname[10]; snprintf(servname, 10, "%d", CFENGINE_PORT); /* Resolve listening interface. */ if (getaddrinfo(ptr, servname, &query, &response) != 0) { Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)", GetErrorStr()); 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) { Log(LOG_LEVEL_ERR, "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)", GetErrorStr()); exit(1); } struct linger cflinger = { .l_onoff = 1, .l_linger = 60 }; if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &cflinger, sizeof(cflinger)) == -1) { Log(LOG_LEVEL_ERR, "Socket option SO_LINGER was not accepted. (setsockopt: %s)", GetErrorStr()); exit(1); } if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1) { if (LogGetGlobalLevel() >= LOG_LEVEL_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); Log(LOG_LEVEL_DEBUG, "Bound to address '%s' on '%s' = %d", txtaddr, CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS); } break; } else { Log(LOG_LEVEL_ERR, "Could not bind server address. (bind: %s)", GetErrorStr()); cf_closesocket(sd); } } if (sd < 0) { Log(LOG_LEVEL_ERR, "Couldn't open/bind a socket"); exit(1); } freeaddrinfo(response); return sd; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, time_t *last_policy_reload) { time_t validated_at; Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config); if (*last_policy_reload < validated_at) { *last_policy_reload = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { Log(LOG_LEVEL_INFO, "Rereading policy file '%s'", config->input_file); /* Free & reload -- lock this to avoid access errors during reload */ EvalContextClear(ctx); free(SV.allowciphers); SV.allowciphers = NULL; DeleteItemList(SV.trustkeylist); DeleteItemList(SV.attackerlist); DeleteItemList(SV.nonattackerlist); DeleteItemList(SV.multiconnlist); DeleteAuthList(SV.admit); DeleteAuthList(SV.deny); DeleteAuthList(SV.varadmit); DeleteAuthList(SV.vardeny); DeleteAuthList(SV.roles); strcpy(VDOMAIN, "undefined.domain"); 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.attackerlist = NULL; SV.nonattackerlist = NULL; SV.multiconnlist = NULL; PolicyDestroy(*policy); *policy = NULL; { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); } UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); KeepHardClasses(ctx); EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); *policy = GenericAgentLoadPolicy(ctx, config); KeepPromises(ctx, *policy, config); Summarize(); } else { Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } }