From 086e589898dfb40f9c87e7c35d0dbba70c987f54 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Fri, 21 May 2004 17:32:30 +0000 Subject: [PATCH] * 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. (calculate_keyid_fpr): Removed. * keydb.h, keyid.c (keystr_from_desc): Calculate a key string from a KEYDB_SEARCH_DESC. --- g10/ChangeLog | 8 ++ g10/keydb.h | 1 + g10/keyid.c | 24 +++++ g10/keyserver.c | 234 +++++++++++++++++++++++++++--------------------- 4 files changed, 167 insertions(+), 100 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 33a536f1e..537d9a404 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,13 @@ 2004-05-21 David Shaw + * 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. + (calculate_keyid_fpr): Removed. + + * keydb.h, keyid.c (keystr_from_desc): Calculate a key string from + a KEYDB_SEARCH_DESC. + * keyserver.c (keyserver_spawn): Fix keyserver options on tempfile only platforms. Noted by Roger Sondermann. diff --git a/g10/keydb.h b/g10/keydb.h index 39f859f0f..ab1056682 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -243,6 +243,7 @@ size_t keystrlen(void); const char *keystr(u32 *keyid); const char *keystr_from_pk(PKT_public_key *pk); const char *keystr_from_sk(PKT_secret_key *sk); +const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc); u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid ); u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ); u32 keyid_from_sig( PKT_signature *sig, u32 *keyid ); diff --git a/g10/keyid.c b/g10/keyid.c index 581d95fc1..aa9ec0b5a 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -212,6 +212,30 @@ keystr_from_sk(PKT_secret_key *sk) return keystr(sk->keyid); } +const char * +keystr_from_desc(KEYDB_SEARCH_DESC *desc) +{ + if(desc->mode==KEYDB_SEARCH_MODE_LONG_KID) + return keystr(desc->u.kid); + else if(desc->mode==KEYDB_SEARCH_MODE_FPR20) + { + u32 keyid[2]; + + keyid[0] = (unsigned char)desc->u.fpr[12] << 24 + | (unsigned char)desc->u.fpr[13] << 16 + | (unsigned char)desc->u.fpr[14] << 8 + | (unsigned char)desc->u.fpr[15] ; + keyid[1] = (unsigned char)desc->u.fpr[16] << 24 + | (unsigned char)desc->u.fpr[17] << 16 + | (unsigned char)desc->u.fpr[18] << 8 + | (unsigned char)desc->u.fpr[19] ; + + return keystr(keyid); + } + else + BUG(); +} + /**************** * Get the keyid from the secret key and put it into keyid * if this is not NULL. Return the 32 low bits of the keyid. diff --git a/g10/keyserver.c b/g10/keyserver.c index 4beeb8d9f..b1094f973 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -850,7 +850,7 @@ keyserver_spawn(int action,STRLIST list,KEYDB_SEARCH_DESC *desc, fprintf(spawn->tochild,"0x%08lX%08lX\n", (ulong)desc[i].u.kid[0], (ulong)desc[i].u.kid[1]); - else + else if(desc[i].mode==KEYDB_SEARCH_MODE_SHORT_KID) fprintf(spawn->tochild,"0x%08lX\n", (ulong)desc[i].u.kid[1]); } @@ -1312,54 +1312,110 @@ keyserver_import_keyid(u32 *keyid) return keyserver_work(GET,NULL,&desc,1,opt.keyserver); } -static void -calculate_keyid_fpr(PKT_public_key *pk,KEYDB_SEARCH_DESC *desc) -{ - if(pk->version<4) - { - desc->mode=KEYDB_SEARCH_MODE_LONG_KID; - keyid_from_pk(pk,desc->u.kid); - } - else - { - size_t dummy; - - desc->mode=KEYDB_SEARCH_MODE_FPR20; - fingerprint_from_pk(pk,desc->u.fpr,&dummy); - } -} - +/* code mostly stolen from do_export_stream */ static int keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) { - int rc=0,num=100; + int rc=0,ndesc,num=100; KBNODE keyblock=NULL,node; - GETKEY_CTX ctx; + KEYDB_HANDLE kdbhd; + KEYDB_SEARCH_DESC *desc; + STRLIST sl; *count=0; - rc=get_pubkey_bynames(&ctx,NULL,users,&keyblock); - if(rc) - { - log_error("error reading key: %s\n", g10_errstr(rc) ); - get_pubkey_end( ctx ); - return rc; - } - *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); - do + kdbhd=keydb_new(0); + + if(!users) { + ndesc = 1; + desc = m_alloc_clear ( ndesc * sizeof *desc); + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + } + else + { + for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) + ; + desc = m_alloc ( ndesc * sizeof *desc); + + for (ndesc=0, sl=users; sl; sl = sl->next) + { + if(classify_user_id (sl->d, desc+ndesc)) + ndesc++; + else + log_error (_("key `%s' not found: %s\n"), + sl->d, g10_errstr (G10ERR_INV_USER_ID)); + } + } + + while (!(rc = keydb_search (kdbhd, desc, ndesc))) + { + if (!users) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + /* read the keyblock */ + rc = keydb_get_keyblock (kdbhd, &keyblock ); + if( rc ) + { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + goto leave; + } + if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY))) { - PKT_public_key *pk=node->pkt->pkt.public_key; + /* This is to work around a bug in some keyservers (pksd and + OKS) that calculate v4 RSA keyids as if they were v3 RSA. + The answer is to refresh both the correct v4 keyid + (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7). + This only happens for key refresh using the HKP scheme + and if the refresh-add-fake-v3-keyids keyserver option is + set. */ + if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) && + node->pkt->pkt.public_key->version>=4) + { + (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; + mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], + (*klist)[*count].u.kid); + (*count)++; - /* Check the user ID for a preferred keyserver subpacket. */ + if(*count==num) + { + num+=100; + *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); + } + } + + /* v4 keys get full fingerprints. v3 keys get long keyids. + This is because it's easy to calculate any sort of keyid + from a v4 fingerprint, but not a v3 fingerprint. */ + + if(node->pkt->pkt.public_key->version<4) + { + (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; + keyid_from_pk(node->pkt->pkt.public_key, + (*klist)[*count].u.kid); + } + else + { + size_t dummy; + + (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20; + fingerprint_from_pk(node->pkt->pkt.public_key, + (*klist)[*count].u.fpr,&dummy); + } + + (*klist)[*count].skipfncvalue=NULL; + + /* Are we honoring preferred keyservers? */ if(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) { PKT_user_id *uid=NULL; PKT_signature *sig=NULL; + merge_keys_and_selfsig(keyblock); + for(node=node->next;node;node=node->next) { if(node->pkt->pkttype==PKT_USER_ID @@ -1381,82 +1437,23 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&plen); if(p && plen) { - struct keyserver_spec *keyserver; byte *dupe=m_alloc(plen+1); memcpy(dupe,p,plen); dupe[plen]='\0'; - /* Make up a keyserver structure and do an - import for this key. Note that a preferred - keyserver without a scheme:// will be - interpreted as hkp:// */ + /* 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. */ - keyserver=parse_keyserver_uri(dupe,0,NULL,0); + (*klist)[*count].skipfncvalue= + parse_keyserver_uri(dupe,0,NULL,0); m_free(dupe); - - if(keyserver) - { - KEYDB_SEARCH_DESC desc; - - calculate_keyid_fpr(pk,&desc); - - rc=keyserver_work(GET,NULL,&desc,1,keyserver); - if(rc) - log_info(_("WARNING: unable to refresh key %s" - " via %s: %s\n"), - keystr_from_pk(pk),keyserver->uri, - g10_errstr(rc)); - free_keyserver_spec(keyserver); - - continue; - } - else - log_info(_("WARNING: unable to refresh key %s" - " via %s: %s\n"), - keystr_from_pk(pk),keyserver->uri, - g10_errstr(G10ERR_BAD_URI)); } } } - /* This is to work around a bug in some keyservers (pksd and - OKS) that calculate v4 RSA keyids as if they were v3 RSA. - The answer is to refresh both the correct v4 keyid - (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7). - This only happens for key refresh using the HKP scheme - and if the refresh-add-fake-v3-keyids keyserver option is - set. */ - if(fakev3 && is_RSA(pk->pubkey_algo) && pk->version>=4) - { - (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - mpi_get_keyid(pk->pkey[0],(*klist)[*count].u.kid); - (*count)++; - - if(*count==num) - { - num+=100; - *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); - } - } - - /* v4 keys get full fingerprints. v3 keys get long keyids. - This is because it's easy to calculate any sort of key id - from a v4 fingerprint, but not a v3 fingerprint. */ - - if(pk->version<4) - { - (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - keyid_from_pk(pk,(*klist)[*count].u.kid); - } - else - { - size_t dummy; - - (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20; - fingerprint_from_pk(pk,(*klist)[*count].u.fpr,&dummy); - } - (*count)++; if(*count==num) @@ -1465,12 +1462,19 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); } } - - release_kbnode(keyblock); } - while(!get_pubkey_next(ctx,NULL,&keyblock)); - return 0; + if(rc==-1) + rc=0; + + leave: + if(rc) + m_free(*klist); + m_free(desc); + keydb_release(kdbhd); + release_kbnode(keyblock); + + return rc; } /* Note this is different than the original HKP refresh. It allows @@ -1500,6 +1504,36 @@ keyserver_refresh(STRLIST users) if(count>0) { + int i; + + /* Try to handle preferred keyserver keys first */ + for(i=0;iuri,g10_errstr(rc)); + else + { + /* We got it, so mark it as NONE so we don't try and + get it again from the regular keyserver. */ + + desc[i].mode=KEYDB_SEARCH_MODE_NONE; + } + + free_keyserver_spec(keyserver); + } + } + if(opt.keyserver) { if(count==1)