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