diff --git a/g10/ChangeLog b/g10/ChangeLog index 7b9db0a73..43f122149 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,6 +1,18 @@ 2005-12-23 David Shaw - * gpgv.c: Stub. + * keyserver.c (keyserver_import_pka): New. Moved from + getkey.c:get_pubkey_byname which was getting crowded. + + * keyserver.c (keyserver_import_cert): Import a key found in DNS + via CERT records. Can handle both the PGP (actual key) and IPGP + (URL) CERT types. + + * getkey.c (get_pubkey_byname): Call them both here. + + * options.h, keyserver.c (parse_keyserver_options): Add + "auto-cert-retrieve" option with optional max size argument. + + * gpgv.c: Stubs. * keyserver-internal.h, keyserver.c (keyserver_spawn, keyserver_work, keygerver_getname): New keyserver_getname function diff --git a/g10/getkey.c b/g10/getkey.c index ebd1345fd..d247b3bcb 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -905,7 +905,7 @@ get_pubkey_byname (PKT_public_key *pk, KEYDB_HANDLE *ret_kdbhd, int include_unusable ) { int rc; - int tried_ks=0, tried_pka=0; + int tried_cert=0, tried_pka=0, tried_ks=0; STRLIST namelist = NULL; add_to_strlist( &namelist, name ); @@ -915,6 +915,25 @@ get_pubkey_byname (PKT_public_key *pk, if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name)) { + int res; + + if(!tried_cert + && (opt.keyserver_options.options&KEYSERVER_AUTO_CERT_RETRIEVE)) + { + tried_cert=1; + + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_cert(name); + glo_ctrl.in_auto_key_retrieve--; + + if(res==0) + { + log_info(_("Automatically retrieved `%s' via %s\n"), + name,"DNS CERT"); + goto retry; + } + } + if(!tried_pka && opt.allow_pka_lookup && (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE)) @@ -922,28 +941,19 @@ get_pubkey_byname (PKT_public_key *pk, /* If the requested name resembles a valid mailbox and automatic retrieval via PKA records has been enabled, we try to import the key via the URI and try again. */ - unsigned char fpr[MAX_FINGERPRINT_LEN]; - char *uri; - struct keyserver_spec *spec; - int try=1; tried_pka=1; - - uri = get_pka_info (name, fpr); - if (uri) + + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_pka(name); + glo_ctrl.in_auto_key_retrieve--; + + if(res==0) { - spec = parse_keyserver_uri (uri, 0, NULL, 0); - if (spec) - { - glo_ctrl.in_auto_key_retrieve++; - try=keyserver_import_fprint (fpr, 20, spec); - glo_ctrl.in_auto_key_retrieve--; - free_keyserver_spec (spec); - } - xfree (uri); + log_info(_("Automatically retrieved `%s' via %s\n"), + name,"PKA"); + goto retry; } - if (try==0) - goto retry; } /* Try keyserver last as it is likely to be the slowest. @@ -952,12 +962,21 @@ get_pubkey_byname (PKT_public_key *pk, with searching for something like "john" and getting a lot of keys back. */ if(!tried_ks + && opt.keyserver && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)) { tried_ks=1; - if(keyserver_getname(name)==0) - goto retry; + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_name(name); + glo_ctrl.in_auto_key_retrieve--; + + if(res==0) + { + log_info(_("Automatically retrieved `%s' via %s\n"), + name,opt.keyserver->uri); + goto retry; + } } } diff --git a/g10/gpgv.c b/g10/gpgv.c index bd5820da7..dbff4831c 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -270,7 +270,7 @@ get_ownertrust (PKT_public_key *pk) } -/* Stub: +/* Stubs: * Because we only work with trusted keys, it does not make sense to * get them from a keyserver */ @@ -280,19 +280,14 @@ keyserver_import_keyid( u32 *keyid, void *dummy ) return -1; } -/* Stub: - * Because we only work with trusted keys, it does not make sense to - * get them from a keyserver - */ int -keyserver_import_fprint (const byte *fprint, size_t fprint_len, - struct keyserver_spec *keyserver) -{ - return -1; -} +keyserver_import_cert(const char *name) { return -1; } int -keyserver_getname(const char *name) { return -1; } +keyserver_import_pka(const char *name) { return -1; } + +int +keyserver_import_name(const char *name) { return -1; } /* Stub: * No encryption here but mainproc links to these functions. diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index 3d2f46581..1f983176e 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -41,6 +41,8 @@ int keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver); int keyserver_refresh(STRLIST users); int keyserver_search(STRLIST tokens); int keyserver_fetch(STRLIST urilist); -int keyserver_getname(const char *name); +int keyserver_import_cert(const char *name); +int keyserver_import_pka(const char *name); +int keyserver_import_name(const char *name); #endif /* !_KEYSERVER_INTERNAL_H_ */ diff --git a/g10/keyserver.c b/g10/keyserver.c index 7b6bdae7a..95d8d8d96 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -86,6 +86,8 @@ static struct parse_options keyserver_opts[]= {"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL, N_("automatically retrieve keys when verifying signatures")}, {"auto-pka-retrieve",KEYSERVER_AUTO_PKA_RETRIEVE,NULL, + N_("automatically retrieve keys from PKA records")}, + {"auto-cert-retrieve",KEYSERVER_AUTO_CERT_RETRIEVE,NULL, N_("automatically retrieve keys from DNS")}, {"try-dns-srv",KEYSERVER_TRY_DNS_SRV,NULL, NULL}, @@ -98,11 +100,19 @@ static int keyserver_work(enum ks_action action,STRLIST list, KEYDB_SEARCH_DESC *desc,int count, struct keyserver_spec *keyserver); +/* Reasonable guess */ +#define DEFAULT_MAX_CERT_SIZE 16384 + +static size_t max_cert_size=DEFAULT_MAX_CERT_SIZE; + int parse_keyserver_options(char *options) { int ret=1; char *tok; + char *max_cert; + + keyserver_opts[7].value=&max_cert; while((tok=optsep(&options))) { @@ -163,6 +173,15 @@ parse_keyserver_options(char *options) } } + if(opt.keyserver_options.options&KEYSERVER_AUTO_CERT_RETRIEVE) + { + if(max_cert) + max_cert_size=strtoul(max_cert,(char **)NULL,10); + + if(max_cert_size==0) + max_cert_size=DEFAULT_MAX_CERT_SIZE; + } + return ret; } @@ -1895,8 +1914,86 @@ keyserver_fetch(STRLIST urilist) return 0; } +/* Import key in a CERT or pointed to by a CERT */ int -keyserver_getname(const char *name) +keyserver_import_cert(const char *name) +{ + char *domain,*look,*url; + IOBUF key; + int type,rc=-1; + + look=xstrdup(name); + + domain=strrchr(look,'@'); + if(domain) + *domain='.'; + + type=get_cert(look,max_cert_size,&key,&url); + if(type==1) + { + int armor_status=opt.no_armor; + + /* CERTs are always in binary format */ + opt.no_armor=1; + + rc=import_keys_stream(key,NULL,opt.keyserver_options.import_options); + + opt.no_armor=armor_status; + + iobuf_close(key); + } + else if(type==2) + { + struct keyserver_spec *spec; + + spec=parse_keyserver_uri(url,1,NULL,0); + if(spec) + { + STRLIST list=NULL; + + add_to_strlist(&list,url); + + rc=keyserver_fetch(list); + + free_strlist(list); + free_keyserver_spec(spec); + } + + xfree(url); + } + + xfree(look); + + return rc; +} + +/* Import key pointed to by a PKA record */ +int +keyserver_import_pka(const char *name) +{ + unsigned char fpr[MAX_FINGERPRINT_LEN]; + char *uri; + int rc=-1; + + uri = get_pka_info (name, fpr); + if (uri) + { + struct keyserver_spec *spec; + spec = parse_keyserver_uri (uri, 0, NULL, 0); + if (spec) + { + rc=keyserver_import_fprint (fpr, 20, spec); + free_keyserver_spec (spec); + } + xfree (uri); + } + + return rc; +} + +/* Import all keys that match name */ +int +keyserver_import_name(const char *name) { STRLIST list=NULL; int rc; diff --git a/g10/options.h b/g10/options.h index 3d425bb85..af5c6f737 100644 --- a/g10/options.h +++ b/g10/options.h @@ -312,5 +312,6 @@ struct { #define KEYSERVER_TRY_DNS_SRV (1<<6) #define KEYSERVER_HONOR_KEYSERVER_URL (1<<7) #define KEYSERVER_AUTO_PKA_RETRIEVE (1<<8) +#define KEYSERVER_AUTO_CERT_RETRIEVE (1<<9) #endif /*G10_OPTIONS_H*/