From 7da1e826ccb08fdd404524146736b3f12a473e31 Mon Sep 17 00:00:00 2001 From: chantra Date: Mon, 31 Jan 2022 14:42:25 -0800 Subject: [PATCH 10/30] [rpm2extents] Make rpmkeys support reading metadata from transcoded footer If the file is seekable and is a transcoded file, read signature validation from transcoded file tail metadata --- lib/rpmchecksig.c | 112 ++++++++++++++++++++++++++++++++++++++++++- tests/rpm2extents.at | 34 ++++++++++++- 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index fcdbb424f..6164d012c 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -24,6 +24,11 @@ #include "debug.h" +/* magic value at end of file (64 bits) that indicates this is a transcoded + * rpm. + */ +#define MAGIC 3472329499408095051 + static int doImport(rpmts ts, const char *fn, char *buf, ssize_t blen) { char const * const pgpmark = "-----BEGIN PGP "; @@ -220,6 +225,107 @@ exit: return rc; } +static rpmRC isTranscodedRpm(FD_t fd) { + rpmRC rc = RPMRC_NOTFOUND; + rpm_loff_t current; + uint64_t magic; + size_t len; + + // If the file is not seekable, we cannot detect whether or not it is transcoded. + if(Fseek(fd, 0, SEEK_CUR) < 0) { + return RPMRC_FAIL; + } + current = Ftell(fd); + + if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) { + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n")); + rc = RPMRC_FAIL; + goto exit; + } + len = sizeof(magic); + if (Fread(&magic, len, 1, fd) != len) { + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n")); + rc = RPMRC_FAIL; + goto exit; + } + if (magic != MAGIC) { + rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n")); + rc = RPMRC_NOTFOUND; + goto exit; + } + rc = RPMRC_OK; +exit: + if (Fseek(fd, current, SEEK_SET) < 0) { + rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to seek back to original location\n")); + } + return rc; +} + +static int rpmpkgVerifySigsTranscoded(FD_t fd){ + rpm_loff_t current; + uint64_t magic; + rpm_loff_t offset; + int32_t rc; + size_t len; + uint64_t content_len; + char *content = NULL; + + current = Ftell(fd); + + if(Fseek(fd, -(sizeof(magic) + 3 * sizeof(offset) ), SEEK_END) < 0) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: failed to seek for offset\n")); + rc = -1; + goto exit; + } + + len = sizeof(offset); + if (Fread(&offset, len, 1, fd) != len) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification offset\n")); + rc = -1; + goto exit; + } + + if(Fseek(fd, offset, SEEK_SET) < 0) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to seek signature verification offset\n")); + rc = -1; + goto exit; + } + len = sizeof(rc); + if (Fread(&rc, len, 1, fd) != len) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification RC\n")); + rc = -1; + goto exit; + } + + len = sizeof(content_len); + if (Fread(&content_len, len, 1, fd) != len) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content length\n")); + goto exit; + } + + content = malloc(content_len + 1); + if(content == NULL) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to allocate memory to read signature content\n")); + goto exit; + } + content[content_len] = 0; + if (Fread(content, content_len, 1, fd) != content_len) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content\n")); + goto exit; + } + + rpmlog(RPMLOG_NOTICE, "%s", content); +exit: + if(content){ + free(content); + } + if (Fseek(fd, current, SEEK_SET) < 0) { + rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: unable to seek back to original location\n")); + } + return rc; + +} + static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, FD_t fd, const char *fn) { @@ -229,10 +335,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, .verbose = rpmIsVerbose(), }; int rc; - struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : ""); + if(isTranscodedRpm(fd) == RPMRC_OK){ + return rpmpkgVerifySigsTranscoded(fd); + } + struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); + rc = rpmpkgRead(vs, fd, NULL, NULL, &msg); if (rc) diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at index baea987e4..18accfc75 100644 --- a/tests/rpm2extents.at +++ b/tests/rpm2extents.at @@ -29,7 +29,7 @@ AT_CHECK([runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rp [ignore]) AT_CLEANUP -# Check that tailer writes checksig return code and content. +# Check that transcoder writes checksig return code and content. # AT_SETUP([rpm2extents signature]) AT_KEYWORDS([rpm2extents digest signature]) @@ -62,3 +62,35 @@ RPMSignOutput Content Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK ], []) AT_CLEANUP + +AT_SETUP([rpm2extents signature verification]) +AT_KEYWORDS([rpm2extents digest signature]) +AT_CHECK([ +RPMDB_INIT + +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64-signed.rpm 2> /dev/null +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $? +runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub +runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64-signed.rpm +runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $? +], +[0], +[/tmp/hello-2.0-1.x86_64-signed.rpm: + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 digest: OK + V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY + MD5 digest: OK +1 +/tmp/hello-2.0-1.x86_64-signed.rpm: + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 digest: OK + V4 RSA/SHA256 Signature, key ID 1964c5fc: OK + MD5 digest: OK +0 +], +[]) +AT_CLEANUP -- 2.35.1