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