int CompareFileHashes(const char *file1, const char *file2, struct stat *sstat, struct stat *dstat, FileCopy fc, AgentConnection *conn) { unsigned char digest1[EVP_MAX_MD_SIZE + 1] = { 0 }, digest2[EVP_MAX_MD_SIZE + 1] = { 0 }; int i; if (sstat->st_size != dstat->st_size) { Log(LOG_LEVEL_DEBUG, "File sizes differ, no need to compute checksum"); return true; } if (conn == NULL) { HashFile(file1, digest1, CF_DEFAULT_DIGEST); HashFile(file2, digest2, CF_DEFAULT_DIGEST); for (i = 0; i < EVP_MAX_MD_SIZE; i++) { if (digest1[i] != digest2[i]) { return true; } } Log(LOG_LEVEL_DEBUG, "Files were identical"); return false; /* only if files are identical */ } else { assert(fc.servers && strcmp(RlistScalarValue(fc.servers), "localhost")); return CompareHashNet(file1, file2, fc.encrypt, conn); /* client.c */ } }
int CompareFileHashes(char *file1, char *file2, struct stat *sstat, struct stat *dstat, Attributes attr, Promise *pp) { unsigned char digest1[EVP_MAX_MD_SIZE + 1] = { 0 }, digest2[EVP_MAX_MD_SIZE + 1] = { 0 }; int i; CfDebug("CompareFileHashes(%s,%s)\n", file1, file2); if (sstat->st_size != dstat->st_size) { CfDebug("File sizes differ, no need to compute checksum\n"); return true; } if ((attr.copy.servers == NULL) || (strcmp(attr.copy.servers->item, "localhost") == 0)) { HashFile(file1, digest1, CF_DEFAULT_DIGEST); HashFile(file2, digest2, CF_DEFAULT_DIGEST); for (i = 0; i < EVP_MAX_MD_SIZE; i++) { if (digest1[i] != digest2[i]) { return true; } } CfDebug("Files were identical\n"); return false; /* only if files are identical */ } else { return CompareHashNet(file1, file2, attr, pp); /* client.c */ } }
HRESULT CPkcs7::VerifyRawFile(HANDLE hFile, LPCWSTR wszFile, HCRYPTPROV hprov, ALG_ID algidHash) // The twin to HashAndSetRawFile. // // Verify that a) this SignedData contains // an IndirectDataContent of type 'raw file', and b) the hash found inside // said IndirectDataContent matches the hash of the file indicated here as // EITHER wszFileName OR hFile. // // Note that we do NOT compare the link info in the IndirectDataContent // to wszFileName in any way. Note also that this does not do signature // checking; that instead is done on SignerInfos found in this SignedData. // // So, the actual verification process is two step: a) verify that the hash of the // current file is what is expected (call this function); and b) verify that // the signature holds (call IAmSigned::Verify in a SignerInfo). // // // Return values: // // S_OK It all matched // // E_FAIL Content isn't an IndirectDataContent of type raw file // // NTE_BAD_SIGNATURE // The hash did not match { PKCS7_FILEDATA rf; m_pworld->Init(rf); HRESULT hr = get_ContentRawFile(&rf); if (hr == S_OK) { if (algidHash == 0) { algidHash = rf.digest.algid; } DIGESTINFO digest; if (hFile != INVALID_HANDLE_VALUE) hr = HashFile(hFile, hprov, algidHash, digest); else hr = HashFile(wszFile, hprov, algidHash, digest); if (hr == S_OK) { if (IsEqual(digest, rf.digest)) hr = S_OK; else hr = NTE_BAD_SIGNATURE; } FreeTaskMem(rf); } else hr = E_FAIL; return hr; }
bool CryptManager::Verify( RageFileBasic &file, RString sSignature, RString sPublicKey ) { RSAKeyWrapper key; RString sError; if( !key.Load(sPublicKey, sError) ) { LOG->Warn( "Error loading RSA key: %s", sError.c_str() ); return false; } int iHash = register_hash( &sha1_desc ); ASSERT( iHash >= 0 ); unsigned char buf_hash[20]; HashFile( file, buf_hash, iHash ); int iMatch; int iRet = rsa_verify_hash_ex( (const unsigned char *) sSignature.data(), sSignature.size(), buf_hash, sizeof(buf_hash), LTC_PKCS_1_EMSA, iHash, 0, &iMatch, &key.m_Key ); if( iRet != CRYPT_OK ) { LOG->Warn( "Verify(%s) failed: %s", file.GetDisplayPath().c_str(), error_to_string(iRet) ); return false; } if( !iMatch ) { LOG->Warn( "Verify(%s) failed: signature mismatch", file.GetDisplayPath().c_str() ); return false; } return true; }
bool Digestor::Sha1File(const std::string &path, std::string *hash_hex) { ByteArray hash; bool ok = HashFile(path, HASH_SHA1, hash); if (ok) *hash_hex = hash.toHexStr(); return ok; }
std::string Digestor::MD5File(const std::string &path) { assert (!path.empty()); ByteArray res; if (HashFile(path, HASH_MD5, res) == false) return ""; return res.toHexStr(); }
void UManifest::GenerateManifest(QDomDocument* dom, QDomElement root, QString dir) { QDomElement folders = dom->createElement("Folders"); root.appendChild(folders); QDomElement files = dom->createElement("Files"); root.appendChild(files); QDirIterator it(dir); while (it.hasNext()) { QString filePath = it.next(); QFileInfo fi(filePath); if (fi.fileName() == "UnrealManifest.exe" || fi.fileName() == "ReleaseNotes.xml" || fi.fileName() == "GameManifest.xml" ||(fi.fileName().startsWith("Qt5") && fi.fileName().endsWith(".dll"))) { continue; } if (QDir(filePath).exists()) { if (!filePath.endsWith(".")) { QDomElement folder = dom->createElement("FolderProperties"); folder.setAttribute("FolderName", fi.fileName()); root.appendChild(folder); GenerateManifest(dom, folder, filePath); } } else { QDomElement e = dom->createElement("FileProperties"); QString fileHash = HashFile(filePath); if (fileHash.length() > 0) { e.setAttribute("FileName", fi.fileName()); e.setAttribute("Size", fi.size()); e.setAttribute("md5", fileHash); ui->releaseNotes->append(filePath + " : " + fileHash); } else { e.setTagName("EmptyFile"); } files.appendChild(e); } } }
void read_hash(const char *path) { int total_read; unsigned char hash[SHA_DIGEST_LENGTH]; if ((total_read = HashFile(path, hash, HASHED_SEGMENT)) > -1) { for (int i = 0; i < SHA_DIGEST_LENGTH; i++) printf("%02x", hash[i]); printf(" in %d bytes", total_read); printf("\n"); } else { printf("Failed to read, got -1"); } }
HRESULT CPkcs7::HashAndSetRawFile(HANDLE hFile, LPCWSTR wszFile, HCRYPTPROV hprov, ALG_ID algidHash) // Set the content to be, indirectly, the indicated raw file, using the indicated // hash algorithm. // { PKCS7_FILEDATA rf; m_pworld->Init(rf); if (wszFile) { rf.link.tag = CERT_LINK_TYPE_FILE; rf.link.wszFile = (LPWSTR)wszFile; } else rf.link.tag = CERT_LINK_TYPE_NONE; HRESULT hr = S_OK; if (hFile != INVALID_HANDLE_VALUE) hr = HashFile(hFile, hprov, algidHash, rf.digest); else hr = HashFile(wszFile, hprov, algidHash, rf.digest); if (hr == S_OK) { hr = put_ContentRawFile(&rf); } #ifdef _DEBUG if (hr == S_OK) { GOOD(VerifyRawFile(hFile, wszFile, hprov, algidHash)); } #endif return hr; }
RString CryptManager::GetMD5ForFile( RString fn ) { RageFile file; if( !file.Open( fn, RageFile::READ ) ) { LOG->Warn( "GetMD5: Failed to open file '%s'", fn.c_str() ); return RString(); } int iHash = register_hash( &md5_desc ); ASSERT( iHash >= 0 ); unsigned char digest[16]; HashFile( file, digest, iHash ); return RString( (const char *) digest, sizeof(digest) ); }
bool CryptManager::Sign( RString sPath, RString &sSignatureOut, RString sPrivKey ) { if( !IsAFile(sPath) ) { LOG->Trace( "SignFileToFile: \"%s\" doesn't exist", sPath.c_str() ); return false; } RageFile file; if( !file.Open(sPath) ) { LOG->Warn( "SignFileToFile: open(%s) failed: %s", sPath.c_str(), file.GetError().c_str() ); return false; } RSAKeyWrapper key; RString sError; if( !key.Load(sPrivKey, sError) ) { LOG->Warn( "Error loading RSA key: %s", sError.c_str() ); return false; } int iHash = register_hash( &sha1_desc ); ASSERT( iHash >= 0 ); unsigned char buf_hash[20]; if( !HashFile(file, buf_hash, iHash) ) return false; unsigned char signature[256]; unsigned long signature_len = sizeof(signature); int iRet = rsa_sign_hash_ex( buf_hash, sizeof(buf_hash), signature, &signature_len, LTC_PKCS_1_V1_5, &g_pPRNG->m_PRNG, g_pPRNG->m_iPRNG, iHash, 0, &key.m_Key); if( iRet != CRYPT_OK ) { LOG->Warn( "SignFileToFile error: %s", error_to_string(iRet) ); return false; } sSignatureOut.assign( (const char *) signature, signature_len ); return true; }
int main(int argc, char* argv[]) { std::cout<<"foo"<<std::endl; //CHHashFileVSalted HashFile(16, 0, CHHASHFILESALTED_SALT_IS_FIRST, CHHASHFILESALTED_HEX_SALT); CHHashFileVSalted HashFile(16, 0, CHHASHFILESALTED_HASH_IS_FIRST, CHHASHFILESALTED_LITERAL_SALT); if (argc != 2) { printf("Call it with the file name!\n"); exit(1); } HashFile.OpenHashFile(argv[1]); std::cout<<(int)HashFile.GetTotalHashCount(); }
void CompareLocalHash(ServerConnectionState *conn, char *sendbuffer, char *recvbuffer) { unsigned char digest1[EVP_MAX_MD_SIZE + 1], digest2[EVP_MAX_MD_SIZE + 1]; char filename[CF_BUFSIZE], rfilename[CF_BUFSIZE]; char *sp; int i; /* TODO - when safe change this proto string to sha2 */ sscanf(recvbuffer, "MD5 %[^\n]", rfilename); sp = recvbuffer + strlen(recvbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { digest1[i] = *sp++; } memset(sendbuffer, 0, CF_BUFSIZE); TranslatePath(filename, rfilename); HashFile(filename, digest2, CF_DEFAULT_DIGEST); if ((HashesMatch(digest1, digest2, CF_DEFAULT_DIGEST)) || (HashesMatch(digest1, digest2, HASH_METHOD_MD5))) { sprintf(sendbuffer, "%s", CFD_FALSE); Log(LOG_LEVEL_DEBUG, "Hashes matched ok"); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); } else { sprintf(sendbuffer, "%s", CFD_TRUE); Log(LOG_LEVEL_DEBUG, "Hashes didn't match"); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); } }
static void PrependAuditFile(char *file) { struct stat statbuf; if ((AUDITPTR = (struct Audit *)malloc(sizeof(struct Audit))) == NULL) { FatalError("Memory allocation failure in PrependAuditFile"); } if (cfstat(file,&statbuf) == -1) { /* shouldn't happen */ return; } HashFile(file,AUDITPTR->digest,CF_DEFAULT_DIGEST); AUDITPTR->next = VAUDIT; AUDITPTR->filename = strdup(file); AUDITPTR->date = strdup(cf_ctime(&statbuf.st_mtime)); Chop(AUDITPTR->date); AUDITPTR->version = NULL; VAUDIT = AUDITPTR; }
int CheckScriptIntegrity(char *ScriptPath) { STREAM *S; char *Tempstr=NULL, *Token=NULL, *Hash=NULL, *FileHash=NULL, *ptr; int result, len; if (! ScriptPath) return(FALSE); if (! (Settings.Flags & FLAG_CHECK_SCRIPTS)) return(TRUE); S=STREAMOpenFile(Settings.ScriptHashFile,SF_RDONLY); if (S) { Tempstr=STREAMReadLine(Tempstr,S); while (Tempstr) { StripTrailingWhitespace(Tempstr); ptr=GetToken(Tempstr," ",&Token,0); while (ptr && isspace(*ptr)) ptr++; if (ptr && (strcmp(ptr,ScriptPath)==0)) { Hash=CopyStr(Hash,Token); len=StrLen(Hash); switch (len) { case 32: //MD5 HashFile(&FileHash, "md5", ScriptPath, ENCODE_HEX); break; case 40: //SHA1 HashFile(&FileHash, "sha1", ScriptPath, ENCODE_HEX); break; case 64: //SHA256 HashFile(&FileHash, "sha256", ScriptPath, ENCODE_HEX); break; case 128: //SHA512 HashFile(&FileHash, "sha512", ScriptPath, ENCODE_HEX); break; } } Tempstr=STREAMReadLine(Tempstr,S); } STREAMClose(S); } if (StrLen(FileHash) && StrLen(Hash) && (strcmp(FileHash,Hash)==0) ) result=TRUE; else { LogToFile(Settings.LogPath,"ERROR: Not running script '%s'. Script failed integrity check.",ScriptPath); result=FALSE; } DestroyString(FileHash); DestroyString(Tempstr); DestroyString(Token); DestroyString(Hash); return(result); }
int CompareHashNet(const char *file1, const char *file2, bool encrypt, AgentConnection *conn) { unsigned char d[EVP_MAX_MD_SIZE + 1]; char *sp, sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], in[CF_BUFSIZE], out[CF_BUFSIZE]; int i, tosend, cipherlen; HashFile(file2, d, CF_DEFAULT_DIGEST); memset(recvbuffer, 0, CF_BUFSIZE); /* We encrypt only for CLASSIC protocol. The TLS protocol is always over * encrypted layer, so it does not support encrypted (S*) commands. */ encrypt = encrypt && conn->conn_info->protocol == CF_PROTOCOL_CLASSIC; if (encrypt) { snprintf(in, CF_BUFSIZE, "MD5 %s", file1); sp = in + strlen(in) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN); snprintf(sendbuffer, CF_BUFSIZE, "SMD5 %d", cipherlen); memcpy(sendbuffer + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer, CF_BUFSIZE, "MD5 %s", file1); sp = sendbuffer + strlen(sendbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } tosend = strlen(sendbuffer) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN; } if (SendTransaction(conn->conn_info, sendbuffer, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Failed send. (SendTransaction: %s)", GetErrorStr()); return false; } if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { /* TODO mark connection in the cache as closed. */ Log(LOG_LEVEL_ERR, "Failed receive. (ReceiveTransaction: %s)", GetErrorStr()); Log(LOG_LEVEL_VERBOSE, "No answer from host, assuming checksum ok to avoid remote copy for now..."); return false; } if (strcmp(CFD_TRUE, recvbuffer) == 0) { return true; /* mismatch */ } else { return false; } /* Not reached */ }
bool Digestor::Sha512File(const std::string &path, ByteArray &hash) { return HashFile(path, HASH_SHA512, hash); }
int CHashManager::HashPath(char *pszBasePath, char *pszFileSpec) { recursivesafe long lHandle = 0; recursivesafe long lSearcherHandle = 0; recursivesafe finddata fdInfo; recursivesafe char szFull[RH_MAX_PATH]; recursivesafe char szAll[RH_MAX_PATH]; if(pszBasePath == NULL) return RH_INVALID_PATH; if(pszFileSpec == NULL) return RH_INVALID_PATH; fmtPath(pszBasePath); fmtPath(pszFileSpec); if(strlen(pszBasePath) == 0) getcwd(pszBasePath, RH_MAX_PATH); fileonly(pszFileSpec); strcpy(szAll, pszBasePath); catdirsep(szAll); strcat(szAll, SZ_DIR_ALL); #ifdef RH_DEBUG printf("Function HashPath: pszBasePath=%s, pszFileSpec=%s", pszBasePath, pszFileSpec); printf(CPS_NEWLINE); printf("Function HashPath: szAll=%s", szAll); printf(CPS_NEWLINE); #endif ////////////////////////////////////////////////////////////////////////// // Start directory enumeration code lSearcherHandle = findfirst(szAll, &fdInfo); while(1) { if(fdInfo.attrib & _A_SUBDIR) { if((ispathnav(fdInfo.name) == false) && (m_bRecursive)) { if(chdir(fdInfo.name) == 0) { getcwd(szFull, RH_MAX_PATH); #ifdef RH_DEBUG printf("Opening new scan path: %s, filemask: %s", szFull, pszFileSpec); printf(CPS_NEWLINE); #endif HashPath(szFull, pszFileSpec); chdir(SZ_LEVEL_UP); } } } if(findnext(lSearcherHandle, &fdInfo) != 0) break; } findclose(lSearcherHandle); lSearcherHandle = 0; // End directory enumeration code ////////////////////////////////////////////////////////////////////////// memset(&fdInfo, 0, sizeof(finddata)); lHandle = findfirst(pszFileSpec, &fdInfo); if(lHandle == EINVAL) return RH_INVALID_PATH; if(lHandle == ENOENT) return RH_NO_PATTERN_MATCH; if(lHandle == -1) return RH_CANNOT_OPEN_FILE; while(1) { if(fdInfo.attrib & _A_SUBDIR) { // Don't process directories here } else { if(m_bFullPath) { fullpath(szFull, fdInfo.name, RH_MAX_PATH); HashFile(szFull); } else { HashFile(fdInfo.name); } printf(CPS_NEWLINE); } if(findnext(lHandle, &fdInfo) != 0) break; } findclose(lHandle); lHandle = 0; return RH_SUCCESS; }
int CompareHashNet(char *file1, char *file2, bool encrypt, AgentConnection *conn) { static unsigned char d[EVP_MAX_MD_SIZE + 1]; char *sp, sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], in[CF_BUFSIZE], out[CF_BUFSIZE]; int i, tosend, cipherlen; HashFile(file2, d, CF_DEFAULT_DIGEST); memset(recvbuffer, 0, CF_BUFSIZE); if (encrypt) { snprintf(in, CF_BUFSIZE, "MD5 %s", file1); sp = in + strlen(in) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN); snprintf(sendbuffer, CF_BUFSIZE, "SMD5 %d", cipherlen); memcpy(sendbuffer + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer, CF_BUFSIZE, "MD5 %s", file1); sp = sendbuffer + strlen(sendbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } tosend = strlen(sendbuffer) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN; } if (SendTransaction(conn->sd, sendbuffer, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Failed send. (SendTransaction: %s)", GetErrorStr()); return false; } if (ReceiveTransaction(conn->sd, recvbuffer, NULL) == -1) { Log(LOG_LEVEL_ERR, "Failed receive. (ReceiveTransaction: %s)", GetErrorStr()); Log(LOG_LEVEL_VERBOSE, "No answer from host, assuming checksum ok to avoid remote copy for now..."); return false; } if (strcmp(CFD_TRUE, recvbuffer) == 0) { return true; /* mismatch */ } else { return false; } /* Not reached */ }
///------------------------------------------------------------------------------------------------- /// Scan a single file. Everything that applies to ms_scan also applies to this function. If /// you know the type of the file, set the type paramter to one of TYPE_AUDIO, TYPE_VIDEO, or /// TYPE_IMAGE. Set it to TYPE_UNKNOWN to have it determined automatically. /// /// @author Andy Grundman /// @date 03/15/2011 /// /// @param [in,out] s If non-null, the. /// @param full_path Full pathname of the full file. /// /// ### remarks . ///------------------------------------------------------------------------------------------------- void ms_scan_file(MediaScan *s, const char *full_path, enum media_type type) { MediaScanError *e = NULL; MediaScanResult *r = NULL; int ret; uint32_t hash; int mtime = 0; uint64_t size = 0; DBT key, data; char tmp_full_path[MAX_PATH_STR_LEN]; #ifdef WIN32 char *ext = strrchr(full_path, '.'); #endif if (s == NULL) { ms_errno = MSENO_NULLSCANOBJ; LOG_ERROR("MediaScan = NULL, aborting scan\n"); return; } if (s->on_result == NULL) { ms_errno = MSENO_NORESULTCALLBACK; LOG_ERROR("Result callback not set, aborting scan\n"); return; } #if (defined(__APPLE__) && defined(__MACH__)) if (isAlias(full_path)) { LOG_INFO("File %s is a mac alias\n", full_path); // Check if this file is a shortcut and if so resolve it if (!CheckMacAlias(full_path, tmp_full_path)) { LOG_ERROR("Failure to follow symlink or alias, skipping file\n"); return; } } else { strcpy(tmp_full_path, full_path); } #elif defined(__unix__) || defined(__unix) if (isAlias(full_path)) { LOG_INFO("File %s is a unix symlink\n", full_path); // Check if this file is a shortcut and if so resolve it FollowLink(full_path, tmp_full_path); } else { strcpy(tmp_full_path, full_path); } #elif defined(WIN32) if (strcasecmp(ext, ".lnk") == 0) { // Check if this file is a shortcut and if so resolve it parse_lnk(full_path, tmp_full_path, MAX_PATH_STR_LEN); if (PathIsDirectory(tmp_full_path)) return; } else { strcpy(tmp_full_path, full_path); } #endif // Check if the file has been recently scanned hash = HashFile(tmp_full_path, &mtime, &size); // Skip 0-byte files if (unlikely(size == 0)) { LOG_WARN("Skipping 0-byte file: %s\n", tmp_full_path); return; } // Setup DBT values memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); key.data = (char *)full_path; key.size = strlen(full_path) + 1; data.data = &hash; data.size = sizeof(uint32_t); if ((s->flags & MS_RESCAN) || (s->flags & MS_FULL_SCAN)) { // s->dbp will be null if this function is called directly, if not check if this file is // already scanned. if (s->dbp != NULL) { // DB_GET_BOTH will only return OK if both key and data match, this avoids the need to check // the returned data against hash int ret = s->dbp->get(s->dbp, NULL, &key, &data, DB_GET_BOTH); if (ret != DB_NOTFOUND) { // LOG_INFO("File %s already scanned, skipping\n", tmp_full_path); return; } } } LOG_INFO("Scanning file %s\n", tmp_full_path); if (type == TYPE_UNKNOWN || type == TYPE_LNK) { // auto-detect type type = _should_scan(s, tmp_full_path); if (!type) { if (s->on_error) { ms_errno = MSENO_SCANERROR; e = error_create(tmp_full_path, MS_ERROR_TYPE_UNKNOWN, "Unrecognized file extension"); send_error(s, e); return; } } } r = result_create(s); if (r == NULL) return; r->type = type; r->path = strdup(full_path); if (result_scan(r)) { // These were determined by HashFile r->mtime = mtime; r->size = size; r->hash = hash; // Store path -> hash data in cache if (s->dbp != NULL) { memset(&data, 0, sizeof(DBT)); data.data = &hash; data.size = sizeof(uint32_t); ret = s->dbp->put(s->dbp, NULL, &key, &data, 0); if (ret != 0) { s->dbp->err(s->dbp, ret, "Cache store failed: %s", db_strerror(ret)); } } send_result(s, r); } else { if (s->on_error && r->error) { // Copy the error, because the original will be cleaned up by result_destroy below MediaScanError *ecopy = error_copy(r->error); send_error(s, ecopy); } result_destroy(r); } } /* ms_scan_file() */
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files) { unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; char hashbuffer[CF_HOSTKEY_STRING_SIZE] = { 0 }; char hashprintbuffer[CF_BUFSIZE] = { 0 }; HashFile(policy_file, digest, CF_DEFAULT_DIGEST); snprintf(hashprintbuffer, CF_BUFSIZE - 1, "{checksum}%s", HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, CF_DEFAULT_DIGEST, true)); Log(LOG_LEVEL_DEBUG, "Hashed policy file %s to %s", policy_file, hashprintbuffer); if (StringSetContains(parsed_files_and_checksums, policy_file)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate policy file %s", policy_file); return NULL; } else if (StringSetContains(parsed_files_and_checksums, hashprintbuffer)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate (detected by hash) policy file %s", policy_file); return NULL; } else { Log(LOG_LEVEL_DEBUG, "Loading policy file %s", policy_file); } Policy *policy = Cf3ParseFile(config, policy_file); // we keep the checksum and the policy file name to help debugging StringSetAdd(parsed_files_and_checksums, xstrdup(policy_file)); StringSetAdd(parsed_files_and_checksums, xstrdup(hashprintbuffer)); if (policy) { Seq *errors = SeqNew(10, free); if (!PolicyCheckPartial(policy, errors)) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); SeqDestroy(errors); StringSetAdd(failed_files, xstrdup(policy_file)); PolicyDestroy(policy); return NULL; } SeqDestroy(errors); } else { StringSetAdd(failed_files, xstrdup(policy_file)); return NULL; } PolicyResolve(ctx, policy, config); DataType def_inputs_type = CF_DATA_TYPE_NONE; VarRef *inputs_ref = VarRefParse("def.augment_inputs"); const void *def_inputs = EvalContextVariableGet(ctx, inputs_ref, &def_inputs_type); VarRefDestroy(inputs_ref); if (RVAL_TYPE_CONTAINER == DataTypeToRvalType(def_inputs_type) && NULL != def_inputs) { const JsonElement *el; JsonIterator iter = JsonIteratorInit((JsonElement*) def_inputs); while ((el = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true))) { char *input = JsonPrimitiveToString(el); Log(LOG_LEVEL_VERBOSE, "Loading augments from def.augment_inputs: %s", input); Rlist* inputs_rlist = NULL; RlistAppendScalar(&inputs_rlist, input); Policy *aux_policy = LoadPolicyInputFiles(ctx, config, inputs_rlist, parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } RlistDestroy(inputs_rlist); free(input); } } Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control"); Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control"); if (body_common_control) { Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } if (body_file_control) { Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } return policy; }
static PromiseResult RenderTemplateMustache(EvalContext *ctx, const Promise *pp, Attributes a, EditContext *edcontext) { PromiseResult result = PROMISE_RESULT_NOOP; if (!FileCanOpen(a.edit_template, "r")) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Template file '%s' could not be opened for reading", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } unsigned char existing_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; if (access(pp->promiser, R_OK) == 0) { HashFile(pp->promiser, existing_output_digest, CF_DEFAULT_DIGEST); } int template_fd = safe_open(a.edit_template, O_RDONLY | O_TEXT); Writer *template_writer = NULL; if (template_fd >= 0) { template_writer = FileReadFromFd(template_fd, SIZE_MAX, NULL); close(template_fd); } if (!template_writer) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not read template file '%s'", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } JsonElement *default_template_data = NULL; if (!a.template_data) { a.template_data = default_template_data = DefaultTemplateData(ctx); } Buffer *output_buffer = BufferNew(); if (MustacheRender(output_buffer, StringWriterData(template_writer), a.template_data)) { unsigned char rendered_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; HashString(BufferData(output_buffer), BufferSize(output_buffer), rendered_output_digest, CF_DEFAULT_DIGEST); if (!HashesMatch(existing_output_digest, rendered_output_digest, CF_DEFAULT_DIGEST)) { if (SaveAsFile(SaveBufferCallback, output_buffer, edcontext->filename, a, edcontext->new_line_mode)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return result; } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error rendering mustache template '%s'", a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } }
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files) { Policy *policy = NULL; unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; char hashbuffer[EVP_MAX_MD_SIZE * 4] = { 0 }; char hashprintbuffer[CF_BUFSIZE] = { 0 }; HashFile(policy_file, digest, CF_DEFAULT_DIGEST); snprintf(hashprintbuffer, CF_BUFSIZE - 1, "{checksum}%s", HashPrintSafe(CF_DEFAULT_DIGEST, true, digest, hashbuffer)); Log(LOG_LEVEL_DEBUG, "Hashed policy file %s to %s", policy_file, hashprintbuffer); if (StringSetContains(parsed_files_and_checksums, policy_file)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate policy file %s", policy_file); return NULL; } else if (StringSetContains(parsed_files_and_checksums, hashprintbuffer)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate (detected by hash) policy file %s", policy_file); return NULL; } else { Log(LOG_LEVEL_DEBUG, "Loading policy file %s", policy_file); } policy = Cf3ParseFile(config, policy_file); // we keep the checksum and the policy file name to help debugging StringSetAdd(parsed_files_and_checksums, xstrdup(policy_file)); StringSetAdd(parsed_files_and_checksums, xstrdup(hashprintbuffer)); if (policy) { Seq *errors = SeqNew(10, free); if (!PolicyCheckPartial(policy, errors)) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); SeqDestroy(errors); StringSetAdd(failed_files, xstrdup(policy_file)); return NULL; } SeqDestroy(errors); } else { StringSetAdd(failed_files, xstrdup(policy_file)); return NULL; } PolicyResolve(ctx, policy, config); Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control"); Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control"); if (body_common_control) { Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } if (body_file_control) { Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } return policy; }