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