LCOV - code coverage report
Current view: top level - g10 - keyring.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 755 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 28 0.0 %

          Line data    Source code
       1             : /* keyring.c - keyring file handling
       2             :  * Copyright (C) 1998-2010 Free Software Foundation, Inc.
       3             :  * Copyright (C) 1997-2015 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #include <assert.h>
      27             : #include <unistd.h>
      28             : #include <sys/types.h>
      29             : #include <sys/stat.h>
      30             : 
      31             : #include "gpg.h"
      32             : #include "util.h"
      33             : #include "keyring.h"
      34             : #include "packet.h"
      35             : #include "keydb.h"
      36             : #include "options.h"
      37             : #include "main.h" /*for check_key_signature()*/
      38             : #include "i18n.h"
      39             : 
      40             : /* off_item is a funny named for an object used to keep track of known
      41             :  * keys.  The idea was to use the offset to seek to the known keyblock, but
      42             :  * this is not possible if more than one process is using the keyring.
      43             :  */
      44             : struct off_item {
      45             :   struct off_item *next;
      46             :   u32 kid[2];
      47             :   /*off_t off;*/
      48             : };
      49             : 
      50             : typedef struct off_item **OffsetHashTable;
      51             : 
      52             : 
      53             : typedef struct keyring_name *KR_NAME;
      54             : struct keyring_name
      55             : {
      56             :   struct keyring_name *next;
      57             :   int read_only;
      58             :   dotlock_t lockhd;
      59             :   int is_locked;
      60             :   int did_full_scan;
      61             :   char fname[1];
      62             : };
      63             : typedef struct keyring_name const * CONST_KR_NAME;
      64             : 
      65             : static KR_NAME kr_names;
      66             : static int active_handles;
      67             : 
      68             : static OffsetHashTable kr_offtbl;
      69             : static int kr_offtbl_ready;
      70             : 
      71             : 
      72             : struct keyring_handle
      73             : {
      74             :   CONST_KR_NAME resource;
      75             :   struct {
      76             :     CONST_KR_NAME kr;
      77             :     IOBUF iobuf;
      78             :     int eof;
      79             :     int error;
      80             :   } current;
      81             :   struct {
      82             :     CONST_KR_NAME kr;
      83             :     off_t offset;
      84             :     size_t pk_no;
      85             :     size_t uid_no;
      86             :     unsigned int n_packets; /*used for delete and update*/
      87             :   } found, saved_found;
      88             :   struct {
      89             :     char *name;
      90             :     char *pattern;
      91             :   } word_match;
      92             : };
      93             : 
      94             : 
      95             : 
      96             : static int do_copy (int mode, const char *fname, KBNODE root,
      97             :                     off_t start_offset, unsigned int n_packets );
      98             : 
      99             : 
     100             : 
     101             : static struct off_item *
     102           0 : new_offset_item (void)
     103             : {
     104             :   struct off_item *k;
     105             : 
     106           0 :   k = xmalloc_clear (sizeof *k);
     107           0 :   return k;
     108             : }
     109             : 
     110             : #if 0
     111             : static void
     112             : release_offset_items (struct off_item *k)
     113             : {
     114             :   struct off_item *k2;
     115             : 
     116             :   for (; k; k = k2)
     117             :     {
     118             :       k2 = k->next;
     119             :       xfree (k);
     120             :     }
     121             : }
     122             : #endif
     123             : 
     124             : static OffsetHashTable
     125           0 : new_offset_hash_table (void)
     126             : {
     127             :   struct off_item **tbl;
     128             : 
     129           0 :   tbl = xmalloc_clear (2048 * sizeof *tbl);
     130           0 :   return tbl;
     131             : }
     132             : 
     133             : #if 0
     134             : static void
     135             : release_offset_hash_table (OffsetHashTable tbl)
     136             : {
     137             :   int i;
     138             : 
     139             :   if (!tbl)
     140             :     return;
     141             :   for (i=0; i < 2048; i++)
     142             :     release_offset_items (tbl[i]);
     143             :   xfree (tbl);
     144             : }
     145             : #endif
     146             : 
     147             : static struct off_item *
     148           0 : lookup_offset_hash_table (OffsetHashTable tbl, u32 *kid)
     149             : {
     150             :   struct off_item *k;
     151             : 
     152           0 :   for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next)
     153           0 :     if (k->kid[0] == kid[0] && k->kid[1] == kid[1])
     154           0 :       return k;
     155           0 :   return NULL;
     156             : }
     157             : 
     158             : static void
     159           0 : update_offset_hash_table (OffsetHashTable tbl, u32 *kid, off_t off)
     160             : {
     161             :   struct off_item *k;
     162             : 
     163             :   (void)off;
     164             : 
     165           0 :   for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next)
     166             :     {
     167           0 :       if (k->kid[0] == kid[0] && k->kid[1] == kid[1])
     168             :         {
     169             :           /*k->off = off;*/
     170           0 :           return;
     171             :         }
     172             :     }
     173             : 
     174           0 :   k = new_offset_item ();
     175           0 :   k->kid[0] = kid[0];
     176           0 :   k->kid[1] = kid[1];
     177             :   /*k->off = off;*/
     178           0 :   k->next = tbl[(kid[1] & 0x07ff)];
     179           0 :   tbl[(kid[1] & 0x07ff)] = k;
     180             : }
     181             : 
     182             : static void
     183           0 : update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off)
     184             : {
     185           0 :   for (; node; node = node->next)
     186             :     {
     187           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
     188           0 :           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
     189             :         {
     190             :           u32 aki[2];
     191           0 :           keyid_from_pk (node->pkt->pkt.public_key, aki);
     192           0 :           update_offset_hash_table (tbl, aki, off);
     193             :         }
     194             :     }
     195           0 : }
     196             : 
     197             : /*
     198             :  * Register a filename for plain keyring files.  ptr is set to a
     199             :  * pointer to be used to create a handles etc, or the already-issued
     200             :  * pointer if it has already been registered.  The function returns 1
     201             :  * if a new keyring was registered.
     202             : */
     203             : int
     204           0 : keyring_register_filename (const char *fname, int read_only, void **ptr)
     205             : {
     206             :     KR_NAME kr;
     207             : 
     208           0 :     if (active_handles)
     209           0 :         BUG (); /* We don't allow that */
     210             : 
     211           0 :     for (kr=kr_names; kr; kr = kr->next)
     212             :       {
     213           0 :         if (same_file_p (kr->fname, fname))
     214             :           {
     215             :             /* Already registered. */
     216           0 :             if (read_only)
     217           0 :               kr->read_only = 1;
     218           0 :             *ptr=kr;
     219           0 :             return 0;
     220             :           }
     221             :       }
     222             : 
     223           0 :     kr = xmalloc (sizeof *kr + strlen (fname));
     224           0 :     strcpy (kr->fname, fname);
     225           0 :     kr->read_only = read_only;
     226           0 :     kr->lockhd = NULL;
     227           0 :     kr->is_locked = 0;
     228           0 :     kr->did_full_scan = 0;
     229             :     /* keep a list of all issued pointers */
     230           0 :     kr->next = kr_names;
     231           0 :     kr_names = kr;
     232             : 
     233             :     /* create the offset table the first time a function here is used */
     234           0 :     if (!kr_offtbl)
     235           0 :       kr_offtbl = new_offset_hash_table ();
     236             : 
     237           0 :     *ptr=kr;
     238             : 
     239           0 :     return 1;
     240             : }
     241             : 
     242             : int
     243           0 : keyring_is_writable (void *token)
     244             : {
     245           0 :   KR_NAME r = token;
     246             : 
     247           0 :   return r? (r->read_only || !access (r->fname, W_OK)) : 0;
     248             : }
     249             : 
     250             : 
     251             : 
     252             : /* Create a new handle for the resource associated with TOKEN.
     253             : 
     254             :    The returned handle must be released using keyring_release (). */
     255             : KEYRING_HANDLE
     256           0 : keyring_new (void *token)
     257             : {
     258             :   KEYRING_HANDLE hd;
     259           0 :   KR_NAME resource = token;
     260             : 
     261           0 :   assert (resource);
     262             : 
     263           0 :   hd = xmalloc_clear (sizeof *hd);
     264           0 :   hd->resource = resource;
     265           0 :   active_handles++;
     266           0 :   return hd;
     267             : }
     268             : 
     269             : void
     270           0 : keyring_release (KEYRING_HANDLE hd)
     271             : {
     272           0 :     if (!hd)
     273           0 :         return;
     274           0 :     assert (active_handles > 0);
     275           0 :     active_handles--;
     276           0 :     xfree (hd->word_match.name);
     277           0 :     xfree (hd->word_match.pattern);
     278           0 :     iobuf_close (hd->current.iobuf);
     279           0 :     xfree (hd);
     280             : }
     281             : 
     282             : 
     283             : /* Save the current found state in HD for later retrieval by
     284             :    keybox_pop_found_state.  Only one state may be saved.  */
     285             : void
     286           0 : keyring_push_found_state (KEYRING_HANDLE hd)
     287             : {
     288           0 :   hd->saved_found = hd->found;
     289           0 :   hd->found.kr = NULL;
     290           0 : }
     291             : 
     292             : 
     293             : /* Restore the saved found state in HD.  */
     294             : void
     295           0 : keyring_pop_found_state (KEYRING_HANDLE hd)
     296             : {
     297           0 :   hd->found = hd->saved_found;
     298           0 :   hd->saved_found.kr = NULL;
     299           0 : }
     300             : 
     301             : 
     302             : const char *
     303           0 : keyring_get_resource_name (KEYRING_HANDLE hd)
     304             : {
     305           0 :     if (!hd || !hd->resource)
     306           0 :       return NULL;
     307           0 :     return hd->resource->fname;
     308             : }
     309             : 
     310             : 
     311             : /*
     312             :  * Lock the keyring with the given handle, or unlock if YES is false.
     313             :  * We ignore the handle and lock all registered files.
     314             :  */
     315             : int
     316           0 : keyring_lock (KEYRING_HANDLE hd, int yes)
     317             : {
     318             :     KR_NAME kr;
     319           0 :     int rc = 0;
     320             : 
     321             :     (void)hd;
     322             : 
     323           0 :     if (yes) {
     324             :         /* first make sure the lock handles are created */
     325           0 :         for (kr=kr_names; kr; kr = kr->next) {
     326           0 :             if (!keyring_is_writable(kr))
     327           0 :                 continue;
     328           0 :             if (!kr->lockhd) {
     329           0 :                 kr->lockhd = dotlock_create (kr->fname, 0);
     330           0 :                 if (!kr->lockhd) {
     331           0 :                     log_info ("can't allocate lock for '%s'\n", kr->fname );
     332           0 :                     rc = GPG_ERR_GENERAL;
     333             :                 }
     334             :             }
     335             :         }
     336           0 :         if (rc)
     337           0 :             return rc;
     338             : 
     339             :         /* and now set the locks */
     340           0 :         for (kr=kr_names; kr; kr = kr->next) {
     341           0 :             if (!keyring_is_writable(kr))
     342           0 :                 continue;
     343           0 :             if (kr->is_locked)
     344             :                 ;
     345           0 :             else if (dotlock_take (kr->lockhd, -1) ) {
     346           0 :                 log_info ("can't lock '%s'\n", kr->fname );
     347           0 :                 rc = GPG_ERR_GENERAL;
     348             :             }
     349             :             else
     350           0 :                 kr->is_locked = 1;
     351             :         }
     352             :     }
     353             : 
     354           0 :     if (rc || !yes) {
     355           0 :         for (kr=kr_names; kr; kr = kr->next) {
     356           0 :             if (!keyring_is_writable(kr))
     357           0 :                 continue;
     358           0 :             if (!kr->is_locked)
     359             :                 ;
     360           0 :             else if (dotlock_release (kr->lockhd))
     361           0 :                 log_info ("can't unlock '%s'\n", kr->fname );
     362             :             else
     363           0 :                 kr->is_locked = 0;
     364             :         }
     365             :     }
     366             : 
     367           0 :     return rc;
     368             : }
     369             : 
     370             : 
     371             : 
     372             : /*
     373             :  * Return the last found keyblock.  Caller must free it.
     374             :  * The returned keyblock has the kbode flag bit 0 set for the node with
     375             :  * the public key used to locate the keyblock or flag bit 1 set for
     376             :  * the user ID node.
     377             :  */
     378             : int
     379           0 : keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     380             : {
     381             :     PACKET *pkt;
     382             :     int rc;
     383           0 :     KBNODE keyblock = NULL, node, lastnode;
     384             :     IOBUF a;
     385           0 :     int in_cert = 0;
     386           0 :     int pk_no = 0;
     387           0 :     int uid_no = 0;
     388             :     int save_mode;
     389             : 
     390           0 :     if (ret_kb)
     391           0 :         *ret_kb = NULL;
     392             : 
     393           0 :     if (!hd->found.kr)
     394           0 :         return -1; /* no successful search */
     395             : 
     396           0 :     a = iobuf_open (hd->found.kr->fname);
     397           0 :     if (!a)
     398             :       {
     399           0 :         log_error(_("can't open '%s'\n"), hd->found.kr->fname);
     400           0 :         return GPG_ERR_KEYRING_OPEN;
     401             :       }
     402             : 
     403           0 :     if (iobuf_seek (a, hd->found.offset) ) {
     404           0 :         log_error ("can't seek '%s'\n", hd->found.kr->fname);
     405           0 :         iobuf_close(a);
     406           0 :         return GPG_ERR_KEYRING_OPEN;
     407             :     }
     408             : 
     409           0 :     pkt = xmalloc (sizeof *pkt);
     410           0 :     init_packet (pkt);
     411           0 :     hd->found.n_packets = 0;;
     412           0 :     lastnode = NULL;
     413           0 :     save_mode = set_packet_list_mode(0);
     414           0 :     while ((rc=parse_packet (a, pkt)) != -1) {
     415           0 :         hd->found.n_packets++;
     416           0 :         if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
     417           0 :             free_packet (pkt);
     418           0 :             init_packet (pkt);
     419           0 :             continue;
     420             :         }
     421           0 :         if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
     422           0 :           break;  /* Upper layer needs to handle this.  */
     423           0 :         if (rc) {
     424           0 :             log_error ("keyring_get_keyblock: read error: %s\n",
     425             :                        gpg_strerror (rc) );
     426           0 :             rc = GPG_ERR_INV_KEYRING;
     427           0 :             break;
     428             :         }
     429             : 
     430             :         /* Filter allowed packets.  */
     431           0 :         switch (pkt->pkttype)
     432             :           {
     433             :           case PKT_PUBLIC_KEY:
     434             :           case PKT_PUBLIC_SUBKEY:
     435             :           case PKT_SECRET_KEY:
     436             :           case PKT_SECRET_SUBKEY:
     437             :           case PKT_USER_ID:
     438             :           case PKT_ATTRIBUTE:
     439             :           case PKT_SIGNATURE:
     440           0 :             break; /* Allowed per RFC.  */
     441             :           case PKT_RING_TRUST:
     442             :           case PKT_OLD_COMMENT:
     443             :           case PKT_COMMENT:
     444             :           case PKT_GPG_CONTROL:
     445           0 :             break; /* Allowed by us.  */
     446             : 
     447             :           default:
     448           0 :             log_error ("skipped packet of type %d in keyring\n",
     449           0 :                        (int)pkt->pkttype);
     450           0 :             free_packet(pkt);
     451           0 :             init_packet(pkt);
     452           0 :             continue;
     453             :           }
     454             : 
     455           0 :         if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
     456           0 :                         || pkt->pkttype == PKT_SECRET_KEY)) {
     457           0 :             hd->found.n_packets--; /* fix counter */
     458           0 :             break; /* ready */
     459             :         }
     460             : 
     461           0 :         in_cert = 1;
     462           0 :         if (pkt->pkttype == PKT_RING_TRUST)
     463             :           {
     464             :             /*(this code is duplicated after the loop)*/
     465           0 :             if ( lastnode
     466           0 :                  && lastnode->pkt->pkttype == PKT_SIGNATURE
     467           0 :                  && (pkt->pkt.ring_trust->sigcache & 1) ) {
     468             :                 /* This is a ring trust packet with a checked signature
     469             :                  * status cache following directly a signature paket.
     470             :                  * Set the cache status into that signature packet.  */
     471           0 :                 PKT_signature *sig = lastnode->pkt->pkt.signature;
     472             : 
     473           0 :                 sig->flags.checked = 1;
     474           0 :                 sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
     475             :             }
     476             :             /* Reset LASTNODE, so that we set the cache status only from
     477             :              * the ring trust packet immediately following a signature. */
     478           0 :             lastnode = NULL;
     479           0 :             free_packet(pkt);
     480           0 :             init_packet(pkt);
     481           0 :             continue;
     482             :           }
     483             : 
     484             : 
     485           0 :         node = lastnode = new_kbnode (pkt);
     486           0 :         if (!keyblock)
     487           0 :           keyblock = node;
     488             :         else
     489           0 :           add_kbnode (keyblock, node);
     490           0 :         switch (pkt->pkttype)
     491             :           {
     492             :           case PKT_PUBLIC_KEY:
     493             :           case PKT_PUBLIC_SUBKEY:
     494             :           case PKT_SECRET_KEY:
     495             :           case PKT_SECRET_SUBKEY:
     496           0 :             if (++pk_no == hd->found.pk_no)
     497           0 :               node->flag |= 1;
     498           0 :             break;
     499             : 
     500             :           case PKT_USER_ID:
     501           0 :             if (++uid_no == hd->found.uid_no)
     502           0 :               node->flag |= 2;
     503           0 :             break;
     504             : 
     505             :           default:
     506           0 :             break;
     507             :           }
     508             : 
     509           0 :         pkt = xmalloc (sizeof *pkt);
     510           0 :         init_packet(pkt);
     511             :     }
     512           0 :     set_packet_list_mode(save_mode);
     513             : 
     514           0 :     if (rc == -1 && keyblock)
     515           0 :         rc = 0; /* got the entire keyblock */
     516             : 
     517           0 :     if (rc || !ret_kb)
     518           0 :         release_kbnode (keyblock);
     519             :     else {
     520             :         /*(duplicated from the loop body)*/
     521           0 :         if ( pkt && pkt->pkttype == PKT_RING_TRUST
     522           0 :              && lastnode
     523           0 :              && lastnode->pkt->pkttype == PKT_SIGNATURE
     524           0 :              && (pkt->pkt.ring_trust->sigcache & 1) ) {
     525           0 :             PKT_signature *sig = lastnode->pkt->pkt.signature;
     526           0 :             sig->flags.checked = 1;
     527           0 :             sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
     528             :         }
     529           0 :         *ret_kb = keyblock;
     530             :     }
     531           0 :     free_packet (pkt);
     532           0 :     xfree (pkt);
     533           0 :     iobuf_close(a);
     534             : 
     535             :     /* Make sure that future search operations fail immediately when
     536             :      * we know that we are working on a invalid keyring
     537             :      */
     538           0 :     if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING)
     539           0 :         hd->current.error = rc;
     540             : 
     541           0 :     return rc;
     542             : }
     543             : 
     544             : int
     545           0 : keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     546             : {
     547             :     int rc;
     548             : 
     549           0 :     if (!hd->found.kr)
     550           0 :         return -1; /* no successful prior search */
     551             : 
     552           0 :     if (hd->found.kr->read_only)
     553           0 :       return gpg_error (GPG_ERR_EACCES);
     554             : 
     555           0 :     if (!hd->found.n_packets) {
     556             :         /* need to know the number of packets - do a dummy get_keyblock*/
     557           0 :         rc = keyring_get_keyblock (hd, NULL);
     558           0 :         if (rc) {
     559           0 :             log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
     560           0 :             return rc;
     561             :         }
     562           0 :         if (!hd->found.n_packets)
     563           0 :             BUG ();
     564             :     }
     565             : 
     566             :     /* The open iobuf isn't needed anymore and in fact is a problem when
     567             :        it comes to renaming the keyring files on some operating systems,
     568             :        so close it here */
     569           0 :     iobuf_close(hd->current.iobuf);
     570           0 :     hd->current.iobuf = NULL;
     571             : 
     572             :     /* do the update */
     573           0 :     rc = do_copy (3, hd->found.kr->fname, kb,
     574             :                   hd->found.offset, hd->found.n_packets );
     575           0 :     if (!rc) {
     576           0 :       if (kr_offtbl)
     577             :         {
     578           0 :           update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
     579             :         }
     580             :       /* better reset the found info */
     581           0 :       hd->found.kr = NULL;
     582           0 :       hd->found.offset = 0;
     583             :     }
     584           0 :     return rc;
     585             : }
     586             : 
     587             : int
     588           0 : keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
     589             : {
     590             :     int rc;
     591             :     const char *fname;
     592             : 
     593           0 :     if (!hd)
     594           0 :         fname = NULL;
     595           0 :     else if (hd->found.kr)
     596             :       {
     597           0 :         fname = hd->found.kr->fname;
     598           0 :         if (hd->found.kr->read_only)
     599           0 :           return gpg_error (GPG_ERR_EACCES);
     600             :       }
     601           0 :     else if (hd->current.kr)
     602             :       {
     603           0 :         fname = hd->current.kr->fname;
     604           0 :         if (hd->current.kr->read_only)
     605           0 :           return gpg_error (GPG_ERR_EACCES);
     606             :       }
     607             :     else
     608           0 :         fname = hd->resource? hd->resource->fname:NULL;
     609             : 
     610           0 :     if (!fname)
     611           0 :         return GPG_ERR_GENERAL;
     612             : 
     613             :     /* Close this one otherwise we will lose the position for
     614             :      * a next search.  Fixme: it would be better to adjust the position
     615             :      * after the write opertions.
     616             :      */
     617           0 :     iobuf_close (hd->current.iobuf);
     618           0 :     hd->current.iobuf = NULL;
     619             : 
     620             :     /* do the insert */
     621           0 :     rc = do_copy (1, fname, kb, 0, 0 );
     622           0 :     if (!rc && kr_offtbl)
     623             :       {
     624           0 :         update_offset_hash_table_from_kb (kr_offtbl, kb, 0);
     625             :       }
     626             : 
     627           0 :     return rc;
     628             : }
     629             : 
     630             : 
     631             : int
     632           0 : keyring_delete_keyblock (KEYRING_HANDLE hd)
     633             : {
     634             :     int rc;
     635             : 
     636           0 :     if (!hd->found.kr)
     637           0 :         return -1; /* no successful prior search */
     638             : 
     639           0 :     if (hd->found.kr->read_only)
     640           0 :       return gpg_error (GPG_ERR_EACCES);
     641             : 
     642           0 :     if (!hd->found.n_packets) {
     643             :         /* need to know the number of packets - do a dummy get_keyblock*/
     644           0 :         rc = keyring_get_keyblock (hd, NULL);
     645           0 :         if (rc) {
     646           0 :             log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc));
     647           0 :             return rc;
     648             :         }
     649           0 :         if (!hd->found.n_packets)
     650           0 :             BUG ();
     651             :     }
     652             : 
     653             :     /* close this one otherwise we will lose the position for
     654             :      * a next search.  Fixme: it would be better to adjust the position
     655             :      * after the write opertions.
     656             :      */
     657           0 :     iobuf_close (hd->current.iobuf);
     658           0 :     hd->current.iobuf = NULL;
     659             : 
     660             :     /* do the delete */
     661           0 :     rc = do_copy (2, hd->found.kr->fname, NULL,
     662             :                   hd->found.offset, hd->found.n_packets );
     663           0 :     if (!rc) {
     664             :         /* better reset the found info */
     665           0 :         hd->found.kr = NULL;
     666           0 :         hd->found.offset = 0;
     667             :         /* Delete is a rare operations, so we don't remove the keys
     668             :          * from the offset table */
     669             :     }
     670           0 :     return rc;
     671             : }
     672             : 
     673             : 
     674             : 
     675             : /*
     676             :  * Start the next search on this handle right at the beginning
     677             :  */
     678             : int
     679           0 : keyring_search_reset (KEYRING_HANDLE hd)
     680             : {
     681           0 :     assert (hd);
     682             : 
     683           0 :     hd->current.kr = NULL;
     684           0 :     iobuf_close (hd->current.iobuf);
     685           0 :     hd->current.iobuf = NULL;
     686           0 :     hd->current.eof = 0;
     687           0 :     hd->current.error = 0;
     688             : 
     689           0 :     hd->found.kr = NULL;
     690           0 :     hd->found.offset = 0;
     691           0 :     return 0;
     692             : }
     693             : 
     694             : 
     695             : static int
     696           0 : prepare_search (KEYRING_HANDLE hd)
     697             : {
     698           0 :     if (hd->current.error) {
     699             :         /* If the last key was a legacy key, we simply ignore the error so that
     700             :            we can easily use search_next.  */
     701           0 :         if (gpg_err_code (hd->current.error) == GPG_ERR_LEGACY_KEY)
     702           0 :             hd->current.error = 0;
     703             :         else
     704           0 :             return hd->current.error; /* still in error state */
     705             :     }
     706             : 
     707           0 :     if (hd->current.kr && !hd->current.eof) {
     708           0 :         if ( !hd->current.iobuf )
     709           0 :             return GPG_ERR_GENERAL; /* Position invalid after a modify.  */
     710           0 :         return 0; /* okay */
     711             :     }
     712             : 
     713           0 :     if (!hd->current.kr && hd->current.eof)
     714           0 :         return -1; /* still EOF */
     715             : 
     716           0 :     if (!hd->current.kr) { /* start search with first keyring */
     717           0 :         hd->current.kr = hd->resource;
     718           0 :         if (!hd->current.kr) {
     719           0 :             hd->current.eof = 1;
     720           0 :             return -1; /* keyring not available */
     721             :         }
     722           0 :         assert (!hd->current.iobuf);
     723             :     }
     724             :     else { /* EOF */
     725           0 :         iobuf_close (hd->current.iobuf);
     726           0 :         hd->current.iobuf = NULL;
     727           0 :         hd->current.kr = NULL;
     728           0 :         hd->current.eof = 1;
     729           0 :         return -1;
     730             :     }
     731             : 
     732           0 :     hd->current.eof = 0;
     733           0 :     hd->current.iobuf = iobuf_open (hd->current.kr->fname);
     734           0 :     if (!hd->current.iobuf)
     735             :       {
     736           0 :         hd->current.error = gpg_error_from_syserror ();
     737           0 :         log_error(_("can't open '%s'\n"), hd->current.kr->fname );
     738           0 :         return hd->current.error;
     739             :       }
     740             : 
     741           0 :     return 0;
     742             : }
     743             : 
     744             : 
     745             : /* A map of the all characters valid used for word_match()
     746             :  * Valid characters are in in this table converted to uppercase.
     747             :  * because the upper 128 bytes have special meaning, we assume
     748             :  * that they are all valid.
     749             :  * Note: We must use numerical values here in case that this program
     750             :  * will be converted to those little blue HAL9000s with their strange
     751             :  * EBCDIC character set (user ids are UTF-8).
     752             :  * wk 2000-04-13: Hmmm, does this really make sense, given the fact that
     753             :  * we can run gpg now on a S/390 running GNU/Linux, where the code
     754             :  * translation is done by the device drivers?
     755             :  */
     756             : static const byte word_match_chars[256] = {
     757             :   /* 00 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     758             :   /* 08 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     759             :   /* 10 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     760             :   /* 18 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     761             :   /* 20 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     762             :   /* 28 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     763             :   /* 30 */  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
     764             :   /* 38 */  0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     765             :   /* 40 */  0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
     766             :   /* 48 */  0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
     767             :   /* 50 */  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
     768             :   /* 58 */  0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00,
     769             :   /* 60 */  0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
     770             :   /* 68 */  0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
     771             :   /* 70 */  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
     772             :   /* 78 */  0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00,
     773             :   /* 80 */  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
     774             :   /* 88 */  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
     775             :   /* 90 */  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
     776             :   /* 98 */  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
     777             :   /* a0 */  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
     778             :   /* a8 */  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
     779             :   /* b0 */  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
     780             :   /* b8 */  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
     781             :   /* c0 */  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
     782             :   /* c8 */  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
     783             :   /* d0 */  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
     784             :   /* d8 */  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
     785             :   /* e0 */  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
     786             :   /* e8 */  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
     787             :   /* f0 */  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
     788             :   /* f8 */  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
     789             : };
     790             : 
     791             : /****************
     792             :  * Do a word match (original user id starts with a '+').
     793             :  * The pattern is already tokenized to a more suitable format:
     794             :  * There are only the real words in it delimited by one space
     795             :  * and all converted to uppercase.
     796             :  *
     797             :  * Returns: 0 if all words match.
     798             :  *
     799             :  * Note: This algorithm is a straightforward one and not very
     800             :  *       fast.  It works for UTF-8 strings.  The uidlen should
     801             :  *       be removed but due to the fact that old versions of
     802             :  *       pgp don't use UTF-8 we still use the length; this should
     803             :  *       be fixed in parse-packet (and replace \0 by some special
     804             :  *       UTF-8 encoding)
     805             :  */
     806             : static int
     807           0 : word_match( const byte *uid, size_t uidlen, const byte *pattern )
     808             : {
     809             :     size_t wlen, n;
     810             :     const byte *p;
     811             :     const byte *s;
     812             : 
     813           0 :     for( s=pattern; *s; ) {
     814             :         do {
     815             :             /* skip leading delimiters */
     816           0 :             while( uidlen && !word_match_chars[*uid] )
     817           0 :                 uid++, uidlen--;
     818             :             /* get length of the word */
     819           0 :             n = uidlen; p = uid;
     820           0 :             while( n && word_match_chars[*p] )
     821           0 :                 p++, n--;
     822           0 :             wlen = p - uid;
     823             :             /* and compare against the current word from pattern */
     824           0 :             for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) {
     825           0 :                 if( word_match_chars[*p] != s[n] )
     826           0 :                     break;
     827             :             }
     828           0 :             if( n == wlen && (s[n] == ' ' || !s[n]) )
     829             :                 break; /* found */
     830           0 :             uid += wlen;
     831           0 :             uidlen -= wlen;
     832           0 :         } while( uidlen );
     833           0 :         if( !uidlen )
     834           0 :             return -1; /* not found */
     835             : 
     836             :         /* advance to next word in pattern */
     837           0 :         for(; *s != ' ' && *s ; s++ )
     838             :             ;
     839           0 :         if( *s )
     840           0 :             s++ ;
     841             :     }
     842           0 :     return 0; /* found */
     843             : }
     844             : 
     845             : /****************
     846             :  * prepare word word_match; that is parse the name and
     847             :  * build the pattern.
     848             :  * caller has to free the returned pattern
     849             :  */
     850             : static char*
     851           0 : prepare_word_match (const byte *name)
     852             : {
     853             :     byte *pattern, *p;
     854             :     int c;
     855             : 
     856             :     /* the original length is always enough for the pattern */
     857           0 :     p = pattern = xmalloc(strlen(name)+1);
     858             :     do {
     859             :         /* skip leading delimiters */
     860           0 :         while( *name && !word_match_chars[*name] )
     861           0 :             name++;
     862             :         /* copy as long as we don't have a delimiter and convert
     863             :          * to uppercase.
     864             :          * fixme: how can we handle utf8 uppercasing */
     865           0 :         for( ; *name &&  (c=word_match_chars[*name]); name++ )
     866           0 :             *p++ = c;
     867           0 :         *p++ = ' '; /* append pattern delimiter */
     868           0 :     } while( *name );
     869           0 :     p[-1] = 0; /* replace last pattern delimiter by EOS */
     870             : 
     871           0 :     return pattern;
     872             : }
     873             : 
     874             : 
     875             : 
     876             : 
     877             : static int
     878           0 : compare_name (int mode, const char *name, const char *uid, size_t uidlen)
     879             : {
     880             :     int i;
     881             :     const char *s, *se;
     882             : 
     883           0 :     if (mode == KEYDB_SEARCH_MODE_EXACT) {
     884           0 :         for (i=0; name[i] && uidlen; i++, uidlen--)
     885           0 :             if (uid[i] != name[i])
     886           0 :                 break;
     887           0 :         if (!uidlen && !name[i])
     888           0 :             return 0; /* found */
     889             :     }
     890           0 :     else if (mode == KEYDB_SEARCH_MODE_SUBSTR) {
     891           0 :         if (ascii_memistr( uid, uidlen, name ))
     892           0 :             return 0;
     893             :     }
     894           0 :     else if (   mode == KEYDB_SEARCH_MODE_MAIL
     895           0 :              || mode == KEYDB_SEARCH_MODE_MAILSUB
     896           0 :              || mode == KEYDB_SEARCH_MODE_MAILEND) {
     897           0 :         for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++)
     898             :             ;
     899           0 :         if (i < uidlen)  {
     900             :             /* skip opening delim and one char and look for the closing one*/
     901           0 :             s++; i++;
     902           0 :             for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++)
     903             :                 ;
     904           0 :             if (i < uidlen) {
     905           0 :                 i = se - s;
     906           0 :                 if (mode == KEYDB_SEARCH_MODE_MAIL) {
     907           0 :                     if( strlen(name)-2 == i
     908           0 :                         && !ascii_memcasecmp( s, name+1, i) )
     909           0 :                         return 0;
     910             :                 }
     911           0 :                 else if (mode == KEYDB_SEARCH_MODE_MAILSUB) {
     912           0 :                     if( ascii_memistr( s, i, name ) )
     913           0 :                         return 0;
     914             :                 }
     915             :                 else { /* email from end */
     916             :                     /* nyi */
     917             :                 }
     918             :             }
     919             :         }
     920             :     }
     921           0 :     else if (mode == KEYDB_SEARCH_MODE_WORDS)
     922           0 :         return word_match (uid, uidlen, name);
     923             :     else
     924           0 :         BUG();
     925             : 
     926           0 :     return -1; /* not found */
     927             : }
     928             : 
     929             : 
     930             : /*
     931             :  * Search through the keyring(s), starting at the current position,
     932             :  * for a keyblock which contains one of the keys described in the DESC array.
     933             :  */
     934             : int
     935           0 : keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
     936             :                 size_t ndesc, size_t *descindex)
     937             : {
     938             :   int rc;
     939             :   PACKET pkt;
     940             :   int save_mode;
     941             :   off_t offset, main_offset;
     942             :   size_t n;
     943             :   int need_uid, need_words, need_keyid, need_fpr, any_skip;
     944             :   int pk_no, uid_no;
     945             :   int initial_skip;
     946             :   int use_offtbl;
     947           0 :   PKT_user_id *uid = NULL;
     948           0 :   PKT_public_key *pk = NULL;
     949             :   u32 aki[2];
     950             : 
     951             :   /* figure out what information we need */
     952           0 :   need_uid = need_words = need_keyid = need_fpr = any_skip = 0;
     953           0 :   for (n=0; n < ndesc; n++)
     954             :     {
     955           0 :       switch (desc[n].mode)
     956             :         {
     957             :         case KEYDB_SEARCH_MODE_EXACT:
     958             :         case KEYDB_SEARCH_MODE_SUBSTR:
     959             :         case KEYDB_SEARCH_MODE_MAIL:
     960             :         case KEYDB_SEARCH_MODE_MAILSUB:
     961             :         case KEYDB_SEARCH_MODE_MAILEND:
     962           0 :           need_uid = 1;
     963           0 :           break;
     964             :         case KEYDB_SEARCH_MODE_WORDS:
     965           0 :           need_uid = 1;
     966           0 :           need_words = 1;
     967           0 :           break;
     968             :         case KEYDB_SEARCH_MODE_SHORT_KID:
     969             :         case KEYDB_SEARCH_MODE_LONG_KID:
     970           0 :           need_keyid = 1;
     971           0 :           break;
     972             :         case KEYDB_SEARCH_MODE_FPR16:
     973             :         case KEYDB_SEARCH_MODE_FPR20:
     974             :         case KEYDB_SEARCH_MODE_FPR:
     975           0 :           need_fpr = 1;
     976           0 :           break;
     977             :         case KEYDB_SEARCH_MODE_FIRST:
     978             :           /* always restart the search in this mode */
     979           0 :           keyring_search_reset (hd);
     980           0 :           break;
     981           0 :         default: break;
     982             :         }
     983           0 :       if (desc[n].skipfnc)
     984             :         {
     985           0 :           any_skip = 1;
     986           0 :           need_keyid = 1;
     987             :         }
     988             :     }
     989             : 
     990           0 :   rc = prepare_search (hd);
     991           0 :   if (rc)
     992           0 :     return rc;
     993             : 
     994           0 :   use_offtbl = !!kr_offtbl;
     995           0 :   if (!use_offtbl)
     996             :     ;
     997           0 :   else if (!kr_offtbl_ready)
     998           0 :     need_keyid = 1;
     999           0 :   else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
    1000             :     {
    1001             :       struct off_item *oi;
    1002             : 
    1003           0 :       oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid);
    1004           0 :       if (!oi)
    1005             :         { /* We know that we don't have this key */
    1006           0 :           hd->found.kr = NULL;
    1007           0 :           hd->current.eof = 1;
    1008           0 :           return -1;
    1009             :         }
    1010             :       /* We could now create a positive search status and return.
    1011             :        * However the problem is that another instance of gpg may
    1012             :        * have changed the keyring so that the offsets are not valid
    1013             :        * anymore - therefore we don't do it
    1014             :        */
    1015             :     }
    1016             : 
    1017           0 :   if (need_words)
    1018             :     {
    1019           0 :       const char *name = NULL;
    1020             : 
    1021           0 :       log_debug ("word search mode does not yet work\n");
    1022             :       /* FIXME: here is a long standing bug in our function and in addition we
    1023             :          just use the first search description */
    1024           0 :       for (n=0; n < ndesc && !name; n++)
    1025             :         {
    1026           0 :           if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS)
    1027           0 :             name = desc[n].u.name;
    1028             :         }
    1029           0 :       assert (name);
    1030           0 :       if ( !hd->word_match.name || strcmp (hd->word_match.name, name) )
    1031             :         {
    1032             :           /* name changed */
    1033           0 :           xfree (hd->word_match.name);
    1034           0 :           xfree (hd->word_match.pattern);
    1035           0 :           hd->word_match.name = xstrdup (name);
    1036           0 :           hd->word_match.pattern = prepare_word_match (name);
    1037             :         }
    1038             :       /*  name = hd->word_match.pattern; */
    1039             :     }
    1040             : 
    1041           0 :   init_packet(&pkt);
    1042           0 :   save_mode = set_packet_list_mode(0);
    1043             : 
    1044           0 :   hd->found.kr = NULL;
    1045           0 :   main_offset = 0;
    1046           0 :   pk_no = uid_no = 0;
    1047           0 :   initial_skip = 1; /* skip until we see the start of a keyblock */
    1048           0 :   while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid)))
    1049             :     {
    1050             :       byte afp[MAX_FINGERPRINT_LEN];
    1051             :       size_t an;
    1052             : 
    1053           0 :       if (pkt.pkttype == PKT_PUBLIC_KEY  || pkt.pkttype == PKT_SECRET_KEY)
    1054             :         {
    1055           0 :           main_offset = offset;
    1056           0 :           pk_no = uid_no = 0;
    1057           0 :           initial_skip = 0;
    1058             :         }
    1059           0 :       if (initial_skip)
    1060             :         {
    1061           0 :           free_packet (&pkt);
    1062           0 :           continue;
    1063             :         }
    1064             : 
    1065           0 :       pk = NULL;
    1066           0 :       uid = NULL;
    1067           0 :       if (   pkt.pkttype == PKT_PUBLIC_KEY
    1068           0 :              || pkt.pkttype == PKT_PUBLIC_SUBKEY
    1069           0 :              || pkt.pkttype == PKT_SECRET_KEY
    1070           0 :              || pkt.pkttype == PKT_SECRET_SUBKEY)
    1071             :         {
    1072           0 :           pk = pkt.pkt.public_key;
    1073           0 :           ++pk_no;
    1074             : 
    1075           0 :           if (need_fpr) {
    1076           0 :             fingerprint_from_pk (pk, afp, &an);
    1077           0 :             while (an < 20) /* fill up to 20 bytes */
    1078           0 :               afp[an++] = 0;
    1079             :           }
    1080           0 :           if (need_keyid)
    1081           0 :             keyid_from_pk (pk, aki);
    1082             : 
    1083           0 :           if (use_offtbl && !kr_offtbl_ready)
    1084           0 :             update_offset_hash_table (kr_offtbl, aki, main_offset);
    1085             :         }
    1086           0 :       else if (pkt.pkttype == PKT_USER_ID)
    1087             :         {
    1088           0 :           uid = pkt.pkt.user_id;
    1089           0 :           ++uid_no;
    1090             :         }
    1091             : 
    1092           0 :       for (n=0; n < ndesc; n++)
    1093             :         {
    1094           0 :           switch (desc[n].mode) {
    1095             :           case KEYDB_SEARCH_MODE_NONE:
    1096           0 :             BUG ();
    1097             :             break;
    1098             :           case KEYDB_SEARCH_MODE_EXACT:
    1099             :           case KEYDB_SEARCH_MODE_SUBSTR:
    1100             :           case KEYDB_SEARCH_MODE_MAIL:
    1101             :           case KEYDB_SEARCH_MODE_MAILSUB:
    1102             :           case KEYDB_SEARCH_MODE_MAILEND:
    1103             :           case KEYDB_SEARCH_MODE_WORDS:
    1104           0 :             if ( uid && !compare_name (desc[n].mode,
    1105           0 :                                        desc[n].u.name,
    1106           0 :                                        uid->name, uid->len))
    1107           0 :               goto found;
    1108           0 :             break;
    1109             : 
    1110             :           case KEYDB_SEARCH_MODE_SHORT_KID:
    1111           0 :             if (pk && desc[n].u.kid[1] == aki[1])
    1112           0 :               goto found;
    1113           0 :             break;
    1114             :           case KEYDB_SEARCH_MODE_LONG_KID:
    1115           0 :             if (pk && desc[n].u.kid[0] == aki[0]
    1116           0 :                 && desc[n].u.kid[1] == aki[1])
    1117           0 :               goto found;
    1118           0 :             break;
    1119             :           case KEYDB_SEARCH_MODE_FPR16:
    1120           0 :             if (pk && !memcmp (desc[n].u.fpr, afp, 16))
    1121           0 :               goto found;
    1122           0 :             break;
    1123             :           case KEYDB_SEARCH_MODE_FPR20:
    1124             :           case KEYDB_SEARCH_MODE_FPR:
    1125           0 :             if (pk && !memcmp (desc[n].u.fpr, afp, 20))
    1126           0 :               goto found;
    1127           0 :             break;
    1128             :           case KEYDB_SEARCH_MODE_FIRST:
    1129           0 :             if (pk)
    1130           0 :               goto found;
    1131           0 :             break;
    1132             :           case KEYDB_SEARCH_MODE_NEXT:
    1133           0 :             if (pk)
    1134           0 :               goto found;
    1135           0 :             break;
    1136             :           default:
    1137           0 :             rc = GPG_ERR_INV_ARG;
    1138           0 :             goto found;
    1139             :           }
    1140             :         }
    1141           0 :       free_packet (&pkt);
    1142           0 :       continue;
    1143             :     found:
    1144             :       /* Record which desc we matched on.  Note this value is only
    1145             :          meaningful if this function returns with no errors. */
    1146           0 :       if(descindex)
    1147           0 :         *descindex=n;
    1148           0 :       for (n=any_skip?0:ndesc; n < ndesc; n++)
    1149             :         {
    1150           0 :           if (desc[n].skipfnc
    1151           0 :               && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid_no))
    1152           0 :             break;
    1153             :         }
    1154           0 :       if (n == ndesc)
    1155           0 :         goto real_found;
    1156           0 :       free_packet (&pkt);
    1157             :     }
    1158             :  real_found:
    1159           0 :   if (!rc)
    1160             :     {
    1161           0 :       hd->found.offset = main_offset;
    1162           0 :       hd->found.kr = hd->current.kr;
    1163           0 :       hd->found.pk_no = pk? pk_no : 0;
    1164           0 :       hd->found.uid_no = uid? uid_no : 0;
    1165             :     }
    1166           0 :   else if (rc == -1)
    1167             :     {
    1168           0 :       hd->current.eof = 1;
    1169             :       /* if we scanned all keyrings, we are sure that
    1170             :        * all known key IDs are in our offtbl, mark that. */
    1171           0 :       if (use_offtbl && !kr_offtbl_ready)
    1172             :         {
    1173             :           KR_NAME kr;
    1174             : 
    1175             :           /* First set the did_full_scan flag for this keyring.  */
    1176           0 :           for (kr=kr_names; kr; kr = kr->next)
    1177             :             {
    1178           0 :               if (hd->resource == kr)
    1179             :                 {
    1180           0 :                   kr->did_full_scan = 1;
    1181           0 :                   break;
    1182             :                 }
    1183             :             }
    1184             :           /* Then check whether all flags are set and if so, mark the
    1185             :              offtbl ready */
    1186           0 :           for (kr=kr_names; kr; kr = kr->next)
    1187             :             {
    1188           0 :               if (!kr->did_full_scan)
    1189           0 :                 break;
    1190             :             }
    1191           0 :           if (!kr)
    1192           0 :             kr_offtbl_ready = 1;
    1193             :         }
    1194             :     }
    1195             :   else
    1196           0 :     hd->current.error = rc;
    1197             : 
    1198           0 :   free_packet(&pkt);
    1199           0 :   set_packet_list_mode(save_mode);
    1200           0 :   return rc;
    1201             : }
    1202             : 
    1203             : 
    1204             : static int
    1205           0 : create_tmp_file (const char *template,
    1206             :                  char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
    1207             : {
    1208             :   char *bakfname, *tmpfname;
    1209             :   mode_t oldmask;
    1210             : 
    1211           0 :   *r_bakfname = NULL;
    1212           0 :   *r_tmpfname = NULL;
    1213             : 
    1214             : # ifdef USE_ONLY_8DOT3
    1215             :   /* Here is another Windoze bug?:
    1216             :    * you cant rename("pubring.gpg.tmp", "pubring.gpg");
    1217             :    * but        rename("pubring.gpg.tmp", "pubring.aaa");
    1218             :    * works.  So we replace .gpg by .bak or .tmp
    1219             :    */
    1220             :   if (strlen (template) > 4
    1221             :       && !strcmp (template+strlen(template)-4, EXTSEP_S GPGEXT_GPG) )
    1222             :     {
    1223             :       bakfname = xmalloc (strlen (template) + 1);
    1224             :       strcpy (bakfname, template);
    1225             :       strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
    1226             : 
    1227             :       tmpfname = xmalloc (strlen( template ) + 1 );
    1228             :       strcpy (tmpfname,template);
    1229             :       strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
    1230             :     }
    1231             :     else
    1232             :       { /* file does not end with gpg; hmmm */
    1233             :         bakfname = xmalloc (strlen( template ) + 5);
    1234             :         strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
    1235             : 
    1236             :         tmpfname = xmalloc (strlen( template ) + 5);
    1237             :         strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp");
    1238             :     }
    1239             : # else /* Posix file names */
    1240           0 :     bakfname = xmalloc (strlen( template ) + 2);
    1241           0 :     strcpy (stpcpy (bakfname,template),"~");
    1242             : 
    1243           0 :     tmpfname = xmalloc (strlen( template ) + 5);
    1244           0 :     strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp");
    1245             : # endif /* Posix filename */
    1246             : 
    1247             :     /* Create the temp file with limited access.  Note that the umask
    1248             :        call is not anymore needed because iobuf_create now takes care
    1249             :        of it.  However, it does not harm and thus we keep it.  */
    1250           0 :     oldmask=umask(077);
    1251           0 :     if (is_secured_filename (tmpfname))
    1252             :       {
    1253           0 :         *r_fp = NULL;
    1254           0 :         gpg_err_set_errno (EPERM);
    1255             :       }
    1256             :     else
    1257           0 :       *r_fp = iobuf_create (tmpfname, 1);
    1258           0 :     umask(oldmask);
    1259           0 :     if (!*r_fp)
    1260             :       {
    1261           0 :         int rc = gpg_error_from_syserror ();
    1262           0 :         log_error(_("can't create '%s': %s\n"), tmpfname, strerror(errno) );
    1263           0 :         xfree (tmpfname);
    1264           0 :         xfree (bakfname);
    1265           0 :         return rc;
    1266             :       }
    1267             : 
    1268           0 :     *r_bakfname = bakfname;
    1269           0 :     *r_tmpfname = tmpfname;
    1270           0 :     return 0;
    1271             : }
    1272             : 
    1273             : 
    1274             : static int
    1275           0 : rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname)
    1276             : {
    1277           0 :   int rc = 0;
    1278             : 
    1279             :   /* Invalidate close caches.  */
    1280           0 :   if (iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)tmpfname ))
    1281             :     {
    1282           0 :       rc = gpg_error_from_syserror ();
    1283           0 :       goto fail;
    1284             :     }
    1285           0 :   iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)bakfname );
    1286           0 :   iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname );
    1287             : 
    1288             :   /* First make a backup file. */
    1289             : #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
    1290             :   gnupg_remove (bakfname);
    1291             : #endif
    1292           0 :   if (rename (fname, bakfname) )
    1293             :     {
    1294           0 :       rc = gpg_error_from_syserror ();
    1295           0 :       log_error ("renaming '%s' to '%s' failed: %s\n",
    1296           0 :                  fname, bakfname, strerror(errno) );
    1297           0 :       return rc;
    1298             :     }
    1299             : 
    1300             :   /* then rename the file */
    1301             : #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
    1302             :   gnupg_remove( fname );
    1303             : #endif
    1304           0 :   if (rename (tmpfname, fname) )
    1305             :     {
    1306           0 :       rc = gpg_error_from_syserror ();
    1307           0 :       log_error (_("renaming '%s' to '%s' failed: %s\n"),
    1308           0 :                  tmpfname, fname, strerror(errno) );
    1309           0 :       register_secured_file (fname);
    1310           0 :       goto fail;
    1311             :     }
    1312             : 
    1313             :   /* Now make sure the file has the same permissions as the original */
    1314             : 
    1315             : #ifndef HAVE_DOSISH_SYSTEM
    1316             :   {
    1317             :     struct stat statbuf;
    1318             : 
    1319           0 :     statbuf.st_mode=S_IRUSR | S_IWUSR;
    1320             : 
    1321           0 :     if (!stat (bakfname, &statbuf) && !chmod (fname, statbuf.st_mode))
    1322             :       ;
    1323             :     else
    1324           0 :       log_error ("WARNING: unable to restore permissions to '%s': %s",
    1325           0 :                  fname, strerror(errno));
    1326             :   }
    1327             : #endif
    1328             : 
    1329           0 :   return 0;
    1330             : 
    1331             :  fail:
    1332           0 :   return rc;
    1333             : }
    1334             : 
    1335             : 
    1336             : static int
    1337           0 : write_keyblock (IOBUF fp, KBNODE keyblock)
    1338             : {
    1339           0 :   KBNODE kbctx = NULL, node;
    1340             :   int rc;
    1341             : 
    1342           0 :   while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
    1343             :     {
    1344           0 :       if (node->pkt->pkttype == PKT_RING_TRUST)
    1345           0 :         continue; /* we write it later on our own */
    1346             : 
    1347           0 :       if ( (rc = build_packet (fp, node->pkt) ))
    1348             :         {
    1349           0 :           log_error ("build_packet(%d) failed: %s\n",
    1350           0 :                      node->pkt->pkttype, gpg_strerror (rc) );
    1351           0 :           return rc;
    1352             :         }
    1353           0 :       if (node->pkt->pkttype == PKT_SIGNATURE)
    1354             :         { /* always write a signature cache packet */
    1355           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    1356           0 :           unsigned int cacheval = 0;
    1357             : 
    1358           0 :           if (sig->flags.checked)
    1359             :             {
    1360           0 :               cacheval |= 1;
    1361           0 :               if (sig->flags.valid)
    1362           0 :                 cacheval |= 2;
    1363             :             }
    1364           0 :           iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
    1365           0 :           iobuf_put (fp, 2);    /* 2 bytes */
    1366           0 :           iobuf_put (fp, 0);    /* unused */
    1367           0 :           if (iobuf_put (fp, cacheval))
    1368             :             {
    1369           0 :               rc = gpg_error_from_syserror ();
    1370           0 :               log_error ("writing sigcache packet failed\n");
    1371           0 :               return rc;
    1372             :             }
    1373             :         }
    1374             :     }
    1375           0 :   return 0;
    1376             : }
    1377             : 
    1378             : /*
    1379             :  * Walk over all public keyrings, check the signatures and replace the
    1380             :  * keyring with a new one where the signature cache is then updated.
    1381             :  * This is only done for the public keyrings.
    1382             :  */
    1383             : int
    1384           0 : keyring_rebuild_cache (void *token,int noisy)
    1385             : {
    1386             :   KEYRING_HANDLE hd;
    1387             :   KEYDB_SEARCH_DESC desc;
    1388           0 :   KBNODE keyblock = NULL, node;
    1389           0 :   const char *lastresname = NULL, *resname;
    1390           0 :   IOBUF tmpfp = NULL;
    1391           0 :   char *tmpfilename = NULL;
    1392           0 :   char *bakfilename = NULL;
    1393             :   int rc;
    1394           0 :   ulong count = 0, sigcount = 0;
    1395             : 
    1396           0 :   hd = keyring_new (token);
    1397           0 :   memset (&desc, 0, sizeof desc);
    1398           0 :   desc.mode = KEYDB_SEARCH_MODE_FIRST;
    1399             : 
    1400           0 :   rc=keyring_lock (hd, 1);
    1401           0 :   if(rc)
    1402           0 :     goto leave;
    1403             : 
    1404             :   for (;;)
    1405             :     {
    1406           0 :       rc = keyring_search (hd, &desc, 1, NULL);
    1407           0 :       if (rc && gpg_err_code (rc) != GPG_ERR_LEGACY_KEY)
    1408           0 :         break;  /* ready.  */
    1409             : 
    1410           0 :       desc.mode = KEYDB_SEARCH_MODE_NEXT;
    1411           0 :       resname = keyring_get_resource_name (hd);
    1412           0 :       if (lastresname != resname )
    1413             :         { /* we have switched to a new keyring - commit changes */
    1414           0 :           if (tmpfp)
    1415             :             {
    1416           0 :               if (iobuf_close (tmpfp))
    1417             :                 {
    1418           0 :                   rc = gpg_error_from_syserror ();
    1419           0 :                   log_error ("error closing '%s': %s\n",
    1420           0 :                              tmpfilename, strerror (errno));
    1421           0 :                   goto leave;
    1422             :                 }
    1423             :               /* because we have switched resources, we can be sure that
    1424             :                * the original file is closed */
    1425           0 :               tmpfp = NULL;
    1426             :             }
    1427           0 :           rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
    1428           0 :                                              lastresname) : 0;
    1429           0 :           xfree (tmpfilename);  tmpfilename = NULL;
    1430           0 :           xfree (bakfilename);  bakfilename = NULL;
    1431           0 :           if (rc)
    1432           0 :             goto leave;
    1433           0 :           lastresname = resname;
    1434           0 :           if (noisy && !opt.quiet)
    1435           0 :             log_info (_("caching keyring '%s'\n"), resname);
    1436           0 :           rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp);
    1437           0 :           if (rc)
    1438           0 :             goto leave;
    1439             :         }
    1440             : 
    1441           0 :       if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
    1442           0 :         continue;
    1443             : 
    1444           0 :       release_kbnode (keyblock);
    1445           0 :       rc = keyring_get_keyblock (hd, &keyblock);
    1446           0 :       if (rc)
    1447             :         {
    1448           0 :           if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
    1449           0 :             continue;  /* Skip legacy keys.  */
    1450           0 :           log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc));
    1451           0 :           goto leave;
    1452             :         }
    1453           0 :       if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
    1454             :         {
    1455             :           /* We had a few reports about corrupted keyrings; if we have
    1456             :              been called directly from the command line we delete such
    1457             :              a keyblock instead of bailing out.  */
    1458           0 :           log_error ("unexpected keyblock found (pkttype=%d)%s\n",
    1459           0 :                      keyblock->pkt->pkttype, noisy? " - deleted":"");
    1460           0 :           if (noisy)
    1461           0 :             continue;
    1462           0 :           log_info ("Hint: backup your keys and try running '%s'\n",
    1463             :                     "gpg --rebuild-keydb-caches");
    1464           0 :           rc = gpg_error (GPG_ERR_INV_KEYRING);
    1465           0 :           goto leave;
    1466             :         }
    1467             : 
    1468           0 :       if (keyblock->pkt->pkt.public_key->version < 4)
    1469             :         {
    1470             :           /* We do not copy/cache v3 keys or any other unknown
    1471             :              packets.  It is better to remove them from the keyring.
    1472             :              The code required to keep them in the keyring would be
    1473             :              too complicated.  Given that we do not touch the old
    1474             :              secring.gpg a suitable backup for decryption of v3 stuff
    1475             :              using an older gpg version will always be available.
    1476             :              Note: This test is actually superfluous because we
    1477             :              already acted upon GPG_ERR_LEGACY_KEY.      */
    1478             :         }
    1479             :       else
    1480             :         {
    1481             :           /* Check all signature to set the signature's cache flags. */
    1482           0 :           for (node=keyblock; node; node=node->next)
    1483             :             {
    1484             :               /* Note that this doesn't cache the result of a
    1485             :                  revocation issued by a designated revoker.  This is
    1486             :                  because the pk in question does not carry the revkeys
    1487             :                  as we haven't merged the key and selfsigs.  It is
    1488             :                  questionable whether this matters very much since
    1489             :                  there are very very few designated revoker revocation
    1490             :                  packets out there. */
    1491           0 :               if (node->pkt->pkttype == PKT_SIGNATURE)
    1492             :                 {
    1493           0 :                   PKT_signature *sig=node->pkt->pkt.signature;
    1494             : 
    1495           0 :                   if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid
    1496           0 :                      && (openpgp_md_test_algo(sig->digest_algo)
    1497           0 :                          || openpgp_pk_test_algo(sig->pubkey_algo)))
    1498           0 :                     sig->flags.checked=sig->flags.valid=0;
    1499             :                   else
    1500           0 :                     check_key_signature (keyblock, node, NULL);
    1501             : 
    1502           0 :                   sigcount++;
    1503             :                 }
    1504             :             }
    1505             : 
    1506             :           /* Write the keyblock to the temporary file.  */
    1507           0 :           rc = write_keyblock (tmpfp, keyblock);
    1508           0 :           if (rc)
    1509           0 :             goto leave;
    1510             : 
    1511           0 :           if ( !(++count % 50) && noisy && !opt.quiet)
    1512           0 :             log_info(_("%lu keys cached so far (%lu signatures)\n"),
    1513             :                      count, sigcount );
    1514             :         }
    1515           0 :     } /* end main loop */
    1516           0 :   if (rc == -1)
    1517           0 :     rc = 0;
    1518           0 :   if (rc)
    1519             :     {
    1520           0 :       log_error ("keyring_search failed: %s\n", gpg_strerror (rc));
    1521           0 :       goto leave;
    1522             :     }
    1523           0 :   if(noisy || opt.verbose)
    1524           0 :     log_info(_("%lu keys cached (%lu signatures)\n"), count, sigcount );
    1525           0 :   if (tmpfp)
    1526             :     {
    1527           0 :       if (iobuf_close (tmpfp))
    1528             :         {
    1529           0 :           rc = gpg_error_from_syserror ();
    1530           0 :           log_error ("error closing '%s': %s\n",
    1531           0 :                      tmpfilename, strerror (errno));
    1532           0 :           goto leave;
    1533             :         }
    1534             :       /* because we have switched resources, we can be sure that
    1535             :        * the original file is closed */
    1536           0 :       tmpfp = NULL;
    1537             :     }
    1538           0 :   rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
    1539           0 :                                      lastresname) : 0;
    1540           0 :   xfree (tmpfilename);  tmpfilename = NULL;
    1541           0 :   xfree (bakfilename);  bakfilename = NULL;
    1542             : 
    1543             :  leave:
    1544           0 :   if (tmpfp)
    1545           0 :     iobuf_cancel (tmpfp);
    1546           0 :   xfree (tmpfilename);
    1547           0 :   xfree (bakfilename);
    1548           0 :   release_kbnode (keyblock);
    1549           0 :   keyring_lock (hd, 0);
    1550           0 :   keyring_release (hd);
    1551           0 :   return rc;
    1552             : }
    1553             : 
    1554             : 
    1555             : /****************
    1556             :  * Perform insert/delete/update operation.
    1557             :  * mode 1 = insert
    1558             :  *      2 = delete
    1559             :  *      3 = update
    1560             :  */
    1561             : static int
    1562           0 : do_copy (int mode, const char *fname, KBNODE root,
    1563             :          off_t start_offset, unsigned int n_packets )
    1564             : {
    1565             :     IOBUF fp, newfp;
    1566           0 :     int rc=0;
    1567           0 :     char *bakfname = NULL;
    1568           0 :     char *tmpfname = NULL;
    1569             : 
    1570             :     /* Open the source file. Because we do a rename, we have to check the
    1571             :        permissions of the file */
    1572           0 :     if (access (fname, W_OK))
    1573           0 :       return gpg_error_from_syserror ();
    1574             : 
    1575           0 :     fp = iobuf_open (fname);
    1576           0 :     if (mode == 1 && !fp && errno == ENOENT) {
    1577             :         /* insert mode but file does not exist: create a new file */
    1578             :         KBNODE kbctx, node;
    1579             :         mode_t oldmask;
    1580             : 
    1581           0 :         oldmask=umask(077);
    1582           0 :         if (is_secured_filename (fname)) {
    1583           0 :             newfp = NULL;
    1584           0 :             gpg_err_set_errno (EPERM);
    1585             :         }
    1586             :         else
    1587           0 :             newfp = iobuf_create (fname, 1);
    1588           0 :         umask(oldmask);
    1589           0 :         if( !newfp )
    1590             :           {
    1591           0 :             rc = gpg_error_from_syserror ();
    1592           0 :             log_error (_("can't create '%s': %s\n"), fname, strerror(errno));
    1593           0 :             return rc;
    1594             :           }
    1595           0 :         if( !opt.quiet )
    1596           0 :             log_info(_("%s: keyring created\n"), fname );
    1597             : 
    1598           0 :         kbctx=NULL;
    1599           0 :         while ( (node = walk_kbnode( root, &kbctx, 0 )) ) {
    1600           0 :             if( (rc = build_packet( newfp, node->pkt )) ) {
    1601           0 :                 log_error("build_packet(%d) failed: %s\n",
    1602           0 :                             node->pkt->pkttype, gpg_strerror (rc) );
    1603           0 :                 iobuf_cancel(newfp);
    1604           0 :                 return rc;
    1605             :             }
    1606             :         }
    1607           0 :         if( iobuf_close(newfp) ) {
    1608           0 :             rc = gpg_error_from_syserror ();
    1609           0 :             log_error ("%s: close failed: %s\n", fname, strerror(errno));
    1610           0 :             return rc;
    1611             :         }
    1612           0 :         return 0; /* ready */
    1613             :     }
    1614             : 
    1615           0 :     if( !fp )
    1616             :       {
    1617           0 :         rc = gpg_error_from_syserror ();
    1618           0 :         log_error(_("can't open '%s': %s\n"), fname, strerror(errno) );
    1619           0 :         goto leave;
    1620             :       }
    1621             : 
    1622             :     /* Create the new file.  */
    1623           0 :     rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
    1624           0 :     if (rc) {
    1625           0 :         iobuf_close(fp);
    1626           0 :         goto leave;
    1627             :     }
    1628             : 
    1629           0 :     if( mode == 1 ) { /* insert */
    1630             :         /* copy everything to the new file */
    1631           0 :         rc = copy_all_packets (fp, newfp);
    1632           0 :         if( rc != -1 ) {
    1633           0 :             log_error("%s: copy to '%s' failed: %s\n",
    1634             :                       fname, tmpfname, gpg_strerror (rc) );
    1635           0 :             iobuf_close(fp);
    1636           0 :             iobuf_cancel(newfp);
    1637           0 :             goto leave;
    1638             :         }
    1639           0 :         rc = 0;
    1640             :     }
    1641             : 
    1642           0 :     if( mode == 2 || mode == 3 ) { /* delete or update */
    1643             :         /* copy first part to the new file */
    1644           0 :         rc = copy_some_packets( fp, newfp, start_offset );
    1645           0 :         if( rc ) { /* should never get EOF here */
    1646           0 :             log_error ("%s: copy to '%s' failed: %s\n",
    1647             :                        fname, tmpfname, gpg_strerror (rc) );
    1648           0 :             iobuf_close(fp);
    1649           0 :             iobuf_cancel(newfp);
    1650           0 :             goto leave;
    1651             :         }
    1652             :         /* skip this keyblock */
    1653           0 :         assert( n_packets );
    1654           0 :         rc = skip_some_packets( fp, n_packets );
    1655           0 :         if( rc ) {
    1656           0 :             log_error("%s: skipping %u packets failed: %s\n",
    1657             :                             fname, n_packets, gpg_strerror (rc));
    1658           0 :             iobuf_close(fp);
    1659           0 :             iobuf_cancel(newfp);
    1660           0 :             goto leave;
    1661             :         }
    1662             :     }
    1663             : 
    1664           0 :     if( mode == 1 || mode == 3 ) { /* insert or update */
    1665           0 :         rc = write_keyblock (newfp, root);
    1666           0 :         if (rc) {
    1667           0 :           iobuf_close(fp);
    1668           0 :           iobuf_cancel(newfp);
    1669           0 :           goto leave;
    1670             :         }
    1671             :     }
    1672             : 
    1673           0 :     if( mode == 2 || mode == 3 ) { /* delete or update */
    1674             :         /* copy the rest */
    1675           0 :         rc = copy_all_packets( fp, newfp );
    1676           0 :         if( rc != -1 ) {
    1677           0 :             log_error("%s: copy to '%s' failed: %s\n",
    1678             :                       fname, tmpfname, gpg_strerror (rc) );
    1679           0 :             iobuf_close(fp);
    1680           0 :             iobuf_cancel(newfp);
    1681           0 :             goto leave;
    1682             :         }
    1683           0 :         rc = 0;
    1684             :     }
    1685             : 
    1686             :     /* close both files */
    1687           0 :     if( iobuf_close(fp) ) {
    1688           0 :         rc = gpg_error_from_syserror ();
    1689           0 :         log_error("%s: close failed: %s\n", fname, strerror(errno) );
    1690           0 :         goto leave;
    1691             :     }
    1692           0 :     if( iobuf_close(newfp) ) {
    1693           0 :         rc = gpg_error_from_syserror ();
    1694           0 :         log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
    1695           0 :         goto leave;
    1696             :     }
    1697             : 
    1698           0 :     rc = rename_tmp_file (bakfname, tmpfname, fname);
    1699             : 
    1700             :   leave:
    1701           0 :     xfree(bakfname);
    1702           0 :     xfree(tmpfname);
    1703           0 :     return rc;
    1704             : }

Generated by: LCOV version 1.11