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