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