Exemplo n.º 1
0
void LogHashChange(char *file, FileState status, char *msg, Promise *pp)
{
    FILE *fp;
    char fname[CF_BUFSIZE];
    time_t now = time(NULL);
    mode_t perm = 0600;
    static char prevFile[CF_MAXVARSIZE] = { 0 };

// we might get called twice..
    if (strcmp(file, prevFile) == 0)
    {
        return;
    }

    strlcpy(prevFile, file, CF_MAXVARSIZE);

/* This is inefficient but we don't want to lose any data */

    snprintf(fname, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_FILECHANGE_NEW);
    MapName(fname);

#ifndef __MINGW32__
    struct stat sb;
    if (cfstat(fname, &sb) != -1)
    {
        if (sb.st_mode & (S_IWGRP | S_IWOTH))
        {
            CfOut(OUTPUT_LEVEL_ERROR, "", "File %s (owner %ju) is writable by others (security exception)", fname, (uintmax_t)sb.st_uid);
        }
    }
#endif /* !__MINGW32__ */

    if ((fp = fopen(fname, "a")) == NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Could not write to the hash change log");
        return;
    }

    const char *handle = PromiseID(pp);

    fprintf(fp, "%ld,%s,%s,%c,%s\n", (long) now, handle, file, FileStateToChar(status), msg);
    fclose(fp);

    cf_chmod(fname, perm);
}
Exemplo n.º 2
0
void CreateFailSafe(char *name)
{
    FILE *fout;

    if ((fout = fopen(name, "w")) == NULL)
    {
        CfOut(cf_error, "fopen", "Unable to write failsafe file! (%s)", name);
        return;
    }

    CfOut(cf_cmdout, "", " -> No policy failsafe discovered, assume temporary bootstrap vector\n");

    fprintf(fout,
            "body common control\n"
            "{\n"
            "bundlesequence => { \"cfe_internal_update\" };\n"
            "}\n\n"
            "body agent control\n"
            "{\n"
            "skipidentify => \"true\";\n"
            "}\n\n"
            "bundle agent cfe_internal_update\n"
            "{\n"
            "classes:\n"
            "  \"have_ppkeys\" expression => fileexists(\"$(sys.workdir)/ppkeys/localhost.pub\"),\n"
            "     handle => \"cfe_internal_bootstrap_update_classes_have_ppkeys\";\n"
            "\ncommands:\n"
            " !have_ppkeys::\n"
            "   \"$(sys.cf_key)\",\n"
            "      handle => \"cfe_internal_bootstrap_update_commands_generate_keys\";\n"
            "\nfiles:\n"
            " !windows::\n"
            "  \"$(sys.workdir)/inputs\" \n"
            "    handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_not_windows\",\n"
            "    copy_from => u_scp(\"/var/cfengine/masterfiles\"),\n"
            "    depth_search => u_recurse(\"inf\"),\n"
            "    classes => success(\"got_policy\");\n"
            "\n"
            "  windows::\n"
            "  \"$(sys.workdir)\\inputs\" \n"
            "    handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_windows\",\n"
            "    copy_from => u_scp(\"/var/cfengine/masterfiles\"),\n"
            "    depth_search => u_recurse(\"inf\"),\n"
            "    classes => success(\"got_policy\");\n\n"
            "\n"
            "     \"$(sys.workdir)\\bin-twin\\.\"\n"
            "          handle => \"cfe_internal_bootstrap_update_files_sys_workdir_bin_twin_windows\",\n"
            "         comment => \"Make sure we maintain a clone of the binaries and libraries for updating\",\n"
            "       copy_from => u_cp(\"$(sys.workdir)\\bin\\.\"),\n"
            "    depth_search => u_recurse(\"1\");\n"
            "\n"
            "\n"
            "\nprocesses:\n"
            "!windows.got_policy::\n"
            "\"cf-execd\" restart_class => \"start_exec\",\n"
            "                    handle => \"cfe_internal_bootstrap_update_processes_start_cf_execd\";\n"
            "am_policy_hub.got_policy::\n"
            "\"cf-serverd\" restart_class => \"start_server\",\n"
            "                      handle => \"cfe_internal_bootstrap_update_processes_start_cf_serverd\";\n\n"
            "\ncommands:\n"
            "start_exec.!windows::\n"
            "\"$(sys.cf_execd)\","
            " handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_execd_start\",\n"
            "classes => outcome(\"executor\");\n"
            "start_server::\n"
            "\"$(sys.cf_serverd)\"\n"
            "handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_serverd_start\",\n"
            "action => ifwin_bg,\n"
            "classes => outcome(\"server\");\n\n"
            "\nservices:\n"
            "windows.got_policy::\n"
            "\"CfengineNovaExec\"\n"
            "           handle => \"cfe_internal_bootstrap_update_services_windows_executor\",\n"
            "   service_policy => \"start\",\n"
            "   service_method => bootstart,\n"
            "   classes => outcome(\"executor\");\n\n"
            "reports:\n"
            "  bootstrap_mode.am_policy_hub::\n"
            "      \"This host assumes the role of policy distribution host\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_assume_policy_hub\";\n"
            "  bootstrap_mode.!am_policy_hub::\n"
            "      \"This autonomous node assumes the role of voluntary client\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_assume_voluntary_client\";\n"
            "  got_policy::      \" -> Updated local policy from policy server\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_got_policy\";\n"
            " !got_policy::      \" !! Failed to pull policy from policy server\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_did_not_get_policy\";\n"
            "  server_ok::      \" -> Started the server\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_started_serverd\";\n"
            " am_policy_hub.!server_ok::      \" !! Failed to start the server\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_serverd\";\n"
            "  executor_ok::      \" -> Started the scheduler\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_started_execd\";\n"
            " !executor_ok::      \" !! Did not start the scheduler\",\n"
            "           handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_execd\";\n"
            "}\n"
            "############################################\n"
            "body classes outcome(x)\n"
            "{\n"
            "promise_repaired => {\"$(x)_ok\"};\n"
            "}\n"
            "############################################\n"
            "body classes success(x)\n"
            "{\n"
            "promise_repaired => {\"$(x)\"};\n"
            "}\n"
            "############################################\n"
            "body perms u_p(p)\n"
            "{\n"
            "mode  => \"$(p)\";\n"
            "}\n"
            "#############################################\n"
            "body copy_from u_scp(from)\n"
            "{\n"
            "source      => \"$(from)\";\n"
            "compare     => \"digest\";\n"
            "trustkey    => \"true\";\n"
            "!am_policy_hub::\n"
            "servers => { \"$(sys.policy_hub)\" };\n"
            "}\n"
            "############################################\n"
            "body action u_background\n"
            "{\n"
            "background => \"true\";\n"
            "}\n"
            "############################################\n"
            "body depth_search u_recurse(d)\n"
            "{\n"
            "depth => \"$(d)\";\n"
            "exclude_dirs => { \"\\.svn\", \"\\.git\" };"
            "}\n"
            "############################################\n"
            "body service_method bootstart\n"
            "{\n"
            "service_autostart_policy => \"boot_time\";\n"
            "}\n"
            "############################################\n"
            "body action ifwin_bg\n"
            "{\n"
            "windows::\n"
            "background => \"true\";\n"
            "}\n"
            "############################################\n"
            "body copy_from u_cp(from)\n"
            "{\n"
            "source          => \"$(from)\";\n"
            "compare         => \"digest\";\n" "copy_backup     => \"false\";\n" "}\n" "\n");

    fclose(fout);

    if (cf_chmod(name, S_IRUSR | S_IWUSR) == -1)
    {
        CfOut(cf_error, "cf_chmod", "!! Failed setting permissions on bootstrap policy (%s)", name);
    }
}
Exemplo n.º 3
0
static void KeepKeyPromises(void)
{
    unsigned long err;
    RSA *pair;
    FILE *fp;
    struct stat statbuf;
    int fd;
    static char *passphrase = "Cfengine passphrase";
    const EVP_CIPHER *cipher;
    char vbuff[CF_BUFSIZE];

    NewScope("common");

    cipher = EVP_des_ede3_cbc();

    if (cfstat(CFPUBKEYFILE, &statbuf) != -1)
    {
        CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPUBKEYFILE);
        return;
    }

    if (cfstat(CFPRIVKEYFILE, &statbuf) != -1)
    {
        CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPRIVKEYFILE);
        return;
    }

    printf("Making a key pair for cfengine, please wait, this could take a minute...\n");

    pair = RSA_generate_key(2048, 35, NULL, NULL);

    if (pair == NULL)
    {
        err = ERR_get_error();
        CfOut(cf_error, "", "Unable to generate key: %s\n", ERR_reason_error_string(err));
        return;
    }

    if (DEBUG)
    {
        RSA_print_fp(stdout, pair, 0);
    }

    fd = open(CFPRIVKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (fd < 0)
    {
        CfOut(cf_error, "open", "Open %s failed: %s.", CFPRIVKEYFILE, strerror(errno));
        return;
    }

    if ((fp = fdopen(fd, "w")) == NULL)
    {
        CfOut(cf_error, "fdopen", "Couldn't open private key %s.", CFPRIVKEYFILE);
        close(fd);
        return;
    }

    CfOut(cf_verbose, "", "Writing private key to %s\n", CFPRIVKEYFILE);

    if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL))
    {
        err = ERR_get_error();
        CfOut(cf_error, "", "Couldn't write private key: %s\n", ERR_reason_error_string(err));
        return;
    }

    fclose(fp);

    fd = open(CFPUBKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (fd < 0)
    {
        CfOut(cf_error, "open", "Unable to open public key %s.", CFPUBKEYFILE);
        return;
    }

    if ((fp = fdopen(fd, "w")) == NULL)
    {
        CfOut(cf_error, "fdopen", "Open %s failed.", CFPUBKEYFILE);
        close(fd);
        return;
    }

    CfOut(cf_verbose, "", "Writing public key to %s\n", CFPUBKEYFILE);

    if (!PEM_write_RSAPublicKey(fp, pair))
    {
        err = ERR_get_error();
        CfOut(cf_error, "", "Unable to write public key: %s\n", ERR_reason_error_string(err));
        return;
    }

    fclose(fp);

    snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR);
    RAND_write_file(vbuff);
    cf_chmod(vbuff, 0644);
}
Exemplo n.º 4
0
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);
      }
   }
}
Exemplo n.º 5
0
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 */
   }
}
Exemplo n.º 6
0
void CreateFailSafe(char *name)
{
    FILE *fout;

    if ((fout = fopen(name, "w")) == NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Unable to write failsafe file! (%s)", name);
        return;
    }

    printf(" -> No policy failsafe discovered, assume temporary bootstrap vector\n");

    fprintf(fout,
            "################################################################################\n"
            "# THIS FILE REPRESENTS A FALL-BACK SOLUTION FOR THE PRIMARY FAILSAFE FILE.\n"
            "# IF THE PRIMARY FAILSAFE/UPDATE LOSES FUNCTIONALITY DUE TO MODIFICATIONS MADE\n" 
            "# BY THE USER, CFENGINE WILL RECOVER BY USING THIS FALL-BACK BOOTSTRAPPED FILE.\n"
            "# NEVER EDIT THIS FILE, YOU WILL HAVE TO LOG ON TO EVERY NODE MANAGED BY\n" 
            "# CFENGINE TO RECTIFY POTENTIAL ERRORS IF SOMETHING GOES WRONG.\n"
            "################################################################################\n"
            "\nbody common control\n"
            "{\n"
            " bundlesequence => { \"cfe_internal_update\" };\n"
            "}\n\n"
            "################################################################################\n"
            "\nbody agent control\n"
            "{\n"
            " skipidentify => \"true\";\n"
            "}\n\n"
            "################################################################################\n"
            "\nbundle agent cfe_internal_update\n"
            "{\n"
            " classes:\n\n"
            "  any::\n"
            "   \"have_ppkeys\"\n"
            "      expression => fileexists(\"$(sys.workdir)/ppkeys/localhost.pub\"),\n"
            "          handle => \"cfe_internal_bootstrap_update_classes_have_ppkeys\";\n"
            "   \"have_promises_cf\"\n"
            "      expression => fileexists(\"$(sys.workdir)/inputs/promises.cf\"),\n"
            "          handle => \"cfe_internal_bootstrap_update_classes_have_promises_cf\";\n"
            "\n#\n\n"
            " commands:\n\n"
            "  !have_ppkeys::\n"
            "   \"$(sys.cf_key)\"\n"
            "      handle => \"cfe_internal_bootstrap_update_commands_generate_keys\";\n"
            "\n#\n\n"
            " files:\n\n"
            "  !windows::\n"
            "   \"$(sys.workdir)/inputs\" \n"
            "            handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_not_windows\",\n"
#ifdef __MINGW32__
            "         copy_from => u_scp(\"/var/cfengine/masterfiles\"),\n"
#else
            "         copy_from => u_scp(\"%s/masterfiles\"),\n"
#endif /* !__MINGW32__ */
            "      depth_search => u_recurse(\"inf\"),\n"
            "           classes => repaired(\"got_policy\");\n"
            "\n"
            "  windows::\n"
            "   \"$(sys.workdir)\\inputs\" \n"
            "            handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_windows\",\n"
#ifdef __MINGW32__
            "         copy_from => u_scp(\"/var/cfengine/masterfiles\"),\n"
#else
            "         copy_from => u_scp(\"%s/masterfiles\"),\n"
#endif /* !__MINGW32__ */
            "      depth_search => u_recurse(\"inf\"),\n"
            "           classes => repaired(\"got_policy\");\n\n"
            "   \"$(sys.workdir)\\bin-twin\\.\"\n"
            "            handle => \"cfe_internal_bootstrap_update_files_sys_workdir_bin_twin_windows\",\n"
            "           comment => \"Make sure we maintain a clone of the binaries and libraries for updating\",\n"
            "         copy_from => u_cp(\"$(sys.workdir)\\bin\\.\"),\n"
            "      depth_search => u_recurse(\"1\");\n"
            "\n#\n\n"
            " processes:\n\n"
            "  !windows.got_policy::\n"
            "   \"cf-execd\" restart_class => \"start_exec\",\n"
            "                     handle => \"cfe_internal_bootstrap_update_processes_start_cf_execd\";\n"
            "  am_policy_hub.got_policy::\n"
            "   \"cf-serverd\" restart_class => \"start_server\",\n"
            "                       handle => \"cfe_internal_bootstrap_update_processes_start_cf_serverd\";\n"
            "\n#\n\n"
            " commands:\n\n"
            "  start_exec.!windows::\n"
            "   \"$(sys.cf_execd)\"\n"
            "       handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_execd_start\",\n"
            "      classes => repaired(\"executor_started\");\n"
            "  start_server::\n"
            "   \"$(sys.cf_serverd)\"\n"
            "       handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_serverd_start\",\n"
            "       action => ifwin_bg,\n"
            "      classes => repaired(\"server_started\");\n"
            "\n#\n\n"
            " services:\n\n"
            "  windows.got_policy::\n"
            "   \"CfengineNovaExec\"\n"
            "              handle => \"cfe_internal_bootstrap_update_services_windows_executor\",\n"
            "      service_policy => \"start\",\n"
            "      service_method => bootstart,\n"
            "             classes => repaired(\"executor_started\");\n"
            "\n#\n\n"
            " reports:\n\n"
            "  bootstrap_mode.am_policy_hub::\n"
            "   \"This host assumes the role of policy distribution host\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_assume_policy_hub\";\n"
            "  bootstrap_mode.!am_policy_hub::\n"
            "   \"This autonomous node assumes the role of voluntary client\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_assume_voluntary_client\";\n"
            "  got_policy::\n"
            "   \" -> Updated local policy from policy server\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_got_policy\";\n"
            "  !got_policy.!have_promises_cf::\n"
            "   \" !! Failed to copy policy from policy server at $(sys.policy_hub):/var/cfengine/masterfiles\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_did_not_get_policy\";\n"
            "  server_started::\n"
            "   \" -> Started the server\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_started_serverd\";\n"
            "  am_policy_hub.!server_started.!have_promises_cf::\n"
            "   \" !! Failed to start the server\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_serverd\";\n"
            "  executor_started::\n"
            "   \" -> Started the scheduler\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_started_execd\";\n"
            "  !executor_started.!have_promises_cf::\n"
            "   \" !! Did not start the scheduler\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_execd\";\n"
            "  !executor_started.have_promises_cf::\n"
            "   \" -> You are running a hard-coded failsafe. Please use the following command instead.\n"
            "    - 3.0.0: $(sys.cf_agent) -f $(sys.workdir)/inputs/failsafe/failsafe.cf\n"
            "    - 3.0.1: $(sys.cf_agent) -f $(sys.workdir)/inputs/update.cf\"\n"
            "      handle => \"cfe_internal_bootstrap_update_reports_run_another_failsafe_instead\";\n"
            "}\n\n"
            "############################################\n"
            "body classes repaired(x)\n"
            "{\n"
            "promise_repaired => {\"$(x)\"};\n"
            "}\n"
            "############################################\n"
            "body perms u_p(p)\n"
            "{\n"
            "mode  => \"$(p)\";\n"
            "}\n"
            "#############################################\n"
            "body copy_from u_scp(from)\n"
            "{\n"
            "source      => \"$(from)\";\n"
            "compare     => \"digest\";\n"
            "trustkey    => \"true\";\n"
            "!am_policy_hub::\n"
            "servers => { \"$(sys.policy_hub)\" };\n"
            "}\n"
            "############################################\n"
            "body action u_background\n"
            "{\n"
            "background => \"true\";\n"
            "}\n"
            "############################################\n"
            "body depth_search u_recurse(d)\n"
            "{\n"
            "depth => \"$(d)\";\n"
            "exclude_dirs => { \"\\.svn\", \"\\.git\" };"
            "}\n"
            "############################################\n"
            "body service_method bootstart\n"
            "{\n"
            "service_autostart_policy => \"boot_time\";\n"
            "}\n"
            "############################################\n"
            "body action ifwin_bg\n"
            "{\n"
            "windows::\n"
            "background => \"true\";\n"
            "}\n"
            "############################################\n"
            "body copy_from u_cp(from)\n"
            "{\n"
            "source          => \"$(from)\";\n"
#ifdef __MINGW32__
            "compare         => \"digest\";\n" "copy_backup     => \"false\";\n" "}\n" "\n");
#else
            "compare         => \"digest\";\n" "copy_backup     => \"false\";\n" "}\n" "\n", CFWORKDIR, CFWORKDIR);
#endif /* !__MINGW32__ */
    fclose(fout);

    if (cf_chmod(name, S_IRUSR | S_IWUSR) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "cf_chmod", "!! Failed setting permissions on bootstrap policy (%s)", name);
    }
}