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