void Summarize() { Auth *ptr; Item *ip, *ipr; CfOut(cf_verbose, "", "Summarize control promises\n"); CfOut(cf_verbose, "", "Granted access to paths :\n"); for (ptr = VADMIT; ptr != NULL; ptr = ptr->next) { CfOut(cf_verbose, "", "Path: %s (encrypt=%d)\n", ptr->path, ptr->encrypt); for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " Admit: %s root=", ip->name); for (ipr = ptr->maproot; ipr != NULL; ipr = ipr->next) { CfOut(cf_verbose, "", "%s,", ipr->name); } } } CfOut(cf_verbose, "", "Denied access to paths :\n"); for (ptr = VDENY; ptr != NULL; ptr = ptr->next) { CfOut(cf_verbose, "", "Path: %s\n", ptr->path); for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " Deny: %s\n", ip->name); } } CfOut(cf_verbose, "", " -> Host IPs allowed connection access :\n"); for (ip = NONATTACKERLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } CfOut(cf_verbose, "", "Host IPs denied connection access :\n"); for (ip = ATTACKERLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } CfOut(cf_verbose, "", "Host IPs allowed multiple connection access :\n"); for (ip = MULTICONNLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } CfOut(cf_verbose, "", "Host IPs from whom we shall accept public keys on trust :\n"); for (ip = TRUSTKEYLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } CfOut(cf_verbose, "", "Users from whom we accept connections :\n"); for (ip = ALLOWUSERLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... USERS: %s\n", ip->name); } CfOut(cf_verbose, "", "Host IPs from NAT which we don't verify :\n"); for (ip = SKIPVERIFY; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } CfOut(cf_verbose, "", "Dynamical Host IPs (e.g. DHCP) whose bindings could vary over time :\n"); for (ip = DHCPLIST; ip != NULL; ip = ip->next) { CfOut(cf_verbose, "", " .... IP: %s\n", ip->name); } }
int ConsiderFile(const char *nodename,char *path,struct Attributes attr,struct Promise *pp) { int i, suspicious = true; struct stat statbuf; char newname[CF_BUFSIZE],vbuff[CF_BUFSIZE]; const char *sp; static char *skipfiles[] = { ".", "..", "lost+found", ".cfengine.rm", NULL }; if (strlen(nodename) < 1) { CfOut(cf_error,"","Empty (null) filename detected in %s\n",path); return true; } if (IsItemIn(SUSPICIOUSLIST,nodename)) { struct stat statbuf; if (cfstat(nodename,&statbuf) != -1) { if (S_ISREG(statbuf.st_mode)) { CfOut(cf_error,"","Suspicious file %s found in %s\n",nodename,path); return false; } } } if (strcmp(nodename,"...") == 0) { CfOut(cf_verbose,"","Possible DFS/FS cell node detected in %s...\n",path); return true; } for (i = 0; skipfiles[i] != NULL; i++) { if (strcmp(nodename,skipfiles[i]) == 0) { Debug("Filename %s/%s is classified as ignorable\n",path,nodename); return false; } } if ((strcmp("[",nodename) == 0) && (strcmp("/usr/bin",path) == 0)) { if (VSYSTEMHARDCLASS == linuxx) { return true; } } suspicious = true; for (sp = nodename; *sp != '\0'; sp++) { if ((*sp > 31) && (*sp < 127)) { suspicious = false; break; } } strcpy(vbuff,path); AddSlash(vbuff); strcat(vbuff,nodename); for (sp = nodename; *sp != '\0'; sp++) /* Check for files like ".. ." */ { if ((*sp != '.') && ! isspace(*sp)) { suspicious = false; return true; } } if (cf_lstat(vbuff,&statbuf,attr,pp) == -1) { CfOut(cf_verbose,"lstat","Couldn't stat %s",vbuff); return true; } if (statbuf.st_size == 0 && ! (VERBOSE||INFORM)) /* No sense in warning about empty files */ { return false; } CfOut(cf_error,"","Suspicious looking file object \"%s\" masquerading as hidden file in %s\n",nodename,path); Debug("Filename looks suspicious\n"); if (S_ISLNK(statbuf.st_mode)) { CfOut(cf_inform,""," %s is a symbolic link\n",nodename); } else if (S_ISDIR(statbuf.st_mode)) { CfOut(cf_inform,""," %s is a directory\n",nodename); } CfOut(cf_verbose,"","[%s] has size %ld and full mode %o\n",nodename,(unsigned long)(statbuf.st_size),(unsigned int)(statbuf.st_mode)); return true; }
static void KeepKeyPromises(void) { unsigned long err; RSA *pair; FILE *fp; struct stat statbuf; int fd; static char *passphrase = "Cfengine passphrase"; const EVP_CIPHER *cipher; char vbuff[CF_BUFSIZE]; NewScope("common"); cipher = EVP_des_ede3_cbc(); if (cfstat(CFPUBKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPUBKEYFILE); return; } if (cfstat(CFPRIVKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPRIVKEYFILE); return; } printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); pair = RSA_generate_key(2048, 35, NULL, NULL); if (pair == NULL) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to generate key: %s\n", ERR_reason_error_string(err)); return; } if (DEBUG) { RSA_print_fp(stdout, pair, 0); } fd = open(CFPRIVKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Open %s failed: %s.", CFPRIVKEYFILE, strerror(errno)); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Couldn't open private key %s.", CFPRIVKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing private key to %s\n", CFPRIVKEYFILE); if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL)) { err = ERR_get_error(); CfOut(cf_error, "", "Couldn't write private key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); fd = open(CFPUBKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Unable to open public key %s.", CFPUBKEYFILE); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Open %s failed.", CFPUBKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing public key to %s\n", CFPUBKEYFILE); if (!PEM_write_RSAPublicKey(fp, pair)) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to write public key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR); RAND_write_file(vbuff); cf_chmod(vbuff, 0644); }
int main(int argc, char *argv[]) { int ret = 0; GenericAgentConfig *config = CheckOpts(argc, argv); #ifdef HAVE_AVAHI_CLIENT_CLIENT_H #ifdef HAVE_AVAHI_COMMON_ADDRESS_H if (NULL_OR_EMPTY(POLICY_SERVER) && BOOTSTRAP) { int ret = AutomaticBootstrap(); if (ret < 0) { return 1; } } #endif #endif ReportContext *report_context = OpenReports(config->agent_type); GenericAgentDiscoverContext(config, report_context); Policy *policy = NULL; if (GenericAgentCheckPolicy(config, report_context, ALWAYS_VALIDATE)) { policy = GenericAgentLoadPolicy(config->agent_type, config, report_context); } else if (config->tty_interactive) { FatalError("CFEngine was not able to get confirmation of promises from cf-promises, please verify input file\n"); } else { CfOut(OUTPUT_LEVEL_ERROR, "", "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe\n"); HardClass("failsafe_fallback"); GenericAgentConfigSetInputFile(config, "failsafe.cf"); policy = GenericAgentLoadPolicy(config->agent_type, config, report_context); } CheckLicenses(); ThisAgentInit(); BeginAudit(); KeepPromises(policy, config, report_context); CloseReports("agent", report_context); // only note class usage when default policy is run if (!config->input_file) { NoteClassUsage(VHEAP, true); NoteClassUsage(VHARDHEAP, true); } #ifdef HAVE_NOVA Nova_NoteVarUsageDB(); Nova_TrackExecution(config->input_file); #endif PurgeLocks(); if (BOOTSTRAP && !VerifyBootstrap()) { ret = 1; } EndAudit(CFA_BACKGROUND); GenericAgentConfigDestroy(config); return ret; }
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 int HailServer(char *host, Attributes a, Promise *pp) { 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]; a.copy.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("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"); a.copy.trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf(" -> Will not trust the key...\n"); a.copy.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, a.copy.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, a.copy.portnumber, REMOTE_AGENT_OPTIONS); } else { CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); CfOut(OUTPUT_LEVEL_INFORM, "", " * Hailing %s : %u, with options \"%s\" (serial)\n", peer, a.copy.portnumber, REMOTE_AGENT_OPTIONS); CfOut(OUTPUT_LEVEL_INFORM, "", "...........................................................................\n"); } #endif /* !__MINGW32__ */ a.copy.servers = RlistFromSplitString(peer, '*'); if (a.copy.servers == NULL || strcmp(a.copy.servers->item, "localhost") == 0) { cfPS(OUTPUT_LEVEL_INFORM, CF_NOP, "", pp, a, "No hosts are registered to connect to"); return false; } else { conn = NewServerConnection(a, pp); if (conn == NULL) { RlistDestroy(a.copy.servers); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> No suitable server responded to hail\n"); return false; } } /* Check trust interaction*/ pp->cache = NULL; if (strlen(MENU) > 0) { #if defined(HAVE_NOVA) if (!ExecuteRunagent(conn, MENU)) { DisconnectServer(conn); RlistDestroy(a.copy.servers); return false; } #endif } else { HailExec(conn, peer, recvbuffer, sendbuffer); } RlistDestroy(a.copy.servers); return true; }
static void HailExec(AgentConnection *conn, char *peer, char *recvbuffer, char *sendbuffer) { FILE *fp = stdout; char *sp; int n_read; if (strlen(DEFINECLASSES)) { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s -D%s", REMOTE_AGENT_OPTIONS, DEFINECLASSES); } else { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s", REMOTE_AGENT_OPTIONS); } if (SendTransaction(conn->sd, sendbuffer, 0, CF_DONE) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "send", "Transmission rejected"); DisconnectServer(conn); return; } fp = NewStream(peer); SendClassData(conn); while (true) { memset(recvbuffer, 0, CF_BUFSIZE); if ((n_read = ReceiveTransaction(conn->sd, recvbuffer, NULL)) == -1) { return; } if (n_read == 0) { break; } if (strlen(recvbuffer) == 0) { continue; } if ((sp = strstr(recvbuffer, CFD_TERMINATOR)) != NULL) { break; } if ((sp = strstr(recvbuffer, "BAD:")) != NULL) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer + 4); continue; } if (strstr(recvbuffer, "too soon")) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer); continue; } fprintf(fp, "%s> -> %s", VPREFIX, recvbuffer); } DeleteStream(fp); DisconnectServer(conn); }
static void CfenvTimeOut(int signum) { alarm(0); TCPPAUSE = true; CfOut(cf_verbose, "", "Time out\n"); }
void MonNetworkSnifferGatherData(double *cf_this) { int i; char vbuff[CF_BUFSIZE]; for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); CfDebug("save incoming %s\n", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, TCPNAMES[i]); if (cfstat(vbuff, &statbuf) != -1) { if ((ByteSizeList(NETIN_DIST[i]) < statbuf.st_size) && (now < statbuf.st_mtime + 40 * 60)) { CfOut(cf_verbose, "", "New state %s is smaller, retaining old for 40 mins longer\n", TCPNAMES[i]); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETIN_DIST[i], i, "in"); entropy = MonEntropyCalculate(NETIN_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "in", entropy); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; } for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); CfDebug("save outgoing %s\n", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, TCPNAMES[i]); if (cfstat(vbuff, &statbuf) != -1) { if ((ByteSizeList(NETOUT_DIST[i]) < statbuf.st_size) && (now < statbuf.st_mtime + 40 * 60)) { CfOut(cf_verbose, "", "New state %s is smaller, retaining old for 40 mins longer\n", TCPNAMES[i]); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETOUT_DIST[i], i, "out"); entropy = MonEntropyCalculate(NETOUT_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "out", entropy); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; } }
int AddVariableHash(const char *scope, const char *lval, Rval rval, enum cfdatatype dtype, const char *fname, int lineno) { Scope *ptr; const Rlist *rp; CfAssoc *assoc; if (rval.rtype == CF_SCALAR) { CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", scope, lval, (const char *) rval.item, CF_DATATYPES[dtype], rval.rtype); } else { CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", scope, lval, CF_DATATYPES[dtype], rval.rtype); } if (lval == NULL || scope == NULL) { CfOut(cf_error, "", "scope.value = %s.%s", scope, lval); ReportError("Bad variable or scope in a variable assignment"); FatalError("Should not happen - forgotten to register a function call in fncall.c?"); } if (rval.item == NULL) { CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n"); return false; } if (strlen(lval) > CF_MAXVARSIZE) { ReportError("variable lval too long"); return false; } /* If we are not expanding a body template, check for recursive singularities */ if (strcmp(scope, "body") != 0) { switch (rval.rtype) { case CF_SCALAR: if (StringContainsVar((char *) rval.item, lval)) { CfOut(cf_error, "", "Scalar variable %s.%s contains itself (non-convergent): %s", scope, lval, (char *) rval.item); return false; } break; case CF_LIST: for (rp = rval.item; rp != NULL; rp = rp->next) { if (StringContainsVar((char *) rp->item, lval)) { CfOut(cf_error, "", "List variable %s contains itself (non-convergent)", lval); return false; } } break; } } ptr = GetScope(scope); if (ptr == NULL) { return false; } // Look for outstanding lists in variable rvals if (THIS_AGENT_TYPE == cf_common) { Rlist *listvars = NULL, *scalarvars = NULL; if (strcmp(CONTEXTID, "this") != 0) { MapIteratorsFromRval(CONTEXTID, &scalarvars, &listvars, rval, NULL); if (listvars != NULL) { CfOut(cf_error, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"", lval, CONTEXTID); } DeleteRlist(scalarvars); DeleteRlist(listvars); } } assoc = HashLookupElement(ptr->hashtable, lval); if (assoc) { if (CompareVariableValue(rval, assoc) == 0) { /* Identical value, keep as is */ } else { /* Different value, bark and replace */ if (!UnresolvedVariables(assoc, rval.rtype)) { CfOut(cf_inform, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval, ptr->scope); if (fname) { CfOut(cf_inform, "", " !! Rule from %s at/before line %d\n", fname, lineno); } else { CfOut(cf_inform, "", " !! in bundle parameterization\n"); } } DeleteRvalItem(assoc->rval); assoc->rval = CopyRvalItem(rval); assoc->dtype = dtype; CfDebug("Stored \"%s\" in context %s\n", lval, scope); } } else { if (!HashInsertElement(ptr->hashtable, lval, rval, dtype)) { FatalError("Hash table is full"); } } CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval, scope); return true; }
void DeRefListsInHashtable(char *scope, Rlist *namelist, Rlist *dereflist) // Go through scope and for each variable in name-list, replace with a // value from the deref "lol" (list of lists) clock { int len; Scope *ptr; Rlist *rp; CfAssoc *cplist; HashIterator i; CfAssoc *assoc; if ((len = RlistLen(namelist)) != RlistLen(dereflist)) { CfOut(cf_error, "", " !! Name list %d, dereflist %d\n", len, RlistLen(dereflist)); FatalError("Software Error DeRefLists... correlated lists not same length"); } if (len == 0) { return; } ptr = GetScope(scope); i = HashIteratorInit(ptr->hashtable); while ((assoc = HashIteratorNext(&i))) { for (rp = dereflist; rp != NULL; rp = rp->next) { cplist = (CfAssoc *) rp->item; if (strcmp(cplist->lval, assoc->lval) == 0) { /* Link up temp hash to variable lol */ if (rp->state_ptr == NULL || rp->state_ptr->type == CF_FNCALL) { /* Unexpanded function, or blank variable must be skipped. */ return; } if (rp->state_ptr) { CfDebug("Rewriting expanded type for %s from %s to %s\n", assoc->lval, CF_DATATYPES[assoc->dtype], (char *) rp->state_ptr->item); // must first free existing rval in scope, then allocate new (should always be string) DeleteRvalItem(assoc->rval); // avoids double free - borrowing value from lol (freed in DeleteScope()) assoc->rval.item = xstrdup(rp->state_ptr->item); } switch (assoc->dtype) { case cf_slist: assoc->dtype = cf_str; assoc->rval.rtype = CF_SCALAR; break; case cf_ilist: assoc->dtype = cf_int; assoc->rval.rtype = CF_SCALAR; break; case cf_rlist: assoc->dtype = cf_real; assoc->rval.rtype = CF_SCALAR; break; default: /* Only lists need to be converted */ break; } CfDebug(" to %s\n", CF_DATATYPES[assoc->dtype]); } } } }
void LoadSecretKeys() { FILE *fp; static char *passphrase = "Cfengine passphrase", name[CF_BUFSIZE], source[CF_BUFSIZE]; char guard[CF_MAXVARSIZE]; unsigned char digest[EVP_MAX_MD_SIZE + 1]; unsigned long err; struct stat sb; if ((fp = fopen(PrivateKeyFile(), "r")) == NULL) { CfOut(OUTPUT_LEVEL_INFORM, "fopen", "Couldn't find a private key (%s) - use cf-key to get one", PrivateKeyFile()); return; } if ((PRIVKEY = PEM_read_RSAPrivateKey(fp, (RSA **) NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err)); PRIVKEY = NULL; fclose(fp); return; } fclose(fp); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded private key %s\n", PrivateKeyFile()); if ((fp = fopen(PublicKeyFile(), "r")) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Couldn't find a public key (%s) - use cf-key to get one", PublicKeyFile()); return; } if ((PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err)); PUBKEY = NULL; fclose(fp); return; } CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded public key %s\n", PublicKeyFile()); fclose(fp); if ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e))) { FatalError("RSA Exponent too small or not odd"); } if (NULL_OR_EMPTY(POLICY_SERVER)) { snprintf(name, CF_MAXVARSIZE - 1, "%s%cpolicy_server.dat", CFWORKDIR, FILE_SEPARATOR); if ((fp = fopen(name, "r")) != NULL) { if (fscanf(fp, "%4095s", POLICY_SERVER) != 1) { CfDebug("Couldn't read string from policy_server.dat"); } fclose(fp); } } /* Check that we have our own SHA key form of the key in the IP on the hub */ char buffer[EVP_MAX_MD_SIZE * 4]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(name, CF_MAXVARSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(CF_DEFAULT_DIGEST, digest, buffer)); MapName(name); snprintf(source, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR); MapName(source); // During bootstrap we need the pre-registered IP/hash pair on the hub snprintf(guard, sizeof(guard), "%s/state/am_policy_hub", CFWORKDIR); MapName(guard); // need to use cf_stat if ((stat(name, &sb) == -1) && (stat(guard, &sb) != -1)) // copy localhost.pub to root-HASH.pub on policy server { LastSaw(POLICY_SERVER, digest, LAST_SEEN_ROLE_CONNECT); if (!LinkOrCopy(source, name, false)) { CfOut(OUTPUT_LEVEL_ERROR, "", " -> Unable to clone server's key file as %s\n", name); } } }
RSA *HavePublicKey(char *username, char *ipaddress, char *digest) { char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE]; struct stat statbuf; static char *passphrase = "public"; unsigned long err; FILE *fp; RSA *newkey = NULL; snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest); CfDebug("HavePublickey(%s)\n", keyname); snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", CFWORKDIR, keyname); MapName(newname); if (cfstat(newname, &statbuf) == -1) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Did not find new key format %s", newname); snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, username, ipaddress); MapName(oldname); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Trying old style %s", oldname); if (cfstat(oldname, &statbuf) == -1) { CfDebug("Did not have old-style key %s\n", oldname); return NULL; } if (strlen(digest) > 0) { CfOut(OUTPUT_LEVEL_INFORM, "", " -> Renaming old key from %s to %s", oldname, newname); if (rename(oldname, newname) != 0) { CfOut(OUTPUT_LEVEL_ERROR, "rename", "!! Could not rename from old key format (%s) to new (%s)", oldname, newname); } } else // we don't know the digest (e.g. because we are a client and // have no lastseen-map and/or root-SHA...pub of the server's key // yet) Just using old file format (root-IP.pub) without renaming for now. { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Could not map key file to new format - we have no digest yet (using %s)", oldname); snprintf(newname, sizeof(newname), "%s", oldname); } } if ((fp = fopen(newname, "r")) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Couldn't find a public key (%s)", newname); return NULL; } if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err)); fclose(fp); return NULL; } fclose(fp); if ((BN_num_bits(newkey->e) < 2) || (!BN_is_odd(newkey->e))) { FatalError("RSA Exponent too small or not odd"); } return newkey; }
/* * Copy data jumping over areas filled by '\0', so files automatically become sparse if possible. */ static bool CopyData(const char *source, int sd, const char *destination, int dd, char *buf, size_t buf_size) { off_t n_read_total = 0; while (true) { ssize_t n_read = read(sd, buf, buf_size); if (n_read == -1) { if (errno == EINTR) { continue; } CfOut(OUTPUT_LEVEL_ERROR, "read", "Unable to read source file while doing %s to %s", source, destination); return false; } if (n_read == 0) { /* * As the tail of file may contain of bytes '\0' (and hence * lseek(2)ed on destination instead of being written), do a * ftruncate(2) here to ensure the whole file is written to the * disc. */ if (ftruncate(dd, n_read_total) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "ftruncate", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } return true; } n_read_total += n_read; /* Copy/seek */ void *cur = buf; void *end = buf + n_read; while (cur < end) { void *skip_span = MemSpan(cur, 0, end - cur); if (skip_span > cur) { if (lseek(dd, skip_span - cur, SEEK_CUR) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "lseek", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } cur = skip_span; } void *copy_span = MemSpanInverse(cur, 0, end - cur); if (copy_span > cur) { if (FullWrite(dd, cur, copy_span - cur) < 0) { CfOut(OUTPUT_LEVEL_ERROR, "write", "Copy failed (no space?) while doing %s to %s", source, destination); return false; } cur = copy_span; } } } }
int main(int argc, char *argv[]) { Rlist *rp; Promise *pp; #if !defined(__MINGW32__) int count = 0; int status; int pid; #endif GenericAgentConfig *config = CheckOpts(argc, argv); ReportContext *report_context = OpenReports(config->agent_type); GenericAgentDiscoverContext(config, report_context); Policy *policy = GenericAgentLoadPolicy(config->agent_type, config, report_context); CheckLicenses(); ThisAgentInit(); KeepControlPromises(policy); // Set RUNATTR using copy if (BACKGROUND && INTERACTIVE) { CfOut(OUTPUT_LEVEL_ERROR, "", " !! You cannot specify background mode and interactive mode together"); exit(1); } pp = MakeDefaultRunAgentPromise(); /* HvB */ if (HOSTLIST) { rp = HOSTLIST; while (rp != NULL) { #ifdef __MINGW32__ if (BACKGROUND) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Windows does not support starting processes in the background - starting in foreground"); BACKGROUND = false; } #else if (BACKGROUND) /* parallel */ { if (count <= MAXCHILD) { if (fork() == 0) /* child process */ { HailServer(rp->item, RUNATTR, pp); exit(0); } else /* parent process */ { rp = rp->next; count++; } } else { pid = wait(&status); CfDebug("child = %d, child number = %d\n", pid, count); count--; } } else /* serial */ #endif /* __MINGW32__ */ { HailServer(rp->item, RUNATTR, pp); rp = rp->next; } } /* end while */ } /* end if HOSTLIST */ #ifndef __MINGW32__ if (BACKGROUND) { printf("Waiting for child processes to finish\n"); while (count > 1) { pid = wait(&status); CfOut(OUTPUT_LEVEL_VERBOSE, "", "Child = %d ended, number = %d\n", pid, count); count--; } } #endif PromiseDestroy(pp); GenericAgentConfigDestroy(config); ReportContextDestroy(report_context); return 0; }
void CheckOpts(int argc,char **argv) { extern char *optarg; char arg[CF_BUFSIZE],*sp; int optindex = 0; int c,alpha = false,v6 = false; /* Because of the MacOS linker we have to call this from each agent individually before Generic Initialize */ POLICY_SERVER[0] = '\0'; while ((c=getopt_long(argc,argv,"rd:vnKIf:D:N:Vs:x:MBb:",OPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'f': if (optarg == NULL) { FatalError(" -f used but no argument"); } if (optarg && strlen(optarg) < 5) { snprintf(arg,CF_MAXVARSIZE," -f used but argument \"%s\" incorrect",optarg); FatalError(arg); } strncpy(VINPUTFILE,optarg,CF_BUFSIZE-1); MINUSF = true; break; case 'b': if (optarg) { CBUNDLESEQUENCE = SplitStringAsRList(optarg,','); CBUNDLESEQUENCE_STR = optarg; } break; case 'd': NewClass("opt_debug"); switch ((optarg==NULL) ? '3' : *optarg) { case '1': D1 = true; DEBUG = true; break; case '2': D2 = true; DEBUG = true; break; default: DEBUG = true; break; } break; case 'B': BOOTSTRAP = true; MINUSF = true; IGNORELOCK = true; NewClass("bootstrap_mode"); break; case 's': // temporary assure that network functions are working OpenNetwork(); strncpy(POLICY_SERVER,Hostname2IPString(optarg),CF_BUFSIZE-1); CloseNetwork(); for (sp = POLICY_SERVER; *sp != '\0'; sp++) { if (isalpha(*sp)) { alpha = true; } if (ispunct(*sp) && *sp != ':' && *sp != '.') { alpha = true; } if (*sp == ':') { v6 = true; } } if (alpha && !v6) { FatalError("Error specifying policy server. The policy server's IP address could not be looked up. Please use the IP address instead if there is no error."); } break; case 'K': IGNORELOCK = true; break; case 'D': NewClassesFromString(optarg); break; case 'N': NegateClassesFromString(optarg,&VNEGHEAP); break; case 'I': INFORM = true; break; case 'v': VERBOSE = true; break; case 'n': DONTDO = true; IGNORELOCK = true; NewClass("opt_dry_run"); break; case 'V': PrintVersionBanner("cf-agent"); exit(0); case 'h': Syntax("cf-agent - cfengine's change agent",OPTIONS,HINTS,ID); exit(0); case 'M': ManPage("cf-agent - cfengine's change agent",OPTIONS,HINTS,ID); exit(0); case 'x': AgentDiagnostic(optarg); exit(0); case 'r': SHOWREPORTS = true; break; default: Syntax("cf-agent - cfengine's change agent",OPTIONS,HINTS,ID); exit(1); } } if (argv[optind] != NULL) { CfOut(cf_error,"","Unexpected argument with no preceding option: %s\n",argv[optind]); FatalError("Aborted"); } Debug("Set debugging\n"); }
static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_RUNAGENT); DEFINECLASSES[0] = '\0'; SENDCLASSES[0] = '\0'; while ((c = getopt_long(argc, argv, "t:q:db:vnKhIif:D:VSxo:s:MH:", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'f': GenericAgentConfigSetInputFile(config, optarg); MINUSF = true; break; case 'b': BACKGROUND = true; if (optarg) { MAXCHILD = atoi(optarg); } break; case 'd': HardClass("opt_debug"); DEBUG = true; break; case 'q': if (optarg == NULL) { strcpy(MENU, "delta"); } else { strncpy(MENU, optarg, CF_MAXVARSIZE); } break; case 'K': IGNORELOCK = true; break; case 's': strncpy(SENDCLASSES, optarg, CF_MAXVARSIZE); if (strlen(optarg) > CF_MAXVARSIZE) { FatalError("Argument too long\n"); } break; case 'D': strncpy(DEFINECLASSES, optarg, CF_MAXVARSIZE); if (strlen(optarg) > CF_MAXVARSIZE) { FatalError("Argument too long\n"); } break; case 'H': HOSTLIST = RlistFromSplitString(optarg, ','); break; case 'o': strncpy(REMOTE_AGENT_OPTIONS, optarg, CF_MAXVARSIZE); break; case 'I': INFORM = true; break; case 'i': INTERACTIVE = true; break; case 'v': VERBOSE = true; break; case 'n': DONTDO = true; IGNORELOCK = true; HardClass("opt_dry_run"); break; case 't': CONNTIMEOUT = atoi(optarg); break; case 'V': PrintVersionBanner("cf-runagent"); exit(0); case 'h': Syntax("cf-runagent - Run agent", OPTIONS, HINTS, ID); exit(0); case 'M': ManPage("cf-runagent - Run agent", OPTIONS, HINTS, ID); exit(0); case 'x': CfOut(OUTPUT_LEVEL_ERROR, "", "Self-diagnostic functionality is retired."); exit(0); default: Syntax("cf-runagent - Run agent", OPTIONS, HINTS, ID); exit(1); } } CfDebug("Set debugging\n"); return config; }
void KeepControlPromises() { struct Constraint *cp; char rettype; void *retval; struct Rlist *rp; for (cp = ControlBodyConstraints(cf_agent); cp != NULL; cp=cp->next) { if (IsExcluded(cp->classes)) { continue; } if (GetVariable("control_common",cp->lval,&retval,&rettype) != cf_notype) { /* Already handled in generic_agent */ continue; } if (GetVariable("control_agent",cp->lval,&retval,&rettype) == cf_notype) { CfOut(cf_error,"","Unknown lval %s in agent control body",cp->lval); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_maxconnections].lval) == 0) { CFA_MAXTHREADS = (int)Str2Int(retval); CfOut(cf_verbose,"","SET maxconnections = %d\n",CFA_MAXTHREADS); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_checksum_alert_time].lval) == 0) { CF_PERSISTENCE = (int)Str2Int(retval); CfOut(cf_verbose,"","SET checksum_alert_time = %d\n",CF_PERSISTENCE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_agentfacility].lval) == 0) { SetFacility(retval); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_agentaccess].lval) == 0) { ACCESSLIST = (struct Rlist *) retval; CheckAgentAccess(ACCESSLIST); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_refresh_processes].lval) == 0) { struct Rlist *rp; if (VERBOSE) { printf("%s> SET refresh_processes when starting: ",VPREFIX); for (rp = (struct Rlist *) retval; 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) { struct Rlist *rp; CfOut(cf_verbose,"","SET Abort classes from ...\n"); for (rp = (struct Rlist *) retval; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strncpy(name, rp->item, CF_MAXVARSIZE - 1); CanonifyNameInPlace(name); if (!IsItemIn(ABORTHEAP,name)) { AppendItem(&ABORTHEAP,name,cp->classes); } } continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_abortbundleclasses].lval) == 0) { struct Rlist *rp; CfOut(cf_verbose,"","SET Abort bundle classes from ...\n"); for (rp = (struct Rlist *) retval; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strncpy(name, rp->item, CF_MAXVARSIZE - 1); CanonifyNameInPlace(name); if (!IsItemIn(ABORTBUNDLEHEAP,name)) { AppendItem(&ABORTBUNDLEHEAP,name,cp->classes); } } continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_addclasses].lval) == 0) { struct Rlist *rp; CfOut(cf_verbose,"","-> Add classes ...\n"); for (rp = (struct Rlist *) retval; rp != NULL; rp = rp->next) { CfOut(cf_verbose,""," -> ... %s\n",rp->item); NewClass(rp->item); } continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_auditing].lval) == 0) { AUDIT = GetBoolean(retval); CfOut(cf_verbose,"","SET auditing = %d\n",AUDIT); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_alwaysvalidate].lval) == 0) { ALWAYS_VALIDATE = GetBoolean(retval); CfOut(cf_verbose,"","SET alwaysvalidate = %d\n",ALWAYS_VALIDATE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_secureinput].lval) == 0) { CFPARANOID = GetBoolean(retval); CfOut(cf_verbose,"","SET secure input = %d\n",CFPARANOID); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_binarypaddingchar].lval) == 0) { PADCHAR = *(char *)retval; CfOut(cf_verbose,"","SET binarypaddingchar = %c\n",PADCHAR); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_bindtointerface].lval) == 0) { strncpy(BINDINTERFACE,retval,CF_BUFSIZE-1); CfOut(cf_verbose,"","SET bindtointerface = %s\n",BINDINTERFACE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_hashupdates].lval) == 0) { CHECKSUMUPDATES = GetBoolean(retval); CfOut(cf_verbose,"","SET ChecksumUpdates %d\n",CHECKSUMUPDATES); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_exclamation].lval) == 0) { EXCLAIM = GetBoolean(retval); CfOut(cf_verbose,"","SET exclamation %d\n",EXCLAIM); 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); if (putenv(strdup(output)) == 0) { CfOut(cf_verbose,"","Setting %s\n",output); } continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_defaultcopytype].lval) == 0) { DEFAULT_COPYTYPE = (char *)retval; CfOut(cf_verbose,"","SET defaultcopytype = %c\n",DEFAULT_COPYTYPE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_fsinglecopy].lval) == 0) { SINGLE_COPY_LIST = (struct Rlist *)retval; CfOut(cf_verbose,"","SET file single copy list\n"); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_fautodefine].lval) == 0) { AUTO_DEFINE_LIST = (struct Rlist *)retval; CfOut(cf_verbose,"","SET file auto define list\n"); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_dryrun].lval) == 0) { DONTDO = GetBoolean(retval); CfOut(cf_verbose,"","SET dryrun = %c\n",DONTDO); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_inform].lval) == 0) { INFORM = GetBoolean(retval); CfOut(cf_verbose,"","SET inform = %c\n",INFORM); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_verbose].lval) == 0) { VERBOSE = GetBoolean(retval); CfOut(cf_verbose,"","SET inform = %c\n",VERBOSE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_repository].lval) == 0) { VREPOSITORY = strdup(retval); CfOut(cf_verbose,"","SET repository = %s\n",VREPOSITORY); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_skipidentify].lval) == 0) { SKIPIDENTIFY = GetBoolean(retval); CfOut(cf_verbose,"","SET skipidentify = %d\n",SKIPIDENTIFY); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_suspiciousnames].lval) == 0) { for (rp = (struct Rlist *) retval; rp != NULL; rp = rp->next) { PrependItem(&SUSPICIOUSLIST,rp->item,NULL); CfOut(cf_verbose,"", "-> Concidering %s as suspicious file", rp->item); } continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_repchar].lval) == 0) { REPOSCHAR = *(char *)retval; CfOut(cf_verbose,"","SET repchar = %c\n",REPOSCHAR); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_mountfilesystems].lval) == 0) { CF_MOUNTALL = GetBoolean(retval); CfOut(cf_verbose,"","SET mountfilesystems = %d\n",CF_MOUNTALL); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_editfilesize].lval) == 0) { EDITFILESIZE = Str2Int(retval); CfOut(cf_verbose,"","SET EDITFILESIZE = %d\n",EDITFILESIZE); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_ifelapsed].lval) == 0) { VIFELAPSED = Str2Int(retval); CfOut(cf_verbose,"","SET ifelapsed = %d\n",VIFELAPSED); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_expireafter].lval) == 0) { VEXPIREAFTER = Str2Int(retval); CfOut(cf_verbose,"","SET ifelapsed = %d\n",VEXPIREAFTER); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_timeout].lval) == 0) { CONNTIMEOUT = Str2Int(retval); CfOut(cf_verbose,"","SET timeout = %d\n",CONNTIMEOUT); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_max_children].lval) == 0) { CFA_BACKGROUND_LIMIT = Str2Int(retval); CfOut(cf_verbose,"","SET MAX_CHILDREN = %d\n",CFA_BACKGROUND_LIMIT); if (CFA_BACKGROUND_LIMIT > 10) { CfOut(cf_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) { LOGGING = GetBoolean(retval); CfOut(cf_verbose,"","SET syslog = %d\n",LOGGING); continue; } if (strcmp(cp->lval,CFA_CONTROLBODY[cfa_environment].lval) == 0) { struct Rlist *rp; CfOut(cf_verbose,"","SET environment variables from ...\n"); for (rp = (struct Rlist *) retval; rp != NULL; rp = rp->next) { if (putenv(rp->item) != 0) { CfOut(cf_error, "putenv", "Failed to set environment variable %s", rp->item); } } continue; } } if (GetVariable("control_common",CFG_CONTROLBODY[cfg_lastseenexpireafter].lval,&retval,&rettype) != cf_notype) { LASTSEENEXPIREAFTER = Str2Int(retval); } if (GetVariable("control_common",CFG_CONTROLBODY[cfg_fips_mode].lval,&retval,&rettype) != cf_notype) { FIPS_MODE = GetBoolean(retval); CfOut(cf_verbose,"","SET FIPS_MODE = %d\n",FIPS_MODE); } if (GetVariable("control_common",CFG_CONTROLBODY[cfg_syslog_port].lval,&retval,&rettype) != cf_notype) { SYSLOGPORT = (unsigned short)Str2Int(retval); CfOut(cf_verbose,"","SET syslog_port to %d",SYSLOGPORT); } if (GetVariable("control_common",CFG_CONTROLBODY[cfg_syslog_host].lval,&retval,&rettype) != cf_notype) { strncpy(SYSLOGHOST,Hostname2IPString(retval),CF_MAXVARSIZE-1); CfOut(cf_verbose,"","SET syslog_host to %s",SYSLOGHOST); } #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; } }
void KeepPromiseBundles() { struct Bundle *bp; struct Rlist *rp,*params; struct FnCall *fp; char rettype,*name; void *retval; int ok = true; if (CBUNDLESEQUENCE) { CfOut(cf_inform,""," >> Using command line specified bundlesequence"); retval = CBUNDLESEQUENCE; rettype = CF_LIST; } else if (GetVariable("control_common","bundlesequence",&retval,&rettype) == cf_notype) { CfOut(cf_error,""," !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); CfOut(cf_error,""," !! No bundlesequence in the common control body"); CfOut(cf_error,""," !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); exit(1); } if (rettype != CF_LIST) { FatalError("Promised bundlesequence was not a list"); } for (rp = (struct Rlist *)retval; rp != NULL; rp=rp->next) { switch (rp->type) { case CF_SCALAR: name = (char *)rp->item; params = NULL; if (strcmp(name,CF_NULL_VALUE) == 0) { continue; } break; case CF_FNCALL: fp = (struct FnCall *)rp->item; name = (char *)fp->name; params = (struct Rlist *)fp->args; break; default: name = NULL; params = NULL; CfOut(cf_error,"","Illegal item found in bundlesequence: "); ShowRval(stdout,rp->item,rp->type); printf(" = %c\n",rp->type); ok = false; break; } if (!IGNORE_MISSING_BUNDLES) { if (!(GetBundle(name,"agent")||(GetBundle(name,"common")))) { CfOut(cf_error,"","Bundle \"%s\" listed in the bundlesequence was not found\n",name); ok = false; } } } if (!ok) { FatalError("Errors in agent bundles"); } if (VERBOSE || DEBUG) { printf("%s> -> Bundlesequence => ",VPREFIX); ShowRval(stdout,retval,rettype); printf("\n"); } /* If all is okay, go ahead and evaluate */ for (rp = (struct Rlist *)retval; rp != NULL; rp=rp->next) { switch (rp->type) { case CF_FNCALL: fp = (struct FnCall *)rp->item; name = (char *)fp->name; params = (struct Rlist *)fp->args; break; default: name = (char *)rp->item; params = NULL; break; } if ((bp = GetBundle(name,"agent")) || (bp = GetBundle(name,"common"))) { SetBundleOutputs(bp->name); AugmentScope(bp->name,bp->args,params); BannerBundle(bp,params); THIS_BUNDLE = bp->name; DeletePrivateClassContext(); // Each time we change bundle ScheduleAgentOperations(bp); ResetBundleOutputs(bp->name); } } }
static void KeepAgentPromise(Promise *pp, const ReportContext *report_context) { char *sp = NULL; struct timespec start = BeginMeasure(); if (!IsDefinedClass(pp->classes, pp->ns)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "\n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", "Skipping whole next promise (%s), as context %s is not relevant\n", pp->promiser, pp->classes); CfOut(OUTPUT_LEVEL_VERBOSE, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); return; } if (pp->done) { return; } if (VarClassExcluded(pp, &sp)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "\n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); CfOut(OUTPUT_LEVEL_VERBOSE, "", "Skipping whole next promise (%s), as var-context %s is not relevant\n", pp->promiser, sp); CfOut(OUTPUT_LEVEL_VERBOSE, "", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . \n"); return; } if (MissingDependencies(pp)) { return; } // Record promises examined for efficiency calc if (strcmp("meta", pp->agentsubtype) == 0) { char ns[CF_BUFSIZE]; snprintf(ns,CF_BUFSIZE,"%s_meta",pp->bundle); NewScope(ns); ConvergeVarHashPromise(ns, pp, true); return; } if (strcmp("vars", pp->agentsubtype) == 0) { ConvergeVarHashPromise(pp->bundle, pp, true); return; } if (strcmp("defaults", pp->agentsubtype) == 0) { DefaultVarPromise(pp); return; } if (strcmp("classes", pp->agentsubtype) == 0) { KeepClassContextPromise(pp); return; } if (strcmp("outputs", pp->agentsubtype) == 0) { VerifyOutputsPromise(pp); return; } SetPromiseOutputs(pp); if (strcmp("interfaces", pp->agentsubtype) == 0) { VerifyInterfacesPromise(pp); return; } if (strcmp("processes", pp->agentsubtype) == 0) { VerifyProcessesPromise(pp); return; } if (strcmp("storage", pp->agentsubtype) == 0) { FindAndVerifyStoragePromises(pp, report_context); EndMeasurePromise(start, pp); return; } if (strcmp("packages", pp->agentsubtype) == 0) { VerifyPackagesPromise(pp); EndMeasurePromise(start, pp); return; } if (strcmp("files", pp->agentsubtype) == 0) { if (PromiseGetConstraintAsBoolean("background", pp)) { ParallelFindAndVerifyFilesPromises(pp, report_context); } else { FindAndVerifyFilesPromises(pp, report_context); } EndMeasurePromise(start, pp); return; } if (strcmp("commands", pp->agentsubtype) == 0) { VerifyExecPromise(pp); EndMeasurePromise(start, pp); return; } if (strcmp("databases", pp->agentsubtype) == 0) { VerifyDatabasePromises(pp); EndMeasurePromise(start, pp); return; } if (strcmp("methods", pp->agentsubtype) == 0) { VerifyMethodsPromise(pp, report_context); EndMeasurePromise(start, pp); return; } if (strcmp("services", pp->agentsubtype) == 0) { VerifyServicesPromise(pp, report_context); EndMeasurePromise(start, pp); return; } if (strcmp("guest_environments", pp->agentsubtype) == 0) { VerifyEnvironmentsPromise(pp); EndMeasurePromise(start, pp); return; } if (strcmp("reports", pp->agentsubtype) == 0) { VerifyReportPromise(pp); return; } }
int VerifyInFstab(char *name, Attributes a, Promise *pp) /* Ensure filesystem IS in fstab, and return no of changes */ { char fstab[CF_BUFSIZE]; char *host, *rmountpt, *mountpt, *fstype, *opts; if (!FSTABLIST) { if (!LoadFileAsItemList(&FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], a, pp)) { CfOut(cf_error, "", "Couldn't open %s!\n", VFSTAB[VSYSTEMHARDCLASS]); return false; } else { FSTAB_EDITS = 0; } } if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; fstype = a.mount.mount_type; switch (VSYSTEMHARDCLASS) { case osf: case bsd4_3: case irix: case irix4: case irix64: case sun3: case aos: case nextstep: case newsos: case qnx: case sun4: snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s %s\t%s 0 0", host, rmountpt, mountpt, fstype, opts); break; case crayos: snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s %s\t%s", host, rmountpt, mountpt, ToUpperStr(fstype), opts); break; case ultrx: //snprintf(fstab,CF_BUFSIZE,"%s@%s:%s:%s:0:0:%s:%s",rmountpt,host,mountpt,mode,fstype,opts); break; case hp: snprintf(fstab, CF_BUFSIZE, "%s:%s %s \t %s \t %s 0 0", host, rmountpt, mountpt, fstype, opts); break; case aix: snprintf(fstab, CF_BUFSIZE, "%s:\n\tdev\t= %s\n\ttype\t= %s\n\tvfs\t= %s\n\tnodename\t= %s\n\tmount\t= true\n\toptions\t= %s\n\taccount\t= false\n", mountpt, rmountpt, fstype, fstype, host, opts); break; case GnU: case linuxx: snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s \t %s \t %s", host, rmountpt, mountpt, fstype, opts); break; case netbsd: case openbsd: case bsd_i: case dragonfly: case freebsd: snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s \t %s \t %s 0 0", host, rmountpt, mountpt, fstype, opts); break; case unix_sv: case solaris: snprintf(fstab, CF_BUFSIZE, "%s:%s - %s %s - yes %s", host, rmountpt, mountpt, fstype, opts); break; case cfnt: snprintf(fstab, CF_BUFSIZE, "/bin/mount %s:%s %s", host, rmountpt, mountpt); break; case cfsco: CfOut(cf_error, "", "Don't understand filesystem format on SCO, no data - please fix me"); break; case unused1: case unused2: case unused3: default: free(opts); return false; } CfOut(cf_verbose, "", "Verifying %s in %s\n", mountpt, VFSTAB[VSYSTEMHARDCLASS]); if (!MatchFSInFstab(mountpt)) { AppendItem(&FSTABLIST, fstab, NULL); FSTAB_EDITS++; cfPS(cf_inform, CF_CHG, "", pp, a, "Adding file system %s:%s seems to %s.\n", host, rmountpt, VFSTAB[VSYSTEMHARDCLASS]); } free(opts); return 0; }
static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; char *sp; int optindex = 0; int c, alpha = false, v6 = false; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_AGENT); /* Because of the MacOS linker we have to call this from each agent individually before Generic Initialize */ POLICY_SERVER[0] = '\0'; while ((c = getopt_long(argc, argv, "rdvnKIf:D:N:Vs:x:MBb:h", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'f': if (optarg && strlen(optarg) < 5) { FatalError(" -f used but argument \"%s\" incorrect", optarg); } GenericAgentConfigSetInputFile(config, optarg); MINUSF = true; break; case 'b': if (optarg) { config->bundlesequence = RlistFromSplitString(optarg, ','); CBUNDLESEQUENCE_STR = optarg; } break; case 'd': HardClass("opt_debug"); DEBUG = true; break; case 'B': BOOTSTRAP = true; MINUSF = true; GenericAgentConfigSetInputFile(config, "promises.cf"); IGNORELOCK = true; HardClass("bootstrap_mode"); break; case 's': if(IsLoopbackAddress(optarg)) { FatalError("Use a non-loopback address when bootstrapping"); } // temporary assure that network functions are working OpenNetwork(); strncpy(POLICY_SERVER, Hostname2IPString(optarg), CF_BUFSIZE - 1); CloseNetwork(); for (sp = POLICY_SERVER; *sp != '\0'; sp++) { if (isalpha((int)*sp)) { alpha = true; } if (ispunct((int)*sp) && *sp != ':' && *sp != '.') { alpha = true; } if (*sp == ':') { v6 = true; } } if (alpha && !v6) { FatalError ("Error specifying policy server. The policy server's IP address could not be looked up. Please use the IP address instead if there is no error."); } break; case 'K': IGNORELOCK = true; break; case 'D': NewClassesFromString(optarg); break; case 'N': NegateClassesFromString(optarg); break; case 'I': INFORM = true; break; case 'v': VERBOSE = true; break; case 'n': DONTDO = true; IGNORELOCK = true; HardClass("opt_dry_run"); break; case 'V': PrintVersionBanner("cf-agent"); exit(0); case 'h': Syntax("cf-agent - cfengine's change agent", OPTIONS, HINTS, ID); exit(0); case 'M': ManPage("cf-agent - cfengine's change agent", OPTIONS, HINTS, ID); exit(0); case 'x': CfOut(OUTPUT_LEVEL_ERROR, "", "Self-diagnostic functionality is retired"); exit(0); case 'r': SHOWREPORTS = true; break; default: Syntax("cf-agent - cfengine's change agent", OPTIONS, HINTS, ID); exit(1); } } if (argv[optind] != NULL) { CfOut(OUTPUT_LEVEL_ERROR, "", "Unexpected argument with no preceding option: %s\n", argv[optind]); FatalError("Aborted"); } CfDebug("Set debugging\n"); return config; }
int VerifyNotInFstab(char *name, Attributes a, Promise *pp) /* Ensure filesystem is NOT in fstab, and return no of changes */ { char regex[CF_BUFSIZE], aixcomm[CF_BUFSIZE], line[CF_BUFSIZE]; char *host, *mountpt, *opts; FILE *pfp; Item *ip; if (!FSTABLIST) { if (!LoadFileAsItemList(&FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], a, pp)) { CfOut(cf_error, "", "Couldn't open %s!\n", VFSTAB[VSYSTEMHARDCLASS]); return false; } else { FSTAB_EDITS = 0; } } if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = VMOUNTOPTS[VSYSTEMHARDCLASS]; } host = a.mount.mount_server; mountpt = name; if (MatchFSInFstab(mountpt)) { if (a.mount.editfstab) { switch (VSYSTEMHARDCLASS) { case aix: snprintf(aixcomm, CF_BUFSIZE, "/usr/sbin/rmnfsmnt -f %s", mountpt); if ((pfp = cf_popen(aixcomm, "r")) == NULL) { cfPS(cf_error, CF_FAIL, "", pp, a, "Failed to invoke /usr/sbin/rmnfsmnt to edit fstab"); return 0; } while (!feof(pfp)) { CfReadLine(line, CF_BUFSIZE, pfp); if (line[0] == '#') { continue; } if (strstr(line, "busy")) { cfPS(cf_inform, CF_INTERPT, "", pp, a, "The device under %s cannot be removed from %s\n", mountpt, VFSTAB[VSYSTEMHARDCLASS]); return 0; } } cf_pclose(pfp); return 0; /* ignore internal editing for aix , always returns 0 changes */ break; default: snprintf(regex, CF_BUFSIZE, ".*[\\s]+%s[\\s]+.*", mountpt); for (ip = FSTABLIST; ip != NULL; ip = ip->next) { if (FullTextMatch(regex, ip->name)) { cfPS(cf_inform, CF_CHG, "", pp, a, "Deleting file system mounted on %s.\n", host); // Check host name matches too? DeleteThisItem(&FSTABLIST, ip); FSTAB_EDITS++; } } break; } } } if (a.mount.mount_options) { free(opts); } return 0; }
static void KeepPromiseBundles(Policy *policy, GenericAgentConfig *config, const ReportContext *report_context) { Bundle *bp; Rlist *rp, *params; FnCall *fp; char *name; Rval retval; int ok = true; if (config->bundlesequence) { CfOut(OUTPUT_LEVEL_INFORM, "", " >> Using command line specified bundlesequence"); retval = (Rval) { config->bundlesequence, RVAL_TYPE_LIST }; } else if (GetVariable("control_common", "bundlesequence", &retval) == DATA_TYPE_NONE) { // TODO: somewhat frenzied way of telling user about an error CfOut(OUTPUT_LEVEL_ERROR, "", " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); CfOut(OUTPUT_LEVEL_ERROR, "", " !! No bundlesequence in the common control body"); CfOut(OUTPUT_LEVEL_ERROR, "", " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); exit(1); } // TODO: should've been checked a long time ago, remove? if (retval.type != RVAL_TYPE_LIST) { FatalError("Promised bundlesequence was not a list"); } for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { switch (rp->type) { case RVAL_TYPE_SCALAR: name = (char *) rp->item; params = NULL; if (strcmp(name, CF_NULL_VALUE) == 0) { continue; } break; case RVAL_TYPE_FNCALL: fp = (FnCall *) rp->item; name = (char *) fp->name; params = (Rlist *) fp->args; break; default: name = NULL; params = NULL; CfOut(OUTPUT_LEVEL_ERROR, "", "Illegal item found in bundlesequence: "); RvalShow(stdout, (Rval) { rp->item, rp->type }); printf(" = %c\n", rp->type); ok = false; break; } if (!config->ignore_missing_bundles) { if (!(PolicyGetBundle(policy, NULL, "agent", name) || (PolicyGetBundle(policy, NULL, "common", name)))) { CfOut(OUTPUT_LEVEL_ERROR, "", "Bundle \"%s\" listed in the bundlesequence was not found\n", name); ok = false; } } } if (!ok) { FatalError("Errors in agent bundles"); } if (VERBOSE || DEBUG) { printf("%s> -> Bundlesequence => ", VPREFIX); RvalShow(stdout, retval); printf("\n"); } /* If all is okay, go ahead and evaluate */ for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next) { switch (rp->type) { case RVAL_TYPE_FNCALL: fp = (FnCall *) rp->item; name = (char *) fp->name; params = (Rlist *) fp->args; break; default: name = (char *) rp->item; params = NULL; break; } if ((bp = PolicyGetBundle(policy, NULL, "agent", name)) || (bp = PolicyGetBundle(policy, NULL, "common", name))) { char ns[CF_BUFSIZE]; snprintf(ns,CF_BUFSIZE,"%s_meta", name); NewScope(ns); SetBundleOutputs(bp->name); AugmentScope(bp->name, bp->ns, bp->args, params); BannerBundle(bp, params); THIS_BUNDLE = bp->name; DeletePrivateClassContext(); // Each time we change bundle ScheduleAgentOperations(bp, report_context); ResetBundleOutputs(bp->name); } } }
int LoadMountInfo(Rlist **list) /* This is, in fact, the most portable way to read the mount info! */ /* Depressing, isn't it? */ { FILE *pp; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE]; char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE], vbuff[CF_BUFSIZE]; int i, nfs = false; for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++) { buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i]; } buf1[i] = '\0'; SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(buf1, "r")) == NULL) { CfOut(cf_error, "cf_popen", "Can't open %s\n", buf1); return false; } do { vbuff[0] = buf1[0] = buf2[0] = buf3[0] = source[0] = '\0'; if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } CfReadLine(vbuff, CF_BUFSIZE, pp); if (ferror(pp)) /* abortable */ { CfOut(cf_error, "ferror", "Error getting mount info\n"); break; } if (strstr(vbuff, "nfs")) { nfs = true; } sscanf(vbuff, "%s%s%s", buf1, buf2, buf3); if (vbuff[0] == '\0' || vbuff[0] == '\n') { break; } if (strstr(vbuff, "not responding")) { CfOut(cf_error, "", "%s\n", vbuff); } if (strstr(vbuff, "be root")) { CfOut(cf_error, "", "Mount access is denied. You must be root.\n"); CfOut(cf_error, "", "Use the -n option to run safely."); } if (strstr(vbuff, "retrying") || strstr(vbuff, "denied") || strstr(vbuff, "backgrounding")) { continue; } if (strstr(vbuff, "exceeded") || strstr(vbuff, "busy")) { continue; } if (strstr(vbuff, "RPC")) { CfOut(cf_inform, "", "There was an RPC timeout. Aborting mount operations.\n"); CfOut(cf_inform, "", "Session failed while trying to talk to remote host\n"); CfOut(cf_inform, "", "%s\n", vbuff); cf_pclose(pp); return false; } switch (VSYSTEMHARDCLASS) { case darwin: case sun4: case sun3: case ultrx: case irix: case irix4: case irix64: case linuxx: case GnU: case unix_sv: case freebsd: case netbsd: case openbsd: case bsd_i: case nextstep: case bsd4_3: case newsos: case aos: case osf: case qnx: case crayos: case dragonfly: if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf3); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf3); } break; case solaris: case hp: if (IsAbsoluteFileName(buf3)) { strcpy(host, "localhost"); strcpy(mounton, buf1); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf1); } break; case aix: /* skip header */ if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf2); } else { strcpy(host, buf1); strcpy(source, buf1); strcpy(mounton, buf3); } break; case cfnt: strcpy(mounton, buf2); strcpy(host, buf1); break; case unused2: case unused3: break; case cfsco: CfOut(cf_error, "", "Don't understand SCO mount format, no data"); default: printf("cfengine software error: case %d = %s\n", VSYSTEMHARDCLASS, CLASSTEXT[VSYSTEMHARDCLASS]); FatalError("System error in GetMountInfo - no such class!"); } CfDebug("GOT: host=%s, source=%s, mounton=%s\n", host, source, mounton); if (nfs) { AugmentMountInfo(list, host, source, mounton, "nfs"); } else { AugmentMountInfo(list, host, source, mounton, NULL); } } while (!feof(pp)); alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); return true; }
static void *CfConnectPostgresqlDB(const char *host, const char *user, const char *password, const char *database) { CfOut(cf_inform, "", "There is no PostgreSQL support compiled into this version"); return NULL; }
void MountAll() { struct stat sb; char line[CF_BUFSIZE]; int fd; FILE *pp; if (DONTDO) { CfOut(cf_verbose, "", "Promised to mount filesystem, but not on this trial run\n"); return; } else { CfOut(cf_verbose, "", " -> Attempting to mount all filesystems.\n"); } if (VSYSTEMHARDCLASS == cfnt) { /* This is a shell script. Make sure it hasn't been compromised. */ if (cfstat("/etc/fstab", &sb) == -1) { if ((fd = creat("/etc/fstab", 0755)) > 0) { write(fd, "#!/bin/sh\n\n", 10); close(fd); } else { if (sb.st_mode & (S_IWOTH | S_IWGRP)) { CfOut(cf_error, "", "File /etc/fstab was insecure. Cannot mount filesystems.\n"); return; } } } } SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(VMOUNTCOMM[VSYSTEMHARDCLASS], "r")) == NULL) { CfOut(cf_error, "cf_popen", "Failed to open pipe from %s\n", VMOUNTCOMM[VSYSTEMHARDCLASS]); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { CfOut(cf_inform, "ferror", "Error mounting filesystems\n"); break; } CfReadLine(line, CF_BUFSIZE, pp); if (ferror(pp)) /* abortable */ { CfOut(cf_inform, "ferror", "Error mounting filesystems\n"); break; } if (strstr(line, "already mounted") || strstr(line, "exceeded") || strstr(line, "determined")) { continue; } if (strstr(line, "not supported")) { continue; } if (strstr(line, "denied") || strstr(line, "RPC")) { CfOut(cf_error, "", "There was a mount error, trying to mount one of the filesystems on this host.\n"); break; } if (strstr(line, "trying") && !strstr(line, "NFS version 2") && !strstr(line, "vers 3")) { CfOut(cf_error, "", "Attempting abort because mount went into a retry loop.\n"); break; } } alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); }
bool LicenseInstall(char *path_source) { CfOut(cf_error, "", "!! License installation only applies to CFEngine Enterprise"); return false; }
void KeepLiteralAccessPromise(Promise *pp, char *type) { Constraint *cp; Rlist *rp; Auth *ap, *dp; char *handle = GetConstraintValue("handle", pp, CF_SCALAR); if (handle == NULL) { CfOut(cf_error, "", "Access to literal server data requires you to define a promise handle for reference"); return; } if (!GetAuthPath(handle, VARADMIT)) { InstallServerAuthPath(handle, &VARADMIT, &VARADMITTOP); } RegisterLiteralServerData(handle, pp); if (!GetAuthPath(handle, VARDENY)) { InstallServerAuthPath(handle, &VARDENY, &VARDENYTOP); } ap = GetAuthPath(handle, VARADMIT); dp = GetAuthPath(handle, VARDENY); if (strcmp(type, "literal") == 0) { ap->literal = true; } if (strcmp(type, "context") == 0) { ap->classpattern = true; } for (cp = pp->conlist; cp != NULL; cp = cp->next) { if (!IsDefinedClass(cp->classes)) { continue; } switch (cp->rval.rtype) { case CF_SCALAR: if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_encrypted].lval) == 0) { ap->encrypt = true; } break; case CF_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_admit].lval) == 0) { PrependItem(&(ap->accesslist), rp->item, NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_deny].lval) == 0) { PrependItem(&(dp->accesslist), rp->item, NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[cfs_maproot].lval) == 0) { PrependItem(&(ap->maproot), rp->item, NULL); continue; } } break; case CF_FNCALL: /* Shouldn't happen */ break; } } }