See ChangeLog: Thu Feb 25 18:47:39 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   #if 0
1510     TRUST_INFO *tmppath;
1511     TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
1512   #endif
1513     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
1514
1515     INIT_TRUSTDB();
1516     if( (rc = get_pubkey_byname(NULL, pk, username, NULL )) )
1517         log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
1518     else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
1519         log_error(_("problem finding '%s' in trustdb: %s\n"),
1520                                             username, g10_errstr(rc));
1521     else if( rc == -1 ) {
1522         log_info(_("user '%s' not in trustdb - inserting\n"), username);
1523         rc = insert_trust_record( pk );
1524         if( rc )
1525             log_error(_("failed to put '%s' into trustdb: %s\n"),
1526                                                     username, g10_errstr(rc));
1527         else {
1528             assert( pk->local_id );
1529         }
1530     }
1531     lid = pk->local_id;
1532     free_public_key( pk );
1533
1534   #if 0
1535     /* collect the paths */
1536     tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
1537     trust_seg_list = NULL;
1538     collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &trust_seg_list );
1539     m_free( tmppath );
1540     sort_tsl_list( &trust_seg_list );
1541     /* and now print them */
1542     for(tsl = trust_seg_list; tsl; tsl = tsl->next ) {
1543         print_path( tsl->pathlen, tsl->path, stdout, 0 );
1544         if( tsl->next )
1545             putchar('\n');
1546     }
1547
1548     /* release the list */
1549     for(tsl = trust_seg_list; tsl; tsl = tsl2 ) {
1550         tsl2 = tsl->next;
1551         m_free( tsl );
1552     }
1553     trust_seg_list = NULL;
1554   #else /* test code */
1555     {
1556         CERT_ITEM *stack;
1557         CERT_CHAIN chains, r;
1558         int i;
1559
1560         chains = NULL;
1561         stack = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *stack );
1562         find_cert_chain( lid, 0, opt.max_cert_depth, stack, &chains);
1563         m_free( stack );
1564         /* dump chains */
1565         for(r=chains; r ; r = r->next ) {
1566             printf("chain:" );
1567             for(i=0; i < r->nitems; i++ )
1568                 printf(" %4lu/%-4lu", r->items[i].lid, r->items[i].uid );
1569             putchar('\n');
1570         }
1571
1572     }
1573   #endif
1574 }
1575
1576
1577 /****************
1578  * Check the complete trustdb or only the entries for the given username.
1579  * We check the complete database. If a username is given or the special
1580  * username "*" is used, a complete recheck is done.  With no user ID
1581  * only the records which are not yet checkd are now checked.
1582  */
1583 void
1584 check_trustdb( const char *username )
1585 {
1586     TRUSTREC rec;
1587     KBNODE keyblock = NULL;
1588     KBPOS kbpos;
1589     int rc;
1590     int recheck = username && *username == '*' && !username[1];
1591
1592     INIT_TRUSTDB();
1593     if( username && !recheck ) {
1594         rc = find_keyblock_byname( &kbpos, username );
1595         if( !rc )
1596             rc = read_keyblock( &kbpos, &keyblock );
1597         if( rc ) {
1598             log_error(_("%s: keyblock read problem: %s\n"),
1599                                     username, g10_errstr(rc));
1600         }
1601         else {
1602             int modified;
1603
1604             rc = update_trust_record( keyblock, 1, &modified );
1605             if( rc == -1 ) { /* not yet in trustdb: insert */
1606                 rc = insert_trust_record(
1607                             find_kbnode( keyblock, PKT_PUBLIC_KEY
1608                                        ) ->pkt->pkt.public_key );
1609
1610             }
1611             if( rc )
1612                 log_error(_("%s: update failed: %s\n"),
1613                                            username, g10_errstr(rc) );
1614             else if( modified )
1615                 log_info(_("%s: updated\n"), username );
1616             else
1617                 log_info(_("%s: okay\n"), username );
1618
1619         }
1620         release_kbnode( keyblock ); keyblock = NULL;
1621     }
1622     else {
1623         ulong recnum;
1624         ulong count=0, upd_count=0, err_count=0, skip_count=0;
1625
1626         for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
1627             if( rec.rectype == RECTYPE_DIR ) {
1628                 TRUSTREC tmp;
1629                 int modified;
1630
1631                 if( !rec.r.dir.keylist ) {
1632                     log_info(_("lid %lu: dir record w/o key - skipped\n"),
1633                                                                   recnum);
1634                     count++;
1635                     skip_count++;
1636                     continue;
1637                 }
1638
1639                 read_record( rec.r.dir.keylist, &tmp, RECTYPE_KEY );
1640
1641                 rc = get_keyblock_byfprint( &keyblock,
1642                                             tmp.r.key.fingerprint,
1643                                             tmp.r.key.fingerprint_len );
1644                 if( rc ) {
1645                     log_error(_("lid %lu: keyblock not found: %s\n"),
1646                                                  recnum, g10_errstr(rc) );
1647                     count++;
1648                     skip_count++;
1649                     continue;
1650                 }
1651
1652                 rc = update_trust_record( keyblock, recheck, &modified );
1653                 if( rc ) {
1654                     log_error(_("lid %lu: update failed: %s\n"),
1655                                                  recnum, g10_errstr(rc) );
1656                     err_count++;
1657                 }
1658                 else if( modified ) {
1659                     if( opt.verbose )
1660                         log_info(_("lid %lu: updated\n"), recnum );
1661                     upd_count++;
1662                 }
1663                 else if( opt.verbose > 1 )
1664                     log_info(_("lid %lu: okay\n"), recnum );
1665
1666                 release_kbnode( keyblock ); keyblock = NULL;
1667                 if( !(++count % 100) )
1668                     log_info(_("%lu keys so far processed\n"), count);
1669             }
1670         }
1671         log_info(_("%lu keys processed\n"), count);
1672         if( skip_count )
1673             log_info(_("\t%lu keys skipped\n"), skip_count);
1674         if( err_count )
1675             log_info(_("\t%lu keys with errors\n"), err_count);
1676         if( upd_count )
1677             log_info(_("\t%lu keys updated\n"), upd_count);
1678     }
1679 }
1680
1681
1682 /****************
1683  * Put new entries  from the pubrings into the trustdb.
1684  * This function honors the sig flags to speed up the check.
1685  */
1686 void
1687 update_trustdb( )
1688 {
1689     KBNODE keyblock = NULL;
1690     KBPOS kbpos;
1691     int rc;
1692
1693     if( opt.dry_run )
1694         return;
1695
1696     INIT_TRUSTDB();
1697     rc = enum_keyblocks( 0, &kbpos, &keyblock );
1698     if( !rc ) {
1699         ulong count=0, upd_count=0, err_count=0, new_count=0;
1700
1701         while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
1702             int modified;
1703
1704             rc = update_trust_record( keyblock, 1, &modified );
1705             if( rc == -1 ) { /* not yet in trustdb: insert */
1706                 PKT_public_key *pk =
1707                             find_kbnode( keyblock, PKT_PUBLIC_KEY
1708                                        ) ->pkt->pkt.public_key;
1709                 rc = insert_trust_record( pk );
1710                 if( rc && !pk->local_id ) {
1711                     log_error(_("lid ?: insert failed: %s\n"),
1712                                                      g10_errstr(rc) );
1713                     err_count++;
1714                 }
1715                 else if( rc ) {
1716                     log_error(_("lid %lu: insert failed: %s\n"),
1717                                        pk->local_id, g10_errstr(rc) );
1718                     err_count++;
1719                 }
1720                 else {
1721                     if( opt.verbose )
1722                         log_info(_("lid %lu: inserted\n"), pk->local_id );
1723                     new_count++;
1724                 }
1725             }
1726             else if( rc ) {
1727                 log_error(_("lid %lu: update failed: %s\n"),
1728                          lid_from_keyblock(keyblock), g10_errstr(rc) );
1729                 err_count++;
1730             }
1731             else if( modified ) {
1732                 if( opt.verbose )
1733                     log_info(_("lid %lu: updated\n"), lid_from_keyblock(keyblock));
1734                 upd_count++;
1735             }
1736             else if( opt.verbose > 1 )
1737                 log_info(_("lid %lu: okay\n"), lid_from_keyblock(keyblock) );
1738
1739             release_kbnode( keyblock ); keyblock = NULL;
1740             if( !(++count % 100) )
1741                 log_info(_("%lu keys so far processed\n"), count);
1742         }
1743         log_info(_("%lu keys processed\n"), count);
1744         if( err_count )
1745             log_info(_("\t%lu keys with errors\n"), err_count);
1746         if( upd_count )
1747             log_info(_("\t%lu keys updated\n"), upd_count);
1748         if( new_count )
1749             log_info(_("\t%lu keys inserted\n"), new_count);
1750     }
1751     if( rc && rc != -1 )
1752         log_error(_("enumerate keyblocks failed: %s\n"), g10_errstr(rc));
1753
1754     enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
1755     release_kbnode( keyblock );
1756 }
1757
1758
1759 \f
1760 /****************
1761  * Get the trustlevel for this PK.
1762  * Note: This does not ask any questions
1763  * Returns: 0 okay of an errorcode
1764  *
1765  * It operates this way:
1766  *  locate the pk in the trustdb
1767  *      found:
1768  *          Do we have a valid cache record for it?
1769  *              yes: return trustlevel from cache
1770  *              no:  make a cache record and all the other stuff
1771  *      not found:
1772  *          try to insert the pubkey into the trustdb and check again
1773  *
1774  * Problems: How do we get the complete keyblock to check that the
1775  *           cache record is actually valid?  Think we need a clever
1776  *           cache in getkey.c  to keep track of this stuff. Maybe it
1777  *           is not necessary to check this if we use a local pubring. Hmmmm.
1778  */
1779 int
1780 check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
1781 {
1782     TRUSTREC rec;
1783     unsigned trustlevel = TRUST_UNKNOWN;
1784     int rc=0;
1785     u32 cur_time;
1786     u32 keyid[2];
1787
1788
1789     INIT_TRUSTDB();
1790     keyid_from_pk( pk, keyid );
1791
1792     /* get the pubkey record */
1793     if( pk->local_id ) {
1794         read_record( pk->local_id, &rec, RECTYPE_DIR );
1795     }
1796     else { /* no local_id: scan the trustdb */
1797         if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
1798             log_error(_("check_trust: search dir record failed: %s\n"),
1799                                                             g10_errstr(rc));
1800             return rc;
1801         }
1802         else if( rc == -1 ) { /* not found - insert */
1803             rc = insert_trust_record( pk );
1804             if( rc ) {
1805                 log_error(_("key %08lX: insert trust record failed: %s\n"),
1806                                           (ulong)keyid[1], g10_errstr(rc));
1807                 goto leave;
1808             }
1809             log_info(_("key %08lX.%lu: inserted into trustdb\n"),
1810                                           (ulong)keyid[1], pk->local_id );
1811             /* and re-read the dir record */
1812             read_record( pk->local_id, &rec, RECTYPE_DIR );
1813         }
1814     }
1815     cur_time = make_timestamp();
1816     if( pk->timestamp > cur_time ) {
1817         log_info(_("key %08lX.%lu: created in future "
1818                    "(time warp or clock problem)\n"),
1819                                           (ulong)keyid[1], pk->local_id );
1820         return G10ERR_TIME_CONFLICT;
1821     }
1822
1823     if( pk->expiredate && pk->expiredate <= cur_time ) {
1824         log_info(_("key %08lX.%lu: expired at %s\n"),
1825                         (ulong)keyid[1], pk->local_id,
1826                              asctimestamp( pk->expiredate) );
1827          trustlevel = TRUST_EXPIRED;
1828     }
1829     else {
1830         rc = do_check( &rec, &trustlevel );
1831         if( rc ) {
1832             log_error(_("key %08lX.%lu: trust check failed: %s\n"),
1833                             (ulong)keyid[1], pk->local_id, g10_errstr(rc));
1834             return rc;
1835         }
1836     }
1837
1838
1839   leave:
1840     if( DBG_TRUST )
1841         log_debug("check_trust() returns trustlevel %04x.\n", trustlevel);
1842     *r_trustlevel = trustlevel;
1843     return 0;
1844 }
1845
1846
1847
1848
1849 int
1850 query_trust_info( PKT_public_key *pk )
1851 {
1852     unsigned trustlevel;
1853     int c;
1854
1855     INIT_TRUSTDB();
1856     if( check_trust( pk, &trustlevel ) )
1857         return '?';
1858     if( trustlevel & TRUST_FLAG_REVOKED )
1859         return 'r';
1860     c = trust_letter( (trustlevel & TRUST_MASK) );
1861     if( !c )
1862         c = '?';
1863     return c;
1864 }
1865
1866
1867
1868 /****************
1869  * Enumerate all keys, which are needed to build all trust paths for
1870  * the given key.  This function does not return the key itself or
1871  * the ultimate key (the last point in cerificate chain).  Only
1872  * certificate chains which ends up at an ultimately trusted key
1873  * are listed.  If ownertrust or validity is not NULL, the corresponding
1874  * value for the returned LID is also returned in these variable(s).
1875  *
1876  *  1) create a void pointer and initialize it to NULL
1877  *  2) pass this void pointer by reference to this function.
1878  *     Set lid to the key you want to enumerate and pass it by reference.
1879  *  3) call this function as long as it does not return -1
1880  *     to indicate EOF. LID does contain the next key used to build the web
1881  *  4) Always call this function a last time with LID set to NULL,
1882  *     so that it can free its context.
1883  *
1884  * Returns: -1 on EOF or the level of the returned LID
1885  */
1886 int
1887 enum_cert_paths( void **context, ulong *lid,
1888                  unsigned *ownertrust, unsigned *validity )
1889 {
1890     struct enum_cert_paths_ctx *ctx;
1891     TRUST_SEG_LIST tsl;
1892
1893     INIT_TRUSTDB();
1894     if( !lid ) {  /* release the context */
1895         if( *context ) {
1896             TRUST_SEG_LIST tsl2;
1897
1898             ctx = *context;
1899             for(tsl = ctx->tsl_head; tsl; tsl = tsl2 ) {
1900                 tsl2 = tsl->next;
1901                 m_free( tsl );
1902             }
1903             *context = NULL;
1904         }
1905         return -1;
1906     }
1907
1908     if( !*context ) {
1909         TRUST_INFO *tmppath;
1910         TRUSTREC rec;
1911
1912         if( !*lid )
1913             return -1;
1914
1915         ctx = m_alloc_clear( sizeof *ctx );
1916         *context = ctx;
1917         /* collect the paths */
1918         read_record( *lid, &rec, RECTYPE_DIR );
1919         tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
1920         tsl = NULL;
1921         collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl );
1922         m_free( tmppath );
1923         sort_tsl_list( &tsl );
1924         /* setup the context */
1925         ctx->tsl_head = tsl;
1926         ctx->tsl = ctx->tsl_head;
1927         ctx->idx = 0;
1928     }
1929     else
1930         ctx = *context;
1931
1932     while( ctx->tsl && ctx->idx >= ctx->tsl->pathlen )  {
1933         ctx->tsl = ctx->tsl->next;
1934         ctx->idx = 0;
1935     }
1936     tsl = ctx->tsl;
1937     if( !tsl )
1938         return -1; /* eof */
1939
1940     if( ownertrust )
1941         *ownertrust = tsl->path[ctx->idx].otrust;
1942     if( validity )
1943         *validity = tsl->path[ctx->idx].trust;
1944     *lid = tsl->path[ctx->idx].lid;
1945     ctx->idx++;
1946     return ctx->idx-1;
1947 }
1948
1949
1950 /****************
1951  * Print the current path
1952  */
1953 void
1954 enum_cert_paths_print( void **context, FILE *fp,
1955                                        int refresh, ulong selected_lid )
1956 {
1957     struct enum_cert_paths_ctx *ctx;
1958     TRUST_SEG_LIST tsl;
1959
1960     if( !*context )
1961         return;
1962     INIT_TRUSTDB();
1963     ctx = *context;
1964     if( !ctx->tsl )
1965         return;
1966     tsl = ctx->tsl;
1967
1968     if( !fp )
1969         fp = stderr;
1970
1971     if( refresh ) { /* update the ownertrust and if possible the validity */
1972         int i;
1973         int match = tdbio_db_matches_options();
1974
1975         for( i = 0; i < tsl->pathlen; i++ )  {
1976             TRUSTREC rec;
1977
1978             read_record( tsl->path[i].lid, &rec, RECTYPE_DIR );
1979             tsl->path[i].otrust = rec.r.dir.ownertrust;
1980             /* update validity only if we have it in the cache
1981              * calculation is too time consuming */
1982             if( match && (rec.r.dir.dirflags & DIRF_VALVALID)
1983                       && rec.r.dir.validity ) {
1984                 tsl->path[i].trust = rec.r.dir.validity;
1985                 if( rec.r.dir.dirflags & DIRF_REVOKED )
1986                     tsl->path[i].trust = TRUST_FLAG_REVOKED;
1987             }
1988         }
1989     }
1990
1991     print_path( tsl->pathlen, tsl->path, fp, selected_lid );
1992 }
1993
1994
1995 /****************
1996  * Return the assigned ownertrust value for the given LID
1997  */
1998 unsigned
1999 get_ownertrust( ulong lid )
2000 {
2001     TRUSTREC rec;
2002
2003     INIT_TRUSTDB();
2004     read_record( lid, &rec, RECTYPE_DIR );
2005     return rec.r.dir.ownertrust;
2006 }
2007
2008 int
2009 get_ownertrust_info( ulong lid )
2010 {
2011     unsigned otrust;
2012     int c;
2013
2014     INIT_TRUSTDB();
2015     otrust = get_ownertrust( lid );
2016     c = trust_letter( (otrust & TRUST_MASK) );
2017     if( !c )
2018         c = '?';
2019     return c;
2020 }
2021
2022 /*
2023  * Return an allocated buffer with the preference values for
2024  * the key with LID and the userid which is identified by the
2025  * HAMEHASH or the firstone if namehash is NULL.  ret_n receives
2026  * the length of the allcoated buffer.  Structure of the buffer is
2027  * a repeated sequences of 2 bytes; where the first byte describes the
2028  * type of the preference and the second one the value.  The constants
2029  * PREFTYPE_xxxx should be used to reference a type.
2030  */
2031 byte *
2032 get_pref_data( ulong lid, const byte *namehash, size_t *ret_n )
2033 {
2034     TRUSTREC rec;
2035     ulong recno;
2036
2037     INIT_TRUSTDB();
2038     read_record( lid, &rec, RECTYPE_DIR );
2039     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
2040         read_record( recno, &rec, RECTYPE_UID );
2041         if( rec.r.uid.prefrec
2042             && ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) ))  {
2043             byte *buf;
2044             /* found the correct one or the first one */
2045             read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
2046             if( rec.r.pref.next )
2047                 log_info(_("WARNING: can't yet handle long pref records\n"));
2048             buf = m_alloc( ITEMS_PER_PREF_RECORD );
2049             memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD );
2050             *ret_n = ITEMS_PER_PREF_RECORD;
2051             return buf;
2052         }
2053     }
2054     return NULL;
2055 }
2056
2057
2058
2059 /****************
2060  * Check whether the algorithm is in one of the pref records
2061  */
2062 int
2063 is_algo_in_prefs( ulong lid, int preftype, int algo )
2064 {
2065     TRUSTREC rec;
2066     ulong recno;
2067     int i;
2068     byte *pref;
2069
2070     INIT_TRUSTDB();
2071     read_record( lid, &rec, RECTYPE_DIR );
2072     for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
2073         read_record( recno, &rec, RECTYPE_UID );
2074         if( rec.r.uid.prefrec ) {
2075             read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
2076             if( rec.r.pref.next )
2077                 log_info(_("WARNING: can't yet handle long pref records\n"));
2078             pref = rec.r.pref.data;
2079             for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) {
2080                 if( pref[i] == preftype && pref[i+1] == algo )
2081                     return 1;
2082             }
2083         }
2084     }
2085     return 0;
2086 }
2087
2088
2089 static int
2090 get_dir_record( PKT_public_key *pk, TRUSTREC *rec )
2091 {
2092     int rc=0;
2093
2094     if( pk->local_id ) {
2095         read_record( pk->local_id, rec, RECTYPE_DIR );
2096     }
2097     else { /* no local_id: scan the trustdb */
2098         if( (rc=tdbio_search_dir_bypk( pk, rec )) && rc != -1 )
2099             log_error(_("get_dir_record: search_record failed: %s\n"),
2100                                                             g10_errstr(rc));
2101     }
2102     return rc;
2103 }
2104
2105
2106
2107 /****************
2108  * This function simply looks for the key in the trustdb
2109  * and makes sure that pk->local_id is set to the correct value.
2110  * Return: 0 = found
2111  *         -1 = not found
2112  *        other = error
2113  */
2114 int
2115 query_trust_record( PKT_public_key *pk )
2116 {
2117     TRUSTREC rec;
2118     INIT_TRUSTDB();
2119     return get_dir_record( pk, &rec );
2120 }
2121
2122
2123 int
2124 clear_trust_checked_flag( PKT_public_key *pk )
2125 {
2126     TRUSTREC rec;
2127     int rc;
2128
2129     if( opt.dry_run )
2130         return 0;
2131
2132     INIT_TRUSTDB();
2133     rc = get_dir_record( pk, &rec );
2134     if( rc )
2135         return rc;
2136
2137     /* check whether they are already reset */
2138     if(   !(rec.r.dir.dirflags & DIRF_CHECKED)
2139        && !(rec.r.dir.dirflags & DIRF_VALVALID) )
2140         return 0;
2141
2142     /* reset the flag */
2143     rec.r.dir.dirflags &= ~DIRF_CHECKED;
2144     rec.r.dir.dirflags &= ~DIRF_VALVALID;
2145     write_record( &rec );
2146     do_sync();
2147     return 0;
2148 }
2149
2150
2151
2152
2153 static void
2154 check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
2155                 TRUSTREC *sigrec, int sigidx, ulong hint_owner )
2156 {
2157     KBNODE node;
2158     int rc, state;
2159     byte uhash[20];
2160     int is_selfsig;
2161     PKT_signature *sigpkt = NULL;
2162     TRUSTREC tmp;
2163     u32 sigkid[2];
2164     int revoked = 0;
2165
2166     if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED )
2167         log_info(_("NOTE: sig rec %lu[%d] in hintlist "
2168                    "of %lu but marked as checked\n"),
2169                     sigrec->recnum, sigidx, hint_owner );
2170     if( !(sigrec->r.sig.sig[sigidx].flag & SIGF_NOPUBKEY) )
2171         log_info(_("NOTE: sig rec %lu[%d] in hintlist "
2172                    "of %lu but not marked\n"),
2173                     sigrec->recnum, sigidx, hint_owner );
2174
2175     read_record( sigrec->r.sig.sig[sigidx].lid, &tmp, 0 );
2176     if( tmp.rectype != RECTYPE_DIR ) {
2177         /* we need the dir record */
2178         log_error(_("sig rec %lu[%d] in hintlist "
2179                     "of %lu does not point to a dir record\n"),
2180                     sigrec->recnum, sigidx, hint_owner );
2181         return;
2182     }
2183     if( !tmp.r.dir.keylist ) {
2184         log_error(_("lid %lu: no primary key\n"), tmp.r.dir.lid );
2185         return;
2186     }
2187     read_record(tmp.r.dir.keylist, &tmp, RECTYPE_KEY );
2188     keyid_from_fingerprint( tmp.r.key.fingerprint,
2189                             tmp.r.key.fingerprint_len, sigkid );
2190
2191
2192     /* find the correct signature packet */
2193     state = 0;
2194     for( node=keyblock; node; node = node->next ) {
2195         if( node->pkt->pkttype == PKT_USER_ID ) {
2196             PKT_user_id *uidpkt = node->pkt->pkt.user_id;
2197
2198             if( state )
2199                 break;
2200             rmd160_hash_buffer( uhash, uidpkt->name, uidpkt->len );
2201             if( !memcmp( uhash, uidrec_hash, 20 ) )
2202                 state = 1;
2203         }
2204         else if( state && node->pkt->pkttype == PKT_SIGNATURE ) {
2205             sigpkt = node->pkt->pkt.signature;
2206             if( sigpkt->keyid[0] == sigkid[0]
2207                 && sigpkt->keyid[1] == sigkid[1]
2208                 && ( (sigpkt->sig_class&~3) == 0x10
2209                      || ( revoked = (sigpkt->sig_class == 0x30)) ) ) {
2210                 state = 2;
2211                 break; /* found */
2212             }
2213         }
2214     }
2215
2216     if( !node ) {
2217         log_info(_("lid %lu: user id not found in keyblock\n"), lid );
2218         return ;
2219     }
2220     if( state != 2 ) {
2221         log_info(_("lid %lu: user id without signature\n"), lid );
2222         return ;
2223     }
2224
2225     /* and check the sig */
2226     rc = check_key_signature( keyblock, node, &is_selfsig );
2227     if( is_selfsig ) {
2228         log_error(_("lid %lu: self-signature in hintlist\n"), lid );
2229         return;
2230     }
2231
2232     /* FiXME: handling fo SIGF_REVOKED is not correct! */
2233
2234     if( !rc ) { /* valid signature */
2235         if( opt.verbose )
2236             log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2237                     (ulong)keyid[1], lid, uhash[18], uhash[19],
2238                     (ulong)sigpkt->keyid[1],
2239                     revoked? _("Valid certificate revocation")
2240                            : _("Good certificate") );
2241         sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID;
2242         if( revoked )
2243             sigrec->r.sig.sig[sigidx].flag |= SIGF_REVOKED;
2244     }
2245     else if( rc == G10ERR_NO_PUBKEY ) {
2246         log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2247               (ulong)keyid[1], lid, uhash[18], uhash[19],
2248                (ulong)sigpkt->keyid[1],
2249                  _("very strange: no public key\n") );
2250         sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY;
2251     }
2252     else {
2253         log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2254                     (ulong)keyid[1], lid, uhash[18], uhash[19],
2255                     (ulong)sigpkt->keyid[1], g10_errstr(rc) );
2256         sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED;
2257     }
2258     sigrec->dirty = 1;
2259 }
2260
2261
2262 /****************
2263  * Process a hintlist.
2264  * Fixme: this list is not anymore anchored to another
2265  *        record, so it should be put elsewehere in case of an error
2266  */
2267 static void
2268 process_hintlist( ulong hintlist, ulong hint_owner )
2269 {
2270     ulong hlst_rn;
2271     int rc;
2272
2273     for( hlst_rn = hintlist; hlst_rn; ) {
2274         TRUSTREC hlstrec;
2275         int hlst_idx;
2276
2277         read_record( hlst_rn, &hlstrec, RECTYPE_HLST );
2278
2279         for( hlst_idx=0; hlst_idx < ITEMS_PER_HLST_RECORD; hlst_idx++ ) {
2280             TRUSTREC dirrec;
2281             TRUSTREC uidrec;
2282             TRUSTREC tmprec;
2283             KBNODE keyblock = NULL;
2284             u32 keyid[2];
2285             ulong lid;
2286             ulong r1, r2;
2287
2288             lid = hlstrec.r.hlst.rnum[hlst_idx];
2289             if( !lid )
2290                 continue;
2291
2292             read_record( lid, &dirrec, 0 );
2293             /* make sure it points to a dir record:
2294              * this should be true because it only makes sense to
2295              * call this function if the dir record is available */
2296             if( dirrec.rectype != RECTYPE_DIR )  {
2297                 log_error(_("hintlist %lu[%d] of %lu "
2298                             "does not point to a dir record\n"),
2299                             hlst_rn, hlst_idx, hint_owner );
2300                 continue;
2301             }
2302             if( !dirrec.r.dir.keylist ) {
2303                 log_error(_("lid %lu does not have a key\n"), lid );
2304                 continue;
2305             }
2306
2307             /* get the keyblock */
2308             read_record( dirrec.r.dir.keylist, &tmprec, RECTYPE_KEY );
2309             rc = get_keyblock_byfprint( &keyblock,
2310                                         tmprec.r.key.fingerprint,
2311                                         tmprec.r.key.fingerprint_len );
2312             if( rc ) {
2313                 log_error(_("lid %lu: can't get keyblock: %s\n"),
2314                                                     lid, g10_errstr(rc) );
2315                 continue;
2316             }
2317             keyid_from_fingerprint( tmprec.r.key.fingerprint,
2318                                     tmprec.r.key.fingerprint_len, keyid );
2319
2320             /* Walk over all user ids and their signatures and check all
2321              * the signature which are created by hint_owner */
2322             for( r1 = dirrec.r.dir.uidlist; r1; r1 = uidrec.r.uid.next ) {
2323                 TRUSTREC sigrec;
2324
2325                 read_record( r1, &uidrec, RECTYPE_UID );
2326                 for( r2 = uidrec.r.uid.siglist; r2; r2 = sigrec.r.sig.next ) {
2327                     int i;
2328
2329                     read_record( r2, &sigrec, RECTYPE_SIG );
2330                     sigrec.dirty = 0;
2331                     for(i=0; i < SIGS_PER_RECORD; i++ ) {
2332                         if( !sigrec.r.sig.sig[i].lid )
2333                             continue; /* skip deleted sigs */
2334                         if( sigrec.r.sig.sig[i].lid != hint_owner )
2335                             continue; /* not for us */
2336                         /* some diagnostic messages */
2337                         /* and do the signature check */
2338                         check_hint_sig( lid, keyblock, keyid,
2339                                         uidrec.r.uid.namehash,
2340                                         &sigrec, i, hint_owner );
2341                     }
2342                     if( sigrec.dirty )
2343                         write_record( &sigrec );
2344                 }
2345             }
2346             release_kbnode( keyblock );
2347         } /* loop over hlst entries */
2348
2349         /* delete this hlst record */
2350         hlst_rn = hlstrec.r.hlst.next;
2351         delete_record( hlstrec.recnum );
2352     } /* loop over hintlist */
2353 }
2354
2355
2356 /****************
2357  * Create or update shadow dir record and return the LID of the record
2358  */
2359 static ulong
2360 create_shadow_dir( PKT_signature *sig, ulong lid  )
2361 {
2362     TRUSTREC sdir, hlst, tmphlst;
2363     ulong recno, newlid;
2364     int tmpidx=0; /* avoids gcc warnign - this is controlled by tmphlst */
2365     int rc;
2366
2367     /* first see whether we already have such a record */
2368     rc = tdbio_search_sdir( sig->keyid, sig->pubkey_algo, &sdir );
2369     if( rc && rc != -1 ) {
2370         log_error(_("tdbio_search_dir failed: %s\n"), g10_errstr(rc));
2371         die_invalid_db();
2372     }
2373     if( rc == -1 ) { /* not found: create */
2374         memset( &sdir, 0, sizeof sdir );
2375         sdir.recnum = tdbio_new_recnum();
2376         sdir.rectype= RECTYPE_SDIR;
2377         sdir.r.sdir.lid = sdir.recnum;
2378         sdir.r.sdir.keyid[0] = sig->keyid[0];
2379         sdir.r.sdir.keyid[1] = sig->keyid[1];
2380         sdir.r.sdir.pubkey_algo = sig->pubkey_algo;
2381         sdir.r.sdir.hintlist = 0;
2382         write_record( &sdir );
2383     }
2384     newlid = sdir.recnum;
2385     /* Put the record number into the hintlist.
2386      * (It is easier to use the lid and not the record number of the
2387      *  key to save some space (assuming that a signator has
2388      *  signed more than one user id - and it is easier to implement.)
2389      */
2390     tmphlst.recnum = 0;
2391     for( recno=sdir.r.sdir.hintlist; recno; recno = hlst.r.hlst.next) {
2392         int i;
2393         read_record( recno, &hlst, RECTYPE_HLST );
2394         for( i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
2395             if( !hlst.r.hlst.rnum[i] ) {
2396                 if( !tmphlst.recnum ) {
2397                     tmphlst = hlst;
2398                     tmpidx = i;
2399                 }
2400             }
2401             else if( hlst.r.hlst.rnum[i] == lid )
2402                 return newlid; /* the signature is already in the hintlist */
2403         }
2404     }
2405     /* not yet in the hint list, write it */
2406     if( tmphlst.recnum ) { /* we have an empty slot */
2407         tmphlst.r.hlst.rnum[tmpidx] = lid;
2408         write_record( &tmphlst );
2409     }
2410     else { /* must append a new hlst record */
2411         memset( &hlst, 0, sizeof hlst );
2412         hlst.recnum = tdbio_new_recnum();
2413         hlst.rectype = RECTYPE_HLST;
2414         hlst.r.hlst.next = sdir.r.sdir.hintlist;
2415         hlst.r.hlst.rnum[0] = lid;
2416         write_record( &hlst );
2417         sdir.r.sdir.hintlist = hlst.recnum;
2418         write_record( &sdir );
2419     }
2420
2421     return newlid;
2422 }
2423
2424
2425 /****************
2426  * This function checks the given public key and inserts or updates
2427  * the keyrecord from the trustdb.  Revocation certificates
2428  * are handled here and the keybinding of subkeys is checked.
2429  * Hmmm: Should we check here, that the key has at least one valid
2430  * user ID or do we allow keys w/o user ID?
2431  *
2432  * keyblock points to the first node in the keyblock,
2433  * keynode is the node with the public key to check
2434  * (either primary or secondary), keyid is the keyid of
2435  * the primary key, drec is the directory record and recno_list
2436  * is a list used to keep track of visited records.
2437  * Existing keyflags are recalculated if recheck is true.
2438  */
2439 static void
2440 upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
2441                 TRUSTREC *drec, RECNO_LIST *recno_list, int recheck )
2442 {
2443     TRUSTREC krec;
2444     KBNODE  node;
2445     PKT_public_key *pk = keynode->pkt->pkt.public_key;
2446     ulong lid = drec->recnum;
2447     byte fpr[MAX_FINGERPRINT_LEN];
2448     size_t fprlen;
2449     ulong recno, newrecno;
2450     int keybind_seen = 0;
2451     int revoke_seen = 0;
2452     int rc;
2453
2454     fingerprint_from_pk( pk, fpr, &fprlen );
2455     /* do we already have this key? */
2456     for( recno=drec->r.dir.keylist; recno; recno = krec.r.key.next ) {
2457         read_record( recno, &krec, RECTYPE_KEY );
2458         if( krec.r.key.fingerprint_len == fprlen
2459             && !memcmp( krec.r.key.fingerprint, fpr, fprlen ) )
2460             break;
2461     }
2462     if( recno ) { /* yes */
2463         ins_recno_list( recno_list, recno, RECTYPE_KEY );
2464     }
2465     else { /* no: insert this new key */
2466         recheck = 1;
2467         memset( &krec, 0, sizeof(krec) );
2468         krec.rectype = RECTYPE_KEY;
2469         krec.r.key.lid = lid;
2470         krec.r.key.pubkey_algo = pk->pubkey_algo;
2471         krec.r.key.fingerprint_len = fprlen;
2472         memcpy(krec.r.key.fingerprint, fpr, fprlen );
2473         krec.recnum = newrecno = tdbio_new_recnum();
2474         write_record( &krec );
2475         ins_recno_list( recno_list, newrecno, RECTYPE_KEY );
2476         /* and put this new record at the end of the keylist */
2477         if( !(recno=drec->r.dir.keylist) ) {
2478             /* this is the first key */
2479             drec->r.dir.keylist = newrecno;
2480             drec->dirty = 1;
2481         }
2482         else { /* we already have a key, append the new one */
2483             TRUSTREC save = krec;
2484             for( ; recno; recno = krec.r.key.next )
2485                 read_record( recno, &krec, RECTYPE_KEY );
2486             krec.r.key.next = newrecno;
2487             write_record( &krec );
2488             krec = save;
2489         }
2490     }
2491
2492     if( !recheck && (krec.r.key.keyflags & KEYF_CHECKED) )
2493         return;
2494
2495     /* check keybindings and revocations */
2496     krec.r.key.keyflags = 0;
2497     if( keynode->pkt->pkttype == PKT_PUBLIC_KEY ) {
2498         /* we assume that a primary key is always valid
2499          * and check later whether we have a revocation */
2500         krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
2501     }
2502
2503     for( node=keynode->next; node; node = node->next ) {
2504         PKT_signature *sig;
2505
2506         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2507             break; /* ready */
2508         else if( node->pkt->pkttype != PKT_SIGNATURE )
2509             continue;
2510
2511         sig = node->pkt->pkt.signature;
2512
2513         if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
2514             continue; /* not a self signature */
2515         if( sig->sig_class == 0x18 && !keybind_seen ) { /* a keybinding */
2516             if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
2517                 continue; /* oops, not for a main key */
2518             /* we check until we find a valid keybinding */
2519             rc = check_key_signature( keyblock, node, NULL );
2520             if( !rc ) {
2521                 if( opt.verbose )
2522                     log_info(_(
2523                         "key %08lX.%lu: Good subkey binding\n"),
2524                          (ulong)keyid_from_pk(pk,NULL), lid );
2525                 krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
2526             }
2527             else {
2528                 log_info(_(
2529                   "key %08lX.%lu: Invalid subkey binding: %s\n"),
2530                     (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
2531                 krec.r.key.keyflags |= KEYF_CHECKED;
2532                 krec.r.key.keyflags &= ~KEYF_VALID;
2533             }
2534             keybind_seen = 1;
2535         }
2536         else if( sig->sig_class == 0x20 && !revoke_seen ) {
2537             if( keynode->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2538                 continue; /* a subkey is not expected here */
2539             /* This is a key revocation certificate: check it */
2540             rc = check_key_signature( keyblock, node, NULL );
2541             if( !rc ) {
2542                 if( opt.verbose )
2543                     log_info(_(
2544                         "key %08lX.%lu: Valid key revocation\n"),
2545                          (ulong)keyid_from_pk(pk,NULL), lid );
2546                 krec.r.key.keyflags |= KEYF_REVOKED;
2547             }
2548             else {
2549                 log_info(_(
2550                   "key %08lX.%lu: Invalid key revocation: %s\n"),
2551                   (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
2552             }
2553             revoke_seen = 1;
2554         }
2555         else if( sig->sig_class == 0x28 && !revoke_seen ) {
2556             if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
2557                 continue; /* a mainkey is not expected here */
2558             /* This is a subkey revocation certificate: check it */
2559             /* fixme: we should also check the revocation
2560              * is newer than the key (OpenPGP) */
2561             rc = check_key_signature( keyblock, node, NULL );
2562             if( !rc ) {
2563                 if( opt.verbose )
2564                     log_info(_(
2565                         "key %08lX.%lu: Valid subkey revocation\n"),
2566                          (ulong)keyid_from_pk(pk,NULL), lid );
2567                 krec.r.key.keyflags |= KEYF_REVOKED;
2568             }
2569             else {
2570                 log_info(_(
2571                   "key %08lX.%lu: Invalid subkey binding: %s\n"),
2572                   (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
2573             }
2574             revoke_seen = 1;
2575         }
2576     }
2577
2578     write_record( &krec );
2579 }
2580
2581
2582 /****************
2583  * This function checks the given user ID and inserts or updates
2584  * the uid record of the trustdb.  Revocation certificates
2585  * are handled here.
2586  *
2587  * keyblock points to the first node in the keyblock,
2588  * uidnode is the node with the user id to check
2589  * keyid is the keyid of
2590  * the primary key, drec is the directory record and recno_list
2591  * is a list used to keep track of visited records.
2592  * Existing uidflags are recalculated if recheck is true.
2593  */
2594 static void
2595 upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
2596                 TRUSTREC *drec, RECNO_LIST *recno_list, int recheck )
2597 {
2598     ulong lid = drec->recnum;
2599     PKT_user_id *uid = uidnode->pkt->pkt.user_id;
2600     TRUSTREC urec;
2601     PKT_signature *selfsig = NULL;
2602     byte uidhash[20];
2603     KBNODE node;
2604     ulong recno, newrecno;
2605     int rc;
2606
2607     /* see whether we already have an uid record */
2608     rmd160_hash_buffer( uidhash, uid->name, uid->len );
2609     for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) {
2610         read_record( recno, &urec, RECTYPE_UID );
2611         if( !memcmp( uidhash, urec.r.uid.namehash, 20 ) )
2612             break;
2613     }
2614     if( recno ) { /* we already have this record */
2615         ins_recno_list( recno_list, recno, RECTYPE_UID );
2616     }
2617     else { /* new user id */
2618         recheck = 1;
2619         memset( &urec, 0 , sizeof(urec) );
2620         urec.rectype = RECTYPE_UID;
2621         urec.r.uid.lid = drec->recnum;
2622         memcpy(urec.r.uid.namehash, uidhash, 20 );
2623         urec.recnum = newrecno = tdbio_new_recnum();
2624         write_record( &urec );
2625         ins_recno_list( recno_list, newrecno, RECTYPE_UID );
2626         /* and put this new record at the end of the uidlist */
2627         if( !(recno=drec->r.dir.uidlist) ) { /* this is the first uid */
2628             drec->r.dir.uidlist = newrecno;
2629             drec->dirty = 1;
2630         }
2631         else { /* we already have an uid, append it to the list */
2632             TRUSTREC save = urec;
2633             for( ; recno; recno = urec.r.key.next )
2634                 read_record( recno, &urec, RECTYPE_UID );
2635             urec.r.uid.next = newrecno;
2636             write_record( &urec );
2637             urec = save;
2638         }
2639     }
2640
2641     if( recheck || !(urec.r.uid.uidflags & UIDF_CHECKED) ) {
2642         /* check self signatures */
2643         urec.r.uid.uidflags = 0;
2644         for( node=uidnode->next; node; node = node->next ) {
2645             PKT_signature *sig;
2646
2647             if( node->pkt->pkttype == PKT_USER_ID )
2648                 break; /* ready */
2649             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2650                 break; /* ready */
2651             if( node->pkt->pkttype != PKT_SIGNATURE )
2652                 continue;
2653
2654             sig = node->pkt->pkt.signature;
2655
2656             if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
2657                 continue; /* not a self signature */
2658
2659             if( (sig->sig_class&~3) == 0x10 ) { /* regular self signature */
2660                 rc = check_key_signature( keyblock, node, NULL );
2661                 if( !rc ) {
2662                     if( opt.verbose )
2663                         log_info( "uid %08lX.%lu/%02X%02X: %s\n",
2664                            (ulong)keyid[1], lid, uidhash[18], uidhash[19],
2665                                   _("Good self-signature") );
2666                     urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
2667                     if( !selfsig )
2668                         selfsig = sig; /* use the first valid sig */
2669                     else if( sig->timestamp > selfsig->timestamp
2670                              && sig->sig_class >= selfsig->sig_class )
2671                         selfsig = sig; /* but this one is newer */
2672                 }
2673                 else {
2674                     log_info( "uid %08lX/%02X%02X: %s: %s\n",
2675                                (ulong)keyid[1], uidhash[18], uidhash[19],
2676                               _("Invalid self-signature"),
2677                                g10_errstr(rc) );
2678                     urec.r.uid.uidflags |= UIDF_CHECKED;
2679                 }
2680             }
2681             else if( sig->sig_class == 0x30 ) { /* cert revocation */
2682                 rc = check_key_signature( keyblock, node, NULL );
2683                 if( !rc && selfsig && selfsig->timestamp > sig->timestamp ) {
2684                     log_info( "uid %08lX.%lu/%02X%02X: %s\n",
2685                            (ulong)keyid[1], lid, uidhash[18], uidhash[19],
2686                            _("Valid user ID revocation skipped "
2687                              "due to a newer self signature\n") );
2688                 }
2689                 else if( !rc ) {
2690                     if( opt.verbose )
2691                         log_info( "uid %08lX.%lu/%02X%02X: %s\n",
2692                            (ulong)keyid[1], lid, uidhash[18], uidhash[19],
2693                                  _("Valid user ID revocation\n") );
2694                     urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
2695                     urec.r.uid.uidflags |= UIDF_REVOKED;
2696                 }
2697                 else {
2698                     log_info("uid %08lX/%02X%02X: %s: %s\n",
2699                                 (ulong)keyid[1], uidhash[18], uidhash[19],
2700                                _("Invalid user ID revocation"),
2701                                                         g10_errstr(rc) );
2702                 }
2703             }
2704         }
2705         write_record( &urec );
2706     } /* end check self-signatures */
2707
2708
2709     if( (urec.r.uid.uidflags & (UIDF_CHECKED|UIDF_VALID))
2710         != (UIDF_CHECKED|UIDF_VALID) )
2711         return; /* user ID is not valid, so no need to check more things */
2712
2713     /* check the preferences */
2714     if( selfsig )
2715         upd_pref_record( &urec, keyid, selfsig );
2716
2717     /* check non-self signatures */
2718     for( node=uidnode->next; node; node = node->next ) {
2719         PKT_signature *sig;
2720
2721         if( node->pkt->pkttype == PKT_USER_ID )
2722             break; /* ready */
2723         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2724             break; /* ready */
2725         if( node->pkt->pkttype != PKT_SIGNATURE )
2726             continue;
2727
2728         sig = node->pkt->pkt.signature;
2729
2730         if( keyid[0] == sig->keyid[0] || keyid[1] == sig->keyid[1] )
2731             continue; /* skip self signature */
2732
2733         if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */
2734             upd_cert_record( keyblock, node, keyid, drec, recno_list,
2735                              recheck, &urec, uidhash, 0 );
2736         }
2737         else if( sig->sig_class == 0x30 ) { /* cert revocation */
2738             upd_cert_record( keyblock, node, keyid, drec, recno_list,
2739                              recheck, &urec, uidhash, 1 );
2740         }
2741     } /* end check certificates */
2742
2743     write_record( &urec );
2744 }
2745
2746
2747
2748 /****************
2749  *
2750  *
2751  */
2752 static void
2753 upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig )
2754 {
2755     static struct {
2756         sigsubpkttype_t subpkttype;
2757         int preftype;
2758     } ptable[] = {
2759         { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
2760         { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
2761         { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
2762         { 0, 0 }
2763     };
2764     TRUSTREC prec;
2765     ulong lid = urec->r.uid.lid ;
2766     const byte *uidhash = urec->r.uid.namehash;
2767     const byte *s;
2768     size_t n;
2769     int k, i;
2770     ulong recno;
2771     byte prefs_sig[200];
2772     int n_prefs_sig = 0;
2773     byte prefs_rec[200];
2774     int n_prefs_rec = 0;
2775
2776     /* check for changed preferences */
2777     for(k=0; ptable[k].subpkttype; k++ ) {
2778         s = parse_sig_subpkt2( sig, ptable[k].subpkttype, &n );
2779         if( s ) {
2780             for( ; n; n--, s++ ) {
2781                 if( n_prefs_sig >= DIM(prefs_sig)-1 ) {
2782                     log_info("uid %08lX.%lu/%02X%02X: %s\n",
2783                               (ulong)keyid[1], lid, uidhash[18], uidhash[19],
2784                               _("Too many preferences") );
2785                     break;
2786                 }
2787                 prefs_sig[n_prefs_sig++] = ptable[k].preftype;
2788                 prefs_sig[n_prefs_sig++] = *s;
2789             }
2790         }
2791     }
2792     for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
2793         read_record( recno, &prec, RECTYPE_PREF );
2794         for(i = 0; i < ITEMS_PER_PREF_RECORD; i +=2 )  {
2795             if( n_prefs_rec >= DIM(prefs_rec)-1 ) {
2796                 log_info("uid %08lX.%lu/%02X%02X: %s\n",
2797                           (ulong)keyid[1], lid, uidhash[18], uidhash[19],
2798                           _("Too many preference items") );
2799                 break;
2800             }
2801             if( prec.r.pref.data[i] ) {
2802                 prefs_rec[n_prefs_rec++] = prec.r.pref.data[i];
2803                 prefs_rec[n_prefs_rec++] = prec.r.pref.data[i+1];
2804             }
2805         }
2806     }
2807     if( n_prefs_sig == n_prefs_rec
2808         && !memcmp( prefs_sig, prefs_rec, n_prefs_sig ) )
2809         return;  /* not changed */
2810
2811     /* Preferences have changed:  Delete all pref records
2812      * This is much simpler than checking whether we have to
2813      * do update the record at all - the record cache may care about it
2814      */
2815     for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
2816         read_record( recno, &prec, RECTYPE_PREF );
2817         delete_record( recno );
2818     }
2819
2820     if( n_prefs_sig > ITEMS_PER_PREF_RECORD )
2821          log_info(_("WARNING: can't yet handle long pref records\n"));
2822
2823     memset( &prec, 0, sizeof prec );
2824     prec.recnum = tdbio_new_recnum();
2825     prec.rectype = RECTYPE_PREF;
2826     prec.r.pref.lid = lid;
2827     if( n_prefs_sig <= ITEMS_PER_PREF_RECORD )
2828         memcpy( prec.r.pref.data, prefs_sig, n_prefs_sig );
2829     else { /* need more than one pref record */
2830         TRUSTREC tmp;
2831         ulong nextrn;
2832         byte *pp = prefs_sig;
2833
2834         n = n_prefs_sig;
2835         memcpy( prec.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
2836         n -= ITEMS_PER_PREF_RECORD;
2837         pp += ITEMS_PER_PREF_RECORD;
2838         nextrn = prec.r.pref.next = tdbio_new_recnum();
2839         do {
2840             memset( &tmp, 0, sizeof tmp );
2841             tmp.recnum = nextrn;
2842             tmp.rectype = RECTYPE_PREF;
2843             tmp.r.pref.lid = lid;
2844             if( n <= ITEMS_PER_PREF_RECORD ) {
2845                 memcpy( tmp.r.pref.data, pp, n );
2846                 n = 0;
2847             }
2848             else {
2849                 memcpy( tmp.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
2850                 n -= ITEMS_PER_PREF_RECORD;
2851                 pp += ITEMS_PER_PREF_RECORD;
2852                 nextrn = tmp.r.pref.next = tdbio_new_recnum();
2853             }
2854             write_record( &tmp );
2855         } while( n );
2856     }
2857     write_record( &prec );
2858     urec->r.uid.prefrec = prec.recnum;
2859     urec->dirty = 1;
2860 }
2861
2862
2863
2864 static void
2865 upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
2866                  TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
2867                  TRUSTREC *urec, const byte *uidhash, int revoked )
2868 {
2869     /* We simply insert the signature into the sig records but
2870      * avoid duplicate ones.  We do not check them here because
2871      * there is a big chance, that we import required public keys
2872      * later.  The problem with this is that we must somewhere store
2873      * the information about this signature (we need a record id).
2874      * We do this by using the record type shadow dir, which will
2875      * be converted to a dir record as soon as a new public key is
2876      * inserted into the trustdb.
2877      */
2878     ulong lid = drec->recnum;
2879     PKT_signature *sig = signode->pkt->pkt.signature;
2880     TRUSTREC rec;
2881     ulong recno;
2882     TRUSTREC delrec;
2883     int delrecidx=0;
2884     int newflag = 0;
2885     ulong newlid = 0;
2886     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
2887     ulong pk_lid = 0;
2888     int found_sig = 0;
2889     int found_delrec = 0;
2890     int rc;
2891
2892     delrec.recnum = 0;
2893
2894     /* get the LID of the pubkey of the signature under verification */
2895     rc = get_pubkey( pk, sig->keyid );
2896     if( !rc ) {
2897         if( pk->local_id )
2898             pk_lid = pk->local_id;
2899         else {
2900             rc = tdbio_search_dir_bypk( pk, &rec );
2901             if( !rc )
2902                 pk_lid = rec.recnum;
2903             else if( rc == -1 ) { /* see whether there is a sdir instead */
2904                 u32 akid[2];
2905
2906                 keyid_from_pk( pk, akid );
2907                 rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec );
2908                 if( !rc )
2909                     pk_lid = rec.recnum;
2910             }
2911         }
2912     }
2913     free_public_key( pk ); pk = NULL;
2914
2915     /* Loop over all signatures just in case one is not correctly
2916      * marked.  If we see the correct signature, set a flag.
2917      * delete duplicate signatures (should not happen but...) */
2918     for( recno = urec->r.uid.siglist; recno; recno = rec.r.sig.next ) {
2919         int i;
2920
2921         read_record( recno, &rec, RECTYPE_SIG );
2922         for(i=0; i < SIGS_PER_RECORD; i++ ) {
2923             TRUSTREC tmp;
2924             if( !rec.r.sig.sig[i].lid ) {
2925                 if( !found_delrec && !delrec.recnum ) {
2926                     delrec = rec;
2927                     delrecidx = i;
2928                     found_delrec=1;
2929                 }
2930                 continue; /* skip deleted sigs */
2931             }
2932             if( rec.r.sig.sig[i].lid == pk_lid ) {
2933               #if 0 /* must take uid into account */
2934                 if( found_sig ) {
2935                     log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2936                               (ulong)keyid[1], lid, uidhash[18],
2937                                uidhash[19], (ulong)sig->keyid[1],
2938                              _("duplicated certificate - deleted") );
2939                     rec.r.sig.sig[i].lid = 0;
2940                     rec.dirty = 1;
2941                     continue;
2942                 }
2943               #endif
2944                 found_sig = 1;
2945             }
2946             if( !recheck && !revoked && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
2947                 continue; /* we already checked this signature */
2948             if( !recheck && (rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
2949                 continue; /* we do not have the public key */
2950
2951             read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
2952             if( tmp.rectype == RECTYPE_DIR ) {
2953                 /* In this case we should now be able to check the signature */
2954                 rc = check_key_signature( keyblock, signode, NULL );
2955                 if( !rc ) { /* valid signature */
2956                     if( opt.verbose )
2957                         log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2958                                 (ulong)keyid[1], lid, uidhash[18],
2959                                 uidhash[19], (ulong)sig->keyid[1],
2960                                 revoked? _("Valid certificate revocation")
2961                                        : _("Good certificate") );
2962                     rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID;
2963                     if( revoked )
2964                         rec.r.sig.sig[i].flag |= SIGF_REVOKED;
2965                 }
2966                 else if( rc == G10ERR_NO_PUBKEY ) {
2967                   #if 0 /* fixme: For some reason this really happens? */
2968                     if( (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
2969                         log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
2970                                   (ulong)keyid[1], lid, uidhash[18],
2971                                  uidhash[19], (ulong)sig->keyid[1],
2972                                  _("Hmmm, public key lost?") );
2973                   #endif
2974                     rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
2975                     if( revoked )
2976                         rec.r.sig.sig[i].flag |= SIGF_REVOKED;
2977                 }
2978                 else {
2979                     log_info("sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
2980                                 (ulong)keyid[1], lid, uidhash[18],
2981                                 uidhash[19], (ulong)sig->keyid[1],
2982                                 revoked? _("Invalid certificate revocation")
2983                                        : _("Invalid certificate"),
2984                                                     g10_errstr(rc));
2985                     rec.r.sig.sig[i].flag = SIGF_CHECKED;
2986                     if( revoked )
2987                         rec.r.sig.sig[i].flag |= SIGF_REVOKED;
2988                 }
2989                 rec.dirty = 1;
2990             }
2991             else if( tmp.rectype == RECTYPE_SDIR ) {
2992                 /* must check that it is the right one */
2993                 if( tmp.r.sdir.keyid[0] == sig->keyid[0]
2994                     && tmp.r.sdir.keyid[1] == sig->keyid[1]
2995                     && (!tmp.r.sdir.pubkey_algo
2996                          || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) {
2997                     if( !(rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
2998                         log_info(_("uid %08lX.%lu/%02X%02X: "
2999                                 "has shadow dir %lu but is not yet marked.\n"),
3000                                 (ulong)keyid[1], lid,
3001                                 uidhash[18], uidhash[19], tmp.recnum );
3002                     rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
3003                     if( revoked )
3004                         rec.r.sig.sig[i].flag |= SIGF_REVOKED;
3005                     rec.dirty = 1;
3006                     /* fixme: should we verify that the record is
3007                      * in the hintlist? - This case here should anyway
3008                      * never occur */
3009                 }
3010             }
3011             else {
3012                 log_error(_("sig record %lu[%d] points to wrong record.\n"),
3013                             rec.r.sig.sig[i].lid, i );
3014                 die_invalid_db();
3015             }
3016         }
3017         if( found_delrec && delrec.recnum ) {
3018             delrec = rec;
3019             found_delrec = 0; /* we only want the first one */
3020         }
3021         if( rec.dirty ) {
3022             write_record( &rec );
3023             rec.dirty = 0;
3024         }
3025     }
3026
3027     if( found_sig )  /* fixme: uid stuff */
3028         return;
3029
3030     /* at this point, we have verified, that the signature is not in
3031      * our list of signatures.  Add a new record with that signature
3032      * and if the public key is there, check the signature. */
3033
3034     if( !pk_lid ) /* we have already seen that there is no pubkey */
3035         rc = G10ERR_NO_PUBKEY;
3036     else
3037         rc = check_key_signature( keyblock, signode, NULL );
3038
3039     if( !rc ) { /* valid signature */
3040         if( opt.verbose )
3041             log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
3042                           (ulong)keyid[1], lid, uidhash[18],
3043                            uidhash[19], (ulong)sig->keyid[1],
3044                                 revoked? _("Valid certificate revocation")
3045                                        : _("Good certificate") );
3046         newlid = pk_lid;  /* this is the pk of the signature */
3047         newflag = SIGF_CHECKED | SIGF_VALID;
3048         if( revoked )
3049             newflag |= SIGF_REVOKED;
3050     }
3051     else if( rc == G10ERR_NO_PUBKEY ) {
3052         if( opt.verbose > 1 )
3053             log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
3054                      (ulong)keyid[1], lid, uidhash[18],
3055                       uidhash[19], (ulong)sig->keyid[1], g10_errstr(rc) );
3056         newlid = create_shadow_dir( sig, lid );
3057         newflag = SIGF_NOPUBKEY;
3058         if( revoked )
3059             newflag |= SIGF_REVOKED;
3060     }
3061     else {
3062         log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
3063                     (ulong)keyid[1], lid, uidhash[18], uidhash[19],
3064                               (ulong)sig->keyid[1],
3065                 revoked? _("Invalid certificate revocation")
3066                        : _("Invalid certificate"),
3067                                             g10_errstr(rc));
3068         newlid = create_shadow_dir( sig, lid );
3069         newflag = SIGF_CHECKED;
3070         if( revoked )
3071             newflag |= SIGF_REVOKED;
3072     }
3073
3074     if( delrec.recnum ) { /* we can reuse a deleted/unused slot */
3075         delrec.r.sig.sig[delrecidx].lid = newlid;
3076         delrec.r.sig.sig[delrecidx].flag= newflag;
3077         write_record( &delrec );
3078     }
3079     else { /* must insert a new sig record */
3080         TRUSTREC tmp;
3081
3082         memset( &tmp, 0, sizeof tmp );
3083         tmp.recnum = tdbio_new_recnum();
3084         tmp.rectype = RECTYPE_SIG;
3085         tmp.r.sig.lid = lid;
3086         tmp.r.sig.next = urec->r.uid.siglist;
3087         tmp.r.sig.sig[0].lid = newlid;
3088         tmp.r.sig.sig[0].flag= newflag;
3089         write_record( &tmp );
3090         urec->r.uid.siglist = tmp.recnum;
3091         urec->dirty = 1;
3092     }
3093 }
3094
3095
3096 /****************
3097  * Update all the info from the public keyblock.
3098  * The key must already exist in the keydb.
3099  * This function is responsible for checking the signatures in cases
3100  * where the public key is already available.  If we do not have the public
3101  * key, the check is done by some special code in insert_trust_record().
3102  */
3103 int
3104 update_trust_record( KBNODE keyblock, int recheck, int *modified )
3105 {
3106     PKT_public_key *primary_pk;
3107     KBNODE node;
3108     TRUSTREC drec;
3109     TRUSTREC krec;
3110     TRUSTREC urec;
3111     TRUSTREC prec;
3112     TRUSTREC helprec;
3113     int rc = 0;
3114     u32 keyid[2]; /* keyid of primary key */
3115     ulong recno, lastrecno;
3116     RECNO_LIST recno_list = NULL; /* list of verified records */
3117     /* fixme: replace recno_list by a lookup on node->recno */
3118
3119     if( opt.dry_run )
3120         return 0;
3121
3122     INIT_TRUSTDB();
3123     if( modified )
3124         *modified = 0;
3125
3126     node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
3127     primary_pk = node->pkt->pkt.public_key;
3128     rc = get_dir_record( primary_pk, &drec );
3129     if( rc )
3130         return rc;
3131     if( !primary_pk->local_id )
3132         primary_pk->local_id = drec.recnum;
3133
3134     keyid_from_pk( primary_pk, keyid );
3135
3136     /* fixme: check that the keyblock has a valid structure */
3137
3138     rc = tdbio_begin_transaction();
3139     if( rc )
3140         return rc;
3141
3142     /* update the keys */
3143     for( node=keyblock; node; node = node->next ) {
3144         if( node->pkt->pkttype == PKT_PUBLIC_KEY
3145             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
3146             upd_key_record( keyblock, node, keyid,
3147                             &drec, &recno_list, recheck );
3148     }
3149     /* update the user IDs */
3150     for( node=keyblock; node; node = node->next ) {
3151         if( node->pkt->pkttype == PKT_USER_ID )
3152             upd_uid_record( keyblock, node, keyid,
3153                             &drec, &recno_list, recheck );
3154     }
3155
3156     /* delete keyrecords from the trustdb which are not anymore used */
3157     /* should we really do this, or is it better to keep them and */
3158     /* mark as unused? */
3159     /* And set the revocation flag into the dir record */
3160     drec.r.dir.dirflags &= ~DIRF_REVOKED;
3161     lastrecno = 0;
3162     for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) {
3163         read_record( recno, &krec, RECTYPE_KEY );
3164         if( recno == drec.r.dir.keylist ) { /* this is the primary key */
3165             if( (krec.r.key.keyflags & KEYF_REVOKED) ) {
3166                 drec.r.dir.dirflags |= DIRF_REVOKED;
3167                 drec.dirty = 1;
3168             }
3169         }
3170
3171         if( !qry_recno_list( recno_list, recno, RECTYPE_KEY ) ) {
3172             /* delete this one */
3173             if( !lastrecno ) {
3174                 drec.r.dir.keylist = krec.r.key.next;
3175                 drec.dirty = 1;
3176             }
3177             else {
3178                 read_record( lastrecno, &helprec, RECTYPE_KEY );
3179                 helprec.r.key.next = krec.r.key.next;
3180                 write_record( &helprec );
3181             }
3182             delete_record( recno );
3183         }
3184         else
3185             lastrecno = recno;
3186     }
3187     /* delete uid records and sig and their pref records from the
3188      * trustdb which are not anymore used */
3189     lastrecno = 0;
3190     for( recno=drec.r.dir.uidlist; recno; recno = urec.r.uid.next ) {
3191         read_record( recno, &urec, RECTYPE_UID );
3192         if( !qry_recno_list( recno_list, recno, RECTYPE_UID ) ) {
3193             ulong r2;
3194             /* delete this one */
3195             if( !lastrecno ) {
3196                 drec.r.dir.uidlist = urec.r.uid.next;
3197                 drec.dirty = 1;
3198             }
3199             else {
3200                 read_record( lastrecno, &helprec, RECTYPE_UID );
3201                 helprec.r.uid.next = urec.r.uid.next;
3202                 write_record( &helprec );
3203             }
3204             for(r2=urec.r.uid.prefrec ; r2; r2 = prec.r.pref.next ) {
3205                 read_record( r2, &prec, RECTYPE_PREF );
3206                 delete_record( r2 );
3207             }
3208             for(r2=urec.r.uid.siglist ; r2; r2 = helprec.r.sig.next ) {
3209                 read_record( r2, &helprec, RECTYPE_SIG );
3210                 delete_record( r2 );
3211             }
3212             delete_record( recno );
3213         }
3214         else
3215             lastrecno = recno;
3216     }
3217
3218
3219
3220     if( rc )
3221         rc = tdbio_cancel_transaction();
3222     else {
3223         if( modified && tdbio_is_dirty() )
3224             *modified = 1;
3225         drec.r.dir.dirflags |= DIRF_CHECKED;
3226         drec.r.dir.dirflags &= ~DIRF_VALVALID;
3227         write_record( &drec );
3228         rc = tdbio_end_transaction();
3229     }
3230     rel_recno_list( &recno_list );
3231     return rc;
3232 }
3233
3234
3235 /****************
3236  * Insert a trust record into the TrustDB
3237  * This function assumes that the record does not yet exist.
3238  */
3239 int
3240 insert_trust_record( PKT_public_key *pk )
3241 {
3242     TRUSTREC dirrec;
3243     TRUSTREC shadow;
3244     KBNODE keyblock = NULL;
3245     KBNODE node;
3246     byte fingerprint[MAX_FINGERPRINT_LEN];
3247     size_t fingerlen;
3248     int rc = 0;
3249     ulong hintlist = 0;
3250
3251
3252     if( opt.dry_run )
3253         return 0;
3254
3255     INIT_TRUSTDB();
3256
3257     if( pk->local_id )
3258         log_bug("pk->local_id=%lu\n", pk->local_id );
3259
3260     fingerprint_from_pk( pk, fingerprint, &fingerlen );
3261
3262     /* fixme: assert that we do not have this record.
3263      * we can do this by searching for the primary keyid
3264      *
3265      * fixme: If there is no such key we should look whether one
3266      * of the subkeys has been used to sign another key and in this case
3267      * we got the key anyway.  Because a secondary key can't be used
3268      * without a primary key (it is needed to bind the secondary one
3269      * to the primary one which has the user ids etc.)
3270      */
3271
3272     /* get the keyblock which has the key */
3273     rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
3274     if( rc ) { /* that should never happen */
3275         log_error( _("insert_trust_record: keyblock not found: %s\n"),
3276                                                           g10_errstr(rc) );
3277         goto leave;
3278     }
3279
3280     /* check that we used the primary key (we are little bit paranoid) */
3281     {   PKT_public_key *a_pk;
3282         u32 akid[2], bkid[2];
3283
3284         node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
3285         a_pk = node->pkt->pkt.public_key;
3286
3287         /* we can't use cmp_public_keys here because some parts (expiredate)
3288          * might not be set in pk <--- but why (fixme) */
3289         keyid_from_pk( a_pk, akid );
3290         keyid_from_pk( pk, bkid );
3291
3292         if( akid[0] != bkid[0] || akid[1] != bkid[1] ) {
3293             log_error(_("did not use primary key for insert_trust_record()\n"));
3294             rc = G10ERR_GENERAL;
3295             goto leave;
3296         }
3297     }
3298
3299     /* We have to look for a shadow dir record which must be reused
3300      * as the dir record. And: check all signatures which are listed
3301      * in the hintlist of the shadow dir record.
3302      */
3303     rc = tdbio_search_sdir( pk->keyid, pk->pubkey_algo, &shadow );
3304     if( rc && rc != -1 ) {
3305         log_error(_("tdbio_search_dir failed: %s\n"), g10_errstr(rc));
3306         die_invalid_db();
3307     }
3308     memset( &dirrec, 0, sizeof dirrec );
3309     dirrec.rectype = RECTYPE_DIR;
3310     if( !rc ) {
3311         /* hey, great: this key has already signed other keys
3312          * convert this to a real directory entry */
3313         hintlist = shadow.r.sdir.hintlist;
3314         dirrec.recnum = shadow.recnum;
3315     }
3316     else {
3317         dirrec.recnum = tdbio_new_recnum();
3318     }
3319     dirrec.r.dir.lid = dirrec.recnum;
3320     write_record( &dirrec );
3321
3322     /* store the LID */
3323     pk->local_id = dirrec.r.dir.lid;
3324     for( node=keyblock; node; node = node->next ) {
3325         if( node->pkt->pkttype == PKT_PUBLIC_KEY
3326             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
3327             PKT_public_key *a_pk = node->pkt->pkt.public_key;
3328             a_pk->local_id = dirrec.r.dir.lid;
3329         }
3330         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
3331             PKT_signature *a_sig = node->pkt->pkt.signature;
3332             a_sig->local_id = dirrec.r.dir.lid;
3333         }
3334     }
3335
3336     /* and put all the other stuff into the keydb */
3337     rc = update_trust_record( keyblock, 1, NULL );
3338     if( !rc )
3339         process_hintlist( hintlist, dirrec.r.dir.lid );
3340
3341   leave:
3342     if( rc && hintlist )
3343         ; /* fixme: the hintlist is not anymore anchored */
3344     release_kbnode( keyblock );
3345     do_sync();
3346     return rc;
3347 }
3348
3349
3350 int
3351 update_ownertrust( ulong lid, unsigned new_trust )
3352 {
3353     TRUSTREC rec;
3354
3355     INIT_TRUSTDB();
3356     read_record( lid, &rec, RECTYPE_DIR );
3357     rec.r.dir.ownertrust = new_trust;
3358     write_record( &rec );
3359     do_sync();
3360     return 0;
3361 }
3362
3363