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