/** * @brief Writes a file with a contained timestamp to mark a policy file as validated * @param filename the filename * @return True if successful. */ static bool WritePolicyValidatedFile(ARG_UNUSED const GenericAgentConfig *config, const char *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; } JsonElement *info = JsonObjectCreate(3); JsonObjectAppendInteger(info, "timestamp", time(NULL)); Writer *w = FileWriter(fdopen(fd, "w")); JsonWrite(w, info, 0); WriterClose(w); JsonDestroy(info); Log(LOG_LEVEL_VERBOSE, "Saved policy validated marker file '%s'", filename); return true; }
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; } }
int MakeParentDirectory2(char *parentandchild, int force, bool enforce_promise) { if(enforce_promise) { return MakeParentDirectory(parentandchild, force); } char *parent_dir = GetParentDirectoryCopy(parentandchild); if (parent_dir) { bool parent_exists = IsDir(parent_dir); free(parent_dir); return parent_exists; } else { return false; } }
/** * @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; }
void GenericAgentInitialize(EvalContext *ctx, GenericAgentConfig *config) { int force = false; struct stat statbuf, sb; char vbuff[CF_BUFSIZE]; char ebuff[CF_EXPANDSIZE]; #ifdef __MINGW32__ InitializeWindows(); #endif DetermineCfenginePort(); EvalContextClassPutHard(ctx, "any", "source=agent"); GenericAgentAddEditionClasses(ctx); strcpy(VPREFIX, GetConsolePrefix()); /* Define trusted directories */ { const char *workdir = GetWorkDir(); if (!workdir) { FatalError(ctx, "Error determining working directory"); } strcpy(CFWORKDIR, workdir); MapName(CFWORKDIR); } OpenLog(LOG_USER); SetSyslogFacility(LOG_USER); Log(LOG_LEVEL_VERBOSE, "Work directory is %s", CFWORKDIR); snprintf(vbuff, CF_BUFSIZE, "%s%cupdate.conf", GetInputDir(), FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%cbin%ccf-agent -D from_cfexecd", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%coutputs%cspooled_reports", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%clastseen%cintermittencies", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%creports%cvarious", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s", GetInputDir()); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/inputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } snprintf(vbuff, CF_BUFSIZE, "%s%coutputs", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/outputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_procs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_rootprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_otherprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%cprevious_state%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); snprintf(ebuff, sizeof(ebuff), "%s%cstate%cdiff%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); snprintf(ebuff, sizeof(ebuff), "%s%cstate%cuntracked%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); OpenNetwork(); CryptoInitialize(); CheckWorkingDirectories(ctx); /* Initialize keys and networking. cf-key, doesn't need keys. In fact it must function properly even without them, so that it generates them! */ if (config->agent_type != AGENT_TYPE_KEYGEN) { LoadSecretKeys(); char *bootstrapped_policy_server = ReadPolicyServerFile(CFWORKDIR); PolicyHubUpdateKeys(bootstrapped_policy_server); free(bootstrapped_policy_server); cfnet_init(); } size_t cwd_size = PATH_MAX; while (true) { char cwd[cwd_size]; if (!getcwd(cwd, cwd_size)) { if (errno == ERANGE) { cwd_size *= 2; continue; } Log(LOG_LEVEL_WARNING, "Could not determine current directory. (getcwd: '%s')", GetErrorStr()); break; } EvalContextSetLaunchDirectory(ctx, cwd); break; } if (!MINUSF) { GenericAgentConfigSetInputFile(config, GetInputDir(), "promises.cf"); } VIFELAPSED = 1; VEXPIREAFTER = 1; setlinebuf(stdout); if (config->agent_specific.agent.bootstrap_policy_server) { snprintf(vbuff, CF_BUFSIZE, "%s%cfailsafe.cf", GetInputDir(), FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { GenericAgentConfigSetInputFile(config, GetInputDir(), "failsafe.cf"); } else { GenericAgentConfigSetInputFile(config, GetInputDir(), vbuff); } } }
int ArchiveToRepository(char *file,struct Attributes attr,struct Promise *pp) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; char localrepository[CF_BUFSIZE]; char node[CF_BUFSIZE]; struct stat sb, dsb; char *sp; if (attr.repository == NULL && VREPOSITORY == NULL) { return false; } if (attr.repository != NULL) { strncpy(localrepository,attr.repository,CF_BUFSIZE); } else if (VREPOSITORY != NULL) { strncpy(localrepository,VREPOSITORY,CF_BUFSIZE); } if (attr.copy.backup == cfa_nobackup) { return true; } if (IsItemIn(VREPOSLIST,file)) { CfOut(cf_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); Debug("Repository(%s)\n",file); strcpy (node,file); destination[0] = '\0'; for (sp = node; *sp != '\0'; sp++) { if (*sp == FILE_SEPARATOR) { *sp = REPOSCHAR; } } strncpy(destination,localrepository,CF_BUFSIZE-2); if (!JoinPath(destination,node)) { CfOut(cf_error,"","Internal limit: Buffer ran out of space for long filename\n"); return false; } if (!MakeParentDirectory(destination,attr.move_obstructions)) { } if (cfstat(file,&sb) == -1) { Debug("File %s promised to archive to the repository but it disappeared!\n",file); return true; } cfstat(destination,&dsb); attr.copy.servers = NULL; attr.copy.backup = cfa_repos_store; // cfa_nobackup; attr.copy.stealth = false; attr.copy.verify = false; attr.copy.preserve = false; CheckForFileHoles(&sb,pp); if (CopyRegularFileDisk(file,destination,attr,pp)) { CfOut(cf_inform,"","Moved %s to repository location %s\n",file,destination); return true; } else { CfOut(cf_inform,"","Failed to move %s to repository location %s\n",file,destination); return false; } }
void *CopyFileSources(char *destination, Attributes attr, Promise *pp, const ReportContext *report_context) { char *source = attr.copy.source; char *server = pp->this_server; char vbuff[CF_BUFSIZE]; struct stat ssb, dsb; struct timespec start; char eventname[CF_BUFSIZE]; CfDebug("CopyFileSources(%s,%s)", source, destination); if (pp->conn != NULL && !pp->conn->authenticated) { cfPS(cf_verbose, CF_FAIL, "", pp, attr, "No authenticated source %s in files.copyfrom promise\n", source); return NULL; } if (cf_stat(attr.copy.source, &ssb, attr, pp) == -1) { cfPS(cf_inform, CF_FAIL, "", pp, attr, "Can't stat %s in files.copyfrom promise\n", source); return NULL; } start = BeginMeasure(); strncpy(vbuff, destination, CF_BUFSIZE - 4); if (S_ISDIR(ssb.st_mode)) /* could be depth_search */ { AddSlash(vbuff); strcat(vbuff, "."); } if (!MakeParentDirectory(vbuff, attr.move_obstructions, report_context)) { cfPS(cf_inform, CF_FAIL, "", pp, attr, "Can't make directories for %s in files.copyfrom promise\n", vbuff); return NULL; } if (S_ISDIR(ssb.st_mode)) /* could be depth_search */ { if (attr.copy.purge) { CfOut(cf_verbose, "", " !! (Destination purging enabled)\n"); } CfOut(cf_verbose, "", " ->> Entering %s\n", source); SetSearchDevice(&ssb, pp); SourceSearchAndCopy(source, destination, attr.recursion.depth, attr, pp, report_context); if (cfstat(destination, &dsb) != -1) { if (attr.copy.check_root) { VerifyCopiedFileAttributes(destination, &dsb, &ssb, attr, pp, report_context); } } } else { VerifyCopy(source, destination, attr, pp, report_context); } snprintf(eventname, CF_BUFSIZE - 1, "Copy(%s:%s > %s)", server, source, destination); EndMeasure(eventname, start); return NULL; }
void GenericAgentInitialize(EvalContext *ctx, GenericAgentConfig *config) { int force = false; struct stat statbuf, sb; char vbuff[CF_BUFSIZE]; char ebuff[CF_EXPANDSIZE]; SHORT_CFENGINEPORT = htons((unsigned short) 5308); snprintf(STR_CFENGINEPORT, 15, "5308"); EvalContextHeapAddHard(ctx, "any"); strcpy(VPREFIX, GetConsolePrefix()); /* Define trusted directories */ { const char *workdir = GetWorkDir(); if (!workdir) { FatalError(ctx, "Error determining working directory"); } strcpy(CFWORKDIR, workdir); MapName(CFWORKDIR); } /* On windows, use 'binary mode' as default for files */ #ifdef __MINGW32__ _fmode = _O_BINARY; #endif OpenLog(LOG_USER); SetSyslogFacility(LOG_USER); if (!LOOKUP) /* cf-know should not do this in lookup mode */ { Log(LOG_LEVEL_VERBOSE, "Work directory is %s", CFWORKDIR); snprintf(vbuff, CF_BUFSIZE, "%s%cinputs%cupdate.conf", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%cbin%ccf-agent -D from_cfexecd", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%coutputs%cspooled_reports", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%clastseen%cintermittencies", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%creports%cvarious", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%cinputs", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/inputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } snprintf(vbuff, CF_BUFSIZE, "%s%coutputs", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/outputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } sprintf(ebuff, "%s%cstate%ccf_procs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff, "%s%cstate%ccf_rootprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff, "%s%cstate%ccf_otherprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } } OpenNetwork(); CryptoInitialize(); if (!LOOKUP) { CheckWorkingDirectories(ctx); } const char *bootstrapped_policy_server = ReadPolicyServerFile(CFWORKDIR); /* Initialize keys and networking. cf-key, doesn't need keys. In fact it must function properly even without them, so that it generates them! */ if (config->agent_type != AGENT_TYPE_KEYGEN) { LoadSecretKeys(bootstrapped_policy_server); cfnet_init(); } if (!MINUSF) { GenericAgentConfigSetInputFile(config, GetWorkDir(), "promises.cf"); } DetermineCfenginePort(); VIFELAPSED = 1; VEXPIREAFTER = 1; setlinebuf(stdout); if (config->agent_specific.agent.bootstrap_policy_server) { snprintf(vbuff, CF_BUFSIZE, "%s%cinputs%cfailsafe.cf", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); #ifndef HAVE_ENTERPRISE if (stat(vbuff, &statbuf) == -1) { GenericAgentConfigSetInputFile(config, GetWorkDir(), "failsafe.cf"); } else #endif { GenericAgentConfigSetInputFile(config, GetWorkDir(), vbuff); } } }
static void CheckWorkingDirectories(EvalContext *ctx) /* NOTE: We do not care about permissions (ACLs) in windows */ { struct stat statbuf; char vbuff[CF_BUFSIZE]; if (uname(&VSYSNAME) == -1) { Log(LOG_LEVEL_ERR, "Couldn't get kernel name info. (uname: %s)", GetErrorStr()); memset(&VSYSNAME, 0, sizeof(VSYSNAME)); } snprintf(vbuff, CF_BUFSIZE, "%s%c.", CFWORKDIR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); Log(LOG_LEVEL_VERBOSE, "Making sure that locks are private..."); if (chown(CFWORKDIR, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s'' to '%ju.%ju'. (chown: %s)", CFWORKDIR, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } if (stat(CFWORKDIR, &statbuf) != -1) { /* change permissions go-w */ chmod(CFWORKDIR, (mode_t) (statbuf.st_mode & ~022)); } snprintf(vbuff, CF_BUFSIZE, "%s%cstate%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); Log(LOG_LEVEL_VERBOSE, "Checking integrity of the state database"); snprintf(vbuff, CF_BUFSIZE, "%s%cstate", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cstate%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); if (chown(vbuff, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s' to '%jd.%jd'. (chown: %s)", vbuff, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } chmod(vbuff, (mode_t) 0755); } else { #ifndef __MINGW32__ if (statbuf.st_mode & 022) { Log(LOG_LEVEL_ERR, "UNTRUSTED: State directory %s (mode %jo) was not private!", CFWORKDIR, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } Log(LOG_LEVEL_VERBOSE, "Checking integrity of the module directory"); snprintf(vbuff, CF_BUFSIZE, "%s%cmodules", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cmodules%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); if (chown(vbuff, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s' to '%ju.%ju'. (chown: %s)", vbuff, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } chmod(vbuff, (mode_t) 0700); } else { #ifndef __MINGW32__ if (statbuf.st_mode & 022) { Log(LOG_LEVEL_ERR, "UNTRUSTED: Module directory %s (mode %jo) was not private!", vbuff, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } Log(LOG_LEVEL_VERBOSE, "Checking integrity of the PKI directory"); snprintf(vbuff, CF_BUFSIZE, "%s%cppkeys", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cppkeys%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); chmod(vbuff, (mode_t) 0700); /* Keys must be immutable to others */ } else { #ifndef __MINGW32__ if (statbuf.st_mode & 077) { FatalError(ctx, "UNTRUSTED: Private key directory %s%cppkeys (mode %jo) was not private!\n", CFWORKDIR, FILE_SEPARATOR, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } }
static PromiseResult VerifyMountPromise(EvalContext *ctx, char *name, Attributes a, Promise *pp) { char *options; char dir[CF_BUFSIZE]; int changes = 0; Log(LOG_LEVEL_VERBOSE, "Verifying mounted file systems on '%s'", name); snprintf(dir, CF_BUFSIZE, "%s/.", name); if (!IsPrivileged()) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Only root can mount filesystems"); return PROMISE_RESULT_INTERRUPTED; } options = Rlist2String(a.mount.mount_options, ","); PromiseResult result = PROMISE_RESULT_NOOP; if (!FileSystemMountedCorrectly(GetGlobalMountedFSList(), name, a)) { if (!a.mount.unmount) { if (!MakeParentDirectory(dir, a.move_obstructions)) { } if (a.mount.editfstab) { changes += VerifyInFstab(ctx, name, a, pp, &result); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Filesystem '%s' was not mounted as promised, and no edits were promised in '%s'", name, VFSTAB[VSYSTEMHARDCLASS]); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); // Mount explicitly result = PromiseResultUpdate(result, VerifyMount(ctx, name, a, pp)); } } else { if (a.mount.editfstab) { changes += VerifyNotInFstab(ctx, name, a, pp, &result); } } if (changes) { CF_MOUNTALL = true; } } else { if (a.mount.unmount) { VerifyUnmount(ctx, name, a, pp); if (a.mount.editfstab) { VerifyNotInFstab(ctx, name, a, pp, &result); } } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Filesystem '%s' seems to be mounted as promised", name); } } free(options); return result; }
static int VerifyMountPromise(EvalContext *ctx, char *name, Attributes a, Promise *pp) { char *options; char dir[CF_BUFSIZE]; int changes = 0; CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Verifying mounted file systems on %s\n", name); snprintf(dir, CF_BUFSIZE, "%s/.", name); if (!IsPrivileged()) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_INTERRUPTED, "", pp, a, "Only root can mount filesystems.\n"); return false; } options = Rlist2String(a.mount.mount_options, ","); if (!FileSystemMountedCorrectly(MOUNTEDFSLIST, name, options, a)) { if (!a.mount.unmount) { if (!MakeParentDirectory(dir, a.move_obstructions)) { } if (a.mount.editfstab) { changes += VerifyInFstab(ctx, name, a, pp); } else { cfPS(ctx, OUTPUT_LEVEL_INFORM, PROMISE_RESULT_FAIL, "", pp, a, " -> Filesystem %s was not mounted as promised, and no edits were promised in %s\n", name, VFSTAB[VSYSTEMHARDCLASS]); // Mount explicitly VerifyMount(ctx, name, a, pp); } } else { if (a.mount.editfstab) { changes += VerifyNotInFstab(ctx, name, a, pp); } } if (changes) { CF_MOUNTALL = true; } } else { if (a.mount.unmount) { VerifyUnmount(ctx, name, a, pp); if (a.mount.editfstab) { VerifyNotInFstab(ctx, name, a, pp); } } else { cfPS(ctx, OUTPUT_LEVEL_INFORM, PROMISE_RESULT_NOOP, "", pp, a, " -> Filesystem %s seems to be mounted as promised\n", name); } } free(options); return true; }
static int VerifyMountPromise(char *name, Attributes a, Promise *pp, const ReportContext *report_context) { char *options; char dir[CF_BUFSIZE]; int changes = 0; CfOut(cf_verbose, "", " -> Verifying mounted file systems on %s\n", name); snprintf(dir, CF_BUFSIZE, "%s/.", name); if (!IsPrivileged()) { cfPS(cf_error, CF_INTERPT, "", pp, a, "Only root can mount filesystems.\n"); return false; } options = Rlist2String(a.mount.mount_options, ","); if (!FileSystemMountedCorrectly(MOUNTEDFSLIST, name, options, a, pp)) { if (!a.mount.unmount) { if (!MakeParentDirectory(dir, a.move_obstructions, report_context)) { } if (a.mount.editfstab) { changes += VerifyInFstab(name, a, pp); } else { cfPS(cf_inform, CF_FAIL, "", pp, a, " -> Filesystem %s was not mounted as promised, and no edits were promised in %s\n", name, VFSTAB[VSYSTEMHARDCLASS]); // Mount explicitly VerifyMount(name, a, pp); } } else { if (a.mount.editfstab) { changes += VerifyNotInFstab(name, a, pp); } } if (changes) { CF_MOUNTALL = true; } } else { if (a.mount.unmount) { VerifyUnmount(name, a, pp); if (a.mount.editfstab) { VerifyNotInFstab(name, a, pp); } } else { cfPS(cf_inform, CF_NOP, "", pp, a, " -> Filesystem %s seems to be mounted as promised\n", name); } } free(options); return true; }
void InitializeGA(int argc,char *argv[]) { int seed,force = false; struct stat statbuf,sb; unsigned char s[16]; char vbuff[CF_BUFSIZE]; char ebuff[CF_EXPANDSIZE]; SHORT_CFENGINEPORT = htons((unsigned short)5308); snprintf(STR_CFENGINEPORT,15,"5308"); NewClass("any"); #if defined HAVE_CONSTELLATION NewClass("constellation_edition"); #elif defined HAVE_NOVA NewClass("nova_edition"); #else NewClass("community_edition"); #endif strcpy(VPREFIX,GetConsolePrefix()); if (VERBOSE) { NewClass("verbose_mode"); } if (INFORM) { NewClass("inform_mode"); } if (DEBUG) { NewClass("debug_mode"); } CfOut(cf_verbose,"","Cfengine - autonomous configuration engine - commence self-diagnostic prelude\n"); CfOut(cf_verbose,"","------------------------------------------------------------------------\n"); /* Define trusted directories */ #ifdef MINGW if(NovaWin_GetProgDir(CFWORKDIR, CF_BUFSIZE - sizeof("Cfengine"))) { strcat(CFWORKDIR, "\\Cfengine"); } else { CfOut(cf_error, "", "!! Could not get CFWORKDIR from Windows environment variable, falling back to compile time dir (%s)", WORKDIR); strcpy(CFWORKDIR,WORKDIR); } Debug("Setting CFWORKDIR=%s\n", CFWORKDIR); #elif defined(CFCYG) strcpy(CFWORKDIR,WORKDIR); MapName(CFWORKDIR); #else if (getuid() > 0) { strncpy(CFWORKDIR,GetHome(getuid()),CF_BUFSIZE-10); strcat(CFWORKDIR,"/.cfagent"); if (strlen(CFWORKDIR) > CF_BUFSIZE/2) { FatalError("Suspicious looking home directory. The path is too long and will lead to problems."); } } else { strcpy(CFWORKDIR,WORKDIR); } #endif /* On windows, use 'binary mode' as default for files */ #ifdef MINGW _fmode = _O_BINARY; #endif strcpy(SYSLOGHOST,"localhost"); SYSLOGPORT = htons(514); Cf3OpenLog(LOG_USER); if (!LOOKUP) /* cf-know should not do this in lookup mode */ { CfOut(cf_verbose,"","Work directory is %s\n",CFWORKDIR); snprintf(HASHDB,CF_BUFSIZE-1,"%s%c%s",CFWORKDIR,FILE_SEPARATOR,CF_CHKDB); snprintf(vbuff,CF_BUFSIZE,"%s%cinputs%cupdate.conf",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,force); snprintf(vbuff,CF_BUFSIZE,"%s%cbin%ccf-agent -D from_cfexecd",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,force); snprintf(vbuff,CF_BUFSIZE,"%s%coutputs%cspooled_reports",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,force); snprintf(vbuff,CF_BUFSIZE,"%s%clastseen%cintermittencies",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,force); snprintf(vbuff,CF_BUFSIZE,"%s%creports%cvarious",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,force); snprintf(vbuff,CF_BUFSIZE,"%s%cinputs",CFWORKDIR,FILE_SEPARATOR); if (cfstat(vbuff,&sb) == -1) { FatalError(" !!! No access to WORKSPACE/inputs dir"); } else { cf_chmod(vbuff,sb.st_mode | 0700); } snprintf(vbuff,CF_BUFSIZE,"%s%coutputs",CFWORKDIR,FILE_SEPARATOR); if (cfstat(vbuff,&sb) == -1) { FatalError(" !!! No access to WORKSPACE/outputs dir"); } else { cf_chmod(vbuff,sb.st_mode | 0700); } sprintf(ebuff,"%s%cstate%ccf_procs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(ebuff,force); if (cfstat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff,"%s%cstate%ccf_rootprocs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); if (cfstat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff,"%s%cstate%ccf_otherprocs",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); if (cfstat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } } OpenNetwork(); /* Init crypto stuff */ OpenSSL_add_all_algorithms(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); if(!LOOKUP) { CheckWorkingDirectories(); } RandomSeed(); RAND_bytes(s,16); s[15] = '\0'; seed = ElfHash(s); srand48((long)seed); LoadSecretKeys(); /* CheckOpts(argc,argv); - MacOS can't handle this back reference */ if (!MINUSF) { snprintf(VINPUTFILE,CF_BUFSIZE-1,"promises.cf"); } AUDITDBP = NULL; DetermineCfenginePort(); VIFELAPSED = 1; VEXPIREAFTER = 1; setlinebuf(stdout); if (BOOTSTRAP) { snprintf(vbuff,CF_BUFSIZE,"%s%cinputs%cfailsafe.cf",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); if (!IsEnterprise() && cfstat(vbuff,&statbuf) == -1) { snprintf(VINPUTFILE,CF_BUFSIZE-1,".%cfailsafe.cf",FILE_SEPARATOR); } else { strncpy(VINPUTFILE,vbuff,CF_BUFSIZE-1); } } }
int CheckPromises(enum cfagenttype ag) { char cmd[CF_BUFSIZE], cfpromises[CF_MAXVARSIZE]; char filename[CF_MAXVARSIZE]; struct stat sb; int fd; if ((ag != cf_agent) && (ag != cf_executor) && (ag != cf_server)) { return true; } CfOut(cf_verbose,""," -> Verifying the syntax of the inputs...\n"); snprintf(cfpromises,sizeof(cfpromises),"%s%cbin%ccf-promises%s",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR,EXEC_SUFFIX); if (cfstat(cfpromises,&sb) == -1) { CfOut(cf_error,"","cf-promises%s needs to be installed in %s%cbin for pre-validation of full configuration",EXEC_SUFFIX,CFWORKDIR,FILE_SEPARATOR); return false; } /* If we are cf-agent, check syntax before attempting to run */ snprintf(cmd, sizeof(cmd), "\"%s\" -f \"", cfpromises); if (IsFileOutsideDefaultRepository(VINPUTFILE)) { strlcat(cmd, VINPUTFILE, CF_BUFSIZE); } else { strlcat(cmd, CFWORKDIR, CF_BUFSIZE); strlcat(cmd, FILE_SEPARATOR_STR "inputs" FILE_SEPARATOR_STR, CF_BUFSIZE); strlcat(cmd, VINPUTFILE, CF_BUFSIZE); } strlcat(cmd, "\"", CF_BUFSIZE); if (CBUNDLESEQUENCE) { strlcat(cmd, " -b \"", CF_BUFSIZE); strlcat(cmd, CBUNDLESEQUENCE_STR, CF_BUFSIZE); strlcat(cmd, "\"", CF_BUFSIZE); } if(BOOTSTRAP) { // avoids license complains from commercial cf-promises during bootstrap - see Nova_CheckLicensePromise strlcat(cmd, " -D bootstrap_mode", CF_BUFSIZE); } /* Check if reloading policy will succeed */ CfOut(cf_verbose, "", "Checking policy with command \"%s\"", cmd); if (ShellCommandReturnsZero(cmd,true)) { 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); } MakeParentDirectory(filename,true); if ((fd = creat(filename,0600)) != -1) { close(fd); CfOut(cf_verbose,""," -> Caching the state of validation\n"); } else { CfOut(cf_verbose,"creat"," -> Failed to cache the state of validation\n"); } return true; } else { return false; } }
static void CheckWorkingDirectories() /* NOTE: We do not care about permissions (ACLs) in windows */ { struct stat statbuf; char vbuff[CF_BUFSIZE]; char output[CF_BUFSIZE]; Debug("CheckWorkingDirectories()\n"); if (uname(&VSYSNAME) == -1) { CfOut(cf_error, "uname", "!!! Couldn't get kernel name info!"); memset(&VSYSNAME, 0, sizeof(VSYSNAME)); } else { snprintf(LOGFILE,CF_BUFSIZE,"%s%ccfagent.%s.log",CFWORKDIR,FILE_SEPARATOR,VSYSNAME.nodename); } snprintf(vbuff,CF_BUFSIZE,"%s%c.",CFWORKDIR,FILE_SEPARATOR); MakeParentDirectory(vbuff,false); CfOut(cf_verbose,"","Making sure that locks are private...\n"); if (chown(CFWORKDIR,getuid(),getgid()) == -1) { CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",CFWORKDIR,getuid(),getgid()); } if (cfstat(CFWORKDIR,&statbuf) != -1) { /* change permissions go-w */ cf_chmod(CFWORKDIR,(mode_t)(statbuf.st_mode & ~022)); } snprintf(vbuff,CF_BUFSIZE,"%s%cstate%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,false); if (strlen(CFPRIVKEYFILE) == 0) { snprintf(CFPRIVKEYFILE,CF_BUFSIZE,"%s%cppkeys%clocalhost.priv",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); snprintf(CFPUBKEYFILE,CF_BUFSIZE,"%s%cppkeys%clocalhost.pub",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); } CfOut(cf_verbose,"","Checking integrity of the state database\n"); snprintf(vbuff,CF_BUFSIZE,"%s%cstate",CFWORKDIR,FILE_SEPARATOR); if (cfstat(vbuff,&statbuf) == -1) { snprintf(vbuff,CF_BUFSIZE,"%s%cstate%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,false); if (chown(vbuff,getuid(),getgid()) == -1) { CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",vbuff,getuid(),getgid()); } cf_chmod(vbuff,(mode_t)0755); } else { #ifndef MINGW if (statbuf.st_mode & 022) { CfOut(cf_error,"","UNTRUSTED: State directory %s (mode %o) was not private!\n",CFWORKDIR,statbuf.st_mode & 0777); } #endif /* NOT MINGW */ } CfOut(cf_verbose,"","Checking integrity of the module directory\n"); snprintf(vbuff,CF_BUFSIZE,"%s%cmodules",CFWORKDIR,FILE_SEPARATOR); if (cfstat(vbuff,&statbuf) == -1) { snprintf(vbuff,CF_BUFSIZE,"%s%cmodules%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,false); if (chown(vbuff,getuid(),getgid()) == -1) { CfOut(cf_error,"chown","Unable to set owner on %s to %d.%d",vbuff,getuid(),getgid()); } cf_chmod(vbuff,(mode_t)0700); } else { #ifndef MINGW if (statbuf.st_mode & 022) { CfOut(cf_error,"","UNTRUSTED: Module directory %s (mode %o) was not private!\n",vbuff,statbuf.st_mode & 0777); } #endif /* NOT MINGW */ } CfOut(cf_verbose,"","Checking integrity of the PKI directory\n"); snprintf(vbuff,CF_BUFSIZE,"%s%cppkeys",CFWORKDIR,FILE_SEPARATOR); if (cfstat(vbuff,&statbuf) == -1) { snprintf(vbuff,CF_BUFSIZE,"%s%cppkeys%c.",CFWORKDIR,FILE_SEPARATOR,FILE_SEPARATOR); MakeParentDirectory(vbuff,false); cf_chmod(vbuff,(mode_t)0700); /* Keys must be immutable to others */ } else { #ifndef MINGW if (statbuf.st_mode & 077) { snprintf(output,CF_BUFSIZE-1,"UNTRUSTED: Private key directory %s%cppkeys (mode %o) was not private!\n",CFWORKDIR,FILE_SEPARATOR,statbuf.st_mode & 0777); FatalError(output); } #endif /* NOT MINGW */ } }