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