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