gpg: Don't forget to free some memory.
[gnupg.git] / g10 / keyring.c
index 9ef5b1b..81d2174 100644 (file)
@@ -1,11 +1,12 @@
 /* keyring.c - keyring file handling
- * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2010 Free Software Foundation, Inc.
+ * Copyright (C) 1997-2015 Werner Koch
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,9 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include "gpg.h"
 #include "util.h"
 #include "keyring.h"
 #include "packet.h"
-#include "keydb.h" 
+#include "keydb.h"
 #include "options.h"
 #include "main.h" /*for check_key_signature()*/
 #include "i18n.h"
@@ -47,14 +47,15 @@ struct off_item {
   /*off_t off;*/
 };
 
-typedef struct off_item **OffsetHashTable; 
+typedef struct off_item **OffsetHashTable;
 
 
 typedef struct keyring_name *KR_NAME;
-struct keyring_name {
+struct keyring_name
+{
   struct keyring_name *next;
-  int secret;
-  DOTLOCK lockhd;
+  int read_only;
+  dotlock_t lockhd;
   int is_locked;
   int did_full_scan;
   char fname[1];
@@ -68,9 +69,9 @@ static OffsetHashTable kr_offtbl;
 static int kr_offtbl_ready;
 
 
-struct keyring_handle {
+struct keyring_handle
+{
   CONST_KR_NAME resource;
-  int secret;             /* this is for a secret keyring */
   struct {
     CONST_KR_NAME kr;
     IOBUF iobuf;
@@ -78,12 +79,12 @@ struct keyring_handle {
     int error;
   } current;
   struct {
-    CONST_KR_NAME kr; 
+    CONST_KR_NAME kr;
     off_t offset;
     size_t pk_no;
     size_t uid_no;
     unsigned int n_packets; /*used for delete and update*/
-  } found;
+  } found, saved_found;
   struct {
     char *name;
     char *pattern;
@@ -92,7 +93,7 @@ struct keyring_handle {
 
 
 
-static int do_copy (int mode, const char *fname, KBNODE root, int secret,
+static int do_copy (int mode, const char *fname, KBNODE root,
                     off_t start_offset, unsigned int n_packets );
 
 
@@ -101,7 +102,7 @@ static struct off_item *
 new_offset_item (void)
 {
   struct off_item *k;
-  
+
   k = xmalloc_clear (sizeof *k);
   return k;
 }
@@ -120,7 +121,7 @@ release_offset_items (struct off_item *k)
 }
 #endif
 
-static OffsetHashTable 
+static OffsetHashTable
 new_offset_hash_table (void)
 {
   struct off_item **tbl;
@@ -159,9 +160,11 @@ update_offset_hash_table (OffsetHashTable tbl, u32 *kid, off_t off)
 {
   struct off_item *k;
 
+  (void)off;
+
   for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next)
     {
-      if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) 
+      if (k->kid[0] == kid[0] && k->kid[1] == kid[1])
         {
           /*k->off = off;*/
           return;
@@ -191,14 +194,14 @@ update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off)
     }
 }
 
-/* 
+/*
  * Register a filename for plain keyring files.  ptr is set to a
  * pointer to be used to create a handles etc, or the already-issued
  * pointer if it has already been registered.  The function returns 1
  * if a new keyring was registered.
 */
 int
-keyring_register_filename (const char *fname, int secret, void **ptr)
+keyring_register_filename (const char *fname, int read_only, void **ptr)
 {
     KR_NAME kr;
 
@@ -207,19 +210,19 @@ keyring_register_filename (const char *fname, int secret, void **ptr)
 
     for (kr=kr_names; kr; kr = kr->next)
       {
-        if ( !compare_filenames (kr->fname, fname) )
+        if (same_file_p (kr->fname, fname))
          {
+            /* Already registered. */
+            if (read_only)
+              kr->read_only = 1;
             *ptr=kr;
-           return 0; /* already registered */
+           return 0;
          }
       }
 
-    if (secret)
-      register_secured_file (fname);
-
     kr = xmalloc (sizeof *kr + strlen (fname));
     strcpy (kr->fname, fname);
-    kr->secret = !!secret;
+    kr->read_only = read_only;
     kr->lockhd = NULL;
     kr->is_locked = 0;
     kr->did_full_scan = 0;
@@ -241,31 +244,29 @@ keyring_is_writable (void *token)
 {
   KR_NAME r = token;
 
-  return r? !access (r->fname, W_OK) : 0;
+  return r? (r->read_only || !access (r->fname, W_OK)) : 0;
 }
-    
+
 
 \f
-/* Create a new handle for the resource associated with TOKEN.  SECRET
-   is just just as a cross-check.
-   
+/* Create a new handle for the resource associated with TOKEN.
+
    The returned handle must be released using keyring_release (). */
 KEYRING_HANDLE
-keyring_new (void *token, int secret)
+keyring_new (void *token)
 {
   KEYRING_HANDLE hd;
   KR_NAME resource = token;
 
-  assert (resource && !resource->secret == !secret);
-  
+  assert (resource);
+
   hd = xmalloc_clear (sizeof *hd);
   hd->resource = resource;
-  hd->secret = !!secret;
   active_handles++;
   return hd;
 }
 
-void 
+void
 keyring_release (KEYRING_HANDLE hd)
 {
     if (!hd)
@@ -279,6 +280,25 @@ keyring_release (KEYRING_HANDLE hd)
 }
 
 
+/* Save the current found state in HD for later retrieval by
+   keybox_pop_found_state.  Only one state may be saved.  */
+void
+keyring_push_found_state (KEYRING_HANDLE hd)
+{
+  hd->saved_found = hd->found;
+  hd->found.kr = NULL;
+}
+
+
+/* Restore the saved found state in HD.  */
+void
+keyring_pop_found_state (KEYRING_HANDLE hd)
+{
+  hd->found = hd->saved_found;
+  hd->saved_found.kr = NULL;
+}
+
+
 const char *
 keyring_get_resource_name (KEYRING_HANDLE hd)
 {
@@ -289,42 +309,44 @@ keyring_get_resource_name (KEYRING_HANDLE hd)
 
 
 /*
- * Lock the keyring with the given handle, or unlok if yes is false.
+ * Lock the keyring with the given handle, or unlock if YES is false.
  * We ignore the handle and lock all registered files.
  */
-int 
+int
 keyring_lock (KEYRING_HANDLE hd, int yes)
 {
     KR_NAME kr;
     int rc = 0;
 
+    (void)hd;
+
     if (yes) {
         /* first make sure the lock handles are created */
         for (kr=kr_names; kr; kr = kr->next) {
             if (!keyring_is_writable(kr))
                 continue;
             if (!kr->lockhd) {
-                kr->lockhd = create_dotlock( kr->fname );
+                kr->lockhd = dotlock_create (kr->fname, 0);
                 if (!kr->lockhd) {
-                    log_info ("can't allocate lock for `%s'\n", kr->fname );
-                    rc = G10ERR_GENERAL;
+                    log_info ("can't allocate lock for '%s'\n", kr->fname );
+                    rc = GPG_ERR_GENERAL;
                 }
             }
         }
         if (rc)
             return rc;
-        
+
         /* and now set the locks */
         for (kr=kr_names; kr; kr = kr->next) {
             if (!keyring_is_writable(kr))
                 continue;
             if (kr->is_locked)
                 ;
-            else if (make_dotlock (kr->lockhd, -1) ) {
-                log_info ("can't lock `%s'\n", kr->fname );
-                rc = G10ERR_GENERAL;
+            else if (dotlock_take (kr->lockhd, -1) ) {
+                log_info ("can't lock '%s'\n", kr->fname );
+                rc = GPG_ERR_GENERAL;
             }
-            else 
+            else
                 kr->is_locked = 1;
         }
     }
@@ -335,12 +357,12 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
                 continue;
             if (!kr->is_locked)
                 ;
-            else if (release_dotlock (kr->lockhd))
-                log_info ("can't unlock `%s'\n", kr->fname );
-            else 
+            else if (dotlock_release (kr->lockhd))
+                log_info ("can't unlock '%s'\n", kr->fname );
+            else
                 kr->is_locked = 0;
         }
-    } 
+    }
 
     return rc;
 }
@@ -348,9 +370,9 @@ keyring_lock (KEYRING_HANDLE hd, int yes)
 
 \f
 /*
- * Return the last found keyring.  Caller must free it.
+ * Return the last found keyblock.  Caller must free it.
  * The returned keyblock has the kbode flag bit 0 set for the node with
- * the public key used to locate the keyblock or flag bit 1 set for 
+ * the public key used to locate the keyblock or flag bit 1 set for
  * the user ID node.
  */
 int
@@ -374,14 +396,14 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     a = iobuf_open (hd->found.kr->fname);
     if (!a)
       {
-       log_error(_("can't open `%s'\n"), hd->found.kr->fname);
-       return G10ERR_KEYRING_OPEN;
+       log_error(_("can't open '%s'\n"), hd->found.kr->fname);
+       return GPG_ERR_KEYRING_OPEN;
       }
 
     if (iobuf_seek (a, hd->found.offset) ) {
-        log_error ("can't seek `%s'\n", hd->found.kr->fname);
+        log_error ("can't seek '%s'\n", hd->found.kr->fname);
        iobuf_close(a);
-       return G10ERR_KEYRING_OPEN;
+       return GPG_ERR_KEYRING_OPEN;
     }
 
     pkt = xmalloc (sizeof *pkt);
@@ -391,23 +413,44 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     save_mode = set_packet_list_mode(0);
     while ((rc=parse_packet (a, pkt)) != -1) {
         hd->found.n_packets++;
-        if (rc == G10ERR_UNKNOWN_PACKET) {
+        if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
            free_packet (pkt);
            init_packet (pkt);
            continue;
        }
-       if (rc) {  
+        if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
+          break;  /* Upper layer needs to handle this.  */
+       if (rc) {
             log_error ("keyring_get_keyblock: read error: %s\n",
-                       g10_errstr(rc) );
-            rc = G10ERR_INV_KEYRING;
+                       gpg_strerror (rc) );
+            rc = GPG_ERR_INV_KEYRING;
             break;
         }
-       if (pkt->pkttype == PKT_COMPRESSED) {
-           log_error ("skipped compressed packet in keyring\n");
+
+        /* Filter allowed packets.  */
+        switch (pkt->pkttype)
+          {
+          case PKT_PUBLIC_KEY:
+          case PKT_PUBLIC_SUBKEY:
+          case PKT_SECRET_KEY:
+          case PKT_SECRET_SUBKEY:
+          case PKT_USER_ID:
+          case PKT_ATTRIBUTE:
+          case PKT_SIGNATURE:
+            break; /* Allowed per RFC.  */
+          case PKT_RING_TRUST:
+          case PKT_OLD_COMMENT:
+          case PKT_COMMENT:
+          case PKT_GPG_CONTROL:
+            break; /* Allowed by us.  */
+
+          default:
+           log_error ("skipped packet of type %d in keyring\n",
+                       (int)pkt->pkttype);
            free_packet(pkt);
            init_packet(pkt);
            continue;
-        }
+          }
 
         if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
                         || pkt->pkttype == PKT_SECRET_KEY)) {
@@ -416,57 +459,67 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
         }
 
         in_cert = 1;
-        if (pkt->pkttype == PKT_RING_TRUST) {
+        if (pkt->pkttype == PKT_RING_TRUST)
+          {
             /*(this code is duplicated after the loop)*/
-            if ( lastnode 
+            if ( lastnode
                  && lastnode->pkt->pkttype == PKT_SIGNATURE
                  && (pkt->pkt.ring_trust->sigcache & 1) ) {
-                /* this is a ring trust packet with a checked signature 
+                /* This is a ring trust packet with a checked signature
                  * status cache following directly a signature paket.
-                 * Set the cache status into that signature packet */
+                 * Set the cache status into that signature packet */
                 PKT_signature *sig = lastnode->pkt->pkt.signature;
-                
+
                 sig->flags.checked = 1;
                 sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
             }
-            /* reset lastnode, so that we set the cache status only from
-             * the ring trust packet immediately folling a signature */
+            /* Reset LASTNODE, so that we set the cache status only from
+             * the ring trust packet immediately following a signature. */
             lastnode = NULL;
-        }
-        else {
-            node = lastnode = new_kbnode (pkt);
-            if (!keyblock)
-                keyblock = node;
-            else
-                add_kbnode (keyblock, node);
-
-            if ( pkt->pkttype == PKT_PUBLIC_KEY
-                 || pkt->pkttype == PKT_PUBLIC_SUBKEY
-                 || pkt->pkttype == PKT_SECRET_KEY
-                 || pkt->pkttype == PKT_SECRET_SUBKEY) {
-                if (++pk_no == hd->found.pk_no)
-                    node->flag |= 1;
-            }
-            else if ( pkt->pkttype == PKT_USER_ID) {
-                if (++uid_no == hd->found.uid_no)
-                    node->flag |= 2;
-            }
-        }
+           free_packet(pkt);
+           init_packet(pkt);
+           continue;
+          }
+
+
+        node = lastnode = new_kbnode (pkt);
+        if (!keyblock)
+          keyblock = node;
+        else
+          add_kbnode (keyblock, node);
+        switch (pkt->pkttype)
+          {
+          case PKT_PUBLIC_KEY:
+          case PKT_PUBLIC_SUBKEY:
+          case PKT_SECRET_KEY:
+          case PKT_SECRET_SUBKEY:
+            if (++pk_no == hd->found.pk_no)
+              node->flag |= 1;
+            break;
+
+          case PKT_USER_ID:
+            if (++uid_no == hd->found.uid_no)
+              node->flag |= 2;
+            break;
+
+          default:
+            break;
+          }
 
         pkt = xmalloc (sizeof *pkt);
         init_packet(pkt);
     }
     set_packet_list_mode(save_mode);
 
-    if (rc == -1 && keyblock) 
+    if (rc == -1 && keyblock)
        rc = 0; /* got the entire keyblock */
 
     if (rc || !ret_kb)
        release_kbnode (keyblock);
     else {
-        /*(duplicated form the loop body)*/
+        /*(duplicated from the loop body)*/
         if ( pkt && pkt->pkttype == PKT_RING_TRUST
-             && lastnode 
+             && lastnode
              && lastnode->pkt->pkttype == PKT_SIGNATURE
              && (pkt->pkt.ring_trust->sigcache & 1) ) {
             PKT_signature *sig = lastnode->pkt->pkt.signature;
@@ -480,9 +533,9 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     iobuf_close(a);
 
     /* Make sure that future search operations fail immediately when
-     * we know that we are working on a invalid keyring 
+     * we know that we are working on a invalid keyring
      */
-    if (rc == G10ERR_INV_KEYRING)
+    if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING)
         hd->current.error = rc;
 
     return rc;
@@ -496,11 +549,14 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     if (!hd->found.kr)
         return -1; /* no successful prior search */
 
+    if (hd->found.kr->read_only)
+      return gpg_error (GPG_ERR_EACCES);
+
     if (!hd->found.n_packets) {
         /* need to know the number of packets - do a dummy get_keyblock*/
         rc = keyring_get_keyblock (hd, NULL);
         if (rc) {
-            log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
+            log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
             return rc;
         }
         if (!hd->found.n_packets)
@@ -514,10 +570,10 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     hd->current.iobuf = NULL;
 
     /* do the update */
-    rc = do_copy (3, hd->found.kr->fname, kb, hd->secret,
+    rc = do_copy (3, hd->found.kr->fname, kb,
                   hd->found.offset, hd->found.n_packets );
     if (!rc) {
-      if (!hd->secret && kr_offtbl)
+      if (kr_offtbl)
         {
           update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
         }
@@ -537,16 +593,24 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     if (!hd)
         fname = NULL;
     else if (hd->found.kr)
+      {
         fname = hd->found.kr->fname;
+        if (hd->found.kr->read_only)
+          return gpg_error (GPG_ERR_EACCES);
+      }
     else if (hd->current.kr)
+      {
         fname = hd->current.kr->fname;
-    else 
+        if (hd->current.kr->read_only)
+          return gpg_error (GPG_ERR_EACCES);
+      }
+    else
         fname = hd->resource? hd->resource->fname:NULL;
 
     if (!fname)
-        return G10ERR_GENERAL; 
+        return GPG_ERR_GENERAL;
 
-    /* close this one otherwise we will lose the position for
+    /* Close this one otherwise we will lose the position for
      * a next search.  Fixme: it would be better to adjust the position
      * after the write opertions.
      */
@@ -554,12 +618,12 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     hd->current.iobuf = NULL;
 
     /* do the insert */
-    rc = do_copy (1, fname, kb, hd->secret, 0, 0 );
-    if (!rc && !hd->secret && kr_offtbl)
+    rc = do_copy (1, fname, kb, 0, 0 );
+    if (!rc && kr_offtbl)
       {
         update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
       }
-      
+
     return rc;
 }
 
@@ -572,11 +636,14 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
     if (!hd->found.kr)
         return -1; /* no successful prior search */
 
+    if (hd->found.kr->read_only)
+      return gpg_error (GPG_ERR_EACCES);
+
     if (!hd->found.n_packets) {
         /* need to know the number of packets - do a dummy get_keyblock*/
         rc = keyring_get_keyblock (hd, NULL);
         if (rc) {
-            log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc));
+            log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
             return rc;
         }
         if (!hd->found.n_packets)
@@ -591,7 +658,7 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
     hd->current.iobuf = NULL;
 
     /* do the delete */
-    rc = do_copy (2, hd->found.kr->fname, NULL, hd->secret,
+    rc = do_copy (2, hd->found.kr->fname, NULL,
                   hd->found.offset, hd->found.n_packets );
     if (!rc) {
         /* better reset the found info */
@@ -605,10 +672,10 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
 
 
 \f
-/* 
+/*
  * Start the next search on this handle right at the beginning
  */
-int 
+int
 keyring_search_reset (KEYRING_HANDLE hd)
 {
     assert (hd);
@@ -618,26 +685,32 @@ keyring_search_reset (KEYRING_HANDLE hd)
     hd->current.iobuf = NULL;
     hd->current.eof = 0;
     hd->current.error = 0;
-    
+
     hd->found.kr = NULL;
     hd->found.offset = 0;
-    return 0; 
+    return 0;
 }
 
 
 static int
 prepare_search (KEYRING_HANDLE hd)
 {
-    if (hd->current.error)  
-        return hd->current.error; /* still in error state */
+    if (hd->current.error) {
+        /* If the last key was a legacy key, we simply ignore the error so that
+           we can easily use search_next.  */
+        if (gpg_err_code (hd->current.error) == GPG_ERR_LEGACY_KEY)
+            hd->current.error = 0;
+        else
+            return hd->current.error; /* still in error state */
+    }
 
     if (hd->current.kr && !hd->current.eof) {
         if ( !hd->current.iobuf )
-            return G10ERR_GENERAL; /* position invalid after a modify */
+            return GPG_ERR_GENERAL; /* Position invalid after a modify.  */
         return 0; /* okay */
     }
 
-    if (!hd->current.kr && hd->current.eof)  
+    if (!hd->current.kr && hd->current.eof)
         return -1; /* still EOF */
 
     if (!hd->current.kr) { /* start search with first keyring */
@@ -649,7 +722,7 @@ prepare_search (KEYRING_HANDLE hd)
         assert (!hd->current.iobuf);
     }
     else { /* EOF */
-        iobuf_close (hd->current.iobuf); 
+        iobuf_close (hd->current.iobuf);
         hd->current.iobuf = NULL;
         hd->current.kr = NULL;
         hd->current.eof = 1;
@@ -660,8 +733,9 @@ prepare_search (KEYRING_HANDLE hd)
     hd->current.iobuf = iobuf_open (hd->current.kr->fname);
     if (!hd->current.iobuf)
       {
-        log_error(_("can't open `%s'\n"), hd->current.kr->fname );
-        return (hd->current.error = G10ERR_OPEN_FILE);
+        hd->current.error = gpg_error_from_syserror ();
+        log_error(_("can't open '%s'\n"), hd->current.kr->fname );
+        return hd->current.error;
       }
 
     return 0;
@@ -806,7 +880,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
     int i;
     const char *s, *se;
 
-    if (mode == KEYDB_SEARCH_MODE_EXACT) { 
+    if (mode == KEYDB_SEARCH_MODE_EXACT) {
        for (i=0; name[i] && uidlen; i++, uidlen--)
            if (uid[i] != name[i])
                break;
@@ -817,7 +891,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
        if (ascii_memistr( uid, uidlen, name ))
            return 0;
     }
-    else if (   mode == KEYDB_SEARCH_MODE_MAIL 
+    else if (   mode == KEYDB_SEARCH_MODE_MAIL
              || mode == KEYDB_SEARCH_MODE_MAILSUB
              || mode == KEYDB_SEARCH_MODE_MAILEND) {
        for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++)
@@ -829,7 +903,7 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
                ;
            if (i < uidlen) {
                i = se - s;
-               if (mode == KEYDB_SEARCH_MODE_MAIL) { 
+               if (mode == KEYDB_SEARCH_MODE_MAIL) {
                    if( strlen(name)-2 == i
                         && !ascii_memcasecmp( s, name+1, i) )
                        return 0;
@@ -853,11 +927,11 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen)
 }
 
 \f
-/* 
+/*
  * Search through the keyring(s), starting at the current position,
  * for a keyblock which contains one of the keys described in the DESC array.
  */
-int 
+int
 keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
                size_t ndesc, size_t *descindex)
 {
@@ -872,33 +946,32 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   int use_offtbl;
   PKT_user_id *uid = NULL;
   PKT_public_key *pk = NULL;
-  PKT_secret_key *sk = NULL;
   u32 aki[2];
 
   /* figure out what information we need */
   need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
-  for (n=0; n < ndesc; n++) 
+  for (n=0; n < ndesc; n++)
     {
-      switch (desc[n].mode) 
+      switch (desc[n].mode)
         {
-        case KEYDB_SEARCH_MODE_EXACT: 
+        case KEYDB_SEARCH_MODE_EXACT:
         case KEYDB_SEARCH_MODE_SUBSTR:
         case KEYDB_SEARCH_MODE_MAIL:
         case KEYDB_SEARCH_MODE_MAILSUB:
         case KEYDB_SEARCH_MODE_MAILEND:
           need_uid = 1;
           break;
-        case KEYDB_SEARCH_MODE_WORDS: 
+        case KEYDB_SEARCH_MODE_WORDS:
           need_uid = 1;
           need_words = 1;
           break;
-        case KEYDB_SEARCH_MODE_SHORT_KID: 
+        case KEYDB_SEARCH_MODE_SHORT_KID:
         case KEYDB_SEARCH_MODE_LONG_KID:
           need_keyid = 1;
           break;
-        case KEYDB_SEARCH_MODE_FPR16: 
+        case KEYDB_SEARCH_MODE_FPR16:
         case KEYDB_SEARCH_MODE_FPR20:
-        case KEYDB_SEARCH_MODE_FPR: 
+        case KEYDB_SEARCH_MODE_FPR:
           need_fpr = 1;
           break;
         case KEYDB_SEARCH_MODE_FIRST:
@@ -907,7 +980,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           break;
         default: break;
        }
-      if (desc[n].skipfnc) 
+      if (desc[n].skipfnc)
         {
           any_skip = 1;
           need_keyid = 1;
@@ -918,7 +991,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   if (rc)
     return rc;
 
-  use_offtbl = !hd->secret && kr_offtbl;
+  use_offtbl = !!kr_offtbl;
   if (!use_offtbl)
     ;
   else if (!kr_offtbl_ready)
@@ -926,7 +999,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
     {
       struct off_item *oi;
-            
+
       oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid);
       if (!oi)
         { /* We know that we don't have this key */
@@ -935,9 +1008,9 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           return -1;
         }
       /* We could now create a positive search status and return.
-       * However the problem is that another instance of gpg may 
+       * However the problem is that another instance of gpg may
        * have changed the keyring so that the offsets are not valid
-       * anymore - therefore we don't do it 
+       * anymore - therefore we don't do it
        */
     }
 
@@ -948,13 +1021,13 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       log_debug ("word search mode does not yet work\n");
       /* FIXME: here is a long standing bug in our function and in addition we
          just use the first search description */
-      for (n=0; n < ndesc && !name; n++) 
+      for (n=0; n < ndesc && !name; n++)
         {
-          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) 
+          if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS)
             name = desc[n].u.name;
         }
       assert (name);
-      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) 
+      if ( !hd->word_match.name || strcmp (hd->word_match.name, name) )
         {
           /* name changed */
           xfree (hd->word_match.name);
@@ -962,7 +1035,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           hd->word_match.name = xstrdup (name);
           hd->word_match.pattern = prepare_word_match (name);
         }
-      name = hd->word_match.pattern;
+      /*  name = hd->word_match.pattern; */
     }
 
   init_packet(&pkt);
@@ -972,28 +1045,29 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
   main_offset = 0;
   pk_no = uid_no = 0;
   initial_skip = 1; /* skip until we see the start of a keyblock */
-  while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid))) 
+  while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid)))
     {
       byte afp[MAX_FINGERPRINT_LEN];
       size_t an;
 
-      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY) 
+      if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY)
         {
           main_offset = offset;
           pk_no = uid_no = 0;
           initial_skip = 0;
         }
-      if (initial_skip) 
+      if (initial_skip)
         {
           free_packet (&pkt);
           continue;
         }
-       
+
       pk = NULL;
-      sk = NULL;
       uid = NULL;
       if (   pkt.pkttype == PKT_PUBLIC_KEY
-             || pkt.pkttype == PKT_PUBLIC_SUBKEY)
+             || pkt.pkttype == PKT_PUBLIC_SUBKEY
+             || pkt.pkttype == PKT_SECRET_KEY
+             || pkt.pkttype == PKT_SECRET_SUBKEY)
         {
           pk = pkt.pkt.public_key;
           ++pk_no;
@@ -1009,73 +1083,58 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
           if (use_offtbl && !kr_offtbl_ready)
             update_offset_hash_table (kr_offtbl, aki, main_offset);
         }
-      else if (pkt.pkttype == PKT_USER_ID) 
+      else if (pkt.pkttype == PKT_USER_ID)
         {
           uid = pkt.pkt.user_id;
           ++uid_no;
         }
-      else if (    pkt.pkttype == PKT_SECRET_KEY
-                   || pkt.pkttype == PKT_SECRET_SUBKEY) 
-        {
-          sk = pkt.pkt.secret_key;
-          ++pk_no;
 
-          if (need_fpr) {
-            fingerprint_from_sk (sk, afp, &an);
-            while (an < 20) /* fill up to 20 bytes */
-              afp[an++] = 0;
-          }
-          if (need_keyid)
-            keyid_from_sk (sk, aki);
-            
-        }
-
-      for (n=0; n < ndesc; n++) 
+      for (n=0; n < ndesc; n++)
         {
           switch (desc[n].mode) {
-          case KEYDB_SEARCH_MODE_NONE: 
+          case KEYDB_SEARCH_MODE_NONE:
             BUG ();
             break;
-          case KEYDB_SEARCH_MODE_EXACT: 
+          case KEYDB_SEARCH_MODE_EXACT:
           case KEYDB_SEARCH_MODE_SUBSTR:
           case KEYDB_SEARCH_MODE_MAIL:
           case KEYDB_SEARCH_MODE_MAILSUB:
           case KEYDB_SEARCH_MODE_MAILEND:
-          case KEYDB_SEARCH_MODE_WORDS: 
+          case KEYDB_SEARCH_MODE_WORDS:
             if ( uid && !compare_name (desc[n].mode,
                                        desc[n].u.name,
-                                       uid->name, uid->len)) 
+                                       uid->name, uid->len))
               goto found;
             break;
-                
-          case KEYDB_SEARCH_MODE_SHORT_KID: 
-            if ((pk||sk) && desc[n].u.kid[1] == aki[1])
+
+          case KEYDB_SEARCH_MODE_SHORT_KID:
+            if (pk && desc[n].u.kid[1] == aki[1])
               goto found;
             break;
           case KEYDB_SEARCH_MODE_LONG_KID:
-            if ((pk||sk) && desc[n].u.kid[0] == aki[0]
+            if (pk && desc[n].u.kid[0] == aki[0]
                 && desc[n].u.kid[1] == aki[1])
               goto found;
             break;
           case KEYDB_SEARCH_MODE_FPR16:
-            if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 16))
+            if (pk && !memcmp (desc[n].u.fpr, afp, 16))
               goto found;
             break;
           case KEYDB_SEARCH_MODE_FPR20:
-          case KEYDB_SEARCH_MODE_FPR: 
-            if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20))
+          case KEYDB_SEARCH_MODE_FPR:
+            if (pk && !memcmp (desc[n].u.fpr, afp, 20))
               goto found;
             break;
-          case KEYDB_SEARCH_MODE_FIRST: 
-            if (pk||sk)
+          case KEYDB_SEARCH_MODE_FIRST:
+            if (pk)
               goto found;
             break;
-          case KEYDB_SEARCH_MODE_NEXT: 
-            if (pk||sk)
+          case KEYDB_SEARCH_MODE_NEXT:
+            if (pk)
               goto found;
             break;
-          default: 
-            rc = G10ERR_INV_ARG;
+          default:
+            rc = GPG_ERR_INV_ARG;
             goto found;
           }
        }
@@ -1086,10 +1145,10 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         meaningful if this function returns with no errors. */
       if(descindex)
        *descindex=n;
-      for (n=any_skip?0:ndesc; n < ndesc; n++) 
+      for (n=any_skip?0:ndesc; n < ndesc; n++)
         {
           if (desc[n].skipfnc
-              && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid))
+              && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid_no))
             break;
         }
       if (n == ndesc)
@@ -1101,7 +1160,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
     {
       hd->found.offset = main_offset;
       hd->found.kr = hd->current.kr;
-      hd->found.pk_no = (pk||sk)? pk_no : 0;
+      hd->found.pk_no = pk? pk_no : 0;
       hd->found.uid_no = uid? uid_no : 0;
     }
   else if (rc == -1)
@@ -1112,12 +1171,11 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       if (use_offtbl && !kr_offtbl_ready)
         {
           KR_NAME kr;
-          
-          /* First set the did_full_scan flag for this keyring (ignore
-             secret keyrings) */
+
+          /* First set the did_full_scan flag for this keyring.  */
           for (kr=kr_names; kr; kr = kr->next)
             {
-              if (!kr->secret && hd->resource == kr) 
+              if (hd->resource == kr)
                 {
                   kr->did_full_scan = 1;
                   break;
@@ -1127,14 +1185,14 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
              offtbl ready */
           for (kr=kr_names; kr; kr = kr->next)
             {
-              if (!kr->secret && !kr->did_full_scan) 
+              if (!kr->did_full_scan)
                 break;
             }
           if (!kr)
             kr_offtbl_ready = 1;
         }
     }
-  else 
+  else
     hd->current.error = rc;
 
   free_packet(&pkt);
@@ -1146,7 +1204,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
 static int
 create_tmp_file (const char *template,
                  char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
-{  
+{
   char *bakfname, *tmpfname;
   mode_t oldmask;
 
@@ -1160,7 +1218,7 @@ create_tmp_file (const char *template,
    * works.  So we replace .gpg by .bak or .tmp
    */
   if (strlen (template) > 4
-      && !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") )
+      && !strcmp (template+strlen(template)-4, EXTSEP_S GPGEXT_GPG) )
     {
       bakfname = xmalloc (strlen (template) + 1);
       strcpy (bakfname, template);
@@ -1170,7 +1228,7 @@ create_tmp_file (const char *template,
       strcpy (tmpfname,template);
       strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
     }
-    else 
+    else
       { /* file does not end with gpg; hmmm */
        bakfname = xmalloc (strlen( template ) + 5);
        strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
@@ -1186,24 +1244,27 @@ create_tmp_file (const char *template,
     strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp");
 # endif /* Posix filename */
 
-    /* Create the temp file with limited access */
+    /* Create the temp file with limited access.  Note that the umask
+       call is not anymore needed because iobuf_create now takes care
+       of it.  However, it does not harm and thus we keep it.  */
     oldmask=umask(077);
     if (is_secured_filename (tmpfname))
       {
         *r_fp = NULL;
-        errno = EPERM;
+        gpg_err_set_errno (EPERM);
       }
     else
-      *r_fp = iobuf_create (tmpfname);
+      *r_fp = iobuf_create (tmpfname, 1);
     umask(oldmask);
     if (!*r_fp)
       {
-       log_error(_("can't create `%s': %s\n"), tmpfname, strerror(errno) );
+        int rc = gpg_error_from_syserror ();
+       log_error(_("can't create '%s': %s\n"), tmpfname, strerror(errno) );
         xfree (tmpfname);
         xfree (bakfname);
-       return G10ERR_OPEN_FILE;
+       return rc;
       }
-    
+
     *r_bakfname = bakfname;
     *r_tmpfname = tmpfname;
     return 0;
@@ -1211,51 +1272,42 @@ create_tmp_file (const char *template,
 
 
 static int
-rename_tmp_file (const char *bakfname, const char *tmpfname,
-                 const char *fname, int secret )
+rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname)
 {
-  int rc=0;
+  int rc = 0;
 
-  /* invalidate close caches*/
-  iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
-  iobuf_ioctl (NULL, 2, 0, (char*)bakfname );
-  iobuf_ioctl (NULL, 2, 0, (char*)fname );
+  /* Invalidate close caches.  */
+  if (iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ))
+    {
+      rc = gpg_error_from_syserror ();
+      goto fail;
+    }
+  iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname );
+  iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname );
 
-  /* first make a backup file except for secret keyrings */
-  if (!secret)
-    { 
+  /* First make a backup file. */
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-      remove (bakfname);
+  gnupg_remove (bakfname);
 #endif
-      if (rename (fname, bakfname) )
-        {
-          log_error ("renaming `%s' to `%s' failed: %s\n",
-                     fname, bakfname, strerror(errno) );
-          return G10ERR_RENAME_FILE;
-       }
+  if (rename (fname, bakfname) )
+    {
+      rc = gpg_error_from_syserror ();
+      log_error ("renaming '%s' to '%s' failed: %s\n",
+                 fname, bakfname, strerror(errno) );
+      return rc;
     }
-  
+
   /* then rename the file */
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
-  remove( fname );
+  gnupg_remove( fname );
 #endif
-  if (secret)
-    unregister_secured_file (fname);
   if (rename (tmpfname, fname) )
     {
-      log_error (_("renaming `%s' to `%s' failed: %s\n"),
+      rc = gpg_error_from_syserror ();
+      log_error (_("renaming '%s' to '%s' failed: %s\n"),
                  tmpfname, fname, strerror(errno) );
       register_secured_file (fname);
-      rc = G10ERR_RENAME_FILE;
-      if (secret)
-        {
-          log_info(_("WARNING: 2 files with confidential"
-                     " information exists.\n"));
-          log_info(_("%s is the unchanged one\n"), fname );
-          log_info(_("%s is the new one\n"), tmpfname );
-          log_info(_("Please fix this possible security flaw\n"));
-       }
-      return rc;
+      goto fail;
     }
 
   /* Now make sure the file has the same permissions as the original */
@@ -1266,17 +1318,18 @@ rename_tmp_file (const char *bakfname, const char *tmpfname,
 
     statbuf.st_mode=S_IRUSR | S_IWUSR;
 
-    if(((secret && !opt.preserve_permissions) ||
-       (stat(bakfname,&statbuf)==0)) &&
-       (chmod(fname,statbuf.st_mode)==0))
+    if (!stat (bakfname, &statbuf) && !chmod (fname, statbuf.st_mode))
       ;
     else
-      log_error("WARNING: unable to restore permissions to `%s': %s",
-               fname,strerror(errno));
+      log_error ("WARNING: unable to restore permissions to '%s': %s",
+                 fname, strerror(errno));
   }
 #endif
 
   return 0;
+
+ fail:
+  return rc;
 }
 
 
@@ -1285,24 +1338,24 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
 {
   KBNODE kbctx = NULL, node;
   int rc;
-  
-  while ( (node = walk_kbnode (keyblock, &kbctx, 0)) ) 
+
+  while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
     {
-      if (node->pkt->pkttype == PKT_RING_TRUST) 
+      if (node->pkt->pkttype == PKT_RING_TRUST)
         continue; /* we write it later on our own */
 
       if ( (rc = build_packet (fp, node->pkt) ))
         {
           log_error ("build_packet(%d) failed: %s\n",
-                     node->pkt->pkttype, g10_errstr(rc) );
+                     node->pkt->pkttype, gpg_strerror (rc) );
           return rc;
         }
-      if (node->pkt->pkttype == PKT_SIGNATURE) 
+      if (node->pkt->pkttype == PKT_SIGNATURE)
         { /* always write a signature cache packet */
           PKT_signature *sig = node->pkt->pkt.signature;
           unsigned int cacheval = 0;
-          
-          if (sig->flags.checked) 
+
+          if (sig->flags.checked)
             {
               cacheval |= 1;
               if (sig->flags.valid)
@@ -1311,16 +1364,18 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
           iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
           iobuf_put (fp, 2);    /* 2 bytes */
           iobuf_put (fp, 0);    /* unused */
-          if (iobuf_put (fp, cacheval)) {
-            log_error ("writing sigcache packet failed\n");
-            return G10ERR_WRITE_FILE;
-          }
+          if (iobuf_put (fp, cacheval))
+            {
+              rc = gpg_error_from_syserror ();
+              log_error ("writing sigcache packet failed\n");
+              return rc;
+            }
         }
     }
   return 0;
 }
 
-/* 
+/*
  * Walk over all public keyrings, check the signatures and replace the
  * keyring with a new one where the signature cache is then updated.
  * This is only done for the public keyrings.
@@ -1338,7 +1393,7 @@ keyring_rebuild_cache (void *token,int noisy)
   int rc;
   ulong count = 0, sigcount = 0;
 
-  hd = keyring_new (token, 0);
+  hd = keyring_new (token);
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
 
@@ -1346,8 +1401,12 @@ keyring_rebuild_cache (void *token,int noisy)
   if(rc)
     goto leave;
 
-  while ( !(rc = keyring_search (hd, &desc, 1, NULL)) )
+  for (;;)
     {
+      rc = keyring_search (hd, &desc, 1, NULL);
+      if (rc && gpg_err_code (rc) != GPG_ERR_LEGACY_KEY)
+        break;  /* ready.  */
+
       desc.mode = KEYDB_SEARCH_MODE_NEXT;
       resname = keyring_get_resource_name (hd);
       if (lastresname != resname )
@@ -1356,78 +1415,109 @@ keyring_rebuild_cache (void *token,int noisy)
             {
               if (iobuf_close (tmpfp))
                 {
-                  log_error ("error closing `%s': %s\n",
+                  rc = gpg_error_from_syserror ();
+                  log_error ("error closing '%s': %s\n",
                              tmpfilename, strerror (errno));
-                  rc = G10ERR_CLOSE_FILE;
                   goto leave;
                 }
               /* because we have switched resources, we can be sure that
                * the original file is closed */
               tmpfp = NULL;
             }
-          rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, 
-                                             lastresname, 0) : 0;
+          rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
+                                             lastresname) : 0;
           xfree (tmpfilename);  tmpfilename = NULL;
           xfree (bakfilename);  bakfilename = NULL;
           if (rc)
             goto leave;
           lastresname = resname;
           if (noisy && !opt.quiet)
-            log_info (_("caching keyring `%s'\n"), resname);
+            log_info (_("caching keyring '%s'\n"), resname);
           rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp);
           if (rc)
             goto leave;
         }
-      
+
+      if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
+        continue;
+
       release_kbnode (keyblock);
       rc = keyring_get_keyblock (hd, &keyblock);
-      if (rc) 
+      if (rc)
+        {
+          if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
+            continue;  /* Skip legacy keys.  */
+          log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc));
+          goto leave;
+        }
+      if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
         {
-          log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
+          /* We had a few reports about corrupted keyrings; if we have
+             been called directly from the command line we delete such
+             a keyblock instead of bailing out.  */
+          log_error ("unexpected keyblock found (pkttype=%d)%s\n",
+                     keyblock->pkt->pkttype, noisy? " - deleted":"");
+          if (noisy)
+            continue;
+          log_info ("Hint: backup your keys and try running '%s'\n",
+                    "gpg --rebuild-keydb-caches");
+          rc = gpg_error (GPG_ERR_INV_KEYRING);
           goto leave;
         }
-      assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
 
-      /* check all signature to set the signature's cache flags */
-      for (node=keyblock; node; node=node->next)
+      if (keyblock->pkt->pkt.public_key->version < 4)
         {
-         /* Note that this doesn't cache the result of a revocation
-            issued by a designated revoker.  This is because the pk
-            in question does not carry the revkeys as we haven't
-            merged the key and selfsigs.  It is questionable whether
-            this matters very much since there are very very few
-            designated revoker revocation packets out there. */
-
-          if (node->pkt->pkttype == PKT_SIGNATURE)
+          /* We do not copy/cache v3 keys or any other unknown
+             packets.  It is better to remove them from the keyring.
+             The code required to keep them in the keyring would be
+             too complicated.  Given that we do not touch the old
+             secring.gpg a suitable backup for decryption of v3 stuff
+             using an older gpg version will always be available.
+             Note: This test is actually superfluous because we
+             already acted upon GPG_ERR_LEGACY_KEY.      */
+        }
+      else
+        {
+          /* Check all signature to set the signature's cache flags. */
+          for (node=keyblock; node; node=node->next)
             {
-             PKT_signature *sig=node->pkt->pkt.signature;
+              /* Note that this doesn't cache the result of a
+                 revocation issued by a designated revoker.  This is
+                 because the pk in question does not carry the revkeys
+                 as we haven't merged the key and selfsigs.  It is
+                 questionable whether this matters very much since
+                 there are very very few designated revoker revocation
+                 packets out there. */
+              if (node->pkt->pkttype == PKT_SIGNATURE)
+                {
+                  PKT_signature *sig=node->pkt->pkt.signature;
 
-             if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid
-                && (check_digest_algo(sig->digest_algo)
-                    || check_pubkey_algo(sig->pubkey_algo)))
-               sig->flags.checked=sig->flags.valid=0;
-             else
-               check_key_signature (keyblock, node, NULL);
+                  if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid
+                     && (openpgp_md_test_algo(sig->digest_algo)
+                         || openpgp_pk_test_algo(sig->pubkey_algo)))
+                    sig->flags.checked=sig->flags.valid=0;
+                  else
+                    check_key_signature (keyblock, node, NULL);
 
-              sigcount++;
+                  sigcount++;
+                }
             }
-        }
-      
-      /* write the keyblock to the temporary file */
-      rc = write_keyblock (tmpfp, keyblock);
-      if (rc)
-        goto leave;
 
-      if ( !(++count % 50) && noisy && !opt.quiet)
-        log_info(_("%lu keys cached so far (%lu signatures)\n"),
-                 count, sigcount );
+          /* Write the keyblock to the temporary file.  */
+          rc = write_keyblock (tmpfp, keyblock);
+          if (rc)
+            goto leave;
 
-    } /* end main loop */ 
+          if ( !(++count % 50) && noisy && !opt.quiet)
+            log_info(_("%lu keys cached so far (%lu signatures)\n"),
+                     count, sigcount );
+        }
+    } /* end main loop */
   if (rc == -1)
     rc = 0;
-  if (rc) 
+  if (rc)
     {
-      log_error ("keyring_search failed: %s\n", g10_errstr(rc));
+      log_error ("keyring_search failed: %s\n", gpg_strerror (rc));
       goto leave;
     }
   if(noisy || opt.verbose)
@@ -1436,9 +1526,9 @@ keyring_rebuild_cache (void *token,int noisy)
     {
       if (iobuf_close (tmpfp))
         {
-          log_error ("error closing `%s': %s\n",
+          rc = gpg_error_from_syserror ();
+          log_error ("error closing '%s': %s\n",
                      tmpfilename, strerror (errno));
-          rc = G10ERR_CLOSE_FILE;
           goto leave;
         }
       /* because we have switched resources, we can be sure that
@@ -1446,15 +1536,15 @@ keyring_rebuild_cache (void *token,int noisy)
       tmpfp = NULL;
     }
   rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
-                                     lastresname, 0) : 0;
+                                     lastresname) : 0;
   xfree (tmpfilename);  tmpfilename = NULL;
   xfree (bakfilename);  bakfilename = NULL;
 
  leave:
   if (tmpfp)
     iobuf_cancel (tmpfp);
-  xfree (tmpfilename);  
-  xfree (bakfilename);  
+  xfree (tmpfilename);
+  xfree (bakfilename);
   release_kbnode (keyblock);
   keyring_lock (hd, 0);
   keyring_release (hd);
@@ -1469,7 +1559,7 @@ keyring_rebuild_cache (void *token,int noisy)
  *     3 = update
  */
 static int
-do_copy (int mode, const char *fname, KBNODE root, int secret,
+do_copy (int mode, const char *fname, KBNODE root,
          off_t start_offset, unsigned int n_packets )
 {
     IOBUF fp, newfp;
@@ -1477,29 +1567,30 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
     char *bakfname = NULL;
     char *tmpfname = NULL;
 
-    /* Open the source file. Because we do a rename, we have to check the 
+    /* Open the source file. Because we do a rename, we have to check the
        permissions of the file */
     if (access (fname, W_OK))
-      return G10ERR_WRITE_FILE;
+      return gpg_error_from_syserror ();
 
     fp = iobuf_open (fname);
-    if (mode == 1 && !fp && errno == ENOENT) { 
+    if (mode == 1 && !fp && errno == ENOENT) {
        /* insert mode but file does not exist: create a new file */
        KBNODE kbctx, node;
        mode_t oldmask;
 
        oldmask=umask(077);
-        if (!secret && is_secured_filename (fname)) {
+        if (is_secured_filename (fname)) {
             newfp = NULL;
-            errno = EPERM;
+            gpg_err_set_errno (EPERM);
         }
         else
-            newfp = iobuf_create (fname);
+            newfp = iobuf_create (fname, 1);
        umask(oldmask);
        if( !newfp )
          {
-           log_error (_("can't create `%s': %s\n"), fname, strerror(errno));
-           return G10ERR_OPEN_FILE;
+            rc = gpg_error_from_syserror ();
+           log_error (_("can't create '%s': %s\n"), fname, strerror(errno));
+           return rc;
          }
        if( !opt.quiet )
            log_info(_("%s: keyring created\n"), fname );
@@ -1508,22 +1599,23 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
        while ( (node = walk_kbnode( root, &kbctx, 0 )) ) {
            if( (rc = build_packet( newfp, node->pkt )) ) {
                log_error("build_packet(%d) failed: %s\n",
-                           node->pkt->pkttype, g10_errstr(rc) );
+                           node->pkt->pkttype, gpg_strerror (rc) );
                iobuf_cancel(newfp);
-               return G10ERR_WRITE_FILE;
+               return rc;
            }
        }
        if( iobuf_close(newfp) ) {
+            rc = gpg_error_from_syserror ();
            log_error ("%s: close failed: %s\n", fname, strerror(errno));
-           return G10ERR_CLOSE_FILE;
+           return rc;
        }
        return 0; /* ready */
     }
 
     if( !fp )
       {
-       log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
-       rc = G10ERR_OPEN_FILE;
+        rc = gpg_error_from_syserror ();
+       log_error(_("can't open '%s': %s\n"), fname, strerror(errno) );
        goto leave;
       }
 
@@ -1533,18 +1625,14 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
        iobuf_close(fp);
        goto leave;
     }
-    if (secret)
-      register_secured_file (tmpfname);
 
     if( mode == 1 ) { /* insert */
        /* copy everything to the new file */
        rc = copy_all_packets (fp, newfp);
        if( rc != -1 ) {
-           log_error("%s: copy to `%s' failed: %s\n",
-                     fname, tmpfname, g10_errstr(rc) );
+           log_error("%s: copy to '%s' failed: %s\n",
+                     fname, tmpfname, gpg_strerror (rc) );
            iobuf_close(fp);
-            if (secret)
-              unregister_secured_file (tmpfname);
            iobuf_cancel(newfp);
            goto leave;
        }
@@ -1555,11 +1643,9 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
        /* copy first part to the new file */
        rc = copy_some_packets( fp, newfp, start_offset );
        if( rc ) { /* should never get EOF here */
-           log_error ("%s: copy to `%s' failed: %s\n",
-                       fname, tmpfname, g10_errstr(rc) );
+           log_error ("%s: copy to '%s' failed: %s\n",
+                       fname, tmpfname, gpg_strerror (rc) );
            iobuf_close(fp);
-            if (secret)
-              unregister_secured_file (tmpfname);
            iobuf_cancel(newfp);
            goto leave;
        }
@@ -1568,10 +1654,8 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
        rc = skip_some_packets( fp, n_packets );
        if( rc ) {
            log_error("%s: skipping %u packets failed: %s\n",
-                           fname, n_packets, g10_errstr(rc));
+                           fname, n_packets, gpg_strerror (rc));
            iobuf_close(fp);
-            if (secret)
-              unregister_secured_file (tmpfname);
            iobuf_cancel(newfp);
            goto leave;
        }
@@ -1581,8 +1665,6 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
         rc = write_keyblock (newfp, root);
         if (rc) {
           iobuf_close(fp);
-          if (secret)
-            unregister_secured_file (tmpfname);
           iobuf_cancel(newfp);
           goto leave;
         }
@@ -1592,11 +1674,9 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
        /* copy the rest */
        rc = copy_all_packets( fp, newfp );
        if( rc != -1 ) {
-           log_error("%s: copy to `%s' failed: %s\n",
-                     fname, tmpfname, g10_errstr(rc) );
+           log_error("%s: copy to '%s' failed: %s\n",
+                     fname, tmpfname, gpg_strerror (rc) );
            iobuf_close(fp);
-            if (secret)
-              unregister_secured_file (tmpfname);
            iobuf_cancel(newfp);
            goto leave;
        }
@@ -1605,17 +1685,17 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
 
     /* close both files */
     if( iobuf_close(fp) ) {
+        rc = gpg_error_from_syserror ();
        log_error("%s: close failed: %s\n", fname, strerror(errno) );
-       rc = G10ERR_CLOSE_FILE;
        goto leave;
     }
     if( iobuf_close(newfp) ) {
+        rc = gpg_error_from_syserror ();
        log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
-       rc = G10ERR_CLOSE_FILE;
        goto leave;
     }
 
-    rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
+    rc = rename_tmp_file (bakfname, tmpfname, fname);
 
   leave:
     xfree(bakfname);