Bug 4780 - PGP 2 and 5 are more compatible than rpm assumes.
Summary: PGP 2 and 5 are more compatible than rpm assumes.
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: rpm
Version: 6.0
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jeff Johnson
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 1999-08-30 09:42 UTC by Göran Uddeborg
Modified: 2008-05-01 15:37 UTC (History)
0 users

Fixed In Version:
Clone Of:
Environment:
Last Closed: 1999-09-10 23:51:30 UTC
Embargoed:


Attachments (Terms of Use)

Description Göran Uddeborg 1999-08-30 09:42:40 UTC
This is slightly related to my previous report 4564.

It appears there is still some confusion considering the
compatiblity between PGP 2 and PGP 5.  In the header of an
rpm file there are two different kinds of signature tags,
RPMSIGTAG_PGP and RPMSIGTAG_PGP5.  When creating a signature
using PGP 2 the former tag is used, and when signing with
PGP 5 the latter.

But compatibility doesn't depend on the PGP version used,
but on the kind of KEY used.  PGP 2 understands only RSA
keys.  PGP 5 understands both RSA and DSS keys.  So if I
sign a package with PGP 5 using a RSA key, it will be
possible to verify that package with PGP 2.  It doesn't make
sense to distinguish the signatures depending on which PGP
version has been used to sign it.

It would make sense to have different kinds of tags for
different kinds of keys.  But it would require quite some
parsing to determine this, and the value of this seems
dubious.  So below I enclose a suggested patch te remove the
distinction between the PGP and PGP5 tag.

I have tested this, sending signed packages between a system
with PGP 2 and one with PGP 5.  On the PGP 2 system I have
used both stock rpm 3.0.2 6.0, and my own modified version.
The only combination which fails, is when trying to verify a
package which has been signed with a DSS key on the PGP 2
system.  And that is to be expected.

As a further illustration I have put my modified RPM
packages on ftp://ftp.carmen.se/rpm  These are all signed
using PGP 5, and verified with PGP 2.  (Except the one with
the .dss suffix, that is.)  My keys, if you want them, are
available as http://www.uddeborg.pp.se/g%f6ran/rsa.asc and
http://www.uddeborg.pp.se/g%f6ran/dss.asc respectively.  My
DSS key is also available from the key servers.  The source
RPM package contains the patch included below, if you find
it more convenient to get it that way.

I BELIEVE that GPG is also compatible with PGP on a "common
key type" level.  But I don't know for sure, and I think
I'll wait to install GPG until they release version 1.0,
next month according to their home page.  So I haven't
touched the GPG part of the code in RPM in this patch.
Anayway, it would be interesting to see the response to this
report before I spend any time on GPG.

--- lib/rpmlib.h~       Wed Jun 23 21:39:57 1999
+++ lib/rpmlib.h        Tue Aug 24 12:26:34 1999
@@ -578,7 +578,6 @@ rpmErrorCallBackType rpmErrorSetCallback
 #define        RPMSIGTAG_LEMD5_2               1003
 #define        RPMSIGTAG_MD5                   1004
 #define        RPMSIGTAG_GPG                   1005
-#define        RPMSIGTAG_PGP5                  1006

 /**************************************************/
 /*                                                */
--- lib/signature.h~    Mon Mar 22 17:38:54 1999
+++ lib/signature.h     Tue Aug 24 12:31:29 1999
@@ -54,7 +54,11 @@ int rpmLookupSignatureType(int action);
 /* Utility to read a pass phrase from the user */
 char *rpmGetPassPhrase(const char *prompt, const int
sigTag);

+/* Possible syntax versions for PGP. */
+#define PGP_2 0
+#define PGP_5 2
+
 /* Return path to pgp executable of given type, or NULL
when not found */
-const char *rpmDetectPGPVersion(int sigType);
+const char *rpmDetectPGPVersion(int *pgpVersion);

 #endif /* H_SIGNATURE */
--- lib/signature.c~    Tue Aug 24 11:05:55 1999
+++ lib/signature.c     Tue Aug 24 12:46:29 1999
@@ -24,7 +24,7 @@
 typedef int (*md5func)(const char * fn, unsigned char *
digest);

 static int makePGPSignature(const char *file, void **sig,
int_32 *size,
-                           const char *passPhrase, int
sigTag);
+                           const char *passPhrase);
 static int makeGPGSignature(const char *file, void **sig,
int_32 *size,
                            const char *passPhrase);
 static int checkSize(FD_t fd, int size, int sigsize);
@@ -32,7 +32,7 @@ static int verifySizeSignature(const cha
 static int verifyMD5Signature(const char *datafile,
unsigned char *sig,
                              char *result, md5func fn);
 static int verifyPGPSignature(const char *datafile, void
*sig,
-                             int count, char *result, int
sigTag);+                             int count, char
*result);
 static int verifyGPGSignature(const char *datafile, void
*sig,
                              int count, char *result);
 static int checkPassPhrase(const char *passPhrase, const
int sigTag);
@@ -61,8 +61,6 @@ int rpmLookupSignatureType(int action)
                    rc = 0;
                else if (!strcasecmp(name, "pgp"))
                    rc = RPMSIGTAG_PGP;
-               else if (!strcasecmp(name, "pgp5"))
-                   rc = RPMSIGTAG_PGP5;
                else if (!strcasecmp(name, "gpg"))
                    rc = RPMSIGTAG_GPG;

                else
@@ -78,51 +76,40 @@ int rpmLookupSignatureType(int action)
 /* rpmDetectPGPVersion() returns the absolute path to the
"pgp"  */
 /* executable of the requested version, or NULL when none
found. */

-const char * rpmDetectPGPVersion(int sigTag)
+const char * rpmDetectPGPVersion(int *pgpVersion)
 {
     /* Actually this should support having more then one
pgp version. */
     /* At the moment only one version is possible since we
only       */
     /* have one %_pgpbin and one
%_pgp_path.                          */

-    static int pgp_version;
+    static int saved_pgp_version;
     const char *pgpbin = rpmGetPath("%{_pgpbin}", NULL);

-    if (!pgp_version)
+    if (!saved_pgp_version)
     {
        char *pgpvbin;
        struct stat statbuf;

        if (!pgpbin || ! (pgpvbin = (char
*)malloc(strlen(pgpbin) + 2)))
        {
-         pgp_version = -1;
+         saved_pgp_version = -1;
          return NULL;
        }
        sprintf(pgpvbin, "%sv", pgpbin);

        if (stat(pgpvbin, &statbuf) == 0)
-         pgp_version = 50;
+         saved_pgp_version = PGP_5;
        else if (stat(pgpbin, &statbuf) == 0)
-         pgp_version = 26;
+         saved_pgp_version = PGP_2;
        else
-         pgp_version = -1;
+         saved_pgp_version = -1;

        free(pgpvbin);
     }

-    switch (sigTag)
-    {
-       case RPMSIGTAG_PGP:
-           if (pgp_version == 26)
-               return pgpbin;
-           break;
-       case RPMSIGTAG_PGP5:
-           if (pgp_version == 50)
-               return pgpbin;
-           break;
-       default:
-           break;
-    }
-    return NULL;
+    if (pgpbin && pgpVersion)
+        *pgpVersion = saved_pgp_version;
+    return pgpbin;
 }

 /* rpmReadSignature() emulates the new style signatures if
it finds an */
@@ -248,8 +235,7 @@ int rpmAddSignature(Header header, const
            headerAddEntry(header, sigTag, RPM_BIN_TYPE,
buf, 16);
        break;
       case RPMSIGTAG_PGP:
-      case RPMSIGTAG_PGP5:
-       ret = makePGPSignature(file, &sig, &size,
passPhrase, sigTag);
+       ret = makePGPSignature(file, &sig, &size,
passPhrase);
        if (ret == 0)
            headerAddEntry(header, sigTag, RPM_BIN_TYPE,
sig, size);
        break;
@@ -264,12 +250,13 @@ int rpmAddSignature(Header header,
const
 }

 static int makePGPSignature(const char *file, void **sig,
int_32 *size,
-                           const char *passPhrase, int
sigTag)
+                           const char *passPhrase)
 {
     char sigfile[1024];
     int pid, status;
     int inpipe[2];
     struct stat statbuf;
+    int pgpVer;

     sprintf(sigfile, "%s.sig", file);

@@ -290,13 +277,13 @@ static int makePGPSignature(const char
*

        /* dosetenv("PGPPASS", passPhrase, 1); */

-       if ((path = rpmDetectPGPVersion(sigTag)) != NULL) {
-           switch(sigTag) {
-           case RPMSIGTAG_PGP:
+       if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
+           switch(pgpVer) {
+           case PGP_2:
                execlp(path, "pgp", "+batchmode=on",
"+verbose=0", "+armor=off",
                    name, "-sb", file, sigfile, NULL);
                break;
-           case RPMSIGTAG_PGP5:
+           case PGP_5:
                execlp(path,"pgps", "+batchmode=on",
"+verbose=0", "+armor=off",
                    name, "-b", file, "-o", sigfile, NULL);
                break;
@@ -464,8 +451,7 @@ int rpmVerifySignature(const char *file,
        }
        break;
       case RPMSIGTAG_PGP:
-      case RPMSIGTAG_PGP5:
-       return verifyPGPSignature(file, sig, count, result,
sigTag);
+       return verifyPGPSignature(file, sig, count, result);
        break;
       case RPMSIGTAG_GPG:
        return verifyGPGSignature(file, sig, count, result);
@@ -528,7 +514,7 @@ static int verifyMD5Signature(const char
 }

 static int verifyPGPSignature(const char *datafile, void
*sig,
-                             int count, char *result, int
sigTag)
+                             int count, char *result)
 {
     int pid, status, outpipe[2];
     FD_t sfd;
@@ -536,29 +522,24 @@ static int verifyPGPSignature(const
char
     unsigned char buf[8192];
     FILE *file;
     int res = RPMSIG_OK;
-    int usingPGP5 = 0;
     const char *path;
+    int pgpVer;

     /* What version do we have? */
-    if ((path = rpmDetectPGPVersion(RPMSIGTAG_PGP5))/* Use
pgp5 if we have it */
-           || sigTag == RPMSIGTAG_PGP5)            /* ...
or request it.     */
-    {
-       usingPGP5 = 1;
-       /* Its sad but true: pgp-5.0 returns also an exit
value of 0  */
-       /* when it finds a BAD signature.  So instead we
have to use  */
-       /* the text
output.                                           */
-       res = RPMSIG_BAD;
-    }
-    else if (! (path = rpmDetectPGPVersion(RPMSIGTAG_PGP))
-           || sigTag != RPMSIGTAG_PGP)
-       path = NULL;    /* Fail */
-    if (path == NULL)
+    if ((path = rpmDetectPGPVersion(&pgpVer)) == NULL)
     {
        errno = ENOENT;
        rpmError(RPMERR_EXEC,
                 _("Could not run pgp.  Use --nopgp to skip
PGP checks."));
        _exit(RPMERR_EXEC);
     }
+    if (pgpVer == PGP_5)
+    {
+       /* Its sad but true: pgp-5.0 returns also an exit
value of 0  */
+       /* when it finds a BAD signature.  So instead we
have to use  */
+       /* the text
output.                                           */
+       res = RPMSIG_BAD;
+    }
     /* Write out the signature */
   { const char *tmppath = rpmGetPath("%{_tmppath}", NULL);
     sigfile = tempnam(tmppath, "rpmsig");
@@ -581,7 +562,7 @@ static int verifyPGPSignature(const char
        if (pgp_path && *pgp_path != '%')
            dosetenv("PGPPATH", pgp_path, 1);

-       if (usingPGP5) {
+       if (pgpVer == PGP_5) {
            /* Some output (in particular "This signature
applies to */
            /* another message") is _always_ written to
stderr; we   */
            /* want to catch that output, so dup stdout to
stderr:   */
@@ -717,7 +698,6 @@ char *rpmGetPassPhrase(const char *promp
        }
        break;
       case RPMSIGTAG_PGP:
-      case RPMSIGTAG_PGP5:
       { const char *name = rpmExpand("%{_pgp_name}", NULL);
        aok = (name && *name != '%');
        xfree(name);
@@ -787,22 +767,22 @@ static int checkPassPhrase(const char
*p
            _exit(RPMERR_EXEC);
        }   break;
        case RPMSIGTAG_PGP:
-       case RPMSIGTAG_PGP5:
        {   const char *pgp_path = rpmExpand("%{_pgp_path}",
NULL);
            const char *name =
rpmExpand("+myname=\"%{_pgp_name}\"", NULL);
            const char *path;
+           int pgpVer;

            dosetenv("PGPPASSFD", "3", 1);
            if (pgp_path && *pgp_path != '%')
                dosetenv("PGPPATH", pgp_path, 1);

-           if ((path = rpmDetectPGPVersion(sigTag)) !=
NULL) {
-               switch(sigTag) {
-               case RPMSIGTAG_PGP:
+           if ((path = rpmDetectPGPVersion(&pgpVer)) !=
NULL) {
+               switch(pgpVer) {
+               case PGP_2:
                    execlp(path, "pgp", "+batchmode=on",
"+verbose=0",
                        name, "-sf", NULL);
                    break;
-               case RPMSIGTAG_PGP5:
+               case PGP_5:
                    execlp(path,"pgps", "+batchmode=on",
"+verbose=0",
                        name, "-f", NULL);
                    break;
--- checksig.c~ Fri Jun 25 12:03:15 1999
+++ checksig.c  Tue Aug 24 12:26:37 1999
@@ -216,7 +216,7 @@ int doCheckSig(int flags, const char **a

        sigIter = headerInitIterator(sig);
        while (headerNextIterator(sigIter, &tag, &type,
&ptr, &count)) {
-           if ((tag == RPMSIGTAG_PGP || tag ==
RPMSIGTAG_PGP5)
+           if ((tag == RPMSIGTAG_PGP)
                    && !(flags & CHECKSIG_PGP))
                continue;
            if ((tag == RPMSIGTAG_GPG) && !(flags &
CHECKSIG_GPG))
@@ -246,7 +246,6 @@ int doCheckSig(int flags, const char **a
                        res2 = 1;
                        break;
                      case RPMSIGTAG_PGP:
-                     case RPMSIGTAG_PGP5:
                        if (res3 == RPMSIG_NOKEY || res3 ==
RPMSIG_NOTTRUSTED) {
                            /* Do not consider these a
failure */
                            int offset = 7;
@@ -302,7 +301,6 @@ int doCheckSig(int flags, const char **a
                        strcat(buffer, "md5 ");
                        break;
                      case RPMSIGTAG_PGP:
-                     case RPMSIGTAG_PGP5:
                        strcat(buffer, "pgp ");
                        break;
                      case RPMSIGTAG_GPG:
--- rpm.c~      Wed Jun 30 23:10:31 1999
+++ rpm.c       Tue Aug 24 12:26:39 1999
@@ -1139,25 +1139,9 @@ int main(int argc, char ** argv)
                    break;
                  case RPMSIGTAG_GPG:
                  case RPMSIGTAG_PGP:
-                 case RPMSIGTAG_PGP5:
                    if (sigTag == RPMSIGTAG_PGP
-                           &&
!rpmDetectPGPVersion(RPMSIGTAG_PGP)) {
+                           && !rpmDetectPGPVersion(NULL)) {
                        fprintf(stderr, _("pgp not found:
"));
-                       if
(rpmDetectPGPVersion(RPMSIGTAG_PGP5)) {
-                           fprintf(stderr,
-  _("Use `%%_signature pgp5' instead of `%%_signature pgp'
in macro file.\n"));
-                           exit(EXIT_FAILURE);
-                       }
-                       /* Fall through to default: */
-                   }
-                   else if (sigTag == RPMSIGTAG_PGP5
-                           &&
!rpmDetectPGPVersion(RPMSIGTAG_PGP5)) {
-                       fprintf(stderr, _("pgp version 5 not
found: "));
-                       if
(rpmDetectPGPVersion(RPMSIGTAG_PGP)) {
-                           fprintf(stderr,
-  _("Use `%%_signature pgp' instead of `%%_signature pgp5'
in macro file.\n"));
-                           exit(EXIT_FAILURE);
-                       }
                        /* Fall through to default:*/
                    }
                    else if (!(passPhrase =

Comment 1 Jeff Johnson 1999-09-10 23:51:59 UTC
I just checked in this patch -- thank you!

Next to come is associating algorithms with executables that
understand same. That doesn't look too bad ...


Note You need to log in before you can comment on or make changes to this bug.