aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/trustdb.c846
1 files changed, 425 insertions, 421 deletions
diff --git a/g10/trustdb.c b/g10/trustdb.c
index f3396ab3c..065d00d6c 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -42,58 +42,61 @@
#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5)
#define MAX_LIST_SIGS_DEPTH 20
+
+#define RECTYPE_VER 1
+#define RECTYPE_DIR 2
+#define RECTYPE_KEY 3
+#define RECTYPE_CTL 4
+#define RECTYPE_SIG 5
+
+
struct trust_record {
- byte rectype;
- byte reserved;
+ int rectype;
union {
struct { /* version record: */
- byte magic[2];
byte version; /* should be 1 */
- byte reserved[3];
ulong locked; /* pid of process which holds a lock */
ulong created; /* timestamp of trustdb creation */
ulong modified; /* timestamp of last modification */
ulong validated; /* timestamp of last validation */
- ulong local_id_counter;
byte marginals_needed;
byte completes_needed;
byte max_cert_depth;
- } version;
- struct { /* public key record */
+ } ver;
+ struct { /* directory record */
ulong local_id;
- u32 keyid[2];
+ u32 keyid[2];
+ ulong keyrec; /* recno of public key record */
+ ulong ctlrec /* recno of control record */
+ ulong sigrec; /* recno of first signature record */
+ byte no_sigs; /* does not have sigature and checked */
+ } dir;
+ struct { /* public key record */
+ ulong owner;
+ u32 keyid[2];
byte pubkey_algo;
- byte reserved;
byte fingerprint[20];
byte ownertrust;
- byte no_sigs;
- /* fixme: indicate a flag to */
- } pubkey;
- struct { /* cache record */
+ } key;
+ struct { /* control record */
ulong owner;
- u32 keyid[2]; /* needed?? */
- byte valid;
- byte reserved;
byte blockhash[20];
- byte n_untrusted;
- byte n_marginal;
- byte n_fully;
- byte trustlevel;
- } cache;
- struct {
+ byte trustlevel; /* calculated trustlevel */
+ } ctl;
+ struct { /* signature record */
ulong owner; /* local_id of record owner (pubkey record) */
ulong chain; /* offset of next record or NULL for last one */
struct {
ulong local_id; /* of pubkey record of signator (0=unused) */
byte flag; /* reserved */
} sig[SIGS_PER_RECORD];
- } sigrec;
+ } sig;
} r;
};
typedef struct trust_record TRUSTREC;
typedef struct {
- ulong pubkey_id; /* localid of the pubkey */
+ ulong local_id; /* localid of the pubkey */
ulong sig_id; /* returned signature id */
unsigned sig_flag; /* returned signature record flag */
struct { /* internal data */
@@ -135,10 +138,11 @@ typedef struct {
static void create_db( const char *fname );
static void open_db(void);
+static void dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
static int read_record( ulong recnum, TRUSTREC *rec );
static int write_record( ulong recnum, TRUSTREC *rec );
static ulong new_recnum(void);
-static void dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
+static int search_record( PKT_public_cert *pkc, TRUSTREC *rec );
static int walk_sigrecs( SIGREC_CONTEXT *c, int create );
static LOCAL_ID_INFO *new_lid_table(void);
@@ -215,6 +219,79 @@ fwrite_zeros( FILE *fp, size_t n)
}
+/**********************************************
+ ************* list helpers *******************
+ **********************************************/
+
+static LOCAL_ID_INFO *
+new_lid_table(void)
+{
+ return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO));
+}
+
+static void
+release_lid_table( LOCAL_ID_INFO *tbl )
+{
+ LOCAL_ID_INFO a, a2;
+ int i;
+
+ for(i=0; i < 16; i++ ) {
+ for(a=tbl[i]; a; a = a2 ) {
+ a2 = a->next;
+ m_free(a);
+ }
+ }
+ m_free(tbl);
+}
+
+/****************
+ * Add a new item to the table or return 1 if we already have this item
+ * fixme: maybe its a good idea to take items from an unused item list.
+ */
+static int
+ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
+{
+ LOCAL_ID_INFO a;
+
+ for( a = tbl[lid & 0x0f]; a; a = a->next )
+ if( a->lid == lid )
+ return 1;
+ a = m_alloc( sizeof *a );
+ a->lid = lid;
+ a->flag = flag;
+ a->next = tbl[lid & 0x0f];
+ tbl[lid & 0x0f] = a;
+ return 0;
+}
+
+static int
+qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag )
+{
+ LOCAL_ID_INFO a;
+
+ for( a = tbl[lid & 0x0f]; a; a = a->next )
+ if( a->lid == lid ) {
+ if( flag )
+ *flag = a->flag;
+ return 0;
+ }
+ return -1;
+}
+
+static void
+upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
+{
+ LOCAL_ID_INFO a;
+
+ for( a = tbl[lid & 0x0f]; a; a = a->next )
+ if( a->lid == lid ) {
+ a->flag = flag;
+ return;
+ }
+ BUG();
+}
+
+
/**************************************************
************** read and write stuff **************
**************************************************/
@@ -241,7 +318,7 @@ create_db( const char *fname )
fwrite_32( fp, make_timestamp() ); /* created */
fwrite_32( fp, 0 ); /* not yet modified */
fwrite_32( fp, 0 ); /* not yet validated*/
- fwrite_32( fp, 0 ); /* local-id-counter (not used) */
+ fwrite_32( fp, 0 ); /* reserved */
fwrite_8( fp, 3 ); /* marginals needed */
fwrite_8( fp, 1 ); /* completes needed */
fwrite_8( fp, 4 ); /* max_cet_depth */
@@ -264,6 +341,53 @@ open_db()
}
+static void
+dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
+{
+ int i, any;
+
+ fprintf(fp, "trust record %lu, type=", rnum );
+
+ switch( rec->rectype ) {
+ case 0: fprintf(fp, "free\n");
+ break;
+ case RECTYPE_VER: fprintf(fp, "version\n");
+ break;
+ case RECTYPE_DIR:
+ fprintf(fp, "dir keyid=%08lx, key=%lu, ctl=%lu, sig=%lu%s\n",
+ rec->r.dir.keyid[1],
+ rec->r.dir.keyrec, rec->r.dir.ctlrec, rec->r.dir.sigrec,
+ rec->r.dir.no_sigs?" (inv sigs)":"");
+ break;
+ case RECTYPE_KEY: fprintf(fp, "key keyid=%08lx, own=%lu, ownertrust=%02x\n",
+ rec->r.key.keyid[1],
+ rec->r.key.owner, rec->r.key.ownertrust );
+ break;
+ case RECTYPE_CTL: fprintf(fp, "ctl\n");
+ break;
+ case RECTYPE_SIG:
+ fprintf(fp, "sigrec, owner=%lu, chain=%lu%s\n",
+ rec->r.sig.owner, rec->r.sigrec.chain,
+ rec->rectype == 4?"":" (extend)");
+ for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
+ if( rec->r.sigrec.sig[i].local_id ) {
+ if( !any ) {
+ putc('\t', fp);
+ any++;
+ }
+ fprintf(fp, " %lu:%02x", rec->r.sigrec.sig[i].local_id,
+ rec->r.sigrec.sig[i].flag );
+ }
+ }
+ if( any )
+ putc('\n', fp);
+ break;
+ default:
+ fprintf(fp, "%d (unknown)\n", rec->rectype );
+ break;
+ }
+}
+
/****************
* read the record with number recnum
* returns: -1 on error, 0 on success
@@ -291,75 +415,72 @@ read_record( ulong recnum, TRUSTREC *rec )
}
p = buf;
rec->rectype = *p++;
- rec->reserved = *p++;
+ p++;
switch( rec->rectype ) {
case 0: /* unused record */
break;
- case 1: /* version record */
- rec->r.version.magic[0] = *p++;
- rec->r.version.magic[1] = *p++;
- rec->r.version.version = *p++;
- memcpy( rec->r.version.reserved, p, 3); p += 3;
- rec->r.version.locked = buftoulong(p); p += 4;
- rec->r.version.created = buftoulong(p); p += 4;
- rec->r.version.modified = buftoulong(p); p += 4;
- rec->r.version.validated= buftoulong(p); p += 4;
- rec->r.version.local_id_counter = buftoulong(p); p += 4;
- rec->r.version.marginals_needed = *p++;
- rec->r.version.completes_needed = *p++;
- rec->r.version.max_cert_depth = *p++;
+ case RECTYPE_VER: /* version record */
+ if( memcmp(buf+1, "g10", 3 ) {
+ log_error("%s: not a trustdb file\n", db_name );
+ rc = G10ERR_TRUSTDB;
+ }
+ p += 2; /* skip magic */
+ rec->r.ver.version = *p++;
+ memcpy( rec->r.ver.reserved, p, 3); p += 3;
+ rec->r.ver.locked = buftoulong(p); p += 4;
+ rec->r.ver.created = buftoulong(p); p += 4;
+ rec->r.ver.modified = buftoulong(p); p += 4;
+ rec->r.ver.validated= buftoulong(p); p += 4;
+ rec->r.ver.local_id_counter = buftoulong(p); p += 4;
+ rec->r.ver.marginals_needed = *p++;
+ rec->r.ver.completes_needed = *p++;
+ rec->r.ver.max_cert_depth = *p++;
if( recnum ) {
log_error("%s: version record with recnum %lu\n",
db_name, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
- if( rec->reserved != 'g' || rec->r.version.magic[0] != '1'
- || rec->r.version.magic[1] != '0' ) {
- log_error("%s: not a trustdb file\n", db_name );
- rc = G10ERR_TRUSTDB;
- }
- if( rec->r.version.version != 1 ) {
+ if( rec->r.ver.version != 1 ) {
log_error("%s: invalid file version %d\n",
db_name, rec->r.version.version );
rc = G10ERR_TRUSTDB;
}
break;
- case 2:
- rec->r.pubkey.local_id = buftoulong(p); p += 4;
- rec->r.pubkey.keyid[0] = buftou32(p); p += 4;
- rec->r.pubkey.keyid[1] = buftou32(p); p += 4;
- rec->r.pubkey.pubkey_algo = *p++;
- rec->r.pubkey.reserved = *p++;
- memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20;
- rec->r.pubkey.ownertrust = *p++;
- rec->r.pubkey.no_sigs = *p++;
- if( rec->r.pubkey.local_id != recnum ) {
- log_error("%s: pubkey local_id != recnum (%lu,%lu)\n",
+ case RECTYPE_DIR: /*directory record */
+ rec->r.dir.local_id = buftoulong(p); p += 4;
+ rec->r.dir.keyid[0] = buftou32(p); p += 4;
+ rec->r.dir.keyid[1] = buftou32(p); p += 4;
+ rec->r.dir.keyrec = buftoulong(p); p += 4;
+ rec->r.dir.ctlrec = buftoulong(p); p += 4;
+ rec->r.dir.sigrec = buftoulong(p); p += 4;
+ rec->r.dir.no_sigs = *p++;
+ if( rec->r.dir.local_id != recnum ) {
+ log_error("%s: dir local_id != recnum (%lu,%lu)\n",
db_name,
- (ulong)rec->r.pubkey.local_id,
+ (ulong)rec->r.dir.local_id,
(ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
- case 3:
- rec->r.cache.owner = buftoulong(p); p += 4;
- rec->r.cache.keyid[0] = buftou32(p); p += 4;
- rec->r.cache.keyid[1] = buftou32(p); p += 4;
- rec->r.cache.valid = *p++;
- rec->r.cache.reserved = *p++;
- memcpy(rec->r.cache.blockhash, p, 20); p += 20;
- rec->r.cache.n_untrusted = *p++;
- rec->r.cache.n_marginal = *p++;
- rec->r.cache.n_fully = *p++;
- rec->r.cache.trustlevel = *p++;
+ case RECTYPE_KEY: /* public key record */
+ rec->r.key.owner = buftoulong(p); p += 4;
+ rec->r.dir.keyid[0] = buftou32(p); p += 4;
+ rec->r.dir.keyid[1] = buftou32(p); p += 4;
+ rec->r.key.pubkey_algo = *p++; p++;
+ memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20;
+ rec->r.pubkey.ownertrust = *p++;
+ break;
+ case RECTYPE_CTL: /* control record */
+ rec->r.ctl.owner = buftoulong(p); p += 4;
+ memcpy(rec->r.ctl.blockhash, p, 20); p += 20;
+ rec->r.ctl.trustlevel = *p++;
break;
- case 4:
- case 5:
- rec->r.sigrec.owner = buftoulong(p); p += 4;
- rec->r.sigrec.chain = buftoulong(p); p += 4;
+ case RECTYPE_SIG:
+ rec->r.sig.owner = buftoulong(p); p += 4;
+ rec->r.sig.chain = buftoulong(p); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
- rec->r.sigrec.sig[i].local_id = buftoulong(p); p += 4;
- rec->r.sigrec.sig[i].flag = *p++;
+ rec->r.sig.sig[i].local_id = buftoulong(p); p += 4;
+ rec->r.sig.sig[i].flag = *p++;
}
break;
default:
@@ -395,36 +516,39 @@ write_record( ulong recnum, TRUSTREC *rec )
case 1: /* version record */
BUG();
break;
- case 2:
- ulongtobuf(p, rec->r.pubkey.local_id); p += 4;
- u32tobuf(p, rec->r.pubkey.keyid[0]); p += 4;
- u32tobuf(p, rec->r.pubkey.keyid[1]); p += 4;
- *p++ = rec->r.pubkey.pubkey_algo;
- *p++ = rec->r.pubkey.reserved;
- memcpy( p, rec->r.pubkey.fingerprint, 20); p += 20;
+
+ case RECTYPE_DIR: /*directory record */
+ ulongtobuf(p, rec->r.dir.local_id); p += 4;
+ u32tobuf(p, rec->r.key.keyid[0]); p += 4;
+ u32tobuf(p, rec->r.key.keyid[1]); p += 4;
+ ulongtobuf(p, rec->r.dir.keyrec); p += 4;
+ ulongtobuf(p, rec->r.dir.ctlrec); p += 4;
+ ulongtobuf(p, rec->r.dir.sigrec); p += 4;
+ *p++ = rec->r.dir.no_sigs;
+ assert( rec->r.dir.local_id == recnum );
+ break;
+
+ case RECTYPE_KEY:
+ ulongtobuf(p, rec->r.key.owner); p += 4;
+ u32tobuf(p, rec->r.key.keyid[0]); p += 4;
+ u32tobuf(p, rec->r.key.keyid[1]); p += 4;
+ *p++ = rec->r.pubkey.pubkey_algo; p++;
+ memcpy( p, rec->r.key.fingerprint, 20); p += 20;
*p++ = rec->r.pubkey.ownertrust;
- *p++ = rec->r.pubkey.no_sigs;
- assert( rec->r.pubkey.local_id == recnum );
break;
- case 3:
- ulongtobuf(p, rec->r.cache.owner); p += 4;
- u32tobuf(p, rec->r.cache.keyid[0]); p += 4;
- u32tobuf(p, rec->r.cache.keyid[1]); p += 4;
- *p++ = rec->r.cache.valid;
- *p++ = rec->r.cache.reserved;
- memcpy(p, rec->r.cache.blockhash, 20); p += 20;
- *p++ = rec->r.cache.n_untrusted;
- *p++ = rec->r.cache.n_marginal;
- *p++ = rec->r.cache.n_fully;
- *p++ = rec->r.cache.trustlevel;
+
+ case RECTYPE_CTL: /* control record */
+ ulongtobuf(p, rec->r.ctl.owner); p += 4;
+ memcpy(p, rec->r.ctl.blockhash, 20); p += 20;
+ *p++ = rec->r.ctl.trustlevel;
break;
- case 4:
- case 5:
- ulongtobuf(p, rec->r.sigrec.owner); p += 4;
- ulongtobuf(p, rec->r.sigrec.chain); p += 4;
+
+ case RECTYPE_SIG:
+ ulongtobuf(p, rec->r.sig.owner); p += 4;
+ ulongtobuf(p, rec->r.sig.chain); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
- ulongtobuf(p, rec->r.sigrec.sig[i].local_id); p += 4;
- *p++ = rec->r.sigrec.sig[i].flag;
+ ulongtobuf(p, rec->r.sig.sig[i].local_id); p += 4;
+ *p++ = rec->r.sig.sig[i].flag;
}
break;
default:
@@ -445,7 +569,6 @@ write_record( ulong recnum, TRUSTREC *rec )
}
-
/****************
* create a new record and return its record number
*/
@@ -476,11 +599,13 @@ new_recnum()
}
/****************
- * Scan the trustdb for a record of type RECTYPE which matches PKC
- * The local_id is set to the correct value
+ * Search the trustdb for a key which matches PKC and return the dir record
+ * The local_id of PKC is set to the correct value
+ *
+ * Note: To increase performance, we could use a index search here.
*/
static int
-scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
+search_record( PKT_public_cert *pkc, TRUSTREC *rec )
{
ulong recnum;
u32 keyid[2];
@@ -488,115 +613,37 @@ scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
size_t fingerlen;
int rc;
- assert( rectype == 2 || rectype == 3 );
-
keyid_from_pkc( pkc, keyid );
fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
assert( fingerlen == 20 || fingerlen == 16 );
for(recnum=1; !(rc=read_record( recnum, rec)); recnum++ ) {
- if( rec->rectype != rectype )
+ if( rec->rectype != RECTYPE_DIR )
continue;
- if( rec->rectype == 2 ) {
- if( rec->r.pubkey.keyid[0] == keyid[0]
- && rec->r.pubkey.keyid[1] == keyid[1]
- && rec->r.pubkey.pubkey_algo == pkc->pubkey_algo
- && !memcmp(rec->r.pubkey.fingerprint, fingerprint, fingerlen)
- ) { /* found */
- /* store the local_id */
+ if( rec->r.dir.keyid[0] == keyid[0]
+ && rec->r.dir.keyid[1] == keyid[1]){
+ TRUSTREC keyrec;
+
+ if( read_record( rec->r.dir.keyrec, keyrec ) ) {
+ log_error("%lu: ooops: invalid dir record\n", recnum );
+ break;
+ }
+ if( keyrec.key.pubkey_algo == pkc->pubkey_algo
+ && !memcmp(keyrec.r.key.fingerprint, fingerprint, fingerlen) ){
if( pkc->local_id && pkc->local_id != recnum )
log_error("%s: found record, but local_id from mem does "
- "not match recnum (%lu,%lu)\n", db_name,
- (ulong)pkc->local_id, (ulong)recnum );
+ "not match recnum (%lu,%lu)\n", db_name,
+ (ulong)pkc->local_id, (ulong)recnum );
pkc->local_id = recnum;
return 0;
}
}
- else
- log_bug("not yet implemented\n");
}
if( rc != -1 )
- log_error("%s: scan_record_by_pkc failed: %s\n",db_name, g10_errstr(rc) );
+ log_error("%s: search_db failed: %s\n",db_name, g10_errstr(rc) );
return rc;
}
-/****************
- * scan the DB for a record of type RECTYPE which can be localized
- * with LOCAL_ID
- */
-static int
-scan_record( ulong local_id, TRUSTREC *rec, int rectype, ulong *r_recnum )
-{
- ulong recnum;
- int rc;
-
- assert( rectype == 3 || rectype == 4 );
-
- for(recnum=1; !(rc=read_record( recnum, rec)); recnum++ ) {
- if( rec->rectype != rectype )
- continue;
- if( rec->rectype == 34 ) {
- if( rec->r.cache.owner == local_id ) { /* found */
- *r_recnum = recnum;
- return 0;
- }
- }
- else if( rec->rectype == 4 ) {
- if( rec->r.sigrec.owner == local_id ) { /* found */
- *r_recnum = recnum;
- return 0;
- }
- }
- else
- log_bug("not yet implemented\n");
- }
- if( rc != -1 )
- log_error("%s: scan_record failed: %s\n",db_name, g10_errstr(rc) );
- return rc;
-}
-
-
-static void
-dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
-{
- int i, any;
-
- fprintf(fp, "trust record %lu, type=", rnum );
-
- switch( rec->rectype ) {
- case 0: fprintf(fp, "free\n");
- break;
- case 1: fprintf(fp, "version\n");
- break;
- case 2: fprintf(fp, "pubkey, keyid=%08lX, ownertrust=%02x%s\n",
- rec->r.pubkey.keyid[1], rec->r.pubkey.ownertrust,
- rec->r.pubkey.no_sigs?" (inv sigs)":"");
- break;
- case 3: fprintf(fp, "cache\n");
- case 4:
- case 5:
- fprintf(fp, "sigrec, owner=%lu, chain=%lu%s\n",
- rec->r.sigrec.owner, rec->r.sigrec.chain,
- rec->rectype == 4?"":" (extend)");
- for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
- if( rec->r.sigrec.sig[i].local_id ) {
- if( !any ) {
- putc('\t', fp);
- any++;
- }
- fprintf(fp, " %lu:%02x", rec->r.sigrec.sig[i].local_id,
- rec->r.sigrec.sig[i].flag );
- }
- }
- if( any )
- putc('\n', fp);
- break;
- default:
- fprintf(fp, "%d (unknown)\n", rec->rectype );
- break;
- }
-}
-
/****************
* If we do not have a local_id in a signature packet, find the owner of
@@ -613,7 +660,7 @@ set_signature_packets_local_id( PKT_signature *sig )
if( rc)
goto leave;
if( !pkc->local_id ) {
- rc = scan_record_by_pkc( pkc, &rec, 2 );
+ rc = search_record( pkc, &rec );
if( rc == -1 )
rc = insert_trust_record( pkc );
if( rc )
@@ -628,127 +675,32 @@ set_signature_packets_local_id( PKT_signature *sig )
}
-void
-list_trustdb( const char *username )
-{
- TRUSTREC rec;
- if( username ) {
- PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
- int rc;
-
- if( (rc = get_pubkey_byname( pkc, username )) )
- log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
- else if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 )
- log_error("problem finding '%s' in trustdb: %s\n",
- username, g10_errstr(rc));
- else if( rc == -1 )
- log_error("user '%s' not in trustdb\n", username);
- else if( (rc = list_sigs( pkc->local_id )) )
- log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
- free_public_cert( pkc );
- }
- else {
- ulong recnum;
- int i;
-
- printf("TrustDB: %s\n", db_name );
- for(i=9+strlen(db_name); i > 0; i-- )
- putchar('-');
- putchar('\n');
- for(recnum=0; !read_record( recnum, &rec); recnum++ )
- dump_record( recnum, &rec, stdout );
- }
-}
-
-void
-list_trust_path( int max_depth, const char *username )
+static int
+keyid_from_local_id( ulong lid, u32 *keyid )
{
- int rc;
- int wipe=0;
- int i;
TRUSTREC rec;
- PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
-
- if( max_depth < 0 ) {
- wipe = 1;
- max_depth = -max_depth;
- }
+ int rc;
- if( (rc = get_pubkey_byname( pkc, username )) )
- log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
- else if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 )
- log_error("problem finding '%s' in trustdb: %s\n",
- username, g10_errstr(rc));
- else if( rc == -1 ) {
- log_info("user '%s' not in trustdb - inserting\n", username);
- rc = insert_trust_record( pkc );
- if( rc )
- log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
- else {
- assert( pkc->local_id );
- }
+ rc = read_record( lid, &rec );
+ if( rc ) {
+ log_error("error reading record with local_id %lu: %s\n",
+ lid, g10_errstr(rc));
+ return G10ERR_TRUSTDB;
}
-
- if( !rc ) {
- TRUST_SEG_LIST tsl, tslist = NULL;
-
- if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
- tslist = m_alloc( sizeof *tslist );
- tslist->nseg = 1;
- tslist->dup = 0;
- tslist->seg[0].lid = pkc->local_id;
- tslist->seg[0].trust = 0;
- tslist->next = NULL;
- rc = 0;
- }
- else {
- LOCAL_ID_INFO *lids = new_lid_table();
- TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
-
- stack[0].lid = pkc->local_id;
- stack[0].trust = 0;
- rc = do_list_path( stack, 1, max_depth, lids, &tslist );
- if( wipe ) { /* wipe out duplicates */
- LOCAL_ID_INFO *work;
-
- work = new_lid_table();
- for( tsl=tslist; tsl; tsl = tsl->next ) {
- for(i=1; i < tsl->nseg-1; i++ ) {
- if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
- tsl->dup = 1; /* mark as duplicate */
- break;
- }
- }
- }
- release_lid_table(work);
- }
- release_lid_table(lids);
- }
- if( rc )
- log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
- rc = propagate_trust( tslist );
- if( rc )
- log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
- for(tsl = tslist; tsl; tsl = tsl->next ) {
- int i;
-
- if( tsl->dup )
- continue;
- printf("trust path:" );
- for(i=0; i < tsl->nseg; i++ )
- printf(" %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
- putchar('\n');
- }
+ if( rec.rectype != RECTYPE_DIR ) {
+ log_error("record with local_id %lu is not a dir record\n", lid);
+ return G10ERR_TRUSTDB;
}
-
- free_public_cert( pkc );
+ keyid[0] = rec.r.dir.keyid[0];
+ keyid[1] = rec.r.dir.keyid[1];
+ return 0;
}
/****************
* Walk throug the signatures of a public key.
* The caller must provide a context structure, with all fields set
- * to zero, but the pubkeyid filed set to the requested pubkey;
+ * to zero, but the local_id field set to the requested key;
* This function does not change this field. On return the context
* is filled with the local-id of the signature and the signature flag.
* No fields should be changed (clearing all fields and setting
@@ -758,6 +710,8 @@ list_trust_path( int max_depth, const char *username )
static int
walk_sigrecs( SIGREC_CONTEXT *c, int create )
{
+!!!!!!FIXME!!!!!!!
+
int rc=0;
TRUSTREC *r;
ulong rnum;
@@ -766,6 +720,7 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
return -1;
r = &c->ctl.rec;
if( !r->rectype ) { /* this is the first call */
+
rc = scan_record( c->pubkey_id, r, 4, &rnum );
if( rc == -1 && create ) { /* no signature records */
rc = build_sigrecs( c->pubkey_id, 1 );
@@ -817,101 +772,12 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
return 0;
}
-/***********************************************
- ************* trust logic *******************
- ***********************************************/
-static LOCAL_ID_INFO *
-new_lid_table(void)
-{
- return m_alloc_clear( 16 * sizeof(LOCAL_ID_INFO));
-}
-static void
-release_lid_table( LOCAL_ID_INFO *tbl )
-{
- LOCAL_ID_INFO a, a2;
- int i;
- for(i=0; i < 16; i++ ) {
- for(a=tbl[i]; a; a = a2 ) {
- a2 = a->next;
- m_free(a);
- }
- }
- m_free(tbl);
-}
-
-/****************
- * Add a new item to the table or return 1 if we aread have this item
- * fixme: maybe its a good idea to tage items from an unused item list.
- */
-static int
-ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
-{
- LOCAL_ID_INFO a;
-
- for( a = tbl[lid & 0x0f]; a; a = a->next )
- if( a->lid == lid )
- return 1;
- a = m_alloc( sizeof *a );
- a->lid = lid;
- a->flag = flag;
- a->next = tbl[lid & 0x0f];
- tbl[lid & 0x0f] = a;
- return 0;
-}
-
-static int
-qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag )
-{
- LOCAL_ID_INFO a;
-
- for( a = tbl[lid & 0x0f]; a; a = a->next )
- if( a->lid == lid ) {
- if( flag )
- *flag = a->flag;
- return 0;
- }
- return -1;
-}
-
-static void
-upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
-{
- LOCAL_ID_INFO a;
-
- for( a = tbl[lid & 0x0f]; a; a = a->next )
- if( a->lid == lid ) {
- a->flag = flag;
- return;
- }
- BUG();
-}
-
-
-
-
-static int
-keyid_from_local_id( ulong lid, u32 *keyid )
-{
- TRUSTREC rec;
- int rc;
-
- rc = read_record( lid, &rec );
- if( rc ) {
- log_error("error reading record with local_id %lu: %s\n",
- lid, g10_errstr(rc));
- return G10ERR_TRUSTDB;
- }
- if( rec.rectype != 2 ) {
- log_error("record with local_id %lu is not a pubkey record\n", lid);
- return G10ERR_TRUSTDB;
- }
- keyid[0] = rec.r.pubkey.keyid[0];
- keyid[1] = rec.r.pubkey.keyid[1];
- return 0;
-}
+/***********************************************
+ ************* Trust stuff ******************
+ ***********************************************/
/****************
@@ -992,6 +858,7 @@ verify_own_certs()
return rc;
}
+
static void
print_user_id( const char *text, u32 *keyid )
{
@@ -1020,7 +887,7 @@ do_list_sigs( ulong root, ulong pubkey, int depth,
u32 keyid[2];
memset( &sx, 0, sizeof sx );
- sx.pubkey_id = pubkey;
+ sx.local_id = pubkey;
for(;;) {
rc = walk_sigrecs( &sx, 0 );
if( rc )
@@ -1098,6 +965,9 @@ list_sigs( ulong pubkey_id )
+/****************
+ * Function to collect all trustpaths
+ */
static int
do_list_path( TRUST_INFO *stack, int depth, int max_depth,
LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist )
@@ -1114,7 +984,7 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
return 0;
}
memset( &sx, 0, sizeof sx );
- sx.pubkey_id = stack[depth-1].lid;
+ sx.local_id = stack[depth-1].lid;
/* loop over all signatures. If we do not have any, try to
* create them */
while( !(rc = walk_sigrecs( &sx, 1 )) ) {
@@ -1170,7 +1040,10 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
/****************
* Check all the sigs of the given keyblock and mark them
- * as checked.
+ * as checked. Valid signatures which are duplicates are
+ * also marked [shall we check them at all?]
+ * FIXME: what shall we do if we have duplicate signatures were only
+ * some of them are bad?
*/
static int
check_sigs( KBNODE keyblock, int *selfsig_okay )
@@ -1178,6 +1051,7 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
KBNODE kbctx;
KBNODE node;
int rc;
+ LOCAL_ID_INFO *dups = NULL;
*selfsig_okay = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
@@ -1192,6 +1066,11 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
}
else
node->flag |= 1; /* mark signature valid */
+ if( !dups )
+ dups = new_lid_table();
+ if( ins_lid_table_item( dups,
+ node->pkt->pkt.signature->local_id, 0) )
+ node->flag |= 4; /* mark as duplicate */
}
if( DBG_TRUST )
log_debug("trustdb: sig from %08lX: %s\n",
@@ -1199,6 +1078,8 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
g10_errstr(rc) );
}
}
+ if( dups )
+ release_lid_table(dups);
return 0;
}
@@ -1210,7 +1091,7 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
static int
build_sigrecs( ulong pubkeyid, int kludge )
{
- TRUSTREC rec, rec2;
+ TRUSTREC rec, krec, rec2;
PUBKEY_FIND_INFO finfo=NULL;
KBPOS kbpos;
KBNODE keyblock = NULL;
@@ -1225,18 +1106,22 @@ build_sigrecs( ulong pubkeyid, int kludge )
/* get the keyblock */
if( (rc=read_record( pubkeyid, &rec )) ) {
- log_error("build_sigrecs: can't read pubkey record\n");
+ log_error("%lu: build_sigrecs: can't read dir record\n", pubkeyid );
goto leave;
}
- if( kludge && rec.r.pubkey.no_sigs ) {
+ if( kludge && rec.r.dir.no_sigs ) {
rc = -1;
goto leave;
}
finfo = m_alloc_clear( sizeof *finfo );
- finfo->keyid[0] = rec.r.pubkey.keyid[0];
- finfo->keyid[1] = rec.r.pubkey.keyid[1];
- finfo->pubkey_algo = rec.r.pubkey.pubkey_algo;
- memcpy( finfo->fingerprint, rec.r.pubkey.fingerprint, 20);
+ finfo->keyid[0] = rec.r.dir.keyid[0];
+ finfo->keyid[1] = rec.r.dir.keyid[1];
+ if( (rc=read_record( rec.r.dir.keyrec, &krec )) ) {
+ log_error("%lu: build_sigrecs: can't read key record\n", pubkeyid);
+ goto leave;
+ }
+ finfo->pubkey_algo = krec.r.key.pubkey_algo;
+ memcpy( finfo->fingerprint, krec.r.key.fingerprint, 20);
rc = find_keyblock( finfo, &kbpos );
if( rc ) {
log_error("build_sigrecs: find_keyblock failed\n" );
@@ -1264,11 +1149,12 @@ build_sigrecs( ulong pubkeyid, int kludge )
/* valid key signatures are now marked; we can now build the
* sigrecs */
memset( &rec, 0, sizeof rec );
- rec.rectype = 4;
+ rec.rectype = RECTYPE_SIG;
i = 0;
rnum = rnum2 = 0;
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
- if( node->flag & 1 ) {
+ /* insert sigs which are not a selfsig nor a duplicate */
+ if( (node->flag & 1) && !(node->flag & 4) ) {
assert( node->pkt->pkttype == PKT_SIGNATURE );
if( !node->pkt->pkt.signature->local_id ) {
/* the next function should always succeed, because
@@ -1286,8 +1172,8 @@ build_sigrecs( ulong pubkeyid, int kludge )
/* write the record */
rnum = new_recnum();
if( rnum2 ) { /* write the stored record */
- rec2.r.sigrec.owner = pubkeyid;
- rec2.r.sigrec.chain = rnum; /* the next record number */
+ rec2.r.sig.owner = pubkeyid;
+ rec2.r.sig.chain = rnum; /* the next record number */
rc = write_record( rnum2, &rec2 );
if( rc ) {
log_error("build_sigrecs: write_record failed\n" );
@@ -1297,11 +1183,11 @@ build_sigrecs( ulong pubkeyid, int kludge )
rec2 = rec;
rnum2 = rnum;
memset( &rec, 0, sizeof rec );
- rec.rectype = 5;
+ rec.rectype = RECTYPE_SIG;
i = 0;
}
- rec.r.sigrec.sig[i].local_id = node->pkt->pkt.signature->local_id;
- rec.r.sigrec.sig[i].flag = 0;
+ rec.r.sig.sig[i].local_id = node->pkt->pkt.signature->local_id;
+ rec.r.sig.sig[i].flag = 0;
i++;
}
}
@@ -1309,8 +1195,8 @@ build_sigrecs( ulong pubkeyid, int kludge )
/* write the record */
rnum = new_recnum();
if( rnum2 ) { /* write the stored record */
- rec2.r.sigrec.owner = pubkeyid;
- rec2.r.sigrec.chain = rnum;
+ rec2.r.sig.owner = pubkeyid;
+ rec2.r.sig.chain = rnum;
rc = write_record( rnum2, &rec2 );
if( rc ) {
log_error("build_sigrecs: write_record failed\n" );
@@ -1318,8 +1204,8 @@ build_sigrecs( ulong pubkeyid, int kludge )
}
}
if( i ) { /* write the pending record */
- rec.r.sigrec.owner = pubkeyid;
- rec.r.sigrec.chain = 0;
+ rec.r.sig.owner = pubkeyid;
+ rec.r.sig.chain = 0;
rc = write_record( rnum, &rec );
if( rc ) {
log_error("build_sigrecs: write_record failed\n" );
@@ -1568,6 +1454,124 @@ init_trustdb( int level )
}
+void
+list_trustdb( const char *username )
+{
+ TRUSTREC rec;
+
+ if( username ) {
+ PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+ int rc;
+
+ if( (rc = get_pubkey_byname( pkc, username )) )
+ log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
+ else if( (rc=search_record( pkc, &rec )) && rc != -1 )
+ log_error("problem finding '%s' in trustdb: %s\n",
+ username, g10_errstr(rc));
+ else if( rc == -1 )
+ log_error("user '%s' not in trustdb\n", username);
+ else if( (rc = list_sigs( pkc->local_id )) )
+ log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
+ free_public_cert( pkc );
+ }
+ else {
+ ulong recnum;
+ int i;
+
+ printf("TrustDB: %s\n", db_name );
+ for(i=9+strlen(db_name); i > 0; i-- )
+ putchar('-');
+ putchar('\n');
+ for(recnum=0; !read_record( recnum, &rec); recnum++ )
+ dump_record( recnum, &rec, stdout );
+ }
+}
+
+void
+list_trust_path( int max_depth, const char *username )
+{
+ int rc;
+ int wipe=0;
+ int i;
+ TRUSTREC rec;
+ PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+
+ if( max_depth < 0 ) {
+ wipe = 1;
+ max_depth = -max_depth;
+ }
+
+ if( (rc = get_pubkey_byname( pkc, username )) )
+ log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
+ else if( (rc=search_record( pkc, &rec )) && rc != -1 )
+ log_error("problem finding '%s' in trustdb: %s\n",
+ username, g10_errstr(rc));
+ else if( rc == -1 ) {
+ log_info("user '%s' not in trustdb - inserting\n", username);
+ rc = insert_trust_record( pkc );
+ if( rc )
+ log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc));
+ else {
+ assert( pkc->local_id );
+ }
+ }
+
+ if( !rc ) {
+ TRUST_SEG_LIST tsl, tslist = NULL;
+
+ if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) {
+ tslist = m_alloc( sizeof *tslist );
+ tslist->nseg = 1;
+ tslist->dup = 0;
+ tslist->seg[0].lid = pkc->local_id;
+ tslist->seg[0].trust = 0;
+ tslist->next = NULL;
+ rc = 0;
+ }
+ else {
+ LOCAL_ID_INFO *lids = new_lid_table();
+ TRUST_INFO stack[MAX_LIST_SIGS_DEPTH];
+
+ stack[0].lid = pkc->local_id;
+ stack[0].trust = 0;
+ rc = do_list_path( stack, 1, max_depth, lids, &tslist );
+ if( wipe ) { /* wipe out duplicates */
+ LOCAL_ID_INFO *work;
+
+ work = new_lid_table();
+ for( tsl=tslist; tsl; tsl = tsl->next ) {
+ for(i=1; i < tsl->nseg-1; i++ ) {
+ if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) {
+ tsl->dup = 1; /* mark as duplicate */
+ break;
+ }
+ }
+ }
+ release_lid_table(work);
+ }
+ release_lid_table(lids);
+ } cvs checkout -h
+ if( rc )
+ log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
+ rc = propagate_trust( tslist );
+ if( rc )
+ log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc));
+ for(tsl = tslist; tsl; tsl = tsl->next ) {
+ int i;
+
+ if( tsl->dup )
+ continue;
+ printf("trust path:" );
+ for(i=0; i < tsl->nseg; i++ )
+ printf(" %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust );
+ putchar('\n');
+ }
+ }
+
+ free_public_cert( pkc );
+}
+
+
/****************
* Get the trustlevel for this PKC.
* Note: This does not ask any questions