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