aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/ChangeLog8
-rw-r--r--g10/keydb.h1
-rw-r--r--g10/keyid.c24
-rw-r--r--g10/keyserver.c232
4 files changed, 166 insertions, 99 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 <[email protected]>
+ * 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)
+ *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
+
+ kdbhd=keydb_new(0);
+
+ if(!users)
{
- log_error("error reading key: %s\n", g10_errstr(rc) );
- get_pubkey_end( ctx );
- return rc;
+ 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));
+ }
}
- *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num);
-
- do
+ 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)++;
+
+ 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;
- /* Check the user ID for a preferred keyserver subpacket. */
+ /* 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;i<count;i++)
+ {
+ if(desc[i].skipfncvalue)
+ {
+ struct keyserver_spec *keyserver=desc[i].skipfncvalue;
+
+ /* We use the keyserver structure we parsed out before.
+ Note that a preferred keyserver without a scheme://
+ will be interpreted as hkp:// */
+
+ rc=keyserver_work(GET,NULL,&desc[i],1,keyserver);
+ if(rc)
+ log_info(_("WARNING: unable to refresh key %s"
+ " via %s: %s\n"),keystr_from_desc(&desc[i]),
+ keyserver->uri,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)