From f8f52d8ffea04132714fbc7c7ccda4efc4271756 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Thu, 7 Mar 2002 19:44:57 +0000 Subject: [PATCH] Some minor fixes for revocation keys: print a warning if a key is imported that has been revoked by designated revoker, but the designated revoker is not present to verify the revocation (whew!). This applies to all ways to get a key into the system: --import --recv-keys, and --search-keys. If auto-key-retrieve is set, try and retrieve the revocation key. Also, auto-key-retrieve is now a keyserver-option. --- g10/ChangeLog | 24 ++++++++++++ g10/g10.c | 19 +++++++-- g10/gpgv.c | 2 +- g10/import.c | 84 +++++++++++++++++++++++++++++++++++++++- g10/keyserver-internal.h | 1 + g10/keyserver.c | 39 ++++++++++++++----- g10/mainproc.c | 2 +- g10/options.h | 2 +- g10/options.skel | 19 ++++----- 9 files changed, 162 insertions(+), 30 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 2ffa250b8..c0d9ac896 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,27 @@ +2002-03-07 David Shaw + + * g10.c (main): make a few more strings translatable. + + * options.h, options.skel, g10.c (main), gpgv.c, mainproc.c + (check_sig_and_print), keyserver.c (parse_keyserver_options): + --auto-key-retrieve should really be a keyserver-option variable. + + * import.c (revocation_present): new function to print a warning + if a key is imported that has been revoked by designated revoker, + but the designated revoker is not present to verify the + revocation. If keyserver-options auto-key-retrieve is set, try + and fetch the designated revoker from the keyserver. + + * import.c (import_one): call revocation_present after importing a + new key. Note that this applies to --import, --recv-keys, and + --search-keys. + + * keyserver-internal.h, keyserver.c (keyserver_import_fprint): + import via fingerprint (for revocation keys). + + * keyserver.c (keyserver_import_keyid): much simpler + implementation now that we're using KEYDB_SEARCH_DESC internally. + 2002-03-04 David Shaw * revoke.c (gen_revoke): do not prompt for revocation reason for diff --git a/g10/g10.c b/g10/g10.c index 80aba425f..8f7276bdd 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1227,8 +1227,10 @@ main( int argc, char **argv ) case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oHonorHttpProxy: opt.honor_http_proxy = 1; - log_info("WARNING: --honor-http-proxy is deprecated.\n"); - log_info("please use \"--keyserver-options honor-http-proxy\" instead\n"); + log_info(_("WARNING: %s is a deprecated option.\n"), + "--honor-http-proxy"); + log_info(_("please use \"--keyserver-options %s\" instead\n"), + "honor-http-proxy"); break; case oFastListMode: opt.fast_list_mode = 1; break; case oFixedListMode: opt.fixed_list_mode = 1; break; @@ -1237,8 +1239,17 @@ main( int argc, char **argv ) case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; case oIgnoreCrcError: opt.ignore_crc_error = 1; break; case oNoRandomSeedFile: use_random_seed = 0; break; - case oAutoKeyRetrieve: opt.auto_key_retrieve = 1; break; - case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break; + case oAutoKeyRetrieve: + case oNoAutoKeyRetrieve: + opt.keyserver_options.auto_key_retrieve= + (pargs.r_opt==oAutoKeyRetrieve); + log_info(_("WARNING: %s is a deprecated option.\n"), + pargs.r_opt==oAutoKeyRetrieve? + "--auto-key-retrieve":"--no-auto-key-retrieve"); + log_info(_("please use \"--keyserver-options %s\" instead\n"), + pargs.r_opt==oAutoKeyRetrieve? + "auto-key-retrieve":"no-auto-key-retrieve"); + break; case oShowSessionKey: opt.show_session_key = 1; break; case oOverrideSessionKey: opt.override_session_key = pargs.r.ret_str; diff --git a/g10/gpgv.c b/g10/gpgv.c index 007d44ebf..d127e72ad 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -147,7 +147,7 @@ main( int argc, char **argv ) i18n_init(); opt.command_fd = -1; /* no command fd */ opt.pgp2_workarounds = 1; - opt.auto_key_retrieve = 1; + opt.keyserver_options.auto_key_retrieve = 1; opt.always_trust = 1; opt.batch = 1; diff --git a/g10/import.c b/g10/import.c index 37147b40d..9658530f1 100644 --- a/g10/import.c +++ b/g10/import.c @@ -35,7 +35,7 @@ #include "main.h" #include "i18n.h" #include "status.h" - +#include "keyserver-internal.h" struct stats_s { ulong count; @@ -57,6 +57,7 @@ struct stats_s { static int import( IOBUF inp, int fast, const char* fname, struct stats_s *stats ); static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); +static void revocation_present(KBNODE keyblock); static void remove_bad_stuff (KBNODE keyblock); static int import_one( const char *fname, KBNODE keyblock, int fast, struct stats_s *stats); @@ -597,6 +598,9 @@ import_one( const char *fname, KBNODE keyblock, int fast, leave: release_kbnode( keyblock_orig ); free_public_key( pk_orig ); + + revocation_present(keyblock); + return rc; } @@ -1073,7 +1077,84 @@ collapse_uids( KBNODE *keyblock ) return 1; } +/* Check for a 0x20 revocation from a revocation key that is not + present. This gets called without the benefit of merge_xxxx so you + can't rely on pk->revkey and friends. */ +static void +revocation_present(KBNODE keyblock) +{ + KBNODE onode,inode; + PKT_public_key *pk=keyblock->pkt->pkt.public_key; + for(onode=keyblock->next;onode;onode=onode->next) + { + /* If we reach user IDs, we're done. */ + if(onode->pkt->pkttype==PKT_USER_ID) + break; + + if(onode->pkt->pkttype==PKT_SIGNATURE && + onode->pkt->pkt.signature->sig_class==0x1F && + onode->pkt->pkt.signature->revkey) + { + int idx; + PKT_signature *sig=onode->pkt->pkt.signature; + + for(idx=0;idxnumrevkeys;idx++) + { + u32 keyid[2]; + + keyid_from_fingerprint(sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN,keyid); + + for(inode=keyblock->next;inode;inode=inode->next) + { + /* If we reach user IDs, we're done. */ + if(inode->pkt->pkttype==PKT_USER_ID) + break; + + if(inode->pkt->pkttype==PKT_SIGNATURE && + inode->pkt->pkt.signature->sig_class==0x20 && + inode->pkt->pkt.signature->keyid[0]==keyid[0] && + inode->pkt->pkt.signature->keyid[1]==keyid[1]) + { + /* Okay, we have a revocation key, and a + revocation issued by it. Do we have the key + itself? */ + int rc; + + rc=get_pubkey_byfprint(NULL,sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + { + /* No, so try and get it */ + if(opt.keyserver_scheme && + opt.keyserver_options.auto_key_retrieve) + { + log_info(_("Warning: key %08lX may be revoked: " + "fetching revocation key %08lX\n"), + (ulong)keyid_from_pk(pk,NULL), + (ulong)keyid[1]); + keyserver_import_fprint(sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + + /* Do we have it now? */ + rc=get_pubkey_byfprint(NULL, + sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + } + + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + log_info(_("Warning: key %08lX may be revoked: " + "revocation key %08lX not present.\n"), + (ulong)keyid_from_pk(pk,NULL), + (ulong)keyid[1]); + } + } + } + } + } + } +} /**************** * compare and merge the blocks @@ -1440,4 +1521,3 @@ append_key( KBNODE keyblock, KBNODE node, int *n_sigs, return 0; } - diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index d252de524..9165491b4 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -12,6 +12,7 @@ void parse_keyserver_options(char *options); int parse_keyserver_uri(char *uri); int keyserver_export(STRLIST users); int keyserver_import(STRLIST users); +int keyserver_import_fprint(const byte *fprint,size_t fprint_len); int keyserver_import_keyid(u32 *keyid); int keyserver_refresh(STRLIST users); int keyserver_search(STRLIST tokens); diff --git a/g10/keyserver.c b/g10/keyserver.c index 2df47a0c5..48a6a9b73 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -90,6 +90,10 @@ parse_keyserver_options(char *options) opt.keyserver_options.refresh_add_fake_v3_keyids=1; else if(strcasecmp(tok,"no-refresh-add-fake-v3-keyids")==0) opt.keyserver_options.refresh_add_fake_v3_keyids=0; + else if(strcasecmp(tok,"auto-key-retrieve")==0) + opt.keyserver_options.refresh_add_fake_v3_keyids=1; + else if(strcasecmp(tok,"no-auto-key-retrieve")==0) + opt.keyserver_options.refresh_add_fake_v3_keyids=0; else if(strlen(tok)>0) add_to_strlist(&opt.keyserver_options.other,tok); @@ -676,22 +680,37 @@ keyserver_import(STRLIST users) return rc; } +int +keyserver_import_fprint(const byte *fprint,size_t fprint_len) +{ + KEYDB_SEARCH_DESC desc; + + memset(&desc,0,sizeof(desc)); + + if(fprint_len==16) + desc.mode=KEYDB_SEARCH_MODE_FPR16; + else if(fprint_len==20) + desc.mode=KEYDB_SEARCH_MODE_FPR20; + else + return -1; + + memcpy(desc.u.fpr,fprint,fprint_len); + + return keyserver_work(GET,NULL,&desc,1); +} + int keyserver_import_keyid(u32 *keyid) { - STRLIST sl=NULL; - char key[17]; - int ret; + KEYDB_SEARCH_DESC desc; - sprintf(key,"%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); + memset(&desc,0,sizeof(desc)); - add_to_strlist(&sl,key); + desc.mode=KEYDB_SEARCH_MODE_LONG_KID; + desc.u.kid[0]=keyid[0]; + desc.u.kid[1]=keyid[1]; - ret=keyserver_import(sl); - - free_strlist(sl); - - return ret; + return keyserver_work(GET,NULL,&desc,1); } /* code mostly stolen from do_export_stream */ diff --git a/g10/mainproc.c b/g10/mainproc.c index 9bb9338ae..68752767a 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1258,7 +1258,7 @@ 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 ); - if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.auto_key_retrieve) { + 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 ); } diff --git a/g10/options.h b/g10/options.h index ecbc3fe08..d565e09d9 100644 --- a/g10/options.h +++ b/g10/options.h @@ -109,6 +109,7 @@ struct { int use_temp_files:1; int keep_temp_files:1; int refresh_add_fake_v3_keyids:1; + int auto_key_retrieve:1; STRLIST other; } keyserver_options; int exec_disable; @@ -133,7 +134,6 @@ struct { int ignore_valid_from; int ignore_crc_error; int command_fd; - int auto_key_retrieve; const char *override_session_key; int show_session_key; int use_agent; diff --git a/g10/options.skel b/g10/options.skel index 4fac1df4c..def2fe5fb 100644 --- a/g10/options.skel +++ b/g10/options.skel @@ -131,25 +131,25 @@ lock-once # on the keyserver. # # verbose = show more information as the keys are fetched. -# Can be included more than once to increase the amount +# Can be used more than once to increase the amount # of information shown. # # use-temp-files = use temporary files instead of a pipe to talk to the # keyserver. Some platforms (Win32 for one) always # have this on. # -# keep-temp-files = don't delete the temporary files after using them +# keep-temp-files = do not delete temporary files after using them # (really only useful for debugging) # # honor-http-proxy = if the keyserver uses http, honor the http_proxy # environment variable +# +# auto-key-retrieve = automatically fetch keys as needed from the +# keyserver when verifying signatures or when importing +# keys that have been revoked by a revocation key that +# is not present on the keyring. -#keyserver-options include-disabled include-revoked - -# Uncomment this line to automatically fetch a key from a keyserver -# (which must be set - see above) when verifying signatures. - -#auto-key-retrieve +#keyserver-options auto-key-retrieve include-disabled include-revoked # Uncomment this line to display photo user IDs in key listings #show-photos @@ -201,6 +201,3 @@ lock-once # --gpg-agent-info=::1 # # may be used to override it. -# - -