efe7bcaf085d8d0f69b46e7a2427ce59fcc7dcf7
[gnupg.git] / g10 / trustdb.c
1 /* trustdb.c
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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include "errors.h"
34 #include "iobuf.h"
35 #include "keydb.h"
36 #include "memory.h"
37 #include "util.h"
38 #include "trustdb.h"
39 #include "options.h"
40 #include "packet.h"
41 #include "main.h"
42 #include "i18n.h"
43 #include "tdbio.h"
44
45
46 #if MAX_FINGERPRINT_LEN > 20
47   #error Must change structure of trustdb
48 #endif
49
50 typedef struct local_id_info *LOCAL_ID_INFO;
51 struct local_id_info {
52     LOCAL_ID_INFO next;
53     ulong lid;
54     unsigned flag;
55 };
56
57
58 typedef struct trust_info TRUST_INFO;
59 struct trust_info {
60     ulong    lid;
61     unsigned trust;
62 };
63
64
65 typedef struct trust_seg_list *TRUST_SEG_LIST;
66 struct trust_seg_list {
67     TRUST_SEG_LIST next;
68     int   nseg;     /* number of segmens */
69     int   dup;
70     TRUST_INFO seg[1];   /* segment list */
71 };
72
73
74 typedef struct {
75     TRUST_SEG_LIST tsl;
76     int index;
77 } ENUM_TRUST_WEB_CONTEXT;
78
79
80 static int walk_sigrecs( SIGREC_CONTEXT *c, int create );
81
82 static LOCAL_ID_INFO *new_lid_table(void);
83 static void release_lid_table( LOCAL_ID_INFO *tbl );
84 static int ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
85 static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag );
86 static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
87
88 static void print_user_id( const char *text, u32 *keyid );
89 static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
90                          LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
91 static int update_sigs_by_lid( ulong lid );
92
93 static int list_sigs( ulong pubkey_id );
94 static int propagate_trust( TRUST_SEG_LIST tslist );
95 static int do_check( TRUSTREC *drec, unsigned *trustlevel );
96
97
98 /* a table used to keep track of ultimately trusted keys
99  * which are the ones from our secrings */
100 static LOCAL_ID_INFO *ultikey_table;
101
102 static ulong last_trust_web_key;
103 static TRUST_SEG_LIST last_trust_web_tslist;
104
105
106 #define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
107                       (a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
108
109 /**********************************************
110  ************* list helpers *******************
111  **********************************************/
112
113 static LOCAL_ID_INFO *
114 new_lid_table(void)
115 {
116     return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO));
117 }
118
119 static void
120 release_lid_table( LOCAL_ID_INFO *tbl )
121 {
122     LOCAL_ID_INFO a, a2;
123     int i;
124
125     for(i=0; i < 16; i++ ) {
126         for(a=tbl[i]; a; a = a2 ) {
127             a2 = a->next;
128             m_free(a);
129         }
130     }
131     m_free(tbl);
132 }
133
134 /****************
135  * Add a new item to the table or return 1 if we already have this item
136  * fixme: maybe it's a good idea to take items from an unused item list.
137  */
138 static int
139 ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
140 {
141     LOCAL_ID_INFO a;
142
143     for( a = tbl[lid & 0x0f]; a; a = a->next )
144         if( a->lid == lid )
145             return 1;
146     a = m_alloc( sizeof *a );
147     a->lid = lid;
148     a->flag = flag;
149     a->next = tbl[lid & 0x0f];
150     tbl[lid & 0x0f] = a;
151     return 0;
152 }
153
154 static int
155 qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag )
156 {
157     LOCAL_ID_INFO a;
158
159     for( a = tbl[lid & 0x0f]; a; a = a->next )
160         if( a->lid == lid ) {
161             if( flag )
162                 *flag = a->flag;
163             return 0;
164         }
165     return -1;
166 }
167
168 static void
169 upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
170 {
171     LOCAL_ID_INFO a;
172
173     for( a = tbl[lid & 0x0f]; a; a = a->next )
174         if( a->lid == lid ) {
175             a->flag = flag;
176             return;
177         }
178     BUG();
179 }
180
181 /****************
182  * If we do not have a local_id in a signature packet, find the owner of
183  * the signature packet in our trustdb or insert them into the trustdb
184  */
185 static int
186 set_signature_packets_lid( PKT_signature *sig )
187 {
188     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
189     TRUSTREC rec;
190     int rc;
191
192     rc = get_pubkey( pk, sig->keyid );
193     if( rc)
194         goto leave;
195     if( !pk->local_id ) {
196         rc = tdbio_search_dir_bypk( pk, &rec );
197         if( rc == -1 )
198             rc = insert_trust_record( pk );
199         if( rc )
200             goto leave;
201     }
202     sig->local_id = pk->local_id;
203
204   leave:
205     free_public_key( pk );
206     return rc;
207 }
208
209
210
211 /****************
212  * Return the keyid from the primary key identified by LID.
213  */
214 int
215 keyid_from_lid( ulong lid, u32 *keyid )
216 {
217     TRUSTREC rec;
218     int rc;
219
220     rc = tdbio_read_record( lid, &rec, RECTYPE_DIR );
221     if( rc ) {
222         log_error("error reading dir record for LID %lu: %s\n",
223                                                     lid, g10_errstr(rc));
224         return G10ERR_TRUSTDB;
225     }
226     if( !rec.r.dir.keylist ) {
227         log_error("no primary key for LID %lu\n", lid );
228         return G10ERR_TRUSTDB;
229     }
230     rc = tdbio_read_record( rec.r.dir.keylist, &rec, RECTYPE_KEY );
231     if( rc ) {
232         log_error("error reading primary key for LID %lu: %s\n",
233                                                     lid, g10_errstr(rc));
234         return G10ERR_TRUSTDB;
235     }
236     keyid_from_fingerprint( rec.r.key.fingerprint, rec.r.key.fingerprint_len,
237                             keyid );
238
239     return 0;
240 }
241
242 /****************
243  * Walk through the signatures of a public key.
244  * The caller must provide a context structure, with all fields set
245  * to zero, but the local_id field set to the requested key;
246  * This function does not change this field.  On return the context
247  * is filled with the local-id of the signature and the signature flag.
248  * No fields should be changed (clearing all fields and setting
249  * pubkeyid is okay to continue with an other pubkey)
250  * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
251  */
252 static int
253 walk_sigrecs( SIGREC_CONTEXT *c, int create )
254 {
255     int rc=0;
256     TRUSTREC *r;
257     ulong rnum;
258
259     if( c->ctl.eof )
260         return -1;
261     r = &c->ctl.rec;
262     if( !c->ctl.init_done ) {
263         c->ctl.init_done = 1;
264         rc = tdbio_read_record( c->lid, r, RECTYPE_DIR );
265         if( rc ) {
266             log_error("LID %lu: error reading dir record: %s\n",
267                                     c->lid, g10_errstr(rc));
268             return rc;
269         }
270         c->ctl.nextuid = r->r.dir.uidlist;
271         /* force a read (what a bad bad hack) */
272         c->ctl.index = SIGS_PER_RECORD;
273         r->r.sig.next = 0;
274     }
275
276     /* need a loop to skip over deleted sigs */
277     do {
278         if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
279             rnum = r->r.sig.next;
280             if( !rnum && c->ctl.nextuid ) { /* read next uid record */
281                 rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID );
282                 if( rc ) {
283                     log_error("error reading next uidrec: %s\n",
284                                                     g10_errstr(rc));
285                     c->ctl.eof = 1;
286                     return rc;
287                 }
288                 if( !r->r.uid.siglist && create ) {
289                     rc = update_sigs_by_lid( c->lid );
290                     if( rc ) {
291                         if( rc == G10ERR_BAD_CERT )
292                             rc = -1;  /* maybe no selfsignature */
293                         if( rc != -1 )
294                             log_info("LID %lu: "
295                                      "error building sigs on the fly: %s\n",
296                                       c->lid, g10_errstr(rc) );
297                         c->ctl.eof = 1;
298                         return rc;
299                     }
300                     rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID );
301                     if( rc ) {
302                         log_error("LID %lu: error re-reading uid record: %s\n",
303                                                 c->lid, g10_errstr(rc));
304                         return rc;
305                     }
306                 }
307                 c->ctl.nextuid = r->r.uid.next;
308                 rnum = r->r.uid.siglist;
309             }
310             if( !rnum ) {
311                 c->ctl.eof = 1;
312                 return -1;  /* return eof */
313             }
314             rc = tdbio_read_record( rnum, r, RECTYPE_SIG );
315             if( rc ) {
316                 log_error(_("error reading sigrec: %s\n"), g10_errstr(rc));
317                 c->ctl.eof = 1;
318                 return rc;
319             }
320             if( r->r.sig.lid != c->lid ) {
321                 log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
322                 c->ctl.eof = 1;
323                 return G10ERR_TRUSTDB;
324             }
325             c->ctl.index = 0;
326         }
327     } while( !r->r.sig.sig[c->ctl.index++].lid );
328
329     c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
330     c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
331     return 0;
332 }
333
334
335
336
337 /***********************************************
338  *************  Trust  stuff  ******************
339  ***********************************************/
340
341
342 /****************
343  * Verify that all our public keys are in the trustDB.
344  */
345 static int
346 verify_own_keys()
347 {
348     int rc;
349     void *enum_context = NULL;
350     PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
351     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
352     u32 keyid[2];
353
354     while( !(rc=enum_secret_keys( &enum_context, sk, 0 ) ) ) {
355         keyid_from_sk( sk, keyid );
356
357         if( DBG_TRUST )
358             log_debug("key %08lX: checking secret key\n", (ulong)keyid[1] );
359
360         /* see whether we can access the public key of this secret key */
361         memset( pk, 0, sizeof *pk );
362         rc = get_pubkey( pk, keyid );
363         if( rc ) {
364             log_error(_("key %08lX: secret key without public key\n"),
365                                                             (ulong)keyid[1] );
366             goto leave;
367         }
368         if( cmp_public_secret_key( pk, sk ) ) {
369             log_error(_("key %08lX: secret and public key don't match\n"),
370                                                             (ulong)keyid[1] );
371             rc = G10ERR_GENERAL;
372             goto leave;
373         }
374
375         /* make sure that the pubkey is in the trustdb */
376         rc = query_trust_record( pk );
377         if( rc == -1 ) { /* put it into the trustdb */
378             rc = insert_trust_record( pk );
379             if( rc ) {
380                 log_error(_("key %08lX: can't put it into the trustdb\n"),
381                                                             (ulong)keyid[1] );
382                 goto leave;
383             }
384         }
385         else if( rc ) {
386             log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
387             goto leave;
388
389         }
390
391         if( DBG_TRUST )
392             log_debug("key %08lX.%lu: stored into ultikey_table\n",
393                                     (ulong)keyid[1], pk->local_id );
394         if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
395             log_error(_("key %08lX: already in ultikey_table\n"),
396                                                         (ulong)keyid[1]);
397
398         release_secret_key_parts( sk );
399         release_public_key_parts( pk );
400     }
401     if( rc != -1 )
402         log_error(_("enum_secret_keys failed: %s\n"), g10_errstr(rc) );
403     else
404         rc = 0;
405
406   leave:
407     free_secret_key( sk );
408     free_public_key( pk );
409     return rc;
410 }
411
412
413 static void
414 print_user_id( const char *text, u32 *keyid )
415 {
416     char *p;
417     size_t n;
418
419     p = get_user_id( keyid, &n );
420     if( *text ) {
421         fputs( text, stdout);
422         putchar(' ');
423     }
424     putchar('\"');
425     print_string( stdout, p, n, 0 );
426     putchar('\"');
427     putchar('\n');
428     m_free(p);
429 }
430
431 static void
432 print_keyid( FILE *fp, ulong lid )
433 {
434     u32 ki[2];
435     if( keyid_from_lid( lid, ki ) )
436         fprintf(fp, "????????.%lu", lid );
437     else
438         fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid );
439 }
440
441 static void
442 print_trust( FILE *fp, unsigned trust )
443 {
444     int c;
445     switch( trust ) {
446       case TRUST_UNKNOWN:   c = 'o'; break;
447       case TRUST_EXPIRED:   c = 'e'; break;
448       case TRUST_UNDEFINED: c = 'q'; break;
449       case TRUST_NEVER:     c = 'n'; break;
450       case TRUST_MARGINAL:  c = 'm'; break;
451       case TRUST_FULLY:     c = 'f'; break;
452       case TRUST_ULTIMATE:  c = 'u'; break;
453       default: fprintf(fp, "%02x", trust ); return;
454     }
455     putc(c, fp);
456 }
457
458 /* (a non-recursive algorithm would be easier) */
459 static int
460 do_list_sigs( ulong root, ulong pubkey, int depth,
461               LOCAL_ID_INFO *lids, unsigned *lineno )
462 {
463     SIGREC_CONTEXT sx;
464     int rc;
465     u32 keyid[2];
466
467     memset( &sx, 0, sizeof sx );
468     sx.lid = pubkey;
469     for(;;) {
470         rc = walk_sigrecs( &sx, 0 );
471         if( rc )
472             break;
473         rc = keyid_from_lid( sx.sig_lid, keyid );
474         if( rc ) {
475             printf("%6u: %*s????????.%lu:%02x\n", *lineno, depth*4, "",
476                                                    sx.sig_lid, sx.sig_flag );
477             ++*lineno;
478         }
479         else {
480             printf("%6u: %*s%08lX.%lu:%02x ", *lineno, depth*4, "",
481                               (ulong)keyid[1], sx.sig_lid, sx.sig_flag );
482             /* check whether we already checked this pubkey */
483             if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
484                 print_user_id("[ultimately trusted]", keyid);
485                 ++*lineno;
486             }
487             else if( sx.sig_lid == pubkey ) {
488                 printf("[self-signature]\n");
489                 ++*lineno;
490             }
491             else if( sx.sig_lid == root ) {
492                 printf("[closed]\n");
493                 ++*lineno;
494             }
495             else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
496                 unsigned refline;
497                 qry_lid_table_flag( lids, sx.sig_lid, &refline );
498                 printf("[see line %u]\n", refline);
499                 ++*lineno;
500             }
501             else if( depth+1 >= MAX_LIST_SIGS_DEPTH  ) {
502                 print_user_id( "[too deeply nested]", keyid );
503                 ++*lineno;
504             }
505             else {
506                 print_user_id( "", keyid );
507                 ++*lineno;
508                 rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
509                 if( rc )
510                     break;
511             }
512         }
513     }
514     return rc==-1? 0 : rc;
515 }
516
517 /****************
518  * List all signatures of a public key
519  */
520 static int
521 list_sigs( ulong pubkey_id )
522 {
523     int rc;
524     u32 keyid[2];
525     LOCAL_ID_INFO *lids;
526     unsigned lineno = 1;
527
528     rc = keyid_from_lid( pubkey_id, keyid );
529     if( rc )
530         return rc;
531     printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
532     print_user_id("", keyid);
533     printf("----------------------\n");
534
535     lids = new_lid_table();
536     rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
537     putchar('\n');
538     release_lid_table(lids);
539     return rc;
540 }
541
542 /****************
543  * List all records of a public key
544  */
545 static int
546 list_records( ulong lid )
547 {
548     int rc;
549     TRUSTREC dr, ur, rec;
550     ulong recno;
551
552     rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
553     if( rc ) {
554         log_error("lid %lu: read dir record failed: %s\n", lid, g10_errstr(rc));
555         return rc;
556     }
557     tdbio_dump_record( &dr, stdout );
558
559     for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
560         rc = tdbio_read_record( recno, &rec, RECTYPE_KEY );
561         if( rc ) {
562             log_error("lid %lu: read key record failed: %s\n",
563                                                 lid, g10_errstr(rc));
564             return rc;
565         }
566         tdbio_dump_record( &rec, stdout );
567     }
568
569     for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
570         rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
571         if( rc ) {
572             log_error("lid %lu: read uid record failed: %s\n",
573                                                 lid, g10_errstr(rc));
574             return rc;
575         }
576         tdbio_dump_record( &ur, stdout );
577         /* preference records */
578         for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
579             rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
580             if( rc ) {
581                 log_error("lid %lu: read pref record failed: %s\n",
582                                                     lid, g10_errstr(rc));
583                 return rc;
584             }
585             tdbio_dump_record( &rec, stdout );
586         }
587         /* sig records */
588         for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
589             rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
590             if( rc ) {
591                 log_error("lid %lu: read sig record failed: %s\n",
592                                                     lid, g10_errstr(rc));
593                 return rc;
594             }
595             tdbio_dump_record( &rec, stdout );
596         }
597     }
598
599     /* add cache record dump here */
600
601
602
603     return rc;
604 }
605
606
607
608 /****************
609  * Function to collect all trustpaths
610  */
611 static int
612 do_list_path( TRUST_INFO *stack, int depth, int max_depth,
613               LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist )
614 {
615     SIGREC_CONTEXT sx;
616     unsigned last_depth;
617     int rc;
618
619     assert(depth);
620
621     /*printf("%2lu/%d: scrutinizig\n", stack[depth-1], depth);*/
622     if( depth >= max_depth || depth >= MAX_LIST_SIGS_DEPTH-1 ) {
623         /*printf("%2lu/%d: too deeply nested\n", stack[depth-1], depth);*/
624         return 0;
625     }
626     memset( &sx, 0, sizeof sx );
627     sx.lid = stack[depth-1].lid;
628     /* loop over all signatures. If we do not have any, try to create them */
629     while( !(rc = walk_sigrecs( &sx, 1 )) ) {
630         TRUST_SEG_LIST tsl, t2, tl;
631         int i;
632
633         stack[depth].lid = sx.sig_lid;
634         stack[depth].trust = 0;
635         if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) {
636             /*printf("%2lu/%d: marked\n", sx.sig_lid, depth );*/
637             ins_lid_table_item( lids, sx.sig_lid, depth);
638             last_depth = depth;
639         }
640         else if( depth  < last_depth ) {
641             /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_lid, depth, last_depth);*/
642             last_depth = depth;
643             upd_lid_table_flag( lids, sx.sig_lid, depth);
644         }
645
646         if( last_depth < depth )
647             /*printf("%2lu/%d: already visited\n", sx.sig_lid, depth)*/;
648         else if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
649             /* found end of path; store it, ordered by path length */
650             tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) );
651             tsl->nseg = depth+1;
652             tsl->dup = 0;
653             for(i=0; i <= depth; i++ )
654                 tsl->seg[i] = stack[i];
655             for(t2=*tslist,tl=NULL; t2; tl=t2, t2 = t2->next )
656                 if( depth < t2->nseg )
657                     break;
658             if( !tl ) {
659                 tsl->next = t2;
660                 *tslist = tsl;
661             }
662             else {
663                 tsl->next = t2;
664                 tl->next = tsl;
665             }
666             /*putchar('.'); fflush(stdout);*/
667             /*printf("%2lu/%d: found\n", sx.sig_lid, depth);*/
668         }
669         else {
670             rc = do_list_path( stack, depth+1, max_depth, lids, tslist);
671             if( rc && rc != -1 )
672                 break;
673         }
674     }
675     return rc==-1? 0 : rc;
676 }
677
678
679 /****************
680  * find the uid record given the uid packet and the dir-record.
681  * Returns: 0 = found
682  *         -1 = No such uid-record
683  *         or other error
684  */
685 static int
686 find_urec( TRUSTREC *dir, PKT_user_id *uid, TRUSTREC *urec )
687 {
688     byte nhash[20];
689     ulong recno;
690     int rc;
691
692     assert(dir->rectype == RECTYPE_DIR );
693     rmd160_hash_buffer( nhash, uid->name, uid->len );
694     for( recno=dir->r.dir.uidlist; recno; recno = urec->r.uid.next ) {
695         rc = tdbio_read_record( recno, urec, RECTYPE_UID );
696         if( rc )
697             return rc == -1 ? G10ERR_READ_FILE : rc;
698         if( !memcmp( nhash, urec->r.uid.namehash, 20 ) )
699             return 0;
700     }
701
702     return -1;
703 }
704
705
706 /****************
707  * Test whether zthe signature lid is already in the (in mem) list.
708  * Returns: True if it is a duplicate
709  */
710 static int
711 test_dupsig( TRUSTREC *rec, ulong lid )
712 {
713     int i;
714     ulong alid;
715
716     for( ; rec; rec = rec->next ) {
717         for(i=0; i < SIGS_PER_RECORD && (alid = rec->r.sig.sig[i].lid); i++ )
718             if( alid == lid )
719                 return 1;
720     }
721     return 0;
722 }
723
724
725 /****************
726  * release the sigrec from the uidlist
727  */
728 static void
729 rel_uidsigs( TRUSTREC *urec )
730 {
731     TRUSTREC *r2, *rec;
732     assert( urec->rectype == RECTYPE_UID );
733
734     for(rec=urec->next ; rec; rec = r2 ) {
735         assert( rec->rectype == RECTYPE_SIG );
736         r2 = rec->next;
737         m_free( rec );
738     }
739     urec->next = NULL;
740 }
741
742 static int
743 no_selfsig_del( ulong lid, u32 *keyid, TRUSTREC *urec )
744 {
745     int rc;
746
747     log_error("key %08lX.%lu, uid %02X%02X: "
748               "no self-signature - user id removed\n",
749               (ulong)keyid[1], lid, urec->r.uid.namehash[18],
750               urec->r.uid.namehash[19] );
751     rel_uidsigs( urec );
752     rc = tdbio_delete_uidrec( lid, urec->recnum );
753     if( rc )
754         log_error("no_selfsig_del: delete_uid %lu failed: %s\n",
755                                         lid, g10_errstr(rc) );
756     return rc;
757 }
758
759 /****************
760  * Write the signature records from the in-mem list at urec
761  * (The sequence of signatures does not matter)
762  */
763 static int
764 write_sigs_from_urec( ulong lid, u32 *keyid, TRUSTREC *urec )
765 {
766     int rc;
767     TRUSTREC *rec, srec;
768     ulong nextrecno;
769     ulong recno;
770
771     nextrecno = urec->r.uid.siglist;
772     urec->r.uid.siglist = 0; /* end of list marker */
773     for( rec = urec->next; rec; rec = rec->next ) {
774         assert( rec->rectype == RECTYPE_SIG );
775         if( nextrecno ) { /* read the sig record, so it can be reused */
776             rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG );
777             if( rc ) {
778                 log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n",
779                                                   nextrecno, g10_errstr(rc) );
780                 return rc;
781             }
782             recno = nextrecno;
783             nextrecno = srec.r.sig.next;
784         }
785         else
786             recno = tdbio_new_recnum();
787
788         /* link together (the sequence of signatures does not matter) */
789         rec->r.sig.next = urec->r.uid.siglist;
790         urec->r.uid.siglist = recno;
791         rec->r.sig.lid = lid;
792         /* and write */
793         rec->recnum = recno;
794         rc = tdbio_write_record( rec );
795         if( rc ) {
796             log_error("write_sig_from_urec: write sigrecno %lu failed: %s\n",
797                                                   recno, g10_errstr(rc) );
798             return rc;
799         }
800     }
801
802     /* write the urec back */
803     rc = tdbio_write_record( urec );
804     if( rc ) {
805         log_error("write_sig_from_urec: write urec %lu failed: %s\n",
806                                             urec->recnum, g10_errstr(rc) );
807         return rc;
808     }
809
810     /* delete remaining old sigrecords */
811     while( nextrecno ) {
812         rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG );
813         if( rc ) {
814             log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n",
815                                               nextrecno, g10_errstr(rc) );
816             return rc;
817         }
818         rc = tdbio_delete_record( nextrecno );
819         if( rc ) {
820             log_error("write_sig_from_urec: delete old %lu failed: %s\n",
821                                               nextrecno, g10_errstr(rc) );
822             return rc;
823
824         }
825         nextrecno = srec.r.sig.next;
826     }
827
828     return rc;
829 }
830
831 /****************
832  * If we do not have sigrecs for the given key, build them and write them
833  * to the trustdb
834  */
835 static int
836 update_sigs( TRUSTREC *dir )
837 {
838     TRUSTREC *rec, krec;
839     TRUSTREC urec;
840     TRUSTREC *sigrec_list;
841     KBNODE keyblock = NULL;
842     KBNODE node;
843     int i, sigidx, have_urec ;
844     ulong lid = dir->r.dir.lid;
845     u32 keyid[2];
846     int miskey=0;
847     int rc=0;
848
849     if( DBG_TRUST )
850         log_debug("update_sigs for %lu\n", lid );
851
852     if( (rc=tdbio_read_record( dir->r.dir.keylist, &krec, RECTYPE_KEY )) ) {
853         log_error("update_sigs: can't read primary key for %lu\n", lid);
854         goto leave;
855     }
856     rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint,
857                                            krec.r.key.fingerprint_len );
858     if( rc ) {
859         log_error( "update_sigs: keyblock for %lu not found: %s\n",
860                                                     lid, g10_errstr(rc) );
861         goto leave;
862     }
863
864     /* check all key signatures */
865     assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
866     have_urec = 0;
867     sigrec_list = NULL;
868     sigidx = 0;
869     for( node=keyblock; node; node = node->next ) {
870         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
871             keyid_from_pk( node->pkt->pkt.public_key, keyid );
872         else if( node->pkt->pkttype == PKT_USER_ID ) {
873             if( have_urec && !(urec.mark & 1) ) {
874                if( (rc = no_selfsig_del(lid, keyid, &urec )) )
875                    goto leave;
876                 have_urec = 0;
877             }
878             if( have_urec ) {
879                 rc = write_sigs_from_urec( lid, keyid, &urec );
880                 if( rc )
881                     goto leave;
882                 rel_uidsigs( &urec );
883             }
884             rc = find_urec( dir, node->pkt->pkt.user_id, &urec );
885             urec.next = NULL;
886             urec.mark = 0;
887             have_urec = sigidx = 0;
888             if( rc == -1 ) {
889                 log_info("update_sigs: new user id for %lu\n", lid );
890                 /* fixme: we should add the new user id here */
891             }
892             else if( rc ) {
893                 log_error("update_sigs: find_urec %lu failed: %s\n",
894                                                 lid, g10_errstr(rc) );
895                 goto leave;
896             }
897             else
898                 have_urec = 1;
899         }
900         else if( have_urec && node->pkt->pkttype == PKT_SIGNATURE ) {
901             PKT_signature *sig = node->pkt->pkt.signature;
902
903             if( (sig->sig_class&~3) == 0x10 ) {
904                 rc = check_key_signature( keyblock, node, &i );
905                 if( rc == G10ERR_NO_PUBKEY ) {
906                     log_info("key %08lX.%lu, uid %02X%02X: "
907                               "no public key for signature %08lX\n",
908                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
909                               urec.r.uid.namehash[19], (ulong)sig->keyid[1] );
910                     miskey = 1;
911                 }
912                 else if( rc )
913                     log_error("key %08lX.%lu, uid %02X%02X: "
914                               "invalid %ssignature: %s\n",
915                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
916                               urec.r.uid.namehash[19],
917                               i?"self-":"",g10_errstr(rc));
918                 else if( i ) /* mark that we have a valid selfsignature */
919                     urec.mark |= 1;
920                 else if( (rc = set_signature_packets_lid( sig )) )
921                     log_error("key %08lX.%lu, uid %02X%02X: "
922                               "can't get LID of signer: %s\n",
923                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
924                               urec.r.uid.namehash[19], g10_errstr(rc));
925                 else if( !test_dupsig( urec.next, sig->local_id ) ) {
926                     /* put the valid signature into a list */
927                     rec = urec.next;
928                     if( !rec || sigidx == SIGS_PER_RECORD ) {
929                         rec = m_alloc_clear( sizeof *rec );
930                         rec->rectype = RECTYPE_SIG;
931                         rec->next = urec.next;
932                         urec.next = rec;
933                         sigidx = 0;
934                     }
935                     rec->r.sig.sig[sigidx].lid = sig->local_id;
936                     rec->r.sig.sig[sigidx].flag = 0;
937                     sigidx++;
938                     if( DBG_TRUST )
939                         log_debug("key %08lX.%lu, uid %02X%02X: "
940                               "signed by LID %lu\n",
941                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
942                               urec.r.uid.namehash[19], sig->local_id);
943                 }
944                 else if( DBG_TRUST )
945                     log_debug("key %08lX.%lu, uid %02X%02X: "
946                               "duplicate signature by LID %lu\n",
947                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
948                               urec.r.uid.namehash[19], sig->local_id );
949                 rc = 0;
950             }
951             else {
952                 /* fixme: handle other sig classes here */
953                 /* FIXME: Revocations!!! */
954             }
955         }
956     }
957     if( have_urec && !(urec.mark & 1) ) {
958         if( (rc = no_selfsig_del(lid, keyid, &urec )) )
959             goto leave;
960         have_urec = 0;
961     }
962     if( have_urec ) {
963         rc = write_sigs_from_urec( lid, keyid, &urec );
964         if( rc )
965             goto leave;
966         rel_uidsigs( &urec );
967     }
968     dir->r.dir.dirflags |= DIRF_CHECKED;
969     if( miskey )
970         dir->r.dir.dirflags |= DIRF_MISKEY;
971     else
972         dir->r.dir.dirflags &= ~DIRF_MISKEY;
973     rc = tdbio_write_record( dir );
974     if( rc ) {
975         log_error("update_sigs: write dir record failed: %s\n", g10_errstr(rc));
976         return rc;
977     }
978
979   leave:
980     /* fixme: need more cleanup in case of an error */
981     release_kbnode( keyblock );
982     if( DBG_TRUST )
983         log_debug("update_sigs for %lu: %s\n", lid, g10_errstr(rc) );
984     return rc;
985 }
986
987
988 static int
989 update_sigs_by_lid( ulong lid )
990 {
991     int rc;
992     TRUSTREC rec;
993
994     rc = tdbio_read_record( lid, &rec, RECTYPE_DIR );
995     if( rc ) {
996         log_error("LID %lu: error reading dir record: %s\n",
997                                 lid, g10_errstr(rc));
998         return rc;
999     }
1000     if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
1001         rc = update_sigs( &rec );
1002     return rc;
1003 }
1004
1005 /****************
1006  * Make a list of trust paths
1007  */
1008 static int
1009 make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist )
1010 {
1011     int i, rc;
1012     LOCAL_ID_INFO *lids = new_lid_table();
1013     TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1014     TRUST_SEG_LIST tsl, tslist;
1015     int max_depth = 4;
1016
1017     tslist = *ret_tslist = NULL;
1018
1019     if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) {
1020         tslist = m_alloc( sizeof *tslist );
1021         tslist->nseg = 1;
1022         tslist->dup = 0;
1023         tslist->seg[0].lid = lid;
1024         tslist->seg[0].trust = 0;
1025         tslist->next = NULL;
1026         rc = 0;
1027     }
1028     else {
1029         stack[0].lid = lid;
1030         stack[0].trust = 0;
1031         rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1032     }
1033     if( !rc ) { /* wipe out duplicates */
1034         LOCAL_ID_INFO *work = new_lid_table();
1035         for( tsl=tslist; tsl; tsl = tsl->next ) {
1036             for(i=1; i < tsl->nseg-1; i++ ) {
1037                 if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1038                     tsl->dup = 1; /* mark as duplicate */
1039                     break;
1040                 }
1041             }
1042         }
1043         release_lid_table(work);
1044         *ret_tslist = tslist;
1045     }
1046     else
1047         ; /* FIXME: release tslist */
1048     release_lid_table(lids);
1049     return rc;
1050 }
1051
1052
1053 /****************
1054  * Given a trust segment list tslist, walk over all paths and fill in
1055  * the trust information for each segment.  What this function does is
1056  * to assign a trustvalue to the first segment (which is the requested key)
1057  * of each path.
1058  *
1059  * FIXME: We have to do more thinking here. e.g. we should never increase
1060  *        the trust value.
1061  *
1062  * Do not do it for duplicates.
1063  */
1064 static int
1065 propagate_trust( TRUST_SEG_LIST tslist )
1066 {
1067     int i, rc;
1068     unsigned trust, tr;
1069     TRUST_SEG_LIST tsl;
1070
1071     for(tsl = tslist; tsl; tsl = tsl->next ) {
1072         if( tsl->dup )
1073             continue;
1074         assert( tsl->nseg );
1075         /* the last segment is always an ultimately trusted one, so we can
1076          * assign a fully trust to the next one */
1077         i = tsl->nseg-1;
1078         tsl->seg[i].trust = TRUST_ULTIMATE;
1079         trust = TRUST_FULLY;
1080         for(i-- ; i >= 0; i-- ) {
1081             tsl->seg[i].trust = trust;
1082             if( i > 0 ) {
1083                 /* get the trust of this pubkey */
1084                 rc = get_ownertrust( tsl->seg[i].lid, &tr );
1085                 if( rc )
1086                     return rc;
1087                 if( tr < trust )
1088                     trust = tr;
1089             }
1090         }
1091     }
1092     return 0;
1093 }
1094
1095
1096 /****************
1097  * we have the pubkey record and all needed informations are in the trustdb
1098  * but nothing more is known.
1099  * (this function may re-read the dir record dr)
1100  */
1101 static int
1102 do_check( TRUSTREC *dr, unsigned *trustlevel )
1103 {
1104     int i, rc=0;
1105     TRUST_SEG_LIST tsl, tsl2, tslist;
1106     int marginal, fully;
1107     int fully_needed = opt.completes_needed;
1108     int marginal_needed = opt.marginals_needed;
1109     unsigned tflags = 0;
1110
1111     assert( fully_needed > 0 && marginal_needed > 1 );
1112
1113
1114     *trustlevel = TRUST_UNDEFINED;
1115
1116     if( !dr->r.dir.keylist ) {
1117         log_error("Ooops, no keys\n");
1118         return G10ERR_TRUSTDB;
1119     }
1120     if( !dr->r.dir.uidlist ) {
1121         log_error("Ooops, no user ids\n");
1122         return G10ERR_TRUSTDB;
1123     }
1124
1125     /* did we already check the signatures */
1126     if( !(dr->r.dir.dirflags & DIRF_CHECKED) ) /* no - do it now */
1127         rc = update_sigs( dr );
1128
1129     if( dr->r.dir.dirflags & DIRF_REVOKED )
1130         tflags |= TRUST_FLAG_REVOKED;
1131
1132   #if 0
1133     if( !rc && !dr->r.dir.siglist ) {
1134         /* We do not have any signatures; check whether it is one of our
1135          * secret keys */
1136         if( !qry_lid_table_flag( ultikey_table, dr->r.dir.lid, NULL ) )
1137             *trustlevel = tflags | TRUST_ULTIMATE;
1138         return 0;
1139     }
1140   #endif
1141     if( rc )
1142         return rc;  /* error while looking for sigrec or building sigrecs */
1143
1144     /* fixme: take it from the cache if it is valid */
1145
1146     /* Make a list of all possible trust-paths */
1147     rc = make_tsl( dr->r.dir.lid, &tslist );
1148     if( rc )
1149         return rc;
1150     rc = propagate_trust( tslist );
1151     if( rc )
1152         return rc;
1153     for(tsl = tslist; tsl; tsl = tsl->next ) {
1154         if( tsl->dup )
1155             continue;
1156
1157         if( opt.verbose ) {
1158             log_info("trust path:" );
1159             for(i=0; i < tsl->nseg; i++ ) {
1160                 putc(' ',stderr);
1161                 print_keyid( stderr, tsl->seg[i].lid );
1162                 putc(':',stderr);
1163                 print_trust( stderr, tsl->seg[i].trust );
1164             }
1165             putc('\n',stderr);
1166         }
1167     }
1168
1169     /* and see whether there is a trusted path.
1170      * We only have to look at the first segment, because
1171      * propagate_trust has investigated all other segments */
1172     marginal = fully = 0;
1173     for(tsl = tslist; tsl; tsl = tsl->next ) {
1174         if( tsl->dup )
1175             continue;
1176         if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
1177             *trustlevel = tflags | TRUST_ULTIMATE; /* our own key */
1178             break;
1179         }
1180         if( tsl->seg[0].trust == TRUST_FULLY ) {
1181             marginal++;
1182             fully++;
1183         }
1184         else if( tsl->seg[0].trust == TRUST_MARGINAL )
1185             marginal++;
1186
1187         if( fully >= fully_needed ) {
1188             *trustlevel = tflags | TRUST_FULLY;
1189             break;
1190         }
1191     }
1192     if( !tsl && marginal >= marginal_needed )
1193         *trustlevel = tflags | TRUST_MARGINAL;
1194
1195     /* cache the tslist */
1196     if( last_trust_web_key ) {
1197         for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
1198             tsl2 = tsl->next;
1199             m_free(tsl);
1200         }
1201     }
1202     last_trust_web_key = dr->r.dir.lid;
1203     last_trust_web_tslist = tslist;
1204     return 0;
1205 }
1206
1207
1208 /***********************************************
1209  ****************  API  ************************
1210  ***********************************************/
1211
1212 /****************
1213  * Perform some checks over the trustdb
1214  *  level 0: only open the db
1215  *        1: used for initial program startup
1216  */
1217 int
1218 init_trustdb( int level, const char *dbname )
1219 {
1220     int rc=0;
1221
1222     if( !ultikey_table )
1223         ultikey_table = new_lid_table();
1224
1225     if( !level || level==1 ) {
1226         rc = tdbio_set_dbname( dbname, !!level );
1227         if( rc )
1228             return rc;
1229         if( !level )
1230             return 0;
1231
1232         /* verify that our own keys are in the trustDB
1233          * or move them to the trustdb. */
1234         rc = verify_own_keys();
1235
1236         /* should we check whether there is no other ultimately trusted
1237          * key in the database? */
1238
1239     }
1240     else
1241         BUG();
1242
1243     return rc;
1244 }
1245
1246
1247 void
1248 list_trustdb( const char *username )
1249 {
1250     TRUSTREC rec;
1251
1252     if( username && *username == '#' ) {
1253         int rc;
1254         ulong lid = atoi(username+1);
1255
1256         if( (rc = list_records( lid)) )
1257             log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
1258         else if( (rc = list_sigs( lid )) )
1259             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1260     }
1261     else if( username ) {
1262         PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1263         int rc;
1264
1265         if( (rc = get_pubkey_byname( pk, username )) )
1266             log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1267         else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1268             log_error("problem finding '%s' in trustdb: %s\n",
1269                                                 username, g10_errstr(rc));
1270         else if( rc == -1 )
1271             log_error("user '%s' not in trustdb\n", username);
1272         else if( (rc = list_records( pk->local_id)) )
1273             log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
1274         else if( (rc = list_sigs( pk->local_id )) )
1275             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1276         free_public_key( pk );
1277     }
1278     else {
1279         ulong recnum;
1280         int i;
1281
1282         printf("TrustDB: %s\n", tdbio_get_dbname() );
1283         for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- )
1284             putchar('-');
1285         putchar('\n');
1286         for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
1287             tdbio_dump_record( &rec, stdout );
1288     }
1289 }
1290
1291 /****************
1292  * Print a list of all defined owner trust value.
1293  */
1294 void
1295 export_ownertrust()
1296 {
1297     TRUSTREC rec;
1298     TRUSTREC rec2;
1299     ulong recnum;
1300     int i;
1301     byte *p;
1302     int rc;
1303
1304     for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
1305         if( rec.rectype == RECTYPE_DIR ) {
1306             if( !rec.r.dir.keylist ) {
1307                 log_error("Oops; directory record w/o primary key\n");
1308                 continue;
1309             }
1310             if( !rec.r.dir.ownertrust )
1311                 continue;
1312             rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
1313             if( rc ) {
1314                 log_error("error reading key record: %s\n", g10_errstr(rc));
1315                 continue;
1316             }
1317             p = rec2.r.key.fingerprint;
1318             for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
1319                 printf("%02X", *p );
1320             printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
1321         }
1322     }
1323 }
1324
1325
1326 void
1327 import_ownertrust( const char *fname )
1328 {
1329     FILE *fp;
1330     int is_stdin=0;
1331     char line[256];
1332     char *p;
1333     size_t n, fprlen;
1334     unsigned otrust;
1335
1336     if( !fname || (*fname == '-' && !fname[1]) ) {
1337         fp = stdin;
1338         fname = "[stdin]";
1339         is_stdin = 1;
1340     }
1341     else if( !(fp = fopen( fname, "r" )) ) {
1342         log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
1343         return;
1344     }
1345
1346     while( fgets( line, DIM(line)-1, fp ) ) {
1347         TRUSTREC rec;
1348         int rc;
1349
1350         if( !*line || *line == '#' )
1351             continue;
1352         n = strlen(line);
1353         if( line[n-1] != '\n' ) {
1354             log_error_f(fname, "line to long\n" );
1355             break; /* can't continue */
1356         }
1357         for(p = line; *p && *p != ':' ; p++ )
1358             if( !isxdigit(*p) )
1359                 break;
1360         if( *p != ':' ) {
1361             log_error_f(fname, "error: missing colon\n" );
1362             continue;
1363         }
1364         fprlen = p - line;
1365         if( fprlen != 32 && fprlen != 40 ) {
1366             log_error_f(fname, "error: invalid fingerprint\n" );
1367             continue;
1368         }
1369         if( sscanf(p, ":%u:", &otrust ) != 1 ) {
1370             log_error_f(fname, "error: no otrust value\n" );
1371             continue;
1372         }
1373         if( !otrust )
1374             continue; /* no otrust defined - no need to update or insert */
1375         /* convert the ascii fingerprint to binary */
1376         for(p=line, fprlen=0; *p != ':'; p += 2 )
1377             line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
1378         line[fprlen] = 0;
1379
1380       repeat:
1381         rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
1382         if( !rc ) { /* found: update */
1383             if( rec.r.dir.ownertrust )
1384                 log_info("LID %lu: changing trust from %u to %u\n",
1385                           rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
1386             else
1387                 log_info("LID %lu: setting trust to %u\n",
1388                                    rec.r.dir.lid, otrust );
1389             rec.r.dir.ownertrust = otrust;
1390             rc = tdbio_write_record( &rec );
1391             if( rc )
1392                 log_error_f(fname, "error updating otrust: %s\n",
1393                                                     g10_errstr(rc));
1394         }
1395         else if( rc == -1 ) { /* not found; get the key from the ring */
1396             PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1397
1398             log_info_f(fname, "key not in trustdb, searching ring.\n");
1399             rc = get_pubkey_byfprint( pk, line, fprlen );
1400             if( rc )
1401                 log_info_f(fname, "key not in ring: %s\n", g10_errstr(rc));
1402             else {
1403                 rc = query_trust_record( pk );  /* only as assertion */
1404                 if( rc != -1 )
1405                     log_error_f(fname, "Oops: key is now in trustdb???\n");
1406                 else {
1407                     rc = insert_trust_record( pk );
1408                     if( !rc )
1409                         goto repeat; /* update the ownertrust */
1410                     log_error_f(fname, "insert trust record failed: %s\n",
1411                                                            g10_errstr(rc) );
1412                 }
1413             }
1414         }
1415         else /* error */
1416             log_error_f(fname, "error finding dir record: %s\n",
1417                                                     g10_errstr(rc));
1418     }
1419     if( ferror(fp) )
1420         log_error_f(fname, _("read error: %s\n"), strerror(errno) );
1421     if( !is_stdin )
1422         fclose(fp);
1423 }
1424
1425
1426 void
1427 list_trust_path( int max_depth, const char *username )
1428 {
1429     int rc;
1430     int wipe=0;
1431     int i;
1432     TRUSTREC rec;
1433     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1434
1435     if( max_depth < 0 ) {
1436         wipe = 1;
1437         max_depth = -max_depth;
1438     }
1439
1440     if( (rc = get_pubkey_byname( pk, username )) )
1441         log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1442     else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1443         log_error("problem finding '%s' in trustdb: %s\n",
1444                                             username, g10_errstr(rc));
1445     else if( rc == -1 ) {
1446         log_info("user '%s' not in trustdb - inserting\n", username);
1447         rc = insert_trust_record( pk );
1448         if( rc )
1449             log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
1450         else {
1451             assert( pk->local_id );
1452         }
1453     }
1454
1455     if( !rc ) {
1456         TRUST_SEG_LIST tsl, tslist = NULL;
1457
1458         if( !qry_lid_table_flag( ultikey_table, pk->local_id, NULL ) ) {
1459             tslist = m_alloc( sizeof *tslist );
1460             tslist->nseg = 1;
1461             tslist->dup = 0;
1462             tslist->seg[0].lid = pk->local_id;
1463             tslist->seg[0].trust = 0;
1464             tslist->next = NULL;
1465             rc = 0;
1466         }
1467         else {
1468             LOCAL_ID_INFO *lids = new_lid_table();
1469             TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1470
1471             stack[0].lid = pk->local_id;
1472             stack[0].trust = 0;
1473             rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1474             if( wipe ) { /* wipe out duplicates */
1475                 LOCAL_ID_INFO *work;
1476
1477                 work = new_lid_table();
1478                 for( tsl=tslist; tsl; tsl = tsl->next ) {
1479                     for(i=1; i < tsl->nseg-1; i++ ) {
1480                         if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1481                             tsl->dup = 1; /* mark as duplicate */
1482                             break;
1483                         }
1484                     }
1485                 }
1486                 release_lid_table(work);
1487             }
1488             release_lid_table(lids);
1489         }
1490         if( rc )
1491             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1492         rc = propagate_trust( tslist );
1493         if( rc )
1494             log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
1495         for(tsl = tslist; tsl; tsl = tsl->next ) {
1496             int i;
1497
1498             if( tsl->dup )
1499                 continue;
1500             printf("trust path:" );
1501             for(i=0; i < tsl->nseg; i++ ) {
1502                 putc(' ',stdout);
1503                 print_keyid( stdout, tsl->seg[i].lid );
1504                 putc(':',stdout);
1505                 print_trust( stdout, tsl->seg[i].trust );
1506             }
1507             putchar('\n');
1508         }
1509     }
1510
1511     free_public_key( pk );
1512 }
1513
1514
1515 /****************
1516  * Check the complete trustdb or only the entries for the given username
1517  */
1518 void
1519 check_trustdb( const char *username )
1520 {
1521     TRUSTREC rec;
1522     int rc;
1523
1524     if( username && *username == '#' ) {
1525         int rc;
1526         ulong lid = atoi(username+1);
1527
1528         if( (rc = update_sigs_by_lid( lid )) )
1529             log_error("lid %lu: check failed: %s\n",
1530                                         lid, g10_errstr(rc));
1531         else
1532             log_info("lid %lu: checked: %s\n", lid, g10_errstr(rc));
1533     }
1534     else if( username ) {
1535         PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1536
1537         if( (rc = get_pubkey_byname( pk, username )) )
1538             log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1539         else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1540             log_error("problem finding '%s' in trustdb: %s\n",
1541                                                 username, g10_errstr(rc));
1542         else if( rc == -1 )
1543             log_error("user '%s' not in trustdb\n", username);
1544         else if( (rc = update_sigs( &rec )) )
1545             log_error("lid %lu: check failed: %s\n",
1546                                         rec.recnum, g10_errstr(rc));
1547         else
1548             log_info("lid %lu: checked: %s\n", rec.recnum, g10_errstr(rc));
1549         free_public_key( pk );
1550     }
1551     else {
1552         ulong recnum;
1553
1554         for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
1555             if( rec.rectype == RECTYPE_DIR ) {
1556                 rc = update_sigs( &rec );
1557                 if( rc )
1558                     log_error("lid %lu: check failed: %s\n",
1559                                                  recnum, g10_errstr(rc) );
1560                 else
1561                     log_info("lid %lu: checked\n", recnum );
1562             }
1563         }
1564     }
1565 }
1566
1567 /****************
1568  * Get the trustlevel for this PK.
1569  * Note: This does not ask any questions
1570  * Returns: 0 okay of an errorcode
1571  *
1572  * It operates this way:
1573  *  locate the pk in the trustdb
1574  *      found:
1575  *          Do we have a valid cache record for it?
1576  *              yes: return trustlevel from cache
1577  *              no:  make a cache record and all the other stuff
1578  *      not found:
1579  *          try to insert the pubkey into the trustdb and check again
1580  *
1581  * Problems: How do we get the complete keyblock to check that the
1582  *           cache record is actually valid?  Think we need a clever
1583  *           cache in getkey.c  to keep track of this stuff. Maybe it
1584  *           is not necessary to check this if we use a local pubring. Hmmmm.
1585  */
1586 int
1587 check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
1588 {
1589     TRUSTREC rec;
1590     unsigned trustlevel = TRUST_UNKNOWN;
1591     int rc=0;
1592     u32 cur_time;
1593     u32 keyid[2];
1594
1595
1596     keyid_from_pk( pk, keyid );
1597
1598     /* get the pubkey record */
1599     if( pk->local_id ) {
1600         if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1601             log_error("check_trust: read dir record failed\n");
1602             return G10ERR_TRUSTDB;
1603         }
1604     }
1605     else { /* no local_id: scan the trustdb */
1606         if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
1607             log_error("check_trust: search dir record failed: %s\n",
1608                                                             g10_errstr(rc));
1609             return rc;
1610         }
1611         else if( rc == -1 ) { /* not found - insert */
1612             rc = insert_trust_record( pk );
1613             if( rc ) {
1614                 log_error(_("key %08lX: insert trust record failed: %s\n"),
1615                                                 keyid[1], g10_errstr(rc));
1616                 goto leave;
1617             }
1618             log_info(_("key %08lX.%lu: inserted into trustdb\n"),
1619                                           keyid[1], pk->local_id );
1620             /* and re-read the dir record */
1621             if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1622                 log_error("check_trust: reread dir record failed\n");
1623                 return G10ERR_TRUSTDB;
1624             }
1625         }
1626     }
1627     cur_time = make_timestamp();
1628     if( pk->timestamp > cur_time ) {
1629         log_info(_("key %08lX.%lu: created in future "
1630                    "(time warp or clock problem)\n"),
1631                                           keyid[1], pk->local_id );
1632         return G10ERR_TIME_CONFLICT;
1633     }
1634
1635     if( pk->valid_days && add_days_to_timestamp(pk->timestamp,
1636                                                 pk->valid_days) < cur_time ) {
1637         log_info(_("key %08lX.%lu: expired at %s\n"),
1638                         keyid[1], pk->local_id,
1639                     strtimestamp( add_days_to_timestamp(pk->timestamp,
1640                                                         pk->valid_days)));
1641          trustlevel = TRUST_EXPIRED;
1642     }
1643     else {
1644         rc = do_check( &rec, &trustlevel );
1645         if( rc ) {
1646             log_error(_("key %08lX.%lu: trust check failed: %s\n"),
1647                             keyid[1], pk->local_id, g10_errstr(rc));
1648             return rc;
1649         }
1650     }
1651
1652
1653   leave:
1654     if( DBG_TRUST )
1655         log_debug("check_trust() returns trustlevel %04x.\n", trustlevel);
1656     *r_trustlevel = trustlevel;
1657     return 0;
1658 }
1659
1660
1661 int
1662 query_trust_info( PKT_public_key *pk )
1663 {
1664     unsigned trustlevel;
1665     int c;
1666
1667     if( check_trust( pk, &trustlevel ) )
1668         return '?';
1669     if( trustlevel & TRUST_FLAG_REVOKED )
1670         return 'r';
1671     switch( (trustlevel & TRUST_MASK) ) {
1672       case TRUST_UNKNOWN:   c = 'o'; break;
1673       case TRUST_EXPIRED:   c = 'e'; break;
1674       case TRUST_UNDEFINED: c = 'q'; break;
1675       case TRUST_NEVER:     c = 'n'; break;
1676       case TRUST_MARGINAL:  c = 'm'; break;
1677       case TRUST_FULLY:     c = 'f'; break;
1678       case TRUST_ULTIMATE:  c = 'u'; break;
1679       default: BUG();
1680     }
1681     return c;
1682 }
1683
1684
1685
1686 /****************
1687  * Enumerate all keys, which are needed to build all trust paths for
1688  * the given key.  This function does not return the key itself or
1689  * the ultimate key.
1690  *
1691  *  1) create a void pointer and initialize it to NULL
1692  *  2) pass this void pointer by reference to this function.
1693  *     Set lid to the key you want to enumerate and pass it by reference.
1694  *  3) call this function as long as it does not return -1
1695  *     to indicate EOF. LID does contain the next key used to build the web
1696  *  4) Always call this function a last time with LID set to NULL,
1697  *     so that it can free its context.
1698  */
1699 int
1700 enum_trust_web( void **context, ulong *lid )
1701 {
1702     ENUM_TRUST_WEB_CONTEXT *c = *context;
1703
1704     if( !c ) { /* make a new context */
1705         c = m_alloc_clear( sizeof *c );
1706         *context = c;
1707         if( *lid != last_trust_web_key && last_trust_web_key )
1708             log_bug("enum_trust_web: nyi\n"); /* <--- FIXME */
1709         c->tsl = last_trust_web_tslist;
1710         c->index = 1;
1711     }
1712
1713     if( !lid ) { /* free the context */
1714         m_free( c );
1715         *context = NULL;
1716         return 0;
1717     }
1718
1719     while( c->tsl ) {
1720         if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) {
1721             *lid = c->tsl->seg[c->index].lid;
1722             c->index++;
1723             return 0;
1724         }
1725         c->index = 1;
1726         c->tsl = c->tsl->next;
1727     }
1728     return -1; /* eof */
1729 }
1730
1731
1732 /****************
1733  * Return the assigned ownertrust value for the given LID
1734  */
1735 int
1736 get_ownertrust( ulong lid, unsigned *r_otrust )
1737 {
1738     TRUSTREC rec;
1739
1740     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1741         log_error("get_ownertrust: read dir record failed\n");
1742         return G10ERR_TRUSTDB;
1743     }
1744     if( r_otrust )
1745         *r_otrust = rec.r.dir.ownertrust;
1746     return 0;
1747 }
1748
1749 int
1750 get_ownertrust_info( ulong lid )
1751 {
1752     unsigned otrust;
1753     int c;
1754
1755     if( get_ownertrust( lid, &otrust ) )
1756         return '?';
1757     switch( (otrust & TRUST_MASK) ) {
1758       case TRUST_NEVER:     c = 'n'; break;
1759       case TRUST_MARGINAL:  c = 'm'; break;
1760       case TRUST_FULLY:     c = 'f'; break;
1761       case TRUST_ULTIMATE:  c = 'u'; break;
1762       default:              c = '-'; break;
1763     }
1764     return c;
1765 }
1766
1767
1768 byte *
1769 get_pref_data( ulong lid, const byte *namehash, size_t *ret_n )
1770 {
1771     TRUSTREC rec;
1772     ulong recno;
1773     int rc;
1774
1775     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1776         log_error("get_pref_data: read dir record failed\n");
1777         return NULL;
1778     }
1779
1780     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
1781         rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
1782         if( rc ) {
1783             log_error("get_pref_data: read uid record failed: %s\n",
1784                                                      g10_errstr(rc));
1785             return NULL;
1786         }
1787         if( rec.r.uid.prefrec
1788             && ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) ))  {
1789             byte *buf;
1790             /* found the correct one or the first one */
1791             rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
1792             if( rc ) {
1793                 log_error("get_pref_data: read pref record failed: %s\n",
1794                                                          g10_errstr(rc));
1795                 return NULL;
1796             }
1797             if( rec.r.pref.next )
1798                 log_info("warning: can't yet handle long pref records\n");
1799             buf = m_alloc( ITEMS_PER_PREF_RECORD );
1800             memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD );
1801             *ret_n = ITEMS_PER_PREF_RECORD;
1802             return buf;
1803         }
1804     }
1805     return NULL;
1806 }
1807
1808
1809
1810 /****************
1811  * Check whether the algorithm is in one of the pref records
1812  */
1813 int
1814 is_algo_in_prefs( ulong lid, int preftype, int algo )
1815 {
1816     TRUSTREC rec;
1817     ulong recno;
1818     int i, rc;
1819     byte *pref;
1820
1821     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1822         log_error("is_algo_in_prefs: read dir record failed\n");
1823         return 0;
1824     }
1825
1826     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
1827         rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
1828         if( rc ) {
1829             log_error("is_algo_in_prefs: read uid record failed: %s\n",
1830                                                      g10_errstr(rc));
1831             return 0;
1832         }
1833         if( rec.r.uid.prefrec ) {
1834             rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
1835             if( rc ) {
1836                 log_error("is_algo_in_prefs: read pref record failed: %s\n",
1837                                                          g10_errstr(rc));
1838                 return 0;
1839             }
1840             if( rec.r.pref.next )
1841                 log_info("warning: can't yet handle long pref records\n");
1842             pref = rec.r.pref.data;
1843             for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) {
1844                 if( pref[i] == preftype && pref[i+1] == algo )
1845                     return 1;
1846             }
1847         }
1848     }
1849     return 0;
1850 }
1851
1852
1853 /****************
1854  * This function simply looks for the key in the trustdb
1855  * and makes sure that pk->local_id is set to the coreect value.
1856  * Return: 0 = found
1857  *         -1 = not found
1858  *        other = error
1859  */
1860 int
1861 query_trust_record( PKT_public_key *pk )
1862 {
1863     TRUSTREC rec;
1864     int rc=0;
1865
1866     if( pk->local_id ) {
1867         if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1868             log_error("query_trust_record: read record failed\n");
1869             return G10ERR_TRUSTDB;
1870         }
1871     }
1872     else { /* no local_id: scan the trustdb */
1873         if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
1874             log_error("query_trust_record: search_record failed: %s\n",
1875                                                             g10_errstr(rc));
1876             return rc;
1877         }
1878     }
1879     return rc;
1880 }
1881
1882
1883
1884 /****************
1885  * helper function for insert_trust_record()
1886  */
1887 static void
1888 rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec )
1889 {
1890     TRUSTREC *r, *r2;
1891
1892     if( err )
1893         log_error("key %08lX, uid %02X%02X: invalid user id - removed\n",
1894             (ulong)keyid[1], rec->r.uid.namehash[18], rec->r.uid.namehash[19] );
1895     for(r=rec->help_pref; r; r = r2 ) {
1896         r2 = r->next;
1897         m_free(r);
1898     }
1899
1900     m_free(rec);
1901 }
1902
1903
1904 /****************
1905  * Insert a trust record into the TrustDB
1906  * This function fails if this record already exists.
1907  *
1908  * We build everything we can do at this point. We cannot build
1909  * the sig records, because their LIDs are needed and we may not have them.
1910  */
1911 int
1912 insert_trust_record( PKT_public_key *orig_pk )
1913 {
1914     TRUSTREC dirrec, *rec, *rec2;
1915     TRUSTREC *keylist_head, **keylist_tail, *keylist;
1916     TRUSTREC *uidlist_head, **uidlist_tail, *uidlist;
1917     KBNODE keyblock = NULL;
1918     KBNODE node;
1919     u32 keyid[2]; /* of primary key */
1920     byte *fingerprint;
1921     size_t fingerlen;
1922     int rc = 0;
1923
1924     keylist_head = NULL; keylist_tail = &keylist_head; keylist = NULL;
1925     uidlist_head = NULL; uidlist_tail = &uidlist_head; uidlist = NULL;
1926
1927     /* prepare dir record */
1928     memset( &dirrec, 0, sizeof dirrec );
1929     dirrec.rectype = RECTYPE_DIR;
1930
1931     if( orig_pk->local_id )
1932         log_bug("pk->local_id=%lu\n", (ulong)orig_pk->local_id );
1933
1934     fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
1935
1936     /* fixme: assert that we do not have this record.
1937      * we can do this by searching for the primary keyid
1938      */
1939
1940     /* get the keyblock which has the key */
1941     rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
1942     if( rc ) { /* that should never happen */
1943         log_error( "insert_trust_record: keyblock not found: %s\n",
1944                                                           g10_errstr(rc) );
1945         goto leave;
1946     }
1947
1948     /* build data structure as linked lists in memory */
1949     keyid[0] = keyid[1] = 0;
1950     for( node=keyblock; node; node = node->next ) {
1951         if( node->pkt->pkttype == PKT_PUBLIC_KEY
1952             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1953             PKT_public_key *pk = node->pkt->pkt.public_key;
1954
1955             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1956                 if( keylist_head )
1957                     BUG();  /* more than one primary key */
1958                 keyid_from_pk( pk, keyid );
1959             }
1960             fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
1961             rec = m_alloc_clear( sizeof *rec );
1962             rec->rectype = RECTYPE_KEY;
1963             rec->r.key.pubkey_algo = pk->pubkey_algo;
1964             rec->r.key.fingerprint_len = fingerlen;
1965             memcpy(rec->r.key.fingerprint, fingerprint, fingerlen );
1966
1967             *keylist_tail = rec; keylist_tail = &rec->next;
1968         }
1969         else if( node->pkt->pkttype == PKT_USER_ID ) {
1970             PKT_user_id *uid = node->pkt->pkt.user_id;
1971
1972             rec = m_alloc_clear( sizeof *rec );
1973             rec->rectype = RECTYPE_UID;
1974             rmd160_hash_buffer( rec->r.uid.namehash, uid->name, uid->len );
1975
1976             uidlist = rec;
1977             *uidlist_tail = rec; uidlist_tail = &rec->next;
1978         }
1979         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
1980             PKT_signature *sig = node->pkt->pkt.signature;
1981
1982             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
1983                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
1984                 /* must verify this selfsignature here, so that we can
1985                  * build the preference record and validate the uid record
1986                  */
1987                 if( !uidlist ) {
1988                     log_error("key %08lX: self-signature without user id\n",
1989                               (ulong)keyid[1] );
1990                 }
1991                 else if( (rc = check_key_signature( keyblock, node, NULL ))) {
1992                     log_error("key %08lX, uid %02X%02X: "
1993                               "invalid self-signature: %s\n",
1994                               (ulong)keyid[1], uidlist->r.uid.namehash[18],
1995                               uidlist->r.uid.namehash[19], g10_errstr(rc) );
1996                     rc = 0;
1997                 }
1998                 else { /* build the prefrecord */
1999                     static struct {
2000                         sigsubpkttype_t subpkttype;
2001                         int preftype;
2002                     } prefs[] = {
2003                         { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
2004                         { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
2005                         { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
2006                         { 0, 0 }
2007                     };
2008                     const byte *s;
2009                     size_t n;
2010                     int k, i;
2011                     assert(uidlist);
2012                     assert(!uidlist->help_pref);
2013                     uidlist->mark |= 1; /* mark valid */
2014
2015                     i = 0;
2016                     for(k=0; prefs[k].subpkttype; k++ ) {
2017                         s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
2018                         if( s ) {
2019                             while( n ) {
2020                                 if( !i || i >= ITEMS_PER_PREF_RECORD ) {
2021                                     rec = m_alloc_clear( sizeof *rec );
2022                                     rec->rectype = RECTYPE_PREF;
2023                                     rec->next = uidlist->help_pref;
2024                                     uidlist->help_pref = rec;
2025                                     i = 0;
2026                                 }
2027                                 rec->r.pref.data[i++] = prefs[k].preftype;
2028                                 rec->r.pref.data[i++] = *s++;
2029                                 n--;
2030                             }
2031                         }
2032                     }
2033                 }
2034             }
2035             else if( 0 /* is revocation sig etc */ ) {
2036                 /* handle it here */
2037             }
2038             else { /* not a selfsignature */
2039             }
2040         }
2041     }
2042
2043     /* delete all invalid marked userids and their preferences and sigs */
2044     /* (ugly code - I know) */
2045     while( (rec=uidlist_head) && !(rec->mark & 1) ) {
2046         uidlist_head = rec->next;
2047         rel_mem_uidnode(keyid, 1, rec);
2048     }
2049     for( ; rec; rec = rec->next ) {
2050         if( rec->next && !(rec->next->mark & 1) ) {
2051             TRUSTREC *r = rec->next;
2052             rec->next = r->next;
2053             rel_mem_uidnode(keyid, 1, r);
2054         }
2055     }
2056
2057     /* check that we have at least one userid */
2058     if( !uidlist_head ) {
2059         log_error("key %08lX: no user ids - rejected\n", (ulong)keyid[1] );
2060         rc = G10ERR_BAD_CERT;
2061         goto leave;
2062     }
2063
2064     /* insert the record numbers to build the real (on disk) list */
2065     /* fixme: should start a transaction here */
2066     dirrec.recnum = tdbio_new_recnum();
2067     dirrec.r.dir.lid = dirrec.recnum;
2068     /* (list of keys) */
2069     for(rec=keylist_head; rec; rec = rec->next ) {
2070         rec->r.key.lid = dirrec.recnum;
2071         rec->recnum = tdbio_new_recnum();
2072     }
2073     for(rec=keylist_head; rec; rec = rec->next )
2074         rec->r.key.next = rec->next? rec->next->recnum : 0;
2075     dirrec.r.dir.keylist = keylist_head->recnum;
2076     /* (list of user ids) */
2077     for(rec=uidlist_head; rec; rec = rec->next ) {
2078         rec->r.uid.lid = dirrec.recnum;
2079         rec->recnum = tdbio_new_recnum();
2080         /* (preference records) */
2081         if( rec->help_pref ) {
2082             for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
2083                 rec2->r.pref.lid = dirrec.recnum;
2084                 rec2->recnum = tdbio_new_recnum();
2085             }
2086             for( rec2 = rec->help_pref; rec2->next; rec2 = rec2->next )
2087                 rec2->next->r.pref.next = rec2->recnum;
2088             rec->r.uid.prefrec = rec2->recnum;
2089         }
2090     }
2091     for(rec=uidlist_head; rec; rec = rec->next )
2092         rec->r.uid.next = rec->next? rec->next->recnum : 0;
2093     dirrec.r.dir.uidlist = uidlist_head->recnum;
2094
2095     /* write all records */
2096     for(rec=keylist_head; rec; rec = rec->next ) {
2097         assert( rec->rectype == RECTYPE_KEY );
2098         if( tdbio_write_record( rec ) ) {
2099             log_error("writing key record failed\n");
2100             rc = G10ERR_TRUSTDB;
2101             goto leave;
2102         }
2103     }
2104     for(rec=uidlist_head; rec; rec = rec->next ) {
2105         assert( rec->rectype == RECTYPE_UID );
2106         if( tdbio_write_record( rec ) ) {
2107             log_error("writing uid record failed\n");
2108             rc = G10ERR_TRUSTDB;
2109             goto leave;
2110         }
2111         for( rec2=rec->help_pref; rec2; rec2 = rec2->next ) {
2112             assert( rec2->rectype == RECTYPE_PREF );
2113             if( tdbio_write_record( rec2 ) ) {
2114                 log_error("writing pref record failed\n");
2115                 rc = G10ERR_TRUSTDB;
2116                 goto leave;
2117             }
2118         }
2119     }
2120     if( tdbio_write_record( &dirrec ) ) {
2121         log_error("writing dir record failed\n");
2122         return G10ERR_TRUSTDB;
2123     }
2124
2125     /* and store the LID */
2126     orig_pk->local_id = dirrec.r.dir.lid;
2127     for( node=keyblock; node; node = node->next ) {
2128         if( node->pkt->pkttype == PKT_PUBLIC_KEY
2129             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2130             PKT_public_key *pk = node->pkt->pkt.public_key;
2131             pk->local_id = dirrec.r.dir.lid;
2132         }
2133         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
2134             PKT_signature *sig = node->pkt->pkt.signature;
2135             sig->local_id = dirrec.r.dir.lid;
2136         }
2137     }
2138
2139
2140   leave:
2141     for(rec=uidlist_head; rec; rec = rec->next ) {
2142         rec2 = rec->next;
2143         rel_mem_uidnode(NULL, 0, rec );
2144     }
2145     for(rec=keylist_head; rec; rec = rec->next ) {
2146         rec2 = rec->next;
2147         m_free(rec);
2148     }
2149
2150     return rc;
2151 }
2152
2153
2154 int
2155 update_ownertrust( ulong lid, unsigned new_trust )
2156 {
2157     TRUSTREC rec;
2158
2159     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
2160         log_error("update_ownertrust: read dir failed\n");
2161         return G10ERR_TRUSTDB;
2162     }
2163     rec.r.dir.ownertrust = new_trust;
2164     if( tdbio_write_record( &rec ) ) {
2165         log_error("update_ownertrust: write failed\n");
2166         return G10ERR_TRUSTDB;
2167     }
2168     return 0;
2169 }
2170
2171