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