|
|
621668 |
diff --git a/Makefile.am b/Makefile.am
|
|
|
621668 |
index 288668819..96542c8c8 100644
|
|
|
621668 |
--- a/Makefile.am
|
|
|
621668 |
+++ b/Makefile.am
|
|
|
621668 |
@@ -185,7 +185,7 @@ bin_PROGRAMS += rpmgraph
|
|
|
621668 |
rpmgraph_SOURCES = tools/rpmgraph.c
|
|
|
621668 |
rpmgraph_LDADD = lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@
|
|
|
621668 |
|
|
|
621668 |
-dist_bin_SCRIPTS = scripts/gendiff
|
|
|
621668 |
+dist_bin_SCRIPTS = scripts/gendiff scripts/rpm2extents_dump
|
|
|
621668 |
|
|
|
621668 |
rpmconfig_DATA = rpmrc
|
|
|
621668 |
rpmrc: $(top_srcdir)/rpmrc.in
|
|
|
621668 |
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
|
|
|
621668 |
index 40a3ab83f..6164d012c 100644
|
|
|
621668 |
--- a/lib/rpmchecksig.c
|
|
|
621668 |
+++ b/lib/rpmchecksig.c
|
|
|
621668 |
@@ -24,6 +24,11 @@
|
|
|
621668 |
|
|
|
621668 |
#include "debug.h"
|
|
|
621668 |
|
|
|
621668 |
+/* magic value at end of file (64 bits) that indicates this is a transcoded
|
|
|
621668 |
+ * rpm.
|
|
|
621668 |
+ */
|
|
|
621668 |
+#define MAGIC 3472329499408095051
|
|
|
621668 |
+
|
|
|
621668 |
static int doImport(rpmts ts, const char *fn, char *buf, ssize_t blen)
|
|
|
621668 |
{
|
|
|
621668 |
char const * const pgpmark = "-----BEGIN PGP ";
|
|
|
621668 |
@@ -220,6 +225,107 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd,
|
|
|
621668 |
return rc;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
+static rpmRC isTranscodedRpm(FD_t fd) {
|
|
|
621668 |
+ rpmRC rc = RPMRC_NOTFOUND;
|
|
|
621668 |
+ rpm_loff_t current;
|
|
|
621668 |
+ uint64_t magic;
|
|
|
621668 |
+ size_t len;
|
|
|
621668 |
+
|
|
|
621668 |
+ // If the file is not seekable, we cannot detect whether or not it is transcoded.
|
|
|
621668 |
+ if(Fseek(fd, 0, SEEK_CUR) < 0) {
|
|
|
621668 |
+ return RPMRC_FAIL;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ current = Ftell(fd);
|
|
|
621668 |
+
|
|
|
621668 |
+ if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ len = sizeof(magic);
|
|
|
621668 |
+ if (Fread(&magic, len, 1, fd) != len) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ if (magic != MAGIC) {
|
|
|
621668 |
+ rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n"));
|
|
|
621668 |
+ rc = RPMRC_NOTFOUND;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ rc = RPMRC_OK;
|
|
|
621668 |
+exit:
|
|
|
621668 |
+ if (Fseek(fd, current, SEEK_SET) < 0) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to seek back to original location\n"));
|
|
|
621668 |
+ }
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+static int rpmpkgVerifySigsTranscoded(FD_t fd){
|
|
|
621668 |
+ rpm_loff_t current;
|
|
|
621668 |
+ uint64_t magic;
|
|
|
621668 |
+ rpm_loff_t offset;
|
|
|
621668 |
+ int32_t rc;
|
|
|
621668 |
+ size_t len;
|
|
|
621668 |
+ uint64_t content_len;
|
|
|
621668 |
+ char *content = NULL;
|
|
|
621668 |
+
|
|
|
621668 |
+ current = Ftell(fd);
|
|
|
621668 |
+
|
|
|
621668 |
+ if(Fseek(fd, -(sizeof(magic) + 3 * sizeof(offset) ), SEEK_END) < 0) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: failed to seek for offset\n"));
|
|
|
621668 |
+ rc = -1;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ len = sizeof(offset);
|
|
|
621668 |
+ if (Fread(&offset, len, 1, fd) != len) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification offset\n"));
|
|
|
621668 |
+ rc = -1;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ if(Fseek(fd, offset, SEEK_SET) < 0) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to seek signature verification offset\n"));
|
|
|
621668 |
+ rc = -1;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ len = sizeof(rc);
|
|
|
621668 |
+ if (Fread(&rc, len, 1, fd) != len) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification RC\n"));
|
|
|
621668 |
+ rc = -1;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ len = sizeof(content_len);
|
|
|
621668 |
+ if (Fread(&content_len, len, 1, fd) != len) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content length\n"));
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ content = malloc(content_len + 1);
|
|
|
621668 |
+ if(content == NULL) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to allocate memory to read signature content\n"));
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ content[content_len] = 0;
|
|
|
621668 |
+ if (Fread(content, content_len, 1, fd) != content_len) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content\n"));
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ rpmlog(RPMLOG_NOTICE, "%s", content);
|
|
|
621668 |
+exit:
|
|
|
621668 |
+ if(content){
|
|
|
621668 |
+ free(content);
|
|
|
621668 |
+ }
|
|
|
621668 |
+ if (Fseek(fd, current, SEEK_SET) < 0) {
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: unable to seek back to original location\n"));
|
|
|
621668 |
+ }
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
|
|
621668 |
FD_t fd, const char *fn)
|
|
|
621668 |
{
|
|
|
621668 |
@@ -229,10 +335,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
|
|
621668 |
.verbose = rpmIsVerbose(),
|
|
|
621668 |
};
|
|
|
621668 |
int rc;
|
|
|
621668 |
- struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
|
|
621668 |
|
|
|
621668 |
rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : "");
|
|
|
621668 |
|
|
|
621668 |
+ if(isTranscodedRpm(fd) == RPMRC_OK){
|
|
|
621668 |
+ return rpmpkgVerifySigsTranscoded(fd);
|
|
|
621668 |
+ }
|
|
|
621668 |
+ struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
|
|
621668 |
+
|
|
|
621668 |
rc = rpmpkgRead(vs, fd, NULL, NULL, &msg;;
|
|
|
621668 |
|
|
|
621668 |
if (rc)
|
|
|
621668 |
@@ -260,6 +370,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
|
|
621668 |
return rc;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
+static int rpmpkgVerifySigsFD(rpmKeyring keyring, int vfylevel, rpmVSFlags flags,
|
|
|
621668 |
+ FD_t fd, rpmsinfoCb cb, void *cbdata)
|
|
|
621668 |
+{
|
|
|
621668 |
+ char *msg = NULL;
|
|
|
621668 |
+ int rc;
|
|
|
621668 |
+ struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring);
|
|
|
621668 |
+
|
|
|
621668 |
+ rc = rpmpkgRead(vs, fd, NULL, NULL, &msg;;
|
|
|
621668 |
+
|
|
|
621668 |
+ if (rc)
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+
|
|
|
621668 |
+ rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata);
|
|
|
621668 |
+
|
|
|
621668 |
+exit:
|
|
|
621668 |
+ if (rc && msg)
|
|
|
621668 |
+ rpmlog(RPMLOG_ERR, "%s\n", msg);
|
|
|
621668 |
+ rpmvsFree(vs);
|
|
|
621668 |
+ free(msg);
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
/* Wrapper around rpmkVerifySigs to preserve API */
|
|
|
621668 |
int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn)
|
|
|
621668 |
{
|
|
|
621668 |
@@ -304,3 +437,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv)
|
|
|
621668 |
rpmKeyringFree(keyring);
|
|
|
621668 |
return res;
|
|
|
621668 |
}
|
|
|
621668 |
+
|
|
|
621668 |
+struct vfydatafd_s {
|
|
|
621668 |
+ size_t len;
|
|
|
621668 |
+ char msg[BUFSIZ];
|
|
|
621668 |
+};
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
+static int vfyFDCb(struct rpmsinfo_s *sinfo, void *cbdata)
|
|
|
621668 |
+{
|
|
|
621668 |
+ struct vfydatafd_s *vd = cbdata;
|
|
|
621668 |
+ char *vmsg, *msg;
|
|
|
621668 |
+ size_t n;
|
|
|
621668 |
+ size_t remainder = BUFSIZ - vd->len;
|
|
|
621668 |
+
|
|
|
621668 |
+ vmsg = rpmsinfoMsg(sinfo);
|
|
|
621668 |
+ rasprintf(&msg, " %s\n", vmsg);
|
|
|
621668 |
+ n = rstrlcpy(vd->msg + vd->len, msg, remainder);
|
|
|
621668 |
+ free(vmsg);
|
|
|
621668 |
+ free(msg);
|
|
|
621668 |
+ if(n <= remainder){
|
|
|
621668 |
+ vd->len += n;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ return 1;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
+int rpmcliVerifySignaturesFD(rpmts ts, FD_t fdi, char **msg)
|
|
|
621668 |
+{
|
|
|
621668 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
621668 |
+ rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
|
|
|
621668 |
+ rpmVSFlags vsflags = rpmtsVfyFlags(ts);
|
|
|
621668 |
+ int vfylevel = rpmtsVfyLevel(ts);
|
|
|
621668 |
+ struct vfydatafd_s vd = {.len = 0};
|
|
|
621668 |
+
|
|
|
621668 |
+ vsflags |= rpmcliVSFlags;
|
|
|
621668 |
+ if (rpmcliVfyLevelMask) {
|
|
|
621668 |
+ vfylevel &= ~rpmcliVfyLevelMask;
|
|
|
621668 |
+ rpmtsSetVfyLevel(ts, vfylevel);
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ if (!rpmpkgVerifySigsFD(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) {
|
|
|
621668 |
+ rc = RPMRC_OK;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ *msg = strdup(vd.msg);
|
|
|
621668 |
+ rpmsqPoll();
|
|
|
621668 |
+
|
|
|
621668 |
+ rpmKeyringFree(keyring);
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
diff --git a/lib/rpmcli.h b/lib/rpmcli.h
|
|
|
621668 |
index 906fe9951..7ff48b37a 100644
|
|
|
621668 |
--- a/lib/rpmcli.h
|
|
|
621668 |
+++ b/lib/rpmcli.h
|
|
|
621668 |
@@ -411,6 +411,16 @@ int rpmcliImportPubkeys(rpmts ts, ARGV_const_t argv);
|
|
|
621668 |
*/
|
|
|
621668 |
int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv);
|
|
|
621668 |
|
|
|
621668 |
+
|
|
|
621668 |
+/** \ingroup rpmcli
|
|
|
621668 |
+ * Verify package signatures.
|
|
|
621668 |
+ * @param ts transaction set
|
|
|
621668 |
+ * @param fd a file descriptor to verify
|
|
|
621668 |
+ * @param msg a string containing textual information about the verification, similar to rpmcliVerifySignatures output.
|
|
|
621668 |
+ * @return 0 on success
|
|
|
621668 |
+ */
|
|
|
621668 |
+int rpmcliVerifySignaturesFD(rpmts ts, FD_t fd, char **msg);
|
|
|
621668 |
+
|
|
|
621668 |
#ifdef __cplusplus
|
|
|
621668 |
}
|
|
|
621668 |
#endif
|
|
|
621668 |
diff --git a/rpm2extents.c b/rpm2extents.c
|
|
|
621668 |
index c111be0a2..e316a2834 100644
|
|
|
621668 |
--- a/rpm2extents.c
|
|
|
621668 |
+++ b/rpm2extents.c
|
|
|
621668 |
@@ -2,7 +2,9 @@
|
|
|
621668 |
|
|
|
621668 |
#include "system.h"
|
|
|
621668 |
|
|
|
621668 |
+#include <rpm/rpmcli.h>
|
|
|
621668 |
#include <rpm/rpmlib.h> /* rpmReadPackageFile .. */
|
|
|
621668 |
+#include <rpm/rpmlog.h>
|
|
|
621668 |
#include <rpm/rpmfi.h>
|
|
|
621668 |
#include <rpm/rpmtag.h>
|
|
|
621668 |
#include <rpm/rpmio.h>
|
|
|
621668 |
@@ -10,6 +12,7 @@
|
|
|
621668 |
|
|
|
621668 |
#include <rpm/rpmts.h>
|
|
|
621668 |
#include "lib/rpmlead.h"
|
|
|
621668 |
+#include "lib/rpmts.h"
|
|
|
621668 |
#include "lib/signature.h"
|
|
|
621668 |
#include "lib/header_internal.h"
|
|
|
621668 |
#include "rpmio/rpmio_internal.h"
|
|
|
621668 |
@@ -51,38 +54,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit)
|
|
|
621668 |
return (unit - (pos % unit)) % unit;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
-static int digestor(
|
|
|
621668 |
+static struct poptOption optionsTable[] = {
|
|
|
621668 |
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
|
|
|
621668 |
+ N_("Common options for all rpm modes and executables:"), NULL },
|
|
|
621668 |
+
|
|
|
621668 |
+ POPT_AUTOALIAS
|
|
|
621668 |
+ POPT_AUTOHELP
|
|
|
621668 |
+ POPT_TABLEEND
|
|
|
621668 |
+};
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
+static void FDDigestInit(FD_t fdi, uint8_t algos[], uint32_t algos_len){
|
|
|
621668 |
+ int algo;
|
|
|
621668 |
+
|
|
|
621668 |
+ for (algo = 0; algo < algos_len; algo++) {
|
|
|
621668 |
+ fdInitDigest(fdi, algos[algo], 0);
|
|
|
621668 |
+ }
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+static int FDWriteDigests(
|
|
|
621668 |
FD_t fdi,
|
|
|
621668 |
FD_t fdo,
|
|
|
621668 |
- FD_t validationo,
|
|
|
621668 |
uint8_t algos[],
|
|
|
621668 |
- uint32_t algos_len
|
|
|
621668 |
-)
|
|
|
621668 |
+ uint32_t algos_len)
|
|
|
621668 |
{
|
|
|
621668 |
- ssize_t fdilength;
|
|
|
621668 |
const char *filedigest, *algo_name;
|
|
|
621668 |
size_t filedigest_len, len;
|
|
|
621668 |
uint32_t algo_name_len, algo_digest_len;
|
|
|
621668 |
int algo;
|
|
|
621668 |
rpmRC rc = RPMRC_FAIL;
|
|
|
621668 |
|
|
|
621668 |
- for (algo = 0; algo < algos_len; algo++) {
|
|
|
621668 |
- fdInitDigest(fdi, algos[algo], 0);
|
|
|
621668 |
- }
|
|
|
621668 |
- fdilength = ufdCopy(fdi, fdo);
|
|
|
621668 |
- if (fdilength == -1) {
|
|
|
621668 |
- fprintf(stderr, _("digest cat failed\n"));
|
|
|
621668 |
- goto exit;
|
|
|
621668 |
- }
|
|
|
621668 |
+ ssize_t fdilength = fdOp(fdi, FDSTAT_READ)->bytes;
|
|
|
621668 |
|
|
|
621668 |
len = sizeof(fdilength);
|
|
|
621668 |
- if (Fwrite(&fdilength, len, 1, validationo) != len) {
|
|
|
621668 |
+ if (Fwrite(&fdilength, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr, _("Unable to write input length %zd\n"), fdilength);
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
len = sizeof(algos_len);
|
|
|
621668 |
- if (Fwrite(&algos_len, len, 1, validationo) != len) {
|
|
|
621668 |
- fprintf(stderr, _("Unable to write number of validation digests\n"));
|
|
|
621668 |
+ if (Fwrite(&algos_len, len, 1, fdo) != len) {
|
|
|
621668 |
+ algo_digest_len = (uint32_t)filedigest_len;
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write number of digests\n"));
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
for (algo = 0; algo < algos_len; algo++) {
|
|
|
621668 |
@@ -93,24 +105,24 @@ static int digestor(
|
|
|
621668 |
algo_digest_len = (uint32_t)filedigest_len;
|
|
|
621668 |
|
|
|
621668 |
len = sizeof(algo_name_len);
|
|
|
621668 |
- if (Fwrite(&algo_name_len, len, 1, validationo) != len) {
|
|
|
621668 |
+ if (Fwrite(&algo_name_len, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr,
|
|
|
621668 |
- _("Unable to write validation algo name length\n"));
|
|
|
621668 |
+ _("Unable to write digest algo name length\n"));
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
len = sizeof(algo_digest_len);
|
|
|
621668 |
- if (Fwrite(&algo_digest_len, len, 1, validationo) != len) {
|
|
|
621668 |
+ if (Fwrite(&algo_digest_len, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr,
|
|
|
621668 |
- _("Unable to write number of bytes for validation digest\n"));
|
|
|
621668 |
+ _("Unable to write number of bytes for digest\n"));
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
- if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) {
|
|
|
621668 |
- fprintf(stderr, _("Unable to write validation algo name\n"));
|
|
|
621668 |
+ if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) {
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write digest algo name\n"));
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
- if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) {
|
|
|
621668 |
+ if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) {
|
|
|
621668 |
fprintf(stderr,
|
|
|
621668 |
- _("Unable to write validation digest value %u, %zu\n"),
|
|
|
621668 |
+ _("Unable to write digest value %u, %zu\n"),
|
|
|
621668 |
algo_digest_len, filedigest_len);
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
@@ -120,7 +132,69 @@ static int digestor(
|
|
|
621668 |
return rc;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
-static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
+static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
|
|
|
621668 |
+ size_t len;
|
|
|
621668 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
621668 |
+
|
|
|
621668 |
+ if(rpmvsrc){
|
|
|
621668 |
+ fprintf(stderr, _("Error verifying package signatures\n"));
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ len = sizeof(rpmvsrc);
|
|
|
621668 |
+ if (Fwrite(&rpmvsrc, len, 1, fdo) != len) {
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write signature verification RC code %d\n"), rpmvsrc);
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ size_t content_len = msg ? strlen(msg) : 0;
|
|
|
621668 |
+ len = sizeof(content_len);
|
|
|
621668 |
+ if (Fwrite(&content_len, len, 1, fdo) != len) {
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write signature verification output length %zd\n"), content_len);
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ if (Fwrite(msg, content_len, 1, fdo) != content_len) {
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write signature verification output %s\n"), msg);
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ rc = RPMRC_OK;
|
|
|
621668 |
+exit:
|
|
|
621668 |
+
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+static rpmRC validator(FD_t fdi, FD_t digesto, FD_t sigo,
|
|
|
621668 |
+ uint8_t algos[],
|
|
|
621668 |
+ uint32_t algos_len){
|
|
|
621668 |
+ int rpmvsrc;
|
|
|
621668 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
621668 |
+ char *msg = NULL;
|
|
|
621668 |
+ rpmts ts = rpmtsCreate();
|
|
|
621668 |
+
|
|
|
621668 |
+ rpmtsSetRootDir(ts, rpmcliRootDir);
|
|
|
621668 |
+
|
|
|
621668 |
+ FDDigestInit(fdi, algos, algos_len);
|
|
|
621668 |
+
|
|
|
621668 |
+ rpmvsrc = rpmcliVerifySignaturesFD(ts, fdi, &msg;;
|
|
|
621668 |
+
|
|
|
621668 |
+ // Write result of digest computation
|
|
|
621668 |
+ if(FDWriteDigests(fdi, digesto, algos, algos_len) != RPMRC_OK) {
|
|
|
621668 |
+ fprintf(stderr, _("Failed to write digests"));
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ // Write result of signature validation.
|
|
|
621668 |
+ if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) {
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ rc = RPMRC_OK;
|
|
|
621668 |
+exit:
|
|
|
621668 |
+ if(msg) {
|
|
|
621668 |
+ free(msg);
|
|
|
621668 |
+ }
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
|
621668 |
{
|
|
|
621668 |
uint32_t diglen;
|
|
|
621668 |
/* GNU C extension: can use diglen from outer context */
|
|
|
621668 |
@@ -148,7 +222,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
rpm_mode_t mode;
|
|
|
621668 |
char *rpmio_flags = NULL, *zeros;
|
|
|
621668 |
const unsigned char *digest;
|
|
|
621668 |
- rpm_loff_t pos, size, pad, validation_pos;
|
|
|
621668 |
+ rpm_loff_t pos, size, pad, digest_pos, validation_pos, digest_table_pos;
|
|
|
621668 |
uint32_t offset_ix = 0;
|
|
|
621668 |
size_t len;
|
|
|
621668 |
int next = 0;
|
|
|
621668 |
@@ -253,6 +327,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset),
|
|
|
621668 |
digestoffsetCmp);
|
|
|
621668 |
|
|
|
621668 |
+ validation_pos = pos;
|
|
|
621668 |
+ ssize_t validation_len = ufdCopy(validationi, fdo);
|
|
|
621668 |
+ if (validation_len == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("validation output ufdCopy failed\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ digest_table_pos = validation_pos + validation_len;
|
|
|
621668 |
+
|
|
|
621668 |
len = sizeof(offset_ix);
|
|
|
621668 |
if (Fwrite(&offset_ix, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr, _("Unable to write length of table\n"));
|
|
|
621668 |
@@ -278,17 +362,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
}
|
|
|
621668 |
- validation_pos = (
|
|
|
621668 |
- pos + sizeof(offset_ix) + sizeof(diglen) +
|
|
|
621668 |
+ digest_pos = (
|
|
|
621668 |
+ digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
|
|
|
621668 |
offset_ix * (diglen + sizeof(rpm_loff_t))
|
|
|
621668 |
);
|
|
|
621668 |
|
|
|
621668 |
- ssize_t validation_len = ufdCopy(validationi, fdo);
|
|
|
621668 |
- if (validation_len == -1) {
|
|
|
621668 |
+ ssize_t digest_len = ufdCopy(digestori, fdo);
|
|
|
621668 |
+ if (digest_len == -1) {
|
|
|
621668 |
fprintf(stderr, _("digest table ufdCopy failed\n"));
|
|
|
621668 |
rc = RPMRC_FAIL;
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
+
|
|
|
621668 |
/* add more padding so the last file can be cloned. It doesn't matter that
|
|
|
621668 |
* the table and validation etc are in this space. In fact, it's pretty
|
|
|
621668 |
* efficient if it is.
|
|
|
621668 |
@@ -302,12 +387,17 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
zeros = _free(zeros);
|
|
|
621668 |
- if (Fwrite(&pos, len, 1, fdo) != len) {
|
|
|
621668 |
+ if (Fwrite(&validation_pos, len, 1, fdo) != len) {
|
|
|
621668 |
+ fprintf(stderr, _("Unable to write offset of validation output\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ goto exit;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ if (Fwrite(&digest_table_pos, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr, _("Unable to write offset of digest table\n"));
|
|
|
621668 |
rc = RPMRC_FAIL;
|
|
|
621668 |
goto exit;
|
|
|
621668 |
}
|
|
|
621668 |
- if (Fwrite(&validation_pos, len, 1, fdo) != len) {
|
|
|
621668 |
+ if (Fwrite(&digest_pos, len, 1, fdo) != len) {
|
|
|
621668 |
fprintf(stderr, _("Unable to write offset of validation table\n"));
|
|
|
621668 |
rc = RPMRC_FAIL;
|
|
|
621668 |
goto exit;
|
|
|
621668 |
@@ -327,104 +417,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi)
|
|
|
621668 |
return rc;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
-int main(int argc, char *argv[]) {
|
|
|
621668 |
- rpmRC rc;
|
|
|
621668 |
- int cprc = 0;
|
|
|
621668 |
- uint8_t algos[argc - 1];
|
|
|
621668 |
- int mainpipefd[2];
|
|
|
621668 |
- int metapipefd[2];
|
|
|
621668 |
- pid_t cpid, w;
|
|
|
621668 |
- int wstatus;
|
|
|
621668 |
+static off_t ufdTee(FD_t sfd, FD_t *fds, int len)
|
|
|
621668 |
+{
|
|
|
621668 |
+ char buf[BUFSIZ];
|
|
|
621668 |
+ ssize_t rdbytes, wrbytes;
|
|
|
621668 |
+ off_t total = 0;
|
|
|
621668 |
+
|
|
|
621668 |
+ while (1) {
|
|
|
621668 |
+ rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
|
|
|
621668 |
+
|
|
|
621668 |
+ if (rdbytes > 0) {
|
|
|
621668 |
+ for(int i=0; i < len; i++) {
|
|
|
621668 |
+ wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, fds[i]);
|
|
|
621668 |
+ if (wrbytes != rdbytes) {
|
|
|
621668 |
+ fprintf(stderr, "Error wriing to FD %d: %s\n", i, Fstrerror(fds[i]));
|
|
|
621668 |
+ total = -1;
|
|
|
621668 |
+ break;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ }
|
|
|
621668 |
+ if(total == -1){
|
|
|
621668 |
+ break;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ total += wrbytes;
|
|
|
621668 |
+ } else {
|
|
|
621668 |
+ if (rdbytes < 0)
|
|
|
621668 |
+ total = -1;
|
|
|
621668 |
+ break;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ }
|
|
|
621668 |
|
|
|
621668 |
- xsetprogname(argv[0]); /* Portability call -- see system.h */
|
|
|
621668 |
- rpmReadConfigFiles(NULL, NULL);
|
|
|
621668 |
+ return total;
|
|
|
621668 |
+}
|
|
|
621668 |
|
|
|
621668 |
- if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
|
|
|
621668 |
- fprintf(stderr, _("Usage: %s [DIGESTALGO]...\n"), argv[0]);
|
|
|
621668 |
- exit(EXIT_FAILURE);
|
|
|
621668 |
- }
|
|
|
621668 |
+static rpmRC teeRpm(FD_t fdi, uint8_t algos[], uint32_t algos_len) {
|
|
|
621668 |
+ rpmRC rc = RPMRC_FAIL;
|
|
|
621668 |
+ off_t offt = -1;
|
|
|
621668 |
+ // tee-ed stdin
|
|
|
621668 |
+ int processorpipefd[2];
|
|
|
621668 |
+ int validatorpipefd[2];
|
|
|
621668 |
+ // metadata
|
|
|
621668 |
+ int meta_digestpipefd[2];
|
|
|
621668 |
+ int meta_rpmsignpipefd[2];
|
|
|
621668 |
+
|
|
|
621668 |
+ pid_t cpids[2], w;
|
|
|
621668 |
+ int wstatus;
|
|
|
621668 |
+ FD_t fds[2];
|
|
|
621668 |
|
|
|
621668 |
- if (argc == 1) {
|
|
|
621668 |
- fprintf(stderr,
|
|
|
621668 |
- _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
|
|
|
621668 |
- exit(EXIT_FAILURE);
|
|
|
621668 |
+ if (pipe(processorpipefd) == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("Processor pipe failure\n"));
|
|
|
621668 |
+ return RPMRC_FAIL;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
- for (int x = 0; x < (argc - 1); x++) {
|
|
|
621668 |
- if (pgpStringVal(PGPVAL_HASHALGO, argv[x + 1], &algos[x]) != 0)
|
|
|
621668 |
- {
|
|
|
621668 |
- fprintf(stderr,
|
|
|
621668 |
- _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
|
|
|
621668 |
- argv[x + 1]);
|
|
|
621668 |
- exit(EXIT_FAILURE);
|
|
|
621668 |
- }
|
|
|
621668 |
+ if (pipe(validatorpipefd) == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("Validator pipe failure\n"));
|
|
|
621668 |
+ return RPMRC_FAIL;
|
|
|
621668 |
}
|
|
|
621668 |
|
|
|
621668 |
-
|
|
|
621668 |
- if (pipe(mainpipefd) == -1) {
|
|
|
621668 |
- fprintf(stderr, _("Main pipe failure\n"));
|
|
|
621668 |
- exit(EXIT_FAILURE);
|
|
|
621668 |
+ if (pipe(meta_digestpipefd) == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("Meta digest pipe failure\n"));
|
|
|
621668 |
+ return RPMRC_FAIL;
|
|
|
621668 |
}
|
|
|
621668 |
- if (pipe(metapipefd) == -1) {
|
|
|
621668 |
- fprintf(stderr, _("Meta pipe failure\n"));
|
|
|
621668 |
- exit(EXIT_FAILURE);
|
|
|
621668 |
+
|
|
|
621668 |
+ if (pipe(meta_rpmsignpipefd) == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("Meta rpm signature pipe failure\n"));
|
|
|
621668 |
+ return RPMRC_FAIL;
|
|
|
621668 |
}
|
|
|
621668 |
- cpid = fork();
|
|
|
621668 |
- if (cpid == 0) {
|
|
|
621668 |
- /* child: digestor */
|
|
|
621668 |
- close(mainpipefd[0]);
|
|
|
621668 |
- close(metapipefd[0]);
|
|
|
621668 |
- FD_t fdi = fdDup(STDIN_FILENO);
|
|
|
621668 |
- FD_t fdo = fdDup(mainpipefd[1]);
|
|
|
621668 |
- FD_t validationo = fdDup(metapipefd[1]);
|
|
|
621668 |
- rc = digestor(fdi, fdo, validationo, algos, argc - 1);
|
|
|
621668 |
- Fclose(validationo);
|
|
|
621668 |
- Fclose(fdo);
|
|
|
621668 |
+
|
|
|
621668 |
+ cpids[0] = fork();
|
|
|
621668 |
+ if (cpids[0] == 0) {
|
|
|
621668 |
+ /* child: validator */
|
|
|
621668 |
+ close(processorpipefd[0]);
|
|
|
621668 |
+ close(processorpipefd[1]);
|
|
|
621668 |
+ close(validatorpipefd[1]);
|
|
|
621668 |
+ close(meta_digestpipefd[0]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[0]);
|
|
|
621668 |
+ FD_t fdi = fdDup(validatorpipefd[0]);
|
|
|
621668 |
+ FD_t digesto = fdDup(meta_digestpipefd[1]);
|
|
|
621668 |
+ FD_t sigo = fdDup(meta_rpmsignpipefd[1]);
|
|
|
621668 |
+ close(meta_digestpipefd[1]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[1]);
|
|
|
621668 |
+ rc = validator(fdi, digesto, sigo, algos, algos_len);
|
|
|
621668 |
+ if(rc != RPMRC_OK) {
|
|
|
621668 |
+ fprintf(stderr, _("Validator failed\n"));
|
|
|
621668 |
+ }
|
|
|
621668 |
Fclose(fdi);
|
|
|
621668 |
+ Fclose(digesto);
|
|
|
621668 |
+ Fclose(sigo);
|
|
|
621668 |
+ if (rc != RPMRC_OK) {
|
|
|
621668 |
+ exit(EXIT_FAILURE);
|
|
|
621668 |
+ }
|
|
|
621668 |
+ exit(EXIT_SUCCESS);
|
|
|
621668 |
} else {
|
|
|
621668 |
/* parent: main program */
|
|
|
621668 |
- close(mainpipefd[1]);
|
|
|
621668 |
- close(metapipefd[1]);
|
|
|
621668 |
- FD_t fdi = fdDup(mainpipefd[0]);
|
|
|
621668 |
- FD_t validationi = fdDup(metapipefd[0]);
|
|
|
621668 |
- rc = process_package(fdi, validationi);
|
|
|
621668 |
- Fclose(validationi);
|
|
|
621668 |
- /* fdi is normally closed through the stacked file gzdi in the
|
|
|
621668 |
- * function.
|
|
|
621668 |
- * Wait for child process (digestor for stdin) to complete.
|
|
|
621668 |
- */
|
|
|
621668 |
- if (rc != RPMRC_OK) {
|
|
|
621668 |
- if (kill(cpid, SIGTERM) != 0) {
|
|
|
621668 |
- fprintf(stderr,
|
|
|
621668 |
- _("Failed to kill digest process when main process failed: %s\n"),
|
|
|
621668 |
- strerror(errno));
|
|
|
621668 |
+ cpids[1] = fork();
|
|
|
621668 |
+ if (cpids[1] == 0) {
|
|
|
621668 |
+ /* child: process_package */
|
|
|
621668 |
+ close(validatorpipefd[0]);
|
|
|
621668 |
+ close(validatorpipefd[1]);
|
|
|
621668 |
+ close(processorpipefd[1]);
|
|
|
621668 |
+ close(meta_digestpipefd[1]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[1]);
|
|
|
621668 |
+ FD_t fdi = fdDup(processorpipefd[0]);
|
|
|
621668 |
+ close(processorpipefd[0]);
|
|
|
621668 |
+ FD_t sigi = fdDup(meta_rpmsignpipefd[0]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[0]);
|
|
|
621668 |
+ FD_t digestori = fdDup(meta_digestpipefd[0]);
|
|
|
621668 |
+ close(meta_digestpipefd[0]);
|
|
|
621668 |
+
|
|
|
621668 |
+ rc = process_package(fdi, digestori, sigi);
|
|
|
621668 |
+ if(rc != RPMRC_OK) {
|
|
|
621668 |
+ fprintf(stderr, _("Validator failed\n"));
|
|
|
621668 |
}
|
|
|
621668 |
- }
|
|
|
621668 |
- w = waitpid(cpid, &wstatus, 0);
|
|
|
621668 |
- if (w == -1) {
|
|
|
621668 |
- fprintf(stderr, _("waitpid failed\n"));
|
|
|
621668 |
- cprc = EXIT_FAILURE;
|
|
|
621668 |
- } else if (WIFEXITED(wstatus)) {
|
|
|
621668 |
- cprc = WEXITSTATUS(wstatus);
|
|
|
621668 |
- if (cprc != 0) {
|
|
|
621668 |
- fprintf(stderr,
|
|
|
621668 |
- _("Digest process non-zero exit code %d\n"),
|
|
|
621668 |
- cprc);
|
|
|
621668 |
+ Fclose(digestori);
|
|
|
621668 |
+ Fclose(sigi);
|
|
|
621668 |
+ /* fdi is normally closed through the stacked file gzdi in the
|
|
|
621668 |
+ * function
|
|
|
621668 |
+ */
|
|
|
621668 |
+
|
|
|
621668 |
+ if (rc != RPMRC_OK) {
|
|
|
621668 |
+ exit(EXIT_FAILURE);
|
|
|
621668 |
}
|
|
|
621668 |
- } else if (WIFSIGNALED(wstatus)) {
|
|
|
621668 |
- fprintf(stderr,
|
|
|
621668 |
- _("Digest process was terminated with a signal: %d\n"),
|
|
|
621668 |
- WTERMSIG(wstatus));
|
|
|
621668 |
- cprc = EXIT_FAILURE;
|
|
|
621668 |
+ exit(EXIT_SUCCESS);
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
} else {
|
|
|
621668 |
- /* Don't think this can happen, but covering all bases */
|
|
|
621668 |
- fprintf(stderr, _("Unhandled circumstance in waitpid\n"));
|
|
|
621668 |
- cprc = EXIT_FAILURE;
|
|
|
621668 |
+ /* Actual parent. Read from fdi and write to both processes */
|
|
|
621668 |
+ close(processorpipefd[0]);
|
|
|
621668 |
+ close(validatorpipefd[0]);
|
|
|
621668 |
+ fds[0] = fdDup(processorpipefd[1]);
|
|
|
621668 |
+ fds[1] = fdDup(validatorpipefd[1]);
|
|
|
621668 |
+ close(validatorpipefd[1]);
|
|
|
621668 |
+ close(processorpipefd[1]);
|
|
|
621668 |
+ close(meta_digestpipefd[0]);
|
|
|
621668 |
+ close(meta_digestpipefd[1]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[0]);
|
|
|
621668 |
+ close(meta_rpmsignpipefd[1]);
|
|
|
621668 |
+
|
|
|
621668 |
+ rc = RPMRC_OK;
|
|
|
621668 |
+ offt = ufdTee(fdi, fds, 2);
|
|
|
621668 |
+ if(offt == -1){
|
|
|
621668 |
+ fprintf(stderr, _("Failed to tee RPM\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ Fclose(fds[0]);
|
|
|
621668 |
+ Fclose(fds[1]);
|
|
|
621668 |
+ w = waitpid(cpids[0], &wstatus, 0);
|
|
|
621668 |
+ if (w == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("waitpid cpids[0] failed\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ }
|
|
|
621668 |
+ w = waitpid(cpids[1], &wstatus, 0);
|
|
|
621668 |
+ if (w == -1) {
|
|
|
621668 |
+ fprintf(stderr, _("waitpid cpids[1] failed\n"));
|
|
|
621668 |
+ rc = RPMRC_FAIL;
|
|
|
621668 |
+ }
|
|
|
621668 |
}
|
|
|
621668 |
- if (cprc != EXIT_SUCCESS) {
|
|
|
621668 |
- rc = RPMRC_FAIL;
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ return rc;
|
|
|
621668 |
+}
|
|
|
621668 |
+
|
|
|
621668 |
+int main(int argc, char *argv[]) {
|
|
|
621668 |
+ rpmRC rc;
|
|
|
621668 |
+ poptContext optCon = NULL;
|
|
|
621668 |
+ const char **args = NULL;
|
|
|
621668 |
+ int nb_algos = 0;
|
|
|
621668 |
+
|
|
|
621668 |
+ xsetprogname(argv[0]); /* Portability call -- see system.h */
|
|
|
621668 |
+ rpmReadConfigFiles(NULL, NULL);
|
|
|
621668 |
+ optCon = rpmcliInit(argc, argv, optionsTable);
|
|
|
621668 |
+ poptSetOtherOptionHelp(optCon, "[OPTIONS]* <DIGESTALGO>");
|
|
|
621668 |
+
|
|
|
621668 |
+ if (poptPeekArg(optCon) == NULL) {
|
|
|
621668 |
+ fprintf(stderr,
|
|
|
621668 |
+ _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n"));
|
|
|
621668 |
+ poptPrintUsage(optCon, stderr, 0);
|
|
|
621668 |
+ exit(EXIT_FAILURE);
|
|
|
621668 |
+ }
|
|
|
621668 |
+
|
|
|
621668 |
+ args = poptGetArgs(optCon);
|
|
|
621668 |
+
|
|
|
621668 |
+ for (nb_algos=0; args[nb_algos]; nb_algos++);
|
|
|
621668 |
+ uint8_t algos[nb_algos];
|
|
|
621668 |
+ for (int x = 0; x < nb_algos; x++) {
|
|
|
621668 |
+ if (pgpStringVal(PGPVAL_HASHALGO, args[x], &algos[x]) != 0)
|
|
|
621668 |
+ {
|
|
|
621668 |
+ fprintf(stderr,
|
|
|
621668 |
+ _("Unable to resolve '%s' as a digest algorithm, exiting\n"),
|
|
|
621668 |
+ args[x]);
|
|
|
621668 |
+ exit(EXIT_FAILURE);
|
|
|
621668 |
}
|
|
|
621668 |
}
|
|
|
621668 |
+
|
|
|
621668 |
+ FD_t fdi = fdDup(STDIN_FILENO);
|
|
|
621668 |
+ rc = teeRpm(fdi, algos, nb_algos);
|
|
|
621668 |
if (rc != RPMRC_OK) {
|
|
|
621668 |
/* translate rpmRC into generic failure return code. */
|
|
|
621668 |
return EXIT_FAILURE;
|
|
|
621668 |
diff --git a/scripts/rpm2extents_dump b/scripts/rpm2extents_dump
|
|
|
621668 |
new file mode 100755
|
|
|
621668 |
index 000000000..596a59a49
|
|
|
621668 |
--- /dev/null
|
|
|
621668 |
+++ b/scripts/rpm2extents_dump
|
|
|
621668 |
@@ -0,0 +1,94 @@
|
|
|
621668 |
+#!/usr/bin/env python3
|
|
|
621668 |
+
|
|
|
621668 |
+import argparse
|
|
|
621668 |
+import binascii
|
|
|
621668 |
+import os
|
|
|
621668 |
+import struct
|
|
|
621668 |
+import sys
|
|
|
621668 |
+
|
|
|
621668 |
+MAGIC_SIZE = 8
|
|
|
621668 |
+MAGIC_STR = b'KWTSH100'
|
|
|
621668 |
+
|
|
|
621668 |
+POS_SIZE = 8
|
|
|
621668 |
+
|
|
|
621668 |
+def keep_position(func):
|
|
|
621668 |
+ def wrapper(*args, **kwargs):
|
|
|
621668 |
+ curr = args[0].tell()
|
|
|
621668 |
+ res = func(*args, **kwargs)
|
|
|
621668 |
+ f.seek(curr, os.SEEK_SET)
|
|
|
621668 |
+ return res
|
|
|
621668 |
+ return wrapper
|
|
|
621668 |
+
|
|
|
621668 |
+def read_validation_digest(f, validation_offset):
|
|
|
621668 |
+ digests = []
|
|
|
621668 |
+ # validation
|
|
|
621668 |
+ f.seek(validation_offset, os.SEEK_SET)
|
|
|
621668 |
+ val_content_len, val_digests_num = struct.unpack('=QI', f.read(8+4))
|
|
|
621668 |
+ for i in range(val_digests_num):
|
|
|
621668 |
+ algo_name_len, digest_len = struct.unpack('=II', f.read(8))
|
|
|
621668 |
+ algo_name, digest = struct.unpack(f'{algo_name_len}s{digest_len}s', f.read(algo_name_len+digest_len))
|
|
|
621668 |
+ digests.append((algo_name, binascii.hexlify(digest)))
|
|
|
621668 |
+ return digests
|
|
|
621668 |
+
|
|
|
621668 |
+
|
|
|
621668 |
+def read_digests_table(f, digest_offset):
|
|
|
621668 |
+ digests = []
|
|
|
621668 |
+ # validation
|
|
|
621668 |
+ f.seek(digest_offset, os.SEEK_SET)
|
|
|
621668 |
+ table_len, digest_len = struct.unpack('=II', f.read(8))
|
|
|
621668 |
+
|
|
|
621668 |
+ for i in range(table_len):
|
|
|
621668 |
+ digest, pos = struct.unpack(f'{digest_len}sQ', f.read(digest_len + 8))
|
|
|
621668 |
+ digests.append((pos, binascii.hexlify(digest)))
|
|
|
621668 |
+ return digests
|
|
|
621668 |
+
|
|
|
621668 |
+def read_signature_output(f, signature_offset):
|
|
|
621668 |
+ f.seek(signature_offset, os.SEEK_SET)
|
|
|
621668 |
+ signature_rc, signature_output_len = struct.unpack('=IQ', f.read(12))
|
|
|
621668 |
+ return signature_rc, f.read(signature_output_len)
|
|
|
621668 |
+
|
|
|
621668 |
+@keep_position
|
|
|
621668 |
+def parse_file(f):
|
|
|
621668 |
+ digests = []
|
|
|
621668 |
+ pos_table_offset = f.seek(-8 - 3*POS_SIZE, os.SEEK_END)
|
|
|
621668 |
+ signature_offset, digest_offset, validation_offset = struct.unpack('=QQQ', f.read(3*POS_SIZE))
|
|
|
621668 |
+
|
|
|
621668 |
+ validation_digests = read_validation_digest(f, validation_offset)
|
|
|
621668 |
+ digests_table = read_digests_table(f, digest_offset)
|
|
|
621668 |
+ signature_ouput = read_signature_output(f, signature_offset)
|
|
|
621668 |
+
|
|
|
621668 |
+ return validation_digests, digests_table, signature_ouput
|
|
|
621668 |
+
|
|
|
621668 |
+@keep_position
|
|
|
621668 |
+def is_transcoded(f):
|
|
|
621668 |
+ f.seek(-MAGIC_SIZE, os.SEEK_END)
|
|
|
621668 |
+ magic = f.read(MAGIC_SIZE)
|
|
|
621668 |
+ return magic == MAGIC_STR
|
|
|
621668 |
+
|
|
|
621668 |
+def arg_parse():
|
|
|
621668 |
+ parser = argparse.ArgumentParser()
|
|
|
621668 |
+ parser.add_argument('--dump-signature', action='store_true')
|
|
|
621668 |
+ parser.add_argument('--dump-file-digest-table', action='store_true')
|
|
|
621668 |
+ parser.add_argument('--dump-digests', action='store_true')
|
|
|
621668 |
+ parser.add_argument('file')
|
|
|
621668 |
+
|
|
|
621668 |
+ return parser.parse_args()
|
|
|
621668 |
+
|
|
|
621668 |
+if __name__ == '__main__':
|
|
|
621668 |
+ args = arg_parse()
|
|
|
621668 |
+ f = open(args.file, 'rb')
|
|
|
621668 |
+ if not is_transcoded(f):
|
|
|
621668 |
+ sys.exit(1)
|
|
|
621668 |
+
|
|
|
621668 |
+ validation_digests, digests_table, signature_output = parse_file(f)
|
|
|
621668 |
+ if(args.dump_file_digest_table):
|
|
|
621668 |
+ for digest in digests_table:
|
|
|
621668 |
+ print(f"FileDigest {hex(digest[0])}: {digest[1]}")
|
|
|
621668 |
+
|
|
|
621668 |
+ if(args.dump_digests):
|
|
|
621668 |
+ for validation_digest in validation_digests:
|
|
|
621668 |
+ print(f"HeaderDigest {validation_digest[0]} {validation_digest[1]}")
|
|
|
621668 |
+
|
|
|
621668 |
+ if(args.dump_signature):
|
|
|
621668 |
+ print(f"RPMSignOutput RC {signature_output[0]}\nRPMSignOutput Content {signature_output[1].decode()}")
|
|
|
621668 |
+
|
|
|
621668 |
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
|
|
621668 |
index f78e17c3e..fc8a24a5e 100644
|
|
|
621668 |
--- a/tests/Makefile.am
|
|
|
621668 |
+++ b/tests/Makefile.am
|
|
|
621668 |
@@ -36,6 +36,7 @@ TESTSUITE_AT += rpmio.at
|
|
|
621668 |
TESTSUITE_AT += rpmorder.at
|
|
|
621668 |
TESTSUITE_AT += rpmvfylevel.at
|
|
|
621668 |
TESTSUITE_AT += rpmpgp.at
|
|
|
621668 |
+TESTSUITE_AT += rpm2extents.at
|
|
|
621668 |
EXTRA_DIST += $(TESTSUITE_AT)
|
|
|
621668 |
|
|
|
621668 |
## testsuite data
|
|
|
621668 |
diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at
|
|
|
621668 |
new file mode 100644
|
|
|
621668 |
index 000000000..18accfc75
|
|
|
621668 |
--- /dev/null
|
|
|
621668 |
+++ b/tests/rpm2extents.at
|
|
|
621668 |
@@ -0,0 +1,96 @@
|
|
|
621668 |
+# rpm2extents.at: Some very basic checks
|
|
|
621668 |
+#
|
|
|
621668 |
+# Copyright (C) 2022 Manu Bretelle <chantr4@gmail.com>
|
|
|
621668 |
+#
|
|
|
621668 |
+# This program is free software; you can redistribute it and/or modify
|
|
|
621668 |
+# it under the terms of the GNU General Public License as published by
|
|
|
621668 |
+# the Free Software Foundation; either version 2 of the License, or
|
|
|
621668 |
+# (at your option) any later version.
|
|
|
621668 |
+#
|
|
|
621668 |
+# This program is distributed in the hope that it will be useful,
|
|
|
621668 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
621668 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
621668 |
+# GNU General Public License for more details.
|
|
|
621668 |
+#
|
|
|
621668 |
+# You should have received a copy of the GNU General Public License
|
|
|
621668 |
+# along with this program; if not, write to the Free Software
|
|
|
621668 |
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
621668 |
+
|
|
|
621668 |
+AT_BANNER([rpm2extents tests])
|
|
|
621668 |
+
|
|
|
621668 |
+# ------------------------------
|
|
|
621668 |
+
|
|
|
621668 |
+# check that transcoder write magic at the end
|
|
|
621668 |
+AT_SETUP([rpm2extents magic])
|
|
|
621668 |
+AT_KEYWORDS([rpm2extents])
|
|
|
621668 |
+AT_CHECK([runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 | tail -c8],
|
|
|
621668 |
+[0],
|
|
|
621668 |
+[KWTSH100],
|
|
|
621668 |
+[ignore])
|
|
|
621668 |
+AT_CLEANUP
|
|
|
621668 |
+
|
|
|
621668 |
+# Check that transcoder writes checksig return code and content.
|
|
|
621668 |
+#
|
|
|
621668 |
+AT_SETUP([rpm2extents signature])
|
|
|
621668 |
+AT_KEYWORDS([rpm2extents digest signature])
|
|
|
621668 |
+AT_CHECK([
|
|
|
621668 |
+RPMDB_INIT
|
|
|
621668 |
+
|
|
|
621668 |
+runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm 2> /dev/null
|
|
|
621668 |
+rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm
|
|
|
621668 |
+runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
|
|
|
621668 |
+runroot_other cat /data/RPMS/hello-2.0-1.x86_64-signed.rpm | runroot_other rpm2extents SHA256 > /tmp/hello-2.0-1.x86_64-signed.rpm
|
|
|
621668 |
+rpm2extents_dump --dump-signature /tmp/hello-2.0-1.x86_64-signed.rpm
|
|
|
621668 |
+],
|
|
|
621668 |
+[0],
|
|
|
621668 |
+[RPMSignOutput RC 2
|
|
|
621668 |
+RPMSignOutput Content Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
|
|
621668 |
+ Header SHA256 digest: OK
|
|
|
621668 |
+ Header SHA1 digest: OK
|
|
|
621668 |
+ Payload SHA256 digest: OK
|
|
|
621668 |
+ V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
|
|
621668 |
+ MD5 digest: OK
|
|
|
621668 |
+
|
|
|
621668 |
+RPMSignOutput RC 0
|
|
|
621668 |
+RPMSignOutput Content Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
|
|
621668 |
+ Header SHA256 digest: OK
|
|
|
621668 |
+ Header SHA1 digest: OK
|
|
|
621668 |
+ Payload SHA256 digest: OK
|
|
|
621668 |
+ V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
|
|
621668 |
+ MD5 digest: OK
|
|
|
621668 |
+
|
|
|
621668 |
+],
|
|
|
621668 |
+[])
|
|
|
621668 |
+AT_CLEANUP
|
|
|
621668 |
+
|
|
|
621668 |
+AT_SETUP([rpm2extents signature verification])
|
|
|
621668 |
+AT_KEYWORDS([rpm2extents digest signature])
|
|
|
621668 |
+AT_CHECK([
|
|
|
621668 |
+RPMDB_INIT
|
|
|
621668 |
+
|
|
|
621668 |
+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
|
|
|
621668 |
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $?
|
|
|
621668 |
+runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
|
|
|
621668 |
+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
|
|
|
621668 |
+runroot rpmkeys -Kv /tmp/hello-2.0-1.x86_64-signed.rpm; echo $?
|
|
|
621668 |
+],
|
|
|
621668 |
+[0],
|
|
|
621668 |
+[/tmp/hello-2.0-1.x86_64-signed.rpm:
|
|
|
621668 |
+ Header V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
|
|
621668 |
+ Header SHA256 digest: OK
|
|
|
621668 |
+ Header SHA1 digest: OK
|
|
|
621668 |
+ Payload SHA256 digest: OK
|
|
|
621668 |
+ V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY
|
|
|
621668 |
+ MD5 digest: OK
|
|
|
621668 |
+1
|
|
|
621668 |
+/tmp/hello-2.0-1.x86_64-signed.rpm:
|
|
|
621668 |
+ Header V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
|
|
621668 |
+ Header SHA256 digest: OK
|
|
|
621668 |
+ Header SHA1 digest: OK
|
|
|
621668 |
+ Payload SHA256 digest: OK
|
|
|
621668 |
+ V4 RSA/SHA256 Signature, key ID 1964c5fc: OK
|
|
|
621668 |
+ MD5 digest: OK
|
|
|
621668 |
+0
|
|
|
621668 |
+],
|
|
|
621668 |
+[])
|
|
|
621668 |
+AT_CLEANUP
|
|
|
621668 |
diff --git a/tests/rpmtests.at b/tests/rpmtests.at
|
|
|
621668 |
index a1adab8e0..205fed6a3 100644
|
|
|
621668 |
--- a/tests/rpmtests.at
|
|
|
621668 |
+++ b/tests/rpmtests.at
|
|
|
621668 |
@@ -21,3 +21,4 @@ m4_include([rpmreplace.at])
|
|
|
621668 |
m4_include([rpmconfig.at])
|
|
|
621668 |
m4_include([rpmconfig2.at])
|
|
|
621668 |
m4_include([rpmconfig3.at])
|
|
|
621668 |
+m4_include([rpm2extents.at])
|