RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: rpm/ CHANGES rpm/build/ build.c pack.c rpm/lib/ Makefile.am...

From: Jeff Johnson <jbj@rpm5.org>
Date: Mon 01 Oct 2007 - 00:38:31 CEST
Message-Id: <20070930223831.9D12334845F@rpm5.org>
  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:   01-Oct-2007 00:38:31
  Branch: HEAD                             Handle: 2007093023382703

  Added files:
    rpm/rpmdb               signature.c signature.h
  Modified files:
    rpm                     CHANGES
    rpm/build               build.c pack.c
    rpm/lib                 Makefile.am librpm.vers misc.c misc.h psm.c
                            rpmchecksig.c rpmlib.h rpmts.c
    rpm/python              rpmts-py.c
    rpm/rpmdb               Makefile.am librpmdb.vers pkgio.c rpmdb.c
  Removed files:
    rpm/lib                 signature.c signature.h

  Log:
    - insure rpmlib -> rpmdb forward linkage only.

  Summary:
    Revision    Changes     Path
    1.1650      +1  -0      rpm/CHANGES
    2.116       +2  -1      rpm/build/build.c
    2.229       +2  -1      rpm/build/pack.c
    2.166       +2  -2      rpm/lib/Makefile.am
    1.20        +0  -4      rpm/lib/librpm.vers
    2.144       +0  -104    rpm/lib/misc.c
    2.67        +0  -21     rpm/lib/misc.h
    2.233       +3  -3      rpm/lib/psm.c
    1.148       +2  -3      rpm/lib/rpmchecksig.c
    2.439       +0  -12     rpm/lib/rpmlib.h
    2.104       +0  -11     rpm/lib/rpmts.c
    2.193       +0  -1239   rpm/lib/signature.c
    2.48        +0  -52     rpm/lib/signature.h
    1.71        +1  -0      rpm/python/rpmts-py.c
    1.81        +2  -2      rpm/rpmdb/Makefile.am
    1.19        +5  -0      rpm/rpmdb/librpmdb.vers
    1.10        +38 -18     rpm/rpmdb/pkgio.c
    1.163       +10 -0      rpm/rpmdb/rpmdb.c
    1.1         +1344 -0    rpm/rpmdb/signature.c
    1.1         +85 -0      rpm/rpmdb/signature.h
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/CHANGES
  ============================================================================
  $ cvs diff -u -r1.1649 -r1.1650 CHANGES
  --- rpm/CHANGES	29 Sep 2007 19:29:00 -0000	1.1649
  +++ rpm/CHANGES	30 Sep 2007 22:38:27 -0000	1.1650
  @@ -1,4 +1,5 @@
   4.5 -> 5.0:
  +    - jbj: insure rpmlib -> rpmdb forward linkage only.
       - jbj: eliminate (*hdrchk) vector everywhere, use headerCheck() instead.
       - jbj: add metadata header stubs to pkgio.c.
       - jbj: move rpmtsFindPubkey() and rpmtsOp() to rpmdb for forward linkage.
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/build/build.c
  ============================================================================
  $ cvs diff -u -r2.115 -r2.116 build.c
  --- rpm/build/build.c	17 Aug 2007 00:13:56 -0000	2.115
  +++ rpm/build/build.c	30 Sep 2007 22:38:28 -0000	2.116
  @@ -7,6 +7,7 @@
   
   #include <rpmio_internal.h>
   #include <rpmbuild.h>
  +#include "signature.h"		/* XXX rpmTempFile */
   
   #include "debug.h"
   
  @@ -145,7 +146,7 @@
   	goto exit;
       }
       
  -    if (makeTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
  +    if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
   	rpmError(RPMERR_SCRIPT, _("Unable to open temp file.\n"));
   	rc = RPMERR_SCRIPT;
   	goto exit;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/build/pack.c
  ============================================================================
  $ cvs diff -u -r2.228 -r2.229 pack.c
  --- rpm/build/pack.c	29 Sep 2007 18:18:57 -0000	2.228
  +++ rpm/build/pack.c	30 Sep 2007 22:38:28 -0000	2.229
  @@ -8,6 +8,7 @@
   #include <rpmio_internal.h>
   #define	_RPMEVR_INTERNAL	/* XXX RPMSENSE_ANY */
   #include <rpmbuild.h>
  +#include "signature.h"		/* XXX rpmTempFile */
   
   #include "rpmps.h"
   
  @@ -618,7 +619,7 @@
        * archive (after compression) can be added to the header.
        */
       sigtarget = NULL;
  -    if (makeTempFile(NULL, &sigtarget, &fd)) {
  +    if (rpmTempFile(NULL, &sigtarget, &fd)) {
   	rc = RPMERR_CREATE;
   	rpmError(RPMERR_CREATE, _("Unable to open temp file.\n"));
   	goto exit;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/Makefile.am
  ============================================================================
  $ cvs diff -u -r2.165 -r2.166 Makefile.am
  --- rpm/lib/Makefile.am	8 Sep 2007 16:17:33 -0000	2.165
  +++ rpm/lib/Makefile.am	30 Sep 2007 22:38:28 -0000	2.166
  @@ -27,7 +27,7 @@
   	rpmal.h rpmdpkg.h rpmds.h rpmevr.h rpmfc.h rpmfi.h rpmgi.h \
   	rpmns.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h
   noinst_HEADERS = \
  -	cpio.h fsm.h manifest.h psm.h rpmlock.h signature.h tar.h
  +	cpio.h fsm.h manifest.h psm.h rpmlock.h tar.h
   
   usrlibdir = $(libdir)
   usrlib_LTLIBRARIES = librpm.la
  @@ -38,7 +38,7 @@
   	rpmal.c rpmchecksig.c rpmdpkg.c rpmds.c rpmevr.c rpmfc.c \
   	rpmfi.c rpmgi.c rpminstall.c rpmrollback.c \
   	rpmlock.c rpmns.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \
  -	signature.c stringbuf.c transaction.c \
  +	stringbuf.c transaction.c \
   	verify.c tar.c
   librpm_la_LDFLAGS = -release $(LT_CURRENT).$(LT_REVISION)
   if HAVE_LD_VERSION_SCRIPT
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/librpm.vers
  ============================================================================
  $ cvs diff -u -r1.19 -r1.20 librpm.vers
  --- rpm/lib/librpm.vers	29 Sep 2007 16:23:39 -0000	1.19
  +++ rpm/lib/librpm.vers	30 Sep 2007 22:38:28 -0000	1.20
  @@ -49,7 +49,6 @@
       _print_pkts;
       _psm_debug;
       _psm_threads;
  -    rpmAddSignature;
       rpmalAdd;
       rpmalAddProvides;
       rpmalAllFileSatisfiesDepend;
  @@ -60,7 +59,6 @@
       rpmalFree;
       rpmalMakeIndex;
       rpmalSatisfiesDepend;
  -    rpmCheckPassPhrase;
       rpmcliAllPoptTable;
       rpmcliArgIter;
       rpmcliConfigured;
  @@ -346,7 +344,6 @@
       rpmtsFlags;
       rpmtsFree;
       rpmtsFreeLock;
  -    rpmtsGetRdb;
       rpmtsGetTid;
       rpmtsGetType;
       rpmtsGoal;
  @@ -399,7 +396,6 @@
       rpmvercmp;
       rpmVerifyFile;
       rpmVerifyPoptTable;
  -    rpmVerifySignature;
       rpmVerifySignatures;
       RPMVERSION;
       rpmVersionCompare;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/misc.c
  ============================================================================
  $ cvs diff -u -r2.143 -r2.144 misc.c
  --- rpm/lib/misc.c	30 Sep 2007 20:38:25 -0000	2.143
  +++ rpm/lib/misc.c	30 Sep 2007 22:38:28 -0000	2.144
  @@ -113,110 +113,6 @@
       return putenv(a);
   }
   
  -int makeTempFile(const char * prefix, const char ** fnptr, void * fdptr)
  -{
  -    const char * tpmacro = "%{?_tmppath}%{!?_tmppath:/var/tmp/}";
  -    const char * tempfn = NULL;
  -    const char * tfn = NULL;
  -    static int _initialized = 0;
  -    int temput;
  -    FD_t fd = NULL;
  -    int ran;
  -
  -    if (!prefix) prefix = "";
  -
  -    /* Create the temp directory if it doesn't already exist. */
  -    if (!_initialized) {
  -	_initialized = 1;
  -	tempfn = rpmGenPath(prefix, tpmacro, NULL);
  -	if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
  -	    goto errxit;
  -    }
  -
  -    /* XXX should probably use mkstemp here */
  -    srand(time(NULL));
  -    ran = rand() % 100000;
  -
  -    /* maybe this should use link/stat? */
  -
  -    do {
  -	char tfnbuf[64];
  -#ifndef	NOTYET
  -	sprintf(tfnbuf, "rpm-tmp.%d", ran++);
  -	tempfn = _free(tempfn);
  -	tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
  -#else
  -	strcpy(tfnbuf, "rpm-tmp.XXXXXX");
  -	tempfn = _free(tempfn);
  -	tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
  -#endif
  -
  -	temput = urlPath(tempfn, &tfn);
  -	if (*tfn == '\0') goto errxit;
  -
  -	switch (temput) {
  -	case URL_IS_DASH:
  -	case URL_IS_HKP:
  -	    goto errxit;
  -	    /*@notreached@*/ /*@switchbreak@*/ break;
  -	case URL_IS_HTTPS:
  -	case URL_IS_HTTP:
  -	case URL_IS_FTP:
  -	default:
  -	    /*@switchbreak@*/ break;
  -	}
  -
  -	fd = Fopen(tempfn, "w+x.fdio");
  -	/* XXX FIXME: errno may not be correct for ufdio */
  -    } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
  -
  -    if (fd == NULL || Ferror(fd))
  -	goto errxit;
  -
  -    switch(temput) {
  -    case URL_IS_PATH:
  -    case URL_IS_UNKNOWN:
  -      {	struct stat sb, sb2;
  -	if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
  -	    rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  -	    goto errxit;
  -	}
  -
  -	if (sb.st_nlink != 1) {
  -	    rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  -	    goto errxit;
  -	}
  -
  -	if (fstat(Fileno(fd), &sb2) == 0) {
  -	    if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
  -		rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  -		goto errxit;
  -	    }
  -	}
  -      }	break;
  -    default:
  -	break;
  -    }
  -
  -    if (fnptr)
  -	*fnptr = tempfn;
  -    else 
  -	tempfn = _free(tempfn);
  -    if (fdptr)
  -	*(FD_t *)fdptr = fd;
  -
  -    return 0;
  -
  -errxit:
  -    tempfn = _free(tempfn);
  -    if (fnptr)
  -	*fnptr = NULL;
  -    /*@-usereleased@*/
  -    if (fd != NULL) (void) Fclose(fd);
  -    /*@=usereleased@*/
  -    return 1;
  -}
  -
   char * currentDirectory(void)
   {
       int currDirLen = 0;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/misc.h
  ============================================================================
  $ cvs diff -u -r2.66 -r2.67 misc.h
  --- rpm/lib/misc.h	16 Jul 2007 01:32:28 -0000	2.66
  +++ rpm/lib/misc.h	30 Sep 2007 22:38:28 -0000	2.67
  @@ -79,27 +79,6 @@
   	/*@modifies *environ @*/;
   
   /**
  - * Return file handle for a temporaray file.
  - * A unique temporaray file path will be generated using
  - *	rpmGenPath(prefix, "%{_tmppath}/", "rpm-tmp.XXXXX")
  - * where "XXXXXX" is filled in using rand(3). The file is opened, and
  - * the link count and (dev,ino) location are verified after opening.
  - * The file name and the open file handle are returned.
  - *
  - * @param prefix	leading part of temp file path
  - * @retval *fnptr	temp file name (or NULL)
  - * @retval *fdptr	temp file handle
  - * @return		0 on success
  - */
  -int makeTempFile(/*@null@*/ const char * prefix,
  -		/*@null@*/ /*@out@*/ const char ** fnptr,
  -		/*@out@*/ void * fdptr)
  -	/*@globals rpmGlobalMacroContext, h_errno,
  -		fileSystem, internalState @*/
  -	/*@modifies *fnptr, *fdptr, rpmGlobalMacroContext,
  -		fileSystem, internalState @*/;
  -
  -/**
    * Return (malloc'd) current working directory.
    * @return		current working directory (malloc'ed)
    */
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/psm.c
  ============================================================================
  $ cvs diff -u -r2.232 -r2.233 psm.c
  --- rpm/lib/psm.c	30 Sep 2007 20:38:25 -0000	2.232
  +++ rpm/lib/psm.c	30 Sep 2007 22:38:28 -0000	2.233
  @@ -28,9 +28,9 @@
   #include "rpmts.h"
   
   #include <pkgio.h>
  -#include "signature.h"		/* signature constants */
  -#include "misc.h"		/* XXX stripTrailingChar() */
  +#include "misc.h"		/* XXX rpmMkdirPath */
   #include "rpmdb.h"		/* XXX for db_chrootDone */
  +#include "signature.h"		/* signature constants */
   #include "debug.h"
   
   #define	_PSM_DEBUG	0
  @@ -701,7 +701,7 @@
   	const char * rootDir = rpmtsRootDir(ts);
   	FD_t fd;
   
  -	if (makeTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd))
  +	if (rpmTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd))
   	    goto exit;
   
   	if (rpmIsDebug() &&
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/rpmchecksig.c
  ============================================================================
  $ cvs diff -u -r1.147 -r1.148 rpmchecksig.c
  --- rpm/lib/rpmchecksig.c	30 Sep 2007 20:38:25 -0000	1.147
  +++ rpm/lib/rpmchecksig.c	30 Sep 2007 22:38:28 -0000	1.148
  @@ -17,7 +17,6 @@
   
   #include <pkgio.h>
   #include "signature.h"
  -#include "misc.h"	/* XXX for makeTempFile() */
   #include "debug.h"
   
   /*@access FD_t @*/		/* XXX stealing digests */
  @@ -68,8 +67,8 @@
       /* open a temp file */
       if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) {
   	fn = NULL;
  -	if (makeTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
  -	    rpmError(RPMERR_MAKETEMP, _("makeTempFile failed\n"));
  +	if (rpmTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
  +	    rpmError(RPMERR_MAKETEMP, _("rpmTempFile failed\n"));
   	    return 1;
   	}
   	if (fnp != NULL)
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/rpmlib.h
  ============================================================================
  $ cvs diff -u -r2.438 -r2.439 rpmlib.h
  --- rpm/lib/rpmlib.h	30 Sep 2007 20:38:25 -0000	2.438
  +++ rpm/lib/rpmlib.h	30 Sep 2007 22:38:28 -0000	2.439
  @@ -938,18 +938,6 @@
       RPMSIGTAG_RSA	= RPMTAG_RSAHEADER	/*!< internal RSA header signature. */
   };
   
  -/** \ingroup signature
  - * Verify a signature from a package.
  - *
  - * @param _dig		container
  - * @retval result	detailed text result of signature verification
  - * @return		result of signature verification
  - */
  -rpmRC rpmVerifySignature(void * _dig, /*@out@*/ char * result)
  -	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  -	/*@modifies _dig, *result, rpmGlobalMacroContext,
  -		fileSystem, internalState @*/;
  -
   /*@}*/
   
   #ifdef __cplusplus
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/lib/rpmts.c
  ============================================================================
  $ cvs diff -u -r2.103 -r2.104 rpmts.c
  --- rpm/lib/rpmts.c	30 Sep 2007 20:38:26 -0000	2.103
  +++ rpm/lib/rpmts.c	30 Sep 2007 22:38:28 -0000	2.104
  @@ -881,17 +881,6 @@
       return otid;
   }
   
  -rpmdb rpmtsGetRdb(rpmts ts)
  -{
  -    rpmdb rdb = NULL;
  -    if (ts != NULL) {
  -	rdb = ts->rdb;
  -    }
  -/*@-compdef -refcounttrans -usereleased @*/
  -    return rdb;
  -/*@=compdef =refcounttrans =usereleased @*/
  -}
  -
   rpmPRCO rpmtsPRCO(rpmts ts)
   {
   /*@-compdef -retexpose -usereleased @*/
  @@ .
  rm -f rpm/lib/signature.c <<'@@ .'
  Index: rpm/lib/signature.c
  ============================================================================
  [NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]
  @@ .
  rm -f rpm/lib/signature.h <<'@@ .'
  Index: rpm/lib/signature.h
  ============================================================================
  [NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/python/rpmts-py.c
  ============================================================================
  $ cvs diff -u -r1.70 -r1.71 rpmts-py.c
  --- rpm/python/rpmts-py.c	21 Aug 2007 03:41:52 -0000	1.70
  +++ rpm/python/rpmts-py.c	30 Sep 2007 22:38:30 -0000	1.71
  @@ -10,6 +10,7 @@
   #include <rpmcli.h>
   #include <rpmpgp.h>
   #include <rpmdb.h>
  +#include <pkgio.h>		/* XXX headerCheck() */
   #include <rpmbuild.h>
   
   #include "header-py.h"
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/Makefile.am
  ============================================================================
  $ cvs diff -u -r1.80 -r1.81 Makefile.am
  --- rpm/rpmdb/Makefile.am	30 Sep 2007 17:29:05 -0000	1.80
  +++ rpm/rpmdb/Makefile.am	30 Sep 2007 22:38:30 -0000	1.81
  @@ -26,7 +26,7 @@
   tjfn_LDADD = librpmdb.la
   
   pkgincdir = $(pkgincludedir)$(WITH_PATH_VERSIONED_SUFFIX)
  -pkginc_HEADERS = header.h hdrinline.h pkgio.h rpmdb.h
  +pkginc_HEADERS = header.h hdrinline.h pkgio.h rpmdb.h signature.h
   noinst_HEADERS = fprint.h header_internal.h legacy.h
   
   pkglibdir =		@USRLIBRPM@
  @@ -42,7 +42,7 @@
   	dbconfig.c fprint.c \
   	hdrfmt.c hdrNVR.c header.c header_internal.c legacy.c merge.c \
   	pkgio.c poptDB.c rpmdb.c \
  -	tagname.c tagtbl.c
  +	signature.c tagname.c tagtbl.c
   librpmdb_la_LDFLAGS = -release $(LT_CURRENT).$(LT_REVISION)
   if HAVE_LD_VERSION_SCRIPT
   librpmdb_la_LDFLAGS += -Wl,--version-script=$(srcdir)/librpmdb.vers
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/librpmdb.vers
  ============================================================================
  $ cvs diff -u -r1.18 -r1.19 librpmdb.vers
  --- rpm/rpmdb/librpmdb.vers	29 Sep 2007 17:06:25 -0000	1.18
  +++ rpm/rpmdb/librpmdb.vers	30 Sep 2007 22:38:30 -0000	1.19
  @@ -45,6 +45,8 @@
       _newmagic;
       prDbiOpenFlags;
       rdbOptions;
  +    rpmAddSignature;
  +    rpmCheckPassPhrase;
       rpmDatabasePoptTable;
       rpmdbAdd;
       rpmdbAppendIterator;
  @@ -85,12 +87,15 @@
       rpmTagTable;
       rpmTagTableSize;
       rpmTags;
  +    rpmTempFile;
       rpmtsCleanDig;
       rpmtsDig;
       rpmtsFindPubkey;
  +    rpmtsGetRdb;
       rpmtsOp;
       rpmtsPubkey;
       rpmtsSetSig;
  +    rpmVerifySignature;
       sqlitevec;
       XrpmdbLink;
       XrpmdbUnlink;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/pkgio.c
  ============================================================================
  $ cvs diff -u -r1.9 -r1.10 pkgio.c
  --- rpm/rpmdb/pkgio.c	30 Sep 2007 17:29:05 -0000	1.9
  +++ rpm/rpmdb/pkgio.c	30 Sep 2007 22:38:30 -0000	1.10
  @@ -26,6 +26,7 @@
   
   #include "header_internal.h"
   #include <pkgio.h>
  +#include "signature.h"
   #include "debug.h"
   
   /*@access rpmts @*/
  @@ -59,6 +60,17 @@
   /*@=onlytrans@*/
   }
   
  +rpmdb rpmtsGetRdb(rpmts ts)
  +{
  +    rpmdb rdb = NULL;
  +    if (ts != NULL) {
  +	rdb = ts->rdb;
  +    }
  +/*@-compdef -refcounttrans -usereleased @*/
  +    return rdb;
  +/*@=compdef =refcounttrans =usereleased @*/
  +}
  +
   rpmRC rpmtsFindPubkey(rpmts ts, void * _dig)
   {
       pgpDig dig = (_dig ? _dig : rpmtsDig(ts));
  @@ -72,8 +84,16 @@
   #endif
       int xx;
   
  +#ifdef	DYING
       if (sig == NULL || dig == NULL || sigp == NULL || pubp == NULL)
   	goto exit;
  +#else
  +assert(sig != NULL);
  +assert(dig != NULL);
  +assert(sigp != NULL);
  +assert(pubp != NULL);
  +assert(rpmtsDig(ts) == dig);
  +#endif
   
   #if 0
   fprintf(stderr, "==> find sig id %08x %08x ts pubkey id %08x %08x\n",
  @@ -119,7 +139,7 @@
   		ts->pkpkt = _free(ts->pkpkt);
   		ts->pkpktlen = 0;
   	    }
  -        }
  +	}
   /*@=moduncon@*/
       }
   #endif
  @@ -132,7 +152,7 @@
   	Header h;
   
   	/* Retrieve the pubkey that matches the signature. */
  -	mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
  +	mi = rpmdbInitIterator(rpmtsGetRdb(ts), RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
   	while ((h = rpmdbNextIterator(mi)) != NULL) {
   	    const char ** pubkeys;
   	    int_32 pt, pc;
  @@ -259,8 +279,8 @@
   {
   /*@-mods@*/ /* FIX: hide lazy malloc for now */
       if (ts->dig == NULL) {
  -        ts->dig = pgpNewDig(0);
  -        (void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts);
  +	ts->dig = pgpNewDig(0);
  +	(void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts);
       }
   /*@=mods@*/
       return ts->dig;
  @@ -287,9 +307,9 @@
       if (ts && ts->dig) {
   	int opx;
   	opx = RPMTS_OP_DIGEST;
  -        (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
  +	(void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
   	opx = RPMTS_OP_SIGNATURE;
  -        (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
  +	(void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
   	(void) rpmtsSetSig(ts, 0, 0, NULL, 0);	/* XXX headerFreeData */
   	ts->dig = pgpFreeDig(ts->dig);
       }
  @@ -965,18 +985,18 @@
   
   	b = (unsigned char *) ildl;
   	nb = sizeof(ildl);
  -        (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  +	dig->nbytes += nb;
   
   	b = (unsigned char *) pe;
   	nb = (htonl(ildl[0]) * sizeof(*pe));
  -        (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  +	dig->nbytes += nb;
   
   	b = (unsigned char *) dataStart;
   	nb = htonl(ildl[1]);
  -        (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
  +	dig->nbytes += nb;
   	(void) rpmswExit(op, dig->nbytes);
   
   	break;
  @@ -1010,18 +1030,18 @@
   
   	b = (unsigned char *) ildl;
   	nb = sizeof(ildl);
  -        (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  +	dig->nbytes += nb;
   
   	b = (unsigned char *) pe;
   	nb = (htonl(ildl[0]) * sizeof(*pe));
  -        (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  +	dig->nbytes += nb;
   
   	b = (unsigned char *) dataStart;
   	nb = htonl(ildl[1]);
  -        (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  -        dig->nbytes += nb;
  +	(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
  +	dig->nbytes += nb;
   	(void) rpmswExit(op, dig->nbytes);
   
   	break;
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/rpmdb.c
  ============================================================================
  $ cvs diff -u -r1.162 -r1.163 rpmdb.c
  --- rpm/rpmdb/rpmdb.c	30 Sep 2007 17:29:05 -0000	1.162
  +++ rpm/rpmdb/rpmdb.c	30 Sep 2007 22:38:30 -0000	1.163
  @@ -17,12 +17,22 @@
   #define	_RPMEVR_INTERNAL	/* XXX isInstallPrereq */
   #include <rpmevr.h>
   
  +#ifdef	NOTYET
  +/*@exposed@*/
  +extern pgpDig rpmtsDig(void * ts)
  +        /*@*/;
  +extern void rpmtsCleanDig(void * ts)
  +        /*@modifies ts @*/;
  +#endif
  +
   #define	_RPMDB_INTERNAL
   #define	_MIRE_INTERNAL
   #include "rpmdb.h"
  +#include "pkgio.h"
   #include "fprint.h"
   #include "legacy.h"
   #include "header_internal.h"	/* XXX for HEADERFLAG_ALLOCATED */
  +
   #include "debug.h"
   
   /*@access dbiIndexSet@*/
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/signature.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1 signature.c
  --- /dev/null	2007-10-01 00:33:00 +0200
  +++ signature.c	2007-10-01 00:38:31 +0200
  @@ -0,0 +1,1344 @@
  +/** \ingroup signature
  + * \file lib/signature.c
  + */
  +
  +#include "system.h"
  +#if defined(HAVE_KEYUTILS_H)
  +#include <keyutils.h>
  +#endif
  +
  +#include "rpmio_internal.h"
  +#include <rpmlib.h>
  +#include <rpmmacro.h>	/* XXX for rpmGetPath() */
  +#include "rpmdb.h"
  +
  +#include "misc.h"	/* XXX for dosetenv() */
  +#include "legacy.h"	/* XXX for mdbinfile() */
  +#include <pkgio.h>
  +#include "signature.h"
  +#include "debug.h"
  +
  +/*@access FD_t@*/		/* XXX ufdio->read arg1 is void ptr */
  +/*@access Header@*/		/* XXX compared with NULL */
  +/*@access DIGEST_CTX@*/		/* XXX compared with NULL */
  +/*@access pgpDig@*/
  +/*@access pgpDigParams@*/
  +
  +int rpmTempFile(const char * prefix, const char ** fnptr, void * fdptr)
  +{
  +    const char * tpmacro = "%{?_tmppath}%{!?_tmppath:/var/tmp/}";
  +    const char * tempfn = NULL;
  +    const char * tfn = NULL;
  +    static int _initialized = 0;
  +    int temput;
  +    FD_t fd = NULL;
  +    int ran;
  +
  +    if (!prefix) prefix = "";
  +
  +    /* Create the temp directory if it doesn't already exist. */
  +    if (!_initialized) {
  +	_initialized = 1;
  +	tempfn = rpmGenPath(prefix, tpmacro, NULL);
  +	if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
  +	    goto errxit;
  +    }
  +
  +    /* XXX should probably use mkstemp here */
  +    srand(time(NULL));
  +    ran = rand() % 100000;
  +
  +    /* maybe this should use link/stat? */
  +
  +    do {
  +	char tfnbuf[64];
  +#ifndef	NOTYET
  +	sprintf(tfnbuf, "rpm-tmp.%d", ran++);
  +	tempfn = _free(tempfn);
  +	tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
  +#else
  +	strcpy(tfnbuf, "rpm-tmp.XXXXXX");
  +	tempfn = _free(tempfn);
  +	tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
  +#endif
  +
  +	temput = urlPath(tempfn, &tfn);
  +	if (*tfn == '\0') goto errxit;
  +
  +	switch (temput) {
  +	case URL_IS_DASH:
  +	case URL_IS_HKP:
  +	    goto errxit;
  +	    /*@notreached@*/ /*@switchbreak@*/ break;
  +	case URL_IS_HTTPS:
  +	case URL_IS_HTTP:
  +	case URL_IS_FTP:
  +	default:
  +	    /*@switchbreak@*/ break;
  +	}
  +
  +	fd = Fopen(tempfn, "w+x.fdio");
  +	/* XXX FIXME: errno may not be correct for ufdio */
  +    } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
  +
  +    if (fd == NULL || Ferror(fd))
  +	goto errxit;
  +
  +    switch(temput) {
  +    case URL_IS_PATH:
  +    case URL_IS_UNKNOWN:
  +      {	struct stat sb, sb2;
  +	if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
  +	    rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  +	    goto errxit;
  +	}
  +
  +	if (sb.st_nlink != 1) {
  +	    rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  +	    goto errxit;
  +	}
  +
  +	if (fstat(Fileno(fd), &sb2) == 0) {
  +	    if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
  +		rpmError(RPMERR_SCRIPT, _("error creating temporary file %s\n"), tfn);
  +		goto errxit;
  +	    }
  +	}
  +      }	break;
  +    default:
  +	break;
  +    }
  +
  +    if (fnptr)
  +	*fnptr = tempfn;
  +    else 
  +	tempfn = _free(tempfn);
  +    if (fdptr)
  +	*(FD_t *)fdptr = fd;
  +
  +    return 0;
  +
  +errxit:
  +    tempfn = _free(tempfn);
  +    if (fnptr)
  +	*fnptr = NULL;
  +    /*@-usereleased@*/
  +    if (fd != NULL) (void) Fclose(fd);
  +    /*@=usereleased@*/
  +    return 1;
  +}
  +
  +
  +#if defined(SUPPORT_PGP_SIGNING)
  +int rpmLookupSignatureType(int action)
  +{
  +    /*@unchecked@*/
  +    static int disabled = 0;
  +    int rc = 0;
  +
  +    switch (action) {
  +    case RPMLOOKUPSIG_DISABLE:
  +	disabled = -2;
  +	break;
  +    case RPMLOOKUPSIG_ENABLE:
  +	disabled = 0;
  +	/*@fallthrough@*/
  +    case RPMLOOKUPSIG_QUERY:
  +	if (disabled)
  +	    break;	/* Disabled */
  +      { const char *name = rpmExpand("%{?_signature}", NULL);
  +	if (!(name && *name != '\0'))
  +	    rc = 0;
  +	else if (!xstrcasecmp(name, "none"))
  +	    rc = 0;
  +	else if (!xstrcasecmp(name, "pgp"))
  +	    rc = RPMSIGTAG_PGP;
  +	else if (!xstrcasecmp(name, "pgp5"))	/* XXX legacy */
  +	    rc = RPMSIGTAG_PGP;
  +	else if (!xstrcasecmp(name, "gpg"))
  +	    rc = RPMSIGTAG_GPG;
  +	else
  +	    rc = -1;	/* Invalid %_signature spec in macro file */
  +	name = _free(name);
  +      }	break;
  +    }
  +    return rc;
  +}
  +
  +/* rpmDetectPGPVersion() returns the absolute path to the "pgp"  */
  +/* executable of the requested version, or NULL when none found. */
  +
  +const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
  +{
  +    /* Actually this should support having more then one pgp version. */
  +    /* At the moment only one version is possible since we only       */
  +    /* have one %__pgp and one %_pgp_path.                          */
  +
  +    static pgpVersion saved_pgp_version = PGP_UNKNOWN;
  +    const char *pgpbin = rpmGetPath("%{?__pgp}", NULL);
  +
  +    if (saved_pgp_version == PGP_UNKNOWN) {
  +	char *pgpvbin;
  +	struct stat st;
  +
  +	if (!(pgpbin && pgpbin[0] != '\0')) {
  +	    pgpbin = _free(pgpbin);
  +	    saved_pgp_version = -1;
  +	    return NULL;
  +	}
  +	pgpvbin = (char *)alloca(strlen(pgpbin) + sizeof("v"));
  +	(void)stpcpy(stpcpy(pgpvbin, pgpbin), "v");
  +
  +	if (Stat(pgpvbin, &st) == 0)
  +	    saved_pgp_version = PGP_5;
  +	else if (Stat(pgpbin, &st) == 0)
  +	    saved_pgp_version = PGP_2;
  +	else
  +	    saved_pgp_version = PGP_NOTDETECTED;
  +    }
  +
  +    if (pgpVer && pgpbin)
  +	*pgpVer = saved_pgp_version;
  +    return pgpbin;
  +}
  +#endif	/* SUPPORT_PGP_SIGNING */
  +
  +#if defined(SUPPORT_PGP_SIGNING)
  +/**
  + * Generate PGP signature(s) for a header+payload file.
  + * @param file		header+payload file name
  + * @retval *sigTagp	signature tag
  + * @retval *pktp	signature packet(s)
  + * @retval *pktlenp	signature packet(s) length
  + * @param passPhrase	private key pass phrase
  + * @return		0 on success, 1 on failure
  + */
  +static int makePGPSignature(const char * file, /*@unused@*/ int_32 * sigTagp,
  +		/*@out@*/ byte ** pktp, /*@out@*/ int_32 * pktlenp,
  +		/*@null@*/ const char * passPhrase)
  +	/*@globals errno, rpmGlobalMacroContext, h_errno,
  +		fileSystem, internalState @*/
  +	/*@modifies errno, *pktp, *pktlenp, rpmGlobalMacroContext,
  +		fileSystem, internalState @*/
  +{
  +    char * sigfile = alloca(1024);
  +    int pid, status;
  +    int inpipe[2];
  +    struct stat st;
  +    const char * cmd;
  +    char *const *av;
  +#ifdef	NOTYET
  +    pgpDig dig = NULL;
  +    pgpDigParams sigp = NULL;
  +#endif
  +    int rc;
  +
  +    (void) stpcpy( stpcpy(sigfile, file), ".sig");
  +
  +    addMacro(NULL, "__plaintext_filename", NULL, file, -1);
  +    addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
  +
  +    inpipe[0] = inpipe[1] = 0;
  +    (void) pipe(inpipe);
  +
  +    if (!(pid = fork())) {
  +	const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
  +	const char *path;
  +	pgpVersion pgpVer;
  +
  +	(void) dup2(inpipe[0], 3);
  +	(void) close(inpipe[1]);
  +
  +	(void) dosetenv("PGPPASSFD", "3", 1);
  +	if (pgp_path && *pgp_path != '\0')
  +	    (void) dosetenv("PGPPATH", pgp_path, 1);
  +
  +	/* dosetenv("PGPPASS", passPhrase, 1); */
  +
  +	unsetenv("MALLOC_CHECK_");
  +	if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
  +	    switch(pgpVer) {
  +	    case PGP_2:
  +		cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
  +		rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +		if (!rc)
  +		    rc = execve(av[0], av+1, environ);
  +		break;
  +	    case PGP_5:
  +		cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
  +		rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +		if (!rc)
  +		    rc = execve(av[0], av+1, environ);
  +		break;
  +	    case PGP_UNKNOWN:
  +	    case PGP_NOTDETECTED:
  +		errno = ENOENT;
  +		break;
  +	    }
  +	}
  +	rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
  +			strerror(errno));
  +	_exit(RPMERR_EXEC);
  +    }
  +
  +    delMacro(NULL, "__plaintext_filename");
  +    delMacro(NULL, "__signature_filename");
  +
  +    (void) close(inpipe[0]);
  +    if (passPhrase)
  +	(void) write(inpipe[1], passPhrase, strlen(passPhrase));
  +    (void) write(inpipe[1], "\n", 1);
  +    (void) close(inpipe[1]);
  +
  +    (void)waitpid(pid, &status, 0);
  +    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
  +	rpmError(RPMERR_SIGGEN, _("pgp failed\n"));
  +	return 1;
  +    }
  +
  +    if (Stat(sigfile, &st)) {
  +	/* PGP failed to write signature */
  +	if (sigfile) (void) Unlink(sigfile);  /* Just in case */
  +	rpmError(RPMERR_SIGGEN, _("pgp failed to write signature\n"));
  +	return 1;
  +    }
  +
  +    *pktlenp = st.st_size;
  +    rpmMessage(RPMMESS_DEBUG, D_("PGP sig size: %d\n"), *pktlenp);
  +    *pktp = xmalloc(*pktlenp);
  +
  +    {	FD_t fd;
  +
  +	rc = 0;
  +	fd = Fopen(sigfile, "r.fdio");
  +	if (fd != NULL && !Ferror(fd)) {
  +	    rc = timedRead(fd, (void *)*pktp, *pktlenp);
  +	    if (sigfile) (void) Unlink(sigfile);
  +	    (void) Fclose(fd);
  +	}
  +	if (rc != *pktlenp) {
  +	    *pktp = _free(*pktp);
  +	    rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
  +	    return 1;
  +	}
  +    }
  +
  +    rpmMessage(RPMMESS_DEBUG, D_("Got %d bytes of PGP sig\n"), *pktlenp);
  +
  +#ifdef	NOTYET
  +    /* Parse the signature, change signature tag as appropriate. */
  +    dig = pgpNewDig(0);
  +
  +    (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
  +    sigp = pgpGetSignature(dig);
  +
  +    dig = pgpFreeDig(dig);
  +#endif
  +
  +    return 0;
  +}
  +#endif	/* SUPPORT_PGP_SIGNING */
  +
  +/**
  + * Generate GPG signature(s) for a header+payload file.
  + * @param file		header+payload file name
  + * @retval *sigTagp	signature tag
  + * @retval *pktp	signature packet(s)
  + * @retval *pktlenp	signature packet(s) length
  + * @param passPhrase	private key pass phrase
  + * @return		0 on success, 1 on failure
  + */
  +static int makeGPGSignature(const char * file, int_32 * sigTagp,
  +		/*@out@*/ byte ** pktp, /*@out@*/ int_32 * pktlenp,
  +		/*@null@*/ const char * passPhrase)
  +	/*@globals rpmGlobalMacroContext, h_errno,
  +		fileSystem, internalState @*/
  +	/*@modifies *pktp, *pktlenp, *sigTagp, rpmGlobalMacroContext,
  +		fileSystem, internalState @*/
  +{
  +    char * sigfile = alloca(strlen(file)+sizeof(".sig"));
  +    int pid, status;
  +    int inpipe[2];
  +    FILE * fpipe;
  +    struct stat st;
  +    const char * cmd;
  +    char *const *av;
  +    pgpDig dig = NULL;
  +    pgpDigParams sigp = NULL;
  +    const char * pw = NULL;
  +    int rc;
  +
  +    (void) stpcpy( stpcpy(sigfile, file), ".sig");
  +
  +    addMacro(NULL, "__plaintext_filename", NULL, file, -1);
  +    addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
  +
  +    inpipe[0] = inpipe[1] = 0;
  +    (void) pipe(inpipe);
  +
  +    if (!(pid = fork())) {
  +	const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
  +
  +	(void) dup2(inpipe[0], 3);
  +	(void) close(inpipe[1]);
  +
  +	if (gpg_path && *gpg_path != '\0')
  +	    (void) dosetenv("GNUPGHOME", gpg_path, 1);
  +
  +	unsetenv("MALLOC_CHECK_");
  +	cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
  +	rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +	if (!rc)
  +	    rc = execve(av[0], av+1, environ);
  +
  +	rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
  +			strerror(errno));
  +	_exit(RPMERR_EXEC);
  +    }
  +
  +    delMacro(NULL, "__plaintext_filename");
  +    delMacro(NULL, "__signature_filename");
  +
  +#if defined(HAVE_KEYUTILS_H)
  +    if (!strcmp(passPhrase, "@u user rpm:passwd")) {
  +	key_serial_t keyring = KEY_SPEC_PROCESS_KEYRING;
  +	long key;
  +	int xx;
  +
  +/*@-moduncon@*/
  +	key = keyctl_search(keyring, "user", "rpm:passwd", 0);
  +	if ((xx = keyctl_read_alloc(key, (void **)&pw)) < 0) {
  +	    rpmError(RPMERR_SIGGEN, _("Failed %s(%d) key(0x%lx): %s\n"),
  +			"keyctl_read_alloc of key", xx, key, strerror(errno));
  +	    return 1;
  +	}
  +/*@=moduncon@*/
  +    } else
  +#endif
  +	pw = passPhrase;
  +
  +    fpipe = fdopen(inpipe[1], "w");
  +    (void) close(inpipe[0]);
  +    if (fpipe) {
  +	fprintf(fpipe, "%s\n", (pw ? pw : ""));
  +	(void) fclose(fpipe);
  +    }
  +/*@-mods@*/
  +    if (pw && pw != passPhrase) {
  +	(void) memset((void *)pw, 0, strlen(pw));
  +/*@-temptrans@*/	/* XXX mixed use in variable */
  +	pw = _free(pw);
  +/*@=temptrans@*/
  +    }
  +/*@=mods@*/
  +
  +    (void) waitpid(pid, &status, 0);
  +    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
  +	rpmError(RPMERR_SIGGEN, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
  +	return 1;
  +    }
  +
  +    if (Stat(sigfile, &st)) {
  +	/* GPG failed to write signature */
  +	if (sigfile) (void) Unlink(sigfile);  /* Just in case */
  +	rpmError(RPMERR_SIGGEN, _("gpg failed to write signature\n"));
  +	return 1;
  +    }
  +
  +    *pktlenp = st.st_size;
  +    rpmMessage(RPMMESS_DEBUG, D_("GPG sig size: %d\n"), *pktlenp);
  +    *pktp = xmalloc(*pktlenp);
  +
  +    {	FD_t fd;
  +
  +	rc = 0;
  +	fd = Fopen(sigfile, "r.fdio");
  +	if (fd != NULL && !Ferror(fd)) {
  +	    rc = timedRead(fd, (void *)*pktp, *pktlenp);
  +	    if (sigfile) (void) Unlink(sigfile);
  +	    (void) Fclose(fd);
  +	}
  +	if (rc != *pktlenp) {
  +	    *pktp = _free(*pktp);
  +	    rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
  +	    return 1;
  +	}
  +    }
  +
  +    rpmMessage(RPMMESS_DEBUG, D_("Got %d bytes of GPG sig\n"), *pktlenp);
  +
  +    /* Parse the signature, change signature tag as appropriate. */
  +    dig = pgpNewDig(0);
  +
  +    (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
  +    sigp = pgpGetSignature(dig);
  +
  +    /* Identify the type of signature being returned. */
  +    switch (*sigTagp) {
  +    case RPMSIGTAG_SIZE:
  +    case RPMSIGTAG_MD5:
  +    case RPMSIGTAG_SHA1:
  +	break;
  +#if defined(SUPPORT_RPMV3_SIGN_DSA) || defined(SUPPORT_RPMV3_SIGN_RSA)
  +    case RPMSIGTAG_GPG:
  +	/* XXX check hash algorithm too? */
  +	if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
  +	    *sigTagp = RPMSIGTAG_PGP;
  +	break;
  +#endif
  +#if defined(SUPPORT_RPMV3_SIGN_DSA) || defined(SUPPORT_RPMV3_SIGN_RSA)
  +    case RPMSIGTAG_PGP5:	/* XXX legacy */
  +    case RPMSIGTAG_PGP:
  +	if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
  +	    *sigTagp = RPMSIGTAG_GPG;
  +	break;
  +#endif
  +    case RPMSIGTAG_DSA:
  +	/* XXX check hash algorithm too? */
  +	if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
  +	    *sigTagp = RPMSIGTAG_RSA;
  +	break;
  +    case RPMSIGTAG_RSA:
  +	if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
  +	    *sigTagp = RPMSIGTAG_DSA;
  +	break;
  +    }
  +
  +    dig = pgpFreeDig(dig);
  +
  +    return 0;
  +}
  +
  +/**
  + * Generate header only signature(s) from a header+payload file.
  + * @param sigh		signature header
  + * @param file		header+payload file name
  + * @param sigTag	type of signature(s) to add
  + * @param passPhrase	private key pass phrase
  + * @return		0 on success, -1 on failure
  + */
  +static int makeHDRSignature(Header sigh, const char * file, int_32 sigTag,
  +		/*@null@*/ const char * passPhrase)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies sigh, sigTag, rpmGlobalMacroContext, fileSystem, internalState @*/
  +{
  +    Header h = NULL;
  +    FD_t fd = NULL;
  +    byte * pkt;
  +    int_32 pktlen;
  +    const char * fn = NULL;
  +    const char * SHA1 = NULL;
  +    int ret = -1;	/* assume failure. */
  +
  +    switch (sigTag) {
  +    case RPMSIGTAG_SIZE:
  +    case RPMSIGTAG_MD5:
  +    case RPMSIGTAG_PGP5:	/* XXX legacy */
  +    case RPMSIGTAG_PGP:
  +    case RPMSIGTAG_GPG:
  +	goto exit;
  +	/*@notreached@*/ break;
  +    case RPMSIGTAG_SHA1:
  +	fd = Fopen(file, "r.fdio");
  +	if (fd == NULL || Ferror(fd))
  +	    goto exit;
  +	h = headerRead(fd);
  +	if (h == NULL)
  +	    goto exit;
  +	(void) Fclose(fd);	fd = NULL;
  +
  +	if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
  +	    unsigned char * hmagic = NULL;
  +	    size_t nmagic = 0;
  +	    DIGEST_CTX ctx;
  +	    void * uh;
  +	    int_32 uht, uhc;
  +	
  +	    if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)
  +	     ||  uh == NULL)
  +	    {
  +		h = headerFree(h);
  +		goto exit;
  +	    }
  +	    (void) headerGetMagic(NULL, &hmagic, &nmagic);
  +	    ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
  +	    if (hmagic && nmagic > 0)
  +		(void) rpmDigestUpdate(ctx, hmagic, nmagic);
  +	    (void) rpmDigestUpdate(ctx, uh, uhc);
  +	    (void) rpmDigestFinal(ctx, &SHA1, NULL, 1);
  +	    uh = headerFreeData(uh, uht);
  +	}
  +	h = headerFree(h);
  +
  +	if (SHA1 == NULL)
  +	    goto exit;
  +	if (!headerAddEntry(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
  +	    goto exit;
  +	ret = 0;
  +	break;
  +    case RPMSIGTAG_DSA:
  +	fd = Fopen(file, "r.fdio");
  +	if (fd == NULL || Ferror(fd))
  +	    goto exit;
  +	h = headerRead(fd);
  +	if (h == NULL)
  +	    goto exit;
  +	(void) Fclose(fd);	fd = NULL;
  +	if (rpmTempFile(NULL, &fn, &fd))
  +	    goto exit;
  +	if (headerWrite(fd, h))
  +	    goto exit;
  +	(void) Fclose(fd);	fd = NULL;
  +	if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
  +	 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
  +	    goto exit;
  +	ret = 0;
  +	break;
  +#if defined(SUPPORT_PGP_SIGNING)
  +    case RPMSIGTAG_RSA:
  +	fd = Fopen(file, "r.fdio");
  +	if (fd == NULL || Ferror(fd))
  +	    goto exit;
  +	h = headerRead(fd);
  +	if (h == NULL)
  +	    goto exit;
  +	(void) Fclose(fd);	fd = NULL;
  +	if (rpmTempFile(NULL, &fn, &fd))
  +	    goto exit;
  +	if (headerWrite(fd, h))
  +	    goto exit;
  +	(void) Fclose(fd);	fd = NULL;
  +	if (makePGPSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
  +	 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
  +	    goto exit;
  +	ret = 0;
  +	break;
  +#endif	/* SUPPORT_PGP_SIGNING */
  +    }
  +
  +exit:
  +    if (fn) {
  +	(void) Unlink(fn);
  +	fn = _free(fn);
  +    }
  +    SHA1 = _free(SHA1);
  +    h = headerFree(h);
  +    if (fd != NULL) (void) Fclose(fd);
  +    return ret;
  +}
  +
  +int rpmAddSignature(Header sigh, const char * file, int_32 sigTag,
  +		const char * passPhrase)
  +{
  +    struct stat st;
  +    byte * pkt;
  +    int_32 pktlen;
  +    int ret = -1;	/* assume failure. */
  +
  +    switch (sigTag) {
  +    case RPMSIGTAG_SIZE:
  +	if (Stat(file, &st) != 0)
  +	    break;
  +	pktlen = st.st_size;
  +	if (!headerAddEntry(sigh, sigTag, RPM_INT32_TYPE, &pktlen, 1))
  +	    break;
  +	ret = 0;
  +	break;
  +    case RPMSIGTAG_MD5:
  +	pktlen = 16;
  +	pkt = memset(alloca(pktlen), 0, pktlen);
  +	if (dodigest(PGPHASHALGO_MD5, file, pkt, 0, NULL)
  +	 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
  +	    break;
  +	ret = 0;
  +	break;
  +#if defined(SUPPORT_PGP_SIGNING)
  +    case RPMSIGTAG_PGP5:	/* XXX legacy */
  +    case RPMSIGTAG_PGP:
  +#if defined(SUPPORT_RPMV3_SIGN_RSA)
  +	if (makePGPSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
  +	 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
  +	    break;
  +	/* XXX Piggyback a header-only RSA signature as well. */
  +#endif
  +#ifdef	NOTYET	/* XXX needs hdrmd5ctx, like hdrsha1ctx. */
  +	ret = makeHDRSignature(sigh, file, RPMSIGTAG_RSA, passPhrase);
  +#endif
  +	ret = 0;
  +	break;
  +#endif	/* SUPPORT_PGP_SIGNING */
  +    case RPMSIGTAG_GPG:
  +#if defined(SUPPORT_RPMV3_SIGN_DSA)
  +	if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
  +	 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
  +	    break;
  +	/* XXX Piggyback a header-only DSA signature as well. */
  +#endif
  +	ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
  +	break;
  +    case RPMSIGTAG_RSA:
  +    case RPMSIGTAG_DSA:
  +    case RPMSIGTAG_SHA1:
  +	ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
  +	break;
  +    }
  +
  +    return ret;
  +}
  +
  +int rpmCheckPassPhrase(const char * passPhrase)
  +{
  +    const char *pw;
  +    int p[2];
  +    int pid, status;
  +    int rc;
  +    int xx;
  +
  +    p[0] = p[1] = 0;
  +    xx = pipe(p);
  +
  +    if (!(pid = fork())) {
  +	const char * cmd;
  +	char *const *av;
  +	int fdno;
  +
  +	xx = close(STDIN_FILENO);
  +	xx = close(STDOUT_FILENO);
  +	xx = close(p[1]);
  +	if (!rpmIsVerbose())
  +	    xx = close(STDERR_FILENO);
  +	if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
  +	    xx = dup2(fdno, STDIN_FILENO);
  +	    xx = close(fdno);
  +	}
  +	if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
  +	    xx = dup2(fdno, STDOUT_FILENO);
  +	    xx = close(fdno);
  +	}
  +	xx = dup2(p[0], 3);
  +
  +	unsetenv("MALLOC_CHECK_");
  +#if defined(SUPPORT_PGP_SIGNING)
  +        if (use_pgp) {
  +	    const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
  +	    const char *path;
  +	    pgpVersion pgpVer;
  +
  +	    (void) dosetenv("PGPPASSFD", "3", 1);
  +	    if (pgp_path && *pgp_path != '\0')
  +		xx = dosetenv("PGPPATH", pgp_path, 1);
  +
  +	    if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
  +		switch(pgpVer) {
  +		case PGP_2:
  +		    cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
  +		    rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +		    if (!rc)
  +			rc = execve(av[0], av+1, environ);
  +		    /*@innerbreak@*/ break;
  +		case PGP_5:	/* XXX legacy */
  +		    cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
  +		    rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +		    if (!rc)
  +			rc = execve(av[0], av+1, environ);
  +		    /*@innerbreak@*/ break;
  +		case PGP_UNKNOWN:
  +		case PGP_NOTDETECTED:
  +		    /*@innerbreak@*/ break;
  +		}
  +	    }
  +	    rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
  +			strerror(errno));
  +	    _exit(RPMERR_EXEC);
  +        } else
  +#endif	/* SUPPORT_PGP_SIGNING */
  +	{   const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
  +
  +	    if (gpg_path && *gpg_path != '\0')
  +  		(void) dosetenv("GNUPGHOME", gpg_path, 1);
  +
  +	    cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
  +	    rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
  +	    if (!rc)
  +		rc = execve(av[0], av+1, environ);
  +
  +	    rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
  +			strerror(errno));
  +	}
  +    }
  +
  +#if defined(HAVE_KEYUTILS_H)
  +    if (!strcmp(passPhrase, "@u user rpm:passwd")) {
  +	long key;
  +	key_serial_t keyring = KEY_SPEC_PROCESS_KEYRING;
  +
  +/*@-moduncon@*/
  +	key = keyctl_search(keyring, "user", "rpm:passwd", 0);
  +	if ((xx = keyctl_read_alloc(key, (void **)&pw)) < 0) {
  +	    rpmError(RPMERR_SIGGEN, _("Failed %s(%d) key(0x%lx): %s\n"),
  +			"keyctl_read_alloc of key", xx, key, strerror(errno));
  +	    return 1;
  +	}
  +/*@=moduncon@*/
  +    } else
  +#endif
  +	pw = passPhrase;
  +
  +    xx = close(p[0]);
  +    xx = write(p[1], pw, strlen(pw));
  +    xx = write(p[1], "\n", 1);
  +    xx = close(p[1]);
  +
  +/*@-mods@*/
  +    if (pw && pw != passPhrase) {
  +	(void) memset((void *)pw, 0, strlen(pw));
  +/*@-temptrans@*/	/* XXX mixed use in variable */
  +	pw = _free(pw);
  +/*@=temptrans@*/
  +    }
  +/*@=mods@*/
  +
  +    (void) waitpid(pid, &status, 0);
  +
  +    return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
  +}
  +
  +static /*@observer@*/ const char * rpmSigString(rpmRC res)
  +	/*@*/
  +{
  +    const char * str;
  +    switch (res) {
  +    case RPMRC_OK:		str = "OK";		break;
  +    case RPMRC_FAIL:		str = "BAD";		break;
  +    case RPMRC_NOKEY:		str = "NOKEY";		break;
  +    case RPMRC_NOTTRUSTED:	str = "NOTRUSTED";	break;
  +    default:
  +    case RPMRC_NOTFOUND:	str = "UNKNOWN";	break;
  +    }
  +    return str;
  +}
  +
  +static rpmRC
  +verifySizeSignature(const pgpDig dig, /*@out@*/ char * t)
  +	/*@modifies *t @*/
  +{
  +    const void * sig = pgpGetSig(dig);
  +    rpmRC res;
  +    int_32 size = 0x7fffffff;
  +
  +    *t = '\0';
  +    t = stpcpy(t, _("Header+Payload size: "));
  +
  +    if (sig == NULL || dig == NULL || dig->nbytes == 0) {
  +	res = RPMRC_NOKEY;
  +	t = stpcpy(t, rpmSigString(res));
  +	goto exit;
  +    }
  +
  +    memcpy(&size, sig, sizeof(size));
  +
  +    if (size != dig->nbytes) {
  +	res = RPMRC_FAIL;
  +	t = stpcpy(t, rpmSigString(res));
  +	sprintf(t, " Expected(%d) != (%d)\n", (int)size, (int)dig->nbytes);
  +    } else {
  +	res = RPMRC_OK;
  +	t = stpcpy(t, rpmSigString(res));
  +	sprintf(t, " (%d)", (int)dig->nbytes);
  +    }
  +
  +exit:
  +    t = stpcpy(t, "\n");
  +    return res;
  +}
  +
  +static rpmRC
  +verifyMD5Signature(const pgpDig dig, /*@out@*/ char * t,
  +		/*@null@*/ DIGEST_CTX md5ctx)
  +	/*@globals internalState @*/
  +	/*@modifies *t, internalState @*/
  +{
  +    const void * sig = pgpGetSig(dig);
  +    int_32 siglen = pgpGetSiglen(dig);
  +    rpmRC res;
  +    byte * md5sum = NULL;
  +    size_t md5len = 0;
  +
  +    *t = '\0';
  +    t = stpcpy(t, _("MD5 digest: "));
  +
  +    if (md5ctx == NULL || sig == NULL || dig == NULL) {
  +	res = RPMRC_NOKEY;
  +	t = stpcpy(t, rpmSigString(res));
  +	goto exit;
  +    }
  +
  +    {	rpmop op = pgpStatsAccumulator(dig, 10);	/* RPMTS_OP_DIGEST */
  +	(void) rpmswEnter(op, 0);
  +	(void) rpmDigestFinal(rpmDigestDup(md5ctx), &md5sum, &md5len, 0);
  +	(void) rpmswExit(op, 0);
  +	op->count--;	/* XXX one too many */
  +    }
  +
  +    if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
  +	res = RPMRC_FAIL;
  +	t = stpcpy(t, rpmSigString(res));
  +	t = stpcpy(t, " Expected(");
  +	(void) pgpHexCvt(t, sig, siglen);
  +	t += strlen(t);
  +	t = stpcpy(t, ") != (");
  +    } else {
  +	res = RPMRC_OK;
  +	t = stpcpy(t, rpmSigString(res));
  +	t = stpcpy(t, " (");
  +    }
  +    (void) pgpHexCvt(t, md5sum, md5len);
  +    t += strlen(t);
  +    t = stpcpy(t, ")");
  +
  +exit:
  +    md5sum = _free(md5sum);
  +    t = stpcpy(t, "\n");
  +    return res;
  +}
  +
  +/**
  + * Verify header immutable region SHA1 digest.
  + * @param dig		container
  + * @retval t		verbose success/failure text
  + * @param sha1ctx
  + * @return 		RPMRC_OK on success
  + */
  +static rpmRC
  +verifySHA1Signature(const pgpDig dig, /*@out@*/ char * t,
  +		/*@null@*/ DIGEST_CTX sha1ctx)
  +	/*@globals internalState @*/
  +	/*@modifies *t, internalState @*/
  +{
  +    const void * sig = pgpGetSig(dig);
  +#ifdef	NOTYET
  +    int_32 siglen = pgpGetSiglen(dig);
  +#endif
  +    rpmRC res;
  +    const char * SHA1 = NULL;
  +
  +    *t = '\0';
  +    t = stpcpy(t, _("Header SHA1 digest: "));
  +
  +    if (sha1ctx == NULL || sig == NULL || dig == NULL) {
  +	res = RPMRC_NOKEY;
  +	t = stpcpy(t, rpmSigString(res));
  +	goto exit;
  +    }
  +
  +    {	rpmop op = pgpStatsAccumulator(dig, 10);	/* RPMTS_OP_DIGEST */
  +	(void) rpmswEnter(op, 0);
  +	(void) rpmDigestFinal(rpmDigestDup(sha1ctx), &SHA1, NULL, 1);
  +	(void) rpmswExit(op, 0);
  +    }
  +
  +    if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
  +	res = RPMRC_FAIL;
  +	t = stpcpy(t, rpmSigString(res));
  +	t = stpcpy(t, " Expected(");
  +	t = stpcpy(t, sig);
  +	t = stpcpy(t, ") != (");
  +    } else {
  +	res = RPMRC_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;
  +}
  +
  +/**
  + * 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;
  +}
  +
  +/**
  + * Verify RSA signature.
  + * @param dig		container
  + * @retval t		verbose success/failure text
  + * @param md5ctx
  + * @return 		RPMRC_OK on success
  + */
  +static rpmRC
  +verifyRSASignature(pgpDig dig, /*@out@*/ char * t,
  +		/*@null@*/ DIGEST_CTX md5ctx)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies dig, *t, rpmGlobalMacroContext, fileSystem, internalState */
  +{
  +    const void * sig = pgpGetSig(dig);
  +#ifdef	NOTYET
  +    int_32 siglen = pgpGetSiglen(dig);
  +#endif
  +    int_32 sigtag = pgpGetSigtag(dig);
  +    pgpDigParams sigp = pgpGetSignature(dig);
  +    const char * prefix = NULL;
  +    rpmRC res = RPMRC_OK;
  +    int xx;
  +
  +assert(dig != NULL);
  +assert(sigp != NULL);
  +    *t = '\0';
  +    if (dig != NULL && dig->hdrmd5ctx == md5ctx)
  +	t = stpcpy(t, _("Header "));
  +    *t++ = 'V';
  +    switch (sigp->version) {
  +    case 3:	*t++ = '3';	break;
  +    case 4:	*t++ = '4';	break;
  +    }
  +
  +    if (md5ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
  +	res = RPMRC_NOKEY;
  +    }
  +
  +    /* Verify the desired signature match. */
  +    switch (sigp->pubkey_algo) {
  +    case PGPPUBKEYALGO_RSA:
  +	if (sigtag == RPMSIGTAG_RSA
  +#if defined(SUPPORT_RPMV3_VERIFY_RSA)
  +	 || sigtag == RPMSIGTAG_PGP
  +	 || sigtag == RPMSIGTAG_PGP5
  +#endif
  +	)
  +	    break;
  +	/*@fallthrough@*/
  +    default:
  +	res = RPMRC_NOKEY;
  +	break;
  +    }
  +
  +    /* Verify the desired hash match. */
  +    /* XXX Values from PKCS#1 v2.1 (aka RFC-3447) */
  +    switch (sigp->hash_algo) {
  +    case PGPHASHALGO_MD5:
  +	t = stpcpy(t, " RSA/MD5");
  +	prefix = "3020300c06082a864886f70d020505000410";
  +	break;
  +    case PGPHASHALGO_SHA1:
  +	t = stpcpy(t, " RSA/SHA1");
  +	prefix = "3021300906052b0e03021a05000414";
  +	break;
  +    case PGPHASHALGO_RIPEMD160:
  +	t = stpcpy(t, " RSA/RIPEMD160");
  +	prefix = "3021300906052b2403020105000414";
  +	break;
  +    case PGPHASHALGO_MD2:
  +	t = stpcpy(t, " RSA/MD2");
  +	prefix = "3020300c06082a864886f70d020205000410";
  +	break;
  +    case PGPHASHALGO_TIGER192:
  +	t = stpcpy(t, " RSA/TIGER192");
  +	prefix = "3029300d06092b06010401da470c0205000418";
  +	break;
  +    case PGPHASHALGO_HAVAL_5_160:
  +	res = RPMRC_NOKEY;
  +	prefix = NULL;
  +	break;
  +    case PGPHASHALGO_SHA256:
  +	t = stpcpy(t, " RSA/SHA256");
  +	prefix = "3031300d060960864801650304020105000420";
  +	break;
  +    case PGPHASHALGO_SHA384:
  +	t = stpcpy(t, " RSA/SHA384");
  +	prefix = "3041300d060960864801650304020205000430";
  +	break;
  +    case PGPHASHALGO_SHA512:
  +	t = stpcpy(t, " RSA/SHA512");
  +	prefix = "3051300d060960864801650304020305000440";
  +	break;
  +    default:
  +	res = RPMRC_NOKEY;
  +	prefix = NULL;
  +	break;
  +    }
  +
  +    t = stpcpy(t, _(" signature: "));
  +    if (res != RPMRC_OK) {
  +	goto exit;
  +    }
  +
  +assert(md5ctx != NULL);	/* XXX can't happen. */
  +    {	rpmop op = pgpStatsAccumulator(dig, 10);	/* RPMTS_OP_DIGEST */
  +	DIGEST_CTX ctx;
  +	byte signhash16[2];
  +	const char * s;
  +
  +	(void) rpmswEnter(op, 0);
  +	ctx = rpmDigestDup(md5ctx);
  +	if (sigp->hash != NULL)
  +	    xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
  +
  +#ifdef	NOTYET	/* XXX not for binary/text signatures as in packages. */
  +	if (!(sigp->sigtype == PGPSIGTYPE_BINARY || sigp->sigtype == PGP_SIGTYPE_TEXT)) {
  +	    int nb = dig->nbytes + sigp->hashlen;
  +	    byte trailer[6];
  +	    nb = htonl(nb);
  +	    trailer[0] = 0x4;
  +	    trailer[1] = 0xff;
  +	    memcpy(trailer+2, &nb, sizeof(nb));
  +	    xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
  +	}
  +#endif
  +
  +	xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 1);
  +	(void) rpmswExit(op, sigp->hashlen);
  +	op->count--;	/* XXX one too many */
  +
  +	/* Compare leading 16 bits of digest for quick check. */
  +	s = dig->md5;
  +	signhash16[0] = (nibble(s[0]) << 4) | nibble(s[1]);
  +	signhash16[1] = (nibble(s[2]) << 4) | nibble(s[3]);
  +	if (memcmp(signhash16, sigp->signhash16, sizeof(signhash16))) {
  +	    res = RPMRC_FAIL;
  +	    goto exit;
  +	}
  +    }
  +
  +    /* Generate RSA modulus parameter. */
  +    {	unsigned int nbits = MP_WORDS_TO_BITS(dig->c.size);
  +	unsigned int nb = (nbits + 7) >> 3;
  +	const char * hexstr;
  +	char * tt;
  +
  +assert(prefix != NULL);
  +	hexstr = tt = xmalloc(2 * nb + 1);
  +	memset(tt, 'f', (2 * nb));
  +	tt[0] = '0'; tt[1] = '0';
  +	tt[2] = '0'; tt[3] = '1';
  +	tt += (2 * nb) - strlen(prefix) - strlen(dig->md5) - 2;
  +	*tt++ = '0'; *tt++ = '0';
  +	tt = stpcpy(tt, prefix);
  +	tt = stpcpy(tt, dig->md5);
  +
  +/*@-moduncon -noeffectuncon @*/
  +	mpnzero(&dig->rsahm);	(void) mpnsethex(&dig->rsahm, hexstr);
  +/*@=moduncon =noeffectuncon @*/
  +
  +	hexstr = _free(hexstr);
  +
  +    }
  +
  +    /* Retrieve the matching public key. */
  +    res = pgpFindPubkey(dig);
  +    if (res != RPMRC_OK)
  +	goto exit;
  +
  +    {	rpmop op = pgpStatsAccumulator(dig, 11);	/* RPMTS_OP_SIGNATURE */
  +	(void) rpmswEnter(op, 0);
  +/*@-moduncon@*/
  +#if defined(HAVE_BEECRYPT_API_H)
  +	xx = rsavrfy(&dig->rsa_pk.n, &dig->rsa_pk.e, &dig->c, &dig->rsahm);
  +#else
  +	xx = rsavrfy(&dig->rsa_pk, &dig->rsahm, &dig->c);
  +#endif
  +/*@=moduncon@*/
  +	(void) rpmswExit(op, 0);
  +	res = (xx ? RPMRC_OK : RPMRC_FAIL);
  +    }
  +
  +exit:
  +    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;
  +}
  +
  +/**
  + * Verify DSA signature.
  + * @param dig		container
  + * @retval t		verbose success/failure text
  + * @param sha1ctx
  + * @return 		RPMRC_OK on success
  + */
  +static rpmRC
  +verifyDSASignature(pgpDig dig, /*@out@*/ char * t,
  +		/*@null@*/ DIGEST_CTX sha1ctx)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies dig, *t, rpmGlobalMacroContext, fileSystem, internalState */
  +{
  +    const void * sig = pgpGetSig(dig);
  +#ifdef	NOTYET
  +    int_32 siglen = pgpGetSiglen(dig);
  +#endif
  +    int_32 sigtag = pgpGetSigtag(dig);
  +    pgpDigParams sigp = pgpGetSignature(dig);
  +    rpmRC res;
  +    int xx;
  +
  +assert(dig != NULL);
  +assert(sigp != NULL);
  +    *t = '\0';
  +    if (dig != NULL && dig->hdrsha1ctx == sha1ctx)
  +	t = stpcpy(t, _("Header "));
  +    *t++ = 'V';
  +    switch (sigp->version) {
  +    case 3:    *t++ = '3';     break;
  +    case 4:    *t++ = '4';     break;
  +    }
  +    t = stpcpy(t, _(" DSA signature: "));
  +
  +    if (sha1ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
  +	res = RPMRC_NOKEY;
  +	goto exit;
  +    }
  +
  +    /* XXX sanity check on sigtag and signature agreement. */
  +    if (!(
  +#if defined(SUPPORT_RPMV3_VERIFY_DSA)
  +	(sigtag == RPMSIGTAG_GPG || sigtag == RPMSIGTAG_DSA)
  +#else
  +	(sigtag == RPMSIGTAG_DSA)
  +#endif
  +    	&& sigp->pubkey_algo == PGPPUBKEYALGO_DSA
  +    	&& sigp->hash_algo == PGPHASHALGO_SHA1))
  +    {
  +	res = RPMRC_NOKEY;
  +	goto exit;
  +    }
  +
  +    {	rpmop op = pgpStatsAccumulator(dig, 10);	/* RPMTS_OP_DIGEST */
  +	DIGEST_CTX ctx;
  +	byte signhash16[2];
  +
  +	(void) rpmswEnter(op, 0);
  +	ctx = rpmDigestDup(sha1ctx);
  +	if (sigp->hash != NULL)
  +	    xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
  +
  +	if (sigp->version == 4) {
  +	    int nb = sigp->hashlen;
  +	    byte trailer[6];
  +	    nb = htonl(nb);
  +	    trailer[0] = sigp->version;
  +	    trailer[1] = 0xff;
  +	    memcpy(trailer+2, &nb, sizeof(nb));
  +	    xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
  +	}
  +	xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 1);
  +	(void) rpmswExit(op, sigp->hashlen);
  +	op->count--;	/* XXX one too many */
  +
  +/*@-moduncon -noeffectuncon @*/
  +	mpnzero(&dig->hm);	(void) mpnsethex(&dig->hm, dig->sha1);
  +/*@=moduncon =noeffectuncon @*/
  +
  +	/* Compare leading 16 bits of digest for quick check. */
  +	signhash16[0] = (*dig->hm.data >> 24) & 0xff;
  +	signhash16[1] = (*dig->hm.data >> 16) & 0xff;
  +	if (memcmp(signhash16, sigp->signhash16, sizeof(signhash16))) {
  +	    res = RPMRC_FAIL;
  +	    goto exit;
  +	}
  +    }
  +
  +    /* Retrieve the matching public key. */
  +    res = pgpFindPubkey(dig);
  +    if (res != RPMRC_OK)
  +	goto exit;
  +
  +    {	rpmop op = pgpStatsAccumulator(dig, 11);	/* RPMTS_OP_SIGNATURE */
  +	(void) rpmswEnter(op, 0);
  +/*@-moduncon@*/
  +	if (dsavrfy(&dig->p, &dig->q, &dig->g,
  +		&dig->hm, &dig->y, &dig->r, &dig->s))
  +	    res = RPMRC_OK;
  +	else
  +	    res = RPMRC_FAIL;
  +/*@=moduncon@*/
  +	(void) rpmswExit(op, 0);
  +    }
  +
  +exit:
  +    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;
  +}
  +
  +rpmRC
  +rpmVerifySignature(void * _dig, char * result)
  +{
  +    pgpDig dig = _dig;
  +    const void * sig = pgpGetSig(dig);
  +    int_32 siglen = pgpGetSiglen(dig);
  +    int_32 sigtag = pgpGetSigtag(dig);
  +    rpmRC res;
  +
  +    if (dig == NULL || sig == NULL || siglen <= 0) {
  +	sprintf(result, _("Verify signature: BAD PARAMETERS\n"));
  +	return RPMRC_NOTFOUND;
  +    }
  +
  +    switch (sigtag) {
  +    case RPMSIGTAG_SIZE:
  +	res = verifySizeSignature(dig, result);
  +	break;
  +    case RPMSIGTAG_MD5:
  +	res = verifyMD5Signature(dig, result, dig->md5ctx);
  +	break;
  +    case RPMSIGTAG_SHA1:
  +	res = verifySHA1Signature(dig, result, dig->hdrsha1ctx);
  +	break;
  +    case RPMSIGTAG_RSA:
  +	res = verifyRSASignature(dig, result, dig->hdrmd5ctx);
  +	break;
  +#if defined(SUPPORT_RPMV3_VERIFY_RSA)
  +    case RPMSIGTAG_PGP5:	/* XXX legacy */
  +    case RPMSIGTAG_PGP:
  +	res = verifyRSASignature(dig, result,
  +		((dig->signature.hash_algo == PGPHASHALGO_MD5)
  +			? dig->md5ctx : dig->sha1ctx));
  +	break;
  +#endif
  +    case RPMSIGTAG_DSA:
  +	res = verifyDSASignature(dig, result, dig->hdrsha1ctx);
  +	break;
  +#if defined(SUPPORT_RPMV3_VERIFY_DSA)
  +    case RPMSIGTAG_GPG:
  +	res = verifyDSASignature(dig, result, dig->sha1ctx);
  +	break;
  +#endif
  +#if defined(SUPPORT_RPMV3_BROKEN)
  +    case RPMSIGTAG_LEMD5_1:
  +    case RPMSIGTAG_LEMD5_2:
  +	sprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
  +	res = RPMRC_NOTFOUND;
  +	break;
  +#endif
  +    default:
  +	sprintf(result, _("Signature: UNKNOWN (%d)\n"), sigtag);
  +	res = RPMRC_NOTFOUND;
  +	break;
  +    }
  +    return res;
  +}
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/signature.h
  ============================================================================
  $ cvs diff -u -r0 -r1.1 signature.h
  --- /dev/null	2007-10-01 00:33:00 +0200
  +++ signature.h	2007-10-01 00:38:31 +0200
  @@ -0,0 +1,85 @@
  +#ifndef H_SIGNATURE
  +#define	H_SIGNATURE
  +
  +/** \ingroup signature
  + * \file lib/signature.h
  + * Generate and verify rpm package signatures.
  + */
  +
  +#include <header.h>
  +
  +/** \ingroup signature
  + * Identify PGP versions.
  + * @note Greater than 0 is a valid PGP version.
  + */
  +typedef enum pgpVersion_e {
  +    PGP_NOTDETECTED	= -1,
  +    PGP_UNKNOWN		= 0,
  +    PGP_2		= 2,
  +    PGP_5		= 5
  +} pgpVersion;
  +
  +#ifdef __cplusplus
  +extern "C" {
  +#endif
  +
  +/**
  + * Return file handle for a temporaray file.
  + * A unique temporaray file path will be generated using
  + *	rpmGenPath(prefix, "%{_tmppath}/", "rpm-tmp.XXXXX")
  + * where "XXXXXX" is filled in using rand(3). The file is opened, and
  + * the link count and (dev,ino) location are verified after opening.
  + * The file name and the open file handle are returned.
  + *
  + * @param prefix	leading part of temp file path
  + * @retval *fnptr	temp file name (or NULL)
  + * @retval *fdptr	temp file handle
  + * @return		0 on success
  + */
  +int rpmTempFile(/*@null@*/ const char * prefix,
  +		/*@null@*/ /*@out@*/ const char ** fnptr,
  +		/*@out@*/ void * fdptr)
  +	/*@globals rpmGlobalMacroContext, h_errno,
  +		fileSystem, internalState @*/
  +	/*@modifies *fnptr, *fdptr, rpmGlobalMacroContext,
  +		fileSystem, internalState @*/;
  +
  +/** \ingroup signature
  + * Generate signature(s) from a header+payload file, save in signature header.
  + * @param sigh		signature header
  + * @param file		header+payload file name
  + * @param sigTag	type of signature(s) to add
  + * @param passPhrase	private key pass phrase
  + * @return		0 on success, -1 on failure
  + */
  +int rpmAddSignature(Header sigh, const char * file,
  +		    int_32 sigTag, /*@null@*/ const char * passPhrase)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies sigh, sigTag, rpmGlobalMacroContext, fileSystem, internalState @*/;
  +
  +/**
  + * Check for valid pass phrase by invoking a helper.
  + * @param passPhrase	pass phrase
  + * @return		0 on valid, 1 on invalid
  + */
  +int rpmCheckPassPhrase(const char * passPhrase)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/;
  +
  +/** \ingroup signature
  + * Verify a signature from a package.
  + *
  + * @param _dig		container
  + * @retval result	detailed text result of signature verification
  + * @return		result of signature verification
  + */
  +rpmRC rpmVerifySignature(void * _dig, /*@out@*/ char * result)
  +	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
  +	/*@modifies _dig, *result, rpmGlobalMacroContext,
  +		fileSystem, internalState @*/;
  +
  +#ifdef __cplusplus
  +}
  +#endif
  +
  +#endif	/* H_SIGNATURE */
  @@ .
Received on Mon Oct 1 00:38:31 2007
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.