RPM Community Forums

Mailing List Message of <rpm-devel>

Re: [CVS] RPM: rpm/ CHANGES rpm/lib/ librpm.vers rpmns.c rpmns.h

From: Jeff Johnson <n3npq@mac.com>
Date: Sat 29 Dec 2007 - 21:29:11 CET
Message-Id: <92E28D4E-8822-460F-ACAD-AC141833F0DB@mac.com>
Almost all yours Ralf ;-)

I've renamed the routine (and changed the name space) to be more  
generic.
I'm way tired of branding signification issues, PGP and GPG too ...

I'll wire up (and test) the signature(...) probe next.

Then I'll set about wiring up rpmRC returns, and add sufficient
debugging to diagnose rpm's bizarrely inscrutable behavior patterns.  
There's way
too many error conditions (and the args are a bit twisty) to rely on the
overly simplified 0/1 verify return. You lose! is not what lusers  
want to hear ...

Enjoy!

73 de Jeff


On Dec 29, 2007, at 3:18 PM, Jeff Johnson wrote:

>   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
>   @@ .
> ______________________________________________________________________
> RPM Package Manager                                    http://rpm5.org
> CVS Sources Repository                                rpm-cvs@rpm5.org
Received on Sat Dec 29 21:29:33 2007
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.