summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/package.c151
-rw-r--r--lib/query.c2
-rw-r--r--lib/rpmchecksig.c44
-rw-r--r--lib/rpmlib.h13
-rw-r--r--lib/signature.c328
-rw-r--r--lib/verify.c2
6 files changed, 392 insertions, 148 deletions
diff --git a/lib/package.c b/lib/package.c
index 712289b0c..3d79c2b9a 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -39,6 +39,7 @@ void headerMergeLegacySigs(Header h, const Header sig)
ptr = hfd(ptr, type))
{
switch (tag) {
+ /* XXX Translate legacy signature tag values. */
case RPMSIGTAG_SIZE:
tag = RPMTAG_SIGSIZE;
/*@switchbreak@*/ break;
@@ -60,6 +61,11 @@ void headerMergeLegacySigs(Header h, const Header sig)
case RPMSIGTAG_PGP5:
tag = RPMTAG_SIGPGP5;
/*@switchbreak@*/ break;
+ case RPMSIGTAG_PAYLOADSIZE:
+ tag = RPMTAG_ARCHIVESIZE;
+ /*@switchbreak@*/ break;
+ case RPMSIGTAG_SHA1:
+ case RPMSIGTAG_DSA:
default:
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
continue;
@@ -88,6 +94,7 @@ Header headerRegenSigHeader(const Header h)
ptr = hfd(ptr, type))
{
switch (tag) {
+ /* XXX Translate legacy signature tag values. */
case RPMTAG_SIGSIZE:
stag = RPMSIGTAG_SIZE;
/*@switchbreak@*/ break;
@@ -109,6 +116,11 @@ Header headerRegenSigHeader(const Header h)
case RPMTAG_SIGPGP5:
stag = RPMSIGTAG_PGP5;
/*@switchbreak@*/ break;
+ case RPMTAG_ARCHIVESIZE:
+ stag = RPMSIGTAG_PAYLOADSIZE;
+ /*@switchbreak@*/ break;
+ case RPMTAG_SHA1HEADER:
+ case RPMTAG_DSAHEADER:
default:
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
continue;
@@ -249,6 +261,7 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
/*@notreached@*/ break;
}
+ /* Read the signature header. */
rc = rpmReadSignature(fd, &sig, l->signature_type);
if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn);
@@ -260,24 +273,26 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
goto exit;
}
- if (!ts->verify_legacy) /* leave fd ready to install payload */
- ts->sigtag = 0;
- else if (headerIsEntry(sig, RPMSIGTAG_GPG))
+ /* Figger the most effective available signature. */
+ if (headerIsEntry(sig, RPMSIGTAG_DSA))
+ ts->sigtag = RPMSIGTAG_DSA;
+ else if (!ts->verify_legacy) /* leave fd ready to install payload */
+ ts->sigtag = (headerIsEntry(sig, RPMSIGTAG_SHA1)) ? RPMSIGTAG_SHA1 : 0;
+ else if (headerIsEntry(sig, RPMSIGTAG_GPG)) {
ts->sigtag = RPMSIGTAG_GPG;
- else if (headerIsEntry(sig, RPMSIGTAG_PGP))
+ fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
+ } else if (headerIsEntry(sig, RPMSIGTAG_PGP)) {
ts->sigtag = RPMSIGTAG_PGP;
- else if (headerIsEntry(sig, RPMSIGTAG_MD5))
+ fdInitDigest(fd, PGPHASHALGO_MD5, 0);
+ } else if (headerIsEntry(sig, RPMSIGTAG_SHA1)) {
+ ts->sigtag = RPMSIGTAG_SHA1; /* XXX never happens */
+ } else if (headerIsEntry(sig, RPMSIGTAG_MD5)) {
ts->sigtag = RPMSIGTAG_MD5;
- else
- ts->sigtag = 0;
-
- /*@-type@*/ /* FIX: cast? */
- if (ts->sigtag == RPMSIGTAG_GPG)
- fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
- else if (ts->sigtag == RPMSIGTAG_PGP || ts->sigtag == RPMSIGTAG_MD5)
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
- /*@=type@*/
+ } else
+ ts->sigtag = 0; /* XXX never happens */
+ /* Read the metadata, computing digest(s) on the fly. */
hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
h = headerRead(fd, hmagic);
if (h == NULL) {
@@ -293,56 +308,94 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
}
ts->dig = pgpNewDig();
- ts->dig->nbytes = headerSizeof(h, hmagic);
-
- /* Read the compressed payload. */
- while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
- ts->dig->nbytes += count;
-
- if (count < 0) {
- rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd));
- rc = RPMRC_FAIL;
+ if (ts->dig == NULL) {
+ rc = RPMRC_OK; /* XXX WRONG */
goto exit;
}
- ts->dig->nbytes += count;
+ ts->dig->nbytes = 0;
+ /* Retrieve the tag parameters from the signature header. */
+ ts->sig = NULL;
xx = headerGetEntry(sig, ts->sigtag, &ts->sigtype,
(void **) &ts->sig, &ts->siglen);
+ if (ts->sig == NULL) {
+ rc = RPMRC_OK; /* XXX WRONG */
+ goto exit;
+ }
- xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
-
- /*@-type@*/ /* FIX: cast? */
- for (i = fd->ndigests - 1; i >= 0; i--) {
- FDDIGEST_t fddig = fd->digests + i;
- if (fddig->hashctx == NULL)
- continue;
- if (fddig->hashalgo == PGPHASHALGO_MD5) {
- /*@-branchstate@*/
- if (ts->dig->md5ctx != NULL)
- (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0);
- /*@=branchstate@*/
- ts->dig->md5ctx = fddig->hashctx;
- fddig->hashctx = NULL;
- continue;
+ switch (ts->sigtag) {
+ case RPMSIGTAG_DSA:
+ /* Parse the parameters from the OpenPGP packets that will be needed. */
+ xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
+ /*@fallthrough@*/
+ case RPMSIGTAG_SHA1:
+ { void * uh = NULL;
+ int_32 uht;
+ int_32 uhc;
+
+ /*@-branchstate@*/
+ if (headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
+ ts->dig->sha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
+ (void) rpmDigestUpdate(ts->dig->sha1ctx, uh, uhc);
+ ts->dig->nbytes += uhc;
+ uh = headerFreeData(uh, uht);
}
- if (fddig->hashalgo == PGPHASHALGO_SHA1) {
- /*@-branchstate@*/
- if (ts->dig->sha1ctx != NULL)
- (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0);
- /*@=branchstate@*/
- ts->dig->sha1ctx = fddig->hashctx;
- fddig->hashctx = NULL;
- continue;
+ /*@=branchstate@*/
+ } break;
+ case RPMSIGTAG_GPG:
+ case RPMSIGTAG_PGP5: /* XXX legacy */
+ case RPMSIGTAG_PGP:
+ /* Parse the parameters from the OpenPGP packets that will be needed. */
+ xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
+ /*@fallthrough@*/
+ case RPMSIGTAG_MD5:
+ /* Legacy signatures need the compressed payload in the digest too. */
+ ts->dig->nbytes += headerSizeof(h, hmagic);
+ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
+ ts->dig->nbytes += count;
+ if (count < 0) {
+ rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
+ fn, Fstrerror(fd));
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+ ts->dig->nbytes += count;
+
+ /* XXX Steal the digest-in-progress from the file handle. */
+ /*@-type@*/ /* FIX: cast? */
+ for (i = fd->ndigests - 1; i >= 0; i--) {
+ FDDIGEST_t fddig = fd->digests + i;
+ if (fddig->hashctx == NULL)
+ continue;
+ if (fddig->hashalgo == PGPHASHALGO_MD5) {
+ /*@-branchstate@*/
+ if (ts->dig->md5ctx != NULL)
+ (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0);
+ /*@=branchstate@*/
+ ts->dig->md5ctx = fddig->hashctx;
+ fddig->hashctx = NULL;
+ continue;
+ }
+ if (fddig->hashalgo == PGPHASHALGO_SHA1) {
+ /*@-branchstate@*/
+ if (ts->dig->sha1ctx != NULL)
+ (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0);
+ /*@=branchstate@*/
+ ts->dig->sha1ctx = fddig->hashctx;
+ fddig->hashctx = NULL;
+ continue;
+ }
}
+ /*@=type@*/
+ break;
}
- /*@=type@*/
/** @todo Implement disable/enable/warn/error/anal policy. */
buf[0] = '\0';
switch (rpmVerifySignature(ts, buf)) {
case RPMSIG_OK: /* Signature is OK. */
- rpmMessage(RPMMESS_VERBOSE, "%s: %s", fn, buf);
+ rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
rc = RPMRC_OK;
break;
case RPMSIG_UNKNOWN: /* Signature is unknown. */
@@ -363,7 +416,7 @@ exit:
/* Convert legacy headers on the fly ... */
legacyRetrofit(h, l);
- /* Append (and remap) signature tags. */
+ /* Append (and remap) signature tags to the metadata. */
headerMergeLegacySigs(h, sig);
/* Bump reference count for return. */
diff --git a/lib/query.c b/lib/query.c
index d08b02ad5..09f0875e9 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -974,7 +974,9 @@ int rpmcliQuery(rpmTransactionSet ts, QVA_t qva, const char ** argv)
qva->qva_showPackage = showQueryPackage;
switch (qva->qva_source) {
+#ifdef DYING
case RPMQV_RPM:
+#endif
case RPMQV_SPECFILE:
break;
default:
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
index 671b3a49a..6bc10328d 100644
--- a/lib/rpmchecksig.c
+++ b/lib/rpmchecksig.c
@@ -21,6 +21,8 @@
/*@access FD_t @*/
/*@access pgpDig @*/
+/**
+ */
static int manageFile(FD_t *fdp, const char **fnp, int flags,
/*@unused@*/ int rc)
/*@globals rpmGlobalMacroContext,
@@ -78,6 +80,7 @@ static int manageFile(FD_t *fdp, const char **fnp, int flags,
}
/**
+ * Copy header+payload, calculating digest(s) on the fly.
*/
static int copyFile(FD_t *sfdp, const char **sfnp,
FD_t *tfdp, const char **tfnp)
@@ -158,11 +161,11 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts,
}
switch (l->major) {
case 1:
- rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1.0 RPM\n"), rpm);
+ rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1 packaging\n"), rpm);
goto exit;
/*@notreached@*/ /*@switchbreak@*/ break;
case 2:
- rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
+ rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2 packaging\n"), rpm);
goto exit;
/*@notreached@*/ /*@switchbreak@*/ break;
default:
@@ -202,18 +205,25 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts,
}
(void) headerRemoveEntry(sig, RPMSIGTAG_SIZE);
- (void) headerRemoveEntry(sig, RPMSIGTAG_MD5);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase);
(void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_1);
(void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_2);
+ (void) headerRemoveEntry(sig, RPMSIGTAG_MD5);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase);
+#ifdef NOTNOW
+ (void) headerRemoveEntry(sig, RPMSIGTAG_SHA1);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SHA1, qva->passPhrase);
+
(void) headerRemoveEntry(sig, RPMSIGTAG_PGP5);
(void) headerRemoveEntry(sig, RPMSIGTAG_PGP);
(void) headerRemoveEntry(sig, RPMSIGTAG_GPG);
- (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase);
- (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase);
+#endif
}
- if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0)
+ if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
+ (void) headerRemoveEntry(sig, sigtype);
(void) rpmAddSignature(sig, sigtarget, sigtype, qva->passPhrase);
+ }
/* Write the lead/signature of the output rpm */
strcpy(tmprpm, rpm);
@@ -466,7 +476,6 @@ static int readFile(FD_t fd, int_32 sigtag, const char * fn, pgpDig dig)
rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd));
goto exit;
}
- dig->nbytes += count;
/*@-type@*/ /* FIX: cast? */
for (i = fd->ndigests - 1; i >= 0; i--) {
@@ -546,14 +555,20 @@ int rpmVerifySignatures(QVA_t qva, rpmTransactionSet ts, FD_t fd,
}
/* Grab a hint of what needs doing to avoid duplication. */
- if (headerIsEntry(sig, RPMSIGTAG_GPG))
+ if (headerIsEntry(sig, RPMSIGTAG_DSA))
+ sigtag = RPMSIGTAG_DSA;
+ else if (headerIsEntry(sig, RPMSIGTAG_GPG))
sigtag = RPMSIGTAG_GPG;
else if (headerIsEntry(sig, RPMSIGTAG_PGP))
sigtag = RPMSIGTAG_PGP;
else if (headerIsEntry(sig, RPMSIGTAG_MD5))
sigtag = RPMSIGTAG_MD5;
+#ifdef NOTYET
+ else if (headerIsEntry(sig, RPMSIGTAG_SHA1))
+ sigtag = RPMSIGTAG_SHA1; /* XXX never happens */
+#endif
else
- sigtag = 0; /* XXX never happens */
+ sigtag = 0; /* XXX never happens */
ts->dig = pgpNewDig();
@@ -589,6 +604,7 @@ if (rpmIsDebug())
fprintf(stderr, "========================= Package RSA Signature\n");
xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
if (!(qva->qva_flags & VERIFY_SIGNATURE))
continue;
@@ -603,11 +619,17 @@ fprintf(stderr, "========================= Package DSA Signature\n");
continue;
/*
* Don't bother with md5 if pgp, as RSA/MD5 is more reliable
- * than the legacy -- now unsupported -- legacy md5 breakage.
+ * than the -- now unsupported -- legacy md5 breakage.
*/
if (sigtag == RPMSIGTAG_PGP)
continue;
/*@switchbreak@*/ break;
+ case RPMSIGTAG_SHA1:
+#ifdef NOTYET
+ if (!(qva->qva_flags & VERIFY_DIGEST))
+ continue;
+ /*@switchbreak@*/ break;
+#endif
default:
continue;
/*@notreached@*/ /*@switchbreak@*/ break;
@@ -662,6 +684,7 @@ fprintf(stderr, "========================= Package DSA Signature\n");
/*@innerbreak@*/ break;
}
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
/* Do not consider this a failure */
switch (res3) {
@@ -703,6 +726,7 @@ fprintf(stderr, "========================= Package DSA Signature\n");
case RPMSIGTAG_PGP:
b = stpcpy(b, "pgp ");
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
b = stpcpy(b, "gpg ");
/*@switchbreak@*/ break;
diff --git a/lib/rpmlib.h b/lib/rpmlib.h
index 4b34fbbe7..1f7310969 100644
--- a/lib/rpmlib.h
+++ b/lib/rpmlib.h
@@ -228,6 +228,7 @@ typedef enum rpmTag_e {
/*@=enummemuse@*/
RPMTAG_SHA1HEADER = RPMTAG_SIG_BASE+9,
RPMTAG_PUBKEYS = RPMTAG_SIG_BASE+10,
+ RPMTAG_DSAHEADER = RPMTAG_SIG_BASE+11,
RPMTAG_NAME = 1000,
RPMTAG_VERSION = 1001,
@@ -773,9 +774,9 @@ typedef /*@abstract@*/ struct _rpmdbMatchIterator * rpmdbMatchIterator;
/*@modifies mi, fileSystem @*/;
/** \ingroup rpmdb
- * Return join key for current position of rpm database iterator.
+ * Return header join key for current position of rpm database iterator.
* @param mi rpm database iterator
- * @return current join key
+ * @return current header join key
*/
unsigned int rpmdbGetIteratorOffset(/*@null@*/ rpmdbMatchIterator mi)
/*@*/;
@@ -1780,12 +1781,16 @@ typedef enum rpmEraseInterfaceFlags_e {
enum rpmtagSignature {
RPMSIGTAG_SIZE = 1000, /*!< Header+Payload size in bytes. */
/* the md5 sum was broken *twice* on big endian machines */
- RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 */
+ RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 @deprecated legacy. */
RPMSIGTAG_PGP = 1002, /*!< PGP 2.6.3 signature. */
- RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 */
+ RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 @deprecated legacy. */
RPMSIGTAG_MD5 = 1004, /*!< MD5 signature. */
RPMSIGTAG_GPG = 1005, /*!< GnuPG signature. */
RPMSIGTAG_PGP5 = 1006, /*!< PGP5 signature @deprecated legacy. */
+ RPMSIGTAG_PAYLOADSIZE = 1007,
+ /*!< uncompressed payload size in bytes. */
+ RPMSIGTAG_SHA1 = RPMTAG_SHA1HEADER, /*!< sha1 header digest. */
+ RPMSIGTAG_DSA = RPMTAG_DSAHEADER, /*!< DSA header signature. */
};
/**
diff --git a/lib/signature.c b/lib/signature.c
index 40ed66cc1..f9a81b2e0 100644
--- a/lib/signature.c
+++ b/lib/signature.c
@@ -7,6 +7,7 @@
#include "rpmio_internal.h"
#include <rpmlib.h>
#include <rpmmacro.h> /* XXX for rpmGetPath() */
+#include "rpmdb.h"
#include "depends.h"
#include "misc.h" /* XXX for dosetenv() and makeTempFile() */
@@ -483,6 +484,10 @@ int rpmAddSignature(Header h, const char * file, int_32 sigTag,
if (ret == 0)
(void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, sig, size);
break;
+ case RPMSIGTAG_DSA: /* XXX UNIMPLEMENTED */
+ break;
+ case RPMSIGTAG_SHA1: /* XXX UNIMPLEMENTED */
+ break;
}
return ret;
@@ -523,6 +528,7 @@ static int checkPassPhrase(const char * passPhrase, const int sigTag)
(void) dup2(passPhrasePipe[0], 3);
switch (sigTag) {
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
{ const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
@@ -597,6 +603,7 @@ char * rpmGetPassPhrase(const char * prompt, const int sigTag)
int aok;
switch (sigTag) {
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
{ const char *name = rpmExpand("%{?_gpg_name}", NULL);
aok = (name && *name != '\0');
@@ -662,21 +669,31 @@ verifySizeSignature(const rpmTransactionSet ts, /*@out@*/ char * t)
*t = '\0';
t = stpcpy(t, _("Header+Payload size: "));
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
memcpy(&size, ts->sig, sizeof(size));
/*@-type@*/
/*@-nullderef@*/ /* FIX: ts->dig can be NULL */
if (size != ts->dig->nbytes) {
res = RPMSIG_BAD;
- sprintf(t, "BAD Expected(%d) != (%d)\n", size, ts->dig->nbytes);
+ t = stpcpy(t, rpmSigString(res));
+ sprintf(t, " Expected(%d) != (%d)\n", size, ts->dig->nbytes);
} else {
res = RPMSIG_OK;
- sprintf(t, "OK (%d)\n", ts->dig->nbytes);
+ t = stpcpy(t, rpmSigString(res));
+ sprintf(t, " (%d)", ts->dig->nbytes);
}
/*@=type@*/
/*@=nullpass =nullderef@*/
+exit:
+ t = stpcpy(t, "\n");
return res;
}
@@ -691,7 +708,13 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
*t = '\0';
t = stpcpy(t, _("MD5 digest: "));
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
/*@-type@*/
(void) rpmDigestFinal(rpmDigestDup(ts->dig->md5ctx),
(void **)&md5sum, &md5len, 0);
@@ -699,21 +722,172 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
if (md5len != ts->siglen || memcmp(md5sum, ts->sig, md5len)) {
res = RPMSIG_BAD;
- t = stpcpy(t, "BAD Expected(");
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " Expected(");
(void) pgpHexCvt(t, ts->sig, ts->siglen);
t += strlen(t);
t = stpcpy(t, ") != (");
} else {
res = RPMSIG_OK;
- t = stpcpy(t, "OK (");
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " (");
}
/*@=nullpass =nullderef@*/
(void) pgpHexCvt(t, md5sum, md5len);
t += strlen(t);
- t = stpcpy(t, ")\n");
+ t = stpcpy(t, ")");
+exit:
md5sum = _free(md5sum);
+ t = stpcpy(t, "\n");
+ return res;
+}
+
+static rpmVerifySignatureReturn
+verifySHA1Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
+ /*@modifies *t @*/
+{
+ rpmVerifySignatureReturn res;
+ const char * sha1 = NULL;
+
+ *t = '\0';
+ t = stpcpy(t, _("SHA1 header digest: "));
+
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+ /*@-type@*/
+ (void) rpmDigestFinal(rpmDigestDup(ts->dig->sha1ctx),
+ (void **)&sha1, NULL, 1);
+ /*@=type@*/
+
+ if (sha1 == NULL || strlen(sha1) != strlen(ts->sig)) {
+ res = RPMSIG_BAD;
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " Expected(");
+ t = stpcpy(t, ts->sig);
+ t = stpcpy(t, ") != (");
+ } else {
+ res = RPMSIG_OK;
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " (");
+ }
+ if (sha1)
+ t = stpcpy(t, sha1);
+ t = stpcpy(t, ")");
+
+exit:
+ sha1 = _free(sha1);
+ t = stpcpy(t, "\n");
+ return res;
+}
+
+/**
+ * Retrieve pubkey from rpm database.
+ * @param ts rpm transaction
+ * @return RPMSIG_OK on success, RPMSIG_NOKEY if not found
+ */
+static rpmVerifySignatureReturn
+rpmtsFindPubkey(rpmTransactionSet ts)
+ /*@modifies ts */
+{
+ struct pgpDigParams_s * sigp = NULL;
+ rpmVerifySignatureReturn res;
+ /*@unchecked@*/ /*@only@*/ static const byte * pkpkt = NULL;
+ /*@unchecked@*/ static size_t pkpktlen = 0;
+ /*@unchecked@*/ static byte pksignid[8];
+ int xx;
+
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
+ /*@-globs -internalglobs -mods -modfilesys@*/
+ if (pkpkt == NULL || memcmp(sigp->signid, pksignid, sizeof(pksignid))) {
+ int ix = -1;
+ rpmdbMatchIterator mi;
+ Header h;
+
+ pkpkt = _free(pkpkt);
+ pkpktlen = 0;
+ memset(pksignid, 0, sizeof(pksignid));
+
+ (void) rpmtsOpenDB(ts, ts->dbmode);
+
+ mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
+ while ((h = rpmdbNextIterator(mi)) != NULL) {
+ const char ** pubkeys;
+ int_32 pt, pc;
+
+ if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc))
+ continue;
+ ix = rpmdbGetIteratorFileNum(mi);
+ if (ix >= pc
+ || b64decode(pubkeys[ix], (void **) &pkpkt, &pkpktlen))
+ ix = -1;
+ pubkeys = headerFreeData(pubkeys, pt);
+ break;
+ }
+ mi = rpmdbFreeIterator(mi);
+
+ if (ix < 0 || pkpkt == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+
+ /* Make sure the pkt can be parsed, print info if debugging. */
+ if (pgpPrtPkts(pkpkt, pkpktlen, NULL, 0)) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+
+ /* XXX Verify the pubkey signature. */
+
+ /* Packet looks good, save the signer id. */
+ memcpy(pksignid, sigp->signid, sizeof(pksignid));
+ }
+
+#ifdef NOTNOW
+ {
+ if (pkpkt == NULL) {
+ const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
+ if (pgpReadPkts(pkfn, &pkpkt, &pkpktlen) != PGPARMOR_PUBKEY) {
+ pkfn = _free(pkfn);
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ pkfn = _free(pkfn);
+ }
+ }
+#endif
+
+ rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n",
+ (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" :
+ (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")),
+ pgpHexStr(sigp->signid, sizeof(sigp->signid)));
+
+ /* Retrieve parameters from pubkey packet(s). */
+ xx = pgpPrtPkts(pkpkt, pkpktlen, ts->dig, 0);
+ /*@=globs =internalglobs =mods =modfilesys@*/
+
+ /* Make sure we have the correct public key. */
+ if (ts->dig->signature.pubkey_algo == ts->dig->pubkey.pubkey_algo
+#ifdef NOTYET
+ && ts->dig->signature.hash_algo == ts->dig->pubkey.hash_algo
+#endif
+ && !memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
+ res = RPMSIG_OK;
+ else
+ res = RPMSIG_NOKEY;
+
+ /* XXX Verify the signature signature. */
+exit:
return res;
}
@@ -721,22 +895,33 @@ static rpmVerifySignatureReturn
verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t)
/*@modifies ts, *t */
{
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ struct pgpDigParams_s * sigp = NULL;
rpmVerifySignatureReturn res;
- struct pgpDigParams_s * digp = &ts->dig->signature;
- /*@unchecked@*/ static const byte * pgppk = NULL;
- /*@unchecked@*/ static size_t pgppklen = 0;
int xx;
*t = '\0';
t = stpcpy(t, _("V3 RSA/MD5 signature: "));
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
/* XXX sanity check on ts->sigtag and signature agreement. */
+ if (!(ts->sigtag == RPMSIGTAG_PGP
+ && sigp->pubkey_algo == PGPPUBKEYALGO_RSA
+ && sigp->hash_algo == PGPHASHALGO_MD5))
+ {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
/*@-type@*/ /* FIX: cast? */
{ DIGEST_CTX ctx = rpmDigestDup(ts->dig->md5ctx);
- xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen);
+ if (sigp->hash != NULL)
+ xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
xx = rpmDigestFinal(ctx, (void **)&ts->dig->md5, &ts->dig->md5len, 1);
/* XXX compare leading 16 bits of digest for quick check. */
@@ -763,46 +948,25 @@ verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t)
hexstr = _free(hexstr);
}
- /* XXX retrieve by keyid from signature. */
-
- /*@-globs -internalglobs -mods -modfilesys@*/
- if (pgppk == NULL) {
- const char * pkfn = rpmExpand("%{_pgp_pubkey}", NULL);
- if (pgpReadPkts(pkfn, &pgppk, &pgppklen) != PGPARMOR_PUBKEY) {
- pkfn = _free(pkfn);
- res = RPMSIG_NOKEY;
- goto exit;
- }
- rpmMessage(RPMMESS_DEBUG,
- "========== PGP RSA/MD5 pubkey %s\n", pkfn);
- xx = pgpPrtPkts(pgppk, pgppklen, NULL, rpmIsDebug());
- pkfn = _free(pkfn);
- }
-
- /* Retrieve parameters from pubkey packet(s). */
- xx = pgpPrtPkts(pgppk, pgppklen, ts->dig, 0);
- /*@=globs =internalglobs =mods =modfilesys@*/
-
- /* Make sure we have the correct public key. */
- if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo
- || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
- {
- res = RPMSIG_NOKEY;
+ /* Retrieve the matching public key. */
+ res = rpmtsFindPubkey(ts);
+ if (res != RPMSIG_OK)
goto exit;
- }
/*@-type@*/
- if (!rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c))
- res = RPMSIG_BAD;
- else
+ if (rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c))
res = RPMSIG_OK;
+ else
+ res = RPMSIG_BAD;
/*@=type@*/
-/*@=nullpass =nullderef@*/
exit:
- t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID ");
- (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4);
- t += strlen(t);
+ t = stpcpy(t, rpmSigString(res));
+ if (sigp != NULL) {
+ t = stpcpy(t, ", key ID ");
+ (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
+ t += strlen(t);
+ }
t = stpcpy(t, "\n");
return res;
}
@@ -811,71 +975,61 @@ static rpmVerifySignatureReturn
verifyGPGSignature(rpmTransactionSet ts, /*@out@*/ char * t)
/*@modifies ts, *t @*/
{
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ struct pgpDigParams_s * sigp = NULL;
rpmVerifySignatureReturn res;
- struct pgpDigParams_s * digp = &ts->dig->signature;
- /*@unchecked@*/ static const byte * gpgpk = NULL;
- /*@unchecked@*/ static size_t gpgpklen = 0;
int xx;
*t = '\0';
t = stpcpy(t, _("V3 DSA signature: "));
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
/* XXX sanity check on ts->sigtag and signature agreement. */
+ if (!((ts->sigtag == RPMSIGTAG_GPG || ts->sigtag == RPMSIGTAG_DSA)
+ && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
+ && sigp->hash_algo == PGPHASHALGO_SHA1))
+ {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
/*@-type@*/ /* FIX: cast? */
{ DIGEST_CTX ctx = rpmDigestDup(ts->dig->sha1ctx);
- xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen);
+ if (sigp->hash != NULL)
+ xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
xx = rpmDigestFinal(ctx, (void **)&ts->dig->sha1, &ts->dig->sha1len, 1);
+ /* XXX compare leading 16 bits of digest for quick check. */
+
mp32nzero(&ts->dig->hm); mp32nsethex(&ts->dig->hm, ts->dig->sha1);
}
/*@=type@*/
- /* XXX retrieve by keyid from signature. */
-
- /*@-globs -internalglobs -mods -modfilesys@*/
- if (gpgpk == NULL) {
- const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
- int printing = 0; /* XXX was rpmIsDebug() */
-
- if (pgpReadPkts(pkfn, &gpgpk, &gpgpklen) != PGPARMOR_PUBKEY) {
- pkfn = _free(pkfn);
- res = RPMSIG_NOKEY;
- goto exit;
- }
- rpmMessage(RPMMESS_DEBUG,
- "========== GPG DSA pubkey %s\n", pkfn);
- xx = pgpPrtPkts(gpgpk, gpgpklen, NULL, printing);
- pkfn = _free(pkfn);
- }
-
- /* Retrieve parameters from pubkey packet(s). */
- xx = pgpPrtPkts(gpgpk, gpgpklen, ts->dig, 0);
- /*@=globs =internalglobs =mods =modfilesys@*/
-
- /* Make sure we have the correct public key. */
- if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo
- || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
- {
- res = RPMSIG_NOKEY;
+ /* Retrieve the matching public key. */
+ res = rpmtsFindPubkey(ts);
+ if (res != RPMSIG_OK)
goto exit;
- }
/*@-type@*/
- if (!dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g,
+ if (dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g,
&ts->dig->hm, &ts->dig->y, &ts->dig->r, &ts->dig->s))
- res = RPMSIG_BAD;
- else
res = RPMSIG_OK;
+ else
+ res = RPMSIG_BAD;
/*@=type@*/
-/*@=nullpass =nullderef@*/
exit:
- t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID ");
- (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4);
- t += strlen(t);
+ t = stpcpy(t, rpmSigString(res));
+ if (sigp != NULL) {
+ t = stpcpy(t, ", key ID ");
+ (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
+ t += strlen(t);
+ }
t = stpcpy(t, "\n");
return res;
}
@@ -897,10 +1051,14 @@ rpmVerifySignature(const rpmTransactionSet ts, char * result)
case RPMSIGTAG_MD5:
res = verifyMD5Signature(ts, result);
break;
+ case RPMSIGTAG_SHA1:
+ res = verifySHA1Signature(ts, result);
+ break;
case RPMSIGTAG_PGP5: /* XXX legacy */
case RPMSIGTAG_PGP:
res = verifyPGPSignature(ts, result);
break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
res = verifyGPGSignature(ts, result);
break;
diff --git a/lib/verify.c b/lib/verify.c
index 13a30e3ee..c3f544bf1 100644
--- a/lib/verify.c
+++ b/lib/verify.c
@@ -572,10 +572,12 @@ int rpmcliVerify(rpmTransactionSet ts, QVA_t qva, const char ** argv)
qva->qva_showPackage = showVerifyPackage;
switch (qva->qva_source) {
+#ifdef DYING
case RPMQV_RPM:
if (!(qva->qva_flags & VERIFY_DEPS))
break;
/*@fallthrough@*/
+#endif
default:
if (rpmtsOpenDB(ts, O_RDONLY))
return 1; /* XXX W2DO? */