handle new sig types
authorroot <devnull@localhost>
Thu, 20 Jun 1996 03:10:44 +0000 (03:10 +0000)
committerroot <devnull@localhost>
Thu, 20 Jun 1996 03:10:44 +0000 (03:10 +0000)
always do at least a MD5

CVS patchset: 658
CVS date: 1996/06/20 03:10:44

lib/signature.c

index f4f8944..d7666de 100644 (file)
@@ -2,15 +2,12 @@
 
 /* NOTES
  *
- * A PGP 2.6.2 1024 bit key generates a 152 byte signature
- * A ViaCryptPGP 2.7.1 1024 bit key generates a 152 byte signature
- * A PGP 2.6.2  768 bit key generates a 120 byte signature
+ * Things have been cleaned up wrt PGP.  We can now handle
+ * signatures of any length (which means you can use any
+ * size key you like).  We also honor PGPPATH finally.
  *
- * This code only only works with 1024 bit keys!
- *
- * Sometimes we get 151 byte signatures.  Not sure why, but if we
- * do, we toss it and try once more to get a 152 bytes signature.
- * If we still get a 151 byte sig, fail.  :-(
+ * We are aligning the sig section on disk to 8 bytes.
+ * The lead is already 8 byte aligned.
  */
 
 #include <stdlib.h>
 #include <strings.h>
 
 #include "signature.h"
+#include "md5.h"
 #include "rpmlib.h"
 #include "rpmerr.h"
 
+static int makeMD5Signature(char *file, int ofd);
 static int makePGPSignature(char *file, int ofd, char *passPhrase);
 static int verifyPGPSignature(int fd, void *sig, char *result);
 static int checkPassPhrase(char *passPhrase);
 
+unsigned short sigLookupType(void)
+{
+    char *name;
+
+    /* Now we always generate at least a RPMSIG_MD5 */
+    
+    if (! (name = getVar(RPMVAR_SIGTYPE))) {
+       return RPMSIG_MD5;
+    }
+
+    if (!strcasecmp(name, "none")) {
+       return RPMSIG_MD5;
+    } else if (!strcasecmp(name, "pgp")) {
+       return RPMSIG_MD5_PGP;
+    } else {
+       return RPMSIG_BAD;
+    }
+}
+
+int verifySignature(int fd, short sig_type, void *sig, char *result)
+{
+    switch (sig_type) {
+    case RPMSIG_NONE:
+       strcpy(result, "No signature information available\n");
+       return RPMSIG_NOSIG;
+       break;
+    case RPMSIG_PGP262_1024:
+       if (verifyPGPSignature(fd, sig, result)) {
+           return RPMSIG_BADSIG;
+       }
+       break;
+    case RPMSIG_MD5:
+    case RPMSIG_MD5_PGP:
+       /* XXX */
+       fprintf(stderr, "Almost there...\n");
+       break;
+    default:
+       sprintf(result, "Unimplemented signature type\n");
+       return RPMSIG_UNKNOWNSIG;
+       break;
+    }
+
+    return RPMSIG_SIGOK;
+}
+
+/* We need to be careful here to do 8 byte alignment */
+/* when reading any of the "new" style signatures.   */
+
 int readSignature(int fd, short sig_type, void **sig)
 {
-    unsigned char pgpbuf[256];
+    unsigned char buf[2048];
+    int length;
     
     switch (sig_type) {
     case RPMSIG_NONE:
@@ -40,14 +88,48 @@ int readSignature(int fd, short sig_type, void **sig)
        }
        break;
     case RPMSIG_PGP262_1024:
-       if (read(fd, pgpbuf, 256) != 256) {
+       /* These are always 256 bytes */
+       if (read(fd, buf, 256) != 256) {
           return 0;
        }
        if (sig) {
            *sig = malloc(152);
-           memcpy(*sig, pgpbuf, 152);
+           memcpy(*sig, buf, 152);
        }
        break;
+    case RPMSIG_MD5:
+       /* 8 byte aligned */
+       if (read(fd, buf, 16) != 16) {
+           return 0;
+       }
+       if (sig) {
+           *sig = malloc(16);
+           memcpy(*sig, buf, 16);
+       }
+       break;
+    case RPMSIG_MD5_PGP:
+       /* 8 byte aligned */
+       if (read(fd, buf, 18) != 18) {
+           return 0;
+       }
+       length = buf[16] * 256 + buf[17];
+       if (read(fd, buf + 18, length) != length) {
+           return 0;
+       }
+       if (sig) {
+           *sig = malloc(18 + length);
+           memcpy(*sig, buf, 18 + length);
+       }
+       /* The is the align magic */
+       length = (8 - ((length + 18) % 8)) % 8;
+       if (length) {
+           if (read(fd, buf, length) != length) {
+               return 0;
+           }
+       }
+       break;
+    default:
+       return 0;
     }
 
     return 1;
@@ -55,10 +137,10 @@ int readSignature(int fd, short sig_type, void **sig)
 
 int makeSignature(char *file, short sig_type, int ofd, char *passPhrase)
 {
-    int res;
-    
     switch (sig_type) {
     case RPMSIG_PGP262_1024:
+       /* We no longer generate these */
+#if 0  
        if (! getVar(RPMVAR_PGP_NAME)) {
            error(RPMERR_SIGGEN, "You must set \"pgp_name:\" in /etc/rpmrc\n");
            return RPMERR_SIGGEN;
@@ -68,6 +150,30 @@ int makeSignature(char *file, short sig_type, int ofd, char *passPhrase)
            return makePGPSignature(file, ofd, passPhrase);
        }
         return res;
+#endif
+       error(RPMERR_SIGGEN, "Internal error! RPMSIG_PGP262_1024\n");
+       return RPMERR_SIGGEN;
+       break;
+    case RPMSIG_MD5:
+       if (makeMD5Signature(file, ofd)) {
+           error(RPMERR_SIGGEN, "Unable to generate MD5 signature\n");
+           return RPMERR_SIGGEN;
+       }
+       break;
+    case RPMSIG_MD5_PGP:
+       if (! getVar(RPMVAR_PGP_NAME)) {
+           error(RPMERR_SIGGEN, "You must set \"pgp_name:\" in /etc/rpmrc\n");
+           return RPMERR_SIGGEN;
+       }
+       if (makeMD5Signature(file, ofd)) {
+           error(RPMERR_SIGGEN, "Unable to generate MD5 signature\n");
+           return RPMERR_SIGGEN;
+       }
+       /* makePGPSignature() takes care of 8 byte alignment */
+       if (makePGPSignature(file, ofd, passPhrase)) {
+           error(RPMERR_SIGGEN, "Unable to generate PGP signature\n");
+           return RPMERR_SIGGEN;
+       }
        break;
     case RPMSIG_NONE:
     }
@@ -75,100 +181,28 @@ int makeSignature(char *file, short sig_type, int ofd, char *passPhrase)
     return 0;
 }
 
-#if 0
-void ttycbreak(void)
+static int makeMD5Signature(char *file, int ofd)
 {
-    int tty;
-
-    if ((tty = open("/dev/tty", O_RDWR)) < 0) {
-       fprintf(stderr, "Unable to open tty.  Using standard input.\n");
-       tty = 0;
-    }
-
-    
-}
-#endif
-
-char *getPassPhrase(char *prompt)
-{
-    char *pass;
+    unsigned char sig[16];
 
-    if (! getVar(RPMVAR_PGP_NAME)) {
-       error(RPMERR_SIGGEN,
-             "You must set \"pgp_name:\" in your rpmrc file");
-       return NULL;
-    }
-
-    if (prompt) {
-        pass = getpass(prompt);
-    } else {
-        pass = getpass("");
-    }
-
-    if (checkPassPhrase(pass)) {
-       return NULL;
-    }
-
-    return pass;
-}
-
-static int checkPassPhrase(char *passPhrase)
-{
-    char name[1024];
-    int passPhrasePipe[2];
-    FILE *fpipe;
-    int pid, status;
-    int fd;
-
-    sprintf(name, "+myname=\"%s\"", getVar(RPMVAR_PGP_NAME));
-
-    pipe(passPhrasePipe);
-    if (!(pid = fork())) {
-       close(0);
-       close(1);
-       if (! isVerbose()) {
-           close(2);
-       }
-       if ((fd = open("/dev/null", O_RDONLY)) != 0) {
-           dup2(fd, 0);
-       }
-       if ((fd = open("/dev/null", O_WRONLY)) != 1) {
-           dup2(fd, 1);
-       }
-       dup2(passPhrasePipe[0], 3);
-       setenv("PGPPASSFD", "3", 1);
-       if (getVar(RPMVAR_PGP_PATH)) {
-           setenv("PGPPATH", getVar(RPMVAR_PGP_PATH), 1);
-       }
-       execlp("pgp", "pgp",
-              "+batchmode=on", "+verbose=0",
-              name, "-sf",
-              NULL);
-       error(RPMERR_EXEC, "Couldn't exec pgp");
-       exit(RPMERR_EXEC);
-    }
-
-    fpipe = fdopen(passPhrasePipe[1], "w");
-    close(passPhrasePipe[0]);
-    fprintf(fpipe, "%s\n", passPhrase);
-    fclose(fpipe);
-
-    waitpid(pid, &status, 0);
-    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+    mdbinfile(file, sig);
+    if (write(ofd, sig, 16) != 16) {
        return 1;
     }
-
-    /* passPhrase is good */
+    
     return 0;
 }
 
+/* Be sure to handle 8 byte alignment! */
+
 static int makePGPSignature(char *file, int ofd, char *passPhrase)
 {
+    unsigned char length[2];
     char name[1024];
     char sigfile[1024];
-    int pid, status;
+    int pid, status, len;
     int fd, inpipe[2];
-    unsigned char sigbuf[256];   /* 1024bit sig is 152 bytes */
+    unsigned char sigbuf[2048];   /* 1024bit sig is ~152 bytes */
     FILE *fpipe;
     struct stat statbuf;
 
@@ -212,24 +246,42 @@ static int makePGPSignature(char *file, int ofd, char *passPhrase)
        error(RPMERR_SIGGEN, "pgp failed to write signature");
        return 1;
     }
-    if (statbuf.st_size != 152) {
-       /* 151 byte sig hack */
-       unlink(sigfile);
-       error(RPMERR_SIGGEN, "pgp failed to write 152 byte signature");
-       return -1;
-    }
+
+    /* Fill in the length, data, and then 8 byte alignment magic */
+    len = statbuf.st_size;
+    length[0] = len / 256;
+    length[1] = len % 256;
+    write(ofd, length, 2);
     
     fd = open(sigfile, O_RDONLY);
-    if (read(fd, sigbuf, 152) != 152) {       /* signature is 152 bytes */
+    if (read(fd, sigbuf, len) != len) {
+       unlink(sigfile);
+       close(fd);
+       error(RPMERR_SIGGEN, "unable to read the signature");
+       return 1;
+    }
+    if (write(ofd, sigbuf, len) != len) {
        unlink(sigfile);
        close(fd);
-       error(RPMERR_SIGGEN, "unable to read 152 bytes of signature");
+       error(RPMERR_SIGGEN, "unable to write the signature");
        return 1;
     }
     close(fd);
     unlink(sigfile);
 
-    write(ofd, sigbuf, 256);   /* We write an even 256 bytes */
+    message(MESS_DEBUG, "Wrote %d bytes of PGP sig\n", len);
+    
+    /* Now the alignment */
+    len = (8 - ((len + 18) % 8)) % 8;
+    if (len) {
+       memset(sigbuf, 0xff, len);
+       if (write(ofd, sigbuf, len) != len) {
+           close(fd);
+           error(RPMERR_SIGGEN, "unable to write the alignment cruft");
+           return 1;
+       }
+       message(MESS_DEBUG, "Wrote %d bytes of alignment cruft\n", len);
+    }
     
     return 0;
 }
@@ -245,6 +297,7 @@ static int verifyPGPSignature(int fd, void *sig, char *result)
     /* Write out the signature */
     sigfile = tempnam("/var/tmp", "rpmsig");
     sfd = open(sigfile, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    /* XXX */
     write(sfd, sig, 152);
     close(sfd);
 
@@ -295,40 +348,75 @@ static int verifyPGPSignature(int fd, void *sig, char *result)
     return(0);
 }
 
-int verifySignature(int fd, short sig_type, void *sig, char *result)
+char *getPassPhrase(char *prompt)
 {
-    switch (sig_type) {
-    case RPMSIG_NONE:
-       strcpy(result, "No signature information available\n");
-       return RPMSIG_NOSIG;
-       break;
-    case RPMSIG_PGP262_1024:
-       if (verifyPGPSignature(fd, sig, result)) {
-           return RPMSIG_BADSIG;
-       }
-       break;
-    default:
-       sprintf(result, "Unimplemented signature type\n");
-       return RPMSIG_UNKNOWNSIG;
-       break;
+    char *pass;
+
+    if (! getVar(RPMVAR_PGP_NAME)) {
+       error(RPMERR_SIGGEN,
+             "You must set \"pgp_name:\" in your rpmrc file");
+       return NULL;
     }
 
-    return RPMSIG_SIGOK;
+    if (prompt) {
+        pass = getpass(prompt);
+    } else {
+        pass = getpass("");
+    }
+
+    if (checkPassPhrase(pass)) {
+       return NULL;
+    }
+
+    return pass;
 }
 
-unsigned short sigLookupType(void)
+static int checkPassPhrase(char *passPhrase)
 {
-    char *name;
+    char name[1024];
+    int passPhrasePipe[2];
+    FILE *fpipe;
+    int pid, status;
+    int fd;
 
-    if (! (name = getVar(RPMVAR_SIGTYPE))) {
-       return RPMSIG_NONE;
+    sprintf(name, "+myname=\"%s\"", getVar(RPMVAR_PGP_NAME));
+
+    pipe(passPhrasePipe);
+    if (!(pid = fork())) {
+       close(0);
+       close(1);
+       if (! isVerbose()) {
+           close(2);
+       }
+       if ((fd = open("/dev/null", O_RDONLY)) != 0) {
+           dup2(fd, 0);
+       }
+       if ((fd = open("/dev/null", O_WRONLY)) != 1) {
+           dup2(fd, 1);
+       }
+       dup2(passPhrasePipe[0], 3);
+       setenv("PGPPASSFD", "3", 1);
+       if (getVar(RPMVAR_PGP_PATH)) {
+           setenv("PGPPATH", getVar(RPMVAR_PGP_PATH), 1);
+       }
+       execlp("pgp", "pgp",
+              "+batchmode=on", "+verbose=0",
+              name, "-sf",
+              NULL);
+       error(RPMERR_EXEC, "Couldn't exec pgp");
+       exit(RPMERR_EXEC);
     }
 
-    if (!strcasecmp(name, "none")) {
-       return RPMSIG_NONE;
-    } else if (!strcasecmp(name, "pgp")) {
-       return RPMSIG_PGP262_1024;
-    } else {
-       return RPMSIG_BAD;
+    fpipe = fdopen(passPhrasePipe[1], "w");
+    close(passPhrasePipe[0]);
+    fprintf(fpipe, "%s\n", passPhrase);
+    fclose(fpipe);
+
+    waitpid(pid, &status, 0);
+    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+       return 1;
     }
+
+    /* passPhrase is good */
+    return 0;
 }