static int CompareResult(char *filename, char *prev_file) { int i; unsigned char digest1[EVP_MAX_MD_SIZE + 1]; unsigned char digest2[EVP_MAX_MD_SIZE + 1]; int md_len1, md_len2; FILE *fp; int rtn = 0; CfOut(cf_verbose, "", "Comparing files %s with %s\n", prev_file, filename); if ((fp = fopen(prev_file, "r")) != NULL) { fclose(fp); md_len1 = FileChecksum(prev_file, digest1); md_len2 = FileChecksum(filename, digest2); if (md_len1 != md_len2) { rtn = 1; } else { for (i = 0; i < md_len1; i++) { if (digest1[i] != digest2[i]) { rtn = 1; break; } } } } else { /* no previous file */ rtn = 1; } if (!ThreadLock(cft_count)) { CfOut(cf_error, "", "!! Severe lock error when mailing in exec"); return 1; } /* replace old file with new*/ unlink(prev_file); if (!LinkOrCopy(filename, prev_file, true)) { CfOut(cf_inform, "", "Could not symlink or copy %s to %s", filename, prev_file); rtn = 1; } ThreadUnlock(cft_count); return (rtn); }
static int CompareResult(const char *filename, const char *prev_file) { Log(LOG_LEVEL_VERBOSE, "Comparing files %s with %s", prev_file, filename); int rtn = 0; FILE *fp = fopen(prev_file, "r"); if (fp) { fclose(fp); unsigned char digest1[EVP_MAX_MD_SIZE + 1]; int md_len1 = FileChecksum(prev_file, digest1); unsigned char digest2[EVP_MAX_MD_SIZE + 1]; int md_len2 = FileChecksum(filename, digest2); if (md_len1 != md_len2) { rtn = 1; } else { for (int i = 0; i < md_len1; i++) { if (digest1[i] != digest2[i]) { rtn = 1; break; } } } } else { /* no previous file */ rtn = 1; } if (!ThreadLock(cft_count)) { Log(LOG_LEVEL_ERR, "Severe lock error when mailing in exec"); return 1; } /* replace old file with new*/ unlink(prev_file); if (!LinkOrCopy(filename, prev_file, true)) { Log(LOG_LEVEL_INFO, "Could not symlink or copy %s to %s", filename, prev_file); rtn = 1; } ThreadUnlock(cft_count); return rtn; }
void PolicyHubUpdateKeys(const char *policy_server) { if (GetAmPolicyHub(CFWORKDIR) && NULL != PUBKEY) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; char dst_public_key_filename[CF_BUFSIZE] = ""; { char buffer[CF_HOSTKEY_STRING_SIZE]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(dst_public_key_filename, sizeof(dst_public_key_filename), "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(buffer, sizeof(buffer), digest, CF_DEFAULT_DIGEST, true)); MapName(dst_public_key_filename); } struct stat sb; if ((stat(dst_public_key_filename, &sb) == -1)) { char src_public_key_filename[CF_BUFSIZE] = ""; snprintf(src_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR); MapName(src_public_key_filename); // copy localhost.pub to root-HASH.pub on policy server if (!LinkOrCopy(src_public_key_filename, dst_public_key_filename, false)) { Log(LOG_LEVEL_ERR, "Unable to copy policy server's own public key from '%s' to '%s'", src_public_key_filename, dst_public_key_filename); } if (policy_server) { LastSaw(policy_server, digest, LAST_SEEN_ROLE_CONNECT); } } } }
static int CompareResult(const char *filename, const char *prev_file) { Log(LOG_LEVEL_VERBOSE, "Comparing files %s with %s", prev_file, filename); int rtn = 0; FILE *old_fp = safe_fopen(prev_file, "r"); FILE *new_fp = safe_fopen(filename, "r"); if (old_fp && new_fp) { const char *errptr; int erroffset; pcre_extra *regex_extra = NULL; // Match timestamps and remove them. Not Y21K safe! :-) pcre *regex = pcre_compile(LOGGING_TIMESTAMP_REGEX, PCRE_MULTILINE, &errptr, &erroffset, NULL); if (!regex) { UnexpectedError("Compiling regular expression failed"); rtn = 1; } else { regex_extra = pcre_study(regex, 0, &errptr); } while (regex) { char old_line[CF_BUFSIZE]; char new_line[CF_BUFSIZE]; char *old_msg = old_line; char *new_msg = new_line; if (CfReadLine(old_line, sizeof(old_line), old_fp) <= 0) { old_msg = NULL; } if (CfReadLine(new_line, sizeof(new_line), new_fp) <= 0) { new_msg = NULL; } if (!old_msg || !new_msg) { if (old_msg != new_msg) { rtn = 1; } break; } char *index; if (pcre_exec(regex, regex_extra, old_msg, strlen(old_msg), 0, 0, NULL, 0) >= 0) { index = strstr(old_msg, ": "); if (index != NULL) { old_msg = index + 2; } } if (pcre_exec(regex, regex_extra, new_msg, strlen(new_msg), 0, 0, NULL, 0) >= 0) { index = strstr(new_msg, ": "); if (index != NULL) { new_msg = index + 2; } } if (strcmp(old_msg, new_msg) != 0) { rtn = 1; break; } } if (regex_extra) { free(regex_extra); } free(regex); } else { /* no previous file */ rtn = 1; } if (old_fp) { fclose(old_fp); } if (new_fp) { fclose(new_fp); } if (!ThreadLock(cft_count)) { Log(LOG_LEVEL_ERR, "Severe lock error when mailing in exec"); return 1; } /* replace old file with new*/ unlink(prev_file); if (!LinkOrCopy(filename, prev_file, true)) { Log(LOG_LEVEL_INFO, "Could not symlink or copy '%s' to '%s'", filename, prev_file); rtn = 1; } ThreadUnlock(cft_count); return rtn; }
/** * @return true the error is not so severe that we must stop */ bool LoadSecretKeys(const char *policy_server) { static char *passphrase = "Cfengine passphrase"; { FILE *fp = fopen(PrivateKeyFile(GetWorkDir()), "r"); if (!fp) { Log(LOG_LEVEL_INFO, "Couldn't find a private key at '%s', use cf-key to get one. (fopen: %s)", PrivateKeyFile(GetWorkDir()), GetErrorStr()); return true; } if ((PRIVKEY = PEM_read_RSAPrivateKey(fp, (RSA **) NULL, NULL, passphrase)) == NULL) { unsigned long err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Error reading private key. (PEM_read_RSAPrivateKey: %s)", ERR_reason_error_string(err)); PRIVKEY = NULL; fclose(fp); return true; } fclose(fp); Log(LOG_LEVEL_VERBOSE, "Loaded private key at '%s'", PrivateKeyFile(GetWorkDir())); } { FILE *fp = fopen(PublicKeyFile(GetWorkDir()), "r"); if (!fp) { Log(LOG_LEVEL_ERR, "Couldn't find a public key at '%s', use cf-key to get one (fopen: %s)", PublicKeyFile(GetWorkDir()), GetErrorStr()); return true; } if ((PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL) { unsigned long err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Error reading public key at '%s'. (PEM_read_RSAPublicKey: %s)", PublicKeyFile(GetWorkDir()), ERR_reason_error_string(err)); PUBKEY = NULL; fclose(fp); return true; } Log(LOG_LEVEL_VERBOSE, "Loaded public key '%s'", PublicKeyFile(GetWorkDir())); fclose(fp); } if ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e))) { Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd"); return false; } if (GetAmPolicyHub(CFWORKDIR)) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; char dst_public_key_filename[CF_BUFSIZE] = ""; { char buffer[EVP_MAX_MD_SIZE * 4]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(dst_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(CF_DEFAULT_DIGEST, digest, buffer)); MapName(dst_public_key_filename); } struct stat sb; if ((stat(dst_public_key_filename, &sb) == -1)) { char src_public_key_filename[CF_BUFSIZE] = ""; snprintf(src_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR); MapName(src_public_key_filename); // copy localhost.pub to root-HASH.pub on policy server if (!LinkOrCopy(src_public_key_filename, dst_public_key_filename, false)) { Log(LOG_LEVEL_ERR, "Unable to copy policy server's own public key from '%s' to '%s'", src_public_key_filename, dst_public_key_filename); } if (policy_server) { LastSaw(policy_server, digest, LAST_SEEN_ROLE_CONNECT); } } } return true; }
void LoadSecretKeys() { FILE *fp; static char *passphrase = "Cfengine passphrase", name[CF_BUFSIZE], source[CF_BUFSIZE]; char guard[CF_MAXVARSIZE]; unsigned char digest[EVP_MAX_MD_SIZE + 1]; unsigned long err; struct stat sb; if ((fp = fopen(PrivateKeyFile(), "r")) == NULL) { CfOut(OUTPUT_LEVEL_INFORM, "fopen", "Couldn't find a private key (%s) - use cf-key to get one", PrivateKeyFile()); return; } if ((PRIVKEY = PEM_read_RSAPrivateKey(fp, (RSA **) NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err)); PRIVKEY = NULL; fclose(fp); return; } fclose(fp); CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded private key %s\n", PrivateKeyFile()); if ((fp = fopen(PublicKeyFile(), "r")) == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "fopen", "Couldn't find a public key (%s) - use cf-key to get one", PublicKeyFile()); return; } if ((PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); CfOut(OUTPUT_LEVEL_ERROR, "PEM_read", "Error reading Private Key = %s\n", ERR_reason_error_string(err)); PUBKEY = NULL; fclose(fp); return; } CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Loaded public key %s\n", PublicKeyFile()); fclose(fp); if ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e))) { FatalError("RSA Exponent too small or not odd"); } if (NULL_OR_EMPTY(POLICY_SERVER)) { snprintf(name, CF_MAXVARSIZE - 1, "%s%cpolicy_server.dat", CFWORKDIR, FILE_SEPARATOR); if ((fp = fopen(name, "r")) != NULL) { if (fscanf(fp, "%4095s", POLICY_SERVER) != 1) { CfDebug("Couldn't read string from policy_server.dat"); } fclose(fp); } } /* Check that we have our own SHA key form of the key in the IP on the hub */ char buffer[EVP_MAX_MD_SIZE * 4]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(name, CF_MAXVARSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(CF_DEFAULT_DIGEST, digest, buffer)); MapName(name); snprintf(source, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR); MapName(source); // During bootstrap we need the pre-registered IP/hash pair on the hub snprintf(guard, sizeof(guard), "%s/state/am_policy_hub", CFWORKDIR); MapName(guard); // need to use cf_stat if ((stat(name, &sb) == -1) && (stat(guard, &sb) != -1)) // copy localhost.pub to root-HASH.pub on policy server { LastSaw(POLICY_SERVER, digest, LAST_SEEN_ROLE_CONNECT); if (!LinkOrCopy(source, name, false)) { CfOut(OUTPUT_LEVEL_ERROR, "", " -> Unable to clone server's key file as %s\n", name); } } }
static bool CompareResultEqualOrFiltered(const ExecConfig *config, const char *filename, const char *prev_file) { Log(LOG_LEVEL_VERBOSE, "Comparing files %s with %s", prev_file, filename); bool rtn = true; FILE *old_fp = safe_fopen(prev_file, "r"); FILE *new_fp = safe_fopen(filename, "r"); if (new_fp) { const char *errptr; int erroffset; pcre_extra *regex_extra = NULL; // Match timestamps and remove them. Not Y21K safe! :-) pcre *regex = pcre_compile(LOGGING_TIMESTAMP_REGEX, PCRE_MULTILINE, &errptr, &erroffset, NULL); if (!regex) { UnexpectedError("Compiling regular expression failed"); rtn = false; } else { regex_extra = pcre_study(regex, 0, &errptr); } size_t old_line_size = CF_BUFSIZE; char *old_line = xmalloc(old_line_size); size_t new_line_size = CF_BUFSIZE; char *new_line = xmalloc(new_line_size); bool any_new_msg_present = false; while (regex) { char *old_msg = NULL; if (old_fp) { while (CfReadLine(&old_line, &old_line_size, old_fp) >= 0) { if (!LineIsFiltered(config, old_line)) { old_msg = old_line; break; } } } char *new_msg = NULL; while (CfReadLine(&new_line, &new_line_size, new_fp) >= 0) { if (!LineIsFiltered(config, new_line)) { any_new_msg_present = true; new_msg = new_line; break; } } if (!old_msg || !new_msg) { // Return difference in most cases, when there is a new // message line, but if there isn't one, return equal, even // if strictly speaking they aren't, since we don't want to // send an empty email. if (any_new_msg_present && old_msg != new_msg) { rtn = false; } break; } // Remove timestamps from lines before comparison. char *index; if (pcre_exec(regex, regex_extra, old_msg, strlen(old_msg), 0, 0, NULL, 0) >= 0) { index = strstr(old_msg, ": "); if (index != NULL) { old_msg = index + 2; } } if (pcre_exec(regex, regex_extra, new_msg, strlen(new_msg), 0, 0, NULL, 0) >= 0) { index = strstr(new_msg, ": "); if (index != NULL) { new_msg = index + 2; } } if (strcmp(old_msg, new_msg) != 0) { rtn = false; break; } } free(old_line); free(new_line); if (regex_extra) { free(regex_extra); } pcre_free(regex); } else { /* no previous file */ rtn = false; } if (old_fp) { fclose(old_fp); } if (new_fp) { fclose(new_fp); } if (!ThreadLock(cft_count)) { Log(LOG_LEVEL_ERR, "Severe lock error when mailing in exec"); return 1; } /* replace old file with new*/ unlink(prev_file); if (!LinkOrCopy(filename, prev_file, true)) { Log(LOG_LEVEL_INFO, "Could not symlink or copy '%s' to '%s'", filename, prev_file); rtn = false; } ThreadUnlock(cft_count); return rtn; }