diff --git a/g10/ChangeLog b/g10/ChangeLog index 537d9a404..d33dec6cd 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,20 @@ 2004-05-21 David Shaw + * mainproc.c (check_sig_and_print): If we're honoring preferred + keyservers, and auto-key-retrieve is set, try and get a missing + key from the preferred keyserver subpacket when we verify the sig. + + * gpgv.c (parse_preferred_keyserver, free_keyserver_spec): Stubs. + + * keyserver.c (keyidlist): Use new parse_preferred_keyserver + function. + (keyserver_work): Use the passed-in keyserver spec rather than the + options global one. + + * keyserver-internal.h, keyserver.c (parse_preferred_keyserver): + New function to take a sig and return a split out keyserver_spec. + (keyserver_import_keyid): Now takes a keyserver_spec. + * keyserver.c (keyidlist): Go back to the old fast keyid lister. Only merge selfsigs if we have to for honor-keyserver-url. (keyserver_refresh): Keyserver URL handler moved here. diff --git a/g10/gpgv.c b/g10/gpgv.c index 4c01b8f94..9de44a15a 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -331,6 +331,9 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, return NULL; } +struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig) {return NULL;} +void free_keyserver_spec(struct keyserver_spec *keyserver) {} + /* Stubs to avoid linking to photoid.c */ void show_photos(const struct user_attribute *attrs,int count,PKT_public_key *pk) {} int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) {return 0;} diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index 7e02821f1..851f1a904 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -1,4 +1,22 @@ -/* Keyserver internals */ +/* keyserver-internal.h - Keyserver internals + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ #ifndef _KEYSERVER_INTERNAL_H_ #define _KEYSERVER_INTERNAL_H_ @@ -13,10 +31,11 @@ void free_keyserver_spec(struct keyserver_spec *keyserver); struct keyserver_spec *parse_keyserver_uri(const char *uri,int require_scheme, const char *configname, unsigned int configlineno); +struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig); 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_import_keyid(u32 *keyid,struct keyserver_spec *keyserver); int keyserver_refresh(STRLIST users); int keyserver_search(STRLIST tokens); diff --git a/g10/keyserver.c b/g10/keyserver.c index b1094f973..fc3f4fecb 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -282,6 +282,27 @@ parse_keyserver_uri(const char *uri,int require_scheme, return NULL; } +struct keyserver_spec * +parse_preferred_keyserver(PKT_signature *sig) +{ + struct keyserver_spec *spec=NULL; + const byte *p; + size_t plen; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&plen); + if(p && plen) + { + byte *dupe=m_alloc(plen+1); + + memcpy(dupe,p,plen); + dupe[plen]='\0'; + spec=parse_keyserver_uri(dupe,0,NULL,0); + m_free(dupe); + } + + return spec; +} + static void print_keyrec(int number,struct keyrec *keyrec) { @@ -1173,7 +1194,7 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc, { case KEYSERVER_SCHEME_NOT_FOUND: log_error(_("no handler for keyserver scheme \"%s\"\n"), - opt.keyserver->scheme); + keyserver->scheme); break; case KEYSERVER_NOT_SUPPORTED: @@ -1181,12 +1202,12 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc, "scheme \"%s\"\n"), action==GET?"get":action==SEND?"send": action==SEARCH?"search":"unknown", - opt.keyserver->scheme); + keyserver->scheme); break; case KEYSERVER_VERSION_ERROR: log_error(_("gpgkeys_%s does not support handler version %d\n"), - opt.keyserver->scheme,KEYSERVER_PROTO_VERSION); + keyserver->scheme,KEYSERVER_PROTO_VERSION); break; case KEYSERVER_INTERNAL_ERROR: @@ -1299,7 +1320,7 @@ keyserver_import_fprint(const byte *fprint,size_t fprint_len) } int -keyserver_import_keyid(u32 *keyid) +keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver) { KEYDB_SEARCH_DESC desc; @@ -1309,7 +1330,7 @@ keyserver_import_keyid(u32 *keyid) desc.u.kid[0]=keyid[0]; desc.u.kid[1]=keyid[1]; - return keyserver_work(GET,NULL,&desc,1,opt.keyserver); + return keyserver_work(GET,NULL,&desc,1,keyserver); } /* code mostly stolen from do_export_stream */ @@ -1430,28 +1451,11 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) } } + /* Try and parse the keyserver URL. If it doesn't work, + then we end up writing NULL which indicates we are + the same as any other key. */ if(uid && sig) - { - const byte *p; - size_t plen; - p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&plen); - if(p && plen) - { - byte *dupe=m_alloc(plen+1); - - memcpy(dupe,p,plen); - dupe[plen]='\0'; - - /* Try and parse the keyserver URL. If it - doesn't work, then we end up writing NULL - which indicates we are the same as any other - key. */ - - (*klist)[*count].skipfncvalue= - parse_keyserver_uri(dupe,0,NULL,0); - m_free(dupe); - } - } + (*klist)[*count].skipfncvalue=parse_preferred_keyserver(sig); } (*count)++; diff --git a/g10/mainproc.c b/g10/mainproc.c index 7c760b1a3..514ee1843 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1345,20 +1345,8 @@ check_sig_and_print( CTX c, KBNODE node ) keystr(sig->keyid)); rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - if( rc == G10ERR_NO_PUBKEY && opt.keyserver - && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)) - { - int res; - ctrl.in_auto_key_retrieve++; - res=keyserver_import_keyid ( sig->keyid ); - ctrl.in_auto_key_retrieve--; - if(!res) - 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 - can be found. */ + /* If the key isn't found, check for a preferred keyserver */ if(rc==G10ERR_NO_PUBKEY && sig->flags.pref_ks) { @@ -1375,9 +1363,46 @@ check_sig_and_print( CTX c, KBNODE node ) log_info(_("Key available at: ") ); print_string( log_stream(), p, n, 0 ); putc( '\n', log_stream() ); + + if(opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE + && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) + { + struct keyserver_spec *spec; + + spec=parse_preferred_keyserver(sig); + if(spec) + { + int res; + + ctrl.in_auto_key_retrieve++; + res=keyserver_import_keyid(sig->keyid,spec); + ctrl.in_auto_key_retrieve--; + if(!res) + rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + free_keyserver_spec(spec); + + if(!rc) + break; + } + } } } + /* If the preferred keyserver thing above didn't work, this is a + second try. */ + + if( rc == G10ERR_NO_PUBKEY && opt.keyserver + && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)) + { + int res; + + ctrl.in_auto_key_retrieve++; + res=keyserver_import_keyid ( sig->keyid, opt.keyserver ); + ctrl.in_auto_key_retrieve--; + if(!res) + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + } + if( !rc || rc == G10ERR_BAD_SIGN ) { KBNODE un, keyblock; int count=0, statno;