void IfConf (char *vifdev,char *vaddress,char *vnetmask,char *vbroadcast) { int sk, flags, metric, isnotsane = false; Verbose("Assumed interface name: %s %s %s\n",vifdev,vnetmask,vbroadcast); if (!IsPrivileged()) { printf("%s: Only root can configure the net interface.\n",VPREFIX); return; } if (vnetmask[0] == '\0') { CfLog(cferror,"Program does not define a subnetmask",""); return; } if (vbroadcast[0] == '\0') { CfLog(cferror,"Program does not define a broadcast mode for this host",""); return; } strcpy(IFR.ifr_name,vifdev); IFR.ifr_addr.sa_family = AF_INET; if ((sk = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP)) == -1) { CfLog(cferror,"","socket"); FatalError("Error in IfConfig()"); } if (ioctl(sk,SIOCGIFFLAGS, (caddr_t) &IFR) == -1) /* Get the device status flags */ { CfLog(cferror,"No such network device","ioctl"); return; } flags = IFR.ifr_flags; strcpy(IFR.ifr_name,vifdev); /* copy this each time */ if (ioctl(sk,SIOCGIFMETRIC, (caddr_t) &IFR) == -1) /* Get the routing priority */ { CfLog(cferror,"","ioctl"); FatalError("Software error: error getting metric"); } metric = IFR.ifr_metric; isnotsane = GetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); if (! DONTDO && isnotsane) { SetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); GetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); } close(sk); }
int FileSecure (char *name) { struct stat statbuf; if (PARSEONLY || !CFPARANOID) { return true; } if (stat(name,&statbuf) == -1) { return false; } if (statbuf.st_uid != getuid()) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by uid %d (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); } /* Is the file writable by ANYONE except the owner ? */ if (statbuf.st_mode & (S_IWGRP | S_IWOTH)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s (owner %d) is writable by others (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); return false; } return true; }
void KillOldLink(char *name, char *defs) { char linkbuf[CF_BUFSIZE]; char linkpath[CF_BUFSIZE],*sp; struct stat statbuf; Debug("KillOldLink(%s)\n",name); memset(linkbuf,0,CF_BUFSIZE); memset(linkpath,0,CF_BUFSIZE); if (readlink(name,linkbuf,CF_BUFSIZE-1) == -1) { snprintf(g_output,CF_BUFSIZE*2, "(Can't read link %s while checking for deadlinks)\n",name); CfLog(cfverbose,g_output,""); return; } if (linkbuf[0] != '/') { strcpy(linkpath,name); /* Get path to link */ for (sp = linkpath+strlen(linkpath); (*sp != '/') && (sp >= linkpath); sp-- ) { *sp = '\0'; } } strcat(linkpath,linkbuf); CompressPath(g_vbuff,linkpath); /* link points nowhere */ if (stat(g_vbuff,&statbuf) == -1) { if (g_killoldlinks || g_debug || g_d2) { snprintf(g_output, CF_BUFSIZE*2, "%s is a link which points to %s, " "but that file doesn't seem to exist\n", name, g_vbuff); CfLog(cfverbose,g_output,""); } if (g_killoldlinks) { snprintf(g_output,CF_BUFSIZE*2,"Removing dead link %s\n",name); CfLog(cfinform,g_output,""); if (! g_dontdo) { /* May not work on a client-mounted system ! */ unlink(name); AddMultipleClasses(defs); } } } }
int LoadProcessTable(struct Item **procdata,char *psopts) { FILE *pp; char pscomm[CF_MAXLINKSIZE], imgbackup; snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", g_vpscomm[g_vsystemhardclass], psopts); Verbose("%s: Running process command %s\n",g_vprefix,pscomm); if ((pp = cfpopen(pscomm,"r")) == NULL) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't open the process list with command %s\n",pscomm); CfLog(cferror,g_output,"popen"); return false; } while (!feof(pp)) { memset(g_vbuff,0,CF_BUFSIZE); ReadLine(g_vbuff,CF_BUFSIZE,pp); AppendItem(procdata,g_vbuff,""); } cfpclose(pp); snprintf(g_vbuff,CF_MAXVARSIZE,"%s/state/cfng_procs",WORKDIR); imgbackup = g_imagebackup; g_imagebackup = 'n'; SaveItemList(*procdata,g_vbuff,"none"); g_imagebackup = imgbackup; return true; }
void CreateEmptyFile(char *name) { int tempfd; /* FILE *fp; if ((fp = fopen(name,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Cannot create file %s",name); CfLog(cfverbose,OUTPUT,"fopen"); return; } fclose(fp); */ if (unlink(name) == -1) { Debug("Pre-existing object %s could not be removed or was not there\n",VLOGFILE); } if ((tempfd = open(name, O_CREAT|O_EXCL|O_WRONLY,0600)) < 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open a file %s\n",VLOGFILE); CfLog(cfverbose,OUTPUT,"open"); } close(tempfd); }
void DeletePersistentClass(char *name) { int errno; DBT key,value; DB *dbp; struct CfState state; time_t now = time(NULL),expires; char filename[CF_BUFSIZE]; snprintf(filename,CF_BUFSIZE,"%s/%s",g_vlockdir,CF_STATEDB_FILE); if ((errno = db_create(&dbp,NULL,0)) != 0) { snprintf(g_output, CF_BUFSIZE, "Couldn't open average database %s\n", filename); CfLog(cferror,g_output,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = dbp->open(dbp,filename,NULL,DB_BTREE, DB_CREATE,0644)) != 0) #else if ((errno = dbp->open(dbp,NULL,filename,NULL,DB_BTREE, DB_CREATE,0644)) != 0) #endif { snprintf(g_output,CF_BUFSIZE,"Couldn't open average database %s\n",filename); CfLog(cferror,g_output,"db_open"); return; } chmod(filename,0644); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = name; key.size = strlen(name)+1; if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } Debug("Deleted persistent state %s if found\n",name); dbp->close(dbp,0); }
void DoHardLink(char *from, char *to, char *defines) { if (g_dontdo) { printf("Hardlink files %s -> %s\n\n",from,to); } else { snprintf(g_output, CF_BUFSIZE*2, "Hardlinking files %s -> %s\n", from, to); CfLog(cfinform,g_output,""); if (link(to,from) == -1) { CfLog(cferror,"","link"); } else { AddMultipleClasses(defines); } } }
void DoSignals(struct Process *pp,struct Item *list) { struct Item *ip; pid_t pid; int ret; Verbose("DoSignals(%s)\n",pp->expr); if (list == NULL) { return; } if (pp->signal == cfnosignal) { snprintf(g_output,CF_BUFSIZE,"No signal to send for %s\n",pp->expr); CfLog(cfinform,g_output,""); return; } for (ip = list; ip != NULL; ip=ip->next) { pid = (pid_t)-1; sscanf(ip->name,"%d",&pid); if (pid == (pid_t)-1) { CfLog(cferror,"Software error: Unable to decypher pid list",""); return; } if (!g_dontdo) { if ((ret = kill((pid_t)pid,pp->signal)) < 0) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't send signal to pid %d\n",pid); CfLog(cfverbose,g_output,"kill"); return; } if ((pp->signal == cfkill || pp->signal == cfterm) && ret >= 0) { snprintf(g_output,CF_BUFSIZE*2,"Killed: %s\n",ip->name); CfLog(cfinform,g_output,""); } } } }
int AbsoluteLink(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; Debug2("AbsoluteLink(%s,%s)\n",from,to); if (*to == '.') { strcpy(g_linkto,from); ChopLastNode(g_linkto); AddSlash(g_linkto); strcat(g_linkto,to); } else { strcpy(g_linkto,to); } CompressPath(absto,g_linkto); expand[0] = '\0'; if (!nofile) { /* begin at level 1 and beam out at 15 */ if (!ExpandLinks(expand,absto,0)) { CfLog(cferror,"Failed to make absolute link in\n",""); snprintf(g_output,CF_BUFSIZE*2,"%s -> %s\n",from,to); CfLog(cferror,g_output,""); return false; } else { Debug2("ExpandLinks returned %s\n",expand); } } else { strcpy(expand,absto); } CompressPath(g_linkto,expand); return LinkFiles(from,g_linkto,inclusions,exclusions,copy,nofile,ptr); }
int DoLink(char *from, char *to, char *defines) { if (g_dontdo) { printf("cfagent: Need to link files %s -> %s\n",from,to); } else { snprintf(g_output,CF_BUFSIZE*2,"Linking files %s -> %s\n",from,to); CfLog(cfinform,g_output,""); if (symlink(to,from) == -1) { snprintf(g_output,CF_BUFSIZE*2,"Couldn't link %s to %s\n",to,from); CfLog(cferror,g_output,"symlink"); return false; } else { AddMultipleClasses(defines); return true; } } return true; }
void CheckLinkSecurity(struct stat *sb,char *name) { struct stat security; Debug("Checking the inode and device to make sure we are where we think we are...\n"); if (stat(".",&security) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not stat directory %s after entering!",name); CfLog(cferror,OUTPUT,"stat"); return; } if ((sb->st_dev != security.st_dev) || (sb->st_ino != security.st_ino)) { snprintf(OUTPUT,CF_BUFSIZE,"SERIOUS SECURITY ALERT: path race exploited in recursion to/from %s. Not safe for agent to continue - aborting",name); CfLog(cferror,OUTPUT,""); HandleSignal(SIGTERM); /* Exits */ } }
void CheckClass(char *name,char *source) { char *sp; for (sp = name; *sp != '\0'; sp++) { if (!isalnum((int)*sp) && (*sp != '_')) { snprintf(OUTPUT,CF_BUFSIZE,"Module class contained an illegal character (%c). Only alphanumeric or underscores in classes.",*sp); CfLog(cferror,OUTPUT,""); } } }
int ExpandOverflow(char *str1,char *str2) /* Should be an inline ! */ { int len = strlen(str2); if ((strlen(str1)+len) > (CF_EXPANDSIZE - CF_BUFFERMARGIN)) { snprintf(OUTPUT,CF_BUFSIZE,"Expansion overflow constructing string. Increase CF_EXPANDSIZE macro.\n"); CfLog(cferror,OUTPUT,""); printf("%s: Tried to add %s to %s\n",VPREFIX,str2,str1); return true; } return false; }
short CfenginePort(void) { struct servent *server; if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL) { CfLog(cflogonly, "Couldn't get cfengine service, " "using default","getservbyname"); return htons(5308); } return server->s_port; }
char * Hostname2IPString(char *hostname) { static char ipbuffer[65]; int err; #if defined(HAVE_GETADDRINFO) && !defined(DARWIN) struct addrinfo query, *response, *ap; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; memset(ipbuffer,0,63); if ((err = getaddrinfo(hostname,NULL,&query,&response)) != 0) { snprintf(g_output,CF_BUFSIZE, "Unable to lookup hostname (%s) or cfengine service: %s", hostname,gai_strerror(err)); CfLog(cferror,g_output,""); return hostname; } for (ap = response; ap != NULL; ap = ap->ai_next) { strncpy(ipbuffer,sockaddr_ntop(ap->ai_addr),64); Debug("Found address (%s) for host %s\n",ipbuffer,hostname); freeaddrinfo(response); return ipbuffer; } #else struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); memset(ipbuffer,0,63); if ((hp = gethostbyname(hostname)) != NULL) { cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; strncpy(ipbuffer,inet_ntoa(cin.sin_addr),63); Verbose("Found address (%s) for host %s\n",ipbuffer,hostname); return ipbuffer; } #endif snprintf(ipbuffer,63,"Unknown IP %s",hostname); return ipbuffer; }
void DirPop(int goback,char * name,struct stat *sb) /* Exit dir and check for race exploits */ { if (goback && TRAVLINKS) { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } CheckLinkSecurity(sb,name); } else if (goback) { if (chdir("..") == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } } }
void CheckRemoteVersion() { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; int tosend; Debug("CheckRemoteVersion\n"); snprintf(sendbuffer,CF_BUFSIZE,"VERSION"); tosend = strlen(sendbuffer); if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Transmission failed while checking version"); CfLog(cfinform,OUTPUT,"send"); return; } if (ReceiveTransaction(CONN->sd,recvbuffer,NULL) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Reply failed while checking version"); CfLog(cfinform,OUTPUT,"send"); CONN->protoversion = 0; return; } if (BadProtoReply(recvbuffer)) { CONN->protoversion = 0; return; } else { CONN->protoversion = 1; return; } }
void CfenginePort() { struct servent *server; if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL) { CfLog(cflogonly,"Couldn't get cfengine service, using default","getservbyname"); SHORT_CFENGINEPORT = htons((unsigned short)5308); } else { SHORT_CFENGINEPORT = server->s_port; } Debug("Setting cfengine new port to %u\n",ntohs(SHORT_CFENGINEPORT)); }
int DirPush(char *name,struct stat *sb) /* Enter dir and check for race exploits */ { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not change to directory %s, mode %o in tidy",name,sb->st_mode & 07777); CfLog(cfinform,OUTPUT,"chdir"); return false; } else { Debug("Changed directory to %s\n",name); } CheckLinkSecurity(sb,name); return true; }
void AppendTwoDimItem(struct TwoDimList **liststart,struct Item *itemlist) { struct TwoDimList *ip, *lp; Debug("\nAppendTwoDimItem()\n"); if (liststart == NULL) { Debug("SOFTWARE ERROR in AppendTwoDimItem()\n "); return; } if ((ip = (struct TwoDimList *)malloc(sizeof(struct TwoDimList))) == NULL) { CfLog(cferror,"AppendTwoDimItem","malloc"); FatalError(""); } if (*liststart == NULL) { *liststart = ip; } else { for (lp = *liststart; lp->next != NULL; lp=lp->next) { } lp->next = ip; } ip->ilist = itemlist; ip->current = itemlist; /* init to start of list - steps through these */ ip->next = NULL; ip->rounds = 0; ip->tied = 0; if (itemlist == NULL || itemlist->next == NULL) { ip->is2d = false; } else { ip->is2d = true; /* List has more than one element */ } }
/* String form (char *ipaddress) */ char * IPString2Hostname(char *ipaddress) { static char hostbuffer[128]; int err; #if defined(HAVE_GETADDRINFO) && !defined(DARWIN) struct addrinfo query, *response, *ap; memset(&query,0,sizeof(query)); memset(&response,0,sizeof(response)); query.ai_flags = AI_CANONNAME; memset(hostbuffer,0,128); if ((err = getaddrinfo(ipaddress,NULL,&query,&response)) != 0) { snprintf(g_output,CF_BUFSIZE,"Unable to lookup IP address (%s): %s", ipaddress,gai_strerror(err)); CfLog(cferror,g_output,""); snprintf(hostbuffer,127,"(Non registered IP)"); return hostbuffer; } for (ap = response; ap != NULL; ap = ap->ai_next) { if ((err = getnameinfo(ap->ai_addr,ap->ai_addrlen, hostbuffer,127,0,0,0)) != 0) { snprintf(hostbuffer,127,"(Non registered IP)"); freeaddrinfo(response); return hostbuffer; } Debug("Found address (%s) for host %s\n",hostbuffer,ipaddress); freeaddrinfo(response); return hostbuffer; } snprintf(hostbuffer,127,"(Non registered IP)"); #else snprintf(hostbuffer,127,"(Not for old BIND)"); #endif return hostbuffer; }
void Chop(char *str) /* remove trailing spaces */ { int i; if ((str == NULL) || (strlen(str) == 0)) { return; } if (strlen(str) > CF_BUFSIZE) { CfLog(cferror,"Chop was called on a string that seemed to have no terminator",""); return; } for (i = strlen(str)-1; isspace((int)str[i]); i--) { str[i] = '\0'; } }
void TruncateFile(char *name) { struct stat statbuf; int fd; if (stat(name,&statbuf) == -1) { Debug2("cfengine: didn't find %s to truncate\n",name); return; } else { if ((fd = creat(name,000)) == -1) /* dummy mode ignored */ { snprintf(OUTPUT,CF_BUFSIZE*2,"creat(%s) failed\n",name); CfLog(cferror,OUTPUT,"creat"); } else { close(fd); } } }
void Build2DListFromVarstring(struct TwoDimList **TwoDimlist, char *varstring, char sep, short tied) { struct Item *ip, *basis; char *sp; Debug1("Build2DListFromVarstring([%s],sep=[%c])\n",varstring,sep); if (varstring == NULL) { AppendTwoDimItem(TwoDimlist,NULL); return; } if (sp = strchr(varstring,sep)) { if (sp == varstring || (sp > varstring && *(sp-1) != '\\')) { snprintf(OUTPUT,CF_BUFSIZE,"Warning: varstring \"%s\" contains the list iterator \'%c\' - you should escape these close to non-separator characters so they don't get lost! (e.g. /bin/echo\\%c )",varstring,sep,sep); CfLog(cferror,OUTPUT,""); } } basis = SplitVarstring(varstring); for (ip = basis; ip != NULL; ip=ip->next) { /* Expand the list variables in each slot */ AppendTwoDimItem(TwoDimlist,SplitString(ip->name,sep)); } if (TwoDimlist && *TwoDimlist) { /* Policy for expansion of lists */ (*TwoDimlist)->tied = tied; } }
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])); } } }
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 SetClassesOnScript(char *execstr,char *classes,char *elseclasses,int useshell) { FILE *pp; int print; char line[CF_BUFSIZE],*sp; switch (useshell) { case 'y': pp = cfpopen_sh(execstr,"r"); break; default: pp = cfpopen(execstr,"r"); break; } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } /* * Dumb script - echo non-empty lines to standard output. */ print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { Verbose("%s:%s: %s\n",VPREFIX,execstr,line); } } cfpclose_def(pp,classes,elseclasses); }
int ShellCommandReturnsZero(char *comm,int useshell) { int status, i, argc = 0; pid_t pid; char arg[CF_MAXSHELLARGS][CF_BUFSIZE]; char **argv; if (!useshell) { /* Build argument array */ for (i = 0; i < CF_MAXSHELLARGS; i++) { memset (arg[i],0,CF_BUFSIZE); } argc = SplitCommand(comm,arg); if (argc == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Too many arguments in %s\n",comm); CfLog(cferror,OUTPUT,""); return false; } } if ((pid = fork()) < 0) { FatalError("Failed to fork new process"); } else if (pid == 0) /* child */ { ALARM_PID = -1; if (useshell) { if (execl("/bin/sh","sh","-c",comm,NULL) == -1) { yyerror("script failed"); perror("execl"); exit(1); } } else { argv = (char **) malloc((argc+1)*sizeof(char *)); if (argv == NULL) { FatalError("Out of memory"); } for (i = 0; i < argc; i++) { argv[i] = arg[i]; } argv[i] = (char *) NULL; if (execv(arg[0],argv) == -1) { yyerror("script failed"); perror("execvp"); exit(1); } free((char *)argv); } } else /* parent */ { pid_t wait_result; while ((wait_result = wait(&status)) != pid) { if (wait_result <= 0) { snprintf(OUTPUT,CF_BUFSIZE,"Wait for child failed\n"); CfLog(cfinform,OUTPUT,"wait"); return false; } } if (WIFSIGNALED(status)) { Debug("Script %s returned: %d\n",comm,WTERMSIG(status)); return false; } if (! WIFEXITED(status)) { return false; } if (WEXITSTATUS(status) == 0) { Debug("Shell command returned 0\n"); return true; } else { Debug("Shell command was non-zero: %d\n",WEXITSTATUS(status)); return false; } } return false; }
int DoRecursiveEditFiles(char *name,int level,struct Edit *ptr,struct stat *sb) { DIR *dirh; struct dirent *dirp; char pcwd[CF_BUFSIZE]; struct stat statbuf; int goback; if (level == -1) { return false; } Debug("RecursiveEditFiles(%s)\n",name); if (!DirPush(name,sb)) { return false; } if ((dirh = opendir(".")) == NULL) { return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,ptr->ignores)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { return true; } strcat(pcwd,dirp->d_name); if (!FileObjectFilter(pcwd,&statbuf,ptr->filters,editfiles)) { Verbose("Skipping filtered file %s\n",pcwd); continue; } if (TRAVLINKS) { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); continue; } if (stat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working on %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } } else { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working in %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"lstat"); continue; } } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,level)) { continue; } else { if ((ptr->recurse > 1) || (ptr->recurse == CF_INF_RECURSE)) { goback = DoRecursiveEditFiles(pcwd,level-1,ptr,&statbuf); DirPop(goback,name,sb); } else { WrapDoEditFile(ptr,pcwd); } } } else { WrapDoEditFile(ptr,pcwd); } } closedir(dirh); return true; }
void DoEditHomeFiles(struct Edit *ptr) { DIR *dirh, *dirh2; struct dirent *dirp, *dirp2; char *sp,homedir[CF_BUFSIZE],dest[CF_BUFSIZE]; struct passwd *pw; struct stat statbuf; struct Item *ip; uid_t uid; if (!MountPathDefined()) { CfLog(cfinform,"Mountpattern is undefined\n",""); return; } for (ip = VMOUNTLIST; ip != NULL; ip=ip->next) { if (IsExcluded(ip->classes)) { continue; } if ((dirh = opendir(ip->name)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",ip->name); CfLog(cferror,OUTPUT,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,ip->name,NULL)) { continue; } strcpy(homedir,ip->name); AddSlash(homedir); strcat(homedir,dirp->d_name); if (! IsHomeDir(homedir)) { continue; } if ((dirh2 = opendir(homedir)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory%s\n",homedir); CfLog(cferror,OUTPUT,"opendir"); return; } for (dirp2 = readdir(dirh2); dirp2 != NULL; dirp2 = readdir(dirh2)) { if (!SensibleFile(dirp2->d_name,homedir,NULL)) { continue; } strcpy(dest,homedir); AddSlash(dest); strcat(dest,dirp2->d_name); AddSlash(dest); sp = ptr->fname + strlen("home/"); strcat(dest,sp); if (stat(dest,&statbuf)) { EditVerbose("File %s doesn't exist for editing, skipping\n",dest); continue; } if ((pw = getpwnam(dirp2->d_name)) == NULL) { Debug2("cfengine: directory corresponds to no user %s - ignoring\n",dirp2->d_name); continue; } else { Debug2("(Setting user id to %s)\n",dirp2->d_name); } uid = statbuf.st_uid; WrapDoEditFile(ptr,dest); chown(dest,uid,CF_SAME_OWNER); } closedir(dirh2); } closedir(dirh); } }