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