* keyserver.c (keyidlist): Go back to the old fast keyid lister. Only
authorDavid Shaw <dshaw@jabberwocky.com>
Fri, 21 May 2004 17:32:30 +0000 (17:32 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Fri, 21 May 2004 17:32:30 +0000 (17:32 +0000)
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
g10/keydb.h
g10/keyid.c
g10/keyserver.c

index 33a536f..537d9a4 100644 (file)
@@ -1,5 +1,13 @@
 2004-05-21  David Shaw  <dshaw@jabberwocky.com>
 
+       * 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.
 
index 39f859f..ab10566 100644 (file)
@@ -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 );
index 581d95f..aa9ec0b 100644 (file)
@@ -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.
index 4beeb8d..b1094f9 100644 (file)
@@ -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)