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