See ChangeLog: Mon Jan 24 22:24:38 CET 2000 Werner Koch
[gnupg.git] / g10 / ringedit.c
1 /* ringedit.c -  Function for key ring editing
2  *      Copyright (C) 1998 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
22 /****************
23  * This module supplies function for:
24  *
25  *  - Search for a key block (pubkey and all other stuff) and return a
26  *    handle for it.
27  *
28  *  - Lock/Unlock a key block
29  *
30  *  - Read a key block into a tree
31  *
32  *  - Update a key block
33  *
34  *  - Insert a new key block
35  *
36  *  - Delete a key block
37  *
38  */
39
40
41
42 #include <config.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <unistd.h> /* for truncate */
50 #include <assert.h>
51 #ifdef HAVE_LIBGDBM
52   #include <gdbm.h>
53 #endif
54 #include "util.h"
55 #include "packet.h"
56 #include <gcrypt.h>
57 #include "iobuf.h"
58 #include "keydb.h"
59 #include "host2net.h"
60 #include "options.h"
61 #include "main.h"
62 #include "i18n.h"
63
64
65 #ifdef MKDIR_TAKES_ONE_ARG
66 # undef mkdir
67 # define mkdir(a,b) mkdir(a)
68 #endif
69
70
71 struct resource_table_struct {
72     int used;
73     int secret; /* this is a secret keyring */
74     char *fname;
75     IOBUF iobuf;
76   #ifdef HAVE_LIBGDBM
77     GDBM_FILE dbf;
78   #endif
79     enum resource_type rt;
80     DOTLOCK lockhd;
81     int    is_locked;
82 };
83 typedef struct resource_table_struct RESTBL;
84
85 #define MAX_RESOURCES 10
86 static RESTBL resource_table[MAX_RESOURCES];
87 static int default_public_resource;
88 static int default_secret_resource;
89
90 static int search( PACKET *pkt, KBPOS *kbpos, int secret );
91
92
93 static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
94                                                 const char *fname );
95 static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
96 static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
97 static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
98
99 #ifdef HAVE_LIBGDBM
100 static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
101 static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
102                                           const byte *fpr, int fprlen );
103 static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );
104 static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root );
105 static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root );
106 #endif
107
108
109 static RESTBL *
110 check_pos( KBPOS *kbpos )
111 {
112     if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
113         return NULL;
114     if( !resource_table[kbpos->resno].used )
115         return NULL;
116     return resource_table + kbpos->resno;
117 }
118
119 #ifdef HAVE_LIBGDBM
120 static void
121 fatal_gdbm_error( const char *string )
122 {
123     log_fatal("gdbm failed: %s\n", string);
124 }
125
126 #endif /* HAVE_LIBGDBM */
127
128
129 /****************
130  * Hmmm, how to avoid deadlock? They should not happen if everyone
131  * locks the key resources in the same order; but who knows.
132  * A solution is to use only one lock file in the gnupg homedir but
133  * what will happen with key resources which normally don't belong
134  * to the gpg homedir?
135  */
136 static void
137 lock_rentry( RESTBL *rentry )
138 {
139     if( !rentry->lockhd ) {
140         rentry->lockhd = create_dotlock( rentry->fname );
141         if( !rentry->lockhd )
142             log_fatal("can't allocate lock for `%s'\n", rentry->fname );
143         rentry->is_locked = 0;
144     }
145     if( !rentry->is_locked ) {
146         if( make_dotlock( rentry->lockhd, -1 ) )
147             log_fatal("can't lock `%s'\n", rentry->fname );
148         rentry->is_locked = 1;
149     }
150 }
151
152 static void
153 unlock_rentry( RESTBL *rentry )
154 {
155     if( opt.lock_once )
156         return;
157     if( !release_dotlock( rentry->lockhd ) )
158         rentry->is_locked = 0;
159 }
160
161
162 /****************************************************************
163  ****************** public functions ****************************
164  ****************************************************************/
165
166 /****************
167  * Get the name of the keyrings, start with a sequence number pointing to a 0.
168  */
169 const char *
170 enum_keyblock_resources( int *sequence, int secret )
171 {
172     int i = *sequence;
173     const char *name = NULL;
174
175     for(; i < MAX_RESOURCES; i++ )
176         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
177             if( resource_table[i].fname ) {
178                 name = resource_table[i].fname;
179                 break;
180             }
181         }
182     *sequence = ++i;
183     return name;
184 }
185
186
187
188 /****************
189  * Register a resource (which currently may only be a keyring file).
190  * The first keyring which is added by this function is
191  * created if it does not exist.
192  * Note: this function may be called before secure memory is
193  * available.
194  */
195 int
196 add_keyblock_resource( const char *url, int force, int secret )
197 {
198     static int any_secret, any_public;
199     const char *resname = url;
200     IOBUF iobuf = NULL;
201     int i;
202     char *filename = NULL;
203     int rc = 0;
204     enum resource_type rt = rt_UNKNOWN;
205
206
207     /* Do we have an URL?
208      *  gnupg-gdbm:filename  := this is a GDBM resource
209      *  gnupg-ring:filename  := this is a plain keyring
210      *  filename := See what is is, but create as plain keyring.
211      */
212     if( strlen( resname ) > 11 ) {
213         if( !strncmp( resname, "gnupg-ring:", 11 ) ) {
214             rt = rt_RING;
215             resname += 11;
216         }
217         else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
218             rt = rt_GDBM;
219             resname += 11;
220         }
221       #ifndef HAVE_DRIVE_LETTERS
222         else if( strchr( resname, ':' ) ) {
223             log_error("%s: invalid URL\n", url );
224             rc = G10ERR_GENERAL;
225             goto leave;
226         }
227       #endif
228     }
229
230     if( *resname != '/' ) { /* do tilde expansion etc */
231         if( strchr(resname, '/') )
232             filename = make_filename(resname, NULL);
233         else
234             filename = make_filename(opt.homedir, resname, NULL);
235     }
236     else
237         filename = gcry_xstrdup( resname );
238
239     if( !force )
240         force = secret? !any_secret : !any_public;
241
242     for(i=0; i < MAX_RESOURCES; i++ )
243         if( !resource_table[i].used )
244             break;
245     if( i == MAX_RESOURCES ) {
246         rc = G10ERR_RESOURCE_LIMIT;
247         goto leave;
248     }
249
250     /* see whether we can determine the filetype */
251     if( rt == rt_UNKNOWN ) {
252         FILE *fp = fopen( filename, "rb" );
253
254         if( fp ) {
255             u32 magic;
256
257             if( fread( &magic, 4, 1, fp) == 1 ) {
258                 if( magic == 0x13579ace )
259                     rt = rt_GDBM;
260                 else if( magic == 0xce9a5713 )
261                     log_error("%s: endianess does not match\n", url );
262                 else
263                     rt = rt_RING;
264             }
265             else /* maybe empty: assume ring */
266                 rt = rt_RING;
267             fclose( fp );
268         }
269         else /* no file yet: create ring */
270             rt = rt_RING;
271     }
272
273     switch( rt ) {
274       case rt_UNKNOWN:
275         log_error("%s: unknown resource type\n", url );
276         rc = G10ERR_GENERAL;
277         goto leave;
278
279       case rt_RING:
280         iobuf = iobuf_open( filename );
281         if( !iobuf && !force ) {
282             rc = G10ERR_OPEN_FILE;
283             goto leave;
284         }
285
286         if( !iobuf ) {
287             char *last_slash_in_filename;
288
289             last_slash_in_filename = strrchr(filename, '/');
290             *last_slash_in_filename = 0;
291
292             if( access(filename, F_OK) ) {
293                 if( strlen(filename) >= 7
294                     && !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
295                     if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
296                     {
297                         log_error( _("%s: can't create directory: %s\n"),
298                                   filename, strerror(errno));
299                         rc = G10ERR_OPEN_FILE;
300                         goto leave;
301                     }
302                     else if( !opt.quiet )
303                         log_info( _("%s: directory created\n"), filename );
304                     copy_options_file( filename );
305                 }
306                 else
307                 {
308                     rc = G10ERR_OPEN_FILE;
309                     goto leave;
310                 }
311             }
312
313             *last_slash_in_filename = '/';
314
315             iobuf = iobuf_create( filename );
316             if( !iobuf ) {
317                 log_error(_("%s: can't create keyring: %s\n"),
318                                             filename, strerror(errno));
319                 rc = G10ERR_OPEN_FILE;
320                 goto leave;
321             }
322             else {
323               #ifndef HAVE_DOSISH_SYSTEM
324                 if( secret ) {
325                     if( chmod( filename, S_IRUSR | S_IWUSR ) ) {
326                         log_error("%s: chmod failed: %s\n",
327                                                 filename, strerror(errno) );
328                         rc = G10ERR_WRITE_FILE;
329                         goto leave;
330                     }
331                 }
332               #endif
333                 if( !opt.quiet )
334                     log_info(_("%s: keyring created\n"), filename );
335             }
336         }
337       #if HAVE_DOSISH_SYSTEM || 1
338         iobuf_close( iobuf );
339         iobuf = NULL;
340         /* must close it again */
341       #endif
342         break;
343
344     #ifdef HAVE_LIBGDBM
345       case rt_GDBM:
346         resource_table[i].dbf = gdbm_open( filename, 0,
347                                            force? GDBM_WRCREAT : GDBM_WRITER,
348                                            S_IRUSR | S_IWUSR |
349                                            S_IRGRP | S_IWGRP | S_IROTH,
350                                            fatal_gdbm_error );
351         if( !resource_table[i].dbf ) {
352             log_error("%s: can't open gdbm file: %s\n",
353                             filename, gdbm_strerror(gdbm_errno));
354             rc = G10ERR_OPEN_FILE;
355             goto leave;
356         }
357         break;
358     #endif
359
360       default:
361         log_error("%s: unsupported resource type\n", url );
362         rc = G10ERR_GENERAL;
363         goto leave;
364     }
365
366   #ifndef HAVE_DOSISH_SYSTEM
367   #if 0 /* fixme: check directory permissions and print a warning */
368     if( secret ) {
369     }
370   #endif
371   #endif
372
373     /* fixme: avoid duplicate resources */
374     resource_table[i].used = 1;
375     resource_table[i].secret = !!secret;
376     resource_table[i].fname = gcry_xstrdup(filename);
377     resource_table[i].iobuf = iobuf;
378     resource_table[i].rt    = rt;
379     if( secret )
380         default_secret_resource = i;
381     else
382         default_public_resource = i;
383
384   leave:
385     if( rc )
386         log_error("keyblock resource `%s': %s\n", filename, g10_errstr(rc) );
387     else if( secret )
388         any_secret = 1;
389     else
390         any_public = 1;
391     gcry_free( filename );
392     return rc;
393 }
394
395 /****************
396  * Return the resource name of the keyblock associated with KBPOS.
397  */
398 const char *
399 keyblock_resource_name( KBPOS *kbpos )
400 {
401     RESTBL *rentry;
402
403     if( !(rentry = check_pos( kbpos )) || !rentry->fname )
404         log_bug("no name for keyblock resource %d\n", kbpos->resno );
405     return rentry->fname;
406 }
407
408
409 /****************
410  * Get a keyblock handle KBPOS from a filename. This can be used
411  * to get a handle for insert_keyblock for a new keyblock.
412  * Using a filename of NULL returns the default resource
413  */
414 int
415 get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
416 {
417     int i = 0;
418
419     if( !filename )
420         i = secret? default_secret_resource : default_public_resource;
421
422     for(; i < MAX_RESOURCES; i++ ) {
423         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
424             /* fixme: dos needs case insensitive file compare */
425             if( !filename || !strcmp( resource_table[i].fname, filename ) ) {
426                 memset( kbpos, 0, sizeof *kbpos );
427                 kbpos->resno = i;
428                 kbpos->rt = resource_table[i].rt;
429                 return 0;
430             }
431         }
432     }
433     return -1; /* not found */
434 }
435
436
437
438 /****************
439  * Search a keyblock which starts with the given packet and puts all
440  * information into KBPOS, which can be used later to access this key block.
441  * This function looks into all registered keyblock sources.
442  * PACKET must be a packet with either a secret_key or a public_key
443  *
444  * This function is intended to check whether a given certificate
445  * is already in a keyring or to prepare it for editing.
446  *
447  * Returns: 0 if found, -1 if not found or an errorcode.
448  */
449 static int
450 search( PACKET *pkt, KBPOS *kbpos, int secret )
451 {
452     int i, rc, last_rc=-1;
453
454     for(i=0; i < MAX_RESOURCES; i++ ) {
455         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
456             switch( resource_table[i].rt ) {
457               case rt_RING:
458                 rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
459                                                  resource_table[i].fname );
460                 break;
461              #ifdef HAVE_LIBGDBM
462               case rt_GDBM: {
463                     PKT_public_key *req_pk = pkt->pkt.public_key;
464                     byte fpr[20];
465                     size_t fprlen;
466
467                     fingerprint_from_pk( req_pk, fpr, &fprlen );
468                     rc = do_gdbm_locate( resource_table[i].dbf,
469                                          kbpos, fpr, fprlen );
470                 }
471                 break;
472              #endif
473               default: BUG();
474             }
475
476             kbpos->rt = resource_table[i].rt;
477             if( !rc ) {
478                 kbpos->resno = i;
479                 kbpos->fp = NULL;
480                 return 0;
481             }
482             if( rc != -1 ) {
483                 log_error("error searching resource %d: %s\n",
484                                                   i, g10_errstr(rc));
485                 last_rc = rc;
486             }
487         }
488     }
489     return last_rc;
490 }
491
492
493 /****************
494  * Combined function to search for a username and get the position
495  * of the keyblock.
496  */
497 int
498 find_keyblock_byname( KBPOS *kbpos, const char *username )
499 {
500     PACKET pkt;
501     PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
502     int rc;
503
504     rc = get_pubkey_byname( NULL, pk, username, NULL );
505     if( rc ) {
506         free_public_key(pk);
507         return rc;
508     }
509
510     init_packet( &pkt );
511     pkt.pkttype = PKT_PUBLIC_KEY;
512     pkt.pkt.public_key = pk;
513     rc = search( &pkt, kbpos, 0 );
514     free_public_key(pk);
515     return rc;
516 }
517
518
519 /****************
520  * Combined function to search for a key and get the position
521  * of the keyblock.
522  */
523 int
524 find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
525 {
526     PACKET pkt;
527     int rc;
528
529     init_packet( &pkt );
530     pkt.pkttype = PKT_PUBLIC_KEY;
531     pkt.pkt.public_key = pk;
532     rc = search( &pkt, kbpos, 0 );
533     return rc;
534 }
535
536 /****************
537  * Combined function to search for a key and get the position
538  * of the keyblock.
539  */
540 int
541 find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk )
542 {
543     PACKET pkt;
544     int rc;
545
546     init_packet( &pkt );
547     pkt.pkttype = PKT_SECRET_KEY;
548     pkt.pkt.secret_key = sk;
549     rc = search( &pkt, kbpos, 0 );
550     return rc;
551 }
552
553
554 /****************
555  * Combined function to search for a username and get the position
556  * of the keyblock. This function does not unprotect the secret key.
557  */
558 int
559 find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
560 {
561     PACKET pkt;
562     PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
563     int rc;
564
565     rc = get_seckey_byname( sk, username, 0 );
566     if( rc ) {
567         free_secret_key(sk);
568         return rc;
569     }
570
571     init_packet( &pkt );
572     pkt.pkttype = PKT_SECRET_KEY;
573     pkt.pkt.secret_key = sk;
574     rc = search( &pkt, kbpos, 1 );
575     free_secret_key(sk);
576     return rc;
577 }
578
579
580 /****************
581  * Locate a keyblock in a database which is capable of direct access
582  * Put all information into KBPOS, which can be later be to access this
583  * key block.
584  * This function looks into all registered keyblock sources.
585  *
586  * Returns: 0 if found,
587  *          -1 if not found
588  *          G10ERR_UNSUPPORTED if no resource is able to handle this
589  *          or another errorcode.
590  */
591 int
592 locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret )
593 {
594     RESTBL *rentry;
595     int i, rc, any=0, last_rc=-1;
596
597
598     for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
599         if( rentry->used && !rentry->secret == !secret ) {
600             kbpos->rt = rentry->rt;
601             switch( rentry->rt ) {
602              #ifdef HAVE_LIBGDBM
603               case rt_GDBM:
604                 any = 1;
605                 rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
606                 break;
607              #endif
608               default:
609                 rc = G10ERR_UNSUPPORTED;
610                 break;
611             }
612
613             if( !rc ) {
614                 kbpos->resno = i;
615                 kbpos->fp = NULL;
616                 return 0;
617             }
618             else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
619                 log_error("error searching resource %d: %s\n",
620                                                   i, g10_errstr(rc));
621                 last_rc = rc;
622             }
623         }
624     }
625
626     return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
627 }
628
629
630 int
631 locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret )
632 {
633     RESTBL *rentry;
634     int i, rc, any=0, last_rc=-1;
635
636     if( shortkid )
637         return G10ERR_UNSUPPORTED;
638
639     for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
640         if( rentry->used && !rentry->secret == !secret ) {
641             kbpos->rt = rentry->rt;
642             switch( rentry->rt ) {
643              #ifdef HAVE_LIBGDBM
644               case rt_GDBM:
645                 any = 1;
646                 rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
647                 break;
648              #endif
649               default:
650                 rc = G10ERR_UNSUPPORTED;
651                 break;
652             }
653
654             if( !rc ) {
655                 kbpos->resno = i;
656                 kbpos->fp = NULL;
657                 return 0;
658             }
659             else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
660                 log_error("error searching resource %d: %s\n",
661                                                   i, g10_errstr(rc));
662                 last_rc = rc;
663             }
664         }
665     }
666
667     return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
668 }
669
670
671
672
673 /****************
674  * Lock the keyblock; wait until it's available
675  * This function may change the internal data in kbpos, in cases
676  * when the keyblock to be locked has been modified.
677  * fixme: remove this function and add an option to search()?
678  */
679 int
680 lock_keyblock( KBPOS *kbpos )
681 {
682     if( !check_pos(kbpos) )
683         return G10ERR_GENERAL;
684     return 0;
685 }
686
687 /****************
688  * Release a lock on a keyblock
689  */
690 void
691 unlock_keyblock( KBPOS *kbpos )
692 {
693     if( !check_pos(kbpos) )
694         BUG();
695 }
696
697 /****************
698  * Read a complete keyblock and return the root in ret_root.
699  */
700 int
701 read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
702 {
703     if( !check_pos(kbpos) )
704         return G10ERR_GENERAL;
705
706     switch( kbpos->rt ) {
707       case rt_RING:
708         return keyring_read( kbpos, ret_root );
709      #ifdef HAVE_LIBGDBM
710       case rt_GDBM:
711         return do_gdbm_read( kbpos, ret_root );
712      #endif
713       default: BUG();
714     }
715 }
716
717
718 /****************
719  * This functions can be used to read through a complete keyring.
720  * Mode is: 0 = open
721  *          1 = read
722  *          2 = close
723  *          5 = open secret keyrings
724  *          11 = read but skip signature and comment packets.
725  *          all others are reserved!
726  * Note that you do not need a search prior to this function,
727  * only a handle is needed.
728  * NOTE: It is not allowed to do an insert/update/delete with this
729  *       keyblock, if you want to do this, use search/read!
730  */
731 int
732 enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
733 {
734     int rc = 0;
735     RESTBL *rentry;
736
737     if( !mode || mode == 5 || mode == 100 ) {
738         int i;
739
740         kbpos->fp = NULL;
741         kbpos->rt = rt_UNKNOWN;
742         if( !mode ) {
743             kbpos->secret = 0;
744             i = 0;
745         }
746         else if( mode == 5 ) {
747             kbpos->secret = 1;
748             mode = 0;
749             i = 0;
750         }
751         else
752             i = kbpos->resno+1;
753         for(; i < MAX_RESOURCES; i++ )
754             if( resource_table[i].used
755                 && !resource_table[i].secret == !kbpos->secret )
756                 break;
757         if( i == MAX_RESOURCES )
758             return -1; /* no resources */
759         kbpos->resno = i;
760         rentry = check_pos( kbpos );
761         kbpos->rt = resource_table[i].rt;
762         kbpos->valid = 0;
763         switch( kbpos->rt ) {
764           case rt_RING:
765             kbpos->fp = iobuf_open( rentry->fname );
766             if( !kbpos->fp ) {
767                 log_error("can't open `%s'\n", rentry->fname );
768                 return G10ERR_OPEN_FILE;
769             }
770             break;
771          #ifdef HAVE_LIBGDBM
772           case rt_GDBM:
773             /* FIXME: make sure that there is only one enum at a time */
774             kbpos->offset = 0;
775             break;
776          #endif
777           default: BUG();
778         }
779         kbpos->pkt = NULL;
780     }
781     else if( mode == 1 || mode == 11 ) {
782         int cont;
783         do {
784             cont = 0;
785             switch( kbpos->rt ) {
786               case rt_RING:
787                 if( !kbpos->fp )
788                     return G10ERR_GENERAL;
789                 rc = keyring_enum( kbpos, ret_root, mode == 11 );
790                 break;
791              #ifdef HAVE_LIBGDBM
792               case rt_GDBM:
793                 rc = do_gdbm_enum( kbpos, ret_root );
794                 break;
795              #endif
796               default: BUG();
797             }
798
799             if( rc == -1 ) {
800                 assert( !kbpos->pkt );
801                 rentry = check_pos( kbpos );
802                 assert(rentry);
803                 /* close */
804                 enum_keyblocks(2, kbpos, ret_root );
805                 /* and open the next one */
806                 rc = enum_keyblocks(100, kbpos, ret_root );
807                 if( !rc )
808                     cont = 1;
809             }
810         } while(cont);
811     }
812     else {
813         switch( kbpos->rt ) {
814           case rt_RING:
815             if( kbpos->fp ) {
816                 iobuf_close( kbpos->fp );
817                 kbpos->fp = NULL;
818             }
819             break;
820           case rt_GDBM:
821             break;
822           case rt_UNKNOWN:
823             /* this happens when we have no keyring at all */
824             return rc;
825
826           default:
827             BUG();
828         }
829         /* release pending packet */
830         free_packet( kbpos->pkt );
831         gcry_free( kbpos->pkt );
832     }
833     return rc;
834 }
835
836
837
838
839 /****************
840  * Insert the keyblock described by ROOT into the keyring described
841  * by KBPOS.  This actually appends the data to the keyfile.
842  */
843 int
844 insert_keyblock( KBPOS *kbpos, KBNODE root )
845 {
846     int rc;
847
848     if( !check_pos(kbpos) )
849         return G10ERR_GENERAL;
850
851     switch( kbpos->rt ) {
852       case rt_RING:
853         rc = keyring_copy( kbpos, 1, root );
854         break;
855      #ifdef HAVE_LIBGDBM
856       case rt_GDBM:
857         rc = do_gdbm_store( kbpos, root, 0 );
858         break;
859      #endif
860       default: BUG();
861     }
862
863     return rc;
864 }
865
866 /****************
867  * Delete the keyblock described by KBPOS.
868  * The current code simply changes the keyblock in the keyring
869  * to packet of type 0 with the correct length.  To help detect errors,
870  * zero bytes are written.
871  */
872 int
873 delete_keyblock( KBPOS *kbpos )
874 {
875     int rc;
876
877     if( !check_pos(kbpos) )
878         return G10ERR_GENERAL;
879
880     switch( kbpos->rt ) {
881       case rt_RING:
882         rc = keyring_copy( kbpos, 2, NULL );
883         break;
884      #ifdef HAVE_LIBGDBM
885       case rt_GDBM:
886         log_debug("deleting gdbm keyblock is not yet implemented\n");
887         rc = 0;
888         break;
889      #endif
890       default: BUG();
891     }
892
893     return rc;
894 }
895
896
897 /****************
898  * Update the keyblock at KBPOS with the one in ROOT.
899  */
900 int
901 update_keyblock( KBPOS *kbpos, KBNODE root )
902 {
903     int rc;
904
905     if( !check_pos(kbpos) )
906         return G10ERR_GENERAL;
907
908     switch( kbpos->rt ) {
909       case rt_RING:
910         rc = keyring_copy( kbpos, 3, root );
911         break;
912      #ifdef HAVE_LIBGDBM
913       case rt_GDBM:
914         rc = do_gdbm_store( kbpos, root, 1 );
915         break;
916      #endif
917       default: BUG();
918     }
919
920     return rc;
921 }
922
923
924 \f
925 /****************************************************************
926  ********** Implemenation of a user ID database    **************
927  ****************************************************************/
928 #if 0
929 /****************
930  * Layout of the user ID db
931  *
932  * This user ID DB provides fast lookup of user ID, but the user ids are
933  * not in any specific order.
934  *
935  * A string "GnuPG user db", a \n.
936  * user ids of one key, delimited by \t,
937  * a # or ^ followed by a 20 byte fingerprint, followed by an \n
938  * The literal characters %, \n, \t, #, ^ must be replaced by a percent sign
939  * and their hex value.
940  *
941  * (We use Boyer/Moore pattern matching)
942  */
943
944 /****************
945  * This compiles pattern to the distance table, the table will be allocate
946  * here and must be freed by using free().
947  * Returns: Ptr to new allocated Table
948  *          Caller must free the table.
949  */
950
951 static size_t *
952 compile_bm_table( const byte *pattern, size_t len )
953 {
954     ushort *dist;
955     int i;
956
957     dist = gcry_xcalloc( 1, 256 * sizeof *dist );
958     for(i=0; i < 256; i++ )
959         dist[i] = len;
960     for(i=0; i < len-1; i++ )
961         dTbl[p[i]] = len-i-1;
962     return dist;
963 }
964
965
966
967
968 /****************
969  * Search BUF of BUFLEN for pattern P of length PATLEN.
970  * dist is the Boyer/Moore distance table of 256 Elements,
971  * case insensitive search is done if IGNCASE is true (In this case
972  * the distance table has to compiled from uppercase chacaters and
973  * PAT must also be uppercase.
974  * Returns: Prt to maching string in BUF, or NULL if not found.
975  */
976
977 static const *
978 do_bm_search( const byte *buf, size_t buflen,
979               const byte *pat, size_t patlen, size_t *dist, int igncase )
980 {
981     int i, j, k;
982
983     if( igncase ) {
984         int c, c1;
985
986         for( i = --patlen; i < buflen; i += dist[c1] )
987             for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
988                                           j--, k--, c=toupper(buf[k]) ) {
989                 if( !j )
990                     return buf+k;
991             }
992     }
993     else {
994         for( i = --patlen; i < buflen; i += dist[buf[i]] )
995             for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
996                 if( !j )
997                     return buf+k;
998             }
999     }
1000     return NULL;
1001 }
1002
1003
1004 typedef struct {
1005     size_t dist[256];
1006 } *SCAN_USER_HANDLE;
1007
1008 static SCAN_USER_HANDLE
1009 scan_user_file_open( const byte *name )
1010 {
1011     SCAN_USER_HANDLE hd;
1012     size_t *dist;
1013     int i;
1014
1015     hd = gcry_xcalloc( 1, sizeof *hd );
1016     dist = hd->dist;
1017     /* compile the distance table */
1018     for(i=0; i < 256; i++ )
1019         dist[i] = len;
1020     for(i=0; i < len-1; i++ )
1021         dTbl[p[i]] = len-i-1;
1022     /* setup other things */
1023
1024     return hd;
1025 }
1026
1027 static int
1028 scan_user_file_close( SCAN_USER_HANDLE hd )
1029 {
1030     gcry_free( hd );
1031 }
1032
1033 static int
1034 scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
1035 {
1036     char record[1000];
1037
1038     /* read a record */
1039
1040
1041 }
1042 #endif
1043
1044
1045 \f
1046 /****************************************************************
1047  ********** Functions which operates on regular keyrings ********
1048  ****************************************************************/
1049
1050 static int
1051 cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
1052 {
1053     int n,i;
1054
1055     assert( req_sk->pubkey_algo == sk->pubkey_algo );
1056
1057     n = pubkey_get_nskey( req_sk->pubkey_algo );
1058     for(i=0; i < n; i++ ) {
1059         if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
1060             return -1;
1061     }
1062     return 0;
1063 }
1064
1065 static int
1066 cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
1067 {
1068     int n, i;
1069
1070     assert( req_pk->pubkey_algo == pk->pubkey_algo );
1071
1072     n = pubkey_get_npkey( req_pk->pubkey_algo );
1073     for(i=0; i < n; i++ ) {
1074         if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] )  )
1075             return -1;
1076     }
1077     return 0;
1078 }
1079
1080 /****************
1081  * search one keyring, return 0 if found, -1 if not found or an errorcode.
1082  */
1083 static int
1084 keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
1085 {
1086     int rc;
1087     PACKET pkt;
1088     int save_mode;
1089     ulong offset;
1090     int pkttype = req->pkttype;
1091     PKT_public_key *req_pk = req->pkt.public_key;
1092     PKT_secret_key *req_sk = req->pkt.secret_key;
1093
1094     init_packet(&pkt);
1095     save_mode = set_packet_list_mode(0);
1096     kbpos->rt = rt_RING;
1097     kbpos->valid = 0;
1098
1099   #if HAVE_DOSISH_SYSTEM || 1
1100     assert(!iobuf);
1101     iobuf = iobuf_open( fname );
1102     if( !iobuf ) {
1103         log_error("%s: can't open keyring file\n", fname);
1104         rc = G10ERR_KEYRING_OPEN;
1105         goto leave;
1106     }
1107   #else
1108     if( iobuf_seek( iobuf, 0 ) ) {
1109         log_error("can't rewind keyring file\n");
1110         rc = G10ERR_KEYRING_OPEN;
1111         goto leave;
1112     }
1113   #endif
1114
1115     while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
1116         if( pkt.pkttype == PKT_SECRET_KEY ) {
1117             PKT_secret_key *sk = pkt.pkt.secret_key;
1118
1119             if(   req_sk->timestamp == sk->timestamp
1120                && req_sk->pubkey_algo == sk->pubkey_algo
1121                && !cmp_seckey( req_sk, sk) )
1122                 break; /* found */
1123         }
1124         else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
1125             PKT_public_key *pk = pkt.pkt.public_key;
1126
1127             if(   req_pk->timestamp == pk->timestamp
1128                && req_pk->pubkey_algo == pk->pubkey_algo
1129                && !cmp_pubkey( req_pk, pk ) )
1130                 break; /* found */
1131         }
1132         else
1133             BUG();
1134         free_packet(&pkt);
1135     }
1136     if( !rc ) {
1137         kbpos->offset = offset;
1138         kbpos->valid = 1;
1139     }
1140
1141   leave:
1142     free_packet(&pkt);
1143     set_packet_list_mode(save_mode);
1144   #if HAVE_DOSISH_SYSTEM || 1
1145     iobuf_close(iobuf);
1146   #endif
1147     return rc;
1148 }
1149
1150
1151 static int
1152 keyring_read( KBPOS *kbpos, KBNODE *ret_root )
1153 {
1154     PACKET *pkt;
1155     int rc;
1156     RESTBL *rentry;
1157     KBNODE root = NULL;
1158     IOBUF a;
1159     int in_cert = 0;
1160
1161     if( !(rentry=check_pos(kbpos)) )
1162         return G10ERR_GENERAL;
1163
1164     a = iobuf_open( rentry->fname );
1165     if( !a ) {
1166         log_error("can't open `%s'\n", rentry->fname );
1167         return G10ERR_OPEN_FILE;
1168     }
1169
1170     if( !kbpos->valid )
1171         log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
1172     if( iobuf_seek( a, kbpos->offset ) ) {
1173         log_error("can't seek to %lu\n", kbpos->offset);
1174         iobuf_close(a);
1175         return G10ERR_KEYRING_OPEN;
1176     }
1177
1178     pkt = gcry_xmalloc( sizeof *pkt );
1179     init_packet(pkt);
1180     kbpos->count=0;
1181     while( (rc=parse_packet(a, pkt)) != -1 ) {
1182         if( rc ) {  /* ignore errors */
1183             if( rc != G10ERR_UNKNOWN_PACKET ) {
1184                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
1185                 rc = G10ERR_INV_KEYRING;
1186                 goto ready;
1187             }
1188             kbpos->count++;
1189             free_packet( pkt );
1190             init_packet( pkt );
1191             continue;
1192         }
1193         /* make a linked list of all packets */
1194         switch( pkt->pkttype ) {
1195           case PKT_COMPRESSED:
1196             log_error("skipped compressed packet in keyring\n" );
1197             free_packet(pkt);
1198             init_packet(pkt);
1199             break;
1200
1201           case PKT_PUBLIC_KEY:
1202           case PKT_SECRET_KEY:
1203             if( in_cert )
1204                 goto ready;
1205             in_cert = 1;
1206           default:
1207             kbpos->count++;
1208             if( !root )
1209                 root = new_kbnode( pkt );
1210             else
1211                 add_kbnode( root, new_kbnode( pkt ) );
1212             pkt = gcry_xmalloc( sizeof *pkt );
1213             init_packet(pkt);
1214             break;
1215         }
1216     }
1217   ready:
1218     kbpos->valid = 0;
1219     if( rc == -1 && root )
1220         rc = 0;
1221
1222     if( rc )
1223         release_kbnode( root );
1224     else
1225         *ret_root = root;
1226     free_packet( pkt );
1227     gcry_free( pkt );
1228     iobuf_close(a);
1229     return rc;
1230 }
1231
1232
1233 static int
1234 keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
1235 {
1236     PACKET *pkt;
1237     int rc;
1238     RESTBL *rentry;
1239     KBNODE root = NULL;
1240
1241     if( !(rentry=check_pos(kbpos)) )
1242         return G10ERR_GENERAL;
1243
1244     if( kbpos->pkt ) {
1245         root = new_kbnode( kbpos->pkt );
1246         kbpos->pkt = NULL;
1247     }
1248
1249     pkt = gcry_xmalloc( sizeof *pkt );
1250     init_packet(pkt);
1251     while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
1252         if( rc ) {  /* ignore errors */
1253             if( rc != G10ERR_UNKNOWN_PACKET ) {
1254                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
1255                 rc = G10ERR_INV_KEYRING;
1256                 goto ready;
1257             }
1258             free_packet( pkt );
1259             init_packet( pkt );
1260             continue;
1261         }
1262         /* make a linked list of all packets */
1263         switch( pkt->pkttype ) {
1264           case PKT_COMPRESSED:
1265             log_error("skipped compressed packet in keyring\n" );
1266             free_packet(pkt);
1267             init_packet(pkt);
1268             break;
1269
1270           case PKT_PUBLIC_KEY:
1271           case PKT_SECRET_KEY:
1272             if( root ) { /* store this packet */
1273                 kbpos->pkt = pkt;
1274                 pkt = NULL;
1275                 goto ready;
1276             }
1277             root = new_kbnode( pkt );
1278             pkt = gcry_xmalloc( sizeof *pkt );
1279             init_packet(pkt);
1280             break;
1281
1282           default:
1283             /* skip pakets at the beginning of a keyring, until we find
1284              * a start packet; issue a warning if it is not a comment */
1285             if( !root && pkt->pkttype != PKT_COMMENT
1286                       && pkt->pkttype != PKT_OLD_COMMENT ) {
1287                 break;
1288             }
1289             if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
1290                                       ||pkt->pkttype == PKT_COMMENT
1291                                       ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
1292                 init_packet(pkt);
1293                 break;
1294             }
1295             add_kbnode( root, new_kbnode( pkt ) );
1296             pkt = gcry_xmalloc( sizeof *pkt );
1297             init_packet(pkt);
1298             break;
1299         }
1300     }
1301   ready:
1302     if( rc == -1 && root )
1303         rc = 0;
1304
1305     if( rc )
1306         release_kbnode( root );
1307     else
1308         *ret_root = root;
1309     free_packet( pkt );
1310     gcry_free( pkt );
1311
1312     return rc;
1313 }
1314
1315
1316 /****************
1317  * Perform insert/delete/update operation.
1318  * mode 1 = insert
1319  *      2 = delete
1320  *      3 = update
1321  */
1322 static int
1323 keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
1324 {
1325     RESTBL *rentry;
1326     IOBUF fp, newfp;
1327     int rc=0;
1328     char *bakfname = NULL;
1329     char *tmpfname = NULL;
1330
1331     if( !(rentry = check_pos( kbpos )) )
1332         return G10ERR_GENERAL;
1333     if( kbpos->fp )
1334         BUG(); /* not allowed with such a handle */
1335
1336     if( opt.dry_run )
1337         return 0;
1338
1339     lock_rentry( rentry );
1340
1341     /* open the source file */
1342     fp = iobuf_open( rentry->fname );
1343     if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
1344         KBNODE kbctx, node;
1345
1346         /* insert: create a new file */
1347         newfp = iobuf_create( rentry->fname );
1348         if( !newfp ) {
1349             log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno));
1350             unlock_rentry( rentry );
1351             return G10ERR_OPEN_FILE;
1352         }
1353         else if( !opt.quiet )
1354             log_info(_("%s: keyring created\n"), rentry->fname );
1355
1356         kbctx=NULL;
1357         while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
1358             if( (rc = build_packet( newfp, node->pkt )) ) {
1359                 log_error("build_packet(%d) failed: %s\n",
1360                             node->pkt->pkttype, g10_errstr(rc) );
1361                 iobuf_cancel(newfp);
1362                 unlock_rentry( rentry );
1363                 return G10ERR_WRITE_FILE;
1364             }
1365         }
1366         if( iobuf_close(newfp) ) {
1367             log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
1368             unlock_rentry( rentry );
1369             return G10ERR_CLOSE_FILE;
1370         }
1371         if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
1372             log_error("%s: chmod failed: %s\n",
1373                                     rentry->fname, strerror(errno) );
1374             unlock_rentry( rentry );
1375             return G10ERR_WRITE_FILE;
1376         }
1377         return 0;
1378     }
1379     if( !fp ) {
1380         log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
1381         rc = G10ERR_OPEN_FILE;
1382         goto leave;
1383     }
1384
1385     /* create the new file */
1386   #ifdef USE_ONLY_8DOT3
1387     /* Here is another Windoze bug?:
1388      * you cant rename("pubring.gpg.tmp", "pubring.gpg");
1389      * but      rename("pubring.gpg.tmp", "pubring.aaa");
1390      * works.  So we replace .gpg by .bak or .tmp
1391      */
1392     if( strlen(rentry->fname) > 4
1393         && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) {
1394         bakfname = gcry_xmalloc( strlen( rentry->fname ) + 1 );
1395         strcpy(bakfname,rentry->fname);
1396         strcpy(bakfname+strlen(rentry->fname)-4, ".bak");
1397         tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 1 );
1398         strcpy(tmpfname,rentry->fname);
1399         strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp");
1400     }
1401     else { /* file does not end with gpg; hmmm */
1402         bakfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
1403         strcpy(stpcpy(bakfname,rentry->fname),".bak");
1404         tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
1405         strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
1406     }
1407   #else
1408     bakfname = gcry_xmalloc( strlen( rentry->fname ) + 2 );
1409     strcpy(stpcpy(bakfname,rentry->fname),"~");
1410     tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
1411     strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
1412   #endif
1413     newfp = iobuf_create( tmpfname );
1414     if( !newfp ) {
1415         log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
1416         iobuf_close(fp);
1417         rc = G10ERR_OPEN_FILE;
1418         goto leave;
1419     }
1420
1421     if( mode == 1 ) { /* insert */
1422         /* copy everything to the new file */
1423         rc = copy_all_packets( fp, newfp );
1424         if( rc != -1 ) {
1425             log_error("%s: copy to %s failed: %s\n",
1426                       rentry->fname, tmpfname, g10_errstr(rc) );
1427             iobuf_close(fp);
1428             iobuf_cancel(newfp);
1429             goto leave;
1430         }
1431         rc = 0;
1432     }
1433
1434     if( mode == 2 || mode == 3 ) { /* delete or update */
1435         /* copy first part to the new file */
1436         rc = copy_some_packets( fp, newfp, kbpos->offset );
1437         if( rc ) { /* should never get EOF here */
1438             log_error("%s: copy to %s failed: %s\n",
1439                       rentry->fname, tmpfname, g10_errstr(rc) );
1440             iobuf_close(fp);
1441             iobuf_cancel(newfp);
1442             goto leave;
1443         }
1444         /* skip this keyblock */
1445         assert( kbpos->count );
1446         rc = skip_some_packets( fp, kbpos->count );
1447         if( rc ) {
1448             log_error("%s: skipping %u packets failed: %s\n",
1449                             rentry->fname, kbpos->count, g10_errstr(rc));
1450             iobuf_close(fp);
1451             iobuf_cancel(newfp);
1452             goto leave;
1453         }
1454     }
1455
1456     if( mode == 1 || mode == 3 ) { /* insert or update */
1457         KBNODE kbctx, node;
1458
1459         /* append the new data */
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_close(fp);
1466                 iobuf_cancel(newfp);
1467                 rc = G10ERR_WRITE_FILE;
1468                 goto leave;
1469             }
1470         }
1471         kbpos->valid = 0;
1472     }
1473
1474     if( mode == 2 || mode == 3 ) { /* delete or update */
1475         /* copy the rest */
1476         rc = copy_all_packets( fp, newfp );
1477         if( rc != -1 ) {
1478             log_error("%s: copy to %s failed: %s\n",
1479                       rentry->fname, tmpfname, g10_errstr(rc) );
1480             iobuf_close(fp);
1481             iobuf_cancel(newfp);
1482             goto leave;
1483         }
1484         rc = 0;
1485     }
1486
1487     /* close both files */
1488     if( iobuf_close(fp) ) {
1489         log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) );
1490         rc = G10ERR_CLOSE_FILE;
1491         goto leave;
1492     }
1493     if( iobuf_close(newfp) ) {
1494         log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
1495         rc = G10ERR_CLOSE_FILE;
1496         goto leave;
1497     }
1498     /* if the new file is a secring, restrict the permissions */
1499   #ifndef HAVE_DOSISH_SYSTEM
1500     if( rentry->secret ) {
1501         if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
1502             log_error("%s: chmod failed: %s\n",
1503                                     tmpfname, strerror(errno) );
1504             rc = G10ERR_WRITE_FILE;
1505             goto leave;
1506         }
1507     }
1508   #endif
1509
1510     /* rename and make backup file */
1511     if( !rentry->secret ) {  /* but not for secret keyrings */
1512       #ifdef HAVE_DOSISH_SYSTEM
1513         remove( bakfname );
1514       #endif
1515         if( rename( rentry->fname, bakfname ) ) {
1516             log_error("%s: rename to %s failed: %s\n",
1517                                     rentry->fname, bakfname, strerror(errno) );
1518             rc = G10ERR_RENAME_FILE;
1519             goto leave;
1520         }
1521     }
1522   #ifdef HAVE_DOSISH_SYSTEM
1523     remove( rentry->fname );
1524   #endif
1525     if( rename( tmpfname, rentry->fname ) ) {
1526         log_error("%s: rename to %s failed: %s\n",
1527                             tmpfname, rentry->fname,strerror(errno) );
1528         rc = G10ERR_RENAME_FILE;
1529         if( rentry->secret ) {
1530             log_info(_(
1531                 "WARNING: 2 files with confidential information exists.\n"));
1532             log_info(_("%s is the unchanged one\n"), rentry->fname );
1533             log_info(_("%s is the new one\n"), tmpfname );
1534             log_info(_("Please fix this possible security flaw\n"));
1535         }
1536         goto leave;
1537     }
1538
1539   leave:
1540     unlock_rentry( rentry );
1541     gcry_free(bakfname);
1542     gcry_free(tmpfname);
1543     return rc;
1544 }
1545
1546 \f
1547 #ifdef HAVE_LIBGDBM
1548 /****************************************************************
1549  ********** Functions which operates on GDM files ***************
1550  ****************************************************************/
1551
1552 #if MAX_FINGERPRINT_LEN > 20
1553   #error A GDBM keyring assumes that fingerprints are less than 21
1554 #endif
1555
1556 /****************
1557  * Insert the keyblock into the GDBM database
1558  */
1559
1560 static int
1561 do_gdbm_store( KBPOS *kbpos, KBNODE root, int update )
1562 {
1563     RESTBL *rentry;
1564     PKT_public_key *pk;
1565     KBNODE kbctx, node;
1566     IOBUF fp = NULL;
1567     byte fpr[20];
1568     byte contbuf[21];
1569     byte keybuf[21];
1570     size_t fprlen;
1571     datum key, content;
1572     int i, rc;
1573
1574     if( !(rentry = check_pos( kbpos )) )
1575         return G10ERR_GENERAL;
1576
1577     if( opt.dry_run )
1578         return 0;
1579
1580     /* construct the fingerprint which is used as the primary key */
1581     node = find_kbnode( root, PKT_PUBLIC_KEY );
1582     if( !node )
1583         log_bug("a gdbm database can't store secret keys\n");
1584     pk = node->pkt->pkt.public_key;
1585
1586     fingerprint_from_pk( pk, fpr, &fprlen );
1587     for(i=fprlen; i < DIM(fpr); i++ )
1588         fpr[i] = 0;
1589
1590     /* build the keyblock */
1591     kbctx=NULL;
1592     fp = iobuf_temp();
1593     iobuf_put( fp, 1 ); /* data is a keyblock */
1594     while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
1595         if( (rc = build_packet( fp, node->pkt )) ) {
1596             log_error("build_packet(%d) failed: %s\n",
1597                         node->pkt->pkttype, g10_errstr(rc) );
1598             rc = G10ERR_WRITE_FILE;
1599             goto leave;
1600         }
1601     }
1602     /* store data and key */
1603     *keybuf = 1;   /* key is a padded fingerprint */
1604     memcpy(keybuf+1, fpr, 20 );
1605     key.dptr  = keybuf;
1606     key.dsize = 21;
1607     content.dptr  = iobuf_get_temp_buffer( fp );
1608     content.dsize = iobuf_get_temp_length( fp );
1609     rc = gdbm_store( rentry->dbf, key, content,
1610                                   update? GDBM_REPLACE : GDBM_INSERT );
1611     if( rc == 1 && !update )
1612         rc = gdbm_store( rentry->dbf, key, content, GDBM_REPLACE );
1613
1614     if( rc ) {
1615         log_error("%s: gdbm_store failed: %s\n", rentry->fname,
1616                             rc == 1 ? "already stored"
1617                                     : gdbm_strerror(gdbm_errno) );
1618         rc = G10ERR_WRITE_FILE;
1619         goto leave;
1620     }
1621     /* now store all keyids */
1622     *contbuf = 2;  /* data is a list of fingerprints */
1623     memcpy(contbuf+1, fpr, 20 );
1624     content.dptr = contbuf;
1625     content.dsize= 21;
1626     kbctx=NULL;
1627     while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
1628         if(    node->pkt->pkttype == PKT_PUBLIC_KEY
1629             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1630             u32 aki[2];
1631
1632             keyid_from_pk( node->pkt->pkt.public_key, aki );
1633             *keybuf = 2; /* key is a 8 byte keyid */
1634             u32tobuf( keybuf+1  , aki[0] );
1635             u32tobuf( keybuf+5, aki[1] );
1636             key.dptr = keybuf;
1637             key.dsize= 9;
1638             /* fixme: must be more clever when a insert failed:
1639              *        build a list of fingerprints in this case */
1640             rc = gdbm_store( rentry->dbf, key, content,
1641                                           update? GDBM_REPLACE : GDBM_INSERT );
1642             if( rc ) {
1643                 log_info("%s: gdbm_store keyid failed: %s\n", rentry->fname,
1644                                     rc == 1 ? "already stored"
1645                                             : gdbm_strerror(gdbm_errno) );
1646                 rc = 0;
1647             }
1648         }
1649     }
1650
1651   leave:
1652     iobuf_close(fp); /* don't need a cancel because it is a temp iobuf */
1653     return rc;
1654 }
1655
1656
1657
1658 /****************
1659  * search one keybox, return 0 if found, -1 if not found or an errorcode.
1660  */
1661 static int
1662 do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen )
1663 {
1664     byte *keybuf = kbpos->keybuf;
1665     datum key;
1666     int i;
1667
1668     *keybuf = 1;
1669     for(i=0; i < fprlen; i++ )
1670         keybuf[i+1] = fpr[i];
1671     for(; i < 20; i++ )
1672         keybuf[i+1] = 0;
1673
1674     /* fetch the data */
1675     key.dptr  = keybuf;
1676     key.dsize = 21;
1677     if( !gdbm_exists( dbf, key ) )
1678         return -1; /* not found */
1679     return 0;
1680 }
1681
1682 /****************
1683  * locate by keyid.
1684  * FIXME: we must have a way to enumerate thru the list opf fingerprints
1685  */
1686 static int
1687 do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
1688 {
1689     byte keybuf[9];
1690     datum key, content;
1691     int rc;
1692
1693     /* construct the fingerprint which is used as the primary key */
1694     *keybuf = 2;
1695     u32tobuf( keybuf+1, keyid[0] );
1696     u32tobuf( keybuf+5, keyid[1] );
1697
1698     /* fetch the data */
1699     key.dptr  = keybuf;
1700     key.dsize = 9;
1701     content = gdbm_fetch( dbf, key );
1702     if( !content.dptr )
1703         return -1;
1704
1705     if( content.dsize < 2 ) {
1706         log_error("gdbm_fetch did not return enough data\n" );
1707         free( content.dptr ); /* can't use gcry_free() here */
1708         return G10ERR_INV_KEYRING;
1709     }
1710     if( *content.dptr != 2 ) {
1711         log_error("gdbm_fetch returned unexpected type %d\n",
1712                     *(byte*)content.dptr );
1713         free( content.dptr ); /* can't use gcry_free() here */
1714         return G10ERR_INV_KEYRING;
1715     }
1716     if( content.dsize < 21 ) {
1717         log_error("gdbm_fetch did not return a complete fingerprint\n" );
1718         free( content.dptr ); /* can't use gcry_free() here */
1719         return G10ERR_INV_KEYRING;
1720     }
1721     if( content.dsize > 21 )
1722         log_info("gdbm_fetch: WARNING: more than one fingerprint\n" );
1723
1724     rc = do_gdbm_locate( dbf, kbpos, content.dptr+1, 20 );
1725     free( content.dptr ); /* can't use gcry_free() here */
1726     return rc;
1727 }
1728
1729
1730
1731 static int
1732 do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
1733 {
1734     PACKET *pkt;
1735     int rc;
1736     RESTBL *rentry;
1737     KBNODE root = NULL;
1738     IOBUF a;
1739     datum key, content;
1740
1741     if( !(rentry=check_pos(kbpos)) )
1742         return G10ERR_GENERAL;
1743
1744     key.dptr  = kbpos->keybuf;
1745     key.dsize = 21;
1746     content = gdbm_fetch( rentry->dbf, key );
1747     if( !content.dptr ) {
1748         log_error("gdbm_fetch failed: %s\n", gdbm_strerror(gdbm_errno) );
1749         return G10ERR_INV_KEYRING;
1750     }
1751     if( content.dsize < 2 ) {
1752         log_error("gdbm_fetch did not return enough data\n" );
1753         free( content.dptr ); /* can't use gcry_free() here */
1754         return G10ERR_INV_KEYRING;
1755     }
1756     if( *content.dptr != 1 ) {
1757         log_error("gdbm_fetch returned unexpected type %d\n",
1758                     *(byte*)content.dptr );
1759         free( content.dptr ); /* can't use gcry_free() here */
1760         return G10ERR_INV_KEYRING;
1761     }
1762
1763     a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 );
1764     free( content.dptr ); /* can't use gcry_free() here */
1765
1766     pkt = gcry_xmalloc( sizeof *pkt );
1767     init_packet(pkt);
1768     kbpos->count=0;
1769     while( (rc=parse_packet(a, pkt)) != -1 ) {
1770         if( rc ) {  /* ignore errors */
1771             if( rc != G10ERR_UNKNOWN_PACKET ) {
1772                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
1773                 rc = G10ERR_INV_KEYRING;
1774                 break;
1775             }
1776             kbpos->count++;
1777             free_packet( pkt );
1778             init_packet( pkt );
1779             continue;
1780         }
1781         /* make a linked list of all packets */
1782         kbpos->count++;
1783         if( !root )
1784             root = new_kbnode( pkt );
1785         else
1786             add_kbnode( root, new_kbnode( pkt ) );
1787         pkt = gcry_xmalloc( sizeof *pkt );
1788         init_packet(pkt);
1789     }
1790     if( rc == -1 && root )
1791         rc = 0;
1792     if( rc )
1793         release_kbnode( root );
1794     else
1795         *ret_root = root;
1796     free_packet( pkt );
1797     gcry_free( pkt );
1798     iobuf_close(a);
1799     return rc;
1800 }
1801
1802
1803 /****************
1804  * Enum over keyblok data
1805  */
1806 static int
1807 do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root )
1808 {
1809     RESTBL *rentry;
1810     datum key, helpkey;
1811
1812     if( !(rentry=check_pos(kbpos)) )
1813         return G10ERR_GENERAL;
1814
1815     if( !kbpos->offset ) {
1816         kbpos->offset = 1;
1817         key = gdbm_firstkey( rentry->dbf );
1818     }
1819     else {
1820         helpkey.dptr = kbpos->keybuf;
1821         helpkey.dsize= 21;
1822         key = gdbm_nextkey( rentry->dbf, helpkey );
1823     }
1824     while( key.dptr && (!key.dsize || *key.dptr != 1) ) {
1825         helpkey = key;
1826         key = gdbm_nextkey( rentry->dbf, helpkey );
1827         free( helpkey.dptr ); /* free and not gcry_free() ! */
1828     }
1829     if( !key.dptr )
1830         return -1; /* eof */
1831
1832     if( key.dsize < 21 ) {
1833         free( key.dptr ); /* free and not gcry_free() ! */
1834         log_error("do_gdm_enum: key is too short\n" );
1835         return G10ERR_INV_KEYRING;
1836     }
1837     memcpy( kbpos->keybuf, key.dptr, 21 );
1838     free( key.dptr ); /* free and not gcry_free() ! */
1839     return do_gdbm_read( kbpos, ret_root );
1840 }
1841
1842 #endif /*HAVE_LIBGDBM*/