Hi, Continued review...
On Thu, 2023-09-07 at 08:55 -0400, Frank Ch. Eigler via Elfutils-devel wrote: > diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx > index d72d2ad16960..8c3298586672 100644 > --- a/debuginfod/debuginfod.cxx > +++ b/debuginfod/debuginfod.cxx > @@ -113,6 +113,13 @@ using namespace std; > #define MHD_RESULT int > #endif > > +#ifdef ENABLE_IMA_VERIFICATION > + #include <rpm/rpmlib.h> > + #include <rpm/rpmfi.h> > + #include <rpm/header.h> > + #include <glob.h> > +#endif > + > #include <curl/curl.h> > #include <archive.h> > #include <archive_entry.h> OK. > @@ -431,6 +438,8 @@ static const struct argp_option options[] = > { "disable-source-scan", ARGP_KEY_DISABLE_SOURCE_SCAN, NULL, 0, "Do not > scan dwarf source info.", 0 }, > #define ARGP_SCAN_CHECKPOINT 0x100A > { "scan-checkpoint", ARGP_SCAN_CHECKPOINT, "NUM", 0, "Number of files > scanned before a WAL checkpoint.", 0 }, > +#define ARGP_KEY_KOJI_SIGCACHE 0x100B > + { "koji-sigcache", ARGP_KEY_KOJI_SIGCACHE, NULL, 0, "Do a koji specific > mapping of rpm paths to get IMA signatures.", 0 }, > { NULL, 0, NULL, 0, NULL, 0 }, > }; OK. Is actually documented below. But first couldn't find it because of the escaped '-' (good), which apparently is a real issue: https://lwn.net/SubscriberLink/947941/b427a4409847108d/ > @@ -486,6 +495,7 @@ static bool scan_source_info = true; > static string tmpdir; > static bool passive_p = false; > static long scan_checkpoint = 256; > +static bool requires_koji_sigcache_mapping = false; > > static void set_metric(const string& key, double value); > // static void inc_metric(const string& key); > @@ -692,6 +702,9 @@ parse_opt (int key, char *arg, > if (scan_checkpoint < 0) > argp_failure(state, 1, EINVAL, "scan checkpoint"); > break; > + case ARGP_KEY_KOJI_SIGCACHE: > + requires_koji_sigcache_mapping = true; > + break; > // case 'h': argp_state_help (state, stderr, > ARGP_HELP_LONG|ARGP_HELP_EXIT_OK); > default: return ARGP_ERR_UNKNOWN; > } OK. Maybe produce a warning/error ifndef ENABLE_IMA_VERIFICATION ? > @@ -1933,6 +1946,131 @@ handle_buildid_r_match (bool internal_req_p, > return 0; > } > > + // Extract the IMA per-file signature (if it exists) > + string ima_sig = ""; > + #ifdef ENABLE_IMA_VERIFICATION > + do > + { > + FD_t rpm_fd; > + if(!(rpm_fd = Fopen(b_source0.c_str(), "r.ufdio"))) > + { > + if (verbose) obatched(clog) << "There was an error while opening " << > b_source0 << endl; > + break; // Exit IMA extraction > + } So Fopen is part of rpm devel? Is there documentation? Specifically what "r.ufdio" means? > + Header rpm_hdr; > + if(RPMRC_FAIL == rpmReadPackageFile(NULL, rpm_fd, b_source0.c_str(), > &rpm_hdr)) > + { > + if (verbose) obatched(clog) << "There was an error while reading the > header of " << b_source0 << endl; > + Fclose(rpm_fd); > + break; // Exit IMA extraction > + } OK. > + // Fill sig_tag_data with an alloc'd copy of the array of IMA signatures > (if they exist) > + struct rpmtd_s sig_tag_data; > + rpmtdReset(&sig_tag_data); > + do{ /* A do-while so we can break out of the koji sigcache checking on > failure */ > + if(requires_koji_sigcache_mapping) > + { > + /* NB: Koji builds result in a directory structure like the following > + - PACKAGE/VERSION/RELEASE > + - ARCH1 > + - foo.rpm // The rpm known by debuginfod > + - ... > + - ARCHN > + - data > + - signed // Periodically purged (and not scanned by > debuginfod) > + - sigcache > + - ARCH1 > + - foo.rpm.sig // An empty rpm header > + - ... > + - ARCHN > + - PACKAGE_KEYID1 > + - ARCH1 > + - foo.rpm.sig // The header of the signed rpm. This is the > file we need to extract the IMA signatures > + - ... > + - ARCHN > + - ... > + - PACKAGE_KEYIDN > + We therefore need to do a mapping of P/V/R/A/N-V-R.A.rpm -> > P/V/R/data/sigcache/KEYID/A/N-V-R.A.rpm.sig. There are 2 key insights here > + 1. We need to go 2 directories down from sigcache to get to the rpm > header. So to distinguish ARCH1/foo.rpm.sig and > PACKAGE_KEYID1/ARCH1/foo.rpm.sig > + we can look 2 directories down > + 2. Its safe to assume that the user will have all of the required > verification certs. So we can pick from any of the PACKAGE_KEYIDi directories. > + For simplicity we choose first we match against > + See: https://pagure.io/koji/issue/3670 > + */ Nice comment, thanks for the bug reference. Note tiny typo "PACKAGE_KEYIDi" (extra 'i'). > + // Do the mapping from b_source0 to the koji path for the signed rpm > header > + string signed_rpm_path = b_source0; > + size_t insert_pos = string::npos; > + for(int i = 0; i < 2; i++) insert_pos = signed_rpm_path.rfind("/", > insert_pos) - 1; > + string globbed_path = signed_rpm_path.insert(insert_pos + 1, > "/data/sigcache/*").append(".sig"); // The globbed path we're seeking > + glob_t pglob; > + int grc; > + if(0 != (grc = glob(globbed_path.c_str(), GLOB_NOSORT, NULL, &pglob))) > + { > + // Break out, but only report real errors > + if (verbose && grc != GLOB_NOMATCH) obatched(clog) << "There was an > error (" << strerror(errno) << ") globbing " << globbed_path << endl; > + break; // Exit koji sigcache check > + } > + signed_rpm_path = pglob.gl_pathv[0]; // See insight 2 above > + globfree(&pglob); > + > + if (verbose > 2) obatched(clog) << "attempting IMA signature > extraction from koji header " << signed_rpm_path << endl; > + > + FD_t sig_rpm_fd; > + if(NULL == (sig_rpm_fd = Fopen(signed_rpm_path.c_str(), "r"))) > + { > + if (verbose) obatched(clog) << "There was an error while opening " > << signed_rpm_path << endl; > + break; // Exit koji sigcache check > + } > + > + Header sig_hdr = headerRead(sig_rpm_fd, HEADER_MAGIC_YES /* Validate > magic too */ ); > + if (!sig_hdr || 1 != headerGet(sig_hdr, RPMSIGTAG_FILESIGNATURES, > &sig_tag_data, HEADERGET_ALLOC)) > + { > + if (verbose) obatched(clog) << "Unable to extract > RPMSIGTAG_FILESIGNATURES from " << signed_rpm_path << endl; > + } > + headerFree(sig_hdr); // We can free here since sig_tag_data has an > alloc'd copy of the data > + Fclose(sig_rpm_fd); > + } > + }while(false); > + > + if(0 == sig_tag_data.count) > + { > + // In the general case (or a fallback from the koji sigcache mapping > not finding signatures) > + // we can just (try) extract the signatures from the rpm header > + if (1 != headerGet(rpm_hdr, RPMTAG_FILESIGNATURES, &sig_tag_data, > HEADERGET_ALLOC)) > + { > + if (verbose) obatched(clog) << "Unable to extract > RPMTAG_FILESIGNATURES from " << b_source0 << endl; > + } > + } OK. A bit convoluted, but that is just rpm being rpm. > + // Search the array for the signature coresponding to b_source1 > + int idx = -1; > + char *sig = NULL; > + rpmfi hdr_fi = rpmfiNew(NULL, rpm_hdr, RPMTAG_BASENAMES, > RPMFI_FLAGS_QUERY); > + for(sig = (char*)rpmtdNextString(&sig_tag_data), idx = rpmfiNext(hdr_fi); > + idx != -1 && 0 != strcmp(b_source1.c_str(), rpmfiFN(hdr_fi)); > + sig = (char*)rpmtdNextString(&sig_tag_data), idx = > rpmfiNext(hdr_fi)); > + rpmfiFree(hdr_fi); That is a complicated for statement, not easily understood. Partially because of indentation. Advise to at least put ';' on its own line. > + if(sig && 0 != strlen(sig) && idx != -1) > + { > + if (verbose > 2) obatched(clog) << "Found IMA signature for " << > b_source1 << ":\n" << sig << endl; > + ima_sig = sig; > + inc_metric("http_responses_total","extra","ima-sigs-extracted"); > + } > + else > + { > + if (verbose > 2) obatched(clog) << "Could not find IMA signature for " > << b_source1 << endl; > + } > + > + rpmtdFreeData (&sig_tag_data); > + headerFree(rpm_hdr); > + Fclose(rpm_fd); > + } > + while(false); > + #endif OK. BTW. Shouldn't we cache this image_sig somewhere? It seems a lot of work to do each time handle_buildid_r_match is called. > // check for a match in the fdcache first > int fd = fdcache.lookup(b_source0, b_source1); > while (fd >= 0) // got one!; NB: this is really an if() with a possible > branch out to the end > @@ -1990,11 +2128,13 @@ handle_buildid_r_match (bool internal_req_p, > to_string(fs.st_size).c_str()); > add_mhd_response_header (r, "X-DEBUGINFOD-ARCHIVE", b_source0.c_str()); > add_mhd_response_header (r, "X-DEBUGINFOD-FILE", b_source1.c_str()); > + if(!ima_sig.empty()) add_mhd_response_header(r, > "X-DEBUGINFOD-IMASIGNATURE", ima_sig.c_str()); > add_mhd_last_modified (r, fs.st_mtime); > if (verbose > 1) > obatched(clog) << "serving fdcache archive " << b_source0 > << " file " << b_source1 > - << " section=" << section << endl; > + << " section=" << section > + << " IMA signature=" << ima_sig << endl; > /* libmicrohttpd will close it. */ > if (result_fd) > *result_fd = fd; > @@ -2174,11 +2314,13 @@ handle_buildid_r_match (bool internal_req_p, > add_mhd_response_header (r, "X-DEBUGINFOD-ARCHIVE", > b_source0.c_str()); > add_mhd_response_header (r, "X-DEBUGINFOD-FILE", file.c_str()); > + if(!ima_sig.empty()) add_mhd_response_header(r, > "X-DEBUGINFOD-IMASIGNATURE", ima_sig.c_str()); > add_mhd_last_modified (r, archive_entry_mtime(e)); > if (verbose > 1) > obatched(clog) << "serving archive " << b_source0 > << " file " << b_source1 > - << " section=" << section << endl; > + << " section=" << section > + << " IMA signature=" << ima_sig << endl; > /* libmicrohttpd will close it. */ > if (result_fd) > *result_fd = fd; OK. > diff --git a/debuginfod/debuginfod.h.in b/debuginfod/debuginfod.h.in > index 4a256ba9af1f..73f633f0b8e9 100644 > --- a/debuginfod/debuginfod.h.in > +++ b/debuginfod/debuginfod.h.in > @@ -39,6 +39,7 @@ > #define DEBUGINFOD_MAXSIZE_ENV_VAR "DEBUGINFOD_MAXSIZE" > #define DEBUGINFOD_MAXTIME_ENV_VAR "DEBUGINFOD_MAXTIME" > #define DEBUGINFOD_HEADERS_FILE_ENV_VAR "DEBUGINFOD_HEADERS_FILE" > +#define DEBUGINFOD_IMA_CERT_PATH_ENV_VAR "DEBUGINFOD_IMA_CERT_PATH" > > /* The libdebuginfod soname. */ > #define DEBUGINFOD_SONAME "@LIBDEBUGINFOD_SONAME@" OK. > diff --git a/debuginfod/ima-certs/centosimabeta9.crt > b/debuginfod/ima-certs/centosimabeta9.crt > new file mode 100644 > index 000000000000..534f86a15ac5 > --- /dev/null > +++ b/debuginfod/ima-certs/centosimabeta9.crt > @@ -0,0 +1,70 @@ > +Certificate: > + Data: > + Version: 3 (0x2) > + Serial Number: > + d6:78:a4:e3:e7:d3:c5:aa > + Signature Algorithm: sha256WithRSAEncryption > + Issuer: O=RH-IMA-CA, CN=Red Hat IMA > CA/emailAddress=secal...@redhat.com > + Validity > + Not Before: Jul 1 16:14:28 2023 GMT > + Not After : Jan 18 16:14:28 2038 GMT > + Subject: CN=CentOS IMA beta key (for verification) > + Subject Public Key Info: > + Public Key Algorithm: id-ecPublicKey > + Public-Key: (384 bit) > + pub: > + 04:6c:6d:44:6d:eb:55:31:56:11:ab:a7:dc:cc:34: > + 72:9c:9b:05:5c:d8:28:36:c8:04:05:5a:c8:33:b5: > + ba:de:ba:f5:0d:a9:1f:02:c1:43:78:e8:0a:2f:05: > + e9:a9:ce:c4:24:5b:d6:b2:ce:cf:06:52:7a:7a:d9: > + 3f:dd:b3:09:b1:22:90:e4:95:4e:07:80:f4:9c:73: > + e9:6c:00:09:ed:b1:68:76:c5:59:7e:74:a4:c3:cf: > + a1:84:20:51:f6:29:2e > + ASN1 OID: secp384r1 > + NIST CURVE: P-384 > + X509v3 extensions: > + X509v3 Basic Constraints: critical > + CA:FALSE > + X509v3 Key Usage: critical > + Digital Signature > + X509v3 Extended Key Usage: critical > + Code Signing > + X509v3 Subject Key Identifier: > + 61:BA:CE:C0:D7:97:EA:49:9F:D8:92:79:41:57:19:0A:D6:04:63:E1 > + X509v3 Authority Key Identifier: > + > keyid:FB:31:82:5D:D0:E0:73:68:5B:26:4E:30:38:96:36:73:F7:53:95:9A > + > + Signature Algorithm: sha256WithRSAEncryption > + 8b:28:5a:ca:d3:2a:ec:e2:c6:89:f8:4d:e9:ff:c8:31:47:7b: > + 93:17:c1:55:48:40:ce:be:1c:58:ff:6a:83:55:07:72:70:c7: > + a3:25:91:70:90:ab:9d:bc:d3:63:4e:aa:f2:2f:ee:0c:05:a5: > + 8e:2e:98:7b:41:44:37:66:87:80:94:56:b1:1f:13:99:d0:80: > + 0b:e8:ec:50:cf:8c:90:53:cb:b1:9c:35:cf:b7:75:1f:ad:77: > + 52:d2:06:56:7a:37:16:fe:bb:c2:aa:de:72:5d:b3:4b:9f:d3: > + 05:c6:4a:36:d2:14:6b:9a:b3:64:62:4b:d5:9d:aa:71:ab:11: > + c0:08:17:e1:f9:88:49:c7:6f:74:ff:02:04:ee:cd:a2:75:5b: > + 79:19:ed:ad:14:71:b4:19:56:ed:fe:7b:61:7e:d4:97:b5:c7: > + a5:05:41:4c:9f:17:91:71:71:bc:12:2b:d8:6c:2b:c0:02:93: > + ed:28:30:9b:7f:a1:93:8c:32:74:fe:6c:c0:ab:68:5e:e5:3e: > + 22:c9:db:d4:4e:b2:5c:d6:49:e7:1d:91:78:61:3c:ca:5e:72: > + 63:74:ff:af:0d:0d:32:ae:2a:cd:9b:a1:30:95:ea:33:53:64: > + 2b:13:2d:96:e3:b6:6d:f2:c2:3c:24:c8:6b:87:f8:b4:7f:72: > + 30:66:f8:5d > +-----BEGIN CERTIFICATE----- > +MIICzzCCAbegAwIBAgIJANZ4pOPn08WqMA0GCSqGSIb3DQEBCwUAMFExEjAQBgNV > +BAoMCVJILUlNQS1DQTEXMBUGA1UEAwwOUmVkIEhhdCBJTUEgQ0ExIjAgBgkqhkiG > +9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMjMwNzAxMTYxNDI4WhcNMzgw > +MTE4MTYxNDI4WjAxMS8wLQYDVQQDDCZDZW50T1MgSU1BIGJldGEga2V5IChmb3Ig > +dmVyaWZpY2F0aW9uKTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGxtRG3rVTFWEaun > +3Mw0cpybBVzYKDbIBAVayDO1ut669Q2pHwLBQ3joCi8F6anOxCRb1rLOzwZSenrZ > +P92zCbEikOSVTgeA9Jxz6WwACe2xaHbFWX50pMPPoYQgUfYpLqN4MHYwDAYDVR0T > +AQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMw > +HQYDVR0OBBYEFGG6zsDXl+pJn9iSeUFXGQrWBGPhMB8GA1UdIwQYMBaAFPsxgl3Q > +4HNoWyZOMDiWNnP3U5WaMA0GCSqGSIb3DQEBCwUAA4IBAQCLKFrK0yrs4saJ+E3p > +/8gxR3uTF8FVSEDOvhxY/2qDVQdycMejJZFwkKudvNNjTqryL+4MBaWOLph7QUQ3 > +ZoeAlFaxHxOZ0IAL6OxQz4yQU8uxnDXPt3UfrXdS0gZWejcW/rvCqt5yXbNLn9MF > +xko20hRrmrNkYkvVnapxqxHACBfh+YhJx290/wIE7s2idVt5Ge2tFHG0GVbt/nth > +ftSXtcelBUFMnxeRcXG8EivYbCvAApPtKDCbf6GTjDJ0/mzAq2he5T4iydvUTrJc > +1knnHZF4YTzKXnJjdP+vDQ0yrirNm6EwleozU2QrEy2W47Zt8sI8JMhrh/i0f3Iw > +Zvhd > +-----END CERTIFICATE----- > diff --git a/debuginfod/ima-certs/centosimarelease9.crt > b/debuginfod/ima-certs/centosimarelease9.crt > new file mode 100644 > index 000000000000..db641453260f > --- /dev/null > +++ b/debuginfod/ima-certs/centosimarelease9.crt > @@ -0,0 +1,70 @@ > +Certificate: > + Data: > + Version: 3 (0x2) > + Serial Number: > + d6:78:a4:e3:e7:d3:c5:ab > + Signature Algorithm: sha256WithRSAEncryption > + Issuer: O=RH-IMA-CA, CN=Red Hat IMA > CA/emailAddress=secal...@redhat.com > + Validity > + Not Before: Jul 1 16:14:51 2023 GMT > + Not After : Jan 18 16:14:51 2038 GMT > + Subject: CN=CentOS IMA release key (for verification) > + Subject Public Key Info: > + Public Key Algorithm: id-ecPublicKey > + Public-Key: (384 bit) > + pub: > + 04:d4:d0:31:08:09:0d:97:d0:5c:c8:49:ff:90:f4: > + 3a:16:85:a3:73:a1:d9:c4:28:4c:f7:aa:a8:22:c2: > + cf:0e:8b:d7:9a:ed:e6:f0:89:f8:85:95:72:c3:38: > + 27:2a:29:97:6a:6b:2b:01:04:a3:32:ba:f4:75:f9: > + e4:c8:48:2f:f5:36:69:44:27:f9:35:b3:0c:c3:22: > + 24:67:51:06:d3:73:f1:56:94:20:a8:8c:82:34:c0: > + 10:ef:ce:f9:b4:7a:42 > + ASN1 OID: secp384r1 > + NIST CURVE: P-384 > + X509v3 extensions: > + X509v3 Basic Constraints: critical > + CA:FALSE > + X509v3 Key Usage: critical > + Digital Signature > + X509v3 Extended Key Usage: critical > + Code Signing > + X509v3 Subject Key Identifier: > + 54:E5:A3:4F:16:2B:32:B7:77:FF:E3:4F:1E:8B:66:12:7C:43:5B:B5 > + X509v3 Authority Key Identifier: > + > keyid:FB:31:82:5D:D0:E0:73:68:5B:26:4E:30:38:96:36:73:F7:53:95:9A > + > + Signature Algorithm: sha256WithRSAEncryption > + c6:1d:92:0e:92:40:d6:ae:a5:5d:4e:5d:2a:e1:0f:92:42:20: > + 89:e1:a9:82:87:35:42:c9:7f:77:dd:19:e3:cf:ef:be:8b:39: > + 4f:99:2e:cd:cc:a3:18:23:7f:81:4b:7d:63:5d:71:b4:4b:9c: > + ea:dc:2f:1d:16:da:4c:ed:98:bf:df:88:11:d0:8b:af:01:55: > + 71:05:fe:d7:ac:78:4e:46:de:48:9f:04:74:42:c2:c8:1a:fc: > + c5:46:6a:99:3e:9a:b0:e4:04:07:48:e2:4c:65:e5:01:a8:ad: > + 3c:8d:c0:ca:c5:73:23:36:88:27:54:8b:90:f8:ea:55:fc:eb: > + b8:69:a5:8b:a0:1d:8b:f1:93:dd:71:9e:e9:88:f0:2d:0e:7d: > + 86:a4:8d:0b:fd:00:c9:c0:73:aa:b1:65:b1:60:6e:a4:09:1b: > + 3e:30:d9:62:2a:15:d6:50:2a:6a:fd:24:e7:8c:93:78:4a:28: > + d5:b1:d9:ba:1b:8d:ef:48:0d:f4:8c:79:90:0f:95:8d:79:39: > + 8d:41:a5:fc:6f:e4:ef:5c:ee:3b:f4:c3:2c:c3:a0:b7:61:ac: > + 7e:e9:eb:a0:3a:ba:05:2c:bd:aa:a9:1f:c5:b9:ee:72:f6:c4: > + 54:1f:71:3b:e1:70:1a:30:f4:04:18:50:60:c4:5a:da:93:cd: > + b6:f6:67:c8 > +-----BEGIN CERTIFICATE----- > +MIIC0jCCAbqgAwIBAgIJANZ4pOPn08WrMA0GCSqGSIb3DQEBCwUAMFExEjAQBgNV > +BAoMCVJILUlNQS1DQTEXMBUGA1UEAwwOUmVkIEhhdCBJTUEgQ0ExIjAgBgkqhkiG > +9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMjMwNzAxMTYxNDUxWhcNMzgw > +MTE4MTYxNDUxWjA0MTIwMAYDVQQDDClDZW50T1MgSU1BIHJlbGVhc2Uga2V5IChm > +b3IgdmVyaWZpY2F0aW9uKTB2MBAGByqGSM49AgEGBSuBBAAiA2IABNTQMQgJDZfQ > +XMhJ/5D0OhaFo3Oh2cQoTPeqqCLCzw6L15rt5vCJ+IWVcsM4Jyopl2prKwEEozK6 > +9HX55MhIL/U2aUQn+TWzDMMiJGdRBtNz8VaUIKiMgjTAEO/O+bR6QqN4MHYwDAYD > +VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUH > +AwMwHQYDVR0OBBYEFFTlo08WKzK3d//jTx6LZhJ8Q1u1MB8GA1UdIwQYMBaAFPsx > +gl3Q4HNoWyZOMDiWNnP3U5WaMA0GCSqGSIb3DQEBCwUAA4IBAQDGHZIOkkDWrqVd > +Tl0q4Q+SQiCJ4amChzVCyX933Rnjz+++izlPmS7NzKMYI3+BS31jXXG0S5zq3C8d > +FtpM7Zi/34gR0IuvAVVxBf7XrHhORt5InwR0QsLIGvzFRmqZPpqw5AQHSOJMZeUB > +qK08jcDKxXMjNognVIuQ+OpV/Ou4aaWLoB2L8ZPdcZ7piPAtDn2GpI0L/QDJwHOq > +sWWxYG6kCRs+MNliKhXWUCpq/STnjJN4SijVsdm6G43vSA30jHmQD5WNeTmNQaX8 > +b+TvXO479MMsw6C3Yax+6eugOroFLL2qqR/Fue5y9sRUH3E74XAaMPQEGFBgxFra > +k8229mfI > +-----END CERTIFICATE----- > diff --git a/debuginfod/ima-certs/fedora-38-ima.der > b/debuginfod/ima-certs/fedora-38-ima.der > new file mode 100644 > index 000000000000..238ae6c30763 > Binary files /dev/null and b/debuginfod/ima-certs/fedora-38-ima.der differ > diff --git a/debuginfod/ima-certs/fedora-39-ima.der > b/debuginfod/ima-certs/fedora-39-ima.der > new file mode 100644 > index 000000000000..0d13baa62d75 > Binary files /dev/null and b/debuginfod/ima-certs/fedora-39-ima.der differ > diff --git a/debuginfod/ima-certs/redhatimabeta9.crt > b/debuginfod/ima-certs/redhatimabeta9.crt > new file mode 100644 > index 000000000000..4a3b6701d6c4 > --- /dev/null > +++ b/debuginfod/ima-certs/redhatimabeta9.crt > @@ -0,0 +1,70 @@ > +Certificate: > + Data: > + Version: 3 (0x2) > + Serial Number: > + d6:78:a4:e3:e7:d3:c5:a8 > + Signature Algorithm: sha256WithRSAEncryption > + Issuer: O=RH-IMA-CA, CN=Red Hat IMA > CA/emailAddress=secal...@redhat.com > + Validity > + Not Before: Jul 1 16:13:38 2023 GMT > + Not After : Jan 18 16:13:38 2038 GMT > + Subject: CN=Red Hat IMA beta key (for verification) > + Subject Public Key Info: > + Public Key Algorithm: id-ecPublicKey > + Public-Key: (384 bit) > + pub: > + 04:af:d0:5e:29:27:3a:26:05:27:74:1b:07:62:20: > + c3:3e:40:43:73:3e:ad:e4:24:3e:b1:24:9d:72:81: > + e3:f0:43:40:7b:82:52:dc:57:66:ed:92:af:79:c2: > + 6b:09:31:bf:50:1b:76:24:b5:2f:8f:ce:9c:65:20: > + d4:e2:3d:37:41:0d:5d:b7:78:af:8c:d3:71:b7:10: > + c9:70:15:77:d0:8f:09:97:3f:7e:83:7d:67:98:8f: > + cf:be:16:b5:6d:73:7d > + ASN1 OID: secp384r1 > + NIST CURVE: P-384 > + X509v3 extensions: > + X509v3 Basic Constraints: critical > + CA:FALSE > + X509v3 Key Usage: critical > + Digital Signature > + X509v3 Extended Key Usage: critical > + Code Signing > + X509v3 Subject Key Identifier: > + 7D:45:10:63:D2:89:7B:E3:6D:A6:62:D6:6B:36:15:E5:F0:F2:9C:D0 > + X509v3 Authority Key Identifier: > + > keyid:FB:31:82:5D:D0:E0:73:68:5B:26:4E:30:38:96:36:73:F7:53:95:9A > + > + Signature Algorithm: sha256WithRSAEncryption > + 68:9b:7d:29:e2:46:ed:03:6a:5d:d9:9e:f3:7a:0d:49:fa:22: > + 40:02:3e:cb:af:a3:ee:aa:b5:43:fd:d9:1e:5b:82:89:e7:ad: > + 48:03:d4:4c:50:7e:03:32:c3:eb:88:b8:b4:57:8c:1d:78:f9: > + a4:ca:d2:55:78:a1:ec:67:c8:1b:90:40:be:98:5b:fd:77:91: > + 6b:7c:ed:5f:e9:b0:af:6e:71:03:bc:03:5f:ad:f0:01:bc:24: > + 0d:ea:1e:04:9e:10:ee:5c:97:17:49:3e:8e:7b:51:17:1a:e2: > + 06:09:04:d4:6d:94:ea:30:57:fd:70:d0:56:6c:36:81:9f:81: > + 75:25:98:34:9b:e8:03:14:b0:7c:8c:13:b5:59:0a:45:15:d8: > + 75:c9:7a:01:a4:2d:71:a1:6d:53:b6:22:37:ab:98:d3:f0:76: > + 28:8d:c3:3b:7d:c5:11:b1:89:7b:ac:41:e2:92:e9:38:4d:6d: > + 07:d9:07:76:53:1a:87:ca:79:2e:5d:20:ec:8b:f2:55:56:dd: > + b1:65:ec:4c:d7:86:7b:8e:9b:a7:7f:6d:6e:7a:3f:18:e3:e3: > + e7:3f:1c:fb:44:ab:7e:0c:c2:1d:61:7c:92:73:07:a2:b4:5a: > + 6b:45:64:dd:4d:c9:df:a3:e1:5f:39:db:36:f3:d0:ba:c6:be: > + 97:3c:2f:e6 > +-----BEGIN CERTIFICATE----- > +MIIC0DCCAbigAwIBAgIJANZ4pOPn08WoMA0GCSqGSIb3DQEBCwUAMFExEjAQBgNV > +BAoMCVJILUlNQS1DQTEXMBUGA1UEAwwOUmVkIEhhdCBJTUEgQ0ExIjAgBgkqhkiG > +9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMjMwNzAxMTYxMzM4WhcNMzgw > +MTE4MTYxMzM4WjAyMTAwLgYDVQQDDCdSZWQgSGF0IElNQSBiZXRhIGtleSAoZm9y > +IHZlcmlmaWNhdGlvbikwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASv0F4pJzomBSd0 > +GwdiIMM+QENzPq3kJD6xJJ1ygePwQ0B7glLcV2btkq95wmsJMb9QG3YktS+Pzpxl > +INTiPTdBDV23eK+M03G3EMlwFXfQjwmXP36DfWeYj8++FrVtc32jeDB2MAwGA1Ud > +EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMD > +MB0GA1UdDgQWBBR9RRBj0ol7422mYtZrNhXl8PKc0DAfBgNVHSMEGDAWgBT7MYJd > +0OBzaFsmTjA4ljZz91OVmjANBgkqhkiG9w0BAQsFAAOCAQEAaJt9KeJG7QNqXdme > +83oNSfoiQAI+y6+j7qq1Q/3ZHluCieetSAPUTFB+AzLD64i4tFeMHXj5pMrSVXih > +7GfIG5BAvphb/XeRa3ztX+mwr25xA7wDX63wAbwkDeoeBJ4Q7lyXF0k+jntRFxri > +BgkE1G2U6jBX/XDQVmw2gZ+BdSWYNJvoAxSwfIwTtVkKRRXYdcl6AaQtcaFtU7Yi > +N6uY0/B2KI3DO33FEbGJe6xB4pLpOE1tB9kHdlMah8p5Ll0g7IvyVVbdsWXsTNeG > +e46bp39tbno/GOPj5z8c+0SrfgzCHWF8knMHorRaa0Vk3U3J36PhXznbNvPQusa+ > +lzwv5g== > +-----END CERTIFICATE----- > diff --git a/debuginfod/ima-certs/redhatimarelease9.crt > b/debuginfod/ima-certs/redhatimarelease9.crt > new file mode 100644 > index 000000000000..cd0b66494da2 > --- /dev/null > +++ b/debuginfod/ima-certs/redhatimarelease9.crt > @@ -0,0 +1,70 @@ > +Certificate: > + Data: > + Version: 3 (0x2) > + Serial Number: > + d6:78:a4:e3:e7:d3:c5:a9 > + Signature Algorithm: sha256WithRSAEncryption > + Issuer: O=RH-IMA-CA, CN=Red Hat IMA > CA/emailAddress=secal...@redhat.com > + Validity > + Not Before: Jul 1 16:14:04 2023 GMT > + Not After : Jan 18 16:14:04 2038 GMT > + Subject: CN=Red Hat IMA release key (for verification) > + Subject Public Key Info: > + Public Key Algorithm: id-ecPublicKey > + Public-Key: (384 bit) > + pub: > + 04:4f:0e:ef:bf:e2:23:89:91:27:4e:7c:32:a1:d0: > + c0:26:92:de:37:8d:b0:5d:ea:7f:d6:27:18:9b:b4: > + 62:be:06:85:3d:f9:cc:47:7e:c7:bd:91:54:53:62: > + b4:c0:8a:43:48:c2:59:07:2b:88:d7:3d:4b:30:8d: > + 6c:32:fb:a5:da:dc:8a:85:e9:61:44:18:fc:d9:8b: > + f5:5e:38:c8:85:77:ca:73:68:ce:48:df:af:3d:06: > + 43:2f:4b:6c:0c:cd:88 > + ASN1 OID: secp384r1 > + NIST CURVE: P-384 > + X509v3 extensions: > + X509v3 Basic Constraints: critical > + CA:FALSE > + X509v3 Key Usage: critical > + Digital Signature > + X509v3 Extended Key Usage: critical > + Code Signing > + X509v3 Subject Key Identifier: > + 22:FA:01:DC:0E:A0:26:9F:69:A8:67:E5:CF:E4:9C:FB:D3:32:04:49 > + X509v3 Authority Key Identifier: > + > keyid:FB:31:82:5D:D0:E0:73:68:5B:26:4E:30:38:96:36:73:F7:53:95:9A > + > + Signature Algorithm: sha256WithRSAEncryption > + 1a:1e:c1:2d:65:ad:f0:24:ec:9e:a7:fd:d4:ea:e1:54:dc:31: > + 1c:62:8c:29:0b:7a:56:6e:f7:b4:87:92:3e:ff:d5:40:4b:24: > + a1:68:6e:ee:9c:35:65:a1:3f:8e:f3:8b:9b:18:b1:03:ed:fb: > + 50:2e:a3:23:d1:93:1d:d6:82:0a:10:6f:34:be:d6:3a:bd:76: > + 8c:44:0e:ad:a7:2a:c4:8e:8d:c4:e4:8d:51:d8:26:b7:38:89: > + d1:23:a0:23:88:76:fa:f1:27:91:57:3e:b2:0f:cf:73:53:db: > + 20:40:5d:82:b9:e9:bc:a2:94:09:57:fb:85:0d:56:4b:dc:19: > + 65:12:2f:6d:6a:3b:be:35:1f:d4:52:ea:e4:72:36:f9:fe:cb: > + d4:1b:0f:e3:0e:88:7c:68:58:28:c3:06:5f:bd:d2:f9:2e:1a: > + 30:f0:63:65:2d:55:e1:a4:fd:97:cf:ff:c0:52:22:1c:24:a3: > + 6e:de:7a:c9:9d:75:d2:d0:82:b0:7f:6f:db:21:01:69:f0:54: > + 76:04:19:68:2c:22:72:dd:3b:0d:04:d5:ad:5a:80:30:68:90: > + 6e:c2:27:f4:28:af:1b:78:f6:0a:70:74:5c:3a:61:42:f5:63: > + 7c:83:12:5a:1b:43:bc:d4:1b:28:b5:ef:98:c5:14:04:42:80: > + dd:54:30:a4 > +-----BEGIN CERTIFICATE----- > +MIIC0zCCAbugAwIBAgIJANZ4pOPn08WpMA0GCSqGSIb3DQEBCwUAMFExEjAQBgNV > +BAoMCVJILUlNQS1DQTEXMBUGA1UEAwwOUmVkIEhhdCBJTUEgQ0ExIjAgBgkqhkiG > +9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMjMwNzAxMTYxNDA0WhcNMzgw > +MTE4MTYxNDA0WjA1MTMwMQYDVQQDDCpSZWQgSGF0IElNQSByZWxlYXNlIGtleSAo > +Zm9yIHZlcmlmaWNhdGlvbikwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARPDu+/4iOJ > +kSdOfDKh0MAmkt43jbBd6n/WJxibtGK+BoU9+cxHfse9kVRTYrTAikNIwlkHK4jX > +PUswjWwy+6Xa3IqF6WFEGPzZi/VeOMiFd8pzaM5I3689BkMvS2wMzYijeDB2MAwG > +A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUF > +BwMDMB0GA1UdDgQWBBQi+gHcDqAmn2moZ+XP5Jz70zIESTAfBgNVHSMEGDAWgBT7 > +MYJd0OBzaFsmTjA4ljZz91OVmjANBgkqhkiG9w0BAQsFAAOCAQEAGh7BLWWt8CTs > +nqf91OrhVNwxHGKMKQt6Vm73tIeSPv/VQEskoWhu7pw1ZaE/jvOLmxixA+37UC6j > +I9GTHdaCChBvNL7WOr12jEQOracqxI6NxOSNUdgmtziJ0SOgI4h2+vEnkVc+sg/P > +c1PbIEBdgrnpvKKUCVf7hQ1WS9wZZRIvbWo7vjUf1FLq5HI2+f7L1BsP4w6IfGhY > +KMMGX73S+S4aMPBjZS1V4aT9l8//wFIiHCSjbt56yZ110tCCsH9v2yEBafBUdgQZ > +aCwict07DQTVrVqAMGiQbsIn9CivG3j2CnB0XDphQvVjfIMSWhtDvNQbKLXvmMUU > +BEKA3VQwpA== > +-----END CERTIFICATE----- So not sure I like distributing this imho random collection of certificates. > diff --git a/doc/ChangeLog b/doc/ChangeLog > index 7f2d6ff4fd31..914f8f649511 100644 > --- a/doc/ChangeLog > +++ b/doc/ChangeLog > @@ -1,3 +1,10 @@ > +2023-08-14 Ryan Goldberg <rgold...@redhat.com> > + > + * debuginfod-client-config.7: Document DEBUGINFOD_IMA_CERT_PATH, > + update DEBUGINFOD_URLS. > + * debuginfod.8: Document --koji-sigcache > + * debuginfod-find.1, debuginfod_find_debuginfo.3: Update SECURITY > + > 2023-02-14 Mark Wielaard <m...@klomp.org> > > * debuginfod.8: Add .TP before -g. > diff --git a/doc/debuginfod-client-config.7 b/doc/debuginfod-client-config.7 > index 53d82806d395..11d2465858c5 100644 > --- a/doc/debuginfod-client-config.7 > +++ b/doc/debuginfod-client-config.7 > @@ -27,6 +27,34 @@ debuginfod instances. Alternate URL prefixes are > separated by space. > This environment variable may be set by /etc/profile.d scripts > reading /etc/debuginfod/*.urls files. > > +This environment variable can also contain policy defining tags which > +dictate the response policy for verifying per-file IMA signatures in > +RPMs. As the space seperated list is read left to right, upon > +encountering a tag, subsequent URLs up to the next tag will be handled > +using that specified policy. All URLs before the first tag will use > +the default policy, \fIima:permissive\fP. For example: > + > +.in +4n > +.EX > +DEBUGINFOD_URLS="https://foo.com ima:enforcing https://bar.ca > http://localhost:8002/ ima:permissive https://baz.org" > +.EE > +.in > + > +Where foo.com and baz.org use the default \fIpermissive\fP policy and > +bar.ca and localhost use an \fIenforcing\fP policy. The policy tag > +may be one of the following: > +.IP > +\fIima:enforcing\fP Every downloaded file requires a valid signature. > +.IP > +\fIima:permissive\fP Every downloaded file accompanied by a signature > +must be valid, but downloads without signatures are accepted. > +.IP > +\fIima:ignore\fP Skips verification altogether. > +.IP > + > +Alerts of validation failure will be directed as specified > +in $DEBUGINFOD_VERBOSE. > + > .TP > .B $DEBUGINFOD_CACHE_PATH > This environment variable governs the location of the cache where > @@ -82,6 +110,12 @@ outbound HTTP requests, one per line. The header lines > shouldn't end with > CRLF, unless that's the system newline convention. Whitespace-only lines > are skipped. > > +.TP > +.B $DEBUGINFOD_IMA_CERT_PATH > +This environment variable contains a list of absolute directory paths > +holding X.509 certificates for RPM per-file IMA-verification. > +Alternate paths are separated by colons. > + > .SH CACHE > > Before each query, the debuginfod client library checks for a need to OK. Nice documentation. Thanks. > diff --git a/doc/debuginfod-find.1 b/doc/debuginfod-find.1 > index 7d577babeb89..89a706728cd6 100644 > --- a/doc/debuginfod-find.1 > +++ b/doc/debuginfod-find.1 > @@ -129,10 +129,19 @@ and printing the http response headers from the server. > > .SH "SECURITY" > > -debuginfod-find \fBdoes not\fP include any particular security > -features. It trusts that the binaries returned by the debuginfod(s) > -are accurate. Therefore, the list of servers should include only > -trustworthy ones. If accessed across HTTP rather than HTTPS, the > +If IMA signature(s) are available from the RPMs that contain > +requested files, then > +.BR debuginfod > +will extract those signatures into response headers, and > +.BR debuginfod-find > +will perform verification upon the files. > +Validation policy is controlled via tags inserted into > +$DEBUGINFOD_URLS. By default, > +.BR debuginfod-find > +acts in permissive mode, only rejecting incorrect > +signatures. See below for details and other policy options. > + > +If accessed across HTTP rather than HTTPS, the > network should be trustworthy. Authentication information through > the internal \fIlibcurl\fP library is not currently enabled, except > for the basic plaintext \%\fIhttp[s]://userid:password@hostname/\fP style. OK. > diff --git a/doc/debuginfod.8 b/doc/debuginfod.8 > index d4316bec8175..3e73868715d7 100644 > --- a/doc/debuginfod.8 > +++ b/doc/debuginfod.8 > @@ -289,6 +289,14 @@ completed archive or file scans. This may slow down > parallel scanning > phase somewhat, but generate much smaller "-wal" temporary files on > busy servers. The default is 256. Disabled if 0. > > +.TP > +.B "\-\-koji\-sigcache" > +Enable an additional step of RPM path mapping when extracting signatures for > use > +in RPM per-file IMA verification on koji repositories. The signatures are > retrieved > +from the Fedora koji sigcache rpm.sig files as opposed to the original RPM > header. > +If a signature cannot be found in the sigcache rpm.sig file, the RPM will be > +tried as a fallback. > + > .TP > .B "\-v" > Increase verbosity of logging to the standard error file descriptor. > @@ -311,7 +319,8 @@ X-DEBUGINFOD-FILE is simply the unescaped filename and > X-DEBUGINFOD-SIZE is the size of the file. For files found in archives, > in addition to X-DEBUGINFOD-FILE and X-DEBUGINFOD-SIZE, > X-DEBUGINFOD-ARCHIVE is added. X-DEBUGINFOD-ARCHIVE is the name of the > -archive the file was found in. > +archive the file was found in. X-DEBUGINFOD-IMA-SIGNATURE contains the > +per-file IMA signature as a hexadecimal blob. > > There are three requests. In each case, the buildid is encoded as a > lowercase hexadecimal string. For example, for a program \fI/bin/ls\fP, OK. > diff --git a/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3 > index 6469a3dfb2db..e170b94367b5 100644 > --- a/doc/debuginfod_find_debuginfo.3 > +++ b/doc/debuginfod_find_debuginfo.3 > @@ -250,13 +250,22 @@ void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, > RTLD_LAZY); > .in > > .SH "SECURITY" > + > +If IMA signature(s) are available from the RPMs that contain > +requested files, then > +.BR debuginfod > +will extract those signatures into response headers, and > +.BR debuginfod_find_* () > +will perform verification upon the files. > +Validation policy is controlled via tags inserted into > +$DEBUGINFOD_URLS. By default, > .BR debuginfod_find_* () > -functions \fBdo not\fP include any particular security > -features. They trust that the binaries returned by the debuginfod(s) > -are accurate. Therefore, the list of servers should include only > -trustworthy ones. If accessed across HTTP rather than HTTPS, the > -network should be trustworthy. Passing user authentication information > -through the internal \fIlibcurl\fP library is not currently enabled, except > +acts in permissive mode, only rejecting incorrect > +signatures. See below for details and other policy options. > + > +If accessed across HTTP rather than HTTPS, the > +network should be trustworthy. Authentication information through > +the internal \fIlibcurl\fP library is not currently enabled, except > for the basic plaintext \%\fIhttp[s]://userid:password@hostname/\fP style. > (The debuginfod server does not perform authentication, but a front-end > proxy server could.) OK. > diff --git a/tests/ChangeLog b/tests/ChangeLog > index d816873ce083..e52470c04f49 100644 > --- a/tests/ChangeLog > +++ b/tests/ChangeLog > @@ -1,3 +1,11 @@ > +2023-08-14 Ryan Goldberg <rgold...@redhat.com> > + > + * run-debuginfod-ima-verification.sh: New test. > + * hello2-1.0-1.x86_64.rpm. New test file. > + * debuginfod-ima/koji. New test directory. > + * imacert.der. New test file. > + * Makefile.am (TESTS, EXTRA_DIST): Add it. > + > 2023-04-21 Frank Ch. Eigler <f...@redhat.com> > > * run-debuginfod-IXr.sh: New test. > diff --git a/tests/Makefile.am b/tests/Makefile.am > index 32b18e6ef633..130cc992c42e 100644 > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -273,6 +273,9 @@ if !OLD_LIBMICROHTTPD > # Too many open file descriptors confuses libmicrohttpd < 0.9.51 > TESTS += run-debuginfod-federation-metrics.sh > endif > +if ENABLE_IMA_VERIFICATION > +TESTS += run-debuginfod-ima-verification.sh > +endif > endif > > if HAVE_CXX11 > @@ -588,6 +591,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ > run-debuginfod-webapi-concurrency.sh \ > run-debuginfod-section.sh \ > run-debuginfod-IXr.sh \ > + run-debuginfod-ima-verification.sh \ > debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm \ > debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm \ > debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm \ > @@ -611,6 +615,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ > debuginfod-rpms/rhel7/hello2-debuginfo-1.0-2.x86_64.rpm \ > debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm \ > debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm \ > + debuginfod-ima/rhel9/hello2-1.0-1.x86_64.rpm \ > + debuginfod-ima/rhel9/imacert.der \ > + debuginfod-ima/koji \ > debuginfod-debs/hithere-dbgsym_1.0-1_amd64.ddeb \ > debuginfod-debs/hithere_1.0-1.debian.tar.xz \ > debuginfod-debs/hithere_1.0-1.dsc \ Should hello-2.10-9.fc38.x86_64.rpm.sig also be added to EXTRA_DIST? > diff --git a/tests/debuginfod-ima/koji/arch/hello-2.10-9.fc38.x86_64.rpm > b/tests/debuginfod-ima/koji/arch/hello-2.10-9.fc38.x86_64.rpm > new file mode 100644 > index 000000000000..b04ad8c2af39 > Binary files /dev/null and > b/tests/debuginfod-ima/koji/arch/hello-2.10-9.fc38.x86_64.rpm differ > diff --git > a/tests/debuginfod-ima/koji/data/sigcache/keyid/arch/hello-2.10-9.fc38.x86_64.rpm.sig > > b/tests/debuginfod-ima/koji/data/sigcache/keyid/arch/hello-2.10-9.fc38.x86_64.rpm.sig > new file mode 100644 > index 000000000000..ee7eb8e467b4 > Binary files /dev/null and > b/tests/debuginfod-ima/koji/data/sigcache/keyid/arch/hello-2.10-9.fc38.x86_64.rpm.sig > differ > diff --git a/tests/debuginfod-ima/rhel9/hello2-1.0-1.x86_64.rpm > b/tests/debuginfod-ima/rhel9/hello2-1.0-1.x86_64.rpm > new file mode 100644 > index 000000000000..0262ae2f0c4c > Binary files /dev/null and > b/tests/debuginfod-ima/rhel9/hello2-1.0-1.x86_64.rpm differ > diff --git a/tests/debuginfod-ima/rhel9/imacert.der > b/tests/debuginfod-ima/rhel9/imacert.der > new file mode 100644 > index 000000000000..b0250b6c30d5 > Binary files /dev/null and b/tests/debuginfod-ima/rhel9/imacert.der differ > diff --git a/tests/run-debuginfod-ima-verification.sh > b/tests/run-debuginfod-ima-verification.sh > new file mode 100755 > index 000000000000..45f3e7d037a6 > --- /dev/null > +++ b/tests/run-debuginfod-ima-verification.sh > @@ -0,0 +1,177 @@ > +#!/usr/bin/env bash > +# > +# Copyright (C) 2019-2023 Red Hat, Inc. > +# This file is part of elfutils. > +# > +# This file is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# elfutils is distributed in the hope that it will be useful, but > +# WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see <http://www.gnu.org/licenses/>. > + > +. $srcdir/debuginfod-subr.sh > + > +type rpmsign 2>/dev/null || { echo "need rpmsign"; exit 77; } Add rpmsign to elfutils.spec.in as BuildRequires? > +cat << EoF > include.c > +#include <rpm/rpmlib.h> > +#include <rpm/rpmfi.h> > +#include <rpm/header.h> > +#include <imaevm.h> > +#include <openssl/evp.h> > +EoF > +tempfiles include.c > +gcc -H -fsyntax-only include.c 2> /dev/null || { echo "one or more devel > packages are missing (rpm-devel, ima-evm-utils-devel, openssl-devel)"; exit > 77; } Isn't this redundant with the configure.ac checks? > +DB=${PWD}/.debuginfod_tmp.sqlite > +tempfiles $DB > +export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache > +IMA_POLICY="enforcing" > + > +# This variable is essential and ensures no time-race for claiming ports > occurs > +# set base to a unique multiple of 100 not used in any other > 'run-debuginfod-*' test > +base=14000 > +get_ports > +mkdir R > +env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= > ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -R \ > + -d $DB -p $PORT1 -t0 -g0 R > vlog$PORT1 2>&1 & > +PID1=$! > +tempfiles vlog$PORT1 > +errfiles vlog$PORT1 > + > +######################################################################## > +cp -pv ${abs_srcdir}/debuginfod-ima/rhel9/hello2-1.0-1.x86_64.rpm signed.rpm > +tempfiles signed.rpm > +RPM_BUILDID=460912dbc989106ec7325d243384df20c5ccec0c # /usr/local/bin/hello > + > +MIN_IMAEVM_MAJ_VERSION=3 > +MIN_RPM_MAJ_VERSION=4 > +# If the correct programs (and versions) exist sign the rpm in the test > +if (command -v openssl &> /dev/null) && \ > + (command -v rpmsign &> /dev/null) && \ > + (command -v gpg &> /dev/null) && \ > + [ $(ldd `which rpmsign` | grep libimaevm | awk -F'[^0-9]+' '{ print $2 > }') -ge $MIN_IMAEVM_MAJ_VERSION ] && \ > + [ $(rpm --version | awk -F'[^0-9]+' '{ print $2 }') -ge > $MIN_RPM_MAJ_VERSION ] > +then > + # SIGN THE RPM > + # First remove any old signatures > + rpmsign --delsign signed.rpm &> /dev/null > + rpmsign --delfilesign signed.rpm &> /dev/null > + > + # Make a gpg keypair (with $PWD as the homedir) > + mkdir -m 700 openpgp-revocs.d private-keys-v1.d > + gpg --quick-gen-key --yes --homedir ${PWD} --batch --passphrase '' > --no-default-keyring --keyring "${PWD}/pubring.kbx" exam...@elfutils.org 2> > /dev/null > + > + # Create a private DER signing key and a public X509 DER format > verification key pair > + openssl genrsa | openssl pkcs8 -topk8 -nocrypt -outform PEM -out > signing.pem > + openssl req -x509 -key signing.pem -out imacert.pem -days 365 -keyform > PEM \ > + -subj "/C=CA/ST=ON/L=TO/O=Elfutils/CN=www.sourceware.org\/elfutils" > + > + tempfiles openpgp-revocs.d/* private-keys-v1.d/* * openpgp-revocs.d > private-keys-v1.d > + > + rpmsign --addsign --signfiles --fskpath=signing.pem -D "_gpg_name > exam...@elfutils.org" -D "_gpg_path ${PWD}" signed.rpm > + cp signed.rpm R/signed.rpm > + VERIFICATION_CERT_DIR=${PWD} > + > + # Cleanup > + rm -rf openpgp-revocs.d private-keys-v1.d > +else > + # USE A PRESIGNED RPM > + cp signed.rpm R/signed.rpm > + # Note we test with no trailing / > + VERIFICATION_CERT_DIR=${abs_srcdir}/debuginfod-ima/rhel9 > +fi It seems simpler to just add openssl and gpg to BuildRequires and the at the start of the test. If you really want a presigned RPM add another test? > +######################################################################## > +# Server must become ready with R fully scanned and indexed > +wait_ready $PORT1 'ready' 1 > +wait_ready $PORT1 'thread_work_total{role="traverse"}' 1 > +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 > +wait_ready $PORT1 'thread_busy{role="scan"}' 0 > + > +export DEBUGINFOD_URLS="ima:$IMA_POLICY http://127.0.0.1:$PORT1" > + > +# Test 1: Without a certificate the verification should fail > +export DEBUGINFOD_IMA_CERT_PATH= > +RC=0 > +testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vv executable > $RPM_BUILDID || RC=1 > +test $RC -ne 0 > + > +# Test 2: It should pass once the certificate is added to the path > +export DEBUGINFOD_IMA_CERT_PATH=$VERIFICATION_CERT_DIR > +rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests > +kill -USR1 $PID1 > +wait_ready $PORT1 'thread_work_total{role="traverse"}' 2 > +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 > +wait_ready $PORT1 'thread_busy{role="scan"}' 0 > +testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vv executable > $RPM_BUILDID > + > +# Test 3: Corrupt the data and it should fail > +dd if=/dev/zero of=R/signed.rpm bs=1 count=128 seek=1024 conv=notrunc > +rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests > +kill -USR1 $PID1 > +wait_ready $PORT1 'thread_work_total{role="traverse"}' 3 > +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 > +wait_ready $PORT1 'thread_busy{role="scan"}' 0 > +RC=0 > +testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable > $RPM_BUILDID || RC=1 > +test $RC -ne 0 > + > +# Test 4: A rpm without a signature will fail > +cp signed.rpm R/signed.rpm > +rpmsign --delfilesign R/signed.rpm > +rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests > +kill -USR1 $PID1 > +wait_ready $PORT1 'thread_work_total{role="traverse"}' 4 > +wait_ready $PORT1 'thread_work_pending{role="scan"}' 0 > +wait_ready $PORT1 'thread_busy{role="scan"}' 0 > +RC=0 > +testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable > $RPM_BUILDID || RC=1 > +test $RC -ne 0 > + > +# Test 5: Only tests 1,2 will result in extracted signature > +[[ $(curl -s http://127.0.0.1:$PORT1/metrics | grep > 'http_responses_total{extra="ima-sigs-extracted"}' | awk '{print $NF}') -eq 2 > ]] > + > +kill $PID1 > +wait $PID1 > +PID1=0 > + > +####################################################################### > +# We also test the --koji-sigcache > +cp -pR ${abs_srcdir}/debuginfod-ima/koji R/koji > + > +rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests > +env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= > ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -R \ > + -d $DB -p $PORT2 -t0 -g0 -X /data/ --koji-sigcache R/koji > vlog$PORT1 > 2>&1 & > +#reuse PID1 > +PID1=$! > +tempfiles vlog$PORT2 > +errfiles vlog$PORT2 > + > +RPM_BUILDID=c592a95e45625d7891b90f6b86e63373d540461d #/usr/bin/hello > +# Note we test with a trailing slash and with the required directory as the > third in the PATH > +VERIFICATION_CERT_DIR=/not/a/dir:${abs_srcdir}/debuginfod-ima/rhel9:${abs_srcdir}/../debuginfod/ima-certs/ > + > +######################################################################## > +# Server must become ready with koji fully scanned and indexed > +wait_ready $PORT2 'ready' 1 > +wait_ready $PORT2 'thread_work_total{role="traverse"}' 1 > +wait_ready $PORT2 'thread_work_pending{role="scan"}' 0 > +wait_ready $PORT2 'thread_busy{role="scan"}' 0 > + > +# Test 1: The path should be properly mapped and verified using the actual > fedora 38 cert > +export DEBUGINFOD_URLS="ima:$IMA_POLICY http://127.0.0.1:$PORT2" > +export DEBUGINFOD_IMA_CERT_PATH=$VERIFICATION_CERT_DIR > +testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vv executable > $RPM_BUILDID > + > +kill $PID1 > +wait $PID1 > +PID1=0 > + > +exit 0 I haven't ran the tests but it looks OK. Thanks, Mark