[Rpm-maint] [PATCH v9 09/13] Add file signature support to package signing
Fionnuala Gunter
fionnuala.gunter at gmail.com
Tue Jul 21 17:00:43 UTC 2015
From: "fin at linux.vnet.ibm.com" <fin at linux.vnet.ibm.com>
This patch modifies rpmSign to include file signatures in the header.
Since the header is altered, the package digest and package+archive
digest need to be recalculated and updated in the signature header.
Defer resigning the header digests to replaceSignature().
Changelog:
- removed extraneous semicolon - Mimi
- Update signature header digests only if necessary - Mimi
- deallocate sigp before it's overriden - Fin
- fix dependency on ima - Fin
- replace utd parameter with a local variable - Mimi
- fix sigsize - Fin
- calculate MD5 digest with SHA1 - Fin
- removed unused buffer - Fin
---
lib/rpmsignfiles.c | 2 +-
sign/rpmgensig.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 165 insertions(+), 7 deletions(-)
diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
index 376f47e..414983b 100644
--- a/lib/rpmsignfiles.c
+++ b/lib/rpmsignfiles.c
@@ -37,7 +37,7 @@ static char *signFile(const char *algo, const char *fdigest, int diglen, const c
unsigned char signature[MAX_SIGNATURE_LENGTH];
int siglen;
-#ifndef IMAEVM
+#ifndef WITH_IMAEVM
rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
return NULL;
#endif
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index b0bed44..bc50ee4 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -17,9 +17,11 @@
#include <rpm/rpmfileutil.h> /* rpmMkTemp() */
#include <rpm/rpmlog.h>
#include <rpm/rpmstring.h>
+#include <rpmio/rpmio_internal.h>
#include "lib/rpmlead.h"
#include "lib/signature.h"
+#include "lib/rpmsignfiles.h"
#include "debug.h"
@@ -471,9 +473,10 @@ static int replaceSignature(Header sigh, sigTarget sigt1, sigTarget sigt2)
return rc;
}
-static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag, rpmtd utd)
+static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
{
- struct rpmtd_s copytd;
+ struct rpmtd_s copytd, td;
+ rpmtd utd = &td;
Header nh;
Header oh;
HeaderIterator hi;
@@ -498,13 +501,164 @@ static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag, rpmtd utd)
}
}
+static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
+ off_t sigStart, off_t sigTargetSize,
+ char *SHA1, uint8_t *MD5)
+{
+ off_t archiveSize;
+ rpmRC rc = RPMRC_OK;
+
+ if (Fseek(fd, sigStart, SEEK_SET) < 0) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
+ rpm, Fstrerror(fd));
+ goto exit;
+ }
+
+ /* Get payload size from signature tag */
+ archiveSize = headerGetNumber(*sigp, RPMSIGTAG_PAYLOADSIZE);
+ if (!archiveSize) {
+ archiveSize = headerGetNumber(*sigp, RPMSIGTAG_LONGARCHIVESIZE);
+ }
+
+ /* Replace old digests in sigh */
+ rc = rpmGenerateSignature(SHA1, MD5, sigTargetSize, archiveSize, fd);
+ if (rc != RPMRC_OK) {
+ rpmlog(RPMLOG_ERR, _("generateSignature failed\n"));
+ goto exit;
+ }
+
+ if (Fseek(fd, sigStart, SEEK_SET) < 0) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
+ rpm, Fstrerror(fd));
+ goto exit;
+ }
+
+ headerFree(*sigp);
+ rc = rpmReadSignature(fd, sigp, RPMSIGTYPE_HEADERSIG, NULL);
+ if (rc != RPMRC_OK) {
+ rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n"));
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
+
+static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
+ Header *sigp, Header *hdrp,
+ off_t sigStart, off_t headerStart)
+{
+ FD_t ofd = NULL;
+ char *trpm = NULL;
+ const char *key;
+ char *SHA1 = NULL;
+ uint8_t *MD5 = NULL;
+ size_t sha1len;
+ size_t md5len;
+ off_t sigTargetSize;
+ rpmRC rc = RPMRC_OK;
+ struct rpmtd_s osigtd;
+ char *o_sha1 = NULL;
+ uint8_t o_md5[16];
+
+#ifndef WITH_IMAEVM
+ rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
+ return RPMRC_FAIL;
+#endif
+ unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE);
+
+ key = rpmExpand("%{?_file_signing_key}", NULL);
+
+ rc = rpmSignFiles(*hdrp, key);
+ if (rc != RPMRC_OK) {
+ goto exit;
+ }
+
+ *hdrp = headerReload(*hdrp, RPMTAG_HEADERIMMUTABLE);
+ if (*hdrp == NULL) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("headerReload failed\n"));
+ goto exit;
+ }
+
+ ofd = rpmMkTempFile(NULL, &trpm);
+ if (ofd == NULL || Ferror(ofd)) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
+ goto exit;
+ }
+
+ /* Copy archive to temp file */
+ if (copyFile(&fd, rpm, &ofd, trpm)) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
+ goto exit;
+ }
+
+ if (Fseek(fd, headerStart, SEEK_SET) < 0) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
+ rpm, Fstrerror(fd));
+ goto exit;
+ }
+
+ /* Start MD5 calculation */
+ fdInitDigest(fd, PGPHASHALGO_MD5, 0);
+
+ /* Write header to rpm and recalculate SHA1 */
+ fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
+ rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
+ if (rc != RPMRC_OK) {
+ rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
+ goto exit;
+ }
+ fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, &sha1len, 1);
+
+ /* Copy archive from temp file */
+ if (Fseek(ofd, 0, SEEK_SET) < 0) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
+ rpm, Fstrerror(fd));
+ goto exit;
+ }
+ if (copyFile(&ofd, trpm, &fd, rpm)) {
+ rc = RPMRC_FAIL;
+ rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
+ goto exit;
+ }
+ unlink(trpm);
+
+ sigTargetSize = Ftell(fd) - headerStart;
+ fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&MD5, &md5len, 0);
+
+ if (headerGet(*sigp, RPMSIGTAG_MD5, &osigtd, HEADERGET_DEFAULT))
+ memcpy(o_md5, osigtd.data, 16);
+
+ if (headerGet(*sigp, RPMSIGTAG_SHA1, &osigtd, HEADERGET_DEFAULT))
+ o_sha1 = xstrdup(osigtd.data);
+
+ if (memcmp(MD5, o_md5, md5len) == 0 && strcmp(SHA1, o_sha1) == 0)
+ rpmlog(RPMLOG_WARNING,
+ _("%s already contains identical file signatures\n"),
+ rpm);
+ else
+ replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA1, MD5);
+
+exit:
+if (ofd) (void) closeFile(&ofd);
+ return rc;
+}
+
/** \ingroup rpmcli
* Create/modify elements in signature header.
* @param rpm path to package
* @param deleting adding or deleting signature?
+ * @param signfiles sign files if non-zero
* @return 0 on success, -1 on error
*/
-static int rpmSign(const char *rpm, int deleting)
+static int rpmSign(const char *rpm, int deleting, int signfiles)
{
FD_t fd = NULL;
FD_t ofd = NULL;
@@ -555,7 +709,11 @@ static int rpmSign(const char *rpm, int deleting)
goto exit;
}
- unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES, &utd);
+ if (signfiles) {
+ includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
+ }
+
+ unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
if (deleting) { /* Nuke all the signature tags. */
@@ -704,7 +862,7 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs * args)
}
}
- rc = rpmSign(path, 0);
+ rc = rpmSign(path, 0, args->signfiles);
if (args) {
if (args->hashalgo) {
@@ -720,5 +878,5 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs * args)
int rpmPkgDelSign(const char *path)
{
- return rpmSign(path, 1);
+ return rpmSign(path, 1, 0);
}
--
2.4.3
More information about the Rpm-maint
mailing list