1f382f7166a60bf0c7748eab0a0de45b892d9b7f
[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 #include "util.h"
54 #include "packet.h"
55 #include "memory.h"
56 #include "mpi.h"
57 #include "iobuf.h"
58 #include "keydb.h"
59 #include "options.h"
60 #include "i18n.h"
61
62
63 struct resource_table_struct {
64     int used;
65     int secret; /* this is a secret keyring */
66     char *fname;
67     IOBUF iobuf;
68 };
69 typedef struct resource_table_struct RESTBL;
70
71 #define MAX_RESOURCES 10
72 static RESTBL resource_table[MAX_RESOURCES];
73
74 static int search( PACKET *pkt, KBPOS *kbpos, int secret );
75
76
77 static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
78                                                 const char *fname );
79 static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
80 static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
81 static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
82
83
84
85 static RESTBL *
86 check_pos( KBPOS *kbpos )
87 {
88     if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
89         return NULL;
90     if( !resource_table[kbpos->resno].used )
91         return NULL;
92     return resource_table + kbpos->resno;
93 }
94
95
96 /****************************************************************
97  ****************** public functions ****************************
98  ****************************************************************/
99
100 /****************
101  * Get the name of the keyrings, start with a sequence number pointing to a 0.
102  */
103 const char *
104 enum_keyblock_resources( int *sequence, int secret )
105 {
106     int i = *sequence;
107     const char *name = NULL;
108
109     for(; i < MAX_RESOURCES; i++ )
110         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
111             if( resource_table[i].fname ) {
112                 name = resource_table[i].fname;
113                 break;
114             }
115         }
116     *sequence = ++i;
117     return NULL; /* not found */
118 }
119
120
121
122 /****************
123  * Register a resource (which currently may only be a keyring file).
124  * The first keyring which is added by this function is
125  * created if it does not exist.
126  * Note: this function may be called before secure memory is
127  * available.
128  */
129 int
130 add_keyblock_resource( const char *resname, int force, int secret )
131 {
132     static int any_secret, any_public;
133     IOBUF iobuf;
134     int i, force;
135     char *filename;
136     int rc = 0;
137
138     if( *resname != '/' ) { /* do tilde expansion etc */
139         if( strchr(resname, '/') )
140             filename = make_filename(resname, NULL);
141         else
142             filename = make_filename(opt.homedir, resname, NULL);
143     }
144     else
145         filename = m_strdup( resname );
146
147     if( !force )
148         force = secret? !any_secret : !any_public;
149
150     for(i=0; i < MAX_RESOURCES; i++ )
151         if( !resource_table[i].used )
152             break;
153     if( i == MAX_RESOURCES ) {
154         rc = G10ERR_RESOURCE_LIMIT;
155         goto leave;
156     }
157
158     iobuf = iobuf_fopen( filename, "rb" );
159     if( !iobuf && !force ) {
160         rc = G10ERR_OPEN_FILE;
161         goto leave;
162     }
163
164     if( !iobuf ) {
165         iobuf = iobuf_create( filename );
166         if( !iobuf ) {
167             log_error("%s: can't create: %s\n", filename, strerror(errno));
168             rc = G10ERR_OPEN_FILE;
169             goto leave;
170         }
171         else
172             log_info("%s: keyring created\n", filename );
173     }
174
175   #ifdef __MINGW32__
176     /* must close it again */
177     iobuf_close( iobuf );
178     iobuf = NULL;
179   #endif
180
181     resource_table[i].used = 1;
182     resource_table[i].secret = !!secret;
183     resource_table[i].fname = m_strdup(filename);
184     resource_table[i].iobuf = iobuf;
185   leave:
186     if( rc )
187         log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) );
188     else if( secret )
189         any_secret = 1;
190     else
191         any_public = 1;
192     m_free( filename );
193     return rc;
194 }
195
196 /****************
197  * Return the resource name of the keyblock associated with KBPOS.
198  */
199 const char *
200 keyblock_resource_name( KBPOS *kbpos )
201 {
202     RESTBL *rentry;
203
204     if( !(rentry = check_pos( kbpos )) || !rentry->fname )
205         log_bug("no name for keyblock resource %d\n", kbpos->resno );
206     return rentry->fname;
207 }
208
209
210 /****************
211  * Get a keyblock handle KBPOS from a filename. This can be used
212  * to get a handle for insert_keyblock for a new keyblock.
213  * Using a filename of NULL returns the default resource
214  */
215 int
216 get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
217 {
218     int i;
219
220     for(i=0; i < MAX_RESOURCES; i++ )
221         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
222             /* fixme: dos needs case insensitive file compare */
223             if( !filename || !strcmp( resource_table[i].fname, filename ) ) {
224                 memset( kbpos, 0, sizeof *kbpos );
225                 kbpos->resno = i;
226                 return 0;
227             }
228         }
229     return -1; /* not found */
230 }
231
232
233
234 /****************
235  * Search a keyblock which starts with the given packet and puts all
236  * information into KBPOS, which can be used later to access this key block.
237  * This function looks into all registered keyblock sources.
238  * PACKET must be a packet with either a secret_key or a public_key
239  *
240  * This function is intended to check whether a given certificate
241  * is already in a keyring or to prepare it for editing.
242  *
243  * Returns: 0 if found, -1 if not found or an errorcode.
244  */
245 static int
246 search( PACKET *pkt, KBPOS *kbpos, int secret )
247 {
248     int i, rc, last_rc=-1;
249
250     for(i=0; i < MAX_RESOURCES; i++ ) {
251         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
252             /* note: here we have to add different search functions,
253              * depending on the type of the resource */
254             rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
255                                              resource_table[i].fname );
256             if( !rc ) {
257                 kbpos->resno = i;
258                 kbpos->fp = NULL;
259                 return 0;
260             }
261             if( rc != -1 ) {
262                 log_error("error searching resource %d: %s\n",
263                                                   i, g10_errstr(rc));
264                 last_rc = rc;
265             }
266         }
267     }
268     return last_rc;
269 }
270
271
272 /****************
273  * Combined function to search for a username and get the position
274  * of the keyblock.
275  */
276 int
277 find_keyblock_byname( KBPOS *kbpos, const char *username )
278 {
279     PACKET pkt;
280     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
281     int rc;
282
283     rc = get_pubkey_byname( pk, username );
284     if( rc ) {
285         free_public_key(pk);
286         return rc;
287     }
288
289     init_packet( &pkt );
290     pkt.pkttype = PKT_PUBLIC_KEY;
291     pkt.pkt.public_key = pk;
292     rc = search( &pkt, kbpos, 0 );
293     free_public_key(pk);
294     return rc;
295 }
296
297
298 /****************
299  * Combined function to search for a key and get the position
300  * of the keyblock.
301  */
302 int
303 find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
304 {
305     PACKET pkt;
306     int rc;
307
308     init_packet( &pkt );
309     pkt.pkttype = PKT_PUBLIC_KEY;
310     pkt.pkt.public_key = pk;
311     rc = search( &pkt, kbpos, 0 );
312     return rc;
313 }
314
315
316 /****************
317  * Combined function to search for a username and get the position
318  * of the keyblock. This function does not unprotect the secret key.
319  */
320 int
321 find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
322 {
323     PACKET pkt;
324     PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
325     int rc;
326
327     rc = get_seckey_byname( sk, username, 0 );
328     if( rc ) {
329         free_secret_key(sk);
330         return rc;
331     }
332
333     init_packet( &pkt );
334     pkt.pkttype = PKT_SECRET_KEY;
335     pkt.pkt.secret_key = sk;
336     rc = search( &pkt, kbpos, 1 );
337     free_secret_key(sk);
338     return rc;
339 }
340
341
342
343 /****************
344  * Lock the keyblock; wait until it's available
345  * This function may change the internal data in kbpos, in cases
346  * when the keyblock to be locked has been modified.
347  * fixme: remove this function and add an option to search()?
348  */
349 int
350 lock_keyblock( KBPOS *kbpos )
351 {
352     if( !check_pos(kbpos) )
353         return G10ERR_GENERAL;
354     return 0;
355 }
356
357 /****************
358  * Release a lock on a keyblock
359  */
360 void
361 unlock_keyblock( KBPOS *kbpos )
362 {
363     if( !check_pos(kbpos) )
364         BUG();
365 }
366
367 /****************
368  * Read a complete keyblock and return the root in ret_root.
369  */
370 int
371 read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
372 {
373     if( !check_pos(kbpos) )
374         return G10ERR_GENERAL;
375     return keyring_read( kbpos, ret_root );
376 }
377
378
379 /****************
380  * This functions can be used to read through a complete keyring.
381  * Mode is: 0 = open
382  *          1 = read
383  *          2 = close
384  *          5 = open secret keyrings
385  *          11 = read but skip signature and comment packets.
386  *          all others are reserved!
387  * Note that you do not need a search prior to this function,
388  * only a handle is needed.
389  * NOTE: It is not allowed to do an insert/update/delete with this
390  *       keyblock, if you want to do this, use search/read!
391  */
392 int
393 enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
394 {
395     int rc = 0;
396     RESTBL *rentry;
397
398     if( !mode || mode == 5 || mode == 100 ) {
399         int i;
400         kbpos->fp = NULL;
401         if( !mode ) {
402             kbpos->secret = 0;
403             i = 0;
404         }
405         else if( mode == 5 ) {
406             kbpos->secret = 1;
407             mode = 0;
408             i = 0;
409         }
410         else
411             i = kbpos->resno+1;
412         for(; i < MAX_RESOURCES; i++ )
413             if( resource_table[i].used
414                 && !resource_table[i].secret == !kbpos->secret )
415                 break;
416         if( i == MAX_RESOURCES )
417             return -1; /* no resources */
418         kbpos->resno = i;
419         rentry = check_pos( kbpos );
420         kbpos->fp = iobuf_fopen( rentry->fname, "rb" );
421         if( !kbpos->fp ) {
422             log_error("can't open '%s'\n", rentry->fname );
423             return G10ERR_OPEN_FILE;
424         }
425         kbpos->pkt = NULL;
426     }
427     else if( mode == 1 || mode == 11 ) {
428         int cont;
429         do {
430             cont = 0;
431             if( !kbpos->fp )
432                 return G10ERR_GENERAL;
433             rc = keyring_enum( kbpos, ret_root, mode == 11 );
434             if( rc == -1 ) {
435                 assert( !kbpos->pkt );
436                 rentry = check_pos( kbpos );
437                 assert(rentry);
438                 /* close */
439                 enum_keyblocks(2, kbpos, ret_root );
440                 /* and open the next one */
441                 rc = enum_keyblocks(100, kbpos, ret_root );
442                 if( !rc )
443                     cont = 1;
444             }
445         } while(cont);
446     }
447     else if( kbpos->fp ) {
448         iobuf_close( kbpos->fp );
449         kbpos->fp = NULL;
450         /* release pending packet */
451         free_packet( kbpos->pkt );
452         m_free( kbpos->pkt );
453     }
454     return rc;
455 }
456
457
458
459
460 /****************
461  * Insert the keyblock described by ROOT into the keyring described
462  * by KBPOS.  This actually appends the data to the keyfile.
463  */
464 int
465 insert_keyblock( KBPOS *kbpos, KBNODE root )
466 {
467     int rc;
468
469     if( !check_pos(kbpos) )
470         return G10ERR_GENERAL;
471
472     rc = keyring_copy( kbpos, 1, root );
473
474     return rc;
475 }
476
477 /****************
478  * Delete the keyblock described by KBPOS.
479  * The current code simply changes the keyblock in the keyring
480  * to packet of type 0 with the correct length.  To help detect errors,
481  * zero bytes are written.
482  */
483 int
484 delete_keyblock( KBPOS *kbpos )
485 {
486     int rc;
487
488     if( !check_pos(kbpos) )
489         return G10ERR_GENERAL;
490
491     rc = keyring_copy( kbpos, 2, NULL );
492
493     return rc;
494 }
495
496
497 /****************
498  * Update the keyblock at KBPOS with the one in ROOT.
499  */
500 int
501 update_keyblock( KBPOS *kbpos, KBNODE root )
502 {
503     int rc;
504
505     if( !check_pos(kbpos) )
506         return G10ERR_GENERAL;
507
508     rc = keyring_copy( kbpos, 3, root );
509
510     return rc;
511 }
512
513
514 /****************************************************************
515  ********** Functions which operates on regular keyrings ********
516  ****************************************************************/
517
518 static int
519 cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
520 {
521     int n,i;
522
523     assert( req_sk->pubkey_algo == sk->pubkey_algo );
524
525     n = pubkey_get_nskey( req_sk->pubkey_algo );
526     for(i=0; i < n; i++ ) {
527         if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
528             return -1;
529     }
530     return 0;
531 }
532
533 static int
534 cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
535 {
536     int n, i;
537
538     assert( req_pk->pubkey_algo == pk->pubkey_algo );
539
540     n = pubkey_get_npkey( req_pk->pubkey_algo );
541     for(i=0; i < n; i++ ) {
542         if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] )  )
543             return -1;
544     }
545     return 0;
546 }
547
548 /****************
549  * search one keyring, return 0 if found, -1 if not found or an errorcode.
550  */
551 static int
552 keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
553 {
554     int rc;
555     PACKET pkt;
556     int save_mode;
557     ulong offset;
558     int pkttype = req->pkttype;
559     PKT_public_key *req_pk = req->pkt.public_key;
560     PKT_secret_key *req_sk = req->pkt.secret_key;
561
562     init_packet(&pkt);
563     save_mode = set_packet_list_mode(0);
564
565   #if __MINGW32__
566     assert(!iobuf);
567     iobuf = iobuf_open( fname );
568     if( !iobuf ) {
569         log_error("%s: can't open keyring file\n", fname);
570         rc = G10ERR_KEYRING_OPEN;
571         goto leave;
572     }
573   #else
574     if( iobuf_seek( iobuf, 0 ) ) {
575         log_error("can't rewind keyring file\n");
576         rc = G10ERR_KEYRING_OPEN;
577         goto leave;
578     }
579   #endif
580
581     while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
582         if( pkt.pkttype == PKT_SECRET_KEY ) {
583             PKT_secret_key *sk = pkt.pkt.secret_key;
584
585             if(   req_sk->timestamp == sk->timestamp
586                && req_sk->pubkey_algo == sk->pubkey_algo
587                && !cmp_seckey( req_sk, sk) )
588                 break; /* found */
589         }
590         else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
591             PKT_public_key *pk = pkt.pkt.public_key;
592
593             if(   req_pk->timestamp == pk->timestamp
594                && req_pk->pubkey_algo == pk->pubkey_algo
595                && !cmp_pubkey( req_pk, pk ) )
596                 break; /* found */
597         }
598         else
599             BUG();
600         free_packet(&pkt);
601     }
602     if( !rc )
603         kbpos->offset = offset;
604
605   leave:
606     free_packet(&pkt);
607     set_packet_list_mode(save_mode);
608   #if __MINGW32__
609     iobuf_close(iobuf);
610   #endif
611     return rc;
612 }
613
614
615 static int
616 keyring_read( KBPOS *kbpos, KBNODE *ret_root )
617 {
618     PACKET *pkt;
619     int rc;
620     RESTBL *rentry;
621     KBNODE root = NULL;
622     IOBUF a;
623     int in_cert = 0;
624
625     if( !(rentry=check_pos(kbpos)) )
626         return G10ERR_GENERAL;
627
628     a = iobuf_fopen( rentry->fname, "rb" );
629     if( !a ) {
630         log_error("can't open '%s'\n", rentry->fname );
631         return G10ERR_OPEN_FILE;
632     }
633
634     if( iobuf_seek( a, kbpos->offset ) ) {
635         log_error("can't seek to %lu\n", kbpos->offset);
636         iobuf_close(a);
637         return G10ERR_KEYRING_OPEN;
638     }
639
640     pkt = m_alloc( sizeof *pkt );
641     init_packet(pkt);
642     kbpos->count=0;
643     while( (rc=parse_packet(a, pkt)) != -1 ) {
644         if( rc ) {  /* ignore errors */
645             if( rc != G10ERR_UNKNOWN_PACKET ) {
646                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
647                 rc = G10ERR_INV_KEYRING;
648                 goto ready;
649             }
650             kbpos->count++;
651             free_packet( pkt );
652             init_packet( pkt );
653             continue;
654         }
655         /* make a linked list of all packets */
656         switch( pkt->pkttype ) {
657           case PKT_PUBLIC_KEY:
658           case PKT_SECRET_KEY:
659             if( in_cert )
660                 goto ready;
661             in_cert = 1;
662           default:
663             kbpos->count++;
664             if( !root )
665                 root = new_kbnode( pkt );
666             else
667                 add_kbnode( root, new_kbnode( pkt ) );
668             pkt = m_alloc( sizeof *pkt );
669             init_packet(pkt);
670             break;
671         }
672     }
673   ready:
674     if( rc == -1 && root )
675         rc = 0;
676
677     if( rc )
678         release_kbnode( root );
679     else
680         *ret_root = root;
681     free_packet( pkt );
682     m_free( pkt );
683     iobuf_close(a);
684     return rc;
685 }
686
687
688 static int
689 keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
690 {
691     PACKET *pkt;
692     int rc;
693     RESTBL *rentry;
694     KBNODE root = NULL;
695
696     if( !(rentry=check_pos(kbpos)) )
697         return G10ERR_GENERAL;
698
699     if( kbpos->pkt ) {
700         root = new_kbnode( kbpos->pkt );
701         kbpos->pkt = NULL;
702     }
703
704     pkt = m_alloc( sizeof *pkt );
705     init_packet(pkt);
706     while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
707         if( rc ) {  /* ignore errors */
708             if( rc != G10ERR_UNKNOWN_PACKET ) {
709                 log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
710                 rc = G10ERR_INV_KEYRING;
711                 goto ready;
712             }
713             free_packet( pkt );
714             init_packet( pkt );
715             continue;
716         }
717         /* make a linked list of all packets */
718         switch( pkt->pkttype ) {
719           case PKT_PUBLIC_KEY:
720           case PKT_SECRET_KEY:
721             if( root ) { /* store this packet */
722                 kbpos->pkt = pkt;
723                 pkt = NULL;
724                 goto ready;
725             }
726             root = new_kbnode( pkt );
727             pkt = m_alloc( sizeof *pkt );
728             init_packet(pkt);
729             break;
730
731           default:
732             /* skip pakets at the beginning of a keyring, until we find
733              * a start packet; issue a warning if it is not a comment */
734             if( !root && pkt->pkttype != PKT_COMMENT
735                       && pkt->pkttype != PKT_OLD_COMMENT ) {
736                 log_info("keyring_enum: skipped packet of type %d\n",
737                             pkt->pkttype );
738                 break;
739             }
740             if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
741                                       ||pkt->pkttype == PKT_COMMENT
742                                       ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
743                 init_packet(pkt);
744                 break;
745             }
746             add_kbnode( root, new_kbnode( pkt ) );
747             pkt = m_alloc( sizeof *pkt );
748             init_packet(pkt);
749             break;
750         }
751     }
752   ready:
753     if( rc == -1 && root )
754         rc = 0;
755
756     if( rc )
757         release_kbnode( root );
758     else
759         *ret_root = root;
760     free_packet( pkt );
761     m_free( pkt );
762
763     return rc;
764 }
765
766
767 /****************
768  * Perform insert/delete/update operation.
769  * mode 1 = insert
770  *      2 = delete
771  *      3 = update
772  */
773 static int
774 keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
775 {
776     RESTBL *rentry;
777     IOBUF fp, newfp;
778     int rc=0;
779     char *bakfname = NULL;
780     char *tmpfname = NULL;
781
782     if( !(rentry = check_pos( kbpos )) )
783         return G10ERR_GENERAL;
784     if( kbpos->fp )
785         BUG(); /* not allowed with such a handle */
786
787     /* open the source file */
788     fp = iobuf_fopen( rentry->fname, "rb" );
789     if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
790         KBNODE kbctx, node;
791
792         /* insert: create a new file */
793         newfp = iobuf_create( rentry->fname );
794         if( !newfp ) {
795             log_error("%s: can't create: %s\n", rentry->fname, strerror(errno));
796             return G10ERR_OPEN_FILE;
797         }
798         else
799             log_info("%s: keyring created\n", rentry->fname );
800
801         kbctx=NULL;
802         while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
803             if( (rc = build_packet( newfp, node->pkt )) ) {
804                 log_error("build_packet(%d) failed: %s\n",
805                             node->pkt->pkttype, g10_errstr(rc) );
806                 iobuf_cancel(newfp);
807                 return G10ERR_WRITE_FILE;
808             }
809         }
810         if( iobuf_close(newfp) ) {
811             log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
812             return G10ERR_CLOSE_FILE;
813         }
814         if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
815             log_error("%s: chmod failed: %s\n",
816                                     rentry->fname, strerror(errno) );
817             return G10ERR_WRITE_FILE;
818         }
819         return 0;
820     }
821     if( !fp ) {
822         log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
823         rc = G10ERR_OPEN_FILE;
824         goto leave;
825     }
826
827     /* create the new file */
828   #ifdef __MINGW32__
829     /* Here is another Windoze bug?:
830      * you cant rename("pubring.gpg.tmp", "pubring.gpg");
831      * but      rename("pubring.gpg.tmp", "pubring.aaa");
832      * works.  So we replace .gpg by .bak or .tmp
833      */
834     if( strlen(rentry->fname) > 4
835         && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) {
836         bakfname = m_alloc( strlen( rentry->fname ) + 1 );
837         strcpy(bakfname,rentry->fname);
838         strcpy(bakfname+strlen(rentry->fname)-4, ".bak");
839         tmpfname = m_alloc( strlen( rentry->fname ) + 1 );
840         strcpy(tmpfname,rentry->fname);
841         strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp");
842     }
843     else { /* file does not end with gpg; hmmm */
844         bakfname = m_alloc( strlen( rentry->fname ) + 5 );
845         strcpy(stpcpy(bakfname,rentry->fname),".bak");
846         tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
847         strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
848     }
849   #else
850     bakfname = m_alloc( strlen( rentry->fname ) + 2 );
851     strcpy(stpcpy(bakfname,rentry->fname),"~");
852     tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
853     strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
854   #endif
855     newfp = iobuf_create( tmpfname );
856     if( !newfp ) {
857         log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
858         iobuf_close(fp);
859         rc = G10ERR_OPEN_FILE;
860         goto leave;
861     }
862
863     if( mode == 1 ) { /* insert */
864         /* copy everything to the new file */
865         rc = copy_all_packets( fp, newfp );
866         if( rc != -1 ) {
867             log_error("%s: copy to %s failed: %s\n",
868                       rentry->fname, tmpfname, g10_errstr(rc) );
869             iobuf_close(fp);
870             iobuf_cancel(newfp);
871             goto leave;
872         }
873         rc = 0;
874     }
875
876     if( mode == 2 || mode == 3 ) { /* delete or update */
877         /* copy first part to the new file */
878         rc = copy_some_packets( fp, newfp, kbpos->offset );
879         if( rc ) { /* should never get EOF here */
880             log_error("%s: copy to %s failed: %s\n",
881                       rentry->fname, tmpfname, g10_errstr(rc) );
882             iobuf_close(fp);
883             iobuf_cancel(newfp);
884             goto leave;
885         }
886         /* skip this keyblock */
887         assert( kbpos->count );
888         rc = skip_some_packets( fp, kbpos->count );
889         if( rc ) {
890             log_error("%s: skipping %u packets failed: %s\n",
891                             rentry->fname, kbpos->count, g10_errstr(rc));
892             iobuf_close(fp);
893             iobuf_cancel(newfp);
894             goto leave;
895         }
896     }
897
898     if( mode == 1 || mode == 3 ) { /* insert or update */
899         KBNODE kbctx, node;
900
901         /* append the new data */
902         kbctx=NULL;
903         while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
904             if( (rc = build_packet( newfp, node->pkt )) ) {
905                 log_error("build_packet(%d) failed: %s\n",
906                             node->pkt->pkttype, g10_errstr(rc) );
907                 iobuf_close(fp);
908                 iobuf_cancel(newfp);
909                 rc = G10ERR_WRITE_FILE;
910                 goto leave;
911             }
912         }
913     }
914
915     if( mode == 2 || mode == 3 ) { /* delete or update */
916         /* copy the rest */
917         rc = copy_all_packets( fp, newfp );
918         if( rc != -1 ) {
919             log_error("%s: copy to %s failed: %s\n",
920                       rentry->fname, tmpfname, g10_errstr(rc) );
921             iobuf_close(fp);
922             iobuf_cancel(newfp);
923             goto leave;
924         }
925         rc = 0;
926     }
927
928     /* close both files */
929     if( iobuf_close(fp) ) {
930         log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) );
931         rc = G10ERR_CLOSE_FILE;
932         goto leave;
933     }
934     if( iobuf_close(newfp) ) {
935         log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
936         rc = G10ERR_CLOSE_FILE;
937         goto leave;
938     }
939     /* if the new file is a secring, restrict the permissions */
940   #ifndef __MINGW32__
941     if( rentry->secret ) {
942         if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
943             log_error("%s: chmod failed: %s\n",
944                                     tmpfname, strerror(errno) );
945             rc = G10ERR_WRITE_FILE;
946             goto leave;
947         }
948     }
949   #endif
950
951     /* rename and make backup file */
952     if( !rentry->secret ) {  /* but not for secret keyrings */
953       #ifdef __MINGW32__
954         remove( bakfname );
955       #endif
956         if( rename( rentry->fname, bakfname ) ) {
957             log_error("%s: rename to %s failed: %s\n",
958                                     rentry->fname, bakfname, strerror(errno) );
959             rc = G10ERR_RENAME_FILE;
960             goto leave;
961         }
962     }
963   #ifdef __MINGW32__
964     remove( rentry->fname );
965   #endif
966     if( rename( tmpfname, rentry->fname ) ) {
967         log_error("%s: rename to %s failed: %s\n",
968                             tmpfname, rentry->fname,strerror(errno) );
969         rc = G10ERR_RENAME_FILE;
970         if( rentry->secret ) {
971             log_info(_(
972                 "Warning: 2 files with confidential information exists.\n"));
973             log_info(_("%s is the unchanged one\n"), rentry->fname );
974             log_info(_("%s is the new one\n"), tmpfname );
975             log_info(_("Please fix this possible security flaw\n"));
976         }
977         goto leave;
978     }
979
980   leave:
981     m_free(bakfname);
982     m_free(tmpfname);
983     return rc;
984 }
985
986
987 /****************************************************************
988  ********** Functions which operates on databases ***************
989  ****************************************************************/
990 /* ... */