* packet.h, sig-check.c (signature_check2, do_check, do_check_messages):
authorDavid Shaw <dshaw@jabberwocky.com>
Wed, 13 Aug 2003 03:31:36 +0000 (03:31 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Wed, 13 Aug 2003 03:31:36 +0000 (03:31 +0000)
Provide a signing-key-is-revoked flag.  Change all callers.

* status.h, status.c (get_status_string): New REVKEYSIG status tag for a
good signature from a revoked key.

* mainproc.c (do_check_sig, check_sig_and_print): Use it here.

* import.c (import_revoke_cert, merge_blocks, merge_sigs): Compare actual
signatures on import rather than using keyid or class matching.  This does
not change actual behavior with a key, but does mean that all sigs are
imported whether they will be used or not.

* parse-packet.c (parse_signature): Don't give "signature packet without
xxxx" warnings for experimental pk algorithms.  An experimental algorithm
may not have a notion of (for example) a keyid (i.e. PGP's x.509 stuff).

g10/ChangeLog
g10/import.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/sig-check.c
g10/status.c
g10/status.h

index 6424944..f9958dd 100644 (file)
@@ -1,3 +1,25 @@
+2003-08-12  David Shaw  <dshaw@jabberwocky.com>
+
+       * packet.h, sig-check.c (signature_check2, do_check,
+       do_check_messages): Provide a signing-key-is-revoked flag.  Change
+       all callers.
+
+       * status.h, status.c (get_status_string): New REVKEYSIG status tag
+       for a good signature from a revoked key.
+
+       * mainproc.c (do_check_sig, check_sig_and_print): Use it here.
+
+       * import.c (import_revoke_cert, merge_blocks, merge_sigs): Compare
+       actual signatures on import rather than using keyid or class
+       matching.  This does not change actual behavior with a key, but
+       does mean that all sigs are imported whether they will be used or
+       not.
+
+       * parse-packet.c (parse_signature): Don't give "signature packet
+       without xxxx" warnings for experimental pk algorithms.  An
+       experimental algorithm may not have a notion of (for example) a
+       keyid (i.e. PGP's x.509 stuff).
+
 2003-08-02  David Shaw  <dshaw@jabberwocky.com>
 
        * options.h, g10.c (main), keylist.c (list_keyblock_print),
index 48ef868..ac4ab72 100644 (file)
@@ -1,5 +1,6 @@
 /* import.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ *               Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -1030,12 +1031,12 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats )
        if( onode->pkt->pkttype == PKT_USER_ID )
            break;
        else if( onode->pkt->pkttype == PKT_SIGNATURE
-                && onode->pkt->pkt.signature->sig_class == 0x20
-                && keyid[0] == onode->pkt->pkt.signature->keyid[0]
-                && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) {
+                && !cmp_signatures(node->pkt->pkt.signature,
+                                   onode->pkt->pkt.signature))
+         {
            rc = 0;
            goto leave; /* yes, we already know about it */
-       }
+         }
     }
 
 
@@ -1554,13 +1555,12 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
                    break;
                else if( onode->pkt->pkttype == PKT_SIGNATURE
                         && onode->pkt->pkt.signature->sig_class == 0x20
-                        && node->pkt->pkt.signature->keyid[0]
-                           == onode->pkt->pkt.signature->keyid[0]
-                        && node->pkt->pkt.signature->keyid[1]
-                           == onode->pkt->pkt.signature->keyid[1] ) {
+                        && !cmp_signatures(onode->pkt->pkt.signature,
+                                           node->pkt->pkt.signature))
+                 {
                    found = 1;
                    break;
-               }
+                 }
            }
            if( !found ) {
                char *p=get_user_id_printable (keyid);
@@ -1768,20 +1768,12 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
            || n->pkt->pkt.signature->sig_class == 0x28 )
            continue; /* skip signatures which are only valid on subkeys */
        found = 0;
-       for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){
-           if( n2->pkt->pkttype == PKT_SIGNATURE
-               && n->pkt->pkt.signature->keyid[0]
-                  == n2->pkt->pkt.signature->keyid[0]
-               && n->pkt->pkt.signature->keyid[1]
-                  == n2->pkt->pkt.signature->keyid[1]
-               && n->pkt->pkt.signature->timestamp
-                  <= n2->pkt->pkt.signature->timestamp
-               && n->pkt->pkt.signature->sig_class
-                  == n2->pkt->pkt.signature->sig_class ) {
-               found++;
-               break;
+       for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next)
+         if(!cmp_signatures(n->pkt->pkt.signature,n2->pkt->pkt.signature))
+           {
+             found++;
+             break;
            }
-       }
        if( !found ) {
            /* This signature is new or newer, append N to DST.
             * We add a clone to the original keyblock, because this
index e9a658e..8cb7b98 100644 (file)
@@ -660,14 +660,12 @@ proc_compressed( CTX c, PACKET *pkt )
  * Returns: 0 = valid signature or an error code
  */
 static int
-do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey )
+do_check_sig( CTX c, KBNODE node, int *is_selfsig,
+             int *is_expkey, int *is_revkey )
 {
     PKT_signature *sig;
     MD_HANDLE md = NULL, md2 = NULL;
-    int algo, rc, dum2;
-
-    if(!is_expkey)
-      is_expkey=&dum2;
+    int algo, rc;
 
     assert( node->pkt->pkttype == PKT_SIGNATURE );
     if( is_selfsig )
@@ -721,9 +719,9 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey )
     }
     else
        return G10ERR_SIG_CLASS;
-    rc = signature_check2( sig, md, NULL, is_expkey, NULL );
+    rc = signature_check2( sig, md, NULL, is_expkey, is_revkey, NULL );
     if( rc == G10ERR_BAD_SIGN && md2 )
-       rc = signature_check2( sig, md2, NULL, is_expkey, NULL );
+       rc = signature_check2( sig, md2, NULL, is_expkey, is_revkey, NULL );
     md_close(md);
     md_close(md2);
 
@@ -946,7 +944,7 @@ list_node( CTX c, KBNODE node )
            fputs("sig", stdout);
        if( opt.check_sigs ) {
            fflush(stdout);
-           switch( (rc2=do_check_sig( c, node, &is_selfsig, NULL )) ) {
+           switch( (rc2=do_check_sig( c, node, &is_selfsig, NULL, NULL )) ) {
              case 0:                  sigrc = '!'; break;
              case G10ERR_BAD_SIGN:    sigrc = '-'; break;
              case G10ERR_NO_PUBKEY: 
@@ -1205,7 +1203,7 @@ check_sig_and_print( CTX c, KBNODE node )
 {
     PKT_signature *sig = node->pkt->pkt.signature;
     const char *astr, *tstr;
-    int rc, is_expkey=0;
+    int rc, is_expkey=0, is_revkey=0;
 
     if( opt.skip_verify ) {
        log_info(_("signature verification suppressed\n"));
@@ -1280,10 +1278,10 @@ check_sig_and_print( CTX c, KBNODE node )
               (int)strlen(tstr), tstr, astr? astr: "?",
               (ulong)sig->keyid[1] );
 
-    rc = do_check_sig(c, node, NULL, &is_expkey );
+    rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
     if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) {
        if( keyserver_import_keyid ( sig->keyid )==0 )
-           rc = do_check_sig(c, node, NULL, &is_expkey );
+           rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
     }
 
     /* If the key still isn't found, try to inform the user where it
@@ -1319,6 +1317,8 @@ check_sig_and_print( CTX c, KBNODE node )
          statno=STATUS_EXPSIG;
        else if(is_expkey)
          statno=STATUS_EXPKEYSIG;
+       else if(is_revkey)
+         statno=STATUS_REVKEYSIG;
        else
          statno=STATUS_GOODSIG;
 
index 516c93a..9d0e361 100644 (file)
@@ -461,7 +461,7 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
 /*-- sig-check.c --*/
 int signature_check( PKT_signature *sig, MD_HANDLE digest );
 int signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
-                     int *r_expired, PKT_public_key *ret_pk );
+                     int *r_expired, int *r_revoked, PKT_public_key *ret_pk );
 
 /*-- seckey-cert.c --*/
 int is_secret_key_protected( PKT_secret_key *sk );
index b1d1e17..1ba8f32 100644 (file)
@@ -1281,17 +1281,19 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        }
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
-       if( !p )
-           log_error("signature packet without timestamp\n");
-       else
-           sig->timestamp = buffer_to_u32(p);
+       if(p)
+         sig->timestamp = buffer_to_u32(p);
+       else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
+         log_error("signature packet without timestamp\n");
+
        p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
-       if( !p )
-           log_error("signature packet without keyid\n");
-       else {
+       if(p)
+         {
            sig->keyid[0] = buffer_to_u32(p);
            sig->keyid[1] = buffer_to_u32(p+4);
-       }
+         }
+       else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
+         log_error("signature packet without keyid\n");
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
        if(p)
index c2add61..c3b6f04 100644 (file)
@@ -1,5 +1,6 @@
 /* sig-check.c -  Check a signature
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ *               Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -40,7 +41,7 @@ struct cmp_help_context_s {
 };
 
 static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
-                    int *r_expired, PKT_public_key *ret_pk);
+                    int *r_expired, int *r_revoked, PKT_public_key *ret_pk);
 
 /****************
  * Check the signature which is contained in SIG.
@@ -50,12 +51,12 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
 int
 signature_check( PKT_signature *sig, MD_HANDLE digest )
 {
-    return signature_check2( sig, digest, NULL, NULL, NULL );
+    return signature_check2( sig, digest, NULL, NULL, NULL, NULL );
 }
 
 int
 signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, 
-                 int *r_expired, PKT_public_key *ret_pk )
+                 int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
 {
     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
     int rc=0;
@@ -77,7 +78,7 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
     else {
         if(r_expiredate)
          *r_expiredate = pk->expiredate;
-       rc = do_check( pk, sig, digest, r_expired, ret_pk );
+       rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk );
     }
 
     free_public_key( pk );
@@ -201,12 +202,15 @@ cmp_help( void *opaque, MPI result )
 }
 
 static int
-do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired )
+do_check_messages( PKT_public_key *pk, PKT_signature *sig,
+                  int *r_expired, int *r_revoked )
 {
     u32 cur_time;
 
     if(r_expired)
       *r_expired = 0;
+    if(r_revoked)
+      *r_revoked = 0;
     if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
        log_info(_("key %08lX: this is a PGP generated "
                   "ElGamal key which is NOT secure for signatures!\n"),
@@ -253,19 +257,22 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired )
          *r_expired = 1;
     }
 
+    if(pk->is_revoked && r_revoked)
+      *r_revoked=1;
+
     return 0;
 }
 
 
 static int
 do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest,
-         int *r_expired, PKT_public_key *ret_pk )
+         int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
 {
     MPI result = NULL;
     int rc=0;
     struct cmp_help_context_s ctx;
 
-    if( (rc=do_check_messages(pk,sig,r_expired)) )
+    if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) )
         return rc;
     if( (rc=check_digest_algo(sig->digest_algo)) )
        return rc;
@@ -482,6 +489,8 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
    rather than getting it from root or the keydb.  If ret_pk is set,
    fill in the public key that was used to verify the signature.
    ret_pk is only meaningful when the verification was successful. */
+/* TODO: add r_revoked here as well.  It has the same problems as
+   r_expiredate and r_expired and the cache. */
 int
 check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
                      PKT_public_key *ret_pk, int *is_selfsig,
@@ -516,8 +525,9 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
                if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
                    *is_selfsig = 1;
            }
-           /* TODO: should set r_expiredate here as well */
-           if((rc=do_check_messages(pk,sig,r_expired)))
+           /* BUG: This is wrong for non-self-sigs.. needs to be the
+              actual pk */
+           if((rc=do_check_messages(pk,sig,r_expired,NULL)))
              return rc;
             return sig->flags.valid? 0 : G10ERR_BAD_SIGN;
         }
@@ -537,7 +547,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
          {
            md = md_open( algo, 0 );
            hash_public_key( md, pk );
-           rc = do_check( pk, sig, md, r_expired, ret_pk );
+           rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
            cache_sig_result ( sig, rc );
            md_close(md);
          }
@@ -549,7 +559,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
            md = md_open( algo, 0 );
            hash_public_key( md, pk );
            hash_public_key( md, snode->pkt->pkt.public_key );
-           rc = do_check( pk, sig, md, r_expired, ret_pk );
+           rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
             cache_sig_result ( sig, rc );
            md_close(md);
        }
@@ -575,7 +585,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
            md = md_open( algo, 0 );
            hash_public_key( md, pk );
            hash_public_key( md, snode->pkt->pkt.public_key );
-           rc = do_check( pk, sig, md, r_expired, ret_pk );
+           rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
             cache_sig_result ( sig, rc );
            md_close(md);
        }
@@ -590,7 +600,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
     else if( sig->sig_class == 0x1f ) { /* direct key signature */
        md = md_open( algo, 0 );
        hash_public_key( md, pk );
-       rc = do_check( pk, sig, md, r_expired, ret_pk );
+       rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
         cache_sig_result ( sig, rc );
        md_close(md);
     }
@@ -608,12 +618,12 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
              {
                if( is_selfsig )
                  *is_selfsig = 1;
-               rc = do_check( pk, sig, md, r_expired, ret_pk );
+               rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
              }
            else if (check_pk)
-             rc=do_check(check_pk,sig,md,r_expired, ret_pk);
+             rc=do_check(check_pk,sig,md,r_expired,NULL,ret_pk);
            else
-             rc = signature_check2( sig, md, r_expiredate, r_expired, ret_pk);
+             rc=signature_check2(sig,md,r_expiredate,r_expired,NULL,ret_pk);
 
             cache_sig_result ( sig, rc );
            md_close(md);
index cc30db7..cde0c8d 100644 (file)
@@ -148,6 +148,7 @@ get_status_string ( int no )
       case STATUS_SIGEXPIRED     : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break;
       case STATUS_EXPSIG         : s = "EXPSIG"; break;
       case STATUS_EXPKEYSIG      : s = "EXPKEYSIG"; break;
+      case STATUS_REVKEYSIG      : s = "REVKEYSIG"; break;
       case STATUS_ATTRIBUTE      : s = "ATTRIBUTE"; break;
       default: s = "?"; break;
     }
index 44a7d6d..68da60d 100644 (file)
@@ -99,6 +99,7 @@
 #define STATUS_ATTRIBUTE        67
 #define STATUS_IMPORT_OK       68
 #define STATUS_IMPORT_CHECK     69
+#define STATUS_REVKEYSIG        70
 
 /*-- status.c --*/
 void set_status_fd ( int fd );