2
Copyright (C) Cfengine AS
4
This file is part of Cfengine 3 - written and maintained by Cfengine AS.
6
This program is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; version 3.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19
To the extent this program is licensed as part of the Enterprise
20
versions of Cfengine, the applicable Commerical Open Source License
21
(COSL) may apply to this file if you as a licensee so wish it. See
22
included file COSL.txt.
26
/*****************************************************************************/
28
/* File: generic_agent.c */
30
/*****************************************************************************/
33
#include "cf3.extern.h"
36
extern char *CFH[][2];
37
extern void CheckOpts(int argc,char **argv);
39
/*****************************************************************************/
41
void GenericInitialize(int argc,char **argv,char *agents)
43
{ enum cfagenttype ag = Agent2Type(agents);
44
char vbuff[CF_BUFSIZE];
47
InitializeGA(argc,argv);
49
SetReferenceTime(true);
53
// See cf3.defs.h for these settings
55
if (EnterpriseExpiry(LIC_DAY,LIC_MONTH,LIC_YEAR))
57
CfOut(cf_error,"","Cfengine - autonomous configuration engine. This enterprise license is invalid.\n");
68
CfGetInterfaceInfo(ag);
77
LoadPersistentContext();
78
LoadSystemConstants();
80
strcpy(THIS_AGENT,CF_AGENTTYPES[ag]);
81
NewClass(CanonifyName(THIS_AGENT));
84
snprintf(vbuff,CF_BUFSIZE,"control_%s",THIS_AGENT);
92
SetPolicyServer(POLICY_SERVER);
96
ok = BOOTSTRAP || CheckPromises(ag);
100
ReadPromises(ag,agents);
104
CfOut(cf_error,"","cf-agent was not able to get confirmation of promises from cf-promises, so going to failsafe\n");
105
snprintf(VINPUTFILE,CF_BUFSIZE-1,"failsafe.cf");
106
ReadPromises(ag,agents);
109
if (SHOWREPORTS || ERRORCOUNT)
111
CompilationReport(VINPUTFILE);
119
/*****************************************************************************/
121
void GenericDeInitialize()
124
Debug("GenericDeInitialize()\n");
132
/*****************************************************************************/
134
/*****************************************************************************/
136
int CheckPromises(enum cfagenttype ag)
138
{ char cmd[CF_BUFSIZE],path[CF_BUFSIZE];
141
if ((ag != cf_agent) && (ag != cf_executor) && (ag != cf_server))
146
CfOut(cf_verbose,""," > Verifying the syntax of the inputs...\n");
148
snprintf(cmd,CF_BUFSIZE-1,"%s%cbin%ccf-promises%s",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,EXEC_SUFFIX);
150
if (cfstat(cmd,&sb) == -1)
152
CfOut(cf_error,"","cf-promises%s needs to be installed in %s%cbin for pre-validation of full configuration",EXEC_SUFFIX,CFWORKDIR,FILE_SEPARATOR);
156
/* If we are cf-agent, check syntax before attempting to run */
158
if ((*VINPUTFILE == '.') || IsAbsoluteFileName(VINPUTFILE))
160
snprintf(cmd,CF_BUFSIZE-1,"\"%s%cbin%ccf-promises%s\" -f \"%s\"",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,EXEC_SUFFIX,VINPUTFILE);
164
snprintf(cmd,CF_BUFSIZE-1,"\"%s%cbin%ccf-promises%s\" -f \"%s%cinputs%c%s\"",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,EXEC_SUFFIX,CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,VINPUTFILE);
167
/* Check if reloading policy will succeed */
169
if (ShellCommandReturnsZero(cmd,true))
179
/*****************************************************************************/
181
void ReadPromises(enum cfagenttype ag,char *agents)
185
char vbuff[CF_BUFSIZE];
186
struct Constraint *cp;
197
/* Now import some web variables that are set in cf-know/control for the report options */
199
strncpy(STYLESHEET,"/cf_enterprise.css",CF_BUFSIZE-1);
200
strncpy(WEBDRIVER,"",CF_MAXVARSIZE-1);
202
/* Make the compilation reports*/
208
if (GetVariable("control_common","version",&retval,&rettype) != cf_notype)
217
if (strchr(retval,':'))
219
CfOut(cf_error,""," !! The version string may not contain the \":\" character");
222
snprintf(vbuff,CF_BUFSIZE-1,"<h1>Expanded promises for %s</h1>",agents);
223
CfHtmlHeader(FREPORT_HTML,vbuff,STYLESHEET,WEBDRIVER,BANNER);
225
fprintf(FREPORT_TXT,"Expanded promise list for %s component\n\n",agents);
228
fprintf(FREPORT_HTML,"%s",CFH[cfx_promise][cfb]);
230
VerifyPromises(cf_common);
232
fprintf(FREPORT_HTML,"%s",CFH[cfx_promise][cfe]);
236
ShowScopedVariables();
239
CfHtmlFooter(FREPORT_HTML,FOOTER);
241
CloseReports(agents);
244
/*****************************************************************************/
252
openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,FACILITY);
256
/*****************************************************************************/
268
/*****************************************************************************/
270
void PromiseManagement(char *agent)
272
{ enum cfagenttype ag = Agent2Type(agent);
290
/*******************************************************************/
292
/*******************************************************************/
294
void InitializeGA(int argc,char *argv[])
297
int i,j,seed,force = false;
298
struct stat statbuf,sb;
299
unsigned char s[16],vbuff[CF_BUFSIZE];
300
char ebuff[CF_EXPANDSIZE];
303
if (cfstat("/cygdrive",&statbuf) == 0)
305
FILE_SEPARATOR = '/';
306
strcpy(FILE_SEPARATOR_STR,"/");
310
FILE_SEPARATOR = '\\';
311
strcpy(FILE_SEPARATOR_STR,"\\");
314
FILE_SEPARATOR = '/';
315
strcpy(FILE_SEPARATOR_STR,"/");
320
#ifdef HAVE_LIBCFNOVA
321
NewClass("nova_edition");
323
NewClass("community_edition");
326
strcpy(VPREFIX,GetConsolePrefix());
330
NewClass("verbose_mode");
335
NewClass("inform_mode");
340
NewClass("debug_mode");
343
CfOut(cf_verbose,"","Cfengine - autonomous configuration engine - commence self-diagnostic prelude\n");
344
CfOut(cf_verbose,"","------------------------------------------------------------------------\n");
346
/* Define trusted directories */
349
if(NovaWin_GetProgDir(CFWORKDIR, CF_BUFSIZE - sizeof("Cfengine")))
351
strcat(CFWORKDIR, "\\Cfengine");
355
CfOut(cf_error, "", "!! Could not get CFWORKDIR from Windows environment variable, falling back to compile time dir (%s)", WORKDIR);
356
strcpy(CFWORKDIR,WORKDIR);
358
Debug("Setting CFWORKDIR=%s\n", CFWORKDIR);
360
strcpy(CFWORKDIR,WORKDIR);
365
strncpy(CFWORKDIR,GetHome(getuid()),CF_BUFSIZE-10);
366
strcat(CFWORKDIR,"/.cfagent");
368
if (strlen(CFWORKDIR) > CF_BUFSIZE/2)
370
FatalError("Suspicious looking home directory. The path is too long and will lead to problems.");
375
strcpy(CFWORKDIR,WORKDIR);
379
/* On windows, use 'binary mode' as default for files */
385
strcpy(SYSLOGHOST,"localhost");
386
SYSLOGPORT = htons(514);
390
if (!LOOKUP) /* cf-know should not do this in lookup mode */
392
CfOut(cf_verbose,"","Work directory is %s\n",CFWORKDIR);
394
snprintf(HASHDB,CF_BUFSIZE-1,"%s%c%s",CFWORKDIR,FILE_SEPARATOR,CF_CHKDB);
396
snprintf(vbuff,CF_BUFSIZE,"%s%cinputs%cupdate.conf",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
397
MakeParentDirectory(vbuff,force);
398
snprintf(vbuff,CF_BUFSIZE,"%s%cbin%ccf-agent -D from_cfexecd",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
399
MakeParentDirectory(vbuff,force);
400
snprintf(vbuff,CF_BUFSIZE,"%s%coutputs%cspooled_reports",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
401
MakeParentDirectory(vbuff,force);
402
snprintf(vbuff,CF_BUFSIZE,"%s%clastseen%cintermittencies",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
403
MakeParentDirectory(vbuff,force);
404
snprintf(vbuff,CF_BUFSIZE,"%s%creports%cvarious",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
405
MakeParentDirectory(vbuff,force);
407
snprintf(vbuff,CF_BUFSIZE,"%s%cinputs",CFWORKDIR,FILE_SEPARATOR);
409
if (cfstat(vbuff,&sb) == -1)
411
FatalError(" !!! No access to workspace");
415
cf_chmod(vbuff,sb.st_mode | 0700);
418
snprintf(vbuff,CF_BUFSIZE,"%s%coutputs",CFWORKDIR,FILE_SEPARATOR);
420
if (cfstat(vbuff,&sb) == -1)
422
FatalError(" !!! No access to workspace");
426
cf_chmod(vbuff,sb.st_mode | 0700);
429
sprintf(ebuff,"%s%cstate%ccf_procs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
430
MakeParentDirectory(ebuff,force);
432
if (cfstat(ebuff,&statbuf) == -1)
434
CreateEmptyFile(ebuff);
437
sprintf(ebuff,"%s%cstate%ccf_rootprocs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
439
if (cfstat(ebuff,&statbuf) == -1)
441
CreateEmptyFile(ebuff);
444
sprintf(ebuff,"%s%cstate%ccf_otherprocs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
446
if (cfstat(ebuff,&statbuf) == -1)
448
CreateEmptyFile(ebuff);
454
// cleanup db file from v. 3.0.2 (can be removed later)
455
char oldLockDb[CF_BUFSIZE];
456
snprintf(oldLockDb, sizeof(oldLockDb), "%s/cfengine_lock_db", CFWORKDIR);
459
/* Init crypto stuff */
461
OpenSSL_add_all_algorithms();
462
OpenSSL_add_all_digests();
463
ERR_load_crypto_strings();
464
CheckWorkingDirectories();
474
/* CheckOpts(argc,argv); - MacOS can't handle this back reference */
478
snprintf(VINPUTFILE,CF_BUFSIZE-1,"promises.cf");
483
DetermineCfenginePort();
492
snprintf(vbuff,CF_BUFSIZE,"%s%cinputs%cfailsafe.cf",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
494
if (!IsEnterprise() && cfstat(vbuff,&statbuf) == -1)
496
CfOut(cf_inform,"","Didn't find established file %s, so looking for one in current directory\n",vbuff);
497
snprintf(VINPUTFILE,CF_BUFSIZE-1,".%cfailsafe.cf",FILE_SEPARATOR);
501
CfOut(cf_inform,"","Found an established failsafe file %s, so using it.\n",vbuff);
502
strncpy(VINPUTFILE,vbuff,CF_BUFSIZE-1);
508
/*******************************************************************/
512
{ struct Rlist *rp,*sl;
516
if ((PROMISETIME = time((time_t *)NULL)) == -1)
518
printf("Couldn't read system clock\n");
521
Cf3ParseFile(VINPUTFILE);
523
// Expand any lists in this list now
528
if (VINPUTLIST != NULL)
530
for (rp = VINPUTLIST; rp != NULL; rp=rp->next)
532
if (rp->type != CF_SCALAR)
534
CfOut(cf_error,"","Non-file object in inputs list\n");
538
struct Rval returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL);
540
switch (returnval.rtype)
543
Cf3ParseFile((char *)returnval.item);
547
for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next)
549
Cf3ParseFile((char *)sl->item);
561
/*******************************************************************/
563
int NewPromiseProposals()
565
{ struct Rlist *rp,*sl;
569
if (cfstat(InputLocation(VINPUTFILE),&sb) == -1)
571
CfOut(cf_error,"stat","There is no readable input file at %s",VINPUTFILE);
575
if (sb.st_mtime > PROMISETIME)
580
if (VINPUTLIST != NULL)
582
for (rp = VINPUTLIST; rp != NULL; rp=rp->next)
584
if (rp->type != CF_SCALAR)
586
CfOut(cf_error,"","Non file object %s in list\n",(char *)rp->item);
590
struct Rval returnval = EvaluateFinalRval("sys",rp->item,rp->type,true,NULL);
592
switch (returnval.rtype)
596
if (cfstat(InputLocation((char *)returnval.item),&sb) == -1)
598
CfOut(cf_error,"stat","There are no readable promise proposals at %s",(char *)returnval.item);
602
if (sb.st_mtime > PROMISETIME)
611
for (sl = (struct Rlist *)returnval.item; sl != NULL; sl=sl->next)
613
if (cfstat(InputLocation((char *)sl->item),&sb) == -1)
615
CfOut(cf_error,"stat","There are no readable promise proposals at %s",(char *)sl->item);
619
if (sb.st_mtime > PROMISETIME)
629
DeleteRvalItem(returnval.item,returnval.rtype);
642
/*******************************************************************/
644
void OpenReports(char *agents)
646
{ char name[CF_BUFSIZE];
650
snprintf(name,CF_BUFSIZE,"%s%creports%cpromise_output_%s.txt",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,agents);
652
if ((FREPORT_TXT = fopen(name,"w")) == NULL)
654
CfOut(cf_error,"fopen","Cannot open output file %s",name);
655
FREPORT_TXT = fopen(NULLFILE,"w");
658
snprintf(name,CF_BUFSIZE,"%s%creports%cpromise_output_%s.html",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,agents);
660
if ((FREPORT_HTML = fopen(name,"w")) == NULL)
662
CfOut(cf_error,"fopen","Cannot open output file %s",name);
663
FREPORT_HTML = fopen(NULLFILE,"w");
666
snprintf(name,CF_BUFSIZE,"%s%cpromise_knowledge.cf",CFWORKDIR,FILE_SEPARATOR);
668
if ((FKNOW = fopen(name,"w")) == NULL)
670
CfOut(cf_error,"fopen","Cannot open output file %s",name);
671
FKNOW = fopen(NULLFILE,"w");
676
snprintf(name,CF_BUFSIZE,NULLFILE);
677
if ((FREPORT_TXT = fopen(name,"w")) == NULL)
679
char vbuff[CF_BUFSIZE];
680
snprintf(vbuff,CF_BUFSIZE,"Cannot open output file %s",name);
684
if ((FREPORT_HTML = fopen(name,"w")) == NULL)
686
char vbuff[CF_BUFSIZE];
687
snprintf(vbuff,CF_BUFSIZE,"Cannot open output file %s",name);
691
if ((FKNOW = fopen(name,"w")) == NULL)
693
char vbuff[CF_BUFSIZE];
694
snprintf(vbuff,CF_BUFSIZE,"Cannot open output file %s",name);
699
if (!(FKNOW && FREPORT_HTML && FREPORT_TXT))
701
FatalError("Unable to continue as the null-file is unwritable");
704
fprintf(FKNOW,"bundle knowledge CfengineEnterpriseFundamentals\n{\n");
705
ShowTopicRepresentation(FKNOW);
706
fprintf(FKNOW,"}\n\nbundle knowledge CfengineSiteConfiguration\n{\n");
709
/*******************************************************************/
711
void CloseReports(char *agents)
713
{ char name[CF_BUFSIZE];
717
CfOut(cf_cmdout,"","Wrote compilation report %s%creports%cpromise_output_%s.txt",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,agents);
718
CfOut(cf_cmdout,"","Wrote compilation report %s%creports%cpromise_output_%s.html",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,agents);
719
CfOut(cf_cmdout,"","Wrote knowledge map %s%cpromise_knowledge.cf",CFWORKDIR,FILE_SEPARATOR,agents);
722
fprintf(FKNOW,"}\n");
724
fclose(FREPORT_HTML);
728
/*******************************************************************/
730
/*******************************************************************/
732
void Cf3ParseFile(char *filename)
734
{ FILE *save_yyin = yyin;
738
char wfilename[CF_BUFSIZE];
741
strncpy(wfilename,InputLocation(filename),CF_BUFSIZE);
743
if (cfstat(wfilename,&statbuf) == -1)
745
if (IGNORE_MISSING_INPUTS)
750
CfOut(cf_error,"stat","Can't stat file \"%s\" for parsing\n",wfilename);
755
if (statbuf.st_mode & (S_IWGRP | S_IWOTH))
757
CfOut(cf_error,"","File %s (owner %d) is writable by others (security exception)",wfilename,statbuf.st_uid);
762
Debug("+++++++++++++++++++++++++++++++++++++++++++++++\n");
763
CfOut(cf_verbose,""," > Parsing file %s\n",wfilename);
764
Debug("+++++++++++++++++++++++++++++++++++++++++++++++\n");
766
PrependAuditFile(wfilename);
768
if ((yyin = fopen(wfilename,"r")) == NULL) /* Open root file */
770
printf("Can't open file %s for parsing\n",wfilename);
778
P.filename = strdup(wfilename);
781
P.currentstring = NULL;
782
P.currenttype = NULL;
783
P.currentclasses = NULL;
784
P.currentRlist = NULL;
785
P.currentpromise = NULL;
792
if (ferror(yyin)) /* abortable */
802
/*******************************************************************/
804
struct Constraint *ControlBodyConstraints(enum cfagenttype agent)
807
char scope[CF_BUFSIZE];
809
for (body = BODIES; body != NULL; body = body->next)
811
if (strcmp(body->type,CF_AGENTTYPES[agent]) == 0)
813
if (strcmp(body->name,"control") == 0)
815
Debug("%s body for type %s\n",body->name,body->type);
816
return body->conlist;
824
/*******************************************************************/
826
void SetFacility(char *retval)
829
if (strcmp(retval,"LOG_USER") == 0)
833
else if (strcmp(retval,"LOG_DAEMON") == 0)
835
FACILITY = LOG_DAEMON;
837
else if (strcmp(retval,"LOG_LOCAL0") == 0)
839
FACILITY = LOG_LOCAL0;
841
else if (strcmp(retval,"LOG_LOCAL1") == 0)
843
FACILITY = LOG_LOCAL1;
845
else if (strcmp(retval,"LOG_LOCAL2") == 0)
847
FACILITY = LOG_LOCAL2;
849
else if (strcmp(retval,"LOG_LOCAL3") == 0)
851
FACILITY = LOG_LOCAL3;
853
else if (strcmp(retval,"LOG_LOCAL4") == 0)
855
FACILITY = LOG_LOCAL4;
857
else if (strcmp(retval,"LOG_LOCAL5") == 0)
859
FACILITY = LOG_LOCAL5;
861
else if (strcmp(retval,"LOG_LOCAL6") == 0)
863
FACILITY = LOG_LOCAL6;
865
else if (strcmp(retval,"LOG_LOCAL7") == 0)
867
FACILITY = LOG_LOCAL7;
874
/**************************************************************/
876
struct Bundle *GetBundle(char *name,char *agent)
880
for (bp = BUNDLES; bp != NULL; bp = bp->next) /* get schedule */
882
if (strcmp(bp->name,name) == 0)
886
if ((strcmp(bp->type,agent) == 0) || (strcmp(bp->type,"common") == 0))
892
CfOut(cf_verbose,"","The bundle called %s is not of type %s\n",name,agent);
905
/**************************************************************/
907
struct SubType *GetSubTypeForBundle(char *type,struct Bundle *bp)
909
{ struct SubType *sp;
916
for (sp = bp->subtypes; sp != NULL; sp=sp->next)
918
if (strcmp(type,sp->name)== 0)
927
/**************************************************************/
929
void BannerBundle(struct Bundle *bp,struct Rlist *params)
932
CfOut(cf_verbose,"","\n");
933
CfOut(cf_verbose,"","*****************************************************************\n");
935
if (VERBOSE || DEBUG)
937
printf("%s BUNDLE %s",VPREFIX,bp->name);
940
if (params && (VERBOSE||DEBUG))
943
ShowRlist(stdout,params);
948
if (VERBOSE||DEBUG) printf("\n");
951
CfOut(cf_verbose,"","*****************************************************************\n");
952
CfOut(cf_verbose,"","\n");
955
/**************************************************************/
957
void BannerSubBundle(struct Bundle *bp,struct Rlist *params)
960
CfOut(cf_verbose,"","\n");
961
CfOut(cf_verbose,""," * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
963
if (VERBOSE || DEBUG)
965
printf("%s BUNDLE %s",VPREFIX,bp->name);
968
if (params && (VERBOSE||DEBUG))
971
ShowRlist(stdout,params);
976
if (VERBOSE||DEBUG) printf("\n");
978
CfOut(cf_verbose,""," * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
979
CfOut(cf_verbose,"","\n");
982
/**************************************************************/
984
void PromiseBanner(struct Promise *pp)
986
{ char *sp,handle[CF_MAXVARSIZE];
988
if ((sp = GetConstraint("handle",pp,CF_SCALAR)) || (sp = PromiseID(pp)))
990
strncpy(handle,sp,CF_MAXVARSIZE-1);
994
strcpy(handle,"(enterprise only)");
997
CfOut(cf_verbose,"","\n");
998
CfOut(cf_verbose,""," .........................................................\n");
1002
printf ("%s Promise handle: %s\n",VPREFIX,handle);
1003
printf ("%s Promise made by: %s",VPREFIX,pp->promiser);
1011
ShowRval(stdout,pp->promisee,pp->petype);
1022
CfOut(cf_verbose,"","\n");
1023
CfOut(cf_verbose,""," Comment: %s\n",pp->ref);
1026
CfOut(cf_verbose,""," .........................................................\n");
1027
CfOut(cf_verbose,"","\n");
1031
/*********************************************************************/
1033
void CheckWorkingDirectories()
1035
/* NOTE: We do not care about permissions (ACLs) in windows */
1037
{ struct stat statbuf;
1039
char *sp,vbuff[CF_BUFSIZE];
1040
char output[CF_BUFSIZE];
1042
Debug("CheckWorkingDirectories()\n");
1044
if (uname(&VSYSNAME) == -1)
1047
FatalError("Uname couldn't get kernel name info!!\n");
1050
snprintf(LOGFILE,CF_BUFSIZE,"%s%ccfagent.%s.log",CFWORKDIR,FILE_SEPARATOR,VSYSNAME.nodename);
1051
VSETUIDLOG = strdup(LOGFILE);
1053
snprintf(vbuff,CF_BUFSIZE,"%s%c.",CFWORKDIR,FILE_SEPARATOR);
1054
MakeParentDirectory(vbuff,false);
1056
CfOut(cf_verbose,"","Making sure that locks are private...\n");
1058
if (chown(CFWORKDIR,getuid(),getgid()) == -1)
1060
CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",CFWORKDIR,getuid(),getgid());
1063
if (cfstat(CFWORKDIR,&statbuf) != -1)
1065
/* change permissions go-w */
1066
cf_chmod(CFWORKDIR,(mode_t)(statbuf.st_mode & ~022));
1069
snprintf(vbuff,CF_BUFSIZE,"%s%cstate%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1070
MakeParentDirectory(vbuff,false);
1072
snprintf(CFPRIVKEYFILE,CF_BUFSIZE,"%s%cppkeys%clocalhost.priv",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1073
snprintf(CFPUBKEYFILE,CF_BUFSIZE,"%s%cppkeys%clocalhost.pub",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1075
CfOut(cf_verbose,"","Checking integrity of the state database\n");
1076
snprintf(vbuff,CF_BUFSIZE,"%s%cstate",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1078
if (cfstat(vbuff,&statbuf) == -1)
1080
snprintf(vbuff,CF_BUFSIZE,"%s%cstate%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1081
MakeParentDirectory(vbuff,false);
1083
if (chown(vbuff,getuid(),getgid()) == -1)
1085
CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",vbuff,getuid(),getgid());
1088
cf_chmod(vbuff,(mode_t)0755);
1093
if (statbuf.st_mode & 022)
1095
CfOut(cf_error,"","UNTRUSTED: State directory %s (mode %o) was not private!\n",CFWORKDIR,statbuf.st_mode & 0777);
1097
#endif /* NOT MINGW */
1100
CfOut(cf_verbose,"","Checking integrity of the module directory\n");
1102
snprintf(vbuff,CF_BUFSIZE,"%s%cmodules",CFWORKDIR,FILE_SEPARATOR);
1104
if (cfstat(vbuff,&statbuf) == -1)
1106
snprintf(vbuff,CF_BUFSIZE,"%s%cmodules%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1107
MakeParentDirectory(vbuff,false);
1109
if (chown(vbuff,getuid(),getgid()) == -1)
1111
CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",vbuff,getuid(),getgid());
1114
cf_chmod(vbuff,(mode_t)0700);
1119
if (statbuf.st_mode & 022)
1121
CfOut(cf_error,"","UNTRUSTED: Module directory %s (mode %o) was not private!\n",vbuff,statbuf.st_mode & 0777);
1123
#endif /* NOT MINGW */
1126
CfOut(cf_verbose,"","Checking integrity of the PKI directory\n");
1128
snprintf(vbuff,CF_BUFSIZE,"%s%cppkeys",CFWORKDIR,FILE_SEPARATOR);
1130
if (cfstat(vbuff,&statbuf) == -1)
1132
snprintf(vbuff,CF_BUFSIZE,"%s%cppkeys%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR);
1133
MakeParentDirectory(vbuff,false);
1135
cf_chmod(vbuff,(mode_t)0700); /* Keys must be immutable to others */
1140
if (statbuf.st_mode & 077)
1142
snprintf(output,CF_BUFSIZE-1,"UNTRUSTED: Private key directory %s%cppkeys (mode %o) was not private!\n",CFWORKDIR,FILE_SEPARATOR,statbuf.st_mode & 0777);
1145
#endif /* NOT MINGW */
1149
/*******************************************************************/
1151
/*******************************************************************/
1153
char *InputLocation(char *filename)
1155
{ static char wfilename[CF_BUFSIZE], path[CF_BUFSIZE];
1157
if (MINUSF && (filename != VINPUTFILE) && (*VINPUTFILE == '.' || IsAbsoluteFileName(VINPUTFILE)) && !IsAbsoluteFileName(filename))
1159
/* If -f assume included relative files are in same directory */
1160
strncpy(path,VINPUTFILE,CF_BUFSIZE-1);
1162
snprintf(wfilename,CF_BUFSIZE-1,"%s%c%s",path,FILE_SEPARATOR,filename);
1164
else if ((*filename == '.') || IsAbsoluteFileName(filename))
1166
strncpy(wfilename,filename,CF_BUFSIZE-1);
1170
snprintf(wfilename,CF_BUFSIZE-1,"%s%cinputs%c%s",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,filename);
1173
return MapName(wfilename);
1176
/*******************************************************************/
1178
void CompilationReport(char *fname)
1180
{ char filename[CF_BUFSIZE],output[CF_BUFSIZE];
1182
snprintf(filename,CF_BUFSIZE-1,"%s.txt",fname);
1183
printf("Summarizing promises as text to %s\n",filename);
1185
if ((FREPORT_TXT = fopen(filename,"w")) == NULL)
1187
snprintf(output,CF_BUFSIZE,"Could not write output log to %s",filename);
1191
snprintf(filename,CF_BUFSIZE-1,"%s.html",fname);
1192
printf("Summarizing promises as html to %s\n",filename);
1194
if ((FREPORT_HTML = fopen(filename,"w")) == NULL)
1196
snprintf(output,CF_BUFSIZE,"Could not write output log to %s",filename);
1200
if ((FKNOW = fopen(NULLFILE,"w")) == NULL)
1202
FatalError("Null-file failed");
1205
ShowPromises(BUNDLES,BODIES);
1207
fclose(FREPORT_HTML);
1208
fclose(FREPORT_TXT);
1212
/*******************************************************************/
1214
void VerifyPromises(enum cfagenttype agent)
1216
{ struct Bundle *bp,*bundles;
1221
struct Rlist *rp,*params;
1223
char buf[CF_BUFSIZE], *scope;
1226
Debug("\n\nVerifyPromises()\n");
1228
if (REQUIRE_COMMENTS == CF_UNDEFINED)
1230
for (bdp = BODIES; bdp != NULL; bdp = bdp->next) /* get schedule */
1232
if ((strcmp(bdp->name,"control") == 0) && (strcmp(bdp->type,"common") == 0))
1234
REQUIRE_COMMENTS = GetRawBooleanConstraint("require_comments",bdp->conlist);
1240
for (rp = BODYPARTS; rp != NULL; rp=rp->next)
1245
if (!IsBody(BODIES,(char *)rp->item))
1247
CfOut(cf_error,"","Undeclared promise body \"%s()\" was referenced in a promise\n",(char *)rp->item);
1253
fp = (struct FnCall *)rp->item;
1255
if (!IsBody(BODIES,fp->name))
1257
CfOut(cf_error,"","Undeclared promise body \"%s()\" was referenced in a promise\n",fp->name);
1264
/* Check for undefined subbundles */
1266
for (rp = SUBBUNDLES; rp != NULL; rp=rp->next)
1271
if (!IsBundle(BUNDLES,(char *)rp->item))
1273
CfOut(cf_error,"","Undeclared promise bundle \"%s()\" was referenced in a promise\n",(char *)rp->item);
1279
fp = (struct FnCall *)rp->item;
1281
if (!IsBundle(BUNDLES,fp->name))
1283
CfOut(cf_error,"","Undeclared promise bundle \"%s()\" was referenced in a promise\n",fp->name);
1290
/* Now look once through ALL the bundles themselves */
1292
for (bp = BUNDLES; bp != NULL; bp = bp->next) /* get schedule */
1295
THIS_BUNDLE = bp->name;
1297
for (sp = bp->subtypes; sp != NULL; sp = sp->next) /* get schedule */
1299
if (strcmp(sp->name,"classes") == 0)
1301
/* these should not be evaluated here */
1305
for (pp = sp->promiselist; pp != NULL; pp=pp->next)
1307
ExpandPromise(agent,scope,pp,NULL);
1316
/* Now look once through the sequences bundles themselves */
1318
if (BadBundleSequence(agent))
1320
FatalError("Errors in promise bundles");
1324
/********************************************************************/
1326
void PrependAuditFile(char *file)
1328
{ struct stat statbuf;;
1330
if ((AUDITPTR = (struct Audit *)malloc(sizeof(struct Audit))) == NULL)
1332
FatalError("Memory allocation failure in PrependAuditFile");
1335
if (cfstat(file,&statbuf) == -1)
1337
/* shouldn't happen */
1341
HashFile(file,AUDITPTR->digest,cf_md5);
1343
AUDITPTR->next = VAUDIT;
1344
AUDITPTR->filename = strdup(file);
1345
AUDITPTR->date = strdup(cf_ctime(&statbuf.st_mtime));
1346
Chop(AUDITPTR->date);
1347
AUDITPTR->version = NULL;
1352
/*******************************************************************/
1354
/*******************************************************************/
1356
void CheckVariablePromises(char *scope,struct Promise *varlist)
1358
{ struct Promise *pp;
1359
int allow_redefine = false;
1361
Debug("CheckVariablePromises()\n");
1363
for (pp = varlist; pp != NULL; pp=pp->next)
1365
ConvergeVarHashPromise(scope,pp,allow_redefine);
1369
/*******************************************************************/
1371
void CheckCommonClassPromises(struct Promise *classlist)
1373
{ struct Promise *pp;
1375
CfOut(cf_verbose,""," -> Checking common class promises...\n");
1377
for (pp = classlist; pp != NULL; pp=pp->next)
1379
KeepClassContextPromise(pp);
1383
/*******************************************************************/
1385
void CheckBundleParameters(char *scope,struct Rlist *args)
1389
char *lval,rettype;;
1391
for (rp = args; rp != NULL; rp = rp->next)
1393
lval = (char *)rp->item;
1395
if (GetVariable(scope,lval,(void *)&retval,&rettype) != cf_notype)
1397
CfOut(cf_error,"","Variable and bundle parameter %s collide",lval);
1398
FatalError("Aborting");
1403
/*******************************************************************/
1405
void CheckControlPromises(char *scope,char *agent,struct Constraint *controllist)
1407
{ struct Constraint *cp;
1408
struct SubTypeSyntax *sp;
1409
struct BodySyntax *bp = NULL;
1411
void *rval = NULL,*retval;
1412
int i = 0,override = true;
1413
struct Rval returnval;
1416
Debug("CheckControlPromises(%s)\n",agent);
1418
for (i = 0; CF_ALL_BODIES[i].bs != NULL; i++)
1420
bp = CF_ALL_BODIES[i].bs;
1422
if (strcmp(agent,CF_ALL_BODIES[i].btype) == 0)
1430
FatalError("Unknown agent");
1433
for (cp = controllist; cp != NULL; cp=cp->next)
1435
if (IsExcluded(cp->classes))
1440
if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_bundlesequence].lval) == 0)
1442
returnval = ExpandPrivateRval(CONTEXTID,cp->rval,cp->type);
1446
returnval = EvaluateFinalRval(CONTEXTID,cp->rval,cp->type,true,NULL);
1449
DeleteVariable(scope,cp->lval);
1451
if (!AddVariableHash(scope,cp->lval,returnval.item,returnval.rtype,GetControlDatatype(cp->lval,bp),cp->audit->filename,cp->lineno))
1453
CfOut(cf_error,"","Rule from %s at/before line %d\n",cp->audit->filename,cp->lineno);
1456
if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_output_prefix].lval) == 0)
1458
strncpy(VPREFIX,returnval.item,CF_MAXVARSIZE);
1461
if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_domain].lval) == 0)
1463
strcpy(VDOMAIN,cp->rval);
1464
CfOut(cf_verbose,"","SET domain = %s\n",VDOMAIN);
1465
DeleteScalar("sys","domain");
1466
DeleteScalar("sys","fqhost");
1467
snprintf(VFQNAME,CF_MAXVARSIZE,"%s.%s",VUQNAME,VDOMAIN);
1468
NewScalar("sys","fqhost",VFQNAME,cf_str);
1469
NewScalar("sys","domain",VDOMAIN,cf_str);
1470
DeleteClass("undefined_domain");
1471
NewClass(CanonifyName(VDOMAIN));
1474
if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_inputs].lval) == 0)
1476
CfOut(cf_verbose,"","SET ignore_missing_inputs %s\n",cp->rval);
1477
IGNORE_MISSING_INPUTS = GetBoolean(cp->rval);
1480
if (strcmp(cp->lval,CFG_CONTROLBODY[cfg_ignore_missing_bundles].lval) == 0)
1482
CfOut(cf_verbose,"","SET ignore_missing_bundles %s\n",cp->rval);
1483
IGNORE_MISSING_BUNDLES = GetBoolean(cp->rval);
1486
DeleteRvalItem(returnval.item,returnval.rtype);
1490
/*******************************************************************/
1492
void SetAuditVersion()
1497
/* In addition, each bundle can have its own version */
1499
switch (GetVariable("control_common","cfinputs_version",&rval,&rtype))
1502
if (rtype != CF_SCALAR)
1504
yyerror("non-scalar version string");
1506
AUDITPTR->version = strdup((char *)rval);
1510
AUDITPTR->version = strdup("no specified version");
1515
/*******************************************************************/
1517
void Syntax(char *component,struct option options[],char *hints[],char *id)
1521
printf("\n\n%s\n\n",component);
1523
printf("SYNOPSIS:\n\n program [options]\n\nDESCRIPTION:\n\n%s\n",id);
1524
printf("Command line options:\n\n");
1526
for (i=0; options[i].name != NULL; i++)
1528
if (options[i].has_arg)
1530
printf("--%-12s, -%c value - %s\n",options[i].name,(char)options[i].val,hints[i]);
1534
printf("--%-12s, -%-7c - %s\n",options[i].name,(char)options[i].val,hints[i]);
1539
printf("\nBug reports: bug-cfengine@cfengine.org, ");
1540
printf("Community help: help-cfengine@cfengine.org\n");
1541
printf("Community info: http://www.cfengine.org, ");
1542
printf("Support services: http://www.cfengine.com\n\n");
1543
printf("This software is (C) 2008 Cfengine AS.\n");
1546
/*******************************************************************/
1548
void ManPage(char *component,struct option options[],char *hints[],char *id)
1552
printf(".TH %s 8 \"Maintenance Commands\"\n",GetArg0(component));
1553
printf(".SH NAME\n%s\n\n",component);
1555
printf(".SH SYNOPSIS:\n\n %s [options]\n\n.SH DESCRIPTION:\n\n%s\n",GetArg0(component),id);
1557
printf(".B cfengine\n"
1558
"is a self-healing configuration and change management based system. You can think of"
1560
"as a very high level language, much higher level than Perl or shell. A"
1561
"single statement is called a promise, and compliance can result in many hundreds of files"
1562
"being created, or the permissions of many hundreds of"
1563
"files being set. The idea of "
1565
"is to create a one or more sets of configuration files which will"
1566
"classify and describe the setup of every host in a network.\n");
1568
printf(".SH COMMAND LINE OPTIONS:\n");
1570
for (i=0; options[i].name != NULL; i++)
1572
if (options[i].has_arg)
1574
printf(".IP \"--%s, -%c\" value\n%s\n",options[i].name,(char)options[i].val,hints[i]);
1578
printf(".IP \"--%s, -%c\"\n%s\n",options[i].name,(char)options[i].val,hints[i]);
1582
printf(".SH AUTHOR\n"
1583
"Mark Burgess and Cfengine AS\n"
1584
".SH INFORMATION\n");
1586
printf("\nBug reports: bug-cfengine@cfengine.org\n");
1587
printf(".pp\nCommunity help: help-cfengine@cfengine.org\n");
1588
printf(".pp\nCommunity info: http://www.cfengine.org\n");
1589
printf(".pp\nSupport services: http://www.cfengine.com\n");
1590
printf(".pp\nThis software is (C) 2008- Cfengine AS.\n");
1593
/*******************************************************************/
1595
void Version(char *component)
1598
printf("This comprises %s core community version %s - %s%s\n",component,VERSION,CF3COPYRIGHT,VYEAR);
1599
EnterpriseVersion();
1602
/********************************************************************/
1604
void WritePID(char *filename)
1608
snprintf(PIDFILE,CF_BUFSIZE-1,"%s%c%s",CFWORKDIR,FILE_SEPARATOR,filename);
1610
if ((fp = fopen(PIDFILE,"w")) == NULL)
1612
CfOut(cf_inform,"fopen","Could not write to PID file %s\n",filename);
1616
fprintf(fp,"%d\n",getpid());
1621
/*******************************************************************/
1623
void HashVariables()
1625
{ struct Bundle *bp,*bundles;
1629
CfOut(cf_verbose,"","Initiate variable convergence...\n");
1631
for (bp = BUNDLES; bp != NULL; bp = bp->next) /* get schedule */
1633
SetNewScope(bp->name);
1634
THIS_BUNDLE = bp->name;
1636
for (sp = bp->subtypes; sp != NULL; sp = sp->next) /* get schedule */
1638
if (strcmp(sp->name,"vars") == 0)
1640
CheckVariablePromises(bp->name,sp->promiselist);
1643
// We must also set global classes here?
1645
if (strcmp(bp->type,"common") == 0&& strcmp(sp->name,"classes") == 0)
1647
CheckCommonClassPromises(sp->promiselist);
1651
CheckBundleParameters(bp->name,bp->args);
1655
/*******************************************************************/
1660
char buf[CF_BUFSIZE];
1662
/* Only control bodies need to be hashed like variables */
1664
CfOut(cf_verbose,"","Initiate control variable convergence...\n");
1666
for (bdp = BODIES; bdp != NULL; bdp = bdp->next) /* get schedule */
1668
if (strcmp(bdp->name,"control") == 0)
1670
snprintf(buf,CF_BUFSIZE,"%s_%s",bdp->name,bdp->type);
1672
CheckControlPromises(buf,bdp->type,bdp->conlist);
1677
/*******************************************************************/
1679
void UnHashVariables()
1681
{ struct Bundle *bp,*bundles;
1683
for (bp = BUNDLES; bp != NULL; bp = bp->next) /* get schedule */
1685
DeleteScope(bp->name);
1689
/********************************************************************/
1691
int BadBundleSequence(enum cfagenttype agent)
1693
{ struct Rlist *rp,*params;
1695
void *retval = NULL;
1699
if (THIS_AGENT_TYPE != cf_agent && THIS_AGENT_TYPE != cf_know && THIS_AGENT_TYPE != cf_common)
1704
if (CBUNDLESEQUENCE)
1709
if (GetVariable("control_common","bundlesequence",&retval,&rettype) == cf_notype)
1711
CfOut(cf_error,""," !!! No bundlesequence in the common control body");
1713
if (agent == cf_common)
1723
if (rettype != CF_LIST)
1725
FatalError("Promised bundlesequence was not a list");
1728
if (agent == cf_agent || agent == cf_common)
1730
for (rp = (struct Rlist *)retval; rp != NULL; rp=rp->next)
1735
name = (char *)rp->item;
1740
fp = (struct FnCall *)rp->item;
1741
name = (char *)fp->name;
1742
params = (struct Rlist *)fp->args;
1748
CfOut(cf_error,"","Illegal item found in bundlesequence: ");
1749
ShowRval(stdout,rp->item,rp->type);
1750
printf(" = %c\n",rp->type);
1755
if (!IGNORE_MISSING_BUNDLES && !GetBundle(name,NULL))
1757
CfOut(cf_error,"","Bundle \"%s\" listed in the bundlesequence is not a defined bundle\n",name);