static void DeleteAllClasses(EvalContext *ctx, const Rlist *list) { for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (CheckParseContext((char *) rp->item, CF_IDRANGE) != SYNTAX_TYPE_MATCH_OK) { return; // TODO: interesting course of action, but why is the check there in the first place? } if (EvalContextHeapContainsHard(ctx, (char *) rp->item)) { Log(LOG_LEVEL_ERR, "You cannot cancel a reserved hard class '%s' in post-condition classes", RlistScalarValue(rp)); } const char *string = (char *) (rp->item); Log(LOG_LEVEL_VERBOSE, "Cancelling class '%s'", string); EvalContextHeapPersistentRemove(string); EvalContextHeapRemoveSoft(ctx, CanonifyName(string)); EvalContextStackFrameAddNegated(ctx, CanonifyName(string)); } }
static time_t ReadPolicyValidatedFileMTime(const GenericAgentConfig *config) { char filename[CF_MAXVARSIZE]; if (MINUSF) { snprintf(filename, CF_MAXVARSIZE, "%s/state/validated_%s", CFWORKDIR, CanonifyName(config->original_input_file)); MapName(filename); } else { snprintf(filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR); MapName(filename); } struct stat sb; if (stat(filename, &sb) != -1) { return sb.st_mtime; } else { return 0; } }
void AddNetworkClass(char *netmask) { struct in_addr ip,nm; char *sp; char nmbuf[CF_MAXVARSIZE], ipbuf[CF_MAXVARSIZE]; /* * Has to differentiate between cases such as: * 192.168.101.1/24 -> 192.168.101 and * 192.168.101.1/26 -> 192.168.101.0 * We still have the, um... 'interesting' Class C default Network Class * set by GetNameInfo() */ /* This is also a convenient method to ensure valid dotted quad */ if ((nm.s_addr = inet_addr(netmask)) != -1 && (ip.s_addr = inet_addr(g_vipaddress)) != -1) { /* Will not work with IPv6 */ ip.s_addr &= nm.s_addr; strcpy(ipbuf,inet_ntoa(ip)); strcpy(nmbuf, inet_ntoa(nm)); while( (sp = strrchr(nmbuf, '.')) && strcmp(sp, ".0") == 0 ) { *sp = 0; *strrchr(ipbuf, '.') = 0; } AddClassToHeap(CanonifyName(ipbuf)); } }
void AddMultipleClasses(char *classlist) { char *sp, currentitem[CF_MAXVARSIZE],local[CF_MAXVARSIZE]; if ((classlist == NULL) || strlen(classlist) == 0) { return; } memset(local,0,CF_MAXVARSIZE); strncpy(local,classlist,CF_MAXVARSIZE-1); Debug("AddMultipleClasses(%s)\n",local); for (sp = local; *sp != '\0'; sp++) { memset(currentitem,0,CF_MAXVARSIZE); sscanf(sp,"%250[^.:,]",currentitem); sp += strlen(currentitem); if (IsHardClass(currentitem)) { FatalError("cfengine: You cannot use -D to define a reserved class!"); } AddClassToHeap(CanonifyName(currentitem)); } }
int ArchiveToRepository(const char *file, Attributes attr, Promise *pp, const ReportContext *report_context) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; struct stat sb, dsb; if (!GetRepositoryPath(file, attr, destination)) { return false; } if (attr.copy.backup == cfa_nobackup) { return true; } if (IsItemIn(VREPOSLIST, file)) { CfOut(OUTPUT_LEVEL_INFORM, "", "The file %s has already been moved to the repository once. Multiple update will cause loss of backup.", file); return true; } ThreadLock(cft_getaddr); PrependItemList(&VREPOSLIST, file); ThreadUnlock(cft_getaddr); CfDebug("Repository(%s)\n", file); JoinPath(destination, CanonifyName(file)); if (!MakeParentDirectory(destination, attr.move_obstructions, report_context)) { } if (cfstat(file, &sb) == -1) { CfDebug("File %s promised to archive to the repository but it disappeared!\n", file); return true; } cfstat(destination, &dsb); CheckForFileHoles(&sb, pp); if (pp && CopyRegularFileDisk(file, destination, pp->makeholes)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Moved %s to repository location %s\n", file, destination); return true; } else { CfOut(OUTPUT_LEVEL_INFORM, "", "Failed to move %s to repository location %s\n", file, destination); return false; } }
int ArchiveToRepository(const char *file, Attributes attr) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; struct stat sb, dsb; if (!GetRepositoryPath(file, attr, destination)) { return false; } if (attr.copy.backup == BACKUP_OPTION_NO_BACKUP) { return true; } if (IsItemIn(VREPOSLIST, file)) { Log(LOG_LEVEL_INFO, "The file '%s' has already been moved to the repository once. Multiple update will cause loss of backup.", file); return true; } ThreadLock(cft_getaddr); PrependItemList(&VREPOSLIST, file); ThreadUnlock(cft_getaddr); JoinPath(destination, CanonifyName(file)); if (!MakeParentDirectory(destination, attr.move_obstructions)) { } if (stat(file, &sb) == -1) { Log(LOG_LEVEL_DEBUG, "File '%s' promised to archive to the repository but it disappeared!", file); return true; } stat(destination, &dsb); if (CopyRegularFileDisk(file, destination)) { Log(LOG_LEVEL_INFO, "Moved '%s' to repository location '%s'", file, destination); return true; } else { Log(LOG_LEVEL_INFO, "Failed to move '%s' to repository location '%s'", file, destination); return false; } }
/* * Whatever the manuals might say, you cannot get IPV6 interface * configuration from the ioctls. This seems to be implemented in a non * standard way across OSes BSDi has done getifaddrs(), solaris 8 has a * new ioctl, Stevens book shows the suggestion which has not been * implemented... */ void GetV6InterfaceInfo(void) { FILE *pp; char buffer[CF_BUFSIZE]; Verbose("Trying to locate my IPv6 address\n"); switch (g_vsystemhardclass) { case cfnt: /* NT cannot do this */ break; default: if ((pp = cfpopen("/sbin/ifconfig -a", "r")) == NULL) { Verbose("Could not find interface info\n"); return; } while (!feof(pp)) { fgets(buffer, CF_BUFSIZE, pp); if (StrStr(buffer, "inet6")) { struct Item *ip,*list = NULL; char *sp; list = SplitStringAsItemList(buffer, ' '); for (ip = list; ip != NULL; ip=ip->next) { for (sp = ip->name; *sp != '\0'; sp++) { /* Remove CIDR mask */ if (*sp == '/') { *sp = '\0'; } } if (IsIPV6Address(ip->name) && (strcmp(ip->name, "::1") != 0)) { Verbose("Found IPv6 address %s\n", ip->name); AppendItem(&g_ipaddresses, ip->name, ""); AddClassToHeap(CanonifyName(ip->name)); } } DeleteItemList(list); } } fclose(pp); break; } }
int VM_version(void) { FILE *fp; char *sp,buffer[CF_BUFSIZE],classbuf[CF_BUFSIZE],version[CF_BUFSIZE]; struct stat statbuf; int major,minor,bug; int len = 0; int sufficient = 0; /* VMware Server ESX >= 3 has version info in /proc */ if ((fp = fopen("/proc/vmware/version","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); if (sscanf(buffer,"VMware ESX Server %d.%d.%d",&major,&minor,&bug) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d",major); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d",major,minor); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d.%d",major,minor,bug); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } else if (sscanf(buffer,"VMware ESX Server %s",version) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %s",version); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } fclose(fp); } /* Fall back to checking for other files */ if (sufficient < 1 && ((fp = fopen("/etc/vmware-release","r")) != NULL) || (fp = fopen("/etc/issue","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); AddClassToHeap(CanonifyName(buffer)); /* Strip off the release code name e.g. "(Dali)" */ if ((sp = strchr(buffer,'(')) != NULL) { *sp = 0; Chop(buffer); AddClassToHeap(CanonifyName(buffer)); } sufficient = 1; fclose(fp); } return sufficient < 1 ? 1 : 0; }
static void AddAllClasses(EvalContext *ctx, const char *ns, const Rlist *list, bool persist, ContextStatePolicy policy, ContextScope context_scope) { for (const Rlist *rp = list; rp != NULL; rp = rp->next) { char *classname = xstrdup(rp->item); CanonifyNameInPlace(classname); if (EvalContextHeapContainsHard(ctx, classname)) { Log(LOG_LEVEL_ERR, "You cannot use reserved hard class '%s' as post-condition class", classname); // TODO: ok.. but should we take any action? continue; maybe? } if (persist > 0) { if (context_scope != CONTEXT_SCOPE_NAMESPACE) { Log(LOG_LEVEL_INFO, "Automatically promoting context scope for '%s' to namespace visibility, due to persistence", classname); } Log(LOG_LEVEL_VERBOSE, "Defining persistent promise result class '%s'", classname); EvalContextHeapPersistentSave(CanonifyName(rp->item), ns, persist, policy); EvalContextHeapAddSoft(ctx, classname, ns); } else { Log(LOG_LEVEL_VERBOSE, "Defining promise result class '%s'", classname); switch (context_scope) { case CONTEXT_SCOPE_BUNDLE: EvalContextStackFrameAddSoft(ctx, classname); break; default: case CONTEXT_SCOPE_NAMESPACE: EvalContextHeapAddSoft(ctx, classname, ns); break; } } } }
/** * @brief Writes a file with a contained timestamp to mark a policy file as validated * @return True if successful. */ static bool WritePolicyValidatedFile(const GenericAgentConfig *config) { char filename[CF_MAXVARSIZE]; if (MINUSF) { snprintf(filename, CF_MAXVARSIZE, "%s/state/validated_%s", CFWORKDIR, CanonifyName(config->original_input_file)); MapName(filename); } else { snprintf(filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR); MapName(filename); } if (!MakeParentDirectory(filename, true)) { Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create directory (MakeParentDirectory: %s)", filename, GetErrorStr()); return false; } int fd = creat(filename, 0600); if (fd == -1) { Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create file (creat: %s)", filename, GetErrorStr()); return false; } FILE *fp = fdopen(fd, "w"); time_t now = time(NULL); char timebuf[26]; fprintf(fp, "%s", cf_strtimestamp_local(now, timebuf)); fclose(fp); return true; }
static void Unix_GetMacAddress(enum cfagenttype ag, int fd, struct ifreq *ifr, struct ifreq *ifp, Rlist **interfaces, Rlist **hardware) { char name[CF_MAXVARSIZE]; if (ag != cf_know) { snprintf(name, CF_MAXVARSIZE, "hardware_mac[%s]", ifp->ifr_name); } else { snprintf(name, CF_MAXVARSIZE, "hardware_mac[interface_name]"); } # ifdef SIOCGIFHWADDR char hw_mac[CF_MAXVARSIZE]; ioctl(fd, SIOCGIFHWADDR, ifr); snprintf(hw_mac, CF_MAXVARSIZE - 1, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char) ifr->ifr_hwaddr.sa_data[0], (unsigned char) ifr->ifr_hwaddr.sa_data[1], (unsigned char) ifr->ifr_hwaddr.sa_data[2], (unsigned char) ifr->ifr_hwaddr.sa_data[3], (unsigned char) ifr->ifr_hwaddr.sa_data[4], (unsigned char) ifr->ifr_hwaddr.sa_data[5]); NewScalar("sys", name, hw_mac, cf_str); AppendRlist(hardware, hw_mac, CF_SCALAR); AppendRlist(interfaces, ifp->ifr_name, CF_SCALAR); snprintf(name, CF_MAXVARSIZE, "mac_%s", CanonifyName(hw_mac)); NewClass(name); # else NewScalar("sys", name, "mac_unknown", cf_str); NewClass("mac_unknown"); # endif }
static void GetMacAddress(AgentType ag, int fd, struct ifreq *ifr, struct ifreq *ifp, Rlist **interfaces, Rlist **hardware) { char name[CF_MAXVARSIZE]; if ((ag != AGENT_TYPE_KNOW) && (ag != AGENT_TYPE_GENDOC)) { snprintf(name, CF_MAXVARSIZE, "hardware_mac[%s]", ifp->ifr_name); } else { snprintf(name, CF_MAXVARSIZE, "hardware_mac[interface_name]"); } # if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) char hw_mac[CF_MAXVARSIZE]; ioctl(fd, SIOCGIFHWADDR, ifr); snprintf(hw_mac, CF_MAXVARSIZE - 1, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char) ifr->ifr_hwaddr.sa_data[0], (unsigned char) ifr->ifr_hwaddr.sa_data[1], (unsigned char) ifr->ifr_hwaddr.sa_data[2], (unsigned char) ifr->ifr_hwaddr.sa_data[3], (unsigned char) ifr->ifr_hwaddr.sa_data[4], (unsigned char) ifr->ifr_hwaddr.sa_data[5]); NewScalar("sys", name, hw_mac, DATA_TYPE_STRING); RlistAppend(hardware, hw_mac, RVAL_TYPE_SCALAR); RlistAppend(interfaces, ifp->ifr_name, RVAL_TYPE_SCALAR); snprintf(name, CF_MAXVARSIZE, "mac_%s", CanonifyName(hw_mac)); HardClass(name); # else NewScalar("sys", name, "mac_unknown", DATA_TYPE_STRING); HardClass("mac_unknown"); # endif }
void CheckOptsAndInit(int argc,char **argv) { extern char *optarg; int optindex = 0; char ld_library_path[CF_BUFSIZE]; int c,seed; unsigned char s[16]; ld_library_path[0] = '\0'; Banner("Check options"); NOSPLAY = false; sprintf(VPREFIX, "cfexecd"); openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON); while ((c=getopt_long(argc,argv,"L:d:vhpqFV1g",CFDOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } NO_FORK = true; VERBOSE = true; printf("cfexecd Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'q': NOSPLAY = true; break; case 'p': PARSEONLY = true; break; case 'g': NO_FORK = true; break; case 'L': snprintf(ld_library_path,CF_BUFSIZE-1,"LD_LIBRARY_PATH=%s",optarg); if (putenv(strdup(ld_library_path)) != 0) { } break; case 'F': case '1': ONCE = true; NO_FORK = true; break; case 'h': Syntax(); exit(1); break; /* never reached.... */ default: Syntax(); exit(1); } } LOGGING = true; /* Do output to syslog */ /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif snprintf(VBUFF,CF_BUFSIZE,"%s/inputs/update.conf",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/bin/cfagent -D from_cfexecd",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs/spooled_reports",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/inputs",CFWORKDIR); chmod(VBUFF,0700); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs",CFWORKDIR); chmod(VBUFF,0700); strncpy(VLOCKDIR,CFWORKDIR,CF_BUFSIZE-1); strncpy(VLOGDIR,CFWORKDIR,CF_BUFSIZE-1); VCANONICALFILE = strdup(CanonifyName(VINPUTFILE)); GetCfStuff(); MAILTO[0] = '\0'; MAILFROM[0] = '\0'; VIPADDRESS[0] = '\0'; VMAILSERVER[0] = '\0'; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); RandomSeed(); RAND_bytes(s,16); s[15] = '\0'; seed = ElfHash(s); srand48((long)seed); }
void GetInterfaceInfo(void) { int fd, len, i, j; struct ifreq ifbuf[512], ifr, *ifp; struct ifconf list; struct sockaddr_in *sin; struct hostent *hp; char *sp; char ip[CF_MAXVARSIZE]; char name[CF_MAXVARSIZE]; Debug("GetInterfaceInfo()\n"); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { CfLog(cferror, "Couldn't open socket", "socket"); exit(1); } list.ifc_len = sizeof(ifbuf); list.ifc_req = ifbuf; #ifdef SIOCGIFCONF if (ioctl(fd, SIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #else if (ioctl(fd, OSIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #endif { CfLog(cferror, "Couldn't get interfaces", "ioctl"); exit(1); } for (j = 0, len = 0, ifp = list.ifc_req; len < list.ifc_len; len+=SIZEOF_IFREQ(*ifp), j++, ifp=&ifbuf[j]) { if (ifp->ifr_addr.sa_family == 0) { continue; } Verbose("Interface %d: %s\n", j+1, ifp->ifr_name); if(g_underscore_classes) { snprintf(g_vbuff, CF_BUFSIZE, "_net_iface_%s", CanonifyName(ifp->ifr_name)); } else { snprintf(g_vbuff, CF_BUFSIZE, "net_iface_%s", CanonifyName(ifp->ifr_name)); } AddClassToHeap(g_vbuff); if (ifp->ifr_addr.sa_family == AF_INET) { strncpy(ifr.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name)); if (ioctl(fd,SIOCGIFFLAGS,&ifr) == -1) { CfLog(cferror, "No such network device", "ioctl"); close(fd); return; } /* * Used to check if interface was "up" if ((ifr.ifr_flags & * IFF_UP) && !(ifr.ifr_flags & IFF_LOOPBACK)) Now check * whether it is configured ... */ if ((ifr.ifr_flags & IFF_BROADCAST) && !(ifr.ifr_flags & IFF_LOOPBACK)) { sin=(struct sockaddr_in *)&ifp->ifr_addr; snprintf(name, CF_MAXVARSIZE-1, "ipv4[%s]", CanonifyName(ifp->ifr_name)); AddMacroValue(g_contextid, name, inet_ntoa(sin->sin_addr)); if ((hp = gethostbyaddr((char *)&(sin->sin_addr.s_addr), sizeof(sin->sin_addr.s_addr), AF_INET)) == NULL) { Debug("Host information for %s not found\n", inet_ntoa(sin->sin_addr)); } else { if (hp->h_name != NULL) { Debug("Adding hostip %s..\n", inet_ntoa(sin->sin_addr)); AddClassToHeap(CanonifyName(inet_ntoa(sin->sin_addr))); Debug("Adding hostname %s..\n", hp->h_name); AddClassToHeap(CanonifyName(hp->h_name)); for (i=0; hp->h_aliases[i] != NULL; i++) { Debug("Adding alias %s..\n", hp->h_aliases[i]); AddClassToHeap(CanonifyName(hp->h_aliases[i])); } /* Old style compat */ strcpy(ip,inet_ntoa(sin->sin_addr)); AppendItem(&g_ipaddresses, ip, ""); for (sp = ip+strlen(ip)-1; *sp != '.'; sp--) { } *sp = '\0'; AddClassToHeap(CanonifyName(ip)); /* New style */ strcpy(ip, "ipv4_"); strcat(ip, inet_ntoa(sin->sin_addr)); AddClassToHeap(CanonifyName(ip)); for (sp = ip+strlen(ip)-1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; AddClassToHeap(CanonifyName(ip)); } } } } } } ifp = (struct ifreq *)((char *)ifp + SIZEOF_IFREQ(*ifp)); } close(fd); }
void GenericAgentDiscoverContext(EvalContext *ctx, GenericAgentConfig *config) { GenericAgentSetDefaultDigest(&CF_DEFAULT_DIGEST, &CF_DEFAULT_DIGEST_LEN); GenericAgentInitialize(ctx, config); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); SanitizeEnvironment(); THIS_AGENT_TYPE = config->agent_type; EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent"); DetectEnvironment(ctx); EvalContextHeapPersistentLoadAll(ctx); LoadSystemConstants(ctx); if (config->agent_type == AGENT_TYPE_AGENT && config->agent_specific.agent.bootstrap_policy_server) { if (!RemoveAllExistingPolicyInInputs(GetInputDir())) { Log(LOG_LEVEL_ERR, "Error removing existing input files prior to bootstrap"); exit(EXIT_FAILURE); } if (!WriteBuiltinFailsafePolicy(GetInputDir())) { Log(LOG_LEVEL_ERR, "Error writing builtin failsafe to inputs prior to bootstrap"); exit(EXIT_FAILURE); } bool am_policy_server = false; { const char *canonified_bootstrap_policy_server = CanonifyName(config->agent_specific.agent.bootstrap_policy_server); am_policy_server = NULL != EvalContextClassGet(ctx, NULL, canonified_bootstrap_policy_server); { char policy_server_ipv4_class[CF_BUFSIZE]; snprintf(policy_server_ipv4_class, CF_MAXVARSIZE, "ipv4_%s", canonified_bootstrap_policy_server); am_policy_server |= NULL != EvalContextClassGet(ctx, NULL, policy_server_ipv4_class); } if (am_policy_server) { Log(LOG_LEVEL_INFO, "Assuming role as policy server, with policy distribution point at %s", GetMasterDir()); EvalContextClassPutHard(ctx, "am_policy_hub", "source=bootstrap"); if (!MasterfileExists(GetMasterDir())) { Log(LOG_LEVEL_ERR, "In order to bootstrap as a policy server, the file '%s/promises.cf' must exist.", GetMasterDir()); exit(EXIT_FAILURE); } } else { Log(LOG_LEVEL_INFO, "Not assuming role as policy server"); } WriteAmPolicyHubFile(CFWORKDIR, am_policy_server); } WritePolicyServerFile(GetWorkDir(), config->agent_specific.agent.bootstrap_policy_server); SetPolicyServer(ctx, config->agent_specific.agent.bootstrap_policy_server); /* FIXME: Why it is called here? Can't we move both invocations to before if? */ UpdateLastPolicyUpdateTime(ctx); Log(LOG_LEVEL_INFO, "Bootstrapping to '%s'", POLICY_SERVER); } else { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); if (existing_policy_server) { Log(LOG_LEVEL_VERBOSE, "This agent is bootstrapped to '%s'", existing_policy_server); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); UpdateLastPolicyUpdateTime(ctx); } else { Log(LOG_LEVEL_VERBOSE, "This agent is not bootstrapped"); return; } if (GetAmPolicyHub(GetWorkDir())) { EvalContextClassPutHard(ctx, "am_policy_hub", "source=bootstrap,deprecated,alias=policy_server"); Log(LOG_LEVEL_VERBOSE, "Additional class defined: am_policy_hub"); EvalContextClassPutHard(ctx, "policy_server", "inventory,attribute_name=CFEngine roles,source=bootstrap"); Log(LOG_LEVEL_VERBOSE, "Additional class defined: policy_server"); } } }
void *LocalExec(void *scheduled_run) { FILE *pp; char line[CF_BUFSIZE],filename[CF_BUFSIZE],*sp; char cmd[CF_BUFSIZE]; int print, tid; time_t starttime = time(NULL); FILE *fp; #ifdef HAVE_PTHREAD_SIGMASK sigset_t sigmask; sigemptyset(&sigmask); pthread_sigmask(SIG_BLOCK,&sigmask,NULL); #endif #ifdef HAVE_PTHREAD tid = (int)pthread_self(); #endif Verbose("------------------------------------------------------------------\n\n"); Verbose(" LocalExec(%sscheduled) at %s\n", scheduled_run ? "" : "not ", ctime(&starttime)); Verbose("------------------------------------------------------------------\n"); /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ snprintf(cmd,CF_BUFSIZE-1,"%s/bin/cfagent%s -Dfrom_cfexecd%s", CFWORKDIR, NOSPLAY ? " -q" : "", scheduled_run ? ":scheduled_run" : ""); timestamp(starttime, line, CF_BUFSIZE); snprintf(filename,CF_BUFSIZE-1,"%s/outputs/cf_%s_%s_%u",CFWORKDIR,CanonifyName(VFQNAME),line,time(NULL)); /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ if ((fp = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open %s\n",filename); CfLog(cfinform,OUTPUT,"fopen"); return NULL; } if ((pp = cfpopen(cmd,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open pipe to command %s\n",cmd); CfLog(cfinform,OUTPUT,"cfpopen"); fclose(fp); return NULL; } while (!feof(pp) && ReadLine(line,CF_BUFSIZE,pp)) { if (ferror(pp)) { fflush(pp); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { fprintf(fp,"%s\n",line); /* If we can't send mail, log to syslog */ if (strlen(MAILTO) == 0) { strncat(line,"\n",CF_BUFSIZE-1-strlen(line)); if ((strchr(line,'\n')) == NULL) { line[CF_BUFSIZE-2] = '\n'; } CfLog(cfinform,line,""); } line[0] = '\0'; } } cfpclose(pp); Debug("Closing fp\n"); fclose(fp); MailResult(filename,MAILTO); return NULL; }
/* should return true if 'to' found */ int LinkFiles(char *from,char *to_tmp, struct Item *inclusions,struct Item *exclusions,struct Item *copy, short nofile,struct Link *ptr) { struct stat buf,savebuf; char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE]; char saved[CF_BUFSIZE],absto[CF_BUFSIZE],*lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); memset(to,0,CF_BUFSIZE); memset(&ip,0, sizeof(ip)); /* links without a directory reference */ if ((*to_tmp != '/') && (*to_tmp != '.')) { strcpy(to,"./"); } if (strlen(to_tmp)+3 > CF_BUFSIZE) { printf("%s: CF_BUFSIZE boundaries exceeded in LinkFiles(%s->%s)\n", g_vprefix,from,to_tmp); return false; } strcat(to,to_tmp); Debug2("Linkfiles(%s,%s)\n",from,to); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (IgnoredOrExcluded(links,lastnode,inclusions,exclusions)) { Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.defines = ptr->defines; ip.elsedef = ptr->elsedef; ip.backup = true; ip.exclusions = NULL; ip.inclusions = NULL; ip.symlink = NULL; ip.classes = NULL; ip.plus_flags = 0; ip.size = CF_NOSIZE; ip.linktype = 's'; ip.minus_flags = 0; ip.server = strdup("localhost"); Verbose("%s: Link item %s marked for copying instead\n", g_vprefix, from); MakeDirectoriesFor(to,'n'); CheckImage(to,from,&ip); free(ip.server); return true; } /* relative path, must still check if exists */ if (*to != '/') { Debug("Relative link destination detected: %s\n",to); strcpy(absto,AbsLinkPath(from,to)); Debug("Absolute path to relative link = %s, from %s\n",absto,from); } else { strcpy(absto,to); } if (!nofile) { if (stat(absto,&buf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } } Debug2("Trying to link %s -> %s (%s)\n",from,to,absto); if (lstat(from,&buf) == 0) { if (! S_ISLNK(buf.st_mode) && ! g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Error linking %s -> %s\n",from,to); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "Cannot make link: %s exists and is not a link! " "(uid %d)\n", from, buf.st_uid); CfLog(cfsilent,g_output,""); return(true); } if (S_ISREG(buf.st_mode) && g_enforcelinks) { snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s%s\n", from, from, CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } if (Repository(saved,g_vrepository)) { unlink(saved); } } if (S_ISDIR(buf.st_mode) && g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n", from,from,CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); strcat(saved,".dir"); if (stat(saved,&savebuf) != -1) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't save directory %s, " "since %s exists already\n", from,saved); CfLog(cferror,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "Unable to force link to " "existing directory %s\n",from); CfLog(cferror,g_output,""); return true; } if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } } } memset(linkbuf,0,CF_BUFSIZE); if (readlink(from,linkbuf,CF_BUFSIZE-1) == -1) { /* link doesn't exist */ if (! MakeDirectoriesFor(from,'n')) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't build directory tree up to %s!\n",from); CfLog(cfsilent,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "One element was a plain file, not a directory!\n"); CfLog(cfsilent,g_output,""); return(true); } } else { int off1 = 0, off2 = 0; DeleteSlash(linkbuf); /* Ignore ./ at beginning */ if (strncmp(linkbuf,"./",2) == 0) { off1 = 2; } if (strncmp(to,"./",2) == 0) { off2 = 2; } if (strcmp(linkbuf+off1,to+off2) != 0) { if (g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Removing link %s\n",from); CfLog(cfinform,g_output,""); if (!g_dontdo) { if (unlink(from) == -1) { perror("unlink"); return true; } return DoLink(from,to,ptr->defines); } } else { snprintf(g_output,CF_BUFSIZE*2, "Old link %s points somewhere else. Doing nothing!\n", from); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "(Link points to %s not %s)\n\n", linkbuf,to); CfLog(cfsilent,g_output,""); return(true); } } else { snprintf(g_output, CF_BUFSIZE*2, "Link (%s->%s) exists.\n", from, to_tmp); CfLog(cfverbose,g_output,""); if (!nofile) { /* Check whether link points somewhere */ KillOldLink(from,ptr->defines); return true; } AddMultipleClasses(ptr->elsedef); return(true); } } return DoLink(from,to,ptr->defines); }
void GetInterfacesInfo(AgentType ag) { int fd, len, i, j, first_address = false, ipdefault = false; struct ifreq ifbuf[CF_IFREQ], ifr, *ifp; struct ifconf list; struct sockaddr_in *sin; struct hostent *hp; char *sp, workbuf[CF_BUFSIZE]; char ip[CF_MAXVARSIZE]; char name[CF_MAXVARSIZE]; char last_name[CF_BUFSIZE]; Rlist *interfaces = NULL, *hardware = NULL, *ips = NULL; CfDebug("GetInterfacesInfo()\n"); // Long-running processes may call this many times DeleteItemList(IPADDRESSES); IPADDRESSES = NULL; memset(ifbuf, 0, sizeof(ifbuf)); InitIgnoreInterfaces(); last_name[0] = '\0'; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "socket", "Couldn't open socket"); exit(1); } list.ifc_len = sizeof(ifbuf); list.ifc_req = ifbuf; # ifdef SIOCGIFCONF if (ioctl(fd, SIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) # else if ((ioctl(fd, OSIOCGIFCONF, &list) == -1) || (list.ifc_len < (sizeof(struct ifreq)))) # endif { CfOut(OUTPUT_LEVEL_ERROR, "ioctl", "Couldn't get interfaces - old kernel? Try setting CF_IFREQ to 1024"); exit(1); } last_name[0] = '\0'; for (j = 0, len = 0, ifp = list.ifc_req; len < list.ifc_len; len += SIZEOF_IFREQ(*ifp), j++, ifp = (struct ifreq *) ((char *) ifp + SIZEOF_IFREQ(*ifp))) { if (ifp->ifr_addr.sa_family == 0) { continue; } if ((ifp->ifr_name == NULL) || (strlen(ifp->ifr_name) == 0)) { continue; } /* Skip virtual network interfaces for Linux, which seems to be a problem */ if (IgnoreInterface(ifp->ifr_name)) { continue; } if (strstr(ifp->ifr_name, ":")) { #ifdef __linux__ CfOut(OUTPUT_LEVEL_VERBOSE, "", "Skipping apparent virtual interface %d: %s\n", j + 1, ifp->ifr_name); continue; #endif } else { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Interface %d: %s\n", j + 1, ifp->ifr_name); } // Ignore the loopback if (strcmp(ifp->ifr_name, "lo") == 0) { continue; } if (strncmp(last_name, ifp->ifr_name, sizeof(ifp->ifr_name)) == 0) { first_address = false; } else { strncpy(last_name, ifp->ifr_name, sizeof(ifp->ifr_name)); if (!first_address) { NewScalar("sys", "interface", last_name, DATA_TYPE_STRING); first_address = true; } } snprintf(workbuf, CF_BUFSIZE, "net_iface_%s", CanonifyName(ifp->ifr_name)); HardClass(workbuf); if (ifp->ifr_addr.sa_family == AF_INET) { strncpy(ifr.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "ioctl", "No such network device"); continue; } if ((ifr.ifr_flags & IFF_UP) && (!(ifr.ifr_flags & IFF_LOOPBACK))) { sin = (struct sockaddr_in *) &ifp->ifr_addr; if (IgnoreJailInterface(j + 1, sin)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Ignoring interface %d", j + 1); continue; } CfDebug("Adding hostip %s..\n", inet_ntoa(sin->sin_addr)); HardClass(inet_ntoa(sin->sin_addr)); if ((hp = gethostbyaddr((char *) &(sin->sin_addr.s_addr), sizeof(sin->sin_addr.s_addr), AF_INET)) == NULL) { CfDebug("No hostinformation for %s found\n", inet_ntoa(sin->sin_addr)); } else { if (hp->h_name != NULL) { CfDebug("Adding hostname %s..\n", hp->h_name); HardClass(hp->h_name); if (hp->h_aliases != NULL) { for (i = 0; hp->h_aliases[i] != NULL; i++) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Adding alias %s..\n", hp->h_aliases[i]); HardClass(hp->h_aliases[i]); } } } } if (strcmp(inet_ntoa(sin->sin_addr), "0.0.0.0") == 0) { // Maybe we need to do something windows specific here? CfOut(OUTPUT_LEVEL_VERBOSE, "", " !! Cannot discover hardware IP, using DNS value"); strcpy(ip, "ipv4_"); strcat(ip, VIPADDRESS); AppendItem(&IPADDRESSES, VIPADDRESS, ""); RlistAppend(&ips, VIPADDRESS, RVAL_TYPE_SCALAR); for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; HardClass(ip); } } strcpy(ip, VIPADDRESS); i = 3; for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[%s]", i--, CanonifyName(VIPADDRESS)); NewScalar("sys", name, ip, DATA_TYPE_STRING); } } continue; } strncpy(ip, "ipv4_", CF_MAXVARSIZE); strncat(ip, inet_ntoa(sin->sin_addr), CF_MAXVARSIZE - 6); HardClass(ip); if (!ipdefault) { ipdefault = true; NewScalar("sys", "ipv4", inet_ntoa(sin->sin_addr), DATA_TYPE_STRING); strcpy(VIPADDRESS, inet_ntoa(sin->sin_addr)); } AppendItem(&IPADDRESSES, inet_ntoa(sin->sin_addr), ""); RlistAppend(&ips, inet_ntoa(sin->sin_addr), RVAL_TYPE_SCALAR); for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; HardClass(ip); } } // Set the IPv4 on interface array strcpy(ip, inet_ntoa(sin->sin_addr)); if ((ag != AGENT_TYPE_KNOW) && (ag != AGENT_TYPE_GENDOC)) { snprintf(name, CF_MAXVARSIZE - 1, "ipv4[%s]", CanonifyName(ifp->ifr_name)); } else { snprintf(name, CF_MAXVARSIZE - 1, "ipv4[interface_name]"); } NewScalar("sys", name, ip, DATA_TYPE_STRING); i = 3; for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; if ((ag != AGENT_TYPE_KNOW) && (ag != AGENT_TYPE_GENDOC)) { snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[%s]", i--, CanonifyName(ifp->ifr_name)); } else { snprintf(name, CF_MAXVARSIZE - 1, "ipv4_%d[interface_name]", i--); } NewScalar("sys", name, ip, DATA_TYPE_STRING); } } } // Set the hardware/mac address array GetMacAddress(ag, fd, &ifr, ifp, &interfaces, &hardware); } } close(fd); NewList("sys", "interfaces", interfaces, DATA_TYPE_STRING_LIST); NewList("sys", "hardware_addresses", hardware, DATA_TYPE_STRING_LIST); NewList("sys", "ip_addresses", ips, DATA_TYPE_STRING_LIST); RlistDestroy(interfaces); RlistDestroy(hardware); RlistDestroy(ips); FindV6InterfacesInfo(); }
void KeepClassContextPromise(EvalContext *ctx, Promise *pp, ARG_UNUSED const ReportContext *report_context) { Attributes a; a = GetClassContextAttributes(ctx, pp); if (!FullTextMatch("[a-zA-Z0-9_]+", pp->promiser)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "Class identifier \"%s\" contains illegal characters - canonifying", pp->promiser); snprintf(pp->promiser, strlen(pp->promiser) + 1, "%s", CanonifyName(pp->promiser)); } if (a.context.nconstraints == 0) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, "No constraints for class promise %s", pp->promiser); return; } if (a.context.nconstraints > 1) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, "Irreconcilable constraints in classes for %s", pp->promiser); return; } // If this is a common bundle ... if (strcmp(PromiseGetBundle(pp)->type, "common") == 0) { if (EvalClassExpression(ctx, a.context.expression, pp)) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> defining additional global class %s\n", pp->promiser); if (!ValidClassName(pp->promiser)) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, " !! Attempted to name a class \"%s\", which is an illegal class identifier", pp->promiser); } else { if (a.context.persistent > 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> defining explicit persistent class %s (%d mins)\n", pp->promiser, a.context.persistent); EvalContextHeapPersistentSave(pp->promiser, PromiseGetNamespace(pp), a.context.persistent, CONTEXT_STATE_POLICY_RESET); EvalContextHeapAddSoft(ctx, pp->promiser, PromiseGetNamespace(pp)); } else { CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> defining explicit global class %s\n", pp->promiser); EvalContextHeapAddSoft(ctx, pp->promiser, PromiseGetNamespace(pp)); } } } /* These are global and loaded once */ /* *(pp->donep) = true; */ return; } // If this is some other kind of bundle (else here??) if (strcmp(PromiseGetBundle(pp)->type, CF_AGENTTYPES[THIS_AGENT_TYPE]) == 0 || FullTextMatch("edit_.*", PromiseGetBundle(pp)->type)) { if (EvalClassExpression(ctx, a.context.expression, pp)) { if (!ValidClassName(pp->promiser)) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, " !! Attempted to name a class \"%s\", which is an illegal class identifier", pp->promiser); } else { if (a.context.persistent > 0) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> defining explicit persistent class %s (%d mins)\n", pp->promiser, a.context.persistent); CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> Warning: persistent classes are global in scope even in agent bundles\n"); EvalContextHeapPersistentSave(pp->promiser, PromiseGetNamespace(pp), a.context.persistent, CONTEXT_STATE_POLICY_RESET); EvalContextHeapAddSoft(ctx, pp->promiser, PromiseGetNamespace(pp)); } else { CfOut(OUTPUT_LEVEL_VERBOSE, "", " ?> defining explicit local bundle class %s\n", pp->promiser); EvalContextStackFrameAddSoft(ctx, pp->promiser); } } } // Private to bundle, can be reloaded *(pp->donep) = false; return; } }
void LocalExec(const ExecConfig *config) { FILE *pp; char line[CF_BUFSIZE], line_escaped[sizeof(line) * 2], filename[CF_BUFSIZE], *sp; char cmd[CF_BUFSIZE], esc_command[CF_BUFSIZE]; int print, count = 0; void *thread_name; time_t starttime = time(NULL); char starttime_str[64]; FILE *fp; char canonified_fq_name[CF_BUFSIZE]; thread_name = ThreadUniqueName(); cf_strtimestamp_local(starttime, starttime_str); CfOut(cf_verbose, "", "------------------------------------------------------------------\n\n"); CfOut(cf_verbose, "", " LocalExec(%sscheduled) at %s\n", config->scheduled_run ? "" : "not ", starttime_str); CfOut(cf_verbose, "", "------------------------------------------------------------------\n"); /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ if (strlen(config->exec_command) > 0) { strncpy(cmd, config->exec_command, CF_BUFSIZE - 1); if (!strstr(cmd, "-Dfrom_cfexecd")) { strcat(cmd, " -Dfrom_cfexecd"); } } else { ConstructFailsafeCommand(config->scheduled_run, cmd); } strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1); snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(cf_ctime(&starttime))); strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE); CanonifyNameInPlace(canonified_fq_name); snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name); MapName(filename); /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ if ((fp = fopen(filename, "w")) == NULL) { CfOut(cf_error, "fopen", "!! Couldn't open \"%s\" - aborting exec\n", filename); return; } #if !defined(__MINGW32__) /* * Don't inherit this file descriptor on fork/exec */ if (fileno(fp) != -1) { fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } #endif CfOut(cf_verbose, "", " -> Command => %s\n", cmd); if ((pp = cf_popen_sh(esc_command, "r")) == NULL) { CfOut(cf_error, "cf_popen", "!! Couldn't open pipe to command \"%s\"\n", cmd); fclose(fp); return; } CfOut(cf_verbose, "", " -> Command is executing...%s\n", esc_command); while (!feof(pp)) { if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE))) { char errmsg[CF_MAXVARSIZE]; snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it", config->agent_expireafter); CfOut(cf_error, "", "%s", errmsg); fprintf(fp, "%s\n", errmsg); count++; pid_t pid_agent; if(PipeToPid(&pid_agent, pp)) { ProcessSignalTerminate(pid_agent); } else { CfOut(cf_error, "", "!! Could not get PID of agent"); } break; } { ssize_t num_read = CfReadLine(line, CF_BUFSIZE, pp); if (num_read == -1) { FatalError("Cannot continue on CfReadLine error"); } else if (num_read == 0) { break; } } if(!CfReadLine(line, CF_BUFSIZE, pp)) { break; } if (ferror(pp)) { fflush(pp); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } if (print) { // we must escape print format chars (%) from output ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%"); fprintf(fp, "%s\n", line_escaped); count++; /* If we can't send mail, log to syslog */ if (strlen(config->mail_to_address) == 0) { strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped)); if ((strchr(line_escaped, '\n')) == NULL) { line_escaped[sizeof(line_escaped) - 2] = '\n'; } CfOut(cf_inform, "", "%s", line_escaped); } line[0] = '\0'; line_escaped[0] = '\0'; } } cf_pclose(pp); CfDebug("Closing fp\n"); fclose(fp); CfOut(cf_verbose, "", " -> Command is complete\n"); if (count) { CfOut(cf_verbose, "", " -> Mailing result\n"); MailResult(config, filename); } else { CfOut(cf_verbose, "", " -> No output\n"); unlink(filename); } }
static bool IsReadReady(int fd, int timeout_sec) { fd_set rset; FD_ZERO(&rset); FD_SET(fd, &rset); struct timeval tv = { .tv_sec = timeout_sec, .tv_usec = 0, }; int ret = select(fd + 1, &rset, NULL, NULL, &tv); if(ret < 0) { Log(LOG_LEVEL_ERR, "IsReadReady: Failed checking for data. (select: %s)", GetErrorStr()); return false; } if(FD_ISSET(fd, &rset)) { return true; } if(ret == 0) // timeout { return false; } // can we get here? Log(LOG_LEVEL_ERR, "IsReadReady: Unknown outcome (ret > 0 but our only fd is not set). (select: %s)", GetErrorStr()); return false; } #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic warning "-Wstrict-aliasing" #endif #endif /* __MINGW32__ */ void LocalExec(const ExecConfig *config) { time_t starttime = time(NULL); void *thread_name = ThreadUniqueName(); { char starttime_str[64]; cf_strtimestamp_local(starttime, starttime_str); if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); Log(LOG_LEVEL_VERBOSE, " LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); } else { Log(LOG_LEVEL_VERBOSE, "LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); } } /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ char cmd[CF_BUFSIZE]; if (strlen(config->exec_command) > 0) { strncpy(cmd, config->exec_command, CF_BUFSIZE - 1); if (!strstr(cmd, "-Dfrom_cfexecd")) { strcat(cmd, " -Dfrom_cfexecd"); } } else { ConstructFailsafeCommand(config->scheduled_run, cmd); } char esc_command[CF_BUFSIZE]; strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1); char line[CF_BUFSIZE]; snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(ctime(&starttime))); char filename[CF_BUFSIZE]; { char canonified_fq_name[CF_BUFSIZE]; strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE); CanonifyNameInPlace(canonified_fq_name); snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name); MapName(filename); } /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ FILE *fp = fopen(filename, "w"); if (!fp) { Log(LOG_LEVEL_ERR, "Couldn't open '%s' - aborting exec. (fopen: %s)", filename, GetErrorStr()); return; } #if !defined(__MINGW32__) /* * Don't inherit this file descriptor on fork/exec */ if (fileno(fp) != -1) { fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } #endif Log(LOG_LEVEL_VERBOSE, "Command => %s", cmd); FILE *pp = cf_popen_sh(esc_command, "r"); if (!pp) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmd, GetErrorStr()); fclose(fp); return; } Log(LOG_LEVEL_VERBOSE, "Command is executing...%s", esc_command); int count = 0; for (;;) { if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE))) { char errmsg[CF_MAXVARSIZE]; snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it", config->agent_expireafter); Log(LOG_LEVEL_ERR, "%s", errmsg); fprintf(fp, "%s\n", errmsg); count++; pid_t pid_agent; if(PipeToPid(&pid_agent, pp)) { ProcessSignalTerminate(pid_agent); } else { Log(LOG_LEVEL_ERR, "Could not get PID of agent"); } break; } ssize_t res = CfReadLine(line, CF_BUFSIZE, pp); if (res == 0) { break; } if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (cfread: %s)", cmd, GetErrorStr()); cf_pclose(pp); return; } bool print = false; for (const char *sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } if (print) { char line_escaped[sizeof(line) * 2]; // we must escape print format chars (%) from output ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%"); fprintf(fp, "%s\n", line_escaped); count++; /* If we can't send mail, log to syslog */ if (strlen(config->mail_to_address) == 0) { strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped)); if ((strchr(line_escaped, '\n')) == NULL) { line_escaped[sizeof(line_escaped) - 2] = '\n'; } Log(LOG_LEVEL_INFO, "%s", line_escaped); } line[0] = '\0'; line_escaped[0] = '\0'; } } cf_pclose(pp); Log(LOG_LEVEL_DEBUG, "Closing fp"); fclose(fp); Log(LOG_LEVEL_VERBOSE, "Command is complete"); if (count) { Log(LOG_LEVEL_VERBOSE, "Mailing result"); MailResult(config, filename); } else { Log(LOG_LEVEL_VERBOSE, "No output"); unlink(filename); } }
void GenericAgentDiscoverContext(EvalContext *ctx, GenericAgentConfig *config) { GenericAgentInitialize(ctx, config); SetReferenceTime(ctx, true); SetStartTime(); SanitizeEnvironment(); THIS_AGENT_TYPE = config->agent_type; EvalContextHeapAddHard(ctx, CF_AGENTTYPES[config->agent_type]); GenericAgentSetDefaultDigest(&CF_DEFAULT_DIGEST, &CF_DEFAULT_DIGEST_LEN); GetNameInfo3(ctx, config->agent_type); GetInterfacesInfo(ctx); Get3Environment(ctx, config->agent_type); BuiltinClasses(ctx); OSClasses(ctx); EvalContextHeapPersistentLoadAll(ctx); LoadSystemConstants(ctx); if (config->agent_type == AGENT_TYPE_AGENT && config->agent_specific.agent.bootstrap_policy_server) { if (!RemoveAllExistingPolicyInInputs(GetWorkDir())) { Log(LOG_LEVEL_ERR, "Error removing existing input files prior to bootstrap"); exit(EXIT_FAILURE); } if (!WriteBuiltinFailsafePolicy(GetWorkDir())) { Log(LOG_LEVEL_ERR, "Error writing builtin failsafe to inputs prior to bootstrap"); exit(EXIT_FAILURE); } bool am_policy_server = false; { const char *canonified_bootstrap_policy_server = CanonifyName(config->agent_specific.agent.bootstrap_policy_server); am_policy_server = IsDefinedClass(ctx, canonified_bootstrap_policy_server, NULL); { char policy_server_ipv4_class[CF_BUFSIZE]; snprintf(policy_server_ipv4_class, CF_MAXVARSIZE, "ipv4_%s", canonified_bootstrap_policy_server); am_policy_server |= IsDefinedClass(ctx, policy_server_ipv4_class, NULL); } if (am_policy_server) { Log(LOG_LEVEL_INFO, "Assuming role as policy server, with policy distribution point at %s/masterfiles", GetWorkDir()); EvalContextHeapAddHard(ctx, "am_policy_hub"); if (!MasterfileExists(GetWorkDir())) { Log(LOG_LEVEL_ERR, "In order to bootstrap as a policy server, the file '%s/masterfiles/promises.cf' must exist.", GetWorkDir()); exit(EXIT_FAILURE); } } else { Log(LOG_LEVEL_INFO, "Not assuming role as policy server"); } WriteAmPolicyHubFile(CFWORKDIR, am_policy_server); } WritePolicyServerFile(GetWorkDir(), config->agent_specific.agent.bootstrap_policy_server); SetPolicyServer(ctx, config->agent_specific.agent.bootstrap_policy_server); Log(LOG_LEVEL_INFO, "Bootstrapping to '%s'", POLICY_SERVER); } else { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); if (existing_policy_server) { Log(LOG_LEVEL_VERBOSE, "This agent is bootstrapped to '%s'", existing_policy_server); } else { Log(LOG_LEVEL_VERBOSE, "This agent is not bootstrapped"); } SetPolicyServer(ctx, existing_policy_server); if (GetAmPolicyHub(GetWorkDir())) { EvalContextHeapAddHard(ctx, "am_policy_hub"); // DEPRECATED: use policy_server instead Log(LOG_LEVEL_VERBOSE, "Additional class defined: am_policy_hub"); EvalContextHeapAddHard(ctx, "policy_server"); Log(LOG_LEVEL_VERBOSE, "Additional class defined: policy_server"); } } }
int NewPromiseProposals() { struct Rlist *rp,*sl; struct stat sb; int result = false; char filename[CF_MAXVARSIZE]; if (MINUSF) { snprintf(filename,CF_MAXVARSIZE,"%s/state/validated_%s",CFWORKDIR,CanonifyName(VINPUTFILE)); MapName(filename); } else { snprintf(filename,CF_MAXVARSIZE,"%s/masterfiles/cf_promises_validated",CFWORKDIR); MapName(filename); } if (stat(filename,&sb) != -1) { PROMISETIME = sb.st_mtime; } else { PROMISETIME = 0; } // sanity check if(PROMISETIME > time(NULL)) { CfOut(cf_inform, "", "!! Clock seems to have jumped back in time - mtime of %s is newer than current time - touching it", filename); if(utime(filename,NULL) == -1) { CfOut(cf_error, "utime", "!! Could not touch %s", filename); } PROMISETIME = 0; return true; } if (cfstat(InputLocation(VINPUTFILE),&sb) == -1) { CfOut(cf_verbose,"stat","There is no readable input file at %s",VINPUTFILE); return true; } if (sb.st_mtime > PROMISETIME) { CfOut(cf_verbose,""," -> Promises seem to change"); return true; } // Check the directories first for speed and because non-input/data files should trigger an update snprintf(filename,CF_MAXVARSIZE,"%s/inputs",CFWORKDIR); MapName(filename); if (IsNewerFileTree(filename,PROMISETIME)) { CfOut(cf_verbose,""," -> Quick search detected file changes"); return true; } // Check files in case there are any abs paths if (VINPUTLIST != NULL) { for (rp = VINPUTLIST; rp != NULL; rp=rp->next) { if (rp->type != CF_SCALAR) { CfOut(cf_error,"","Non file object %s in list\n",(char *)rp->item); } else { struct Rval returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL); switch (returnval.rtype) { case CF_SCALAR: if (cfstat(InputLocation((char *)returnval.item),&sb) == -1) { CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)returnval.item); result = true; break; } if (sb.st_mtime > PROMISETIME) { result = true; } break; case CF_LIST: for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next) { if (cfstat(InputLocation((char *)sl->item),&sb) == -1) { CfOut(cf_error,"stat","Unreadable promise proposals at %s",(char *)sl->item); result = true; break; } if (sb.st_mtime > PROMISETIME) { result = true; break; } } break; } DeleteRvalItem(returnval.item,returnval.rtype); if (result) { break; } } } } // did policy server change (used in $(sys.policy_hub))? snprintf(filename,CF_MAXVARSIZE,"%s/policy_server.dat",CFWORKDIR); MapName(filename); if ((cfstat(filename,&sb) != -1) && (sb.st_mtime > PROMISETIME)) { result = true; } return result | ALWAYS_VALIDATE; }
void MonNetworkGatherData(double *cf_this) { FILE *pp; char local[CF_BUFSIZE], remote[CF_BUFSIZE], comm[CF_BUFSIZE]; Item *in[ATTR], *out[ATTR]; char *sp; int i; enum cf_netstat_type { cfn_new, cfn_old } type = cfn_new; enum cf_packet_type { cfn_udp4, cfn_udp6, cfn_tcp4, cfn_tcp6} packet = cfn_tcp4; for (i = 0; i < ATTR; i++) { in[i] = out[i] = NULL; } DeleteItemList(ALL_INCOMING); ALL_INCOMING = NULL; sscanf(VNETSTAT[VSYSTEMHARDCLASS], "%s", comm); strcat(comm, " -an"); if ((pp = cf_popen(comm, "r", true)) == NULL) { /* FIXME: no logging */ return; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); for (;;) { memset(local, 0, CF_BUFSIZE); memset(remote, 0, CF_BUFSIZE); size_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: no logging */ cf_pclose(pp); free(vbuff); return; } else { break; } } if (strstr(vbuff, "UNIX")) { break; } if (!((strstr(vbuff, ":")) || (strstr(vbuff, ".")))) { continue; } /* Different formats here ... ugh.. pick a model */ // If this is old style, we look for chapter headings, e.g. "TCP: IPv4" if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_udp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_tcp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_udp4; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_tcp4; type = cfn_old; continue; } // Line by line state in modern/linux output if (strncmp(vbuff,"udp6",4) == 0) { packet = cfn_udp6; type = cfn_new; } else if (strncmp(vbuff,"tcp6",4) == 0) { packet = cfn_tcp6; type = cfn_new; } else if (strncmp(vbuff,"udp",3) == 0) { packet = cfn_udp4; type = cfn_new; } else if (strncmp(vbuff,"tcp",3) == 0) { packet = cfn_tcp4; type = cfn_new; } // End extract type switch (type) { case cfn_new: sscanf(vbuff, "%*s %*s %*s %s %s", local, remote); /* linux-like */ break; case cfn_old: sscanf(vbuff, "%s %s", local, remote); break; } if (strlen(local) == 0) { continue; } // Extract the port number from the end of the string for (sp = local + strlen(local); (*sp != '.') && (*sp != ':') && (sp > local); sp--) { } *sp = '\0'; // Separate address from port number sp++; char *localport = sp; if (strstr(vbuff, "LISTEN")) { // General bucket IdempPrependItem(&ALL_INCOMING, sp, NULL); // Categories the incoming ports by packet types switch (packet) { case cfn_udp4: IdempPrependItem(&MON_UDP4, sp, local); break; case cfn_udp6: IdempPrependItem(&MON_UDP6, sp, local); break; case cfn_tcp4: IdempPrependItem(&MON_TCP4, localport, local); break; case cfn_tcp6: IdempPrependItem(&MON_TCP6, localport, local); break; default: break; } } // Now look at outgoing for (sp = remote + strlen(remote) - 1; (sp >= remote) && (isdigit((int) *sp)); sp--) { } sp++; char *remoteport = sp; // Now look for the specific vital signs to count frequencies for (i = 0; i < ATTR; i++) { if (strcmp(localport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].in]++; AppendItem(&in[i], vbuff, ""); } if (strcmp(remoteport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].out]++; AppendItem(&out[i], vbuff, ""); } } } cf_pclose(pp); /* Now save the state for ShowState() the state is not smaller than the last or at least 40 minutes older. This mirrors the persistence of the maxima classes */ for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save incoming '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(in[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(in[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "in", in[i]); RawSaveItemList(in[i], vbuff); DeleteItemList(in[i]); Log(LOG_LEVEL_DEBUG, "Saved in netstat data in '%s'", vbuff); } for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save outgoing '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(out[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(out[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "out", out[i]); RawSaveItemList(out[i], vbuff); Log(LOG_LEVEL_DEBUG, "Saved out netstat data in '%s'", vbuff); DeleteItemList(out[i]); } free(vbuff); }
void CheckAutoBootstrap() { struct stat sb; char name[CF_BUFSIZE]; int repaired = false, have_policy = false, am_appliance = false; CfOut(cf_cmdout, "", "** CFEngine BOOTSTRAP probe initiated"); PrintVersionBanner("CFEngine"); printf("\n"); printf(" -> This host is: %s\n", VSYSNAME.nodename); printf(" -> Operating System Type is %s\n", VSYSNAME.sysname); printf(" -> Operating System Release is %s\n", VSYSNAME.release); printf(" -> Architecture = %s\n", VSYSNAME.machine); printf(" -> Internal soft-class is %s\n", CLASSTEXT[VSYSTEMHARDCLASS]); if (!BootstrapAllowed()) { FatalError(" !! Not enough privileges to bootstrap CFEngine"); } snprintf(name, CF_BUFSIZE - 1, "%s/inputs/failsafe.cf", CFWORKDIR); MapName(name); if (cfstat(name, &sb) == -1) { CreateFailSafe(name); repaired = true; } snprintf(name, CF_BUFSIZE - 1, "%s/inputs/promises.cf", CFWORKDIR); MapName(name); if (cfstat(name, &sb) == -1) { CfOut(cf_cmdout, "", " -> No previous policy has been cached on this host"); } else { CfOut(cf_cmdout, "", " -> An existing policy was cached on this host in %s/inputs", CFWORKDIR); have_policy = true; } if (strlen(POLICY_SERVER) > 0) { CfOut(cf_cmdout, "", " -> Assuming the policy distribution point at: %s:/var/cfengine/masterfiles\n", POLICY_SERVER); } else { if (have_policy) { CfOut(cf_cmdout, "", " -> No policy distribution host was discovered - it might be contained in the existing policy, otherwise this will function autonomously\n"); } else if (repaired) { CfOut(cf_cmdout, "", " -> No policy distribution host was defined - use --policy-server to set one\n"); } } printf(" -> Attempting to initiate promised autonomous services...\n\n"); am_appliance = IsDefinedClass(CanonifyName(POLICY_SERVER), NULL); snprintf(name, CF_MAXVARSIZE, "ipv4_%s", CanonifyName(POLICY_SERVER)); am_appliance |= IsDefinedClass(name, NULL); if (strlen(POLICY_SERVER) == 0) { am_appliance = false; } snprintf(name, sizeof(name), "%s/state/am_policy_hub", CFWORKDIR); MapName(name); if (am_appliance) { HardClass("am_policy_hub"); printf (" ** This host recognizes itself as a CFEngine Policy Hub, with policy distribution and knowledge base.\n"); printf (" -> The system is now converging. Full initialisation and self-analysis could take up to 30 minutes\n\n"); creat(name, 0600); } else { unlink(name); } }
PromiseResult VerifyClassPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); Attributes a = GetClassContextAttributes(ctx, pp); if (!StringMatchFull("[a-zA-Z0-9_]+", pp->promiser)) { Log(LOG_LEVEL_VERBOSE, "Class identifier '%s' contains illegal characters - canonifying", pp->promiser); xsnprintf(pp->promiser, strlen(pp->promiser) + 1, "%s", CanonifyName(pp->promiser)); } if (a.context.nconstraints == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "No constraints for class promise '%s'", pp->promiser); return PROMISE_RESULT_FAIL; } if (a.context.nconstraints > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Irreconcilable constraints in classes for '%s'", pp->promiser); return PROMISE_RESULT_FAIL; } if (EvalClassExpression(ctx, a.context.expression, pp)) { if (!ValidClassName(pp->promiser)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Attempted to name a class '%s', which is an illegal class identifier", pp->promiser); return PROMISE_RESULT_FAIL; } else { char *tags = NULL; { Buffer *tag_buffer = BufferNew(); BufferAppendString(tag_buffer, "classes promise,attribute_name=label,source=promise"); for (const Rlist *rp = PromiseGetConstraintAsList(ctx, "meta", pp); rp; rp = rp->next) { BufferAppendChar(tag_buffer, ','); BufferAppendString(tag_buffer, RlistScalarValue(rp)); } tags = BufferClose(tag_buffer); } if (/* Persistent classes are always global: */ a.context.persistent > 0 || /* Namespace-scope is global: */ a.context.scope == CONTEXT_SCOPE_NAMESPACE || /* If there is no explicit scope, common bundles define global * classes, other bundles define local classes: */ (a.context.scope == CONTEXT_SCOPE_NONE && 0 == strcmp(PromiseGetBundle(pp)->type, "common"))) { Log(LOG_LEVEL_VERBOSE, "C: + Global class: %s ", pp->promiser); EvalContextClassPutSoft(ctx, pp->promiser, CONTEXT_SCOPE_NAMESPACE, tags); } else { Log(LOG_LEVEL_VERBOSE, "C: + Private class: %s ", pp->promiser); EvalContextClassPutSoft(ctx, pp->promiser, CONTEXT_SCOPE_BUNDLE, tags); } if (a.context.persistent > 0) { Log(LOG_LEVEL_VERBOSE, "C: + Persistent class: '%s'. (%d minutes)", pp->promiser, a.context.persistent); EvalContextHeapPersistentSave(ctx, pp->promiser, a.context.persistent, CONTEXT_STATE_POLICY_RESET, tags); } free(tags); return PROMISE_RESULT_NOOP; } } return PROMISE_RESULT_NOOP; }
void GetNameInfo(void) { int i, found = false; char *sp, *sp2; time_t tloc; struct hostent *hp; struct sockaddr_in cin; #ifdef AIX char real_version[_SYS_NMLN]; #endif #ifdef IRIX char real_version[256]; /* see <sys/syssgi.h> */ #endif #ifdef HAVE_SYSINFO #ifdef SI_ARCHITECTURE long sz; #endif #endif Debug("GetNameInfo()\n"); g_vfqname[0] = g_vuqname[0] = '\0'; if (uname(&g_vsysname) == -1) { perror("uname "); FatalError("Uname couldn't get kernel name info!!\n"); } #ifdef AIX snprintf(real_version, _SYS_NMLN, "%.80s.%.80s", g_vsysname.version, g_vsysname.release); strncpy(g_vsysname.release, real_version, _SYS_NMLN); #elif defined IRIX /* This gets us something like `6.5.19m' rather than just `6.5'. */ syssgi (SGI_RELEASE_NAME, 256, real_version); #endif for (sp = g_vsysname.sysname; *sp != '\0'; sp++) { *sp = ToLower(*sp); } for (sp = g_vsysname.machine; *sp != '\0'; sp++) { *sp = ToLower(*sp); } for (i = 0; g_classattributes[i][0] != '\0'; i++) { if (WildMatch(g_classattributes[i][0], ToLowerStr(g_vsysname.sysname))) { if (WildMatch(g_classattributes[i][1], g_vsysname.machine)) { if (WildMatch(g_classattributes[i][2], g_vsysname.release)) { if (g_underscore_classes) { snprintf(g_vbuff, CF_BUFSIZE, "_%s", g_classtext[i]); AddClassToHeap(g_vbuff); } else { AddClassToHeap(g_classtext[i]); } found = true; g_vsystemhardclass = (enum classes) i; break; } } else { Debug2("Cfengine: I recognize %s but not %s\n", g_vsysname.sysname, g_vsysname.machine); continue; } } } if ((sp = malloc(strlen(g_vsysname.nodename)+1)) == NULL) { FatalError("malloc failure in initialize()"); } strcpy(sp, g_vsysname.nodename); SetDomainName(sp); /* Truncate fully qualified name */ for (sp2=sp; *sp2 != '\0'; sp2++) { if (*sp2 == '.') { *sp2 = '\0'; Debug("Truncating fully qualified hostname %s to %s\n", g_vsysname.nodename,sp); break; } } g_vdefaultbinserver.name = sp; AddClassToHeap(CanonifyName(sp)); if ((tloc = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n"); } if (g_verbose || g_debug || g_d2 || g_d3) { if (g_underscore_classes) { snprintf(g_vbuff, CF_BUFSIZE, "_%s", g_classtext[i]); } else { snprintf(g_vbuff, CF_BUFSIZE, "%s", g_classtext[i]); } if (g_iscfengine) { printf ("cfng: configuration agent (cfagent) - \n%s\n%s\n\n", VERSION, g_copyright); } else { printf ("cfng: configuration server (cfservd) - \n%s\n%s\n\n", VERSION, g_copyright); } printf ("------------------------------------------------------------------------\n\n"); printf ("Host name is: %s\n", g_vsysname.nodename); printf ("Operating System Type is %s\n", g_vsysname.sysname); printf ("Operating System Release is %s\n", g_vsysname.release); printf ("Architecture = %s\n\n\n", g_vsysname.machine); printf ("Using internal soft-class %s for host %s\n\n", g_vbuff, g_classtext[g_vsystemhardclass]); printf ("The time is now %s\n\n", ctime(&tloc)); printf ("------------------------------------------------------------------------\n\n"); } sprintf(g_vbuff, "%d_bit", sizeof(long)*8); AddClassToHeap(g_vbuff); Verbose("Additional hard class defined as: %s\n", CanonifyName(g_vbuff)); snprintf(g_vbuff, CF_BUFSIZE, "%s_%s", g_vsysname.sysname, g_vsysname.release); AddClassToHeap(CanonifyName(g_vbuff)); #ifdef IRIX /* * Get something like `irix64_6_5_19m' defined as well as * `irix64_6_5'. Just copying the latter into g_vsysname.release * wouldn't be backwards-compatible. */ snprintf(g_vbuff, CF_BUFSIZE, "%s_%s", g_vsysname.sysname, real_version); AddClassToHeap(CanonifyName(g_vbuff)); #endif AddClassToHeap(CanonifyName(g_vsysname.machine)); Verbose("Additional hard class defined as: %s\n",CanonifyName(g_vbuff)); snprintf(g_vbuff, CF_BUFSIZE,"%s_%s", g_vsysname.sysname, g_vsysname.machine); AddClassToHeap(CanonifyName(g_vbuff)); Verbose("Additional hard class defined as: %s\n",CanonifyName(g_vbuff)); snprintf(g_vbuff, CF_BUFSIZE, "%s_%s_%s", g_vsysname.sysname, g_vsysname.machine, g_vsysname.release); AddClassToHeap(CanonifyName(g_vbuff)); Verbose("Additional hard class defined as: %s\n", CanonifyName(g_vbuff)); #ifdef HAVE_SYSINFO #ifdef SI_ARCHITECTURE sz = sysinfo(SI_ARCHITECTURE, g_vbuff, CF_BUFSIZE); if (sz == -1) { Verbose("cfagent internal: sysinfo returned -1\n"); } else { AddClassToHeap(CanonifyName(g_vbuff)); Verbose("Additional hard class defined as: %s\n", g_vbuff); } #endif #endif snprintf(g_vbuff, CF_BUFSIZE, "%s_%s_%s_%s", g_vsysname.sysname, g_vsysname.machine, g_vsysname.release, g_vsysname.version); if (strlen(g_vbuff) < CF_MAXVARSIZE-2) { g_varch = strdup(CanonifyName(g_vbuff)); } else { Verbose("cfagent internal: $(arch) overflows CF_MAXVARSIZE! Truncating\n"); g_varch = strdup(CanonifyName(g_vsysname.sysname)); } snprintf(g_vbuff, CF_BUFSIZE, "%s_%s", g_vsysname.sysname, g_vsysname.machine); g_varch2 = strdup(CanonifyName(g_vbuff)); AddClassToHeap(g_varch); Verbose("Additional hard class defined as: %s\n", g_varch); if (! found) { CfLog(cferror,"Cfengine: I don't understand " "what architecture this is!",""); } strcpy(g_vbuff, "compiled_on_"); strcat(g_vbuff, CanonifyName(AUTOCONF_SYSNAME)); AddClassToHeap(CanonifyName(g_vbuff)); Verbose("\nGNU autoconf class from compile time: %s\n\n", g_vbuff); /* Get IP address from nameserver */ if ((hp = gethostbyname(g_vsysname.nodename)) == NULL) { return; } else { memset(&cin, 0, sizeof(cin)); cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; Verbose("Address given by nameserver: %s\n", inet_ntoa(cin.sin_addr)); strcpy(g_vipaddress, inet_ntoa(cin.sin_addr)); for (i=0; hp->h_aliases[i] != NULL; i++) { Debug("Adding alias %s..\n", hp->h_aliases[i]); AddClassToHeap(CanonifyName(hp->h_aliases[i])); } } }
/* should return true if 'to' found */ int HardLinkFiles(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { struct stat frombuf,tobuf; char saved[CF_BUFSIZE], *lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (inclusions != NULL && !IsWildItemIn(inclusions,lastnode)) { Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vexcludelink,lastnode) || IsWildItemIn(exclusions,lastnode)) { Verbose("%s: Skipping excluded pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.backup = true; ip.plus_flags = 0; ip.minus_flags = 0; ip.exclusions = NULL; ip.symlink = NULL; Verbose("%s: Link item %s marked for copying instead\n", g_vprefix, from); CheckImage(to,from,&ip); return true; } if (stat(to,&tobuf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } if (! S_ISREG(tobuf.st_mode)) { snprintf(g_output, CF_BUFSIZE*2, "%s: will only hard link regular files " "and %s is not regular\n", g_vprefix, to); CfLog(cfsilent,g_output,""); return true; } Debug2("Trying to (hard) link %s -> %s\n",from,to); if (stat(from,&frombuf) == -1) { DoHardLink(from,to,ptr->defines); return true; } /* * Both files exist, but are they the same file? POSIX says the * files could be on different devices, but unix doesn't allow this * behaviour so the tests below are theoretical... */ if (frombuf.st_ino != tobuf.st_ino && frombuf.st_dev != frombuf.st_dev) { Verbose("If this is POSIX, unable to determine if %s is " "hard link is correct\n", from); Verbose("since it points to a different filesystem!\n"); if (frombuf.st_mode == tobuf.st_mode && frombuf.st_size == tobuf.st_size) { snprintf(g_output,CF_BUFSIZE*2, "Hard link (%s->%s) on different device APPEARS okay\n", from,to); CfLog(cfverbose,g_output,""); AddMultipleClasses(ptr->elsedef); return true; } } if (frombuf.st_ino == tobuf.st_ino && frombuf.st_dev == frombuf.st_dev) { snprintf(g_output,CF_BUFSIZE*2, "Hard link (%s->%s) exists and is okay.\n",from,to); CfLog(cfverbose,g_output,""); AddMultipleClasses(ptr->elsedef); return true; } snprintf(g_output,CF_BUFSIZE*2, "%s does not appear to be a hard link to %s\n",from,to); CfLog(cfinform,g_output,""); if (g_enforcelinks) { snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s.%s\n", from, from, CF_SAVED); CfLog(cfinform,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { perror("rename"); return(true); } DoHardLink(from,to,ptr->defines); } return(true); }
void VerifyClassPromise(EvalContext *ctx, Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); Attributes a; a = GetClassContextAttributes(ctx, pp); if (!FullTextMatch("[a-zA-Z0-9_]+", pp->promiser)) { Log(LOG_LEVEL_VERBOSE, "Class identifier '%s' contains illegal characters - canonifying", pp->promiser); snprintf(pp->promiser, strlen(pp->promiser) + 1, "%s", CanonifyName(pp->promiser)); } if (a.context.nconstraints == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "No constraints for class promise '%s'", pp->promiser); return; } if (a.context.nconstraints > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Irreconcilable constraints in classes for '%s'", pp->promiser); return; } bool global_class; if (a.context.persistent > 0) /* Persistent classes are always global */ { global_class = true; } else if (a.context.scope == CONTEXT_SCOPE_NONE) { /* If there is no explicit scope, common bundles define global classes, other bundles define local classes */ if (strcmp(PromiseGetBundle(pp)->type, "common") == 0) { global_class = true; } else { global_class = false; } } else if (a.context.scope == CONTEXT_SCOPE_NAMESPACE) { global_class = true; } else if (a.context.scope == CONTEXT_SCOPE_BUNDLE) { global_class = false; } if (EvalClassExpression(ctx, a.context.expression, pp)) { if (!ValidClassName(pp->promiser)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Attempted to name a class '%s', which is an illegal class identifier", pp->promiser); } else { if (global_class) { Log(LOG_LEVEL_VERBOSE, "Adding global class '%s'", pp->promiser); EvalContextHeapAddSoft(ctx, pp->promiser, PromiseGetNamespace(pp)); } else { Log(LOG_LEVEL_VERBOSE, "Adding local bundle class '%s'", pp->promiser); EvalContextStackFrameAddSoft(ctx, pp->promiser); } if (a.context.persistent > 0) { Log(LOG_LEVEL_VERBOSE, "Adding persistent class '%s'. (%d minutes)", pp->promiser, a.context.persistent); EvalContextHeapPersistentSave(pp->promiser, PromiseGetNamespace(pp), a.context.persistent, CONTEXT_STATE_POLICY_RESET); } } } }
void IDClasses() { struct stat statbuf; char *sp; int i = 0; AddClassToHeap("any"); /* This is a reserved word / wildcard */ snprintf(VBUFF,CF_BUFSIZE,"cfengine_%s",CanonifyName(VERSION)); AddClassToHeap(VBUFF); for (sp = VBUFF+strlen(VBUFF); i < 2; sp--) { if (*sp == '_') { i++; *sp = '\0'; AddClassToHeap(VBUFF); } } #ifdef LINUX /* {Mandrake,Fedora} has a symlink at /etc/redhat-release pointing to * /etc/{mandrake,fedora}-release, so we else-if around that */ if (stat("/etc/mandrake-release",&statbuf) != -1) { Verbose("This appears to be a mandrake system.\n"); AddClassToHeap("Mandrake"); linux_mandrake_version(); } else if (stat("/etc/fedora-release",&statbuf) != -1) { Verbose("This appears to be a fedora system.\n"); AddClassToHeap("redhat"); AddClassToHeap("fedora"); linux_fedora_version(); } else if (stat("/etc/redhat-release",&statbuf) != -1) { Verbose("This appears to be a redhat system.\n"); AddClassToHeap("redhat"); linux_redhat_version(); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/SuSE-release",&statbuf) != -1) { Verbose("\nThis appears to be a SuSE system.\n"); AddClassToHeap("SuSE"); linux_suse_version(); } #define SLACKWARE_ANCIENT_VERSION_FILENAME "/etc/slackware-release" #define SLACKWARE_VERSION_FILENAME "/etc/slackware-version" if (stat(SLACKWARE_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be a slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_VERSION_FILENAME); } else if (stat(SLACKWARE_ANCIENT_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be an ancient slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_ANCIENT_VERSION_FILENAME); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/debian_version",&statbuf) != -1) { Verbose("\nThis appears to be a debian system.\n"); AddClassToHeap("debian"); debian_version(); } if (stat("/etc/UnitedLinux-release",&statbuf) != -1) { Verbose("\nThis appears to be a UnitedLinux system.\n"); AddClassToHeap("UnitedLinux"); } if (stat("/etc/gentoo-release",&statbuf) != -1) { Verbose("\nThis appears to be a gentoo system.\n"); AddClassToHeap("gentoo"); } lsb_version(); #endif if (stat("/proc/vmware/version",&statbuf) != -1 || stat("/etc/vmware-release",&statbuf) != -1) { Verbose("\nThis appears to be a VMware Server ESX system.\n"); AddClassToHeap("VMware"); VM_version(); } else if (stat("/etc/vmware",&statbuf) != -1) { if (S_ISDIR(statbuf.st_mode)) { Verbose("\nThis appears to be a VMware xSX system.\n"); AddClassToHeap("VMware"); VM_version(); } } if (stat("/proc/xen/capabilities",&statbuf) != -1) { Verbose("\nThis appears to be a xen pv system.\n"); AddClassToHeap("xen"); Xen_domain(); } #ifdef XEN_CPUID_SUPPORT else if (Xen_hv_check()) { Verbose("\nThis appears to be a xen hv system.\n"); AddClassToHeap("xen"); AddClassToHeap("xen_domu_hv"); } #endif }