gpg: Minor cleanup for key listing related code.
[gnupg.git] / g10 / getkey.c
index 171f177..fe183fa 100644 (file)
@@ -74,6 +74,7 @@ static struct
 typedef struct keyid_list
 {
   struct keyid_list *next;
 typedef struct keyid_list
 {
   struct keyid_list *next;
+  char fpr[MAX_FINGERPRINT_LEN];
   u32 keyid[2];
 } *keyid_list_t;
 
   u32 keyid[2];
 } *keyid_list_t;
 
@@ -128,7 +129,7 @@ void
 cache_public_key (PKT_public_key * pk)
 {
 #if MAX_PK_CACHE_ENTRIES
 cache_public_key (PKT_public_key * pk)
 {
 #if MAX_PK_CACHE_ENTRIES
-  pk_cache_entry_t ce;
+  pk_cache_entry_t ce, ce2;
   u32 keyid[2];
 
   if (pk_cache_disabled)
   u32 keyid[2];
 
   if (pk_cache_disabled)
@@ -140,6 +141,7 @@ cache_public_key (PKT_public_key * pk)
   if (is_ELGAMAL (pk->pubkey_algo)
       || pk->pubkey_algo == PUBKEY_ALGO_DSA
       || pk->pubkey_algo == PUBKEY_ALGO_ECDSA
   if (is_ELGAMAL (pk->pubkey_algo)
       || pk->pubkey_algo == PUBKEY_ALGO_DSA
       || pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+      || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
       || pk->pubkey_algo == PUBKEY_ALGO_ECDH
       || is_RSA (pk->pubkey_algo))
     {
       || pk->pubkey_algo == PUBKEY_ALGO_ECDH
       || is_RSA (pk->pubkey_algo))
     {
@@ -158,11 +160,25 @@ cache_public_key (PKT_public_key * pk)
 
   if (pk_cache_entries >= MAX_PK_CACHE_ENTRIES)
     {
 
   if (pk_cache_entries >= MAX_PK_CACHE_ENTRIES)
     {
-      /* fixme: Use another algorithm to free some cache slots.  */
-      pk_cache_disabled = 1;
-      if (opt.verbose > 1)
-       log_info (_("too many entries in pk cache - disabled\n"));
-      return;
+      int n;
+
+      /* Remove the last 50% of the entries.  */
+      for (ce = pk_cache, n = 0; ce && n < pk_cache_entries/2; n++)
+        ce = ce->next;
+      if (ce != pk_cache && ce->next)
+        {
+          ce2 = ce->next;
+          ce->next = NULL;
+          ce = ce2;
+          for (; ce; ce = ce2)
+            {
+              ce2 = ce->next;
+              free_public_key (ce->pk);
+              xfree (ce);
+              pk_cache_entries--;
+            }
+        }
+      assert (pk_cache_entries < MAX_PK_CACHE_ENTRIES);
     }
   pk_cache_entries++;
   ce = xmalloc (sizeof *ce);
     }
   pk_cache_entries++;
   ce = xmalloc (sizeof *ce);
@@ -248,6 +264,7 @@ cache_user_id (KBNODE keyblock)
          keyid_list_t a = xmalloc_clear (sizeof *a);
          /* Hmmm: For a long list of keyids it might be an advantage
           * to append the keys.  */
          keyid_list_t a = xmalloc_clear (sizeof *a);
          /* Hmmm: For a long list of keyids it might be an advantage
           * to append the keys.  */
+          fingerprint_from_pk (k->pkt->pkt.public_key, a->fpr, NULL);
          keyid_from_pk (k->pkt->pkt.public_key, a->keyid);
          /* First check for duplicates.  */
          for (r = user_id_db; r; r = r->next)
          keyid_from_pk (k->pkt->pkt.public_key, a->keyid);
          /* First check for duplicates.  */
          for (r = user_id_db; r; r = r->next)
@@ -255,8 +272,7 @@ cache_user_id (KBNODE keyblock)
              keyid_list_t b = r->keyids;
              for (b = r->keyids; b; b = b->next)
                {
              keyid_list_t b = r->keyids;
              for (b = r->keyids; b; b = b->next)
                {
-                 if (b->keyid[0] == a->keyid[0]
-                     && b->keyid[1] == a->keyid[1])
+                 if (!memcmp (b->fpr, a->fpr, MAX_FINGERPRINT_LEN))
                    {
                      if (DBG_CACHE)
                        log_debug ("cache_user_id: already in cache\n");
                    {
                      if (DBG_CACHE)
                        log_debug ("cache_user_id: already in cache\n");
@@ -431,7 +447,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
 
   hd = keydb_new ();
   rc = keydb_search_kid (hd, keyid);
 
   hd = keydb_new ();
   rc = keydb_search_kid (hd, keyid);
-  if (rc == -1)
+  if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
@@ -444,8 +460,9 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
       return G10ERR_NO_PUBKEY;
     }
 
       return G10ERR_NO_PUBKEY;
     }
 
-  assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
-         || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+  assert (keyblock && keyblock->pkt
+          && (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+              || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY));
 
   keyid_from_pk (keyblock->pkt->pkt.public_key, pkid);
   if (keyid[0] == pkid[0] && keyid[1] == pkid[1])
 
   keyid_from_pk (keyblock->pkt->pkt.public_key, pkid);
   if (keyid[0] == pkid[0] && keyid[1] == pkid[1])
@@ -696,7 +713,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 
   is_mbox = is_valid_mailbox (name);
 
 
   is_mbox = is_valid_mailbox (name);
 
-  /* Check whether we the default local search has been disabled.
+  /* Check whether the default local search has been disabled.
      This is the case if either the "nodefault" or the "local" keyword
      are in the list of auto key locate mechanisms.
 
      This is the case if either the "nodefault" or the "local" keyword
      are in the list of auto key locate mechanisms.
 
@@ -872,12 +889,12 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
          if (!rc)
            {
              /* Key found.  */
          if (!rc)
            {
              /* Key found.  */
-             log_info (_("automatically retrieved `%s' via %s\n"),
+             log_info (_("automatically retrieved '%s' via %s\n"),
                        name, mechanism);
              break;
            }
          if (rc != G10ERR_NO_PUBKEY || opt.verbose || no_fingerprint)
                        name, mechanism);
              break;
            }
          if (rc != G10ERR_NO_PUBKEY || opt.verbose || no_fingerprint)
-           log_info (_("error retrieving `%s' via %s: %s\n"),
+           log_info (_("error retrieving '%s' via %s: %s\n"),
                      name, mechanism,
                      no_fingerprint ? _("No fingerprint") : g10_errstr (rc));
        }
                      name, mechanism,
                      no_fingerprint ? _("No fingerprint") : g10_errstr (rc));
        }
@@ -911,26 +928,41 @@ get_pubkey_bynames (GETKEY_CTX * retctx, PKT_public_key * pk,
 int
 get_pubkey_next (GETKEY_CTX ctx, PKT_public_key * pk, KBNODE * ret_keyblock)
 {
 int
 get_pubkey_next (GETKEY_CTX ctx, PKT_public_key * pk, KBNODE * ret_keyblock)
 {
-  int rc;
-
-  rc = lookup (ctx, ret_keyblock, 0);
-  if (!rc && pk && ret_keyblock)
-    pk_from_block (ctx, pk, *ret_keyblock);
-
-  return rc;
+  return gpg_err_code (getkey_next (ctx, pk, ret_keyblock));
 }
 
 void
 get_pubkey_end (GETKEY_CTX ctx)
 {
 }
 
 void
 get_pubkey_end (GETKEY_CTX ctx)
 {
-  if (ctx)
-    {
-      memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
-      keydb_release (ctx->kr_handle);
-      free_strlist (ctx->extra_list);
-      if (!ctx->not_allocated)
-       xfree (ctx);
-    }
+  getkey_end (ctx);
+}
+
+
+/* Search for a key with the given standard fingerprint.  In contrast
+ * to get_pubkey_byfprint we assume a right padded fingerprint of the
+ * standard length.  PK may be NULL to only put the result into the
+ * internal caches.  */
+gpg_error_t
+get_pubkey_byfpr (PKT_public_key *pk, const byte *fpr)
+{
+  gpg_error_t err;
+  struct getkey_ctx_s ctx;
+  kbnode_t kb = NULL;
+
+  memset (&ctx, 0, sizeof ctx);
+  ctx.exact = 1;
+  ctx.not_allocated = 1;
+  ctx.kr_handle = keydb_new ();
+  ctx.nitems = 1;
+  ctx.items[0].mode = KEYDB_SEARCH_MODE_FPR;
+  memcpy (ctx.items[0].u.fpr, fpr, MAX_FINGERPRINT_LEN);
+  err = lookup (&ctx, &kb, 0);
+  if (!err && pk)
+    pk_from_block (&ctx, pk, kb);
+  release_kbnode (kb);
+  get_pubkey_end (&ctx);
+
+  return err;
 }
 
 
 }
 
 
@@ -992,7 +1024,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
 
   hd = keydb_new ();
   rc = keydb_search_fpr (hd, fprbuf);
 
   hd = keydb_new ();
   rc = keydb_search_fpr (hd, fprbuf);
-  if (rc == -1)
+  if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
@@ -1212,7 +1244,14 @@ getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
 void
 getkey_end (getkey_ctx_t ctx)
 {
 void
 getkey_end (getkey_ctx_t ctx)
 {
-  get_pubkey_end (ctx);
+  if (ctx)
+    {
+      memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
+      keydb_release (ctx->kr_handle);
+      free_strlist (ctx->extra_list);
+      if (!ctx->not_allocated)
+       xfree (ctx);
+    }
 }
 
 
 }
 
 
@@ -1221,6 +1260,38 @@ getkey_end (getkey_ctx_t ctx)
  ************* Merging stuff ********************
  ************************************************/
 
  ************* Merging stuff ********************
  ************************************************/
 
+/* Set the mainkey_id fields for all keys in KEYBLOCK.  This is
+   usually done by merge_selfsigs but at some places we only need the
+   main_kid but the the full merging.  The function also guarantees
+   that all pk->keyids are computed. */
+void
+setup_main_keyids (kbnode_t keyblock)
+{
+  u32 kid[2], mainkid[2];
+  kbnode_t kbctx, node;
+  PKT_public_key *pk;
+
+  if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
+    BUG ();
+  pk = keyblock->pkt->pkt.public_key;
+
+  keyid_from_pk (pk, mainkid);
+  for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+    {
+      if (!(node->pkt->pkttype == PKT_PUBLIC_KEY
+            || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+        continue;
+      pk = node->pkt->pkt.public_key;
+      keyid_from_pk (pk, kid); /* Make sure pk->keyid is set.  */
+      if (!pk->main_keyid[0] && !pk->main_keyid[1])
+        {
+          pk->main_keyid[0] = mainkid[0];
+          pk->main_keyid[1] = mainkid[1];
+        }
+    }
+}
+
+
 /* Merge all self-signatures with the keys.  */
 void
 merge_keys_and_selfsig (KBNODE keyblock)
 /* Merge all self-signatures with the keys.  */
 void
 merge_keys_and_selfsig (KBNODE keyblock)
@@ -1276,13 +1347,19 @@ parse_key_usage (PKT_signature * sig)
 
       if (flags)
        key_usage |= PUBKEY_USAGE_UNKNOWN;
 
       if (flags)
        key_usage |= PUBKEY_USAGE_UNKNOWN;
+
+      if (!key_usage)
+       key_usage |= PUBKEY_USAGE_NONE;
     }
     }
+  else if (p) /* Key flags of length zero.  */
+    key_usage |= PUBKEY_USAGE_NONE;
 
   /* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a
      capability that we do not handle.  This serves to distinguish
      between a zero key usage which we handle as the default
      capabilities for that algorithm, and a usage that we do not
 
   /* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a
      capability that we do not handle.  This serves to distinguish
      between a zero key usage which we handle as the default
      capabilities for that algorithm, and a usage that we do not
-     handle. */
+     handle.  Likewise we use PUBKEY_USAGE_NONE to indicate that
+     key_flags have been given but they do not specify any usage.  */
 
   return key_usage;
 }
 
   return key_usage;
 }
@@ -2450,7 +2527,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
   int no_suitable_key = 0;
 
   rc = 0;
   int no_suitable_key = 0;
 
   rc = 0;
-  while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems)))
+  while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems, NULL)))
     {
       /* If we are searching for the first key we have to make sure
          that the next iteration does not do an implicit reset.
     {
       /* If we are searching for the first key we have to make sure
          that the next iteration does not do an implicit reset.
@@ -2488,7 +2565,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
     }
 
 found:
     }
 
 found:
-  if (rc && rc != -1)
+  if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
     log_error ("keydb_search failed: %s\n", g10_errstr (rc));
 
   if (!rc)
     log_error ("keydb_search failed: %s\n", g10_errstr (rc));
 
   if (!rc)
@@ -2496,9 +2573,9 @@ found:
       *ret_keyblock = ctx->keyblock; /* Return the keyblock.  */
       ctx->keyblock = NULL;
     }
       *ret_keyblock = ctx->keyblock; /* Return the keyblock.  */
       ctx->keyblock = NULL;
     }
-  else if (rc == -1 && no_suitable_key)
+  else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key)
     rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY;
     rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY;
-  else if (rc == -1)
+  else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY;
 
   release_kbnode (ctx->keyblock);
     rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY;
 
   release_kbnode (ctx->keyblock);
@@ -2633,11 +2710,10 @@ enum_secret_keys (void **context, PKT_public_key *sk)
 
 /* Return a string with a printable representation of the user_id.
  * this string must be freed by xfree.   */
 
 /* Return a string with a printable representation of the user_id.
  * this string must be freed by xfree.   */
-char *
+static char *
 get_user_id_string (u32 * keyid)
 {
   user_id_db_t r;
 get_user_id_string (u32 * keyid)
 {
   user_id_db_t r;
-  char *p;
   int pass = 0;
   /* Try it two times; second pass reads from key resources.  */
   do
   int pass = 0;
   /* Try it two times; second pass reads from key resources.  */
   do
@@ -2649,17 +2725,13 @@ get_user_id_string (u32 * keyid)
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
-                 p = xmalloc (keystrlen () + 1 + r->len + 1);
-                 sprintf (p, "%s %.*s", keystr (keyid), r->len, r->name);
-                 return p;
+                 return xasprintf ("%s %.*s", keystr (keyid), r->len, r->name);
                }
            }
        }
     }
   while (++pass < 2 && !get_pubkey (NULL, keyid));
                }
            }
        }
     }
   while (++pass < 2 && !get_pubkey (NULL, keyid));
-  p = xmalloc (keystrlen () + 5);
-  sprintf (p, "%s [?]", keystr (keyid));
-  return p;
+  return xasprintf ("%s [?]", keystr (keyid));
 }
 
 
 }
 
 
@@ -2677,33 +2749,30 @@ char *
 get_long_user_id_string (u32 * keyid)
 {
   user_id_db_t r;
 get_long_user_id_string (u32 * keyid)
 {
   user_id_db_t r;
-  char *p;
+  keyid_list_t a;
   int pass = 0;
   /* Try it two times; second pass reads from key resources.  */
   do
     {
       for (r = user_id_db; r; r = r->next)
        {
   int pass = 0;
   /* Try it two times; second pass reads from key resources.  */
   do
     {
       for (r = user_id_db; r; r = r->next)
        {
-         keyid_list_t a;
          for (a = r->keyids; a; a = a->next)
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
          for (a = r->keyids; a; a = a->next)
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
-                 p = xmalloc (r->len + 20);
-                 sprintf (p, "%08lX%08lX %.*s",
-                          (ulong) keyid[0], (ulong) keyid[1],
-                          r->len, r->name);
-                 return p;
+                 return xasprintf ("%08lX%08lX %.*s",
+                                    (ulong) keyid[0], (ulong) keyid[1],
+                                    r->len, r->name);
                }
            }
        }
     }
   while (++pass < 2 && !get_pubkey (NULL, keyid));
                }
            }
        }
     }
   while (++pass < 2 && !get_pubkey (NULL, keyid));
-  p = xmalloc (25);
-  sprintf (p, "%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]);
-  return p;
+  return xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]);
 }
 
 }
 
+
+/* Please try to use get_user_id_native instead of this one.  */
 char *
 get_user_id (u32 * keyid, size_t * rn)
 {
 char *
 get_user_id (u32 * keyid, size_t * rn)
 {
@@ -2721,7 +2790,10 @@ get_user_id (u32 * keyid, size_t * rn)
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
-                 p = xmalloc (r->len);
+                  /* An empty string as user id is possible.  Make
+                     sure that the malloc allocates one byte and does
+                     not bail out.  */
+                 p = xmalloc (r->len? r->len : 1);
                  memcpy (p, r->name, r->len);
                  *rn = r->len;
                  return p;
                  memcpy (p, r->name, r->len);
                  *rn = r->len;
                  return p;
@@ -2735,6 +2807,7 @@ get_user_id (u32 * keyid, size_t * rn)
   return p;
 }
 
   return p;
 }
 
+/* Please try to use get_user_id_byfpr_native instead of this one.  */
 char *
 get_user_id_native (u32 * keyid)
 {
 char *
 get_user_id_native (u32 * keyid)
 {
@@ -2745,6 +2818,55 @@ get_user_id_native (u32 * keyid)
   return p2;
 }
 
   return p2;
 }
 
+
+/* Return a user id from the caching by looking it up using the FPR
+   which mustbe of size MAX_FINGERPRINT_LEN.  */
+char *
+get_user_id_byfpr (const byte *fpr, size_t *rn)
+{
+  user_id_db_t r;
+  char *p;
+  int pass = 0;
+
+  /* Try it two times; second pass reads from key resources.  */
+  do
+    {
+      for (r = user_id_db; r; r = r->next)
+       {
+         keyid_list_t a;
+         for (a = r->keyids; a; a = a->next)
+           {
+             if (!memcmp (a->fpr, fpr, MAX_FINGERPRINT_LEN))
+               {
+                  /* An empty string as user id is possible.  Make
+                     sure that the malloc allocates one byte and does
+                     not bail out.  */
+                 p = xmalloc (r->len? r->len : 1);
+                 memcpy (p, r->name, r->len);
+                 *rn = r->len;
+                 return p;
+               }
+           }
+       }
+    }
+  while (++pass < 2 && !get_pubkey_byfpr (NULL, fpr));
+  p = xstrdup (user_id_not_found_utf8 ());
+  *rn = strlen (p);
+  return p;
+}
+
+char *
+get_user_id_byfpr_native (const byte *fpr)
+{
+  size_t rn;
+  char *p = get_user_id_byfpr (fpr, &rn);
+  char *p2 = utf8_to_native (p, rn, 0);
+  xfree (p);
+  return p2;
+}
+
+
+
 KEYDB_HANDLE
 get_ctx_handle (GETKEY_CTX ctx)
 {
 KEYDB_HANDLE
 get_ctx_handle (GETKEY_CTX ctx)
 {
@@ -2787,7 +2909,14 @@ parse_auto_key_locate (char *options)
 
       akl = xmalloc_clear (sizeof (*akl));
 
 
       akl = xmalloc_clear (sizeof (*akl));
 
-      if (ascii_strcasecmp (tok, "nodefault") == 0)
+      if (ascii_strcasecmp (tok, "clear") == 0)
+       {
+          xfree (akl);
+          free_akl (opt.auto_key_locate);
+          opt.auto_key_locate = NULL;
+          continue;
+        }
+      else if (ascii_strcasecmp (tok, "nodefault") == 0)
        akl->type = AKL_NODEFAULT;
       else if (ascii_strcasecmp (tok, "local") == 0)
        akl->type = AKL_LOCAL;
        akl->type = AKL_NODEFAULT;
       else if (ascii_strcasecmp (tok, "local") == 0)
        akl->type = AKL_LOCAL;
@@ -2875,9 +3004,8 @@ have_secret_key_with_kid (u32 *keyid)
   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
   desc.u.kid[0] = keyid[0];
   desc.u.kid[1] = keyid[1];
   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
   desc.u.kid[0] = keyid[0];
   desc.u.kid[1] = keyid[1];
-  while (!result && !(err = keydb_search (kdbhd, &desc, 1)))
+  while (!result && !(err = keydb_search (kdbhd, &desc, 1, NULL)))
     {
     {
-      desc.mode = KEYDB_SEARCH_MODE_NEXT;
       err = keydb_get_keyblock (kdbhd, &keyblock);
       if (err)
         {
       err = keydb_get_keyblock (kdbhd, &keyblock);
       if (err)
         {
@@ -2906,146 +3034,3 @@ have_secret_key_with_kid (u32 *keyid)
   keydb_release (kdbhd);
   return result;
 }
   keydb_release (kdbhd);
   return result;
 }
-
-
-
-#if 0
-/*
- * Merge the secret keys from secblock into the pubblock thereby
- * replacing the public (sub)keys with their secret counterparts Hmmm:
- * It might be better to get away from the concept of entire secret
- * keys at all and have a way to store just the real secret parts
- * from the key.
- *
- * FIXME: this is not anymore needed but we keep it as example code for the
- * new code we need to write for the import/export feature.
- */
-static void
-merge_public_with_secret (KBNODE pubblock, KBNODE secblock)
-{
-  KBNODE pub;
-
-  assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY);
-  assert (secblock->pkt->pkttype == PKT_SECRET_KEY);
-
-  for (pub = pubblock; pub; pub = pub->next)
-    {
-      if (pub->pkt->pkttype == PKT_PUBLIC_KEY)
-       {
-         PKT_public_key *pk = pub->pkt->pkt.public_key;
-         PKT_secret_key *sk = secblock->pkt->pkt.secret_key;
-         assert (pub == pubblock); /* Only in the first node.  */
-         /* There is nothing to compare in this case, so just replace
-          * some information.  */
-         copy_public_parts_to_secret_key (pk, sk);
-         free_public_key (pk);
-         pub->pkt->pkttype = PKT_SECRET_KEY;
-         pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk);
-       }
-      else if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY)
-       {
-         KBNODE sec;
-         PKT_public_key *pk = pub->pkt->pkt.public_key;
-
-         /* This is more complicated: It may happen that the sequence
-          * of the subkeys dosn't match, so we have to find the
-          * appropriate secret key.  */
-         for (sec = secblock->next; sec; sec = sec->next)
-           {
-             if (sec->pkt->pkttype == PKT_SECRET_SUBKEY)
-               {
-                 PKT_secret_key *sk = sec->pkt->pkt.secret_key;
-                 if (!cmp_public_secret_key (pk, sk))
-                   {
-                     copy_public_parts_to_secret_key (pk, sk);
-                     free_public_key (pk);
-                     pub->pkt->pkttype = PKT_SECRET_SUBKEY;
-                     pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk);
-                     break;
-                   }
-               }
-           }
-         if (!sec)
-           BUG (); /* Already checked in premerge.  */
-       }
-    }
-}
-
-
-/* This function checks that for every public subkey a corresponding
- * secret subkey is available and deletes the public subkey otherwise.
- * We need this function because we can't delete it later when we
- * actually merge the secret parts into the pubring.
- * The function also plays some games with the node flags.
- *
- * FIXME: this is not anymore needed but we keep it as example code for the
- * new code we need to write for the import/export feature.
- */
-static void
-premerge_public_with_secret (KBNODE pubblock, KBNODE secblock)
-{
-  KBNODE last, pub;
-
-  assert (pubblock->pkt->pkttype == PKT_PUBLIC_KEY);
-  assert (secblock->pkt->pkttype == PKT_SECRET_KEY);
-
-  for (pub = pubblock, last = NULL; pub; last = pub, pub = pub->next)
-    {
-      pub->flag &= ~3; /* Reset bits 0 and 1.  */
-      if (pub->pkt->pkttype == PKT_PUBLIC_SUBKEY)
-       {
-         KBNODE sec;
-         PKT_public_key *pk = pub->pkt->pkt.public_key;
-
-         for (sec = secblock->next; sec; sec = sec->next)
-           {
-             if (sec->pkt->pkttype == PKT_SECRET_SUBKEY)
-               {
-                 PKT_secret_key *sk = sec->pkt->pkt.secret_key;
-                 if (!cmp_public_secret_key (pk, sk))
-                   {
-                     if (sk->protect.s2k.mode == 1001)
-                       {
-                         /* The secret parts are not available so
-                            we can't use that key for signing etc.
-                            Fix the pubkey usage */
-                         pk->pubkey_usage &= ~(PUBKEY_USAGE_SIG
-                                               | PUBKEY_USAGE_AUTH);
-                       }
-                     /* Transfer flag bits 0 and 1 to the pubblock.  */
-                     pub->flag |= (sec->flag & 3);
-                     break;
-                   }
-               }
-           }
-         if (!sec)
-           {
-             KBNODE next, ll;
-
-             if (opt.verbose)
-               log_info (_("no secret subkey"
-                           " for public subkey %s - ignoring\n"),
-                         keystr_from_pk (pk));
-             /* We have to remove the subkey in this case.  */
-             assert (last);
-             /* Find the next subkey.  */
-             for (next = pub->next, ll = pub;
-                  next && next->pkt->pkttype != PKT_PUBLIC_SUBKEY;
-                  ll = next, next = next->next)
-               ;
-             /* Make new link.  */
-             last->next = next;
-             /* Release this public subkey with all sigs.  */
-             ll->next = NULL;
-             release_kbnode (pub);
-             /* Let the loop continue.  */
-             pub = last;
-           }
-       }
-    }
-  /* We need to copy the found bits (0 and 1) from the secret key to
-     the public key.  This has already been done for the subkeys but
-     got lost on the primary key - fix it here.  */
-  pubblock->flag |= (secblock->flag & 3);
-}
-#endif /*0*/