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