RPM Package Manager, CVS Repository
http://rpm5.org/cvs/
____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson
Root: /v/rpm/cvs Email: jbj@rpm5.org
Module: rpm Date: 29-Dec-2007 21:18:47
Branch: HEAD Handle: 2007122920184601
Modified files:
rpm CHANGES
rpm/lib librpm.vers rpmns.c rpmns.h
Log:
- add rpmnsProbeSignature() & "signature(/text:/sig) = /pub:id" name
space.
Summary:
Revision Changes Path
1.2037 +1 -0 rpm/CHANGES
1.30 +1 -0 rpm/lib/librpm.vers
1.8 +230 -1 rpm/lib/rpmns.c
1.11 +16 -0 rpm/lib/rpmns.h
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: rpm/CHANGES
============================================================================
$ cvs diff -u -r1.2036 -r1.2037 CHANGES
--- rpm/CHANGES 29 Dec 2007 16:00:07 -0000 1.2036
+++ rpm/CHANGES 29 Dec 2007 20:18:46 -0000 1.2037
@@ -1,4 +1,5 @@
5.0b3 -> 5.0b4:
+ - jbj: add rpmnsProbeSignature() & "signature(/text:/sig) = /pub:id" probe.
- jbj: pgpReadPkts: truncate binary encoded pgp pktlen to actual length.
- jbj: pgpReadPkts: identify binary encoded pgp pkts correctly.
- jbj: fix: remove unused assertion.
@@ .
patch -p0 <<'@@ .'
Index: rpm/lib/librpm.vers
============================================================================
$ cvs diff -u -r1.29 -r1.30 librpm.vers
--- rpm/lib/librpm.vers 18 Dec 2007 19:40:53 -0000 1.29
+++ rpm/lib/librpm.vers 29 Dec 2007 20:18:47 -0000 1.30
@@ -221,6 +221,7 @@
_rpmns_debug;
rpmnsClassify;
rpmnsParse;
+ rpmnsProbeSignature;
rpmPermsString;
rpmPlatformScore;
rpmProblemString;
@@ .
patch -p0 <<'@@ .'
Index: rpm/lib/rpmns.c
============================================================================
$ cvs diff -u -r1.7 -r1.8 rpmns.c
--- rpm/lib/rpmns.c 7 Dec 2007 19:54:18 -0000 1.7
+++ rpm/lib/rpmns.c 29 Dec 2007 20:18:47 -0000 1.8
@@ -3,14 +3,23 @@
*/
#include "system.h"
-#include <rpmio.h>
+#include <rpmio_internal.h> /* XXX rpmioSlurp */
#include <rpmmacro.h>
+#define _RPMPGP_INTERNAL
+#include <rpmpgp.h>
+
#define _RPMEVR_INTERNAL
#include <rpmevr.h>
#define _RPMNS_INTERNAL
#include <rpmns.h>
+#include <rpmcb.h>
+#include <rpmdb.h>
+#include <rpmps.h>
+#define _RPMTS_INTERNAL /* XXX ts->pkpkt */
+#include <rpmts.h>
+
#include "debug.h"
/*@unchecked@*/
@@ -79,6 +88,7 @@
{ "running", RPMNS_TYPE_RUNNING },
{ "sanitycheck", RPMNS_TYPE_SANITY },
{ "vcheck", RPMNS_TYPE_VCHECK },
+ { "signature", RPMNS_TYPE_SIGNATURE },
{ "exists", RPMNS_TYPE_ACCESS },
{ "executable", RPMNS_TYPE_ACCESS },
{ "readable", RPMNS_TYPE_ACCESS },
@@ -196,6 +206,7 @@
case RPMNS_TYPE_RUNNING:
case RPMNS_TYPE_SANITY:
case RPMNS_TYPE_VCHECK:
+ case RPMNS_TYPE_SIGNATURE:
ns->NS = ns->str;
if (ns->NS[0] == '!')
ns->NS++;
@@ -226,3 +237,221 @@
}
return 0;
}
+
+/**
+ * Convert hex to binary nibble.
+ * @param c hex character
+ * @return binary nibble
+ */
+static inline unsigned char nibble(char c)
+ /*@*/
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A') + 10;
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a') + 10;
+ return 0;
+}
+
+int rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
+ const char * pubfn, const char * pubid)
+{
+ rpmts ts = _ts;
+ pgpDig dig = rpmtsDig(ts);
+ pgpDigParams sigp;
+ pgpDigParams pubp;
+ const unsigned char * sigpkt = NULL;
+ size_t sigpktlen = 0;
+ DIGEST_CTX ctx = NULL;
+ int printing = 0;
+ int rc = 0;
+ int xx;
+
+ /* Load the signature. Use sigfn if specified, otherwise clearsign. */
+ if (sigfn != NULL) {
+ const char * _sigfn = rpmExpand(sigfn, NULL);
+ xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
+ if (xx != PGPARMOR_SIGNATURE) {
+ _sigfn = _free(_sigfn);
+ goto exit;
+ }
+ _sigfn = _free(_sigfn);
+ } else {
+ const char * _sigfn = rpmExpand(fn, NULL);
+ xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
+ if (xx != PGPARMOR_SIGNATURE) {
+ _sigfn = _free(_sigfn);
+ goto exit;
+ }
+ _sigfn = _free(_sigfn);
+ }
+ xx = pgpPrtPkts((uint8_t *)sigpkt, sigpktlen, dig, printing);
+ if (xx)
+ goto exit;
+
+ sigp = pgpGetSignature(dig);
+
+ if (sigp->version != 3 && sigp->version != 4)
+ goto exit;
+
+ /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */
+ if (pubfn != NULL) {
+ const char * _pubfn = rpmExpand(pubfn, NULL);
+ xx = pgpReadPkts(_pubfn, &ts->pkpkt, &ts->pkpktlen);
+ if (xx != PGPARMOR_PUBKEY) {
+ _pubfn = _free(_pubfn);
+ goto exit;
+ }
+ _pubfn = _free(_pubfn);
+ xx = pgpPrtPkts((uint8_t *)ts->pkpkt, ts->pkpktlen, dig, printing);
+ if (xx)
+ goto exit;
+ } else {
+ if (pgpFindPubkey(dig) != RPMRC_OK)
+ goto exit;
+ }
+
+ pubp = pgpGetPubkey(dig);
+
+ /* Is this the requested pubkey? */
+ if (pubid != NULL) {
+ size_t ns = strlen(pubid);
+ const char * s;
+ char * t;
+ int i;
+
+ /* At least 8 hex digits please. */
+ for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++)
+ ;
+ if (!(*s == '\0' && i > 8 && (i%2) == 0))
+ goto exit;
+
+ /* Truncate to key id size. */
+ s = pubid;
+ if (ns > 16) {
+ s += (ns - 16);
+ ns = 16;
+ }
+ ns >>= 1;
+ t = memset(alloca(ns), 0, ns);
+ for (i = 0; i < ns; i++)
+ t[i] = (nibble(s[2*i]) << 4) | nibble(s[2*i+1]);
+
+ /* Compare the pubkey id. */
+ s = (const char *)pubp->signid;
+ xx = memcmp(t, s + (8 - ns), ns);
+
+ /* XXX HACK: V4 RSA key id's are wonky atm. */
+ if (pubp->pubkey_algo == PGPPUBKEYALGO_RSA)
+ xx = 0;
+
+ if (xx)
+ goto exit;
+ }
+
+ /* Do the parameters match the signature? */
+ if (!(sigp->pubkey_algo == pubp->pubkey_algo
+#ifdef NOTYET
+ && sigp->hash_algo == pubp->hash_algo
+#endif
+ /* XXX HACK: V4 RSA key id's are wonky atm. */
+ && (pubp->pubkey_algo == PGPPUBKEYALGO_RSA || !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid))) ) )
+ goto exit;
+
+ /* Compute the message digest. */
+ ctx = rpmDigestInit(sigp->hash_algo, RPMDIGEST_NONE);
+
+ {
+ static const char clrtxt[] = "-----BEGIN PGP SIGNED MESSAGE-----";
+ static const char sigtxt[] = "-----BEGIN PGP SIGNATURE-----";
+ const char * _fn = rpmExpand(fn, NULL);
+ uint8_t * b = NULL;
+ ssize_t blen = 0;
+ int _rc = rpmioSlurp(_fn, &b, &blen);
+
+ if (!(_rc == 0 && b != NULL && blen > 0)) {
+ b = _free(b);
+ _fn = _free(_fn);
+ goto exit;
+ }
+ _fn = _free(_fn);
+
+ /* XXX clearsign sig is PGPSIGTYPE_TEXT not PGPSIGTYPE_BINARY. */
+ if (!strncmp((char *)b, clrtxt, strlen(clrtxt))) {
+ const char * be = (char *) (b + blen);
+ const char * t;
+ const char * te;
+
+ /* Skip to '\n\n' start-of-plaintext */
+ t = (char *) b;
+ while (t && t < be && *t != '\n')
+ t = strchr(t, '\n') + 1;
+ if (!(t && t < be))
+ goto exit;
+ t++;
+
+ /* Skip to start-of-signature */
+ te = t;
+ while (te && te < be && strncmp(te, sigtxt, strlen(sigtxt)))
+ te = strchr(te, '\n') + 1;
+ if (!(te && te < be))
+ goto exit;
+ te--; /* hmmm, one too far? does clearsign snip last \n? */
+
+ xx = rpmDigestUpdate(ctx, t, (te - t));
+ } else
+ xx = rpmDigestUpdate(ctx, b, blen);
+
+ b = _free(b);
+ }
+
+ if (sigp->hash != NULL)
+ xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
+ if (sigp->version == 4) {
+ uint32_t nb = sigp->hashlen;
+ uint8_t trailer[6];
+ nb = htonl(nb);
+ trailer[0] = sigp->version;
+ trailer[1] = 0xff;
+ memcpy(trailer+2, &nb, sizeof(nb));
+ xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
+ }
+
+ /* Load the message digest. */
+ switch(sigp->pubkey_algo) {
+ default:
+ xx = 1;
+ break;
+ case PGPPUBKEYALGO_DSA:
+ xx = pgpImplSetDSA(ctx, dig, sigp);
+ break;
+ case PGPPUBKEYALGO_RSA:
+ xx = pgpImplSetRSA(ctx, dig, sigp);
+ break;
+ }
+ if (xx)
+ goto exit;
+
+ /* Verify the signature. */
+ switch(sigp->pubkey_algo) {
+ default:
+ rc = 0;
+ break;
+ case PGPPUBKEYALGO_DSA:
+ rc = pgpImplVerifyDSA(dig);
+ break;
+ case PGPPUBKEYALGO_RSA:
+ rc = pgpImplVerifyRSA(dig);
+ break;
+ }
+
+exit:
+ sigpkt = _free(sigpkt);
+ ts->pkpkt = _free(ts->pkpkt);
+ ts->pkpktlen = 0;
+ rpmtsCleanDig(ts);
+
+ return rc;
+}
@@ .
patch -p0 <<'@@ .'
Index: rpm/lib/rpmns.h
============================================================================
$ cvs diff -u -r1.10 -r1.11 rpmns.h
--- rpm/lib/rpmns.h 26 Dec 2007 09:55:59 -0000 1.10
+++ rpm/lib/rpmns.h 29 Dec 2007 20:18:47 -0000 1.11
@@ -50,6 +50,7 @@
RPMNS_TYPE_RUNNING = (1 << 24), /*!< running(foo) */
RPMNS_TYPE_SANITY = (1 << 25), /*!< sanitycheck(foo) */
RPMNS_TYPE_VCHECK = (1 << 26), /*!< vcheck(foo) */
+ RPMNS_TYPE_SIGNATURE= (1 << 27), /*!< signature(/text:/sig) = /pub:id */
} nsType;
#if defined(_RPMNS_INTERNAL)
@@ -115,6 +116,21 @@
/*@globals internalState @*/
/*@modifies internalState @*/;
+/** \ingroup rpmns
+ * Verify OpenPGP signature on a file.
+ * @param _ts transaction set
+ * @param fn plaintext (or clearsign) file
+ * @param sigfn binary/pem encoded signature file (NULL iff clearsign)
+ * @param pubfn binary/pem encoded pubkey file (NULL uses rpmdb keyring)
+ * @param pubid pubkey fingerprint hex string (NULL disables check)
+ * @return 1 if verified, 0 if not verified
+ */
+int rpmnsProbeSignature(void * _ts, const char * fn,
+ /*@null@*/ const char * sigfn,
+ /*@null@*/ const char * pubfn,
+ /*@null@*/ const char * pubid)
+ /*@*/;
+
#ifdef __cplusplus
}
#endif
@@ .
Received on Sat Dec 29 21:18:47 2007