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