doc: Make make distcheck work again.
[gnupg.git] / g10 / keydb.c
index b4877d4..8a68980 100644 (file)
@@ -62,6 +62,28 @@ static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
 static int used_resources;
 static void *primary_keyring=NULL;
 
+
+/* This is a simple cache used to return the last result of a
+   successful fingerprint search.  This works only for keybox resources
+   because (due to lack of a copy_keyblock function) we need to store
+   an image of the keyblock which is fortunately instantly available
+   for keyboxes.  */
+enum keyblock_cache_states {
+  KEYBLOCK_CACHE_EMPTY,
+  KEYBLOCK_CACHE_PREPARED,
+  KEYBLOCK_CACHE_FILLED
+};
+
+struct keyblock_cache {
+  enum keyblock_cache_states state;
+  byte fpr[MAX_FINGERPRINT_LEN];
+  iobuf_t iobuf; /* Image of the keyblock.  */
+  u32 *sigstatus;
+  int pk_no;
+  int uid_no;
+};
+
+
 struct keydb_handle
 {
   /* When we locked all of the resources in ACTIVE (using keyring_lock
@@ -94,6 +116,10 @@ struct keydb_handle
   /* The number of resources in ACTIVE.  */
   int used;
 
+  /* Cache of the last found and parsed key block (only used for
+     keyboxes, not keyrings).  */
+  struct keyblock_cache keyblock_cache;
+
   /* Copy of ALL_RESOURCES when keydb_new is called.  */
   struct resource_item active[MAX_KEYDB_RESOURCES];
 };
@@ -126,32 +152,11 @@ struct kid_not_found_cache_bucket
 };
 
 
-/* This is a simple cache used to return the last result of a
-   successful fingerprint search.  This works only for keybox resources
-   because (due to lack of a copy_keyblock function) we need to store
-   an image of the keyblock which is fortunately instantly available
-   for keyboxes.  */
-enum keyblock_cache_states {
-  KEYBLOCK_CACHE_EMPTY,
-  KEYBLOCK_CACHE_PREPARED,
-  KEYBLOCK_CACHE_FILLED
-};
-
-struct {
-  enum keyblock_cache_states state;
-  byte fpr[MAX_FINGERPRINT_LEN];
-  iobuf_t iobuf; /* Image of the keyblock.  */
-  u32 *sigstatus;
-  int pk_no;
-  int uid_no;
-} keyblock_cache;
-
-
 static int lock_all (KEYDB_HANDLE hd);
 static void unlock_all (KEYDB_HANDLE hd);
 
 
-/* Check whether the keyid KID is in key id is definately not in the
+/* Check whether the keyid KID is in key id is definitely not in the
    database.
 
    Returns:
@@ -233,13 +238,13 @@ kid_not_found_flush (void)
 
 
 static void
-keyblock_cache_clear (void)
+keyblock_cache_clear (struct keydb_handle *hd)
 {
-  keyblock_cache.state = KEYBLOCK_CACHE_EMPTY;
-  xfree (keyblock_cache.sigstatus);
-  keyblock_cache.sigstatus = NULL;
-  iobuf_close (keyblock_cache.iobuf);
-  keyblock_cache.iobuf = NULL;
+  hd->keyblock_cache.state = KEYBLOCK_CACHE_EMPTY;
+  xfree (hd->keyblock_cache.sigstatus);
+  hd->keyblock_cache.sigstatus = NULL;
+  iobuf_close (hd->keyblock_cache.iobuf);
+  hd->keyblock_cache.iobuf = NULL;
 }
 
 
@@ -460,8 +465,70 @@ rt_from_file (const char *filename, int *r_found, int *r_openpgp)
 
   return rt;
 }
+\f
+char *
+keydb_search_desc_dump (struct keydb_search_desc *desc)
+{
+  char b[MAX_FORMATTED_FINGERPRINT_LEN + 1];
+  char fpr[MAX_FINGERPRINT_LEN + 1];
 
-
+  switch (desc->mode)
+    {
+    case KEYDB_SEARCH_MODE_EXACT:
+      return xasprintf ("EXACT: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_SUBSTR:
+      return xasprintf ("SUBSTR: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_MAIL:
+      return xasprintf ("MAIL: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_MAILSUB:
+      return xasprintf ("MAILSUB: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_MAILEND:
+      return xasprintf ("MAILEND: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_WORDS:
+      return xasprintf ("WORDS: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_SHORT_KID:
+      return xasprintf ("SHORT_KID: '%s'",
+                        format_keyid (desc->u.kid, KF_SHORT, b, sizeof (b)));
+    case KEYDB_SEARCH_MODE_LONG_KID:
+      return xasprintf ("LONG_KID: '%s'",
+                        format_keyid (desc->u.kid, KF_LONG, b, sizeof (b)));
+    case KEYDB_SEARCH_MODE_FPR16:
+      bin2hex (desc->u.fpr, 16, fpr);
+      return xasprintf ("FPR16: '%s'",
+                        format_hexfingerprint (fpr, b, sizeof (b)));
+    case KEYDB_SEARCH_MODE_FPR20:
+      bin2hex (desc->u.fpr, 20, fpr);
+      return xasprintf ("FPR20: '%s'",
+                        format_hexfingerprint (fpr, b, sizeof (b)));
+    case KEYDB_SEARCH_MODE_FPR:
+      bin2hex (desc->u.fpr, 20, fpr);
+      return xasprintf ("FPR: '%s'",
+                        format_hexfingerprint (fpr, b, sizeof (b)));
+    case KEYDB_SEARCH_MODE_ISSUER:
+      return xasprintf ("ISSUER: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_ISSUER_SN:
+      return xasprintf ("ISSUER_SN: '%*s'",
+                        (int) (desc->snlen == -1
+                               ? strlen (desc->sn) : desc->snlen),
+                        desc->sn);
+    case KEYDB_SEARCH_MODE_SN:
+      return xasprintf ("SN: '%*s'",
+                        (int) (desc->snlen == -1
+                               ? strlen (desc->sn) : desc->snlen),
+                        desc->sn);
+    case KEYDB_SEARCH_MODE_SUBJECT:
+      return xasprintf ("SUBJECT: '%s'", desc->u.name);
+    case KEYDB_SEARCH_MODE_KEYGRIP:
+      return xasprintf ("KEYGRIP: %s", desc->u.grip);
+    case KEYDB_SEARCH_MODE_FIRST:
+      return xasprintf ("FIRST");
+    case KEYDB_SEARCH_MODE_NEXT:
+      return xasprintf ("NEXT");
+    default:
+      return xasprintf ("Bad search mode (%d)", desc->mode);
+    }
+}
+\f
 gpg_error_t
 keydb_add_resource (const char *url, unsigned int flags)
 {
@@ -1124,20 +1191,28 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
   if (DBG_CLOCK)
     log_clock ("keydb_get_keybock enter");
 
-  if (keyblock_cache.state == KEYBLOCK_CACHE_FILLED)
+  if (hd->keyblock_cache.state == KEYBLOCK_CACHE_FILLED)
     {
-      iobuf_seek (keyblock_cache.iobuf, 0);
-      err = parse_keyblock_image (keyblock_cache.iobuf,
-                                  keyblock_cache.pk_no,
-                                  keyblock_cache.uid_no,
-                                  keyblock_cache.sigstatus,
-                                  ret_kb);
+      err = iobuf_seek (hd->keyblock_cache.iobuf, 0);
       if (err)
-        keyblock_cache_clear ();
-      if (DBG_CLOCK)
-        log_clock (err? "keydb_get_keyblock leave (cached, failed)"
-                      : "keydb_get_keyblock leave (cached)");
-      return err;
+       {
+         log_error ("keydb_get_keyblock: failed to rewind iobuf for cache\n");
+         keyblock_cache_clear (hd);
+       }
+      else
+       {
+         err = parse_keyblock_image (hd->keyblock_cache.iobuf,
+                                     hd->keyblock_cache.pk_no,
+                                     hd->keyblock_cache.uid_no,
+                                     hd->keyblock_cache.sigstatus,
+                                     ret_kb);
+         if (err)
+           keyblock_cache_clear (hd);
+         if (DBG_CLOCK)
+           log_clock (err? "keydb_get_keyblock leave (cached, failed)"
+                      : "keydb_get_keyblock leave (cached)");
+         return err;
+       }
     }
 
   if (hd->found < 0 || hd->found >= hd->used)
@@ -1163,13 +1238,13 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
           {
             err = parse_keyblock_image (iobuf, pk_no, uid_no, sigstatus,
                                         ret_kb);
-            if (!err && keyblock_cache.state == KEYBLOCK_CACHE_PREPARED)
+            if (!err && hd->keyblock_cache.state == KEYBLOCK_CACHE_PREPARED)
               {
-                keyblock_cache.state     = KEYBLOCK_CACHE_FILLED;
-                keyblock_cache.sigstatus = sigstatus;
-                keyblock_cache.iobuf     = iobuf;
-                keyblock_cache.pk_no     = pk_no;
-                keyblock_cache.uid_no    = uid_no;
+                hd->keyblock_cache.state     = KEYBLOCK_CACHE_FILLED;
+                hd->keyblock_cache.sigstatus = sigstatus;
+                hd->keyblock_cache.iobuf     = iobuf;
+                hd->keyblock_cache.pk_no     = pk_no;
+                hd->keyblock_cache.uid_no    = uid_no;
               }
             else
               {
@@ -1181,8 +1256,8 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
       break;
     }
 
-  if (keyblock_cache.state != KEYBLOCK_CACHE_FILLED)
-    keyblock_cache_clear ();
+  if (hd->keyblock_cache.state != KEYBLOCK_CACHE_FILLED)
+    keyblock_cache_clear (hd);
 
   if (DBG_CLOCK)
     log_clock (err? "keydb_get_keyblock leave (failed)"
@@ -1290,7 +1365,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
     return gpg_error (GPG_ERR_INV_ARG);
 
   kid_not_found_flush ();
-  keyblock_cache_clear ();
+  keyblock_cache_clear (hd);
 
   if (hd->found < 0 || hd->found >= hd->used)
     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
@@ -1341,7 +1416,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
     return gpg_error (GPG_ERR_INV_ARG);
 
   kid_not_found_flush ();
-  keyblock_cache_clear ();
+  keyblock_cache_clear (hd);
 
   if (opt.dry_run)
     return 0;
@@ -1401,7 +1476,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
   kid_not_found_flush ();
-  keyblock_cache_clear ();
+  keyblock_cache_clear (hd);
 
   if (hd->found < 0 || hd->found >= hd->used)
     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
@@ -1489,8 +1564,6 @@ keydb_rebuild_caches (int noisy)
 {
   int i, rc;
 
-  keyblock_cache_clear ();
-
   for (i=0; i < used_resources; i++)
     {
       if (!keyring_is_writable (all_resources[i].token))
@@ -1529,7 +1602,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
-  keyblock_cache_clear ();
+  keyblock_cache_clear (hd);
 
   if (DBG_CLOCK)
     log_clock ("keydb_search_reset");
@@ -1560,57 +1633,11 @@ keydb_search_reset (KEYDB_HANDLE hd)
 }
 
 
-static void
-dump_search_desc (KEYDB_HANDLE hd, const char *text,
-                  KEYDB_SEARCH_DESC *desc, size_t ndesc)
-{
-  int n;
-  const char *s;
-
-  for (n=0; n < ndesc; n++)
-    {
-      switch (desc[n].mode)
-        {
-        case KEYDB_SEARCH_MODE_NONE:      s = "none";      break;
-        case KEYDB_SEARCH_MODE_EXACT:     s = "exact";     break;
-        case KEYDB_SEARCH_MODE_SUBSTR:    s = "substr";    break;
-        case KEYDB_SEARCH_MODE_MAIL:      s = "mail";      break;
-        case KEYDB_SEARCH_MODE_MAILSUB:   s = "mailsub";   break;
-        case KEYDB_SEARCH_MODE_MAILEND:   s = "mailend";   break;
-        case KEYDB_SEARCH_MODE_WORDS:     s = "words";     break;
-        case KEYDB_SEARCH_MODE_SHORT_KID: s = "short_kid"; break;
-        case KEYDB_SEARCH_MODE_LONG_KID:  s = "long_kid";  break;
-        case KEYDB_SEARCH_MODE_FPR16:     s = "fpr16";     break;
-        case KEYDB_SEARCH_MODE_FPR20:     s = "fpr20";     break;
-        case KEYDB_SEARCH_MODE_FPR:       s = "fpr";       break;
-        case KEYDB_SEARCH_MODE_ISSUER:    s = "issuer";    break;
-        case KEYDB_SEARCH_MODE_ISSUER_SN: s = "issuer_sn"; break;
-        case KEYDB_SEARCH_MODE_SN:        s = "sn";        break;
-        case KEYDB_SEARCH_MODE_SUBJECT:   s = "subject";   break;
-        case KEYDB_SEARCH_MODE_KEYGRIP:   s = "keygrip";   break;
-        case KEYDB_SEARCH_MODE_FIRST:     s = "first";     break;
-        case KEYDB_SEARCH_MODE_NEXT:      s = "next";      break;
-        default:                          s = "?";         break;
-        }
-      if (!n)
-        log_debug ("%s: mode=%s  (hd=%p)", text, s, hd);
-      else
-        log_debug ("%*s  mode=%s", (int)strlen (text), "", s);
-      if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID)
-        log_printf (" %08lX%08lX", (unsigned long)desc[n].u.kid[0],
-                    (unsigned long)desc[n].u.kid[1]);
-      else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID)
-        log_printf (" %08lX", (unsigned long)desc[n].u.kid[1]);
-      else if (desc[n].mode == KEYDB_SEARCH_MODE_SUBSTR)
-        log_printf (" '%s'", desc[n].u.name);
-    }
-}
-
-
 gpg_error_t
 keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
               size_t ndesc, size_t *descindex)
 {
+  int i;
   gpg_error_t rc;
   int was_reset = hd->is_reset;
   /* If an entry is already in the cache, then don't add it again.  */
@@ -1625,8 +1652,16 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   if (DBG_CLOCK)
     log_clock ("keydb_search enter");
 
-  if (DBG_CACHE)
-    dump_search_desc (hd, "keydb_search", desc, ndesc);
+  if (DBG_LOOKUP)
+    {
+      log_debug ("%s: %zd search descriptions:\n", __func__, ndesc);
+      for (i = 0; i < ndesc; i ++)
+        {
+          char *t = keydb_search_desc_dump (&desc[i]);
+          log_debug ("%s   %d: %s\n", __func__, i, t);
+          xfree (t);
+        }
+    }
 
 
   if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID
@@ -1644,8 +1679,8 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       && ndesc == 1
       && (desc[0].mode == KEYDB_SEARCH_MODE_FPR20
           || desc[0].mode == KEYDB_SEARCH_MODE_FPR)
-      && keyblock_cache.state  == KEYBLOCK_CACHE_FILLED
-      && !memcmp (keyblock_cache.fpr, desc[0].u.fpr, 20))
+      && hd->keyblock_cache.state  == KEYBLOCK_CACHE_FILLED
+      && !memcmp (hd->keyblock_cache.fpr, desc[0].u.fpr, 20))
     {
       /* (DESCINDEX is already set).  */
       if (DBG_CLOCK)
@@ -1657,21 +1692,43 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
          && hd->current >= 0 && hd->current < hd->used)
     {
-      switch (hd->active[hd->current].type)
+      if (DBG_LOOKUP)
+        log_debug ("%s: searching %s (resource %d of %d)\n",
+                   __func__,
+                   hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYRING
+                   ? "keyring"
+                   : (hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYBOX
+                      ? "keybox" : "unknown type"),
+                   hd->current, hd->used);
+
+       switch (hd->active[hd->current].type)
         {
         case KEYDB_RESOURCE_TYPE_NONE:
           BUG(); /* we should never see it here */
           break;
         case KEYDB_RESOURCE_TYPE_KEYRING:
           rc = keyring_search (hd->active[hd->current].u.kr, desc,
-                               ndesc, descindex);
+                               ndesc, descindex, 1);
           break;
         case KEYDB_RESOURCE_TYPE_KEYBOX:
-          rc = keybox_search (hd->active[hd->current].u.kb, desc,
-                              ndesc, KEYBOX_BLOBTYPE_PGP,
-                              descindex, &hd->skipped_long_blobs);
+          do
+            rc = keybox_search (hd->active[hd->current].u.kb, desc,
+                                ndesc, KEYBOX_BLOBTYPE_PGP,
+                                descindex, &hd->skipped_long_blobs);
+          while (rc == GPG_ERR_LEGACY_KEY);
           break;
         }
+
+      if (DBG_LOOKUP)
+        log_debug ("%s: searched %s (resource %d of %d) => %s\n",
+                   __func__,
+                   hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYRING
+                   ? "keyring"
+                   : (hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYBOX
+                      ? "keybox" : "unknown type"),
+                   hd->current, hd->used,
+                   rc == -1 ? "EOF" : gpg_strerror (rc));
+
       if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
         {
           /* EOF -> switch to next resource */
@@ -1686,14 +1743,15 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         ? gpg_error (GPG_ERR_NOT_FOUND)
         : rc);
 
-  keyblock_cache_clear ();
+  keyblock_cache_clear (hd);
   if (!hd->no_caching
       && !rc
       && ndesc == 1 && (desc[0].mode == KEYDB_SEARCH_MODE_FPR20
-                        || desc[0].mode == KEYDB_SEARCH_MODE_FPR))
+                        || desc[0].mode == KEYDB_SEARCH_MODE_FPR)
+      && hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYBOX)
     {
-      keyblock_cache.state = KEYBLOCK_CACHE_PREPARED;
-      memcpy (keyblock_cache.fpr, desc[0].u.fpr, 20);
+      hd->keyblock_cache.state = KEYBLOCK_CACHE_PREPARED;
+      memcpy (hd->keyblock_cache.fpr, desc[0].u.fpr, 20);
     }
 
   if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND
@@ -1720,28 +1778,18 @@ keydb_search_first (KEYDB_HANDLE hd)
 
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
-  err = keydb_search (hd, &desc, 1, NULL);
-  if (gpg_err_code (err) == GPG_ERR_LEGACY_KEY)
-    err = keydb_search_next (hd);
-  return err;
+  return keydb_search (hd, &desc, 1, NULL);
 }
 
 
 gpg_error_t
 keydb_search_next (KEYDB_HANDLE hd)
 {
-  gpg_error_t err;
   KEYDB_SEARCH_DESC desc;
 
-  do
-    {
-      memset (&desc, 0, sizeof desc);
-      desc.mode = KEYDB_SEARCH_MODE_NEXT;
-      err = keydb_search (hd, &desc, 1, NULL);
-    }
-  while (gpg_err_code (err) == GPG_ERR_LEGACY_KEY);
-
-  return err;
+  memset (&desc, 0, sizeof desc);
+  desc.mode = KEYDB_SEARCH_MODE_NEXT;
+  return keydb_search (hd, &desc, 1, NULL);
 }
 
 gpg_error_t
@@ -1759,17 +1807,10 @@ keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
 gpg_error_t
 keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
 {
-  gpg_error_t err;
   KEYDB_SEARCH_DESC desc;
 
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FPR;
   memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
-  do
-    {
-      err = keydb_search (hd, &desc, 1, NULL);
-    }
-  while (gpg_err_code (err) == GPG_ERR_LEGACY_KEY);
-
-  return err;
+  return keydb_search (hd, &desc, 1, NULL);
 }