diff options
Diffstat (limited to '')
-rw-r--r-- | g10/ChangeLog | 11 | ||||
-rw-r--r-- | g10/getkey.c | 67 | ||||
-rw-r--r-- | g10/keyserver-internal.h | 2 | ||||
-rw-r--r-- | g10/keyserver.c | 12 |
4 files changed, 61 insertions, 31 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 2f7bee308..d3df2552b 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,16 @@ 2006-03-13 David Shaw <[email protected]> + * keyserver-internal.h, keyserver.c (keyserver_import_pka): Use + the same API as the other auto-key-locate fetchers. + + * getkey.c (get_pubkey_byname): Use the fingerprint of the key + that we actually fetched. This helps prevent problems where the + key that we fetched doesn't have the same name that we used to + fetch it. In the case of CERT and PKA, this is an actual security + requirement as the URL might point to a key put in by an attacker. + By forcing the use of the fingerprint, we won't use the attacker's + key here. + * keyserver-internal.h, keyserver.c (keyserver_spawn, keyserver_work, keyserver_import_cert, keyserver_import_name, keyserver_import_ldap): Pass fingerprint info through. diff --git a/g10/getkey.c b/g10/getkey.c index 1805eb041..8594ad9e6 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -922,11 +922,14 @@ get_pubkey_byname (PKT_public_key *pk, for(akl=opt.auto_key_locate;akl;akl=akl->next) { + unsigned char *fpr; + size_t fpr_len; + switch(akl->type) { case AKL_CERT: glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_cert(name,NULL,NULL); + res=keyserver_import_cert(name,&fpr,&fpr_len); glo_ctrl.in_auto_key_retrieve--; if(res==0) @@ -935,35 +938,17 @@ get_pubkey_byname (PKT_public_key *pk, 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;i<MAX_FINGERPRINT_LEN;i++) - sprintf(fpr_string+2*i,"%02X",fpr[i]); + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_pka(name,&fpr,&fpr_len); - add_to_strlist( &namelist, fpr_string ); - } - } + if(res==0) + log_info(_("Automatically retrieved `%s' via %s\n"), + name,"PKA"); break; case AKL_LDAP: glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_ldap(name,NULL,NULL); + res=keyserver_import_ldap(name,&fpr,&fpr_len); glo_ctrl.in_auto_key_retrieve--; if(res==0) @@ -979,7 +964,7 @@ get_pubkey_byname (PKT_public_key *pk, if(opt.keyserver) { glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_name(name,NULL,NULL,opt.keyserver); + res=keyserver_import_name(name,&fpr,&fpr_len,opt.keyserver); glo_ctrl.in_auto_key_retrieve--; if(res==0) @@ -994,7 +979,7 @@ get_pubkey_byname (PKT_public_key *pk, keyserver=keyserver_match(akl->spec); glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_name(name,NULL,NULL,keyserver); + res=keyserver_import_name(name,&fpr,&fpr_len,keyserver); glo_ctrl.in_auto_key_retrieve--; if(res==0) @@ -1004,6 +989,34 @@ get_pubkey_byname (PKT_public_key *pk, break; } + /* Use the fingerprint of the key that we actually fetched. + This helps prevent problems where the key that we fetched + doesn't have the same name that we used to fetch it. In + the case of CERT and PKA, this is an actual security + requirement as the URL might point to a key put in by an + attacker. By forcing the use of the fingerprint, we + won't use the attacker's key here. */ + if(res==0 && fpr) + { + int i; + char fpr_string[MAX_FINGERPRINT_LEN*2+1]; + + assert(fpr_len<=MAX_FINGERPRINT_LEN); + + free_strlist(namelist); + namelist=NULL; + + for(i=0;i<fpr_len;i++) + sprintf(fpr_string+2*i,"%02X",fpr[i]); + + if(opt.verbose) + log_info("auto-key-locate found fingerprint %s\n",fpr_string); + + add_to_strlist( &namelist, fpr_string ); + + xfree(fpr); + } + rc = key_byname( NULL, namelist, pk, NULL, 0, include_unusable, ret_keyblock, ret_kdbhd); if(rc!=G10ERR_NO_PUBKEY) diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index 9b6def872..a36598695 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -45,7 +45,7 @@ int keyserver_search(STRLIST tokens); int keyserver_fetch(STRLIST urilist); int keyserver_import_cert(const char *name, unsigned char **fpr,size_t *fpr_len); -int keyserver_import_pka(const char *name,unsigned char *fpr); +int keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len); int keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len, struct keyserver_spec *keyserver); int keyserver_import_ldap(const char *name, diff --git a/g10/keyserver.c b/g10/keyserver.c index b4a8c14ac..31037c01d 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -2036,24 +2036,30 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len) /* Import key pointed to by a PKA record. Return the requested fingerprint in fpr. */ int -keyserver_import_pka(const char *name,unsigned char *fpr) +keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len) { char *uri; int rc=-1; - uri = get_pka_info (name, fpr); + *fpr=xmalloc(20); + *fpr_len=20; + + uri = get_pka_info (name, *fpr); if (uri) { struct keyserver_spec *spec; spec = parse_keyserver_uri (uri, 1, NULL, 0); if (spec) { - rc=keyserver_import_fprint (fpr, 20, spec); + rc=keyserver_import_fprint (*fpr, 20, spec); free_keyserver_spec (spec); } xfree (uri); } + if(rc!=0) + xfree(*fpr); + return rc; } |