From cb7f454b48017f5d21818b163a208f3c83daf9d9 Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Tue, 16 Mar 2021 22:12:05 -0400 Subject: Header signatures alone are not sufficient MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes how RPM handles packages that contain a header signature, but neither header+payload signature nor payload digests. Such packages are obviously not properly signed, but RPM previously accepted them. This could be used to confuse both ‘rpmkeys -K’ and old versions of DNF. Both would report that the package has been properly signed even when it has not. The included regression tests demonstrates the change in behavior. (cherry picked from commit 0e9f6fdc63f09ebd00516e6f2f46a7297b743bcd) --- lib/rpmvs.c | 14 ++++++-- tests/Makefile.am | 1 + tests/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm | Bin 0 -> 3216 bytes tests/rpmsigdig.at | 40 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 tests/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm diff --git a/lib/rpmvs.c b/lib/rpmvs.c index 20a3e28a2..88f2b200f 100644 --- a/lib/rpmvs.c +++ b/lib/rpmvs.c @@ -451,7 +451,7 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, { int failed = 0; int cont = 1; - int range = 0; + int range = 0, vfylevel = sis->vfylevel; int verified[3] = { 0, 0, 0 }; /* sort for consistency and rough "better comes first" semantics*/ @@ -478,6 +478,14 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, } } + /* Unconditionally reject partially signed packages */ + if (verified[RPMSIG_SIGNATURE_TYPE]) + vfylevel |= RPMSIG_SIGNATURE_TYPE; + + /* Cannot verify payload if RPMVSF_NEEDPAYLOAD is set */ + if (sis->vsflags & RPMVSF_NEEDPAYLOAD) + range &= ~RPMSIG_PAYLOAD; + for (int i = 0; i < sis->nsigs && cont; i++) { struct rpmsinfo_s *sinfo = &sis->sigs[i]; int strength = (sinfo->type | sinfo->strength); @@ -490,11 +498,11 @@ int rpmvsVerify(struct rpmvs_s *sis, int type, sinfo->rc = RPMRC_NOTFOUND; } - if (sis->vfylevel & strength & RPMSIG_DIGEST_TYPE) { + if (vfylevel & strength & RPMSIG_DIGEST_TYPE) { int missing = (range & ~verified[RPMSIG_DIGEST_TYPE]); required |= (missing & sinfo->range); } - if (sis->vfylevel & strength & RPMSIG_SIGNATURE_TYPE) { + if (vfylevel & strength & RPMSIG_SIGNATURE_TYPE) { int missing = (range & ~verified[RPMSIG_SIGNATURE_TYPE]); required |= (missing & sinfo->range); } diff --git a/tests/Makefile.am b/tests/Makefile.am index 0840075fb..c66e801da 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -103,6 +103,7 @@ EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64.rpm EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64-signed.rpm EXTRA_DIST += data/RPMS/hlinktest-1.0-1.noarch.rpm EXTRA_DIST += data/RPMS/imatest-1.0-1.fc34.noarch.rpm +EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64-corrupted.rpm EXTRA_DIST += data/SRPMS/foo-1.0-1.src.rpm EXTRA_DIST += data/SRPMS/hello-1.0-1.src.rpm EXTRA_DIST += data/SOURCES/hello.c diff --git a/tests/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm b/tests/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm new file mode 100644 index 000000000..2a6173ba0 Binary files /dev/null and b/tests/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm differ diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at index d60c58869..f8373c640 100644 --- a/tests/rpmsigdig.at +++ b/tests/rpmsigdig.at @@ -445,11 +445,51 @@ runroot rpmkeys -Kv /tmp/${pkg} Payload SHA256 digest: BAD (Expected 84a7338287bf19715c4eed0243f5cdb447eeb0ade37b2af718d4060aefca2f7c != bea903609dceac36e1f26a983c493c98064d320fdfeb423034ed63d649b2c8dc) Payload SHA256 ALT digest: NOTFOUND V4 RSA/SHA256 Signature, key ID 1964c5fc: BAD + DSA signature: NOTFOUND MD5 digest: BAD (Expected 137ca1d8b35cca02a1854ba301c5432e != d662cd0d81601a7107312684ad1ddf38) ], []) AT_CLEANUP +# ------------------------------ +# Test pre-built corrupted package verification (corrupted payload) +AT_SETUP([rpmkeys -Kv 4]) +AT_KEYWORDS([rpmkeys digest signature]) +AT_CHECK([ +RPMDB_INIT[( + +dorpm () { + runroot rpmkeys --define '_pkgverify_level digest' \ + --define '_pkgverify_flags 0x10000' "$1" \ + /data/RPMS/hello-2.0-1.x86_64-corrupted.rpm + [ "$?" -eq 1 ] || exit 1 +} + +dorpm -K +dorpm -Kv +runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub +dorpm -K +dorpm -Kv +)]], +[0], +[[/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm: digests SIGNATURES NOT OK +/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm: + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY + Header SHA256 digest: OK + MD5 digest: OK +/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm: DIGESTS SIGNATURES NOT OK +/data/RPMS/hello-2.0-1.x86_64-corrupted.rpm: + Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK + Header SHA256 digest: OK + Payload SHA256 digest: NOTFOUND + Payload SHA256 ALT digest: NOTFOUND + RSA signature: NOTFOUND + DSA signature: NOTFOUND + MD5 digest: OK +]], +[]) +AT_CLEANUP + # ------------------------------ # Test --addsign AT_SETUP([rpmsign --addsign]) -- cgit v1.2.1