[Rpm-maint] [PATCH 4/4] Sign package files during installation
fin at linux.vnet.ibm.com
fin at linux.vnet.ibm.com
Tue Oct 7 20:19:18 UTC 2014
From: Fionnuala Gunter <fin at linux.vnet.ibm.com>
It will take some time for distros to adopt the file signing process and
distribute packages with file signatures, so this patch extends the rpm
installer to support inline file signing. This patch adds a new option,
signfiles, to the rpm installer.
rpm -ivh [--signfiles [--fskpath <file signing key>]] PACKAGE_FILE ...
Signed-off-by: Fionnuala Gunter <fin at linux.vnet.ibm.com>
---
doc/rpm.8 | 28 +++++++++++++++++++---------
lib/fsm.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
lib/poptI.c | 7 +++++++
lib/rpmcli.h | 2 ++
lib/rpminstall.c | 10 +++++++++-
lib/rpmts.c | 15 +++++++++++++++
lib/rpmts.h | 15 +++++++++++++++
lib/rpmts_internal.h | 2 ++
8 files changed, 114 insertions(+), 15 deletions(-)
diff --git a/doc/rpm.8 b/doc/rpm.8
index e583009..4079f71 100644
--- a/doc/rpm.8
+++ b/doc/rpm.8
@@ -84,15 +84,14 @@ rpm \- RPM Package Manager
[\fB--allfiles\fR] [\fB--badreloc\fR] [\fB--excludepath \fIOLDPATH\fB\fR]
- [\fB--excludedocs\fR] [\fB--force\fR] [\fB-h,--hash\fR]
- [\fB--ignoresize\fR] [\fB--ignorearch\fR] [\fB--ignoreos\fR]
- [\fB--includedocs\fR] [\fB--justdb\fR] [\fB--nocollections\fR]
- [\fB--nodeps\fR] [\fB--nodigest\fR] [\fB--nosignature\fR]
- [\fB--noorder\fR] [\fB--noscripts\fR] [\fB--notriggers\fR]
- [\fB--oldpackage\fR] [\fB--percent\fR] [\fB--prefix \fINEWPATH\fB\fR]
- [\fB--relocate \fIOLDPATH\fB=\fINEWPATH\fB\fR]
- [\fB--replacefiles\fR] [\fB--replacepkgs\fR]
- [\fB--test\fR]
+ [\fB--excludedocs\fR] [\fB--force\fR] [\fB--fskpath \fIKEY\fB\fR]
+ [\fB-h,--hash\fR] [\fB--ignoresize\fR] [\fB--ignorearch\fR]
+ [\fB--ignoreos\fR] [\fB--includedocs\fR] [\fB--justdb\fR]
+ [\fB--nocollections\fR] [\fB--nodeps\fR] [\fB--nodigest\fR]
+ [\fB--nosignature\fR] [\fB--noorder\fR] [\fB--noscripts\fR]
+ [\fB--notriggers\fR] [\fB--oldpackage\fR] [\fB--percent\fR]
+ [\fB--prefix \fINEWPATH\fB\fR] [\fB--relocate \fIOLDPATH\fB=\fINEWPATH\fB\fR]
+ [\fB--replacefiles\fR] [\fB--replacepkgs\fR] [\fB--signfiles] [\fB--test\fR]
.SH "DESCRIPTION"
.PP
@@ -232,6 +231,9 @@ Don't install files whose name begins with
Don't install any files which are marked as documentation
(which includes man pages and texinfo documents).
.TP
+\fB--fskpath \fIKEY\fB\fR
+Used with \fB--signfiles\fR, use file signing key \fIKEY\fR.
+.TP
\fB--force\fR
Same as using
\fB--replacepkgs\fR,
@@ -362,6 +364,13 @@ already installed, packages.
Install the packages even if some of them are already installed
on this system.
.TP
+\fB--signfiles\fR
+Sign package files. The macro \fB%_binary_filedigest_algorithm\fR must be set
+before building the package, and the macro must be set to a supported algorithm:
+2, 8, 9, or 10, which represent SHA1, SHA256, SHA384, and SHA512, respectively.
+The file signing key (RSA private key) can be configured on the command line
+with \fB--fskpath\fR or the macro \fB%_file_signing_key\fR.
+.TP
\fB--test\fR
Do not install the package, simply check for and report
potential conflicts.
@@ -875,4 +884,5 @@ what's available.
Marc Ewing <marc at redhat.com>
Jeff Johnson <jbj at redhat.com>
Erik Troan <ewt at redhat.com>
+Fionnuala Gunter <fin at linux.vnet.ibm.com>
.fi
diff --git a/lib/fsm.c b/lib/fsm.c
index dbeeaab..05ea230 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -21,6 +21,7 @@
#include "lib/rpmplugins.h" /* rpm plugins hooks */
#include "lib/rpmug.h"
#include "lib/rpmlib.h"
+#include "lib/rpmsignfiles.h" /* getDigestAlgo, getDigestLength, signFile */
#include "debug.h"
@@ -825,8 +826,13 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
const char *suffix;
char *fpath = NULL;
Header h = rpmteHeader(te);
- struct rpmtd_s sigs;
- char *sig = NULL;
+ struct rpmtd_s digests, sigs;
+ int signFiles = rpmtsSignFiles(ts);
+ const char *key;
+ const char *algo;
+ const char *digest;
+ const char *sig;
+ int diglen = 0;
if (fi == NULL) {
rc = RPMERR_BAD_MAGIC;
@@ -838,7 +844,30 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
goto exit;
}
- headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
+ if (signFiles) {
+ algo = getDigestAlgo(h);
+ if (!algo) {
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+
+ diglen = getDigestLength(h);
+ if (diglen < 0) {
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+
+ key = rpmExpand("%{_file_signing_key}", NULL);
+ if (rstreq(key, "")) {
+ rc = RPMRC_FAIL;
+ fprintf(stderr, _("You must set \"$$_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
+ rpmlog(RPMLOG_ERR, _("no file signing key provided\n"));
+ }
+
+ headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
+ } else {
+ headerGet(h, RPMTAG_FILESIGNATURES, &sigs, HEADERGET_MINMEM);
+ }
/* transaction id used for temporary path suffix while installing */
rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
@@ -964,12 +993,22 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
if (rc)
*failedFile = xstrdup(fpath);
- /* get file signatures from header */
- if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
+ /* sign executable files */
+ if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH) && signFiles) {
+ digest = rpmtdNextString(&digests);
+ sig = signFile(algo, digest, diglen, key);
+ if (!sig) {
+ rpmlog(RPMLOG_ERR, _("signFile failed\n"));
+ goto exit;
+ }
+ }
+ /* or get file signatures from header */
+ else if (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
sig = rpmtdNextString(&sigs);
} else {
sig = NULL;
rpmtdNextString(&sigs);
+ rpmtdNextString(&digests);
}
/* Run fsm file post hook for all plugins */
@@ -984,6 +1023,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
exit:
/* No need to bother with close errors on read */
+ rpmtdFreeData(&digests);
rpmtdFreeData(&sigs);
headerFree(h);
rpmfiArchiveClose(fi);
diff --git a/lib/poptI.c b/lib/poptI.c
index e21cde1..699c8cd 100644
--- a/lib/poptI.c
+++ b/lib/poptI.c
@@ -16,8 +16,10 @@ struct rpmInstallArguments_s rpmIArgs = {
0, /* numRelocations */
0, /* noDeps */
0, /* incldocs */
+ 0, /* signFiles */
NULL, /* relocations */
NULL, /* prefix */
+ NULL, /* fileSigningKey */
};
#define POPT_RELOCATE -1021
@@ -146,6 +148,9 @@ struct poptOption rpmInstallPoptTable[] = {
(INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL),
N_("upgrade package(s) if already installed"),
N_("<packagefile>+") },
+ { "fskpath", '\0', POPT_ARG_STRING, &rpmIArgs.fileSigningKey, 0,
+ N_("use file signing key <key>"),
+ N_("<key>") },
{ "hash", 'h', POPT_BIT_SET, &rpmIArgs.installInterfaceFlags, INSTALL_HASH,
N_("print hash marks as package installs (good with -v)"), NULL},
{ "ignorearch", '\0', POPT_BIT_SET,
@@ -243,6 +248,8 @@ struct poptOption rpmInstallPoptTable[] = {
{ "replacepkgs", '\0', POPT_BIT_SET,
&rpmIArgs.probFilter, RPMPROB_FILTER_REPLACEPKG,
N_("reinstall if the package is already present"), NULL},
+ { "signfiles", '\0', POPT_ARG_NONE, &rpmIArgs.signFiles, 0,
+ N_("sign package files"), NULL},
{ "test", '\0', POPT_BIT_SET, &rpmIArgs.transFlags, RPMTRANS_FLAG_TEST,
N_("don't install, but tell if it would work or not"), NULL},
{ "upgrade", 'U', POPT_BIT_SET,
diff --git a/lib/rpmcli.h b/lib/rpmcli.h
index 48e8250..ff89171 100644
--- a/lib/rpmcli.h
+++ b/lib/rpmcli.h
@@ -339,8 +339,10 @@ struct rpmInstallArguments_s {
int numRelocations;
int noDeps;
int incldocs;
+ int signFiles;
rpmRelocation * relocations;
char * prefix;
+ char * fileSigningKey;
};
/** \ingroup rpmcli
diff --git a/lib/rpminstall.c b/lib/rpminstall.c
index 2e7da7d..d98d506 100644
--- a/lib/rpminstall.c
+++ b/lib/rpminstall.c
@@ -11,6 +11,7 @@
#include <rpm/rpmds.h>
#include <rpm/rpmts.h>
#include <rpm/rpmlog.h>
+#include <rpm/rpmmacro.h>
#include <rpm/rpmfileutil.h>
#include "lib/rpmgi.h"
@@ -417,7 +418,14 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
relocations = ia->relocations;
- setNotifyFlag(ia, ts);
+ setNotifyFlag(ia, ts);
+
+ rpmtsSetSignFiles(ts, ia->signFiles);
+
+ if (ia->fileSigningKey) {
+ addMacro(NULL, "_file_signing_key", NULL, ia->fileSigningKey,
+ RMIL_GLOBAL);
+ }
if ((eiu->relocations = relocations) != NULL) {
while (eiu->relocations->oldPath)
diff --git a/lib/rpmts.c b/lib/rpmts.c
index a3b4ed2..6d9eb30 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -897,6 +897,21 @@ int rpmtsSetNotifyCallback(rpmts ts,
return 0;
}
+int rpmtsSignFiles(rpmts ts)
+{
+ return ts ? ts->signFiles : NULL;
+}
+
+int rpmtsSetSignFiles(rpmts ts, int signFiles)
+{
+ if (ts == NULL) {
+ return -1;
+ }
+
+ ts->signFiles = signFiles;
+ return 0;
+}
+
tsMembers rpmtsMembers(rpmts ts)
{
return (ts != NULL) ? ts->members : NULL;
diff --git a/lib/rpmts.h b/lib/rpmts.h
index 5231c80..5f45972 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -393,6 +393,21 @@ const char * rpmtsRootDir(rpmts ts);
*/
int rpmtsSetRootDir(rpmts ts, const char * rootDir);
+/**
+ * Get transaction sign files flag
+ * @param ts transaction set
+ * @return non-zero if package files need to be signed
+ */
+int rpmtsSignFiles(rpmts ts);
+
+/**
+ * Set transaction sign files flag
+ * @param ts transaction set
+ * @param signFiles new sign files flag
+ * @return 0 on success, -1 on error
+ */
+int rpmtsSetSignFiles(rpmts ts, int signFiles);
+
/** \ingroup rpmts
* Get transaction script file handle, i.e. stdout/stderr on scriptlet execution
* @param ts transaction set
diff --git a/lib/rpmts_internal.h b/lib/rpmts_internal.h
index 0caa7cb..a196932 100644
--- a/lib/rpmts_internal.h
+++ b/lib/rpmts_internal.h
@@ -68,6 +68,8 @@ struct rpmts_s {
rpmPlugins plugins; /*!< Transaction plugins */
int nrefs; /*!< Reference count. */
+
+ int signFiles; /*!< Sign package files. */
};
#ifdef __cplusplus
--
1.9.3
More information about the Rpm-maint
mailing list