diff --git a/g10/ChangeLog b/g10/ChangeLog index 642494413..f9958dd6a 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,25 @@ +2003-08-12 David Shaw + + * 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 * options.h, g10.c (main), keylist.c (list_keyblock_print), diff --git a/g10/import.c b/g10/import.c index 48ef86834..ac4ab7291 100644 --- a/g10/import.c +++ b/g10/import.c @@ -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 diff --git a/g10/mainproc.c b/g10/mainproc.c index e9a658ead..8cb7b9825 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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; diff --git a/g10/packet.h b/g10/packet.h index 516c93a44..9d0e36154 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -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 ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index b1d1e17df..1ba8f3239 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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) diff --git a/g10/sig-check.c b/g10/sig-check.c index c2add6174..c3b6f041a 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -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); diff --git a/g10/status.c b/g10/status.c index cc30db79b..cde0c8d77 100644 --- a/g10/status.c +++ b/g10/status.c @@ -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; } diff --git a/g10/status.h b/g10/status.h index 44a7d6d32..68da60d28 100644 --- a/g10/status.h +++ b/g10/status.h @@ -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 );