*** empty log message ***
[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                     log_info("key %08lX.%lu, uid %02X%02X: "
913                               "no public key for signature %08lX\n",
914                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
915                               urec.r.uid.namehash[19], (ulong)sig->keyid[1] );
916                     miskey = 1;
917                 }
918                 else if( rc )
919                     log_error("key %08lX.%lu, uid %02X%02X: "
920                               "invalid %ssignature: %s\n",
921                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
922                               urec.r.uid.namehash[19],
923                               i?"self-":"",g10_errstr(rc));
924                 else if( i ) /* mark that we have a valid selfsignature */
925                     urec.mark |= 1;
926                 else if( (rc = set_signature_packets_lid( sig )) )
927                     log_error("key %08lX.%lu, uid %02X%02X: "
928                               "can't get LID of signer: %s\n",
929                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
930                               urec.r.uid.namehash[19], g10_errstr(rc));
931                 else if( !test_dupsig( urec.next, sig->local_id ) ) {
932                     /* put the valid signature into a list */
933                     rec = urec.next;
934                     if( !rec || sigidx == SIGS_PER_RECORD ) {
935                         rec = m_alloc_clear( sizeof *rec );
936                         rec->rectype = RECTYPE_SIG;
937                         rec->next = urec.next;
938                         urec.next = rec;
939                         sigidx = 0;
940                     }
941                     rec->r.sig.sig[sigidx].lid = sig->local_id;
942                     rec->r.sig.sig[sigidx].flag = 0;
943                     sigidx++;
944                     if( DBG_TRUST )
945                         log_debug("key %08lX.%lu, uid %02X%02X: "
946                               "signed by LID %lu\n",
947                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
948                               urec.r.uid.namehash[19], sig->local_id);
949                 }
950                 else if( DBG_TRUST )
951                     log_debug("key %08lX.%lu, uid %02X%02X: "
952                               "duplicate signature by LID %lu\n",
953                               (ulong)keyid[1], lid, urec.r.uid.namehash[18],
954                               urec.r.uid.namehash[19], sig->local_id );
955                 rc = 0;
956             }
957             else {
958                 /* fixme: handle other sig classes here */
959                 /* FIXME: Revocations!!! */
960             }
961         }
962     }
963     if( have_urec && !(urec.mark & 1) ) {
964         if( (rc = no_selfsig_del(lid, keyid, &urec )) )
965             goto leave;
966         have_urec = 0;
967     }
968     if( have_urec ) {
969         rc = write_sigs_from_urec( lid, keyid, &urec );
970         if( rc )
971             goto leave;
972         rel_uidsigs( &urec );
973     }
974     dir->r.dir.dirflags |= DIRF_CHECKED;
975     if( miskey )
976         dir->r.dir.dirflags |= DIRF_MISKEY;
977     else
978         dir->r.dir.dirflags &= ~DIRF_MISKEY;
979     rc = tdbio_write_record( dir );
980     if( rc ) {
981         log_error("update_sigs: write dir record failed: %s\n", g10_errstr(rc));
982         return rc;
983     }
984
985   leave:
986     /* fixme: need more cleanup in case of an error */
987     release_kbnode( keyblock );
988     if( DBG_TRUST )
989         log_debug("update_sigs for %lu: %s\n", lid, g10_errstr(rc) );
990     return rc;
991 }
992
993
994 static int
995 update_sigs_by_lid( ulong lid )
996 {
997     int rc;
998     TRUSTREC rec;
999
1000     rc = tdbio_read_record( lid, &rec, RECTYPE_DIR );
1001     if( rc ) {
1002         log_error("LID %lu: error reading dir record: %s\n",
1003                                 lid, g10_errstr(rc));
1004         return rc;
1005     }
1006     if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
1007         rc = update_sigs( &rec );
1008     return rc;
1009 }
1010
1011 /****************
1012  * Make a list of trust paths
1013  */
1014 static int
1015 make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist )
1016 {
1017     int i, rc;
1018     LOCAL_ID_INFO *lids = new_lid_table();
1019     TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1020     TRUST_SEG_LIST tsl, tslist;
1021     int max_depth = 4;
1022
1023     tslist = *ret_tslist = NULL;
1024
1025     if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) {
1026         tslist = m_alloc( sizeof *tslist );
1027         tslist->nseg = 1;
1028         tslist->dup = 0;
1029         tslist->seg[0].lid = lid;
1030         tslist->seg[0].trust = 0;
1031         tslist->next = NULL;
1032         rc = 0;
1033     }
1034     else {
1035         stack[0].lid = lid;
1036         stack[0].trust = 0;
1037         rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1038     }
1039     if( !rc ) { /* wipe out duplicates */
1040         LOCAL_ID_INFO *work = new_lid_table();
1041         for( tsl=tslist; tsl; tsl = tsl->next ) {
1042             for(i=1; i < tsl->nseg-1; i++ ) {
1043                 if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1044                     tsl->dup = 1; /* mark as duplicate */
1045                     break;
1046                 }
1047             }
1048         }
1049         release_lid_table(work);
1050         *ret_tslist = tslist;
1051     }
1052     else
1053         ; /* FIXME: release tslist */
1054     release_lid_table(lids);
1055     return rc;
1056 }
1057
1058
1059 /****************
1060  * Given a trust segment list tslist, walk over all paths and fill in
1061  * the trust information for each segment.  What this function does is
1062  * to assign a trustvalue to the first segment (which is the requested key)
1063  * of each path.
1064  *
1065  * FIXME: We have to do more thinking here. e.g. we should never increase
1066  *        the trust value.
1067  *
1068  * Do not do it for duplicates.
1069  */
1070 static int
1071 propagate_trust( TRUST_SEG_LIST tslist )
1072 {
1073     int i, rc;
1074     unsigned trust, tr;
1075     TRUST_SEG_LIST tsl;
1076
1077     for(tsl = tslist; tsl; tsl = tsl->next ) {
1078         if( tsl->dup )
1079             continue;
1080         assert( tsl->nseg );
1081         /* the last segment is always an ultimately trusted one, so we can
1082          * assign a fully trust to the next one */
1083         i = tsl->nseg-1;
1084         tsl->seg[i].trust = TRUST_ULTIMATE;
1085         trust = TRUST_FULLY;
1086         for(i-- ; i >= 0; i-- ) {
1087             tsl->seg[i].trust = trust;
1088             if( i > 0 ) {
1089                 /* get the trust of this pubkey */
1090                 rc = get_ownertrust( tsl->seg[i].lid, &tr );
1091                 if( rc )
1092                     return rc;
1093                 if( tr < trust )
1094                     trust = tr;
1095             }
1096         }
1097     }
1098     return 0;
1099 }
1100
1101
1102 /****************
1103  * we have the pubkey record and all needed informations are in the trustdb
1104  * but nothing more is known.
1105  * (this function may re-read the dir record dr)
1106  */
1107 static int
1108 do_check( TRUSTREC *dr, unsigned *trustlevel )
1109 {
1110     int i, rc=0;
1111     TRUST_SEG_LIST tsl, tsl2, tslist;
1112     int marginal, fully;
1113     int fully_needed = opt.completes_needed;
1114     int marginal_needed = opt.marginals_needed;
1115     unsigned tflags = 0;
1116
1117     assert( fully_needed > 0 && marginal_needed > 1 );
1118
1119
1120     *trustlevel = TRUST_UNDEFINED;
1121
1122     if( !dr->r.dir.keylist ) {
1123         log_error("Ooops, no keys\n");
1124         return G10ERR_TRUSTDB;
1125     }
1126     if( !dr->r.dir.uidlist ) {
1127         log_error("Ooops, no user ids\n");
1128         return G10ERR_TRUSTDB;
1129     }
1130
1131     /* did we already check the signatures */
1132     if( !(dr->r.dir.dirflags & DIRF_CHECKED) ) /* no - do it now */
1133         rc = update_sigs( dr );
1134
1135     if( dr->r.dir.dirflags & DIRF_REVOKED )
1136         tflags |= TRUST_FLAG_REVOKED;
1137
1138   #if 0
1139     if( !rc && !dr->r.dir.siglist ) {
1140         /* We do not have any signatures; check whether it is one of our
1141          * secret keys */
1142         if( !qry_lid_table_flag( ultikey_table, dr->r.dir.lid, NULL ) )
1143             *trustlevel = tflags | TRUST_ULTIMATE;
1144         return 0;
1145     }
1146   #endif
1147     if( rc )
1148         return rc;  /* error while looking for sigrec or building sigrecs */
1149
1150     /* fixme: take it from the cache if it is valid */
1151
1152     /* Make a list of all possible trust-paths */
1153     rc = make_tsl( dr->r.dir.lid, &tslist );
1154     if( rc )
1155         return rc;
1156     rc = propagate_trust( tslist );
1157     if( rc )
1158         return rc;
1159     for(tsl = tslist; tsl; tsl = tsl->next ) {
1160         if( tsl->dup )
1161             continue;
1162
1163         if( opt.verbose ) {
1164             log_info("trust path:" );
1165             for(i=0; i < tsl->nseg; i++ ) {
1166                 putc(' ',stderr);
1167                 print_keyid( stderr, tsl->seg[i].lid );
1168                 putc(':',stderr);
1169                 print_trust( stderr, tsl->seg[i].trust );
1170             }
1171             putc('\n',stderr);
1172         }
1173     }
1174
1175     /* and see whether there is a trusted path.
1176      * We only have to look at the first segment, because
1177      * propagate_trust has investigated all other segments */
1178     marginal = fully = 0;
1179     for(tsl = tslist; tsl; tsl = tsl->next ) {
1180         if( tsl->dup )
1181             continue;
1182         if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
1183             *trustlevel = tflags | TRUST_ULTIMATE; /* our own key */
1184             break;
1185         }
1186         if( tsl->seg[0].trust == TRUST_FULLY ) {
1187             marginal++;
1188             fully++;
1189         }
1190         else if( tsl->seg[0].trust == TRUST_MARGINAL )
1191             marginal++;
1192
1193         if( fully >= fully_needed ) {
1194             *trustlevel = tflags | TRUST_FULLY;
1195             break;
1196         }
1197     }
1198     if( !tsl && marginal >= marginal_needed )
1199         *trustlevel = tflags | TRUST_MARGINAL;
1200
1201     /* cache the tslist */
1202     if( last_trust_web_key ) {
1203         for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
1204             tsl2 = tsl->next;
1205             m_free(tsl);
1206         }
1207     }
1208     last_trust_web_key = dr->r.dir.lid;
1209     last_trust_web_tslist = tslist;
1210     return 0;
1211 }
1212
1213 \f
1214 /***********************************************
1215  ****************  API  ************************
1216  ***********************************************/
1217
1218 /****************
1219  * Perform some checks over the trustdb
1220  *  level 0: only open the db
1221  *        1: used for initial program startup
1222  */
1223 int
1224 init_trustdb( int level, const char *dbname )
1225 {
1226     int rc=0;
1227
1228     if( !ultikey_table )
1229         ultikey_table = new_lid_table();
1230
1231     if( !level || level==1 ) {
1232         rc = tdbio_set_dbname( dbname, !!level );
1233         if( rc )
1234             return rc;
1235         if( !level )
1236             return 0;
1237
1238         /* verify that our own keys are in the trustDB
1239          * or move them to the trustdb. */
1240         rc = verify_own_keys();
1241
1242         /* should we check whether there is no other ultimately trusted
1243          * key in the database? */
1244
1245     }
1246     else
1247         BUG();
1248
1249     return rc;
1250 }
1251
1252
1253 void
1254 list_trustdb( const char *username )
1255 {
1256     TRUSTREC rec;
1257
1258     if( username && *username == '#' ) {
1259         int rc;
1260         ulong lid = atoi(username+1);
1261
1262         if( (rc = list_records( lid)) )
1263             log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
1264         else if( (rc = list_sigs( lid )) )
1265             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1266     }
1267     else if( username ) {
1268         PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1269         int rc;
1270
1271         if( (rc = get_pubkey_byname( pk, username )) )
1272             log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1273         else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1274             log_error("problem finding '%s' in trustdb: %s\n",
1275                                                 username, g10_errstr(rc));
1276         else if( rc == -1 )
1277             log_error("user '%s' not in trustdb\n", username);
1278         else if( (rc = list_records( pk->local_id)) )
1279             log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
1280         else if( (rc = list_sigs( pk->local_id )) )
1281             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1282         free_public_key( pk );
1283     }
1284     else {
1285         ulong recnum;
1286         int i;
1287
1288         printf("TrustDB: %s\n", tdbio_get_dbname() );
1289         for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- )
1290             putchar('-');
1291         putchar('\n');
1292         for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
1293             tdbio_dump_record( &rec, stdout );
1294     }
1295 }
1296
1297 /****************
1298  * Print a list of all defined owner trust value.
1299  */
1300 void
1301 export_ownertrust()
1302 {
1303     TRUSTREC rec;
1304     TRUSTREC rec2;
1305     ulong recnum;
1306     int i;
1307     byte *p;
1308     int rc;
1309
1310     for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
1311         if( rec.rectype == RECTYPE_DIR ) {
1312             if( !rec.r.dir.keylist ) {
1313                 log_error("Oops; directory record w/o primary key\n");
1314                 continue;
1315             }
1316             if( !rec.r.dir.ownertrust )
1317                 continue;
1318             rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
1319             if( rc ) {
1320                 log_error("error reading key record: %s\n", g10_errstr(rc));
1321                 continue;
1322             }
1323             p = rec2.r.key.fingerprint;
1324             for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
1325                 printf("%02X", *p );
1326             printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
1327         }
1328     }
1329 }
1330
1331
1332 void
1333 import_ownertrust( const char *fname )
1334 {
1335     FILE *fp;
1336     int is_stdin=0;
1337     char line[256];
1338     char *p;
1339     size_t n, fprlen;
1340     unsigned otrust;
1341
1342     if( !fname || (*fname == '-' && !fname[1]) ) {
1343         fp = stdin;
1344         fname = "[stdin]";
1345         is_stdin = 1;
1346     }
1347     else if( !(fp = fopen( fname, "r" )) ) {
1348         log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
1349         return;
1350     }
1351
1352     while( fgets( line, DIM(line)-1, fp ) ) {
1353         TRUSTREC rec;
1354         int rc;
1355
1356         if( !*line || *line == '#' )
1357             continue;
1358         n = strlen(line);
1359         if( line[n-1] != '\n' ) {
1360             log_error_f(fname, "line to long\n" );
1361             break; /* can't continue */
1362         }
1363         for(p = line; *p && *p != ':' ; p++ )
1364             if( !isxdigit(*p) )
1365                 break;
1366         if( *p != ':' ) {
1367             log_error_f(fname, "error: missing colon\n" );
1368             continue;
1369         }
1370         fprlen = p - line;
1371         if( fprlen != 32 && fprlen != 40 ) {
1372             log_error_f(fname, "error: invalid fingerprint\n" );
1373             continue;
1374         }
1375         if( sscanf(p, ":%u:", &otrust ) != 1 ) {
1376             log_error_f(fname, "error: no otrust value\n" );
1377             continue;
1378         }
1379         if( !otrust )
1380             continue; /* no otrust defined - no need to update or insert */
1381         /* convert the ascii fingerprint to binary */
1382         for(p=line, fprlen=0; *p != ':'; p += 2 )
1383             line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
1384         line[fprlen] = 0;
1385
1386       repeat:
1387         rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
1388         if( !rc ) { /* found: update */
1389             if( rec.r.dir.ownertrust )
1390                 log_info("LID %lu: changing trust from %u to %u\n",
1391                           rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
1392             else
1393                 log_info("LID %lu: setting trust to %u\n",
1394                                    rec.r.dir.lid, otrust );
1395             rec.r.dir.ownertrust = otrust;
1396             rc = tdbio_write_record( &rec );
1397             if( rc )
1398                 log_error_f(fname, "error updating otrust: %s\n",
1399                                                     g10_errstr(rc));
1400         }
1401         else if( rc == -1 ) { /* not found; get the key from the ring */
1402             PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1403
1404             log_info_f(fname, "key not in trustdb, searching ring.\n");
1405             rc = get_pubkey_byfprint( pk, line, fprlen );
1406             if( rc )
1407                 log_info_f(fname, "key not in ring: %s\n", g10_errstr(rc));
1408             else {
1409                 rc = query_trust_record( pk );  /* only as assertion */
1410                 if( rc != -1 )
1411                     log_error_f(fname, "Oops: key is now in trustdb???\n");
1412                 else {
1413                     rc = insert_trust_record( pk );
1414                     if( !rc )
1415                         goto repeat; /* update the ownertrust */
1416                     log_error_f(fname, "insert trust record failed: %s\n",
1417                                                            g10_errstr(rc) );
1418                 }
1419             }
1420         }
1421         else /* error */
1422             log_error_f(fname, "error finding dir record: %s\n",
1423                                                     g10_errstr(rc));
1424     }
1425     if( ferror(fp) )
1426         log_error_f(fname, _("read error: %s\n"), strerror(errno) );
1427     if( !is_stdin )
1428         fclose(fp);
1429 }
1430
1431
1432 void
1433 list_trust_path( int max_depth, const char *username )
1434 {
1435     int rc;
1436     int wipe=0;
1437     int i;
1438     TRUSTREC rec;
1439     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1440
1441     if( max_depth < 0 ) {
1442         wipe = 1;
1443         max_depth = -max_depth;
1444     }
1445
1446     if( (rc = get_pubkey_byname( pk, username )) )
1447         log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1448     else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1449         log_error("problem finding '%s' in trustdb: %s\n",
1450                                             username, g10_errstr(rc));
1451     else if( rc == -1 ) {
1452         log_info("user '%s' not in trustdb - inserting\n", username);
1453         rc = insert_trust_record( pk );
1454         if( rc )
1455             log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
1456         else {
1457             assert( pk->local_id );
1458         }
1459     }
1460
1461     if( !rc ) {
1462         TRUST_SEG_LIST tsl, tslist = NULL;
1463
1464         if( !qry_lid_table_flag( ultikey_table, pk->local_id, NULL ) ) {
1465             tslist = m_alloc( sizeof *tslist );
1466             tslist->nseg = 1;
1467             tslist->dup = 0;
1468             tslist->seg[0].lid = pk->local_id;
1469             tslist->seg[0].trust = 0;
1470             tslist->next = NULL;
1471             rc = 0;
1472         }
1473         else {
1474             LOCAL_ID_INFO *lids = new_lid_table();
1475             TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1476
1477             stack[0].lid = pk->local_id;
1478             stack[0].trust = 0;
1479             rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1480             if( wipe ) { /* wipe out duplicates */
1481                 LOCAL_ID_INFO *work;
1482
1483                 work = new_lid_table();
1484                 for( tsl=tslist; tsl; tsl = tsl->next ) {
1485                     for(i=1; i < tsl->nseg-1; i++ ) {
1486                         if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1487                             tsl->dup = 1; /* mark as duplicate */
1488                             break;
1489                         }
1490                     }
1491                 }
1492                 release_lid_table(work);
1493             }
1494             release_lid_table(lids);
1495         }
1496         if( rc )
1497             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1498         rc = propagate_trust( tslist );
1499         if( rc )
1500             log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
1501         for(tsl = tslist; tsl; tsl = tsl->next ) {
1502             int i;
1503
1504             if( tsl->dup )
1505                 continue;
1506             printf("trust path:" );
1507             for(i=0; i < tsl->nseg; i++ ) {
1508                 putc(' ',stdout);
1509                 print_keyid( stdout, tsl->seg[i].lid );
1510                 putc(':',stdout);
1511                 print_trust( stdout, tsl->seg[i].trust );
1512             }
1513             putchar('\n');
1514         }
1515     }
1516
1517     free_public_key( pk );
1518 }
1519
1520
1521 /****************
1522  * Check the complete trustdb or only the entries for the given username
1523  */
1524 void
1525 check_trustdb( const char *username )
1526 {
1527     TRUSTREC rec;
1528     int rc;
1529
1530     if( username && *username == '#' ) {
1531         int rc;
1532         ulong lid = atoi(username+1);
1533
1534         if( (rc = update_sigs_by_lid( lid )) )
1535             log_error("lid %lu: check failed: %s\n",
1536                                         lid, g10_errstr(rc));
1537         else
1538             log_info("lid %lu: checked: %s\n", lid, g10_errstr(rc));
1539     }
1540     else if( username ) {
1541         PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1542
1543         if( (rc = get_pubkey_byname( pk, username )) )
1544             log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1545         else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1546             log_error("problem finding '%s' in trustdb: %s\n",
1547                                                 username, g10_errstr(rc));
1548         else if( rc == -1 )
1549             log_error("user '%s' not in trustdb\n", username);
1550         else if( (rc = update_sigs( &rec )) )
1551             log_error("lid %lu: check failed: %s\n",
1552                                         rec.recnum, g10_errstr(rc));
1553         else
1554             log_info("lid %lu: checked: %s\n", rec.recnum, g10_errstr(rc));
1555         free_public_key( pk );
1556     }
1557     else {
1558         ulong recnum;
1559
1560         for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
1561             if( rec.rectype == RECTYPE_DIR ) {
1562                 rc = update_sigs( &rec );
1563                 if( rc )
1564                     log_error("lid %lu: check failed: %s\n",
1565                                                  recnum, g10_errstr(rc) );
1566                 else
1567                     log_info("lid %lu: checked\n", recnum );
1568             }
1569         }
1570     }
1571 }
1572
1573
1574 \f
1575 /****************
1576  * Get the trustlevel for this PK.
1577  * Note: This does not ask any questions
1578  * Returns: 0 okay of an errorcode
1579  *
1580  * It operates this way:
1581  *  locate the pk in the trustdb
1582  *      found:
1583  *          Do we have a valid cache record for it?
1584  *              yes: return trustlevel from cache
1585  *              no:  make a cache record and all the other stuff
1586  *      not found:
1587  *          try to insert the pubkey into the trustdb and check again
1588  *
1589  * Problems: How do we get the complete keyblock to check that the
1590  *           cache record is actually valid?  Think we need a clever
1591  *           cache in getkey.c  to keep track of this stuff. Maybe it
1592  *           is not necessary to check this if we use a local pubring. Hmmmm.
1593  */
1594 int
1595 check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
1596 {
1597     TRUSTREC rec;
1598     unsigned trustlevel = TRUST_UNKNOWN;
1599     int rc=0;
1600     u32 cur_time;
1601     u32 keyid[2];
1602
1603
1604     keyid_from_pk( pk, keyid );
1605
1606     /* get the pubkey record */
1607     if( pk->local_id ) {
1608         if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1609             log_error("check_trust: read dir record failed\n");
1610             return G10ERR_TRUSTDB;
1611         }
1612     }
1613     else { /* no local_id: scan the trustdb */
1614         if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
1615             log_error("check_trust: search dir record failed: %s\n",
1616                                                             g10_errstr(rc));
1617             return rc;
1618         }
1619         else if( rc == -1 ) { /* not found - insert */
1620             rc = insert_trust_record( pk );
1621             if( rc ) {
1622                 log_error(_("key %08lX: insert trust record failed: %s\n"),
1623                                           (ulong)keyid[1], g10_errstr(rc));
1624                 goto leave;
1625             }
1626             log_info(_("key %08lX.%lu: inserted into trustdb\n"),
1627                                           (ulong)keyid[1], pk->local_id );
1628             /* and re-read the dir record */
1629             if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1630                 log_error("check_trust: reread dir record failed\n");
1631                 return G10ERR_TRUSTDB;
1632             }
1633         }
1634     }
1635     cur_time = make_timestamp();
1636     if( pk->timestamp > cur_time ) {
1637         log_info(_("key %08lX.%lu: created in future "
1638                    "(time warp or clock problem)\n"),
1639                                           (ulong)keyid[1], pk->local_id );
1640         return G10ERR_TIME_CONFLICT;
1641     }
1642
1643     if( pk->valid_days && add_days_to_timestamp(pk->timestamp,
1644                                                 pk->valid_days) < cur_time ) {
1645         log_info(_("key %08lX.%lu: expired at %s\n"),
1646                         (ulong)keyid[1], pk->local_id,
1647                     asctimestamp( add_days_to_timestamp(pk->timestamp,
1648                                                         pk->valid_days)));
1649          trustlevel = TRUST_EXPIRED;
1650     }
1651     else {
1652         rc = do_check( &rec, &trustlevel );
1653         if( rc ) {
1654             log_error(_("key %08lX.%lu: trust check failed: %s\n"),
1655                             (ulong)keyid[1], pk->local_id, g10_errstr(rc));
1656             return rc;
1657         }
1658     }
1659
1660
1661   leave:
1662     if( DBG_TRUST )
1663         log_debug("check_trust() returns trustlevel %04x.\n", trustlevel);
1664     *r_trustlevel = trustlevel;
1665     return 0;
1666 }
1667
1668
1669 int
1670 query_trust_info( PKT_public_key *pk )
1671 {
1672     unsigned trustlevel;
1673     int c;
1674
1675     if( check_trust( pk, &trustlevel ) )
1676         return '?';
1677     if( trustlevel & TRUST_FLAG_REVOKED )
1678         return 'r';
1679     switch( (trustlevel & TRUST_MASK) ) {
1680       case TRUST_UNKNOWN:   c = 'o'; break;
1681       case TRUST_EXPIRED:   c = 'e'; break;
1682       case TRUST_UNDEFINED: c = 'q'; break;
1683       case TRUST_NEVER:     c = 'n'; break;
1684       case TRUST_MARGINAL:  c = 'm'; break;
1685       case TRUST_FULLY:     c = 'f'; break;
1686       case TRUST_ULTIMATE:  c = 'u'; break;
1687       default: BUG();
1688     }
1689     return c;
1690 }
1691
1692
1693
1694 /****************
1695  * Enumerate all keys, which are needed to build all trust paths for
1696  * the given key.  This function does not return the key itself or
1697  * the ultimate key.
1698  *
1699  *  1) create a void pointer and initialize it to NULL
1700  *  2) pass this void pointer by reference to this function.
1701  *     Set lid to the key you want to enumerate and pass it by reference.
1702  *  3) call this function as long as it does not return -1
1703  *     to indicate EOF. LID does contain the next key used to build the web
1704  *  4) Always call this function a last time with LID set to NULL,
1705  *     so that it can free its context.
1706  */
1707 int
1708 enum_trust_web( void **context, ulong *lid )
1709 {
1710     ENUM_TRUST_WEB_CONTEXT *c = *context;
1711
1712     if( !c ) { /* make a new context */
1713         c = m_alloc_clear( sizeof *c );
1714         *context = c;
1715         if( *lid == last_trust_web_key && last_trust_web_tslist )
1716             c->tsl = last_trust_web_tslist;
1717         else {
1718             TRUST_SEG_LIST tsl, tsl2, tslist;
1719             int rc;
1720
1721             rc = make_tsl( *lid, &tslist );
1722             if( rc ) {
1723                 log_error("failed to build the TSL\n");
1724                 return rc;
1725             }
1726             /* cache the tslist, so that we do not need to free it */
1727             if( last_trust_web_key ) {
1728                 for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
1729                     tsl2 = tsl->next;
1730                     m_free(tsl);
1731                 }
1732             }
1733             last_trust_web_key = *lid;
1734             last_trust_web_tslist = tslist;
1735             c->tsl = last_trust_web_tslist;
1736         }
1737         c->index = 1;
1738     }
1739
1740     if( !lid ) { /* free the context */
1741         m_free( c );
1742         *context = NULL;
1743         return 0;
1744     }
1745
1746     while( c->tsl ) {
1747         if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) {
1748             *lid = c->tsl->seg[c->index].lid;
1749             c->index++;
1750             return 0;
1751         }
1752         c->index = 1;
1753         c->tsl = c->tsl->next;
1754     }
1755     return -1; /* eof */
1756 }
1757
1758
1759 /****************
1760  * Return the assigned ownertrust value for the given LID
1761  */
1762 int
1763 get_ownertrust( ulong lid, unsigned *r_otrust )
1764 {
1765     TRUSTREC rec;
1766
1767     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1768         log_error("get_ownertrust: read dir record failed\n");
1769         return G10ERR_TRUSTDB;
1770     }
1771     if( r_otrust )
1772         *r_otrust = rec.r.dir.ownertrust;
1773     return 0;
1774 }
1775
1776 int
1777 get_ownertrust_info( ulong lid )
1778 {
1779     unsigned otrust;
1780     int c;
1781
1782     if( get_ownertrust( lid, &otrust ) )
1783         return '?';
1784     switch( (otrust & TRUST_MASK) ) {
1785       case TRUST_NEVER:     c = 'n'; break;
1786       case TRUST_MARGINAL:  c = 'm'; break;
1787       case TRUST_FULLY:     c = 'f'; break;
1788       case TRUST_ULTIMATE:  c = 'u'; break;
1789       default:              c = '-'; break;
1790     }
1791     return c;
1792 }
1793
1794
1795 byte *
1796 get_pref_data( ulong lid, const byte *namehash, size_t *ret_n )
1797 {
1798     TRUSTREC rec;
1799     ulong recno;
1800     int rc;
1801
1802     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1803         log_error("get_pref_data: read dir record failed\n");
1804         return NULL;
1805     }
1806
1807     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
1808         rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
1809         if( rc ) {
1810             log_error("get_pref_data: read uid record failed: %s\n",
1811                                                      g10_errstr(rc));
1812             return NULL;
1813         }
1814         if( rec.r.uid.prefrec
1815             && ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) ))  {
1816             byte *buf;
1817             /* found the correct one or the first one */
1818             rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
1819             if( rc ) {
1820                 log_error("get_pref_data: read pref record failed: %s\n",
1821                                                          g10_errstr(rc));
1822                 return NULL;
1823             }
1824             if( rec.r.pref.next )
1825                 log_info("warning: can't yet handle long pref records\n");
1826             buf = m_alloc( ITEMS_PER_PREF_RECORD );
1827             memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD );
1828             *ret_n = ITEMS_PER_PREF_RECORD;
1829             return buf;
1830         }
1831     }
1832     return NULL;
1833 }
1834
1835
1836
1837 /****************
1838  * Check whether the algorithm is in one of the pref records
1839  */
1840 int
1841 is_algo_in_prefs( ulong lid, int preftype, int algo )
1842 {
1843     TRUSTREC rec;
1844     ulong recno;
1845     int i, rc;
1846     byte *pref;
1847
1848     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
1849         log_error("is_algo_in_prefs: read dir record failed\n");
1850         return 0;
1851     }
1852
1853     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
1854         rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
1855         if( rc ) {
1856             log_error("is_algo_in_prefs: read uid record failed: %s\n",
1857                                                      g10_errstr(rc));
1858             return 0;
1859         }
1860         if( rec.r.uid.prefrec ) {
1861             rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
1862             if( rc ) {
1863                 log_error("is_algo_in_prefs: read pref record failed: %s\n",
1864                                                          g10_errstr(rc));
1865                 return 0;
1866             }
1867             if( rec.r.pref.next )
1868                 log_info("warning: can't yet handle long pref records\n");
1869             pref = rec.r.pref.data;
1870             for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) {
1871                 if( pref[i] == preftype && pref[i+1] == algo )
1872                     return 1;
1873             }
1874         }
1875     }
1876     return 0;
1877 }
1878
1879
1880 /****************
1881  * This function simply looks for the key in the trustdb
1882  * and makes sure that pk->local_id is set to the coreect value.
1883  * Return: 0 = found
1884  *         -1 = not found
1885  *        other = error
1886  */
1887 int
1888 query_trust_record( PKT_public_key *pk )
1889 {
1890     TRUSTREC rec;
1891     int rc=0;
1892
1893     if( pk->local_id ) {
1894         if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) {
1895             log_error("query_trust_record: read record failed\n");
1896             return G10ERR_TRUSTDB;
1897         }
1898     }
1899     else { /* no local_id: scan the trustdb */
1900         if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
1901             log_error("query_trust_record: search_record failed: %s\n",
1902                                                             g10_errstr(rc));
1903             return rc;
1904         }
1905     }
1906     return rc;
1907 }
1908
1909
1910 int
1911 clear_trust_checked_flag( PKT_public_key *pk )
1912 {
1913     TRUSTREC rec;
1914     int rc;
1915
1916     if( !pk->local_id ) {
1917         query_trust_record( pk );
1918         if( !pk->local_id )
1919             log_bug("clear_trust_checked_flag: Still no LID\n");
1920     }
1921
1922     if( (rc=tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ))) {
1923         log_error("clear_trust_checked_flag: read record failed: %s\n",
1924                                                               g10_errstr(rc));
1925         return rc;
1926     }
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  * helper function for insert_trust_record()
1945  */
1946 static void
1947 rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec )
1948 {
1949     TRUSTREC *r, *r2;
1950
1951     if( err )
1952         log_error("key %08lX, uid %02X%02X: invalid user id - removed\n",
1953             (ulong)keyid[1], rec->r.uid.namehash[18], rec->r.uid.namehash[19] );
1954     for(r=rec->help_pref; r; r = r2 ) {
1955         r2 = r->next;
1956         m_free(r);
1957     }
1958
1959     m_free(rec);
1960 }
1961
1962
1963 /****************
1964  * Insert a trust record into the TrustDB
1965  * This function fails if this record already exists.
1966  *
1967  * We build everything we can do at this point. We cannot build
1968  * the sig records, because their LIDs are needed and we may not have them.
1969  */
1970 int
1971 insert_trust_record( PKT_public_key *orig_pk )
1972 {
1973     TRUSTREC dirrec, *rec, *rec2;
1974     TRUSTREC *keylist_head, **keylist_tail, *keylist;
1975     TRUSTREC *uidlist_head, **uidlist_tail, *uidlist;
1976     KBNODE keyblock = NULL;
1977     KBNODE node;
1978     u32 keyid[2]; /* of primary key */
1979     byte *fingerprint;
1980     size_t fingerlen;
1981     int rc = 0;
1982
1983     keylist_head = NULL; keylist_tail = &keylist_head; keylist = NULL;
1984     uidlist_head = NULL; uidlist_tail = &uidlist_head; uidlist = NULL;
1985
1986     /* prepare dir record */
1987     memset( &dirrec, 0, sizeof dirrec );
1988     dirrec.rectype = RECTYPE_DIR;
1989
1990     if( orig_pk->local_id )
1991         log_bug("pk->local_id=%lu\n", (ulong)orig_pk->local_id );
1992
1993     fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
1994
1995     /* fixme: assert that we do not have this record.
1996      * we can do this by searching for the primary keyid
1997      */
1998
1999     /* get the keyblock which has the key */
2000     rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
2001     if( rc ) { /* that should never happen */
2002         log_error( "insert_trust_record: keyblock not found: %s\n",
2003                                                           g10_errstr(rc) );
2004         goto leave;
2005     }
2006
2007     /* build data structure as linked lists in memory */
2008     keyid[0] = keyid[1] = 0;
2009     for( node=keyblock; node; node = node->next ) {
2010         if( node->pkt->pkttype == PKT_PUBLIC_KEY
2011             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2012             PKT_public_key *pk = node->pkt->pkt.public_key;
2013
2014             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2015                 if( keylist_head )
2016                     BUG();  /* more than one primary key */
2017                 keyid_from_pk( pk, keyid );
2018             }
2019             fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
2020             rec = m_alloc_clear( sizeof *rec );
2021             rec->rectype = RECTYPE_KEY;
2022             rec->r.key.pubkey_algo = pk->pubkey_algo;
2023             rec->r.key.fingerprint_len = fingerlen;
2024             memcpy(rec->r.key.fingerprint, fingerprint, fingerlen );
2025
2026             *keylist_tail = rec; keylist_tail = &rec->next;
2027         }
2028         else if( node->pkt->pkttype == PKT_USER_ID ) {
2029             PKT_user_id *uid = node->pkt->pkt.user_id;
2030
2031             rec = m_alloc_clear( sizeof *rec );
2032             rec->rectype = RECTYPE_UID;
2033             rmd160_hash_buffer( rec->r.uid.namehash, uid->name, uid->len );
2034
2035             uidlist = rec;
2036             *uidlist_tail = rec; uidlist_tail = &rec->next;
2037         }
2038         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
2039             PKT_signature *sig = node->pkt->pkt.signature;
2040
2041             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2042                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
2043                 /* must verify this selfsignature here, so that we can
2044                  * build the preference record and validate the uid record
2045                  */
2046                 if( !uidlist ) {
2047                     log_error("key %08lX: self-signature without user id\n",
2048                               (ulong)keyid[1] );
2049                 }
2050                 else if( (rc = check_key_signature( keyblock, node, NULL ))) {
2051                     log_error("key %08lX, uid %02X%02X: "
2052                               "invalid self-signature: %s\n",
2053                               (ulong)keyid[1], uidlist->r.uid.namehash[18],
2054                               uidlist->r.uid.namehash[19], g10_errstr(rc) );
2055                     rc = 0;
2056                 }
2057                 else { /* build the prefrecord */
2058                     static struct {
2059                         sigsubpkttype_t subpkttype;
2060                         int preftype;
2061                     } prefs[] = {
2062                         { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
2063                         { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
2064                         { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
2065                         { 0, 0 }
2066                     };
2067                     const byte *s;
2068                     size_t n;
2069                     int k, i;
2070                     assert(uidlist);
2071                     assert(!uidlist->help_pref);
2072                     uidlist->mark |= 1; /* mark valid */
2073
2074                     i = 0;
2075                     for(k=0; prefs[k].subpkttype; k++ ) {
2076                         s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
2077                         if( s ) {
2078                             while( n ) {
2079                                 if( !i || i >= ITEMS_PER_PREF_RECORD ) {
2080                                     rec = m_alloc_clear( sizeof *rec );
2081                                     rec->rectype = RECTYPE_PREF;
2082                                     rec->next = uidlist->help_pref;
2083                                     uidlist->help_pref = rec;
2084                                     i = 0;
2085                                 }
2086                                 rec->r.pref.data[i++] = prefs[k].preftype;
2087                                 rec->r.pref.data[i++] = *s++;
2088                                 n--;
2089                             }
2090                         }
2091                     }
2092                 }
2093             }
2094             else if( 0 /* is revocation sig etc */ ) {
2095                 /* handle it here */
2096             }
2097             else { /* not a selfsignature */
2098             }
2099         }
2100     }
2101
2102     /* delete all invalid marked userids and their preferences and sigs */
2103     /* (ugly code - I know) */
2104     while( (rec=uidlist_head) && !(rec->mark & 1) ) {
2105         uidlist_head = rec->next;
2106         rel_mem_uidnode(keyid, 1, rec);
2107     }
2108     for( ; rec; rec = rec->next ) {
2109         if( rec->next && !(rec->next->mark & 1) ) {
2110             TRUSTREC *r = rec->next;
2111             rec->next = r->next;
2112             rel_mem_uidnode(keyid, 1, r);
2113         }
2114     }
2115
2116     /* check that we have at least one userid */
2117     if( !uidlist_head ) {
2118         log_error("key %08lX: no user ids - rejected\n", (ulong)keyid[1] );
2119         rc = G10ERR_BAD_CERT;
2120         goto leave;
2121     }
2122
2123     /* insert the record numbers to build the real (on disk) list */
2124     /* fixme: should start a transaction here */
2125     dirrec.recnum = tdbio_new_recnum();
2126     dirrec.r.dir.lid = dirrec.recnum;
2127     /* (list of keys) */
2128     for(rec=keylist_head; rec; rec = rec->next ) {
2129         rec->r.key.lid = dirrec.recnum;
2130         rec->recnum = tdbio_new_recnum();
2131     }
2132     for(rec=keylist_head; rec; rec = rec->next )
2133         rec->r.key.next = rec->next? rec->next->recnum : 0;
2134     dirrec.r.dir.keylist = keylist_head->recnum;
2135     /* (list of user ids) */
2136     for(rec=uidlist_head; rec; rec = rec->next ) {
2137         rec->r.uid.lid = dirrec.recnum;
2138         rec->recnum = tdbio_new_recnum();
2139         /* (preference records) */
2140         if( rec->help_pref ) {
2141             for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
2142                 rec2->r.pref.lid = dirrec.recnum;
2143                 rec2->recnum = tdbio_new_recnum();
2144             }
2145             for( rec2 = rec->help_pref; rec2->next; rec2 = rec2->next )
2146                 rec2->next->r.pref.next = rec2->recnum;
2147             rec->r.uid.prefrec = rec2->recnum;
2148         }
2149     }
2150     for(rec=uidlist_head; rec; rec = rec->next )
2151         rec->r.uid.next = rec->next? rec->next->recnum : 0;
2152     dirrec.r.dir.uidlist = uidlist_head->recnum;
2153
2154     /* write all records */
2155     for(rec=keylist_head; rec; rec = rec->next ) {
2156         assert( rec->rectype == RECTYPE_KEY );
2157         if( tdbio_write_record( rec ) ) {
2158             log_error("writing key record failed\n");
2159             rc = G10ERR_TRUSTDB;
2160             goto leave;
2161         }
2162     }
2163     for(rec=uidlist_head; rec; rec = rec->next ) {
2164         assert( rec->rectype == RECTYPE_UID );
2165         if( tdbio_write_record( rec ) ) {
2166             log_error("writing uid record failed\n");
2167             rc = G10ERR_TRUSTDB;
2168             goto leave;
2169         }
2170         for( rec2=rec->help_pref; rec2; rec2 = rec2->next ) {
2171             assert( rec2->rectype == RECTYPE_PREF );
2172             if( tdbio_write_record( rec2 ) ) {
2173                 log_error("writing pref record failed\n");
2174                 rc = G10ERR_TRUSTDB;
2175                 goto leave;
2176             }
2177         }
2178     }
2179     if( tdbio_write_record( &dirrec ) ) {
2180         log_error("writing dir record failed\n");
2181         return G10ERR_TRUSTDB;
2182     }
2183
2184     /* and store the LID */
2185     orig_pk->local_id = dirrec.r.dir.lid;
2186     for( node=keyblock; node; node = node->next ) {
2187         if( node->pkt->pkttype == PKT_PUBLIC_KEY
2188             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2189             PKT_public_key *pk = node->pkt->pkt.public_key;
2190             pk->local_id = dirrec.r.dir.lid;
2191         }
2192         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
2193             PKT_signature *sig = node->pkt->pkt.signature;
2194             sig->local_id = dirrec.r.dir.lid;
2195         }
2196     }
2197
2198
2199   leave:
2200     for(rec=uidlist_head; rec; rec = rec2 ) {
2201         rec2 = rec->next;
2202         rel_mem_uidnode(NULL, 0, rec );
2203     }
2204     for(rec=keylist_head; rec; rec = rec2 ) {
2205         rec2 = rec->next;
2206         m_free(rec);
2207     }
2208
2209     return rc;
2210 }
2211
2212
2213 int
2214 update_ownertrust( ulong lid, unsigned new_trust )
2215 {
2216     TRUSTREC rec;
2217
2218     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
2219         log_error("update_ownertrust: read dir failed\n");
2220         return G10ERR_TRUSTDB;
2221     }
2222     rec.r.dir.ownertrust = new_trust;
2223     if( tdbio_write_record( &rec ) ) {
2224         log_error("update_ownertrust: write failed\n");
2225         return G10ERR_TRUSTDB;
2226     }
2227     return 0;
2228 }
2229
2230