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