mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
backup
This commit is contained in:
parent
786a2870df
commit
8477407e79
48 changed files with 1965 additions and 1215 deletions
547
g10/tdbio.c
547
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;
|
||||
|
@ -148,6 +160,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.
|
||||
*/
|
||||
|
@ -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;
|
||||
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) );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
byte key[8];
|
||||
|
||||
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 */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue