diff options
Diffstat (limited to 'g10/tdbio.c')
-rw-r--r-- | g10/tdbio.c | 145 |
1 files changed, 137 insertions, 8 deletions
diff --git a/g10/tdbio.c b/g10/tdbio.c index 39f1d5677..8e5f5d084 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -69,8 +69,8 @@ struct cmp_krec_fpr_struct { int fprlen; }; -/* a type used to pass infomation to cmp_sdir */ -struct cmp_sdir_struct { +/* a type used to pass infomation to cmp_[s]dir */ +struct cmp_xdir_struct { int pubkey_algo; u32 keyid[2]; }; @@ -852,8 +852,9 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) return rc; /* ready */ } else { - log_error( "hashtbl %lu points to an invalid record\n", - item); + log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n", + table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); + list_trustdb(NULL); return G10ERR_TRUSTDB; } } @@ -862,6 +863,92 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) } +/**************** + * Drop an entry from a hashtable + * table gives the start of the table, key and keylen is the key, + */ +static int +drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) +{ + TRUSTREC rec; + ulong hashrec, item; + int msb; + int level=0; + int rc, i; + + 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, "drop_from_hashtable: read failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; + if( !item ) /* not found - forget about it */ + return 0; + + if( item == recnum ) { /* tables points direct to the record */ + rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0; + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + rc = tdbio_read_record( item, &rec, 0 ); + if( rc ) { + log_error( "drop_from_hashtable: read item failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + if( rec.rectype == RECTYPE_HTBL ) { + hashrec = item; + level++; + if( level >= keylen ) { + log_error( "hashtable has invalid indirections.\n"); + return G10ERR_TRUSTDB; + } + goto next_level; + } + + if( rec.rectype == RECTYPE_HLST ) { + for(;;) { + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( rec.r.hlst.rnum[i] == recnum ) { + rec.r.hlst.rnum[i] = 0; /* drop */ + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + if( rec.r.hlst.next ) { + rc = tdbio_read_record( rec.r.hlst.next, + &rec, RECTYPE_HLST); + if( rc ) { + log_error( "scan keyhashtbl read hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else + return 0; /* key not in table */ + } + } + + log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", + table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); + return G10ERR_TRUSTDB; +} + + /**************** * Lookup a record via the hashtable tablewith key/keylen and return the @@ -973,6 +1060,30 @@ update_sdirhashtbl( TRUSTREC *sr ) return upd_hashtable( get_sdirhashrec(), key, 8, sr->recnum ); } +/**************** + * Drop the records from the key-hashtbl + */ +static int +drop_from_keyhashtbl( TRUSTREC *kr ) +{ + return drop_from_hashtable( get_keyhashrec(), + kr->r.key.fingerprint, + kr->r.key.fingerprint_len, kr->recnum ); +} + +/**************** + * Drop record drom the shadow dir hashtbl + */ +static int +drop_from_sdirhashtbl( TRUSTREC *sr ) +{ + byte key[8]; + + u32tobuf( key , sr->r.sdir.keyid[0] ); + u32tobuf( key+4 , sr->r.sdir.keyid[1] ); + return drop_from_hashtable( get_sdirhashrec(), key, 8, sr->recnum ); +} + @@ -1009,6 +1120,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) if( rec->r.dir.valcheck ) fprintf( fp, ", v=%02x/%s", rec->r.dir.validity, strtimestamp(rec->r.dir.valcheck) ); + if( rec->r.dir.checkat ) + fprintf( fp, ", a=%s", strtimestamp(rec->r.dir.checkat) ); if( rec->r.dir.dirflags & DIRF_CHECKED ) { if( rec->r.dir.dirflags & DIRF_VALID ) fputs(", valid", fp ); @@ -1071,7 +1184,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) fprintf(fp, " %lu:", rec->r.sig.sig[i].lid ); if( rec->r.sig.sig[i].flag & SIGF_CHECKED ) { fprintf(fp,"%c%c%c", - (rec->r.sig.sig[i].flag & SIGF_VALID) ? 'V':'-', + (rec->r.sig.sig[i].flag & SIGF_VALID) ? 'V': + (rec->r.sig.sig[i].flag & SIGF_IGNORED) ? 'I':'-', (rec->r.sig.sig[i].flag & SIGF_EXPIRED) ? 'E':'-', (rec->r.sig.sig[i].flag & SIGF_REVOKED) ? 'R':'-'); } @@ -1196,6 +1310,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) rec->r.dir.dirflags = *p++; rec->r.dir.validity = *p++; rec->r.dir.valcheck = buftoulong(p); p += 4; + rec->r.dir.checkat = buftoulong(p); p += 4; switch( rec->r.dir.validity ) { case 0: case TRUST_UNDEFINED: @@ -1346,6 +1461,7 @@ tdbio_write_record( TRUSTREC *rec ) *p++ = rec->r.dir.dirflags; *p++ = rec->r.dir.validity; ulongtobuf(p, rec->r.dir.valcheck); p += 4; + ulongtobuf(p, rec->r.dir.checkat); p += 4; assert( rec->r.dir.lid == recnum ); break; @@ -1419,7 +1535,7 @@ tdbio_write_record( TRUSTREC *rec ) rc = put_record_into_cache( recnum, buf ); if( rc ) ; - if( rec->rectype == RECTYPE_KEY ) + else if( rec->rectype == RECTYPE_KEY ) rc = update_keyhashtbl( rec ); else if( rec->rectype == RECTYPE_SDIR ) rc = update_sdirhashtbl( rec ); @@ -1433,6 +1549,19 @@ tdbio_delete_record( ulong recnum ) TRUSTREC vr, rec; int rc; + /* Must read the record fist, so we can drop it from the hash tables */ + rc = tdbio_read_record( recnum, &rec, 0 ); + if( rc ) + ; + else if( rec.rectype == RECTYPE_KEY ) + rc = drop_from_keyhashtbl( &rec ); + else if( rec.rectype == RECTYPE_SDIR ) + rc = drop_from_sdirhashtbl( &rec ); + + if( rc ) + return rc; + + /* now we can chnage it to a free record */ rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), @@ -1595,7 +1724,7 @@ tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen, static int cmp_sdir( void *dataptr, const TRUSTREC *rec ) { - const struct cmp_sdir_struct *d = dataptr; + const struct cmp_xdir_struct *d = dataptr; return rec->rectype == RECTYPE_SDIR && ( !d->pubkey_algo || rec->r.sdir.pubkey_algo == d->pubkey_algo ) @@ -1607,7 +1736,7 @@ cmp_sdir( void *dataptr, const TRUSTREC *rec ) int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec ) { - struct cmp_sdir_struct cmpdata; + struct cmp_xdir_struct cmpdata; int rc; byte key[8]; |