michal-grzedzicki / rpms / rpm

Forked from rpms/rpm 4 months ago
Clone

Blame SOURCES/0003-Verify-packages-before-signing-RhBug-1646388.patch

0b2921
From df089e178da0918dc74a8572a99324b0987bce30 Mon Sep 17 00:00:00 2001
0b2921
Message-Id: <df089e178da0918dc74a8572a99324b0987bce30.1554983206.git.pmatilai@redhat.com>
0b2921
In-Reply-To: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
0b2921
References: <2ec0832287bd1443ebf336f8a98293f30bfa2036.1554983205.git.pmatilai@redhat.com>
0b2921
From: Panu Matilainen <pmatilai@redhat.com>
0b2921
Date: Mon, 18 Mar 2019 15:56:34 +0200
0b2921
Subject: [PATCH 3/3] Verify packages before signing (RhBug:1646388)
0b2921
0b2921
Permitting corrupted packages to be signed is bad business for everybody
0b2921
involved, this is something we should've always done. Besides being an
0b2921
actual security risk, it can lead to odd results with verification
0b2921
especially with the payload digest on signed packages.
0b2921
0b2921
One point worth noting is that this means that pre 4.14-packages cannot
0b2921
be signed in FIPS mode now because there's no way to validate the package
0b2921
payload range due to MD5 being disabled. This seems like a feature and
0b2921
not a limitation, so disabler for the verify step intentionally left out.
0b2921
0b2921
Optimally we'd verify the package on the same read that's passed
0b2921
to gpg but for simplicitys sake that's left as an future exercise,
0b2921
now we simply read the package twice.
0b2921
---
0b2921
 sign/rpmgensig.c   | 32 ++++++++++++++++++++++++++++++++
0b2921
 tests/rpmsigdig.at | 20 ++++++++++++++++++++
0b2921
 2 files changed, 52 insertions(+)
0b2921
0b2921
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
0b2921
index 2bcbab768..5be542001 100644
0b2921
--- a/sign/rpmgensig.c
0b2921
+++ b/sign/rpmgensig.c
0b2921
@@ -21,6 +21,7 @@
0b2921
 
0b2921
 #include "lib/rpmlead.h"
0b2921
 #include "lib/signature.h"
0b2921
+#include "lib/rpmvs.h"
0b2921
 #include "sign/rpmsignfiles.h"
0b2921
 
0b2921
 #include "debug.h"
0b2921
@@ -489,6 +490,31 @@ static rpmRC includeFileSignatures(Header *sigp, Header *hdrp)
0b2921
 #endif
0b2921
 }
0b2921
 
0b2921
+static int msgCb(struct rpmsinfo_s *sinfo, void *cbdata)
0b2921
+{
0b2921
+    char **msg = cbdata;
0b2921
+    if (sinfo->rc && *msg == NULL)
0b2921
+	*msg = rpmsinfoMsg(sinfo);
0b2921
+    return (sinfo->rc != RPMRC_FAIL);
0b2921
+}
0b2921
+
0b2921
+/* Require valid digests on entire package for signing. */
0b2921
+static int checkPkg(FD_t fd, char **msg)
0b2921
+{
0b2921
+    int rc;
0b2921
+    struct rpmvs_s *vs = rpmvsCreate(RPMSIG_DIGEST_TYPE, 0, NULL);
0b2921
+    off_t offset = Ftell(fd);
0b2921
+
0b2921
+    Fseek(fd, 0, SEEK_SET);
0b2921
+    rc = rpmpkgRead(vs, fd, NULL, NULL, msg);
0b2921
+    if (!rc)
0b2921
+	rc = rpmvsVerify(vs, RPMSIG_DIGEST_TYPE, msgCb, msg);
0b2921
+    Fseek(fd, offset, SEEK_SET);
0b2921
+
0b2921
+    rpmvsFree(vs);
0b2921
+    return rc;
0b2921
+}
0b2921
+
0b2921
 /** \ingroup rpmcli
0b2921
  * Create/modify elements in signature header.
0b2921
  * @param rpm		path to package
0b2921
@@ -519,6 +545,12 @@ static int rpmSign(const char *rpm, int deleting, int signfiles)
0b2921
     if (manageFile(&fd, rpm, O_RDWR))
0b2921
 	goto exit;
0b2921
 
0b2921
+    /* Ensure package is intact before attempting to sign */
0b2921
+    if ((rc = checkPkg(fd, &msg))) {
0b2921
+	rpmlog(RPMLOG_ERR, "not signing corrupt package %s: %s\n", rpm, msg);
0b2921
+	goto exit;
0b2921
+    }
0b2921
+
0b2921
     if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) {
0b2921
 	rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg);
0b2921
 	goto exit;
0b2921
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
0b2921
index 413c3d2c8..e93420306 100644
0b2921
--- a/tests/rpmsigdig.at
0b2921
+++ b/tests/rpmsigdig.at
0b2921
@@ -472,3 +472,23 @@ run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}"/tmp/hello-2.0-1.x86_64-sign
0b2921
 [],
0b2921
 [])
0b2921
 AT_CLEANUP
0b2921
+
0b2921
+AT_SETUP([rpmsign --addsign <corrupted>])
0b2921
+AT_KEYWORDS([rpmsign signature])
0b2921
+AT_CHECK([
0b2921
+RPMDB_CLEAR
0b2921
+RPMDB_INIT
0b2921
+rm -rf "${TOPDIR}"
0b2921
+
0b2921
+pkg="hello-2.0-1.x86_64.rpm"
0b2921
+cp "${RPMTEST}"/data/RPMS/${pkg} "${RPMTEST}"/tmp/${pkg}
0b2921
+dd if=/dev/zero of="${RPMTEST}"/tmp/${pkg} \
0b2921
+   conv=notrunc bs=1 seek=333 count=4 2> /dev/null
0b2921
+run rpmsign --key-id 1964C5FC --addsign "${RPMTEST}/tmp/${pkg}"
0b2921
+],
0b2921
+[1],
0b2921
+[/home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm:
0b2921
+],
0b2921
+[error: not signing corrupt package /home/pmatilai/repos/rpm/tests/testing/tmp/hello-2.0-1.x86_64.rpm: MD5 digest: BAD (Expected 007ca1d8b35cca02a1854ba301c5432e != 137ca1d8b35cca02a1854ba301c5432e)
0b2921
+])
0b2921
+AT_CLEANUP
0b2921
-- 
0b2921
2.20.1
0b2921