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