aboutsummaryrefslogtreecommitdiffstats
path: root/g10/tdbio.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/tdbio.c549
1 files changed, 320 insertions, 229 deletions
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 70cf4a1ba..82b22b43a 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -39,6 +39,18 @@
#include "trustdb.h"
#include "tdbio.h"
+/* a type used to pass infomation to cmp_krec_fpr */
+struct cmp_krec_fpr_struct {
+ int pubkey_algo;
+ const char *fpr;
+ int fprlen;
+};
+
+/* a type used to pass infomation to cmp_sdir */
+struct cmp_sdir_struct {
+ int pubkey_algo;
+ u32 keyid[2];
+};
static char *db_name;
@@ -149,6 +161,47 @@ open_db()
/****************
+ * Make a hashtable: type 0 = key hash, 1 = sdir hash
+ */
+static void
+create_hashtable( TRUSTREC *vr, int type )
+{
+ TRUSTREC rec;
+ off_t offset;
+ ulong recnum;
+ int i, n, rc;
+
+ offset = lseek( db_fd, 0, SEEK_END );
+ if( offset == -1 )
+ log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
+ recnum = offset / TRUST_RECORD_LEN;
+ assert(recnum); /* this is will never be the first record */
+
+ if( !type )
+ vr->r.ver.keyhashtbl = recnum;
+ else
+ vr->r.ver.sdirhashtbl = recnum;
+ /* Now write the records */
+ n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
+ for(i=0; i < n; i++, recnum++ ) {
+ memset( &rec, 0, sizeof rec );
+ rec.rectype = RECTYPE_HTBL; /* free record */
+ rec.recnum = recnum;
+ rc = tdbio_write_record( &rec );
+ if( rc )
+ log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
+ g10_errstr(rc));
+ }
+ /* update the version record */
+ rc = tdbio_write_record( vr );
+ if( rc )
+ log_fatal_f( db_name, _("error updating version record: %s\n"),
+ g10_errstr(rc));
+}
+
+
+
+/****************
* Return the record number of the keyhash tbl or create a new one.
*/
static ulong
@@ -165,48 +218,45 @@ get_keyhashrec()
if( rc )
log_fatal_f( db_name, _("error reading version record: %s\n"),
g10_errstr(rc) );
- if( vr.r.ver.keyhashtbl )
- keyhashtbl = vr.r.ver.keyhashtbl;
- else {
- TRUSTREC rec;
- off_t offset;
- ulong recnum;
- int i, n;
+ if( !vr.r.ver.keyhashtbl )
+ create_hashtable( &vr, 0 );
- offset = lseek( db_fd, 0, SEEK_END );
- if( offset == -1 )
- log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
- recnum = offset / TRUST_RECORD_LEN;
- assert(recnum); /* this is will never be the first record */
- keyhashtbl = recnum;
- /* Now write the records */
- n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
- for(i=0; i < n; i++, recnum++ ) {
- memset( &rec, 0, sizeof rec );
- rec.rectype = RECTYPE_HTBL; /* free record */
- rec.recnum = recnum;
- rc = tdbio_write_record( &rec );
- if( rc )
- log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
- g10_errstr(rc));
- }
- /* update the version record */
- vr.r.ver.keyhashtbl = keyhashtbl;
- rc = tdbio_write_record( &vr );
- if( rc )
- log_fatal_f( db_name, _("error updating version record: %s\n"),
- g10_errstr(rc));
- }
- return keyhashtbl;
+ return vr.r.ver.keyhashtbl;
+}
+
+/****************
+ * Return the record number of the shadow direcory hash table
+ * or create a new one.
+ */
+static ulong
+get_sdirhashrec()
+{
+ static ulong sdirhashtbl; /* record number of the hashtable */
+ TRUSTREC vr;
+ int rc;
+
+ if( sdirhashtbl )
+ return sdirhashtbl;
+
+ rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
+ if( rc )
+ log_fatal_f( db_name, _("error reading version record: %s\n"),
+ g10_errstr(rc) );
+ if( !vr.r.ver.sdirhashtbl )
+ create_hashtable( &vr, 1 );
+
+ return vr.r.ver.sdirhashtbl;
}
/****************
- * Update the key hashtbl or create the table if it does not exist
+ * Update a hashtable.
+ * table gives the start of the table, key and keylen is the key,
+ * newrecnum is the record number to insert.
*/
static int
-update_keyhashtbl( TRUSTREC *kr )
+upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
{
TRUSTREC lastrec, rec;
ulong hashrec, item;
@@ -214,40 +264,40 @@ update_keyhashtbl( TRUSTREC *kr )
int level=0;
int rc, i;
- hashrec = get_keyhashrec();
+ hashrec = table;
next_level:
- msb = kr->r.key.fingerprint[level];
+ msb = key[level];
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
if( rc ) {
- log_error( db_name, "update_keyhashtbl read failed: %s\n",
+ log_error( db_name, "upd_hashtable: read failed: %s\n",
g10_errstr(rc) );
return rc;
}
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
- if( !item ) { /* insert new one */
- rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = kr->recnum;
+ if( !item ) { /* insert a new item into the hash table */
+ rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc ) {
- log_error( db_name, "update_keyhashtbl write htbl failed: %s\n",
+ log_error( db_name, "upd_hashtable: write htbl failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
- else if( item != kr->recnum ) { /* must do an update */
+ else if( item != newrecnum ) { /* must do an update */
lastrec = rec;
rc = tdbio_read_record( item, &rec, 0 );
if( rc ) {
- log_error( db_name, "update_keyhashtbl read item failed: %s\n",
+ log_error( db_name, "upd_hashtable: read item failed: %s\n",
g10_errstr(rc) );
return rc;
}
if( rec.rectype == RECTYPE_HTBL ) {
hashrec = item;
level++;
- if( level >= kr->r.key.fingerprint_len ) {
- log_error( db_name, "keyhashtbl has invalid indirections\n");
+ if( level >= keylen ) {
+ log_error( db_name, "hashtable has invalid indirections.\n");
return G10ERR_TRUSTDB;
}
goto next_level;
@@ -256,15 +306,13 @@ update_keyhashtbl( TRUSTREC *kr )
/* see whether the key is already in this list */
for(;;) {
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
- if( rec.r.hlst.rnum[i] == kr->recnum ) {
- log_debug("HTBL: no update needed for keyrec %lu\n",
- kr->recnum );
- return 0;
+ if( rec.r.hlst.rnum[i] == newrecnum ) {
+ return 0; /* okay, already in the list */
}
}
if( rec.r.hlst.next ) {
rc = tdbio_read_record( rec.r.hlst.next,
- &rec, RECTYPE_HLST);
+ &rec, RECTYPE_HLST);
if( rc ) {
log_error( db_name,
"scan keyhashtbl read hlst failed: %s\n",
@@ -279,13 +327,13 @@ update_keyhashtbl( TRUSTREC *kr )
for(;;) {
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
if( !rec.r.hlst.rnum[i] ) {
- rec.r.hlst.rnum[i] = kr->recnum;
+ rec.r.hlst.rnum[i] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc )
log_error( db_name,
- "update_keyhashtbl write hlst failed: %s\n",
+ "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
- return rc; /* ready */
+ return rc; /* done */
}
}
if( rec.r.hlst.next ) {
@@ -293,7 +341,7 @@ update_keyhashtbl( TRUSTREC *kr )
&rec, RECTYPE_HLST );
if( rc ) {
log_error( db_name,
- "update_keyhashtbl read hlst failed: %s\n",
+ "upd_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -303,26 +351,26 @@ update_keyhashtbl( TRUSTREC *kr )
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( db_name,
- "update_keyhashtbl write hlst failed: %s\n",
+ "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_HLST;
rec.recnum = item;
- rec.r.hlst.rnum[0] = kr->recnum;
+ rec.r.hlst.rnum[0] = newrecnum;
+ rc = tdbio_write_record( &rec );
if( rc )
log_error( db_name,
- "update_keyhashtbl write ext hlst failed: %s\n",
+ "upd_hashtable: write ext hlst failed: %s\n",
g10_errstr(rc) );
- return rc; /* ready */
+ return rc; /* done */
}
- }
+ } /* end loop over hlst slots */
}
- else if( rec.rectype == RECTYPE_KEY ) { /* insert a list record */
- if( rec.recnum == kr->recnum ) {
- log_debug("HTBL: no update needed for keyrec %lu\n",
- kr->recnum );
+ else if( rec.rectype == RECTYPE_KEY
+ || rec.rectype == RECTYPE_SDIR ) { /* insert a list record */
+ if( rec.recnum == newrecnum ) {
return 0;
}
item = rec.recnum; /* save number of key record */
@@ -330,11 +378,11 @@ update_keyhashtbl( TRUSTREC *kr )
rec.rectype = RECTYPE_HLST;
rec.recnum = tdbio_new_recnum();
rec.r.hlst.rnum[0] = item; /* old keyrecord */
- rec.r.hlst.rnum[1] = kr->recnum; /* and new one */
+ rec.r.hlst.rnum[1] = newrecnum; /* and new one */
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( db_name,
- "update_keyhashtbl write new hlst failed: %s\n",
+ "upd_hashtable: write new hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
@@ -342,13 +390,12 @@ update_keyhashtbl( TRUSTREC *kr )
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
rc = tdbio_write_record( &lastrec );
if( rc )
- log_error( db_name,
- "update_keyhashtbl update htbl failed: %s\n",
- g10_errstr(rc) );
+ log_error( db_name, "upd_hashtable: update htbl failed: %s\n",
+ g10_errstr(rc) );
return rc; /* ready */
}
else {
- log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
+ log_error( db_name, "hashtbl %lu points to an invalid record\n",
item);
return G10ERR_TRUSTDB;
}
@@ -359,6 +406,119 @@ update_keyhashtbl( TRUSTREC *kr )
+/****************
+ * Lookup a record via the hashtable tablewith key/keylen and return the
+ * result in rec. cmp() should return if the record is the desired one.
+ * Returns -1 if not found, 0 if found or another errocode
+ */
+static int
+lookup_hashtable( ulong table, const byte *key, size_t keylen,
+ int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata,
+ TRUSTREC *rec )
+{
+ int rc;
+ ulong hashrec, item;
+ int msb;
+ int level=0;
+
+ hashrec = table;
+ next_level:
+ msb = key[level];
+ hashrec += msb / ITEMS_PER_HTBL_RECORD;
+ rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
+ if( rc ) {
+ log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) );
+ return rc;
+ }
+
+ item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
+ if( !item )
+ return -1; /* not found */
+
+ rc = tdbio_read_record( item, rec, 0 );
+ if( rc ) {
+ log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) );
+ return rc;
+ }
+ if( rec->rectype == RECTYPE_HTBL ) {
+ hashrec = item;
+ level++;
+ if( level >= keylen ) {
+ log_error( db_name, "hashtable has invalid indirections\n");
+ return G10ERR_TRUSTDB;
+ }
+ goto next_level;
+ }
+ else if( rec->rectype == RECTYPE_HLST ) {
+ for(;;) {
+ int i;
+
+ for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
+ if( rec->r.hlst.rnum[i] ) {
+ TRUSTREC tmp;
+
+ rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
+ if( rc ) {
+ log_error( "lookup_hashtable: read item failed: %s\n",
+ g10_errstr(rc) );
+ return rc;
+ }
+ if( (*cmpfnc)( cmpdata, &tmp ) ) {
+ *rec = tmp;
+ return 0;
+ }
+ }
+ }
+ if( rec->r.hlst.next ) {
+ rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
+ if( rc ) {
+ log_error( "lookup_hashtable: read hlst failed: %s\n",
+ g10_errstr(rc) );
+ return rc;
+ }
+ }
+ else
+ return -1; /* not found */
+ }
+ }
+
+
+ if( (*cmpfnc)( cmpdata, rec ) )
+ return 0; /* really found */
+
+ return -1; /* no: not found */
+}
+
+
+
+
+/****************
+ * Update the key hashtbl or create the table if it does not exist
+ */
+static int
+update_keyhashtbl( TRUSTREC *kr )
+{
+ return upd_hashtable( get_keyhashrec(),
+ kr->r.key.fingerprint,
+ kr->r.key.fingerprint_len, kr->recnum );
+}
+
+/****************
+ * Update the shadow dir hashtbl or create the table if it does not exist
+ */
+static int
+update_sdirhashtbl( TRUSTREC *sr )
+{
+ byte key[8];
+
+ u32tobuf( key , sr->r.sdir.keyid[0] );
+ u32tobuf( key+4 , sr->r.sdir.keyid[1] );
+ return upd_hashtable( get_sdirhashrec(), key, 8, sr->recnum );
+}
+
+
+
+
void
tdbio_dump_record( TRUSTREC *rec, FILE *fp )
{
@@ -371,8 +531,9 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
switch( rec->rectype ) {
case 0: fprintf(fp, "blank\n");
break;
- case RECTYPE_VER: fprintf(fp, "version, keyhashtbl=%lu, firstfree=%lu\n",
- rec->r.ver.keyhashtbl, rec->r.ver.firstfree );
+ case RECTYPE_VER: fprintf(fp, "version, kd=%lu, sd=%lu, free=%lu\n",
+ rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
+ rec->r.ver.firstfree );
break;
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
break;
@@ -411,6 +572,10 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
+ if( rec->r.uid.uidflags & UIDF_CHECKED )
+ fputs(", checked", fp );
+ if( rec->r.uid.uidflags & UIDF_VALID )
+ fputs(", valid", fp );
if( rec->r.uid.uidflags & UIDF_REVOKED )
fputs(", revoked", fp );
putc('\n', fp);
@@ -436,6 +601,14 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
}
putc('\n', fp);
break;
+ case RECTYPE_SDIR:
+ fprintf(fp, "sdir %lu, keyid=%08lX%08lX, algo=%d, hint=%lu\n",
+ rec->r.sdir.lid,
+ (ulong)rec->r.sdir.keyid[0],
+ (ulong)rec->r.sdir.keyid[1],
+ rec->r.sdir.pubkey_algo,
+ (ulong)rec->r.sdir.hintlist );
+ break;
case RECTYPE_CACH:
fprintf(fp, "cach\n");
break;
@@ -483,6 +656,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
return G10ERR_READ_FILE;
}
rec->recnum = recnum;
+ rec->dirty = 0;
p = buf;
rec->rectype = *p++;
if( expected && rec->rectype != expected ) {
@@ -508,6 +682,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.ver.validated= buftoulong(p); p += 4;
rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
rec->r.ver.firstfree =buftoulong(p); p += 4;
+ rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
if( recnum ) {
log_error_f( db_name, "version record with recnum %lu\n",
(ulong)recnum );
@@ -568,6 +743,19 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.sig.sig[i].flag = *p++;
}
break;
+ case RECTYPE_SDIR: /* shadow directory record */
+ rec->r.sdir.lid = buftoulong(p); p += 4;
+ rec->r.sdir.keyid[0]= buftou32(p); p += 4;
+ rec->r.sdir.keyid[1]= buftou32(p); p += 4;
+ rec->r.sdir.pubkey_algo = *p++;
+ p += 3;
+ rec->r.sdir.hintlist = buftoulong(p);
+ if( rec->r.sdir.lid != recnum ) {
+ log_error_f( db_name, "sdir LID != recnum (%lu,%lu)\n",
+ rec->r.sdir.lid, (ulong)recnum );
+ rc = G10ERR_TRUSTDB;
+ }
+ break;
case RECTYPE_CACH: /* cache record (FIXME)*/
rec->r.cache.lid = buftoulong(p); p += 4;
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
@@ -609,6 +797,8 @@ tdbio_write_record( TRUSTREC *rec )
if( db_fd == -1 )
open_db();
+tdbio_dump_record( rec, stdout );
+
memset(buf, 0, TRUST_RECORD_LEN);
p = buf;
*p++ = rec->rectype; p++;
@@ -626,6 +816,7 @@ tdbio_write_record( TRUSTREC *rec )
ulongtobuf(p, rec->r.ver.validated); p += 4;
ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
+ ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4;
break;
case RECTYPE_FREE:
@@ -677,6 +868,15 @@ tdbio_write_record( TRUSTREC *rec )
}
break;
+ case RECTYPE_SDIR:
+ ulongtobuf( p, rec->r.sdir.lid); p += 4;
+ u32tobuf( p, rec->r.sdir.keyid[0] ); p += 4;
+ u32tobuf( p, rec->r.sdir.keyid[1] ); p += 4;
+ *p++ = rec->r.sdir.pubkey_algo;
+ p += 3;
+ ulongtobuf( p, rec->r.sdir.hintlist );
+ break;
+
case RECTYPE_CACH: /* FIXME*/
ulongtobuf(p, rec->r.cache.lid); p += 4;
memcpy(p, rec->r.cache.blockhash, 20); p += 20;
@@ -711,6 +911,8 @@ tdbio_write_record( TRUSTREC *rec )
}
else if( rec->rectype == RECTYPE_KEY )
rc = update_keyhashtbl( rec );
+ else if( rec->rectype == RECTYPE_SDIR )
+ rc = update_sdirhashtbl( rec );
return rc;
}
@@ -805,13 +1007,13 @@ tdbio_new_recnum()
int
tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
{
- byte *fingerprint;
+ byte fingerprint[MAX_FINGERPRINT_LEN];
size_t fingerlen;
u32 keyid[2];
int rc;
keyid_from_pk( pk, keyid );
- fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
+ fingerprint_from_pk( pk, fingerprint, &fingerlen );
rc = tdbio_search_dir_byfpr( fingerprint, fingerlen,
pk->pubkey_algo, rec );
@@ -827,185 +1029,74 @@ tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
}
+static int
+cmp_krec_fpr( void *dataptr, const TRUSTREC *rec )
+{
+ const struct cmp_krec_fpr_struct *d = dataptr;
+
+ return rec->rectype == RECTYPE_KEY
+ && ( !d->pubkey_algo || rec->r.key.pubkey_algo == d->pubkey_algo )
+ && rec->r.key.fingerprint_len == d->fprlen
+ && !memcmp( rec->r.key.fingerprint, d->fpr, d->fprlen );
+}
+
int
tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec )
{
+ struct cmp_krec_fpr_struct cmpdata;
ulong recnum;
int rc;
- ulong hashrec, item;
- int msb;
- int level=0;
assert( fingerlen == 20 || fingerlen == 16 );
/* locate the key using the hash table */
- hashrec = get_keyhashrec();
- next_level:
- msb = fingerprint[level];
- hashrec += msb / ITEMS_PER_HTBL_RECORD;
- rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
- if( rc ) {
- log_error( db_name, "scan keyhashtbl failed: %s\n", g10_errstr(rc) );
- return rc;
- }
-
- item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
- if( !item )
- return -1; /* not found */
-
- rc = tdbio_read_record( item, rec, 0 );
- if( rc ) {
- log_error( db_name, "keyhashtbl read failed: %s\n", g10_errstr(rc) );
- return rc;
- }
- if( rec->rectype == RECTYPE_HTBL ) {
- hashrec = item;
- level++;
- if( level >= fingerlen ) {
- log_error( db_name, "keyhashtbl has invalid indirections\n");
- return G10ERR_TRUSTDB;
- }
- goto next_level;
- }
- else if( rec->rectype == RECTYPE_HLST ) {
- for(;;) {
- int i;
-
- for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
- if( rec->r.hlst.rnum[i] ) {
- TRUSTREC tmp;
-
- rc = tdbio_read_record( rec->r.hlst.rnum[i],
- &tmp, RECTYPE_KEY );
- if( rc ) {
- log_error( db_name,
- "scan keyhashtbl read key failed: %s\n",
- g10_errstr(rc) );
- return rc;
- }
- if( (!pubkey_algo || tmp.r.key.pubkey_algo == pubkey_algo)
- && tmp.r.key.fingerprint_len == fingerlen
- && !memcmp(tmp.r.key.fingerprint,
- fingerprint, fingerlen) ) {
- *rec = tmp;
- goto found;
- }
- }
- }
- if( rec->r.hlst.next ) {
- rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
- if( rc ) {
- log_error( db_name,
- "scan keyhashtbl read hlst failed: %s\n",
- g10_errstr(rc) );
- return rc;
- }
- }
- else
- return -1; /* not found */
- }
- found:
- ;
- }
- else if( rec->rectype == RECTYPE_KEY ) {
- /* must check that it is the requested key */
- if( (pubkey_algo && rec->r.key.pubkey_algo != pubkey_algo)
- || rec->r.key.fingerprint_len != fingerlen
- || memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) )
- return -1; /* no: not found */
- }
- else {
- log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
- item);
- return G10ERR_TRUSTDB;
+ cmpdata.pubkey_algo = pubkey_algo;
+ cmpdata.fpr = fingerprint;
+ cmpdata.fprlen = fingerlen;
+ rc = lookup_hashtable( get_keyhashrec(), fingerprint, fingerlen,
+ cmp_krec_fpr, &cmpdata, rec );
+ if( !rc ) {
+ recnum = rec->r.key.lid;
+ /* Now read the dir record */
+ rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
+ if( rc )
+ log_error_f(db_name, "can't read dirrec %lu: %s\n",
+ recnum, g10_errstr(rc) );
}
-
- recnum = rec->r.key.lid;
- /* Now read the dir record */
- rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
- if( rc )
- log_error_f(db_name, "can't read dirrec %lu: %s\n",
- recnum, g10_errstr(rc) );
-
return rc;
}
+
+
static int
-del_reclist( ulong recno, int type )
+cmp_sdir( void *dataptr, const TRUSTREC *rec )
{
- TRUSTREC rec;
- int rc;
+ const struct cmp_sdir_struct *d = dataptr;
- while( recno ) {
- rc = tdbio_read_record( recno, &rec, type);
- if( rc ) {
- log_error_f(db_name, "can't read record %lu: %s\n",
- recno, g10_errstr(rc));
- return rc;
- }
- switch( type ) {
- case RECTYPE_PREF: recno = rec.r.pref.next; break;
- case RECTYPE_UID: recno = rec.r.uid.next; break;
- default: BUG();
- }
- rc = tdbio_delete_record( rec.recnum );
- if( rc ) {
- log_error_f(db_name, "can't delete record %lu: %s\n",
- rec.recnum, g10_errstr(rc));
- return rc;
- }
- }
- return 0;
+ return rec->rectype == RECTYPE_SDIR
+ && ( !d->pubkey_algo || rec->r.sdir.pubkey_algo == d->pubkey_algo )
+ && rec->r.sdir.keyid[0] == d->keyid[0]
+ && rec->r.sdir.keyid[1] == d->keyid[1];
}
-/****************
- * Delete the Userid UIDLID from DIRLID
- */
+
int
-tdbio_delete_uidrec( ulong dirlid, ulong uidlid )
+tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec )
{
- TRUSTREC dirrec, rec;
- ulong recno;
+ struct cmp_sdir_struct cmpdata;
int rc;
-
- rc = tdbio_read_record( dirlid, &dirrec, RECTYPE_DIR);
- if( rc ) {
- log_error_f(db_name, "can't read dirrec %lu: %s\n", dirlid, g10_errstr(rc));
- return rc;
- }
- recno = dirrec.r.dir.uidlist;
- for( ; recno; recno = rec.r.uid.next ) {
- rc = tdbio_read_record( recno, &rec, RECTYPE_UID);
- if( rc ) {
- log_error_f(db_name, "can't read uidrec %lu: %s\n",
- recno, g10_errstr(rc));
- return rc;
- }
- if( recno == uidlid ) {
- rc = del_reclist( rec.r.uid.prefrec, RECTYPE_PREF );
- if( rc )
- return rc;
- rc = del_reclist( rec.r.uid.siglist, RECTYPE_SIG );
- if( rc )
- return rc;
- rc = tdbio_delete_record( recno );
- if( rc ) {
- log_error_f(db_name, "can't delete uidrec %lu: %s\n",
- recno, g10_errstr(rc));
- return rc;
- }
- dirrec.r.dir.uidlist = 0;
- rc = tdbio_write_record( &dirrec );
- if( rc ) {
- log_error_f(db_name, "can't update dirrec %lu: %s\n",
- dirrec.recnum, g10_errstr(rc));
- return rc;
- }
- return 0;
- }
- }
- return -1; /* not found */
+ byte key[8];
+
+ /* locate the shadow dir record using the hash table */
+ u32tobuf( key , keyid[0] );
+ u32tobuf( key+4 , keyid[1] );
+ cmpdata.pubkey_algo = pubkey_algo;
+ cmpdata.keyid[0] = keyid[0];
+ cmpdata.keyid[1] = keyid[1];
+ rc = lookup_hashtable( get_sdirhashrec(), key, 8,
+ cmp_sdir, &cmpdata, rec );
+ return rc;
}