Snapshot release 0.4.2
[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  * FIXME:  Keep track of all nodes, so that a change is propagated
39  *         to all nodes. (or use shallow copies and ref-counting?)
40  */
41
42
43
44 #include <config.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <unistd.h> /* for truncate */
52 #include <assert.h>
53 #ifdef HAVE_LIBGDBM
54   #include <gdbm.h>
55 #endif
56 #include "util.h"
57 #include "packet.h"
58 #include "memory.h"
59 #include "mpi.h"
60 #include "iobuf.h"
61 #include "keydb.h"
62 #include "options.h"
63 #include "i18n.h"
64
65 #undef HAVE_LIBGDBM  /* <--- not ready */
66
67 struct resource_table_struct {
68     int used;
69     int secret; /* this is a secret keyring */
70     char *fname;
71     IOBUF iobuf;
72   #ifdef HAVE_LIBGDBM
73     GDBM_FILE dbf;
74   #endif
75     enum resource_type rt;
76 };
77 typedef struct resource_table_struct RESTBL;
78
79 #define MAX_RESOURCES 10
80 static RESTBL resource_table[MAX_RESOURCES];
81
82 static int search( PACKET *pkt, KBPOS *kbpos, int secret );
83
84
85 static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
86                                                 const char *fname );
87 static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
88 static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
89 static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
90
91
92
93 static RESTBL *
94 check_pos( KBPOS *kbpos )
95 {
96     if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
97         return NULL;
98     if( !resource_table[kbpos->resno].used )
99         return NULL;
100     return resource_table + kbpos->resno;
101 }
102
103
104 /****************************************************************
105  ****************** public functions ****************************
106  ****************************************************************/
107
108 /****************
109  * Get the name of the keyrings, start with a sequence number pointing to a 0.
110  */
111 const char *
112 enum_keyblock_resources( int *sequence, int secret )
113 {
114     int i = *sequence;
115     const char *name = NULL;
116
117     for(; i < MAX_RESOURCES; i++ )
118         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
119             if( resource_table[i].fname ) {
120                 name = resource_table[i].fname;
121                 break;
122             }
123         }
124     *sequence = ++i;
125     return name;
126 }
127
128
129
130 /****************
131  * Register a resource (which currently may only be a keyring file).
132  * The first keyring which is added by this function is
133  * created if it does not exist.
134  * Note: this function may be called before secure memory is
135  * available.
136  */
137 int
138 add_keyblock_resource( const char *url, int force, int secret )
139 {
140     static int any_secret, any_public;
141     const char *resname = url;
142     IOBUF iobuf;
143     int i;
144     char *filename = NULL;
145     int rc = 0;
146     enum resource_type rt = rt_UNKNOWN;
147
148     /* Do we have an URL?
149      *  gnupg-gdbm:filename  := this is a GDBM resource
150      *  gnupg-ring:filename  := this is a plain keyring
151      *  filename := See what is is, but create as plain keyring.
152      */
153     if( strlen( resname ) > 11 ) {
154         if( !strncmp( resname, "gnupg-ring:", 11 ) ) {
155             rt = rt_RING;
156             resname += 11;
157         }
158         else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
159             rt = rt_GDBM;
160             resname += 11;
161         }
162       #ifndef __MINGW32__
163         else if( strchr( resname, ':' ) ) {
164             log_error("%s: invalid URL\n", url );
165             rc = G10ERR_GENERAL;
166             goto leave;
167         }
168       #endif
169     }
170
171     if( *resname != '/' ) { /* do tilde expansion etc */
172         if( strchr(resname, '/') )
173             filename = make_filename(resname, NULL);
174         else
175             filename = make_filename(opt.homedir, resname, NULL);
176     }
177     else
178         filename = m_strdup( resname );
179
180     if( !force )
181         force = secret? !any_secret : !any_public;
182
183     for(i=0; i < MAX_RESOURCES; i++ )
184         if( !resource_table[i].used )
185             break;
186     if( i == MAX_RESOURCES ) {
187         rc = G10ERR_RESOURCE_LIMIT;
188         goto leave;
189     }
190
191
192     switch( rt ) {
193       case rt_UNKNOWN:
194       case rt_RING:
195         iobuf = iobuf_fopen( filename, "rb" );
196         if( !iobuf && !force ) {
197             rc = G10ERR_OPEN_FILE;
198             goto leave;
199         }
200
201         if( !iobuf ) {
202             iobuf = iobuf_create( filename );
203             if( !iobuf ) {
204                 log_error("%s: can't create: %s\n", filename, strerror(errno));
205                 rc = G10ERR_OPEN_FILE;
206                 goto leave;
207             }
208             else
209                 log_info("%s: keyring created\n", filename );
210         }
211         /* fixme: see whether it is really a ring or if type is unknown,
212          * try to figure out of what type it is
213          */
214         rt = rt_RING; /* <--- FIXME */
215
216       #ifdef __MINGW32__
217         /* must close it again */
218         iobuf_close( iobuf );
219         iobuf = NULL;
220       #endif
221         break;
222
223     #ifdef HAVE_LIBGDBM
224       case rt_GDBM:
225         break;
226     #endif
227
228       default:
229         log_error("%s: unsupported resource type\n", url );
230         rc = G10ERR_GENERAL;
231         goto leave;
232     }
233
234     resource_table[i].used = 1;
235     resource_table[i].secret = !!secret;
236     resource_table[i].fname = m_strdup(filename);
237     resource_table[i].iobuf = iobuf;
238     resource_table[i].rt    = rt;
239   leave:
240     if( rc )
241         log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) );
242     else if( secret )
243         any_secret = 1;
244     else
245         any_public = 1;
246     m_free( filename );
247     return rc;
248 }
249
250 /****************
251  * Return the resource name of the keyblock associated with KBPOS.
252  */
253 const char *
254 keyblock_resource_name( KBPOS *kbpos )
255 {
256     RESTBL *rentry;
257
258     if( !(rentry = check_pos( kbpos )) || !rentry->fname )
259         log_bug("no name for keyblock resource %d\n", kbpos->resno );
260     return rentry->fname;
261 }
262
263
264 /****************
265  * Get a keyblock handle KBPOS from a filename. This can be used
266  * to get a handle for insert_keyblock for a new keyblock.
267  * Using a filename of NULL returns the default resource
268  */
269 int
270 get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
271 {
272     int i;
273
274     for(i=0; i < MAX_RESOURCES; i++ )
275         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
276             /* fixme: dos needs case insensitive file compare */
277             if( !filename || !strcmp( resource_table[i].fname, filename ) ) {
278                 memset( kbpos, 0, sizeof *kbpos );
279                 kbpos->resno = i;
280                 kbpos->rt = resource_table[i].rt;
281                 return 0;
282             }
283         }
284     return -1; /* not found */
285 }
286
287
288
289 /****************
290  * Search a keyblock which starts with the given packet and puts all
291  * information into KBPOS, which can be used later to access this key block.
292  * This function looks into all registered keyblock sources.
293  * PACKET must be a packet with either a secret_key or a public_key
294  *
295  * This function is intended to check whether a given certificate
296  * is already in a keyring or to prepare it for editing.
297  *
298  * Returns: 0 if found, -1 if not found or an errorcode.
299  */
300 static int
301 search( PACKET *pkt, KBPOS *kbpos, int secret )
302 {
303     int i, rc, last_rc=-1;
304
305     for(i=0; i < MAX_RESOURCES; i++ ) {
306         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
307             switch( resource_table[i].rt ) {
308               case rt_RING:
309                 rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
310                                                  resource_table[i].fname );
311                 break;
312              #ifdef HAVE_LIBGDBM
313               case rt_GDBM
314                 rc = do_gdbm_search( pkt, kbpos, resource_table[i].dbf,
315                                                  resource_table[i].fname );
316                 break;
317              #endif
318               default: BUG();
319             }
320
321             if( !rc ) {
322                 kbpos->resno = i;
323                 kbpos->fp = NULL;
324                 return 0;
325             }
326             if( rc != -1 ) {
327                 log_error("error searching resource %d: %s\n",
328                                                   i, g10_errstr(rc));
329                 last_rc = rc;
330             }
331         }
332     }
333     return last_rc;
334 }
335
336
337 /****************
338  * Combined function to search for a username and get the position
339  * of the keyblock.
340  */
341 int
342 find_keyblock_byname( KBPOS *kbpos, const char *username )
343 {
344     PACKET pkt;
345     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
346     int rc;
347
348     rc = get_pubkey_byname( pk, username );
349     if( rc ) {
350         free_public_key(pk);
351         return rc;
352     }
353
354     init_packet( &pkt );
355     pkt.pkttype = PKT_PUBLIC_KEY;
356     pkt.pkt.public_key = pk;
357     rc = search( &pkt, kbpos, 0 );
358     free_public_key(pk);
359     return rc;
360 }
361
362
363 /****************
364  * Combined function to search for a key and get the position
365  * of the keyblock.
366  */
367 int
368 find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
369 {
370     PACKET pkt;
371     int rc;
372
373     init_packet( &pkt );
374     pkt.pkttype = PKT_PUBLIC_KEY;
375     pkt.pkt.public_key = pk;
376     rc = search( &pkt, kbpos, 0 );
377     return rc;
378 }
379
380
381 /****************
382  * Combined function to search for a username and get the position
383  * of the keyblock. This function does not unprotect the secret key.
384  */
385 int
386 find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
387 {
388     PACKET pkt;
389     PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
390     int rc;
391
392     rc = get_seckey_byname( sk, username, 0 );
393     if( rc ) {
394         free_secret_key(sk);
395         return rc;
396     }
397
398     init_packet( &pkt );
399     pkt.pkttype = PKT_SECRET_KEY;
400     pkt.pkt.secret_key = sk;
401     rc = search( &pkt, kbpos, 1 );
402     free_secret_key(sk);
403     return rc;
404 }
405
406
407
408 /****************
409  * Lock the keyblock; wait until it's available
410  * This function may change the internal data in kbpos, in cases
411  * when the keyblock to be locked has been modified.
412  * fixme: remove this function and add an option to search()?
413  */
414 int
415 lock_keyblock( KBPOS *kbpos )
416 {
417     if( !check_pos(kbpos) )
418         return G10ERR_GENERAL;
419     return 0;
420 }
421
422 /****************
423  * Release a lock on a keyblock
424  */
425 void
426 unlock_keyblock( KBPOS *kbpos )
427 {
428     if( !check_pos(kbpos) )
429         BUG();
430 }
431
432 /****************
433  * Read a complete keyblock and return the root in ret_root.
434  */
435 int
436 read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
437 {
438     if( !check_pos(kbpos) )
439         return G10ERR_GENERAL;
440
441     switch( kbpos->rt ) {
442       case rt_RING:
443         return keyring_read( kbpos, ret_root );
444      #ifdef HAVE_LIBGDBM
445       case rt_GDBM:
446         return do_gdbm_read( kbpos, ret_root );
447      #endif
448       default: BUG();
449     }
450 }
451
452
453 /****************
454  * This functions can be used to read through a complete keyring.
455  * Mode is: 0 = open
456  *          1 = read
457  *          2 = close
458  *          5 = open secret keyrings
459  *          11 = read but skip signature and comment packets.
460  *          all others are reserved!
461  * Note that you do not need a search prior to this function,
462  * only a handle is needed.
463  * NOTE: It is not allowed to do an insert/update/delete with this
464  *       keyblock, if you want to do this, use search/read!
465  */
466 int
467 enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
468 {
469     int rc = 0;
470     RESTBL *rentry;
471
472     if( !mode || mode == 5 || mode == 100 ) {
473         int i;
474         kbpos->fp = NULL;
475         if( !mode ) {
476             kbpos->secret = 0;
477             i = 0;
478         }
479         else if( mode == 5 ) {
480             kbpos->secret = 1;
481             mode = 0;
482             i = 0;
483         }
484         else
485             i = kbpos->resno+1;
486         for(; i < MAX_RESOURCES; i++ )
487             if( resource_table[i].used
488                 && !resource_table[i].secret == !kbpos->secret )
489                 break;
490         if( i == MAX_RESOURCES )
491             return -1; /* no resources */
492         kbpos->resno = i;
493         rentry = check_pos( kbpos );
494         kbpos->rt = resource_table[i].rt;
495         switch( kbpos->rt ) {
496           case rt_RING:
497             kbpos->fp = iobuf_fopen( rentry->fname, "rb" );
498             if( !kbpos->fp ) {
499                 log_error("can't open '%s'\n", rentry->fname );
500                 return G10ERR_OPEN_FILE;
501             }
502             break;
503          #ifdef HAVE_LIBGDBM
504           case rt_GDBM:
505             /* FIXME!!!! */
506             break;
507          #endif
508           default: BUG();
509         }
510         kbpos->pkt = NULL;
511     }
512     else if( mode == 1 || mode == 11 ) {
513         int cont;
514         do {
515             cont = 0;
516             switch( kbpos->rt ) {
517               case rt_RING:
518                 if( !kbpos->fp )
519                     return G10ERR_GENERAL;
520                 rc = keyring_enum( kbpos, ret_root, mode == 11 );
521                 break;
522              #ifdef HAVE_LIBGDBM
523               case rt_GDBM:
524                 /* FIXME!!!! */
525                 break;
526              #endif
527               default: BUG();
528             }
529
530             if( rc == -1 ) {
531                 assert( !kbpos->pkt );
532                 rentry = check_pos( kbpos );
533                 assert(rentry);
534                 /* close */
535                 enum_keyblocks(2, kbpos, ret_root );
536                 /* and open the next one */
537                 rc = enum_keyblocks(100, kbpos, ret_root );
538                 if( !rc )
539                     cont = 1;
540             }
541         } while(cont);
542     }
543     else {
544         switch( kbpos->rt ) {
545           case rt_RING:
546             if( kbpos->fp ) {
547                 iobuf_close( kbpos->fp );
548                 kbpos->fp = NULL;
549             }
550             break;
551          #ifdef HAVE_LIBGDBM
552           case rt_GDBM:
553             /* FIXME!!!! */
554             break;
555          #endif
556           default: BUG();
557         }
558         /* release pending packet */
559         free_packet( kbpos->pkt );
560         m_free( kbpos->pkt );
561     }
562     return rc;
563 }
564
565
566
567
568 /****************
569  * Insert the keyblock described by ROOT into the keyring described
570  * by KBPOS.  This actually appends the data to the keyfile.
571  */
572 int
573 insert_keyblock( KBPOS *kbpos, KBNODE root )
574 {
575     int rc;
576
577     if( !check_pos(kbpos) )
578         return G10ERR_GENERAL;
579
580     switch( kbpos->rt ) {
581       case rt_RING:
582         rc = keyring_copy( kbpos, 1, root );
583         break;
584      #ifdef HAVE_LIBGDBM
585       case rt_GDBM:
586         /* FIXME!!!! */
587         break;
588      #endif
589       default: BUG();
590     }
591
592     return rc;
593 }
594
595 /****************
596  * Delete the keyblock described by KBPOS.
597  * The current code simply changes the keyblock in the keyring
598  * to packet of type 0 with the correct length.  To help detect errors,
599  * zero bytes are written.
600  */
601 int
602 delete_keyblock( KBPOS *kbpos )
603 {
604     int rc;
605
606     if( !check_pos(kbpos) )
607         return G10ERR_GENERAL;
608
609     switch( kbpos->rt ) {
610       case rt_RING:
611         rc = keyring_copy( kbpos, 2, NULL );
612         break;
613      #ifdef HAVE_LIBGDBM
614       case rt_GDBM:
615         /* FIXME!!!! */
616         break;
617      #endif
618       default: BUG();
619     }
620
621     return rc;
622 }
623
624
625 /****************
626  * Update the keyblock at KBPOS with the one in ROOT.
627  */
628 int
629 update_keyblock( KBPOS *kbpos, KBNODE root )
630 {
631     int rc;
632
633     if( !check_pos(kbpos) )
634         return G10ERR_GENERAL;
635
636     switch( kbpos->rt ) {
637       case rt_RING:
638         rc = keyring_copy( kbpos, 3, root );
639         break;
640      #ifdef HAVE_LIBGDBM
641       case rt_GDBM:
642         /* FIXME!!!! */
643         break;
644      #endif
645       default: BUG();
646     }
647
648     return rc;
649 }
650
651
652 \f
653 /****************************************************************
654  ********** Functions which operates on regular keyrings ********
655  ****************************************************************/
656
657 static int
658 cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
659 {
660     int n,i;
661
662     assert( req_sk->pubkey_algo == sk->pubkey_algo );
663
664     n = pubkey_get_nskey( req_sk->pubkey_algo );
665     for(i=0; i < n; i++ ) {
666         if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
667             return -1;
668     }
669     return 0;
670 }
671
672 static int
673 cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
674 {
675     int n, i;
676
677     assert( req_pk->pubkey_algo == pk->pubkey_algo );
678
679     n = pubkey_get_npkey( req_pk->pubkey_algo );
680     for(i=0; i < n; i++ ) {
681         if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] )  )
682             return -1;
683     }
684     return 0;
685 }
686
687 /****************
688  * search one keyring, return 0 if found, -1 if not found or an errorcode.
689  */
690 static int
691 keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
692 {
693     int rc;
694     PACKET pkt;
695     int save_mode;
696     ulong offset;
697     int pkttype = req->pkttype;
698     PKT_public_key *req_pk = req->pkt.public_key;
699     PKT_secret_key *req_sk = req->pkt.secret_key;
700
701     init_packet(&pkt);
702     save_mode = set_packet_list_mode(0);
703     kbpos->rt = rt_RING;
704
705   #if __MINGW32__
706     assert(!iobuf);
707     iobuf = iobuf_open( fname );
708     if( !iobuf ) {
709         log_error("%s: can't open keyring file\n", fname);
710         rc = G10ERR_KEYRING_OPEN;
711         goto leave;
712     }
713   #else
714     if( iobuf_seek( iobuf, 0 ) ) {
715         log_error("can't rewind keyring file\n");
716         rc = G10ERR_KEYRING_OPEN;
717         goto leave;
718     }
719   #endif
720
721     while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
722         if( pkt.pkttype == PKT_SECRET_KEY ) {
723             PKT_secret_key *sk = pkt.pkt.secret_key;
724
725             if(   req_sk->timestamp == sk->timestamp
726                && req_sk->pubkey_algo == sk->pubkey_algo
727                && !cmp_seckey( req_sk, sk) )
728                 break; /* found */
729         }
730         else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
731             PKT_public_key *pk = pkt.pkt.public_key;
732
733             if(   req_pk->timestamp == pk->timestamp
734                && req_pk->pubkey_algo == pk->pubkey_algo
735                && !cmp_pubkey( req_pk, pk ) )
736                 break; /* found */
737         }
738         else
739             BUG();
740         free_packet(&pkt);
741     }
742     if( !rc )
743         kbpos->offset = offset;
744
745   leave:
746     free_packet(&pkt);
747     set_packet_list_mode(save_mode);
748   #if __MINGW32__
749     iobuf_close(iobuf);
750   #endif
751     return rc;
752 }
753
754
755 static int
756 keyring_read( KBPOS *kbpos, KBNODE *ret_root )
757 {
758     PACKET *pkt;
759     int rc;
760     RESTBL *rentry;
761     KBNODE root = NULL;
762     IOBUF a;
763     int in_cert = 0;
764
765     if( !(rentry=check_pos(kbpos)) )
766         return G10ERR_GENERAL;
767
768     a = iobuf_fopen( rentry->fname, "rb" );
769     if( !a ) {
770         log_error("can't open '%s'\n", rentry->fname );
771         return G10ERR_OPEN_FILE;
772     }
773
774     if( iobuf_seek( a, kbpos->offset ) ) {
775         log_error("can't seek to %lu\n", kbpos->offset);
776         iobuf_close(a);
777         return G10ERR_KEYRING_OPEN;
778     }
779
780     pkt = m_alloc( sizeof *pkt );
781     init_packet(pkt);
782     kbpos->count=0;
783     while( (rc=parse_packet(a, pkt)) != -1 ) {
784         if( rc ) {  /* ignore errors */
785             if( rc != G10ERR_UNKNOWN_PACKET ) {
786                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
787                 rc = G10ERR_INV_KEYRING;
788                 goto ready;
789             }
790             kbpos->count++;
791             free_packet( pkt );
792             init_packet( pkt );
793             continue;
794         }
795         /* make a linked list of all packets */
796         switch( pkt->pkttype ) {
797           case PKT_PUBLIC_KEY:
798           case PKT_SECRET_KEY:
799             if( in_cert )
800                 goto ready;
801             in_cert = 1;
802           default:
803             kbpos->count++;
804             if( !root )
805                 root = new_kbnode( pkt );
806             else
807                 add_kbnode( root, new_kbnode( pkt ) );
808             pkt = m_alloc( sizeof *pkt );
809             init_packet(pkt);
810             break;
811         }
812     }
813   ready:
814     if( rc == -1 && root )
815         rc = 0;
816
817     if( rc )
818         release_kbnode( root );
819     else
820         *ret_root = root;
821     free_packet( pkt );
822     m_free( pkt );
823     iobuf_close(a);
824     return rc;
825 }
826
827
828 static int
829 keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
830 {
831     PACKET *pkt;
832     int rc;
833     RESTBL *rentry;
834     KBNODE root = NULL;
835
836     if( !(rentry=check_pos(kbpos)) )
837         return G10ERR_GENERAL;
838
839     if( kbpos->pkt ) {
840         root = new_kbnode( kbpos->pkt );
841         kbpos->pkt = NULL;
842     }
843
844     pkt = m_alloc( sizeof *pkt );
845     init_packet(pkt);
846     while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
847         if( rc ) {  /* ignore errors */
848             if( rc != G10ERR_UNKNOWN_PACKET ) {
849                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
850                 rc = G10ERR_INV_KEYRING;
851                 goto ready;
852             }
853             free_packet( pkt );
854             init_packet( pkt );
855             continue;
856         }
857         /* make a linked list of all packets */
858         switch( pkt->pkttype ) {
859           case PKT_PUBLIC_KEY:
860           case PKT_SECRET_KEY:
861             if( root ) { /* store this packet */
862                 kbpos->pkt = pkt;
863                 pkt = NULL;
864                 goto ready;
865             }
866             root = new_kbnode( pkt );
867             pkt = m_alloc( sizeof *pkt );
868             init_packet(pkt);
869             break;
870
871           default:
872             /* skip pakets at the beginning of a keyring, until we find
873              * a start packet; issue a warning if it is not a comment */
874             if( !root && pkt->pkttype != PKT_COMMENT
875                       && pkt->pkttype != PKT_OLD_COMMENT ) {
876                 log_info("keyring_enum: skipped packet of type %d\n",
877                             pkt->pkttype );
878                 break;
879             }
880             if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
881                                       ||pkt->pkttype == PKT_COMMENT
882                                       ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
883                 init_packet(pkt);
884                 break;
885             }
886             add_kbnode( root, new_kbnode( pkt ) );
887             pkt = m_alloc( sizeof *pkt );
888             init_packet(pkt);
889             break;
890         }
891     }
892   ready:
893     if( rc == -1 && root )
894         rc = 0;
895
896     if( rc )
897         release_kbnode( root );
898     else
899         *ret_root = root;
900     free_packet( pkt );
901     m_free( pkt );
902
903     return rc;
904 }
905
906
907 /****************
908  * Perform insert/delete/update operation.
909  * mode 1 = insert
910  *      2 = delete
911  *      3 = update
912  */
913 static int
914 keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
915 {
916     RESTBL *rentry;
917     IOBUF fp, newfp;
918     int rc=0;
919     char *bakfname = NULL;
920     char *tmpfname = NULL;
921
922     if( !(rentry = check_pos( kbpos )) )
923         return G10ERR_GENERAL;
924     if( kbpos->fp )
925         BUG(); /* not allowed with such a handle */
926
927     /* open the source file */
928     fp = iobuf_fopen( rentry->fname, "rb" );
929     if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
930         KBNODE kbctx, node;
931
932         /* insert: create a new file */
933         newfp = iobuf_create( rentry->fname );
934         if( !newfp ) {
935             log_error("%s: can't create: %s\n", rentry->fname, strerror(errno));
936             return G10ERR_OPEN_FILE;
937         }
938         else
939             log_info("%s: keyring created\n", rentry->fname );
940
941         kbctx=NULL;
942         while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
943             if( (rc = build_packet( newfp, node->pkt )) ) {
944                 log_error("build_packet(%d) failed: %s\n",
945                             node->pkt->pkttype, g10_errstr(rc) );
946                 iobuf_cancel(newfp);
947                 return G10ERR_WRITE_FILE;
948             }
949         }
950         if( iobuf_close(newfp) ) {
951             log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
952             return G10ERR_CLOSE_FILE;
953         }
954         if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
955             log_error("%s: chmod failed: %s\n",
956                                     rentry->fname, strerror(errno) );
957             return G10ERR_WRITE_FILE;
958         }
959         return 0;
960     }
961     if( !fp ) {
962         log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
963         rc = G10ERR_OPEN_FILE;
964         goto leave;
965     }
966
967     /* create the new file */
968   #ifdef __MINGW32__
969     /* Here is another Windoze bug?:
970      * you cant rename("pubring.gpg.tmp", "pubring.gpg");
971      * but      rename("pubring.gpg.tmp", "pubring.aaa");
972      * works.  So we replace .gpg by .bak or .tmp
973      */
974     if( strlen(rentry->fname) > 4
975         && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) {
976         bakfname = m_alloc( strlen( rentry->fname ) + 1 );
977         strcpy(bakfname,rentry->fname);
978         strcpy(bakfname+strlen(rentry->fname)-4, ".bak");
979         tmpfname = m_alloc( strlen( rentry->fname ) + 1 );
980         strcpy(tmpfname,rentry->fname);
981         strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp");
982     }
983     else { /* file does not end with gpg; hmmm */
984         bakfname = m_alloc( strlen( rentry->fname ) + 5 );
985         strcpy(stpcpy(bakfname,rentry->fname),".bak");
986         tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
987         strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
988     }
989   #else
990     bakfname = m_alloc( strlen( rentry->fname ) + 2 );
991     strcpy(stpcpy(bakfname,rentry->fname),"~");
992     tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
993     strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
994   #endif
995     newfp = iobuf_create( tmpfname );
996     if( !newfp ) {
997         log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
998         iobuf_close(fp);
999         rc = G10ERR_OPEN_FILE;
1000         goto leave;
1001     }
1002
1003     if( mode == 1 ) { /* insert */
1004         /* copy everything to the new file */
1005         rc = copy_all_packets( fp, newfp );
1006         if( rc != -1 ) {
1007             log_error("%s: copy to %s failed: %s\n",
1008                       rentry->fname, tmpfname, g10_errstr(rc) );
1009             iobuf_close(fp);
1010             iobuf_cancel(newfp);
1011             goto leave;
1012         }
1013         rc = 0;
1014     }
1015
1016     if( mode == 2 || mode == 3 ) { /* delete or update */
1017         /* copy first part to the new file */
1018         rc = copy_some_packets( fp, newfp, kbpos->offset );
1019         if( rc ) { /* should never get EOF here */
1020             log_error("%s: copy to %s failed: %s\n",
1021                       rentry->fname, tmpfname, g10_errstr(rc) );
1022             iobuf_close(fp);
1023             iobuf_cancel(newfp);
1024             goto leave;
1025         }
1026         /* skip this keyblock */
1027         assert( kbpos->count );
1028         rc = skip_some_packets( fp, kbpos->count );
1029         if( rc ) {
1030             log_error("%s: skipping %u packets failed: %s\n",
1031                             rentry->fname, kbpos->count, g10_errstr(rc));
1032             iobuf_close(fp);
1033             iobuf_cancel(newfp);
1034             goto leave;
1035         }
1036     }
1037
1038     if( mode == 1 || mode == 3 ) { /* insert or update */
1039         KBNODE kbctx, node;
1040
1041         /* append the new data */
1042         kbctx=NULL;
1043         while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
1044             if( (rc = build_packet( newfp, node->pkt )) ) {
1045                 log_error("build_packet(%d) failed: %s\n",
1046                             node->pkt->pkttype, g10_errstr(rc) );
1047                 iobuf_close(fp);
1048                 iobuf_cancel(newfp);
1049                 rc = G10ERR_WRITE_FILE;
1050                 goto leave;
1051             }
1052         }
1053     }
1054
1055     if( mode == 2 || mode == 3 ) { /* delete or update */
1056         /* copy the rest */
1057         rc = copy_all_packets( fp, newfp );
1058         if( rc != -1 ) {
1059             log_error("%s: copy to %s failed: %s\n",
1060                       rentry->fname, tmpfname, g10_errstr(rc) );
1061             iobuf_close(fp);
1062             iobuf_cancel(newfp);
1063             goto leave;
1064         }
1065         rc = 0;
1066     }
1067
1068     /* close both files */
1069     if( iobuf_close(fp) ) {
1070         log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) );
1071         rc = G10ERR_CLOSE_FILE;
1072         goto leave;
1073     }
1074     if( iobuf_close(newfp) ) {
1075         log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
1076         rc = G10ERR_CLOSE_FILE;
1077         goto leave;
1078     }
1079     /* if the new file is a secring, restrict the permissions */
1080   #ifndef __MINGW32__
1081     if( rentry->secret ) {
1082         if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
1083             log_error("%s: chmod failed: %s\n",
1084                                     tmpfname, strerror(errno) );
1085             rc = G10ERR_WRITE_FILE;
1086             goto leave;
1087         }
1088     }
1089   #endif
1090
1091     /* rename and make backup file */
1092     if( !rentry->secret ) {  /* but not for secret keyrings */
1093       #ifdef __MINGW32__
1094         remove( bakfname );
1095       #endif
1096         if( rename( rentry->fname, bakfname ) ) {
1097             log_error("%s: rename to %s failed: %s\n",
1098                                     rentry->fname, bakfname, strerror(errno) );
1099             rc = G10ERR_RENAME_FILE;
1100             goto leave;
1101         }
1102     }
1103   #ifdef __MINGW32__
1104     remove( rentry->fname );
1105   #endif
1106     if( rename( tmpfname, rentry->fname ) ) {
1107         log_error("%s: rename to %s failed: %s\n",
1108                             tmpfname, rentry->fname,strerror(errno) );
1109         rc = G10ERR_RENAME_FILE;
1110         if( rentry->secret ) {
1111             log_info(_(
1112                 "Warning: 2 files with confidential information exists.\n"));
1113             log_info(_("%s is the unchanged one\n"), rentry->fname );
1114             log_info(_("%s is the new one\n"), tmpfname );
1115             log_info(_("Please fix this possible security flaw\n"));
1116         }
1117         goto leave;
1118     }
1119
1120   leave:
1121     m_free(bakfname);
1122     m_free(tmpfname);
1123     return rc;
1124 }
1125
1126 \f
1127 #ifdef HAVE_LIBGDBM
1128 /****************************************************************
1129  ********** Functions which operates on GDM files ***************
1130  ****************************************************************/
1131
1132 /****************
1133  * search one keybox, return 0 if found, -1 if not found or an errorcode.
1134  */
1135 static int
1136 do_gdbm_search( PACKET *req, KBPOS *kbpos, GDBM_FILE dbf, const char *fname )
1137 {
1138     int rc;
1139     PACKET pkt;
1140     int save_mode;
1141     ulong offset;
1142     int pkttype = req->pkttype;
1143     PKT_public_key *req_pk = req->pkt.public_key;
1144     PKT_secret_key *req_sk = req->pkt.secret_key;
1145
1146     init_packet(&pkt);
1147     save_mode = set_packet_list_mode(0);
1148
1149
1150     while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
1151         if( pkt.pkttype == PKT_SECRET_KEY ) {
1152             PKT_secret_key *sk = pkt.pkt.secret_key;
1153
1154             if(   req_sk->timestamp == sk->timestamp
1155                && req_sk->pubkey_algo == sk->pubkey_algo
1156                && !cmp_seckey( req_sk, sk) )
1157                 break; /* found */
1158         }
1159         else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
1160             PKT_public_key *pk = pkt.pkt.public_key;
1161
1162             if(   req_pk->timestamp == pk->timestamp
1163                && req_pk->pubkey_algo == pk->pubkey_algo
1164                && !cmp_pubkey( req_pk, pk ) )
1165                 break; /* found */
1166         }
1167         else
1168             BUG();
1169         free_packet(&pkt);
1170     }
1171     if( !rc )
1172         kbpos->offset = offset;
1173
1174   leave:
1175     free_packet(&pkt);
1176     set_packet_list_mode(save_mode);
1177   #if __MINGW32__
1178     iobuf_close(iobuf);
1179   #endif
1180     return rc;
1181 }
1182
1183
1184 static int
1185 do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
1186 {
1187     PACKET *pkt;
1188     int rc;
1189     RESTBL *rentry;
1190     KBNODE root = NULL;
1191     IOBUF a;
1192     int in_cert = 0;
1193
1194     if( !(rentry=check_pos(kbpos)) )
1195         return G10ERR_GENERAL;
1196
1197     a = iobuf_fopen( rentry->fname, "rb" );
1198     if( !a ) {
1199         log_error("can't open '%s'\n", rentry->fname );
1200         return G10ERR_OPEN_FILE;
1201     }
1202
1203     if( iobuf_seek( a, kbpos->offset ) ) {
1204         log_error("can't seek to %lu\n", kbpos->offset);
1205         iobuf_close(a);
1206         return G10ERR_KEYRING_OPEN;
1207     }
1208
1209     pkt = m_alloc( sizeof *pkt );
1210     init_packet(pkt);
1211     kbpos->count=0;
1212     while( (rc=parse_packet(a, pkt)) != -1 ) {
1213         if( rc ) {  /* ignore errors */
1214             if( rc != G10ERR_UNKNOWN_PACKET ) {
1215                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
1216                 rc = G10ERR_INV_KEYRING;
1217                 goto ready;
1218             }
1219             kbpos->count++;
1220             free_packet( pkt );
1221             init_packet( pkt );
1222             continue;
1223         }
1224         /* make a linked list of all packets */
1225         switch( pkt->pkttype ) {
1226           case PKT_PUBLIC_KEY:
1227           case PKT_SECRET_KEY:
1228             if( in_cert )
1229                 goto ready;
1230             in_cert = 1;
1231           default:
1232             kbpos->count++;
1233             if( !root )
1234                 root = new_kbnode( pkt );
1235             else
1236                 add_kbnode( root, new_kbnode( pkt ) );
1237             pkt = m_alloc( sizeof *pkt );
1238             init_packet(pkt);
1239             break;
1240         }
1241     }
1242   ready:
1243     if( rc == -1 && root )
1244         rc = 0;
1245
1246     if( rc )
1247         release_kbnode( root );
1248     else
1249         *ret_root = root;
1250     free_packet( pkt );
1251     m_free( pkt );
1252     iobuf_close(a);
1253     return rc;
1254 }
1255
1256
1257 static int
1258 do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
1259 {
1260     PACKET *pkt;
1261     int rc;
1262     RESTBL *rentry;
1263     KBNODE root = NULL;
1264
1265     if( !(rentry=check_pos(kbpos)) )
1266         return G10ERR_GENERAL;
1267
1268     if( kbpos->pkt ) {
1269         root = new_kbnode( kbpos->pkt );
1270         kbpos->pkt = NULL;
1271     }
1272
1273     pkt = m_alloc( sizeof *pkt );
1274     init_packet(pkt);
1275     while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
1276         if( rc ) {  /* ignore errors */
1277             if( rc != G10ERR_UNKNOWN_PACKET ) {
1278                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
1279                 rc = G10ERR_INV_KEYRING;
1280                 goto ready;
1281             }
1282             free_packet( pkt );
1283             init_packet( pkt );
1284             continue;
1285         }
1286         /* make a linked list of all packets */
1287         switch( pkt->pkttype ) {
1288           case PKT_PUBLIC_KEY:
1289           case PKT_SECRET_KEY:
1290             if( root ) { /* store this packet */
1291                 kbpos->pkt = pkt;
1292                 pkt = NULL;
1293                 goto ready;
1294             }
1295             root = new_kbnode( pkt );
1296             pkt = m_alloc( sizeof *pkt );
1297             init_packet(pkt);
1298             break;
1299
1300           default:
1301             /* skip pakets at the beginning of a keyring, until we find
1302              * a start packet; issue a warning if it is not a comment */
1303             if( !root && pkt->pkttype != PKT_COMMENT
1304                       && pkt->pkttype != PKT_OLD_COMMENT ) {
1305                 log_info("keyring_enum: skipped packet of type %d\n",
1306                             pkt->pkttype );
1307                 break;
1308             }
1309             if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
1310                                       ||pkt->pkttype == PKT_COMMENT
1311                                       ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
1312                 init_packet(pkt);
1313                 break;
1314             }
1315             add_kbnode( root, new_kbnode( pkt ) );
1316             pkt = m_alloc( sizeof *pkt );
1317             init_packet(pkt);
1318             break;
1319         }
1320     }
1321   ready:
1322     if( rc == -1 && root )
1323         rc = 0;
1324
1325     if( rc )
1326         release_kbnode( root );
1327     else
1328         *ret_root = root;
1329     free_packet( pkt );
1330     m_free( pkt );
1331
1332     return rc;
1333 }
1334
1335 #endif /*HAVE_LIBGDBM*/
1336
1337