From 7eab1846ca966b0a15107931618b0d5fb15a1444 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Wed, 22 Feb 2006 19:06:23 +0000 Subject: [PATCH] * options.h, keydb.h, g10.c (main), getkey.c (parse_auto_key_locate): Parse a list of key access methods. (get_pubkey_byname): Walk the list here to try and retrieve keys we don't have locally. --- g10/ChangeLog | 7 ++ g10/getkey.c | 190 +++++++++++++++++++++++++++++++------------------- g10/gpg.c | 15 +++- g10/keydb.h | 1 + g10/options.h | 8 +++ 5 files changed, 148 insertions(+), 73 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 7ae181d9f..bd894faa8 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +2006-02-22 David Shaw + + * options.h, keydb.h, g10.c (main), getkey.c + (parse_auto_key_locate): Parse a list of key access methods. + (get_pubkey_byname): Walk the list here to try and retrieve keys + we don't have locally. + 2006-02-21 David Shaw * getkey.c (get_pubkey_byname): Fix minor security problem with diff --git a/g10/getkey.c b/g10/getkey.c index 8ec1e52d1..7d91cde1a 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -905,91 +905,94 @@ get_pubkey_byname (PKT_public_key *pk, KEYDB_HANDLE *ret_kdbhd, int include_unusable ) { int rc; - int tried_cert=0, tried_pka=0, tried_ks=0; STRLIST namelist = NULL; add_to_strlist( &namelist, name ); - retry: + rc = key_byname( NULL, namelist, pk, NULL, 0, include_unusable, ret_keyblock, ret_kdbhd); + /* If the requested name resembles a valid mailbox and automatic + retrieval has been enabled, we try to import the key. */ + if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name)) { int res; + struct akl *akl; - if(!tried_cert - && (opt.keyserver_options.options&KEYSERVER_AUTO_CERT_RETRIEVE)) + for(akl=opt.auto_key_locate;akl;akl=akl->next) { - tried_cert=1; - - glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_cert(name); - glo_ctrl.in_auto_key_retrieve--; - - if(res==0) + switch(akl->type) { - log_info(_("Automatically retrieved `%s' via %s\n"), - name,"DNS CERT"); - goto retry; + case AKL_CERT: + 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"); + break; + + case AKL_PKA: + { + unsigned char fpr[MAX_FINGERPRINT_LEN]; + + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_pka(name,fpr); + glo_ctrl.in_auto_key_retrieve--; + + if(res==0) + { + int i; + char fpr_string[MAX_FINGERPRINT_LEN*2+1]; + + log_info(_("Automatically retrieved `%s' via %s\n"), + name,"PKA"); + + free_strlist(namelist); + namelist=NULL; + + for(i=0;iuri); + } + break; } - } - if(!tried_pka - && opt.allow_pka_lookup - && (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE)) - { - unsigned char fpr[MAX_FINGERPRINT_LEN]; - /* 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. */ - - tried_pka=1; - - glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_pka(name,fpr); - glo_ctrl.in_auto_key_retrieve--; - - if(res==0) - { - int i; - char fpr_string[2+(MAX_FINGERPRINT_LEN*2)+1]; - - log_info(_("Automatically retrieved `%s' via %s\n"), - name,"PKA"); - - free_strlist(namelist); - namelist=NULL; - - for(i=0;iuri); - goto retry; - } + rc = key_byname( NULL, namelist, pk, NULL, 0, + include_unusable, ret_keyblock, ret_kdbhd); + if(rc!=G10ERR_NO_PUBKEY) + break; } } @@ -2875,3 +2878,48 @@ get_ctx_handle(GETKEY_CTX ctx) { return ctx->kr_handle; } + +int +parse_auto_key_locate(char *options) +{ + char *tok; + + while((tok=optsep(&options))) + { + struct akl *akl,*last; + + if(tok[0]=='\0') + continue; + + akl=xmalloc_clear(sizeof(*akl)); + + if(ascii_strcasecmp(tok,"cert")==0) + akl->type=AKL_CERT; + else if(ascii_strcasecmp(tok,"pka")==0) + akl->type=AKL_PKA; + else if(ascii_strcasecmp(tok,"ldap")==0) + akl->type=AKL_LDAP; + else if(ascii_strcasecmp(tok,"keyserver")==0) + akl->type=AKL_KEYSERVER; + else + { + xfree(akl); + return 0; + } + + /* We must maintain the order the user gave us */ + for(last=opt.auto_key_locate;last && last->next;last=last->next) + { + /* Check for duplicates */ + if(last && last->type==akl->type) + return 0; + } + + if(last) + last->next=akl; + else + opt.auto_key_locate=akl; + } + + return 1; +} diff --git a/g10/gpg.c b/g10/gpg.c index b2fb1a57f..825fb7a0c 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -354,14 +354,13 @@ enum cmd_and_opt_values oKeyidFormat, oExitOnStatusWriteError, oLimitCardInsertTries, - oReaderPort, octapiDriver, opcscDriver, oDisableCCID, - oRequireBacksigs, oNoRequireBacksigs, + oAutoKeyLocate, oNoop }; @@ -707,6 +706,7 @@ static ARGPARSE_OPTS opts[] = { { oRecipient, "user", 2, "@" }, { oRequireBacksigs, "require-backsigs", 0, "@"}, { oNoRequireBacksigs, "no-require-backsigs", 0, "@"}, + { oAutoKeyLocate, "auto-key-locate", 2, "@"}, {0,NULL,0,NULL} }; @@ -2645,6 +2645,17 @@ main (int argc, char **argv ) case oRequireBacksigs: opt.require_backsigs=1; break; case oNoRequireBacksigs: opt.require_backsigs=0; break; + case oAutoKeyLocate: + if(!parse_auto_key_locate(pargs.r.ret_str)) + { + if(configname) + log_error(_("%s:%d: invalid auto-key-locate list\n"), + configname,configlineno); + else + log_error(_("invalid auto-key-locate list\n")); + } + break; + case oNoop: break; default : pargs.err = configfp? 1:2; break; diff --git a/g10/keydb.h b/g10/keydb.h index bad6a2e9c..2c97b81a0 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -258,6 +258,7 @@ char*get_long_user_id_string( u32 *keyid ); char*get_user_id( u32 *keyid, size_t *rn ); char*get_user_id_native( u32 *keyid ); KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx); +int parse_auto_key_locate(char *options); /*-- keyid.c --*/ int pubkey_letter( int algo ); diff --git a/g10/options.h b/g10/options.h index af5c6f737..0b6f1c306 100644 --- a/g10/options.h +++ b/g10/options.h @@ -220,6 +220,14 @@ struct error (but an invalid backsig still is). */ int require_backsigs; + /* Linked list of ways to find a key if the key isn't on the local + keyring. */ + struct akl + { + enum {AKL_CERT, AKL_PKA, AKL_LDAP, AKL_KEYSERVER} type; + struct akl *next; + } *auto_key_locate; + } opt; /* CTRL is used to keep some global variables we currently can't