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