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