auf tobold
[gnupg.git] / g10 / trustdb.c
1 /* trustdb.c
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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 <unistd.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <fcntl.h>
29
30 #include "errors.h"
31 #include "iobuf.h"
32 #include "keydb.h"
33 #include "memory.h"
34 #include "util.h"
35 #include "trustdb.h"
36 #include "options.h"
37 #include "packet.h"
38 #include "main.h"
39
40
41 #define TRUST_RECORD_LEN 40
42 #define SIGS_PER_RECORD         ((TRUST_RECORD_LEN-10)/5)
43 #define ITEMS_PER_HTBL_RECORD   ((TRUST_RECORD_LEN-2)/4)
44 #define ITEMS_PER_HLST_RECORD   ((TRUST_RECORD_LEN-6)/5)
45 #define MAX_LIST_SIGS_DEPTH  20
46
47
48 #define RECTYPE_VER  1
49 #define RECTYPE_DIR  2
50 #define RECTYPE_KEY  3
51 #define RECTYPE_CTL  4
52 #define RECTYPE_SIG  5
53 #define RECTYPE_HTBL 6
54 #define RECTYPE_HLST 7
55
56
57 struct trust_record {
58     int  rectype;
59     union {
60         struct {            /* version record: */
61             byte version;   /* should be 1 */
62             ulong locked;    /* pid of process which holds a lock */
63             ulong created;   /* timestamp of trustdb creation  */
64             ulong modified;  /* timestamp of last modification */
65             ulong validated; /* timestamp of last validation   */
66             byte marginals_needed;
67             byte completes_needed;
68             byte max_cert_depth;
69         } ver;
70         struct {            /* directory record */
71             ulong local_id;
72             u32  keyid[2];
73             ulong keyrec;   /* recno of public key record */
74             ulong ctlrec;   /* recno of control record */
75             ulong sigrec;   /* recno of first signature record */
76             ulong link;     /* to next dir record */
77             byte no_sigs;   /* does not have sigature and checked */
78         } dir;
79         struct {            /* public key record */
80             ulong owner;
81             u32  keyid[2];
82             byte pubkey_algo;
83             byte fingerprint[20];
84             byte ownertrust;
85         } key;
86         struct {            /* control record */
87             ulong owner;
88             byte blockhash[20];
89             byte trustlevel;   /* calculated trustlevel */
90         } ctl;
91         struct {            /* signature record */
92             ulong owner;  /* local_id of record owner (pubkey record) */
93             ulong chain;  /* offset of next record or NULL for last one */
94             struct {
95                 ulong  local_id; /* of pubkey record of signator (0=unused) */
96                 byte flag;     /* reserved */
97             } sig[SIGS_PER_RECORD];
98         } sig;
99         struct {
100             ulong item[ITEMS_PER_HTBL_RECORD];
101         } htbl;
102         struct {
103             ulong chain;
104             struct {
105                 byte hash;
106                 ulong rnum;
107             } item[ITEMS_PER_HLST_RECORD];
108         } hlst;
109     } r;
110 };
111 typedef struct trust_record TRUSTREC;
112
113 typedef struct {
114     ulong     local_id;    /* localid of the pubkey */
115     ulong     sigrec;
116     ulong     sig_id;      /* returned signature id */
117     unsigned  sig_flag;    /* returned signature record flag */
118     struct {               /* internal data */
119         int init_done;
120         int eof;
121         TRUSTREC rec;
122         int index;
123     } ctl;
124 } SIGREC_CONTEXT;
125
126 typedef struct local_id_info *LOCAL_ID_INFO;
127 struct local_id_info {
128     LOCAL_ID_INFO next;
129     ulong lid;
130     unsigned flag;
131 };
132
133
134 typedef struct trust_info TRUST_INFO;
135 struct trust_info {
136     ulong    lid;
137     unsigned trust;
138 };
139
140
141 typedef struct trust_seg_list *TRUST_SEG_LIST;
142 struct trust_seg_list {
143     TRUST_SEG_LIST next;
144     int   nseg;     /* number of segmens */
145     int   dup;
146     TRUST_INFO seg[1];   /* segment list */
147 };
148
149
150 typedef struct {
151     TRUST_SEG_LIST tsl;
152     int index;
153 } ENUM_TRUST_WEB_CONTEXT;
154
155
156 static void create_db( const char *fname );
157 static void open_db(void);
158 static void dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
159 static int  read_record( ulong recnum, TRUSTREC *rec, int expected );
160 static int  write_record( ulong recnum, TRUSTREC *rec );
161 static ulong new_recnum(void);
162 static int search_record( PKT_public_cert *pkc, TRUSTREC *rec );
163 static int walk_sigrecs( SIGREC_CONTEXT *c, int create );
164
165 static LOCAL_ID_INFO *new_lid_table(void);
166 static void release_lid_table( LOCAL_ID_INFO *tbl );
167 static int ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
168 static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag );
169 static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
170
171 static void print_user_id( const char *text, u32 *keyid );
172 static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
173                          LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
174
175 static int list_sigs( ulong pubkey_id );
176 static int build_sigrecs( ulong pubkeyid );
177 static int propagate_trust( TRUST_SEG_LIST tslist );
178 static int do_check( ulong pubkeyid, TRUSTREC *drec, unsigned *trustlevel );
179
180 static int update_no_sigs( ulong lid, int no_sigs );
181
182 static char *db_name;
183 static int  db_fd = -1;
184 /* a table used to keep track of ultimately trusted keys
185  * which are the ones from our secrings */
186 static LOCAL_ID_INFO *ultikey_table;
187
188 static ulong last_trust_web_key;
189 static TRUST_SEG_LIST last_trust_web_tslist;
190
191 #define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
192                        (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
193 #define buftoushort( p )  ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
194 #define ulongtobuf( p, a ) do {                           \
195                             ((byte*)p)[0] = a >> 24;    \
196                             ((byte*)p)[1] = a >> 16;    \
197                             ((byte*)p)[2] = a >>  8;    \
198                             ((byte*)p)[3] = a      ;    \
199                         } while(0)
200 #define ushorttobuf( p, a ) do {                           \
201                             ((byte*)p)[0] = a >>  8;    \
202                             ((byte*)p)[1] = a      ;    \
203                         } while(0)
204 #define buftou32( p)    buftoulong( (p) )
205 #define u32tobuf( p, a) ulongtobuf( (p), (a) )
206
207
208 /**************************************************
209  ************** read and write helpers ************
210  **************************************************/
211
212 static void
213 fwrite_8(FILE *fp, byte a)
214 {
215     if( putc( a & 0xff, fp ) == EOF )
216         log_fatal("error writing byte to trustdb: %s\n", strerror(errno) );
217 }
218
219
220 static void
221 fwrite_32( FILE*fp, ulong a)
222 {
223     putc( (a>>24) & 0xff, fp );
224     putc( (a>>16) & 0xff, fp );
225     putc( (a>> 8) & 0xff, fp );
226     if( putc( a & 0xff, fp ) == EOF )
227         log_fatal("error writing ulong to trustdb: %s\n", strerror(errno) );
228 }
229
230 static void
231 fwrite_zeros( FILE *fp, size_t n)
232 {
233     while( n-- )
234         if( putc( 0, fp ) == EOF )
235             log_fatal("error writing zeros to trustdb: %s\n", strerror(errno) );
236 }
237
238
239 /**********************************************
240  ************* list helpers *******************
241  **********************************************/
242
243 static LOCAL_ID_INFO *
244 new_lid_table(void)
245 {
246     return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO));
247 }
248
249 static void
250 release_lid_table( LOCAL_ID_INFO *tbl )
251 {
252     LOCAL_ID_INFO a, a2;
253     int i;
254
255     for(i=0; i < 16; i++ ) {
256         for(a=tbl[i]; a; a = a2 ) {
257             a2 = a->next;
258             m_free(a);
259         }
260     }
261     m_free(tbl);
262 }
263
264 /****************
265  * Add a new item to the table or return 1 if we already have this item
266  * fixme: maybe its a good idea to take items from an unused item list.
267  */
268 static int
269 ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
270 {
271     LOCAL_ID_INFO a;
272
273     for( a = tbl[lid & 0x0f]; a; a = a->next )
274         if( a->lid == lid )
275             return 1;
276     a = m_alloc( sizeof *a );
277     a->lid = lid;
278     a->flag = flag;
279     a->next = tbl[lid & 0x0f];
280     tbl[lid & 0x0f] = a;
281     return 0;
282 }
283
284 static int
285 qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag )
286 {
287     LOCAL_ID_INFO a;
288
289     for( a = tbl[lid & 0x0f]; a; a = a->next )
290         if( a->lid == lid ) {
291             if( flag )
292                 *flag = a->flag;
293             return 0;
294         }
295     return -1;
296 }
297
298 static void
299 upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
300 {
301     LOCAL_ID_INFO a;
302
303     for( a = tbl[lid & 0x0f]; a; a = a->next )
304         if( a->lid == lid ) {
305             a->flag = flag;
306             return;
307         }
308     BUG();
309 }
310
311
312 /**************************************************
313  ************** read and write stuff **************
314  **************************************************/
315
316
317 /****************
318  * Create a new trustdb
319  */
320 static void
321 create_db( const char *fname )
322 {
323     FILE *fp;
324
325     fp =fopen( fname, "w" );
326     if( !fp )
327         log_fatal("can't create %s: %s\n", fname, strerror(errno) );
328     fwrite_8( fp, 1 );
329     fwrite_8( fp, 'g' );
330     fwrite_8( fp, '1' );
331     fwrite_8( fp, '0' );
332     fwrite_8( fp, 1 );  /* version */
333     fwrite_zeros( fp, 3 ); /* reserved */
334     fwrite_32( fp, 0 ); /* not locked */
335     fwrite_32( fp, make_timestamp() ); /* created */
336     fwrite_32( fp, 0 ); /* not yet modified */
337     fwrite_32( fp, 0 ); /* not yet validated*/
338     fwrite_32( fp, 0 ); /* reserved */
339     fwrite_8( fp, 3 );  /* marginals needed */
340     fwrite_8( fp, 1 );  /* completes needed */
341     fwrite_8( fp, 4 );  /* max_cet_depth */
342     fwrite_zeros( fp, 9 ); /* filler */
343     fclose(fp);
344 }
345
346 static void
347 open_db()
348 {
349     TRUSTREC rec;
350     assert( db_fd == -1 );
351
352     db_fd = open( db_name, O_RDWR );
353     if( db_fd == -1 )
354         log_fatal("can't open %s: %s\n", db_name, strerror(errno) );
355     if( read_record( 0, &rec, RECTYPE_VER ) )
356         log_fatal("TrustDB %s is invalid\n", db_name );
357     /* fixme: check ->locked and other stuff */
358 }
359
360
361 static void
362 dump_record( ulong rnum, TRUSTREC *rec, FILE *fp  )
363 {
364     int i, any;
365
366     fprintf(fp, "trust record %lu, type=", rnum );
367
368     switch( rec->rectype ) {
369       case 0: fprintf(fp, "free\n");
370         break;
371       case RECTYPE_VER: fprintf(fp, "version\n");
372         break;
373       case RECTYPE_DIR:
374         fprintf(fp, "dir keyid=%08lx, key=%lu, ctl=%lu, sig=%lu%s\n",
375                     rec->r.dir.keyid[1],
376                     rec->r.dir.keyrec, rec->r.dir.ctlrec, rec->r.dir.sigrec,
377                     rec->r.dir.no_sigs?"  (inv sigs)":"");
378         break;
379       case RECTYPE_KEY: fprintf(fp, "key keyid=%08lx, own=%lu, ownertrust=%02x\n",
380                    rec->r.key.keyid[1],
381                    rec->r.key.owner, rec->r.key.ownertrust );
382         break;
383       case RECTYPE_CTL: fprintf(fp, "ctl\n");
384         break;
385       case RECTYPE_SIG:
386         fprintf(fp, "sigrec, owner=%lu, chain=%lu\n",
387                          rec->r.sig.owner, rec->r.sig.chain );
388         for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
389             if( rec->r.sig.sig[i].local_id ) {
390                 if( !any ) {
391                     putc('\t', fp);
392                     any++;
393                 }
394                 fprintf(fp, "  %lu:%02x", rec->r.sig.sig[i].local_id,
395                                               rec->r.sig.sig[i].flag );
396             }
397         }
398         if( any )
399             putc('\n', fp);
400         break;
401       default:
402         fprintf(fp, "%d (unknown)\n", rec->rectype );
403         break;
404     }
405 }
406
407 /****************
408  * read the record with number recnum
409  * returns: -1 on error, 0 on success
410  */
411 static int
412 read_record( ulong recnum, TRUSTREC *rec, int expected )
413 {
414     byte buf[TRUST_RECORD_LEN], *p;
415     int rc = 0;
416     int n, i;
417
418     if( db_fd == -1 )
419         open_db();
420     if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
421         log_error("trustdb: lseek failed: %s\n", strerror(errno) );
422         return G10ERR_READ_FILE;
423     }
424     n = read( db_fd, buf, TRUST_RECORD_LEN);
425     if( !n ) {
426         return -1; /* eof */
427     }
428     else if( n != TRUST_RECORD_LEN ) {
429         log_error("trustdb: read failed (n=%d): %s\n", n, strerror(errno) );
430         return G10ERR_READ_FILE;
431     }
432     p = buf;
433     rec->rectype = *p++;
434     if( expected && rec->rectype != expected ) {
435         log_error("%lu: read expected rec type %d, got %d\n",
436                     recnum, expected, rec->rectype );
437         return G10ERR_TRUSTDB;
438     }
439     p++;
440     switch( rec->rectype ) {
441       case 0:  /* unused record */
442         break;
443       case RECTYPE_VER: /* version record */
444         if( memcmp(buf+1, "g10", 3 ) ) {
445             log_error("%s: not a trustdb file\n", db_name );
446             rc = G10ERR_TRUSTDB;
447         }
448         p += 2; /* skip magic */
449         rec->r.ver.version  = *p++;
450         rec->r.ver.locked   = buftoulong(p); p += 4;
451         rec->r.ver.created  = buftoulong(p); p += 4;
452         rec->r.ver.modified = buftoulong(p); p += 4;
453         rec->r.ver.validated= buftoulong(p); p += 4;
454         rec->r.ver.marginals_needed = *p++;
455         rec->r.ver.completes_needed = *p++;
456         rec->r.ver.max_cert_depth = *p++;
457         if( recnum ) {
458             log_error("%s: version record with recnum %lu\n",
459                                                     db_name, (ulong)recnum );
460             rc = G10ERR_TRUSTDB;
461         }
462         if( rec->r.ver.version != 1 ) {
463             log_error("%s: invalid file version %d\n",
464                                        db_name, rec->r.ver.version );
465             rc = G10ERR_TRUSTDB;
466         }
467         break;
468       case RECTYPE_DIR:   /*directory record */
469         rec->r.dir.local_id = buftoulong(p); p += 4;
470         rec->r.dir.keyid[0] = buftou32(p); p += 4;
471         rec->r.dir.keyid[1] = buftou32(p); p += 4;
472         rec->r.dir.keyrec   = buftoulong(p); p += 4;
473         rec->r.dir.ctlrec   = buftoulong(p); p += 4;
474         rec->r.dir.sigrec   = buftoulong(p); p += 4;
475         rec->r.dir.no_sigs = *p++;
476         if( rec->r.dir.local_id != recnum ) {
477             log_error("%s: dir local_id != recnum (%lu,%lu)\n",
478                                         db_name,
479                                         (ulong)rec->r.dir.local_id,
480                                         (ulong)recnum );
481             rc = G10ERR_TRUSTDB;
482         }
483         break;
484       case RECTYPE_KEY:   /* public key record */
485         rec->r.key.owner    = buftoulong(p); p += 4;
486         rec->r.dir.keyid[0] = buftou32(p); p += 4;
487         rec->r.dir.keyid[1] = buftou32(p); p += 4;
488         rec->r.key.pubkey_algo = *p++; p++;
489         memcpy( rec->r.key.fingerprint, p, 20); p += 20;
490         rec->r.key.ownertrust = *p++;
491         break;
492       case RECTYPE_CTL:   /* control record */
493         rec->r.ctl.owner    = buftoulong(p); p += 4;
494         memcpy(rec->r.ctl.blockhash, p, 20); p += 20;
495         rec->r.ctl.trustlevel = *p++;
496         break;
497       case RECTYPE_SIG:
498         rec->r.sig.owner   = buftoulong(p); p += 4;
499         rec->r.sig.chain   = buftoulong(p); p += 4;
500         for(i=0; i < SIGS_PER_RECORD; i++ ) {
501             rec->r.sig.sig[i].local_id = buftoulong(p); p += 4;
502             rec->r.sig.sig[i].flag = *p++;
503         }
504         break;
505       default:
506         log_error("%s: invalid record type %d at recnum %lu\n",
507                                         db_name, rec->rectype, (ulong)recnum );
508         rc = G10ERR_TRUSTDB;
509         break;
510     }
511
512     return rc;
513 }
514
515 /****************
516  * Write the record at RECNUM
517  */
518 static int
519 write_record( ulong recnum, TRUSTREC *rec )
520 {
521     byte buf[TRUST_RECORD_LEN], *p;
522     int rc = 0;
523     int i, n;
524
525     if( db_fd == -1 )
526         open_db();
527
528     memset(buf, 0, TRUST_RECORD_LEN);
529     p = buf;
530     *p++ = rec->rectype; p++;
531     switch( rec->rectype ) {
532       case 0:  /* unused record */
533         break;
534       case 1: /* version record */
535         BUG();
536         break;
537
538       case RECTYPE_DIR:   /*directory record */
539         ulongtobuf(p, rec->r.dir.local_id); p += 4;
540         u32tobuf(p, rec->r.key.keyid[0]); p += 4;
541         u32tobuf(p, rec->r.key.keyid[1]); p += 4;
542         ulongtobuf(p, rec->r.dir.keyrec); p += 4;
543         ulongtobuf(p, rec->r.dir.ctlrec); p += 4;
544         ulongtobuf(p, rec->r.dir.sigrec); p += 4;
545         *p++ = rec->r.dir.no_sigs;
546         assert( rec->r.dir.local_id == recnum );
547         break;
548
549       case RECTYPE_KEY:
550         ulongtobuf(p, rec->r.key.owner); p += 4;
551         u32tobuf(p, rec->r.key.keyid[0]); p += 4;
552         u32tobuf(p, rec->r.key.keyid[1]); p += 4;
553         *p++ = rec->r.key.pubkey_algo; p++;
554         memcpy( p, rec->r.key.fingerprint, 20); p += 20;
555         *p++ = rec->r.key.ownertrust;
556         break;
557
558       case RECTYPE_CTL:   /* control record */
559         ulongtobuf(p, rec->r.ctl.owner); p += 4;
560         memcpy(p, rec->r.ctl.blockhash, 20); p += 20;
561         *p++ = rec->r.ctl.trustlevel;
562         break;
563
564       case RECTYPE_SIG:
565         ulongtobuf(p, rec->r.sig.owner); p += 4;
566         ulongtobuf(p, rec->r.sig.chain); p += 4;
567         for(i=0; i < SIGS_PER_RECORD; i++ ) {
568             ulongtobuf(p, rec->r.sig.sig[i].local_id); p += 4;
569             *p++ = rec->r.sig.sig[i].flag;
570         }
571         break;
572       default:
573         BUG();
574     }
575
576     if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
577         log_error("trustdb: lseek failed: %s\n", strerror(errno) );
578         return G10ERR_WRITE_FILE;
579     }
580     n = write( db_fd, buf, TRUST_RECORD_LEN);
581     if( n != TRUST_RECORD_LEN ) {
582         log_error("trustdb: write failed (n=%d): %s\n", n, strerror(errno) );
583         return G10ERR_WRITE_FILE;
584     }
585
586     return rc;
587 }
588
589
590 /****************
591  * create a new record and return its record number
592  */
593 static ulong
594 new_recnum()
595 {
596     off_t offset;
597     ulong recnum;
598     TRUSTREC rec;
599     int rc;
600
601     /* fixme: look for unused records */
602     offset = lseek( db_fd, 0, SEEK_END );
603     if( offset == -1 )
604         log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
605     recnum = offset / TRUST_RECORD_LEN;
606     assert(recnum); /* this is will never be the first record */
607
608     /* we must write a record, so that the next call to this function
609      * returns another recnum */
610     memset( &rec, 0, sizeof rec );
611     rec.rectype = 0; /* free record */
612     rc = write_record(recnum, &rec );
613     if( rc )
614         log_fatal("%s: failed to append a record: %s\n",
615                                             db_name, g10_errstr(rc));
616     return recnum ;
617 }
618
619 /****************
620  * Search the trustdb for a key which matches PKC and return the dir record
621  * The local_id of PKC is set to the correct value
622  *
623  * Note: To increase performance, we could use a index search here.
624  */
625 static int
626 search_record( PKT_public_cert *pkc, TRUSTREC *rec )
627 {
628     ulong recnum;
629     u32 keyid[2];
630     byte *fingerprint;
631     size_t fingerlen;
632     int rc;
633
634     keyid_from_pkc( pkc, keyid );
635     fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
636     assert( fingerlen == 20 || fingerlen == 16 );
637
638     for(recnum=1; !(rc=read_record( recnum, rec, 0)); recnum++ ) {
639         if( rec->rectype != RECTYPE_DIR )
640             continue;
641         if( rec->r.dir.keyid[0] == keyid[0]
642             && rec->r.dir.keyid[1] == keyid[1]){
643             TRUSTREC keyrec;
644
645             if( read_record( rec->r.dir.keyrec, &keyrec, RECTYPE_KEY ) ) {
646                 log_error("%lu: ooops: invalid dir record\n", recnum );
647                 break;
648             }
649             if( keyrec.r.key.pubkey_algo == pkc->pubkey_algo
650                 && !memcmp(keyrec.r.key.fingerprint, fingerprint, fingerlen) ){
651                 if( pkc->local_id && pkc->local_id != recnum )
652                     log_error("%s: found record, but local_id from mem does "
653                                "not match recnum (%lu,%lu)\n", db_name,
654                                      (ulong)pkc->local_id, (ulong)recnum );
655                 pkc->local_id = recnum;
656                 return 0;
657             }
658         }
659     }
660     if( rc != -1 )
661         log_error("%s: search_db failed: %s\n",db_name, g10_errstr(rc) );
662     return rc;
663 }
664
665
666 /****************
667  * If we do not have a local_id in a signature packet, find the owner of
668  * the signature packet in our trustdb or insert him into the trustdb
669  */
670 static int
671 set_signature_packets_local_id( PKT_signature *sig )
672 {
673     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
674     TRUSTREC rec;
675     int rc;
676
677     rc = get_pubkey( pkc, sig->keyid );
678     if( rc)
679         goto leave;
680     if( !pkc->local_id ) {
681         rc = search_record( pkc, &rec );
682         if( rc == -1 )
683             rc = insert_trust_record( pkc );
684         if( rc )
685             goto leave;
686         /* fixme: we should propagate the local_id to all copies of the PKC */
687     }
688     sig->local_id = pkc->local_id;
689
690   leave:
691     free_public_cert( pkc );
692     return rc;
693 }
694
695
696
697 static int
698 keyid_from_local_id( ulong lid, u32 *keyid )
699 {
700     TRUSTREC rec;
701     int rc;
702
703     rc = read_record( lid, &rec, RECTYPE_DIR );
704     if( rc ) {
705         log_error("error reading record with local_id %lu: %s\n",
706                                                     lid, g10_errstr(rc));
707         return G10ERR_TRUSTDB;
708     }
709     if( rec.rectype != RECTYPE_DIR ) {
710         log_error("record with local_id %lu is not a dir record\n", lid);
711         return G10ERR_TRUSTDB;
712     }
713     keyid[0] = rec.r.dir.keyid[0];
714     keyid[1] = rec.r.dir.keyid[1];
715     return 0;
716 }
717
718 /****************
719  * Walk throug the signatures of a public key.
720  * The caller must provide a context structure, with all fields set
721  * to zero, but the local_id field set to the requested key;
722  * This function does not change this field.  On return the context
723  * is filled with the local-id of the signature and the signature flag.
724  * No fields should be changed (clearing all fields and setting
725  * pubkeyid is okay to continue with an other pubkey)
726  * Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
727  */
728 static int
729 walk_sigrecs( SIGREC_CONTEXT *c, int create )
730 {
731     int rc=0;
732     TRUSTREC *r;
733     ulong rnum;
734
735     if( c->ctl.eof )
736         return -1;
737     r = &c->ctl.rec;
738     if( !c->ctl.init_done ) {
739         c->ctl.init_done = 1;
740         if( !c->sigrec ) {
741             rc = read_record( c->local_id, r, RECTYPE_DIR );
742             if( rc ) {
743                 log_error("%lu: error reading dir record: %s\n",
744                                         c->local_id, g10_errstr(rc));
745                 return rc;
746             }
747             c->sigrec = r->r.dir.sigrec;
748             if( !c->sigrec && create && !r->r.dir.no_sigs ) {
749                 rc = build_sigrecs( c->local_id );
750                 if( rc ) {
751                     if( rc != -1 )
752                         log_info("%lu: error building sigs on the fly: %s\n",
753                                c->local_id, g10_errstr(rc) );
754                     c->ctl.eof = 1;
755                     return rc;
756                 }
757                 rc = read_record( c->local_id, r, RECTYPE_DIR );
758                 if( rc ) {
759                     log_error("%lu: error re-reading dir record: %s\n",
760                                             c->local_id, g10_errstr(rc));
761                     return rc;
762                 }
763                 c->sigrec = r->r.dir.sigrec;
764             }
765             if( !c->sigrec ) {
766                 c->ctl.eof = 1;
767                 return -1;
768             }
769         }
770         /* force a read */
771         c->ctl.index = SIGS_PER_RECORD;
772         r->r.sig.chain = c->sigrec;
773     }
774
775     /* enter loop to skip deleted sigs */
776     do {
777         if( c->ctl.index >= SIGS_PER_RECORD ) {
778             /* read the record */
779             rnum = r->r.sig.chain;
780             if( !rnum ) {
781                 c->ctl.eof = 1;
782                 return -1;  /* return eof */
783             }
784             rc = read_record( rnum, r, RECTYPE_SIG );
785             if( rc ) {
786                 log_error("error reading sigrec: %s\n", g10_errstr(rc));
787                 c->ctl.eof = 1;
788                 return rc;
789             }
790             if( r->r.sig.owner != c->local_id ) {
791                 log_error("chained sigrec %lu has a wrong owner\n", rnum );
792                 c->ctl.eof = 1;
793                 return G10ERR_TRUSTDB;
794             }
795             c->ctl.index = 0;
796         }
797     } while( !r->r.sig.sig[c->ctl.index++].local_id );
798     c->sig_id = r->r.sig.sig[c->ctl.index-1].local_id;
799     c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
800     return 0;
801 }
802
803
804
805
806 /***********************************************
807  *************  Trust  stuff  ******************
808  ***********************************************/
809
810
811 /****************
812  * Verify, that all our public keys are in the trustDB.
813  */
814 static int
815 verify_own_certs()
816 {
817     int rc;
818     void *enum_context = NULL;
819     PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
820     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
821     u32 keyid[2];
822
823     while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
824         /* fixed: to be sure that it is a secret key of our own,
825          *        we should check it, but this needs a passphrase
826          *        for every key and this boring for the user.
827          *        Solution:  Sign the secring and the trustring
828          *                   and verify this signature during
829          *                   startup
830          */
831
832         keyid_from_skc( skc, keyid );
833
834         if( DBG_TRUST )
835             log_debug("checking secret key %08lX\n", (ulong)keyid[1] );
836
837         /* look wether we can access the public key of this secret key */
838         rc = get_pubkey( pkc, keyid );
839         if( rc ) {
840             log_error("keyid %08lX: secret key without public key\n",
841                                                             (ulong)keyid[1] );
842             goto leave;
843         }
844         if( cmp_public_secret_cert( pkc, skc ) ) {
845             log_error("keyid %08lX: secret and public key don't match\n",
846                                                             (ulong)keyid[1] );
847             rc = G10ERR_GENERAL;
848             goto leave;
849         }
850
851         /* make sure that the pubkey is in the trustdb */
852         rc = query_trust_record( pkc );
853         if( rc == -1 ) { /* put it into the trustdb */
854             rc = insert_trust_record( pkc );
855             if( rc ) {
856                 log_error("keyid %08lX: can't put it into the trustdb\n",
857                                                             (ulong)keyid[1] );
858                 goto leave;
859             }
860         }
861         else if( rc ) {
862             log_error("keyid %08lX: query record failed\n", (ulong)keyid[1] );
863             goto leave;
864
865         }
866
867         if( DBG_TRUST )
868             log_debug("putting %08lX(%lu) into ultikey_table\n",
869                                     (ulong)keyid[1], pkc->local_id );
870         if( ins_lid_table_item( ultikey_table, pkc->local_id, 0 ) )
871             log_error("keyid %08lX: already in ultikey_table\n",
872                                                         (ulong)keyid[1]);
873
874
875         release_secret_cert_parts( skc );
876         release_public_cert_parts( pkc );
877     }
878     if( rc != -1 )
879         log_error("enum_secret_keys failed: %s\n", g10_errstr(rc) );
880     else
881         rc = 0;
882
883   leave:
884     free_secret_cert( skc );
885     free_public_cert( pkc );
886     return rc;
887 }
888
889
890 static void
891 print_user_id( const char *text, u32 *keyid )
892 {
893     char *p;
894     size_t n;
895
896     p = get_user_id( keyid, &n );
897     if( *text ) {
898         fputs( text, stdout);
899         putchar(' ');
900     }
901     putchar('\"');
902     print_string( stdout, p, n );
903     putchar('\"');
904     putchar('\n');
905     m_free(p);
906 }
907
908 /* (a non-recursive algorithm would be easier) */
909 static int
910 do_list_sigs( ulong root, ulong pubkey, int depth,
911               LOCAL_ID_INFO *lids, unsigned *lineno )
912 {
913     SIGREC_CONTEXT sx;
914     int rc;
915     u32 keyid[2];
916
917     memset( &sx, 0, sizeof sx );
918     sx.local_id = pubkey;
919     for(;;) {
920         rc = walk_sigrecs( &sx, 0 );
921         if( rc )
922             break;
923         rc = keyid_from_local_id( sx.sig_id, keyid );
924         if( rc ) {
925             printf("%6u: %*s????????(%lu:%02x)\n", *lineno, depth*4, "",
926                                                    sx.sig_id, sx.sig_flag );
927             ++*lineno;
928         }
929         else {
930             printf("%6u: %*s%08lX(%lu:%02x) ", *lineno, depth*4, "",
931                               (ulong)keyid[1], sx.sig_id, sx.sig_flag );
932             /* check wether we already checked this pubkey */
933             if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
934                 print_user_id("[ultimately trusted]", keyid);
935                 ++*lineno;
936             }
937             else if( sx.sig_id == pubkey ) {
938                 printf("[self-signature]\n");
939                 ++*lineno;
940             }
941             else if( sx.sig_id == root ) {
942                 printf("[closed]\n");
943                 ++*lineno;
944             }
945             else if( ins_lid_table_item( lids, sx.sig_id, *lineno ) ) {
946                 unsigned refline;
947                 qry_lid_table_flag( lids, sx.sig_id, &refline );
948                 printf("[see line %u]\n", refline);
949                 ++*lineno;
950             }
951             else if( depth+1 >= MAX_LIST_SIGS_DEPTH  ) {
952                 print_user_id( "[too deeply nested]", keyid );
953                 ++*lineno;
954             }
955             else {
956                 print_user_id( "", keyid );
957                 ++*lineno;
958                 rc = do_list_sigs( root, sx.sig_id, depth+1, lids, lineno );
959                 if( rc )
960                     break;
961             }
962         }
963     }
964     return rc==-1? 0 : rc;
965 }
966
967 /****************
968  * List all signatures of a public key
969  */
970 static int
971 list_sigs( ulong pubkey_id )
972 {
973     int rc;
974     u32 keyid[2];
975     LOCAL_ID_INFO *lids;
976     unsigned lineno = 1;
977
978     rc = keyid_from_local_id( pubkey_id, keyid );
979     if( rc ) {
980         log_error("Hmmm, no pubkey record for local_id %lu\n", pubkey_id);
981         return rc;
982     }
983     printf("Signatures of %08lX(%lu) ", (ulong)keyid[1], pubkey_id );
984     print_user_id("", keyid);
985     printf("----------------------\n");
986
987     lids = new_lid_table();
988     rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
989     putchar('\n');
990     release_lid_table(lids);
991     return rc;
992 }
993
994
995
996 /****************
997  * Function to collect all trustpaths
998  */
999 static int
1000 do_list_path( TRUST_INFO *stack, int depth, int max_depth,
1001               LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist )
1002 {
1003     SIGREC_CONTEXT sx;
1004     unsigned last_depth;
1005     int rc;
1006
1007     assert(depth);
1008
1009     /*printf("%2lu/%d: scrutinizig\n", stack[depth-1], depth);*/
1010     if( depth >= max_depth || depth >= MAX_LIST_SIGS_DEPTH-1 ) {
1011         /*printf("%2lu/%d: to deeply nested\n", stack[depth-1], depth);*/
1012         return 0;
1013     }
1014     memset( &sx, 0, sizeof sx );
1015     sx.local_id = stack[depth-1].lid;
1016     /* loop over all signatures. If we do not have any, try to
1017      * create them */
1018     while( !(rc = walk_sigrecs( &sx, 1 )) ) {
1019         TRUST_SEG_LIST tsl, t2, tl;
1020         int i;
1021
1022         stack[depth].lid = sx.sig_id;
1023         stack[depth].trust = 0;
1024         if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) {
1025             /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/
1026             ins_lid_table_item( lids, sx.sig_id, depth);
1027             last_depth = depth;
1028         }
1029         else if( depth  < last_depth ) {
1030             /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_id, depth, last_depth);*/
1031             last_depth = depth;
1032             upd_lid_table_flag( lids, sx.sig_id, depth);
1033         }
1034
1035         if( last_depth < depth )
1036             /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/;
1037         else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
1038             /* found end of path; store it, ordered by path length */
1039             tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) );
1040             tsl->nseg = depth+1;
1041             tsl->dup = 0;
1042             for(i=0; i <= depth; i++ )
1043                 tsl->seg[i] = stack[i];
1044             for(t2=*tslist,tl=NULL; t2; tl=t2, t2 = t2->next )
1045                 if( depth < t2->nseg )
1046                     break;
1047             if( !tl ) {
1048                 tsl->next = t2;
1049                 *tslist = tsl;
1050             }
1051             else {
1052                 tsl->next = t2;
1053                 tl->next = tsl;
1054             }
1055             /*putchar('.'); fflush(stdout);*/
1056             /*printf("%2lu/%d: found\n", sx.sig_id, depth);*/
1057         }
1058         else {
1059             rc = do_list_path( stack, depth+1, max_depth, lids, tslist);
1060             if( rc && rc != -1 )
1061                 break;
1062         }
1063     }
1064     return rc==-1? 0 : rc;
1065 }
1066
1067
1068
1069 /****************
1070  * Check all the sigs of the given keyblock and mark them
1071  * as checked. Valid signatures which are duplicates are
1072  * also marked [shall we check them at all?]
1073  * FIXME: what shall we do if we have duplicate signatures were only
1074  *        some of them are bad?
1075  */
1076 static int
1077 check_sigs( KBNODE keyblock, int *selfsig_okay )
1078 {
1079     KBNODE kbctx;
1080     KBNODE node;
1081     int rc;
1082     LOCAL_ID_INFO *dups = NULL;
1083
1084     *selfsig_okay = 0;
1085     for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
1086         if( node->pkt->pkttype == PKT_SIGNATURE
1087             && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
1088             int selfsig;
1089             rc = check_key_signature( keyblock, node, &selfsig );
1090             if( !rc ) {
1091                 if( selfsig ) {
1092                     node->flag |= 2; /* mark signature valid */
1093                     *selfsig_okay = 1;
1094                 }
1095                 else
1096                     node->flag |= 1; /* mark signature valid */
1097                 if( !dups )
1098                     dups = new_lid_table();
1099                 if( ins_lid_table_item( dups,
1100                                     node->pkt->pkt.signature->local_id, 0) )
1101                     node->flag |= 4; /* mark as duplicate */
1102             }
1103             if( DBG_TRUST )
1104                 log_debug("trustdb: sig from %08lX: %s\n",
1105                                 (ulong)node->pkt->pkt.signature->keyid[1],
1106                                                     g10_errstr(rc) );
1107         }
1108     }
1109     if( dups )
1110         release_lid_table(dups);
1111     return 0;
1112 }
1113
1114
1115 /****************
1116  * If we do not have sigrecs for the given key, build them and write them
1117  * to the trustdb
1118  */
1119 static int
1120 build_sigrecs( ulong pubkeyid )
1121 {
1122     TRUSTREC rec, krec, rec2;
1123     PUBKEY_FIND_INFO finfo=NULL;
1124     KBPOS kbpos;
1125     KBNODE keyblock = NULL;
1126     KBNODE kbctx;
1127     KBNODE node;
1128     int rc=0;
1129     int i, selfsig;
1130     ulong rnum, rnum2;
1131
1132     if( DBG_TRUST )
1133         log_debug("trustdb: build_sigrecs for pubkey %lu\n", (ulong)pubkeyid );
1134
1135     /* get the keyblock */
1136     if( (rc=read_record( pubkeyid, &rec, RECTYPE_DIR )) ) {
1137         log_error("%lu: build_sigrecs: can't read dir record\n", pubkeyid );
1138         goto leave;
1139     }
1140     finfo = m_alloc_clear( sizeof *finfo );
1141     finfo->keyid[0] = rec.r.dir.keyid[0];
1142     finfo->keyid[1] = rec.r.dir.keyid[1];
1143     if( (rc=read_record( rec.r.dir.keyrec, &krec, RECTYPE_KEY )) ) {
1144         log_error("%lu: build_sigrecs: can't read key record\n", pubkeyid);
1145         goto leave;
1146     }
1147     finfo->pubkey_algo = krec.r.key.pubkey_algo;
1148     memcpy( finfo->fingerprint, krec.r.key.fingerprint, 20);
1149     rc = find_keyblock( finfo, &kbpos );
1150     if( rc ) {
1151         log_error("build_sigrecs: find_keyblock failed\n" );
1152         goto leave;
1153     }
1154     rc = read_keyblock( &kbpos, &keyblock );
1155     if( rc ) {
1156         log_error("build_sigrecs: read_keyblock failed\n" );
1157         goto leave;
1158     }
1159     /* check all key signatures */
1160     rc = check_sigs( keyblock, &selfsig );
1161     if( rc ) {
1162         log_error("build_sigrecs: check_sigs failed\n" );
1163         goto leave;
1164     }
1165     if( !selfsig ) {
1166         log_error("build_sigrecs: self-certificate missing\n" );
1167         update_no_sigs( pubkeyid, 1 );
1168         rc = G10ERR_BAD_CERT;
1169         goto leave;
1170     }
1171     update_no_sigs( pubkeyid, 0 );
1172
1173     /* valid key signatures are now marked; we can now build the
1174      * sigrecs */
1175     memset( &rec, 0, sizeof rec );
1176     rec.rectype = RECTYPE_SIG;
1177     i = 0;
1178     rnum = rnum2 = 0;
1179     for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
1180         /* insert sigs which are not a selfsig nor a duplicate */
1181         if( (node->flag & 1) && !(node->flag & 4) ) {
1182             assert( node->pkt->pkttype == PKT_SIGNATURE );
1183             if( !node->pkt->pkt.signature->local_id )  {
1184                 /* the next function should always succeed, because
1185                  * we have already checked the signature, and for this
1186                  * it was necessary to have the pubkey. The only reason
1187                  * this can fail are I/o errors of the trustdb or a
1188                  * remove operation on the pubkey database - which should
1189                  * not disturb us, because we have to chace them anyway. */
1190                 rc = set_signature_packets_local_id( node->pkt->pkt.signature );
1191                 if( rc )
1192                     log_fatal("set_signature_packets_local_id failed: %s\n",
1193                                                               g10_errstr(rc));
1194             }
1195             if( i == SIGS_PER_RECORD ) {
1196                 /* write the record */
1197                 rnum = new_recnum();
1198                 if( rnum2 ) { /* write the stored record */
1199                     rec2.r.sig.owner = pubkeyid;
1200                     rec2.r.sig.chain = rnum; /* the next record number */
1201                     rc = write_record( rnum2, &rec2 );
1202                     if( rc ) {
1203                         log_error("build_sigrecs: write_record failed\n" );
1204                         goto leave;
1205                     }
1206                 }
1207                 rec2 = rec;
1208                 rnum2 = rnum;
1209                 memset( &rec, 0, sizeof rec );
1210                 rec.rectype = RECTYPE_SIG;
1211                 i = 0;
1212             }
1213             rec.r.sig.sig[i].local_id = node->pkt->pkt.signature->local_id;
1214             rec.r.sig.sig[i].flag = 0;
1215             i++;
1216         }
1217     }
1218     if( i || rnum2 ) {
1219         /* write the record */
1220         rnum = new_recnum();
1221         if( rnum2 ) { /* write the stored record */
1222             rec2.r.sig.owner = pubkeyid;
1223             rec2.r.sig.chain = rnum;
1224             rc = write_record( rnum2, &rec2 );
1225             if( rc ) {
1226                 log_error("build_sigrecs: write_record failed\n" );
1227                 goto leave;
1228             }
1229         }
1230         if( i ) { /* write the pending record */
1231             rec.r.sig.owner = pubkeyid;
1232             rec.r.sig.chain = 0;
1233             rc = write_record( rnum, &rec );
1234             if( rc ) {
1235                 log_error("build_sigrecs: write_record failed\n" );
1236                 goto leave;
1237             }
1238         }
1239     }
1240
1241   leave:
1242     m_free( finfo );
1243     release_kbnode( keyblock );
1244     if( DBG_TRUST )
1245         log_debug("trustdb: build_sigrecs: %s\n", g10_errstr(rc) );
1246     return rc;
1247 }
1248
1249 /****************
1250  * Make a list of trust paths
1251  */
1252 static int
1253 make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist )
1254 {
1255     int i, rc;
1256     LOCAL_ID_INFO *lids = new_lid_table();
1257     TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1258     TRUST_SEG_LIST tsl, tslist;
1259     int max_depth = 4;
1260
1261     tslist = *ret_tslist = NULL;
1262
1263     if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) {
1264         tslist = m_alloc( sizeof *tslist );
1265         tslist->nseg = 1;
1266         tslist->dup = 0;
1267         tslist->seg[0].lid = pubkey_id;
1268         tslist->seg[0].trust = 0;
1269         tslist->next = NULL;
1270         rc = 0;
1271     }
1272     else {
1273         stack[0].lid = pubkey_id;
1274         stack[0].trust = 0;
1275         rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1276     }
1277     if( !rc ) { /* wipe out duplicates */
1278         LOCAL_ID_INFO *work = new_lid_table();
1279         for( tsl=tslist; tsl; tsl = tsl->next ) {
1280             for(i=1; i < tsl->nseg-1; i++ ) {
1281                 if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1282                     tsl->dup = 1; /* mark as duplicate */
1283                     break;
1284                 }
1285             }
1286         }
1287         release_lid_table(work);
1288         *ret_tslist = tslist;
1289     }
1290     else
1291         ; /* FIXME: release tslist */
1292     release_lid_table(lids);
1293     return rc;
1294 }
1295
1296
1297 /****************
1298  * Given a trust segment list tslist, walk over all paths and fill in
1299  * the trust information for each segment.  What this function does is
1300  * to assign a trustvalue to the first segment (which is the requested key)
1301  * of each path.
1302  *
1303  * FIXME: We have to do more thinks here. e.g. we should never increase
1304  *        the trust value.
1305  *
1306  * Do not do it for duplicates.
1307  */
1308 static int
1309 propagate_trust( TRUST_SEG_LIST tslist )
1310 {
1311     int i, rc;
1312     unsigned trust;
1313     TRUST_SEG_LIST tsl;
1314
1315     for(tsl = tslist; tsl; tsl = tsl->next ) {
1316         if( tsl->dup )
1317             continue;
1318         assert( tsl->nseg );
1319         /* the last segment is always a ultimately trusted one, so we can
1320          * assign a fully trust to the next one */
1321         i = tsl->nseg-1;
1322         tsl->seg[i].trust = TRUST_ULTIMATE;
1323         trust = TRUST_FULLY;
1324         for(i-- ; i >= 0; i-- ) {
1325             tsl->seg[i].trust = trust;
1326             if( i > 0 ) {
1327                 /* get the trust of this pubkey */
1328                 rc = get_ownertrust( tsl->seg[i].lid, &trust );
1329                 if( rc )
1330                     return rc;
1331             }
1332         }
1333     }
1334     return 0;
1335 }
1336
1337
1338 /****************
1339  * we have the pubkey record but nothing more is known
1340  * function may re-read dr.
1341  */
1342 static int
1343 do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
1344 {
1345     int i, rc=0;
1346     TRUST_SEG_LIST tsl, tsl2, tslist;
1347     int marginal, fully;
1348     int fully_needed = opt.completes_needed;
1349     int marginal_needed = opt.marginals_needed;
1350
1351     assert( fully_needed > 0 && marginal_needed > 1 );
1352
1353
1354     *trustlevel = TRUST_UNDEFINED;
1355
1356     /* verify the cache */
1357
1358     /* do we have sigrecs */
1359     if( !dr->r.dir.sigrec && !dr->r.dir.no_sigs) {
1360         /* no sigrecs, so build them */
1361         rc = build_sigrecs( pubkeyid );
1362         if( !rc ) /* and read again */
1363             rc = read_record( pubkeyid, dr, RECTYPE_DIR );
1364     }
1365     if( !rc && !dr->r.dir.sigrec )
1366         rc = -1;
1367     if( rc )
1368         return rc;  /* error while looking for sigrec or building sigrecs */
1369
1370     /* fixme: take it from the cache if it is valid */
1371
1372     /* Make a list of all possible trust-paths */
1373     rc = make_tsl( pubkeyid, &tslist );
1374     if( rc )
1375         return rc;
1376     rc = propagate_trust( tslist );
1377     if( rc )
1378         return rc;
1379     for(tsl = tslist; tsl; tsl = tsl->next ) {
1380         if( tsl->dup )
1381             continue;
1382
1383         log_debug("tslist segs:" );
1384         for(i=0; i < tsl->nseg; i++ )
1385             fprintf(stderr, "  %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
1386         putc('\n',stderr);
1387     }
1388
1389     /* and look wether there is a trusted path.
1390      * We only have to look at the first segment, because
1391      * propagate_trust has investigated all other segments */
1392     marginal = fully = 0;
1393     for(tsl = tslist; tsl; tsl = tsl->next ) {
1394         if( tsl->dup )
1395             continue;
1396         if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
1397             *trustlevel = TRUST_ULTIMATE; /* our own key */
1398             break;
1399         }
1400         if( tsl->seg[0].trust == TRUST_FULLY ) {
1401             marginal++;
1402             fully++;
1403         }
1404         else if( tsl->seg[0].trust == TRUST_MARGINAL )
1405             marginal++;
1406
1407         if( fully >= fully_needed ) {
1408             *trustlevel = TRUST_FULLY;
1409             break;
1410         }
1411     }
1412     if( !tsl && marginal >= marginal_needed )
1413         *trustlevel = TRUST_MARGINAL;
1414
1415     /* cache the tslist */
1416     if( last_trust_web_key ) {
1417         for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) {
1418             tsl2 = tsl->next;
1419             m_free(tsl);
1420         }
1421     }
1422     last_trust_web_key = pubkeyid;
1423     last_trust_web_tslist = tslist;
1424     return 0;
1425 }
1426
1427
1428 /*********************************************************
1429  ****************  API Interface  ************************
1430  *********************************************************/
1431
1432 /****************
1433  * Perform some checks over the trustdb
1434  *  level 0: only open the db
1435  *        1: used for initial program startup
1436  */
1437 int
1438 init_trustdb( int level )
1439 {
1440     int rc=0;
1441
1442     if( !ultikey_table )
1443         ultikey_table = new_lid_table();
1444
1445     if( !level || level==1 ) {
1446         char *fname = make_filename("~/.g10", "trustdb.g10", NULL );
1447         if( access( fname, R_OK ) ) {
1448             if( errno != ENOENT ) {
1449                 log_error("can't access %s: %s\n", fname, strerror(errno) );
1450                 m_free(fname);
1451                 return G10ERR_TRUSTDB;
1452             }
1453             if( level )
1454                 create_db( fname );
1455         }
1456         m_free(db_name);
1457         db_name = fname;
1458
1459         if( !level )
1460             return 0;
1461
1462         /* we can verify a signature about our local data (secring and trustdb)
1463          * in ~/.g10/ here */
1464         rc = verify_private_data();
1465         if( !rc ) {
1466             /* verify, that our own certificates are in the trustDB
1467              * or move them to the trustdb. */
1468             rc = verify_own_certs();
1469
1470             /* should we check wether there is no other ultimately trusted
1471              * key in the database? */
1472
1473         }
1474     }
1475     else
1476         BUG();
1477
1478     return rc;
1479 }
1480
1481
1482 void
1483 list_trustdb( const char *username )
1484 {
1485     TRUSTREC rec;
1486
1487     if( username ) {
1488         PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
1489         int rc;
1490
1491         if( (rc = get_pubkey_byname( pkc, username )) )
1492             log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1493         else if( (rc=search_record( pkc, &rec )) && rc != -1 )
1494             log_error("problem finding '%s' in trustdb: %s\n",
1495                                                 username, g10_errstr(rc));
1496         else if( rc == -1 )
1497             log_error("user '%s' not in trustdb\n", username);
1498         else if( (rc = list_sigs( pkc->local_id )) )
1499             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1500         free_public_cert( pkc );
1501     }
1502     else {
1503         ulong recnum;
1504         int i;
1505
1506         printf("TrustDB: %s\n", db_name );
1507         for(i=9+strlen(db_name); i > 0; i-- )
1508             putchar('-');
1509         putchar('\n');
1510         for(recnum=0; !read_record( recnum, &rec, 0); recnum++ )
1511             dump_record( recnum, &rec, stdout );
1512     }
1513 }
1514
1515 void
1516 list_trust_path( int max_depth, const char *username )
1517 {
1518     int rc;
1519     int wipe=0;
1520     int i;
1521     TRUSTREC rec;
1522     PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
1523
1524     if( max_depth < 0 ) {
1525         wipe = 1;
1526         max_depth = -max_depth;
1527     }
1528
1529     if( (rc = get_pubkey_byname( pkc, username )) )
1530         log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
1531     else if( (rc=search_record( pkc, &rec )) && rc != -1 )
1532         log_error("problem finding '%s' in trustdb: %s\n",
1533                                             username, g10_errstr(rc));
1534     else if( rc == -1 ) {
1535         log_info("user '%s' not in trustdb - inserting\n", username);
1536         rc = insert_trust_record( pkc );
1537         if( rc )
1538             log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
1539         else {
1540             assert( pkc->local_id );
1541         }
1542     }
1543
1544     if( !rc ) {
1545         TRUST_SEG_LIST tsl, tslist = NULL;
1546
1547         if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
1548             tslist = m_alloc( sizeof *tslist );
1549             tslist->nseg = 1;
1550             tslist->dup = 0;
1551             tslist->seg[0].lid = pkc->local_id;
1552             tslist->seg[0].trust = 0;
1553             tslist->next = NULL;
1554             rc = 0;
1555         }
1556         else {
1557             LOCAL_ID_INFO *lids = new_lid_table();
1558             TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
1559
1560             stack[0].lid = pkc->local_id;
1561             stack[0].trust = 0;
1562             rc = do_list_path( stack, 1, max_depth, lids, &tslist );
1563             if( wipe ) { /* wipe out duplicates */
1564                 LOCAL_ID_INFO *work;
1565
1566                 work = new_lid_table();
1567                 for( tsl=tslist; tsl; tsl = tsl->next ) {
1568                     for(i=1; i < tsl->nseg-1; i++ ) {
1569                         if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
1570                             tsl->dup = 1; /* mark as duplicate */
1571                             break;
1572                         }
1573                     }
1574                 }
1575                 release_lid_table(work);
1576             }
1577             release_lid_table(lids);
1578         }
1579         if( rc )
1580             log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
1581         rc = propagate_trust( tslist );
1582         if( rc )
1583             log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
1584         for(tsl = tslist; tsl; tsl = tsl->next ) {
1585             int i;
1586
1587             if( tsl->dup )
1588                 continue;
1589             printf("trust path:" );
1590             for(i=0; i < tsl->nseg; i++ )
1591                 printf("  %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
1592             putchar('\n');
1593         }
1594     }
1595
1596     free_public_cert( pkc );
1597 }
1598
1599
1600 /****************
1601  * Get the trustlevel for this PKC.
1602  * Note: This does not ask any questions
1603  * Returns: 0 okay of an errorcode
1604  *
1605  * It operates this way:
1606  *  locate the pkc in the trustdb
1607  *      found:
1608  *          Do we have a valid cache record for it?
1609  *              yes: return trustlevel from cache
1610  *              no:  make a cache record and all the other stuff
1611  *      not found:
1612  *          Return with a trustlevel, saying that we do not have
1613  *          a trust record for it. The caller may use insert_trust_record()
1614  *          and then call this function here again.
1615  *
1616  * Problems: How do we get the complete keyblock to check that the
1617  *           cache record is actually valid?  Think we need a clever
1618  *           cache in getkey.c  to keep track of this stuff. Maybe it
1619  *           is not necessary to check this if we use a local pubring. Hmmmm.
1620  */
1621 int
1622 check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel )
1623 {
1624     TRUSTREC rec;
1625     unsigned trustlevel = TRUST_UNKNOWN;
1626     int rc=0;
1627
1628     if( DBG_TRUST )
1629         log_info("check_trust() called.\n");
1630
1631     /* get the pubkey record */
1632     if( pkc->local_id ) {
1633         if( read_record( pkc->local_id, &rec, RECTYPE_DIR ) ) {
1634             log_error("check_trust: read record failed\n");
1635             return G10ERR_TRUSTDB;
1636         }
1637     }
1638     else { /* no local_id: scan the trustdb */
1639         if( (rc=search_record( pkc, &rec )) && rc != -1 ) {
1640             log_error("check_trust: search_record failed: %s\n",
1641                                                             g10_errstr(rc));
1642             return rc;
1643         }
1644         else if( rc == -1 ) {
1645             rc = insert_trust_record( pkc );
1646             if( rc ) {
1647                 log_error("failed to insert pubkey into trustdb: %s\n",
1648                                                             g10_errstr(rc));
1649                 goto leave;
1650             }
1651             log_info("pubkey not in trustdb - inserted as %lu\n",
1652                                     pkc->local_id );
1653         }
1654     }
1655     /* fixme: do some additional checks on the pubkey record */
1656
1657     rc = do_check( pkc->local_id, &rec, &trustlevel );
1658     if( rc ) {
1659         log_error("check_trust: do_check failed: %s\n", g10_errstr(rc));
1660         return rc;
1661     }
1662
1663
1664   leave:
1665     if( DBG_TRUST )
1666         log_info("check_trust() returns trustlevel %04x.\n", trustlevel);
1667     *r_trustlevel = trustlevel;
1668     return 0;
1669 }
1670
1671
1672
1673
1674 /****************
1675  * Enumerate all keys, which are needed to build all trust paths for
1676  * the given key.  This function does not return the key itself or
1677  * the ultimate key.
1678  *
1679  *  1) create a void pointer and initialize it to NULL
1680  *  2) pass this void pointer by reference to this function.
1681  *     Set lid to the key you want to enumerate and pass it by reference.
1682  *  3) call this function as long as it does not return -1
1683  *     to indicate EOF. LID does contain the next key used to build the web
1684  *  4) Always call this function a last time with LID set to NULL,
1685  *     so that it can free it's context.
1686  */
1687 int
1688 enum_trust_web( void **context, ulong *lid )
1689 {
1690     ENUM_TRUST_WEB_CONTEXT *c = *context;
1691
1692     if( !c ) { /* make a new context */
1693         c = m_alloc_clear( sizeof *c );
1694         *context = c;
1695         if( *lid != last_trust_web_key )
1696             log_bug("enum_trust_web: nyi\n");
1697         c->tsl = last_trust_web_tslist;
1698         c->index = 1;
1699     }
1700
1701     if( !lid ) { /* free the context */
1702         m_free( c );
1703         *context = NULL;
1704         return 0;
1705     }
1706
1707     while( c->tsl ) {
1708         if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) {
1709             *lid = c->tsl->seg[c->index].lid;
1710             c->index++;
1711             return 0;
1712         }
1713         c->index = 1;
1714         c->tsl = c->tsl->next;
1715     }
1716     return -1; /* eof */
1717 }
1718
1719
1720 /****************
1721  * Return the assigned ownertrust value for the given LID
1722  */
1723 int
1724 get_ownertrust( ulong lid, unsigned *r_otrust )
1725 {
1726     TRUSTREC rec;
1727
1728     if( read_record( lid, &rec, RECTYPE_DIR ) ) {
1729         log_error("get_ownertrust: read dir record failed\n");
1730         return G10ERR_TRUSTDB;
1731     }
1732     if( read_record( rec.r.dir.keyrec, &rec, RECTYPE_KEY ) ) {
1733         log_error("get_ownertrust: read key record failed\n");
1734         return G10ERR_TRUSTDB;
1735     }
1736     if( r_otrust )
1737         *r_otrust = rec.r.key.ownertrust;
1738     return 0;
1739 }
1740
1741 int
1742 keyid_from_trustdb( ulong lid, u32 *keyid )
1743 {
1744     TRUSTREC rec;
1745
1746     if( read_record( lid, &rec, RECTYPE_DIR ) ) {
1747         log_error("keyid_from_trustdb: read record failed\n");
1748         return G10ERR_TRUSTDB;
1749     }
1750     if( keyid ) {
1751         keyid[0] = rec.r.dir.keyid[0];
1752         keyid[1] = rec.r.dir.keyid[1];
1753     }
1754     return 0;
1755 }
1756
1757
1758 /****************
1759  * This function simply looks for the key in the trustdb
1760  * and sets PKC->local_id.
1761  * Return: 0 = found
1762  *         -1 = not found
1763  *        other = error
1764  */
1765 int
1766 query_trust_record( PKT_public_cert *pkc )
1767 {
1768     TRUSTREC rec;
1769     int rc=0;
1770
1771     if( pkc->local_id ) {
1772         if( read_record( pkc->local_id, &rec, RECTYPE_DIR ) ) {
1773             log_error("query_trust_record: read record failed\n");
1774             return G10ERR_TRUSTDB;
1775         }
1776     }
1777     else { /* no local_id: scan the trustdb */
1778         if( (rc=search_record( pkc, &rec )) && rc != -1 ) {
1779             log_error("query_trust_record: search_record failed: %s\n",
1780                                                             g10_errstr(rc));
1781             return rc;
1782         }
1783     }
1784     return rc;
1785 }
1786
1787
1788 /****************
1789  * Insert a trust record into the TrustDB
1790  * This function failes if this record already exists.
1791  */
1792 int
1793 insert_trust_record( PKT_public_cert *pkc )
1794 {
1795     TRUSTREC rec;
1796     u32 keyid[2];
1797     ulong knum, dnum;
1798     byte *fingerprint;
1799     size_t fingerlen;
1800
1801
1802     if( pkc->local_id )
1803         log_bug("pkc->local_id=%lu\n", (ulong)pkc->local_id );
1804
1805     keyid_from_pkc( pkc, keyid );
1806     fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
1807
1808     /* FIXME: check that we do not have this record. */
1809
1810     dnum = new_recnum();
1811     knum = new_recnum();
1812     /* build dir record */
1813     memset( &rec, 0, sizeof rec );
1814     rec.rectype = RECTYPE_DIR;
1815     rec.r.dir.local_id = dnum;
1816     rec.r.dir.keyid[0] = keyid[0];
1817     rec.r.dir.keyid[1] = keyid[1];
1818     rec.r.dir.keyrec   = knum;
1819     rec.r.dir.no_sigs = 0;
1820     if( write_record( dnum, &rec ) ) {
1821         log_error("writing dir record failed\n");
1822         return G10ERR_TRUSTDB;
1823     }
1824     /* and the key record */
1825     memset( &rec, 0, sizeof rec );
1826     rec.rectype = RECTYPE_KEY;
1827     rec.r.key.owner    = dnum;
1828     rec.r.key.keyid[0] = keyid[0];
1829     rec.r.key.keyid[1] = keyid[1];
1830     rec.r.key.pubkey_algo = pkc->pubkey_algo;
1831     memcpy(rec.r.key.fingerprint, fingerprint, fingerlen );
1832     rec.r.key.ownertrust = 0;
1833     if( write_record( knum, &rec ) ) {
1834         log_error("wrinting key record failed\n");
1835         return G10ERR_TRUSTDB;
1836     }
1837
1838     pkc->local_id = dnum;
1839
1840     return 0;
1841 }
1842
1843
1844 int
1845 update_ownertrust( ulong lid, unsigned new_trust )
1846 {
1847     TRUSTREC rec;
1848     ulong recnum;
1849
1850     if( read_record( lid, &rec, RECTYPE_DIR ) ) {
1851         log_error("update_ownertrust: read dir failed\n");
1852         return G10ERR_TRUSTDB;
1853     }
1854     recnum = rec.r.dir.keyrec;
1855     if( read_record( recnum, &rec, RECTYPE_KEY ) ) {
1856         log_error("update_ownertrust: read key failed\n");
1857         return G10ERR_TRUSTDB;
1858     }
1859     /* check keyid, fingerprint etc ? */
1860
1861     rec.r.key.ownertrust = new_trust;
1862     if( write_record( recnum, &rec ) ) {
1863         log_error("update_ownertrust: write failed\n");
1864         return G10ERR_TRUSTDB;
1865     }
1866
1867     return 0;
1868 }
1869
1870
1871
1872 /****************
1873  * Kludge to prevent duplicate build_sigrecs() due to an invalid
1874  * certificate (no selfsignature or something like this)
1875  */
1876 static int
1877 update_no_sigs( ulong lid, int no_sigs )
1878 {
1879     TRUSTREC rec;
1880
1881     if( read_record( lid, &rec, RECTYPE_DIR ) ) {
1882         log_error("update_no_sigs: read failed\n");
1883         return G10ERR_TRUSTDB;
1884     }
1885
1886     rec.r.dir.no_sigs = !!no_sigs;
1887     if( write_record( lid, &rec ) ) {
1888         log_error("update_no_sigs: write failed\n");
1889         return G10ERR_TRUSTDB;
1890     }
1891
1892     return 0;
1893 }
1894
1895
1896 int
1897 verify_private_data()
1898 {
1899     int rc = 0;
1900     char *sigfile = make_filename("~/.g10", "sig", NULL );
1901
1902     if( access( sigfile, R_OK ) ) {
1903         if( errno != ENOENT ) {
1904             log_error("can't access %s: %s\n", sigfile, strerror(errno) );
1905             rc = G10ERR_TRUSTDB;
1906             goto leave;
1907         }
1908         log_info("private data signature missing; creating ...\n");
1909         rc = sign_private_data();
1910         if( rc ) {
1911             log_error("error creating %s: %s\n", sigfile, g10_errstr(rc) );
1912             goto leave;
1913         }
1914     }
1915
1916     /* FIXME: verify this signature */
1917
1918   leave:
1919     m_free(sigfile);
1920     return rc;
1921 }
1922
1923
1924 int
1925 sign_private_data()
1926 {
1927     int rc;
1928     char *sigfile = make_filename("~/.g10", "sig", NULL );
1929     char *secring = make_filename("~/.g10", "secring.g10", NULL );
1930     STRLIST list = NULL;
1931
1932     add_to_strlist( &list, db_name );
1933     add_to_strlist( &list, secring );
1934
1935     rc = sign_file( list, 1, NULL, 0, NULL, sigfile);
1936
1937     m_free(sigfile);
1938     m_free(secring);
1939     free_strlist(list);
1940     return rc;
1941 }
1942