Bug in blowfish behoben
[gnupg.git] / g10 / ringedit.c
1 /* ringedit.c -  Function for key ring editing
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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:  Add backup stuff
39  * FIXME:  Keep track of all nodes, so that a change is propagated
40  *         to all nodes. (or use shallow copies and ref-counting?)
41  */
42
43
44
45 #include <config.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <assert.h>
50 #include "util.h"
51 #include "packet.h"
52 #include "memory.h"
53 #include "mpi.h"
54 #include "iobuf.h"
55 #include "keydb.h"
56 #include <unistd.h> /* for truncate */
57
58
59 struct resource_table_struct {
60     int used;
61     int secret; /* this is a secret keyring */
62     char *fname;
63     IOBUF iobuf;
64 };
65 typedef struct resource_table_struct RESTBL;
66
67 #define MAX_RESOURCES 10
68 static RESTBL resource_table[MAX_RESOURCES];
69
70
71 static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf );
72 static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
73 static int keyring_insert( KBPOS *kbpos, KBNODE root );
74 static int keyring_delete( KBPOS *kbpos );
75
76
77
78 static RESTBL *
79 check_pos( KBPOS *kbpos )
80 {
81     if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
82         return NULL;
83     if( !resource_table[kbpos->resno].used )
84         return NULL;
85     return resource_table + kbpos->resno;
86 }
87
88
89
90 /****************************************************************
91  ****************** public functions ****************************
92  ****************************************************************/
93
94 /****************
95  * Register a resource (which currently may ionly be a keyring file).
96  */
97 int
98 add_keyblock_resource( const char *filename, int force, int secret )
99 {
100     IOBUF iobuf;
101     int i;
102
103     for(i=0; i < MAX_RESOURCES; i++ )
104         if( !resource_table[i].used )
105             break;
106     if( i == MAX_RESOURCES )
107         return G10ERR_RESOURCE_LIMIT;
108
109     iobuf = iobuf_open( filename );
110     if( !iobuf && !force )
111         return G10ERR_OPEN_FILE;
112     resource_table[i].used = 1;
113     resource_table[i].secret = !!secret;
114     resource_table[i].fname = m_strdup(filename);
115     resource_table[i].iobuf = iobuf;
116     return 0;
117 }
118
119
120 /****************
121  * Get a keyblock handle KBPOS from a filename. This can be used
122  * to get a handle for insert_keyblock for a new keyblock.
123  */
124 int
125 get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
126 {
127     int i;
128
129     for(i=0; i < MAX_RESOURCES; i++ )
130         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
131             /* fixme: dos needs case insensitive file compare */
132             if( !strcmp( resource_table[i].fname, filename ) ) {
133                 memset( kbpos, 0, sizeof *kbpos );
134                 kbpos->resno = i;
135                 return 0;
136             }
137         }
138     return -1; /* not found */
139 }
140
141 /****************
142  * Search a keyblock which starts with the given packet and put all
143  * informations into KBPOS, which can be used later to access this key block.
144  * This function looks into all registered keyblock sources.
145  * PACKET must be a packet with either a secret_cert or a public_cert
146  *
147  * This function is intended to check wether a given certificate
148  * is already in a keyring or to prepare it for editing.
149  *
150  * Returns: 0 if found, -1 if not found or an errorcode.
151  */
152 int
153 search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret )
154 {
155     int i, rc, last_rc=-1;
156
157     for(i=0; i < MAX_RESOURCES; i++ ) {
158         if( resource_table[i].used && !resource_table[i].secret == !secret ) {
159             /* note: here we have to add different search functions,
160              * depending on the type of the resource */
161             rc = keyring_search( pkt, kbpos, resource_table[i].iobuf );
162             if( !rc ) {
163                 kbpos->resno = i;
164                 return 0;
165             }
166             if( rc != -1 ) {
167                 log_error("error searching resource %d: %s\n",
168                                                   i, g10_errstr(rc));
169                 last_rc = rc;
170             }
171         }
172     }
173     return last_rc;
174 }
175
176
177 /****************
178  * Combined function to search for a username and get the position
179  * of the keyblock.
180  */
181 int
182 search_keyblock_byname( KBPOS *kbpos, const char *username )
183 {
184     PACKET pkt;
185     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
186     int rc;
187
188     rc = get_pubkey_byname( pkc, username );
189     if( rc ) {
190         free_public_cert(pkc);
191         return rc;
192     }
193
194     init_packet( &pkt );
195     pkt.pkttype = PKT_PUBLIC_CERT;
196     pkt.pkt.public_cert = pkc;
197     rc = search_keyblock( &pkt, kbpos, 0 );
198     free_public_cert(pkc);
199     return rc;
200 }
201
202 /****************
203  * Combined function to search for a username and get the position
204  * of the keyblock. This function does not unprotect the secret key.
205  */
206 int
207 search_secret_keyblock_byname( KBPOS *kbpos, const char *username )
208 {
209     PACKET pkt;
210     PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
211     int rc;
212
213     rc = get_seckey_byname( skc, username, 0 );
214     if( rc ) {
215         free_secret_cert(skc);
216         return rc;
217     }
218
219     init_packet( &pkt );
220     pkt.pkttype = PKT_SECRET_CERT;
221     pkt.pkt.secret_cert = skc;
222     rc = search_keyblock( &pkt, kbpos, 1 );
223     free_secret_cert(skc);
224     return rc;
225 }
226
227
228 /****************
229  * Lock the keyblock; wait until it's available
230  * This function may change the internal data in kbpos, in cases
231  * when the to be locked keyblock has been modified.
232  * fixme: remove this function and add an option to search_keyblock()?
233  */
234 int
235 lock_keyblock( KBPOS *kbpos )
236 {
237     int rc;
238
239     if( !check_pos(kbpos) )
240         return G10ERR_GENERAL;
241     return 0;
242 }
243
244 /****************
245  * Release a lock on a keyblock
246  */
247 void
248 unlock_keyblock( KBPOS *kbpos )
249 {
250     if( !check_pos(kbpos) )
251         log_bug(NULL);
252 }
253
254 /****************
255  * Read a complete keyblock and return the root in ret_root.
256  */
257 int
258 read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
259 {
260     if( !check_pos(kbpos) )
261         return G10ERR_GENERAL;
262     return keyring_read( kbpos, ret_root );
263 }
264
265 /****************
266  * Insert the keyblock described by ROOT into the keyring described
267  * by KBPOS.  This actually appends the data to the keyfile.
268  */
269 int
270 insert_keyblock( KBPOS *kbpos, KBNODE root )
271 {
272     int rc;
273
274     if( !check_pos(kbpos) )
275         return G10ERR_GENERAL;
276
277     rc = keyring_insert( kbpos, root );
278
279     return rc;
280 }
281
282 /****************
283  * Delete the keyblock described by KBPOS.
284  * The current code simply changes the keyblock in the keyring
285  * to packet of type 0 with the correct length.  To help detecting errors,
286  * zero bytes are written.
287  */
288 int
289 delete_keyblock( KBPOS *kbpos )
290 {
291     int rc;
292
293     if( !check_pos(kbpos) )
294         return G10ERR_GENERAL;
295
296     rc = keyring_delete( kbpos );
297
298     return rc;
299 }
300
301
302 /****************
303  * Update the keyblock at KBPOS with the one in ROOT.
304  */
305 int
306 update_keyblock( KBPOS *kbpos, KBNODE root )
307 {
308     int rc;
309     KBPOS kbpos2;
310
311     /* we do it the simple way: */
312     memset( &kbpos2, 0, sizeof kbpos2 );
313     kbpos2.resno = kbpos->resno;
314     rc = insert_keyblock( &kbpos2, root );
315     if( !rc )
316         rc = delete_keyblock( kbpos );
317
318     return rc;
319 }
320
321
322 /****************************************************************
323  ********** Functions which operates on regular keyrings ********
324  ****************************************************************/
325
326
327 /****************
328  * search one keyring, return 0 if found, -1 if not found or an errorcode.
329  */
330 static int
331 keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf )
332 {
333     int rc;
334     PACKET pkt;
335     int save_mode;
336     ulong offset;
337     int pkttype = req->pkttype;
338     PKT_public_cert *req_pkc = req->pkt.public_cert;
339     PKT_secret_cert *req_skc = req->pkt.secret_cert;
340
341     init_packet(&pkt);
342     save_mode = set_packet_list_mode(0);
343
344     if( iobuf_seek( iobuf, 0 ) ) {
345         log_error("can't rewind keyring file: %s\n", g10_errstr(rc));
346         rc = G10ERR_KEYRING_OPEN;
347         goto leave;
348     }
349
350     while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
351         if( pkt.pkttype == PKT_SECRET_CERT ) {
352             PKT_secret_cert *skc = pkt.pkt.secret_cert;
353
354             if(   req_skc->timestamp == skc->timestamp
355                && req_skc->valid_days == skc->valid_days
356                && req_skc->pubkey_algo == skc->pubkey_algo
357                && (   ( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
358                         && !mpi_cmp( req_skc->d.elg.p, skc->d.elg.p )
359                         && !mpi_cmp( req_skc->d.elg.g, skc->d.elg.g )
360                         && !mpi_cmp( req_skc->d.elg.y, skc->d.elg.y )
361                         && !mpi_cmp( req_skc->d.elg.x, skc->d.elg.x )
362                       )
363                    || ( skc->pubkey_algo == PUBKEY_ALGO_RSA
364                         && !mpi_cmp( req_skc->d.rsa.rsa_n, skc->d.rsa.rsa_n )
365                         && !mpi_cmp( req_skc->d.rsa.rsa_e, skc->d.rsa.rsa_e )
366                         && !mpi_cmp( req_skc->d.rsa.rsa_d, skc->d.rsa.rsa_d )
367                       )
368                   )
369               )
370                 break; /* found */
371         }
372         else if( pkt.pkttype == PKT_PUBLIC_CERT ) {
373             PKT_public_cert *pkc = pkt.pkt.public_cert;
374
375             if(   req_pkc->timestamp == pkc->timestamp
376                && req_pkc->valid_days == pkc->valid_days
377                && req_pkc->pubkey_algo == pkc->pubkey_algo
378                && (   ( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
379                         && !mpi_cmp( req_pkc->d.elg.p, pkc->d.elg.p )
380                         && !mpi_cmp( req_pkc->d.elg.g, pkc->d.elg.g )
381                         && !mpi_cmp( req_pkc->d.elg.y, pkc->d.elg.y )
382                       )
383                    || ( pkc->pubkey_algo == PUBKEY_ALGO_RSA
384                         && !mpi_cmp( req_pkc->d.rsa.rsa_n, pkc->d.rsa.rsa_n )
385                         && !mpi_cmp( req_pkc->d.rsa.rsa_e, pkc->d.rsa.rsa_e )
386                       )
387                   )
388               )
389                 break; /* found */
390         }
391         else
392             log_bug(NULL);
393         free_packet(&pkt);
394     }
395     if( !rc )
396         kbpos->offset = offset;
397
398   leave:
399     free_packet(&pkt);
400     set_packet_list_mode(save_mode);
401     return rc;
402 }
403
404
405 static int
406 keyring_read( KBPOS *kbpos, KBNODE *ret_root )
407 {
408     PACKET *pkt;
409     int rc;
410     RESTBL *rentry;
411     KBNODE root = NULL;
412     KBNODE node, n1, n2;
413     IOBUF a;
414     u32 offset, last_offset;
415
416     if( !(rentry=check_pos(kbpos)) )
417         return G10ERR_GENERAL;
418
419     a = iobuf_open( rentry->fname );
420     if( !a ) {
421         log_error("can't open '%s'\n", rentry->fname );
422         return G10ERR_OPEN_FILE;
423     }
424
425     if( iobuf_seek( a, kbpos->offset ) ) {
426         log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc));
427         iobuf_close(a);
428         return G10ERR_KEYRING_OPEN;
429     }
430
431     pkt = m_alloc( sizeof *pkt );
432     init_packet(pkt);
433     while( (rc=parse_packet(a, pkt)) != -1 ) {
434         if( rc ) {  /* ignore errors */
435             free_packet( pkt );
436             continue;
437         }
438         if( root && ( pkt->pkttype == PKT_PUBLIC_CERT
439                       || pkt->pkttype == PKT_SECRET_CERT ) )
440             goto ready;
441         offset = iobuf_tell(a);
442         switch( pkt->pkttype ) {
443           case PKT_PUBLIC_CERT:
444           case PKT_SECRET_CERT:
445             root = new_kbnode( pkt );
446             pkt = m_alloc( sizeof *pkt );
447             init_packet(pkt);
448             break;
449
450           case PKT_USER_ID:
451             if( !root ) {
452                 log_error("read_keyblock: orphaned user id\n" );
453                 rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
454                 goto ready;
455             }
456             offset = last_offset;
457             /* append the user id */
458             node = new_kbnode( pkt );
459             if( !(n1=root->child) )
460                 root->child = node;
461             else {
462                 for( ; n1->next; n1 = n1->next)
463                     ;
464                 n1->next = node;
465             }
466             pkt = m_alloc( sizeof *pkt );
467             init_packet(pkt);
468             break;
469
470           case PKT_SIGNATURE:
471             if( !root ) {
472                 log_error("read_keyblock: no root for signature\n" );
473                 rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
474                 break;
475             }
476             if( !root->child ) {
477                 log_error("read_keyblock: no userid for signature\n" );
478                 rc = G10ERR_INV_KEYRING;
479                 break;
480             }
481             /* goto the last user id */
482             for(n1=root->child; n1->next; n1 = n1->next )
483                 ;
484             /* append the signature node */
485             node = new_kbnode( pkt );
486             if( !(n2=n1->child) )
487                 n1->child = node;
488             else {
489                 for( ; n2->next; n2 = n2->next)
490                     ;
491                 n2->next = node;
492             }
493             pkt = m_alloc( sizeof *pkt );
494             init_packet(pkt);
495             break;
496
497           default: /* ignore all other packets. FIXME: we should not do this */
498             free_packet( pkt );
499             break;
500         }
501     }
502   ready:
503     kbpos->last_block = rc == -1; /* flag, that this is the last block */
504     if( rc == -1 && root )
505         rc = 0;
506
507     if( rc )
508         release_kbnode( root );
509     else {
510         *ret_root = root;
511         kbpos->length = offset - kbpos->offset;
512     }
513     free_packet( pkt );
514     m_free( pkt );
515     iobuf_close(a);
516     return rc;
517 }
518
519
520 /****************
521  * Insert the keyblock described by ROOT into the keyring described
522  * by KBPOS.  This actually appends the data to the keyfile.
523  */
524 static int
525 keyring_insert( KBPOS *kbpos, KBNODE root )
526 {
527     RESTBL *rentry;
528     IOBUF fp;
529     KBNODE kbctx, node;
530     int rc;
531
532     if( !(rentry = check_pos( kbpos )) )
533         return G10ERR_GENERAL;
534
535     /* FIXME: we must close the file if it's already open, due to
536      *        2 reasons:
537      *         - cannot open the same file twice on DOSish OSes
538      *         - must sync with iobufs somehow
539      */
540     /* open the file for append */
541     fp = iobuf_append( rentry->fname );
542     if( !fp ) {
543         log_error("can't append to '%s'\n", rentry->fname );
544         return G10ERR_OPEN_FILE;
545     }
546
547     kbctx=NULL;
548     while( (node = walk_kbtree( root, &kbctx )) ) {
549         if( (rc = build_packet( fp, node->pkt )) ) {
550             log_error("build_packet(%d) failed: %s\n",
551                         node->pkt->pkttype, g10_errstr(rc) );
552             return G10ERR_WRITE_FILE;
553         }
554     }
555     iobuf_close(fp);
556
557     return 0;
558 }
559
560 static int
561 keyring_delete( KBPOS *kbpos )
562 {
563     RESTBL *rentry;
564     IOBUF fp;
565     KBNODE kbctx, node;
566     int rc;
567     u32 len;
568     int ctb;
569
570     if( !(rentry = check_pos( kbpos )) )
571         return G10ERR_GENERAL;
572
573
574     /* open the file for read/write */
575     fp = iobuf_openrw( rentry->fname );
576     if( !fp ) {
577         log_error("can't open '%s' for writing\n", rentry->fname );
578         return G10ERR_OPEN_FILE;
579     }
580
581     if( iobuf_seek( fp, kbpos->offset ) ) {
582         log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc));
583         iobuf_close(fp);
584         return G10ERR_WRITE_FILE;
585     }
586
587     len = kbpos->length;
588     /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/
589
590     if( len < 2 )
591         log_bug(NULL);
592
593     if( len < 256 ) {
594         ctb = 0x80;
595         len -= 2;
596     }
597     else if( len < 65536 ) {
598         ctb = 0x81;
599         len -= 3;
600     }
601     else {
602         ctb = 0x82;
603         len -= 5;
604     }
605     iobuf_put(fp, ctb );
606     if( ctb & 2 ) {
607         iobuf_put(fp, len >> 24 );
608         iobuf_put(fp, len >> 16 );
609     }
610     if( ctb & 3 )
611         iobuf_put(fp, len >> 8 );
612     if( iobuf_put(fp, len ) ) {
613         iobuf_close(fp);
614         return G10ERR_WRITE_FILE;
615     }
616     for( ; len; len-- )
617         if( iobuf_put(fp, 0xff ) ) {
618             iobuf_close(fp);
619             return G10ERR_WRITE_FILE;
620         }
621
622     iobuf_close(fp);
623
624     return 0;
625 }
626
627
628 /****************************************************************
629  ********** Functions which operates on databases ***************
630  ****************************************************************/
631