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