diff options
Diffstat (limited to 'g10/tdbio.c')
-rw-r--r-- | g10/tdbio.c | 929 |
1 files changed, 375 insertions, 554 deletions
diff --git a/g10/tdbio.c b/g10/tdbio.c index 669f66ffc..537e4c0d4 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1,5 +1,5 @@ /* tdbio.c - * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -31,7 +31,7 @@ #include "errors.h" #include "iobuf.h" -#include <gcrypt.h> +#include "memory.h" #include "util.h" #include "options.h" #include "main.h" @@ -39,6 +39,9 @@ #include "trustdb.h" #include "tdbio.h" +#if defined(HAVE_DOSISH_SYSTEM) && !defined(__CYGWIN32__) +#define ftruncate chsize +#endif /**************** * Yes, this is a very simple implementation. We should really @@ -83,6 +86,8 @@ static int db_fd = -1; static int in_transaction; static void open_db(void); +static void migrate_from_v2 (void); + /************************************* @@ -115,13 +120,13 @@ write_cache_item( CACHE_CTRL r ) if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { log_error(_("trustdb rec %lu: lseek failed: %s\n"), r->recno, strerror(errno) ); - return GPGERR_WRITE_FILE; + return G10ERR_WRITE_FILE; } n = write( db_fd, r->data, TRUST_RECORD_LEN); if( n != TRUST_RECORD_LEN ) { log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), r->recno, n, strerror(errno) ); - return GPGERR_WRITE_FILE; + return G10ERR_WRITE_FILE; } r->flags.dirty = 0; return 0; @@ -175,7 +180,7 @@ put_record_into_cache( ulong recno, const char *data ) } /* see whether we reached the limit */ if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ - r = gcry_xmalloc( sizeof *r ); + r = m_alloc( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -218,7 +223,7 @@ put_record_into_cache( ulong recno, const char *data ) if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ if( opt.debug && !(cache_entries % 100) ) log_debug("increasing tdbio cache size\n"); - r = gcry_xmalloc( sizeof *r ); + r = m_alloc( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -230,7 +235,7 @@ put_record_into_cache( ulong recno, const char *data ) return 0; } log_info(_("trustdb transaction too large\n")); - return GPGERR_RESOURCE_LIMIT; + return G10ERR_RESOURCE_LIMIT; } if( dirty_count ) { int n = dirty_count / 5; /* discard some dirty entries */ @@ -406,6 +411,28 @@ cleanup(void) } } +static int +create_version_record (void) +{ + TRUSTREC rec; + int rc; + + memset( &rec, 0, sizeof rec ); + rec.r.ver.version = 3; + rec.r.ver.created = make_timestamp(); + rec.r.ver.marginals = opt.marginals_needed; + rec.r.ver.completes = opt.completes_needed; + rec.r.ver.cert_depth = opt.max_cert_depth; + rec.rectype = RECTYPE_VER; + rec.recnum = 0; + rc = tdbio_write_record( &rec ); + if( !rc ) + tdbio_sync(); + return rc; +} + + + int tdbio_set_dbname( const char *new_dbname, int create ) { @@ -416,20 +443,23 @@ tdbio_set_dbname( const char *new_dbname, int create ) atexit( cleanup ); initialized = 1; } - fname = new_dbname? gcry_xstrdup( new_dbname ) - : make_filename(opt.homedir, "trustdb.gpg", NULL ); + fname = new_dbname? m_strdup( new_dbname ) + : make_filename(opt.homedir, + "trustdb" EXTSEP_S "gpg", NULL ); + + check_permissions(fname,0,0); if( access( fname, R_OK ) ) { if( errno != ENOENT ) { log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); - gcry_free(fname); - return GPGERR_TRUSTDB; + m_free(fname); + return G10ERR_TRUSTDB; } if( create ) { FILE *fp; TRUSTREC rec; int rc; - char *p = strrchr( fname, '/' ); + char *p = strrchr( fname, DIRSEP_C ); assert(p); *p = 0; @@ -437,14 +467,22 @@ tdbio_set_dbname( const char *new_dbname, int create ) try_make_homedir( fname ); log_fatal( _("%s: directory does not exist!\n"), fname ); } - *p = '/'; + *p = DIRSEP_C; + m_free(db_name); + db_name = fname; +#ifdef __riscos__ + if( !lockhandle ) + lockhandle = create_dotlock( db_name ); + if( !lockhandle ) + log_fatal( _("%s: can't create lock\n"), db_name ); + if( make_dotlock( lockhandle, -1 ) ) + log_fatal( _("%s: can't make lock\n"), db_name ); +#endif /* __riscos__ */ fp =fopen( fname, "wb" ); if( !fp ) log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) ); fclose(fp); - gcry_free(db_name); - db_name = fname; #ifdef HAVE_DOSISH_SYSTEM db_fd = open( db_name, O_RDWR | O_BINARY ); #else @@ -453,25 +491,17 @@ tdbio_set_dbname( const char *new_dbname, int create ) if( db_fd == -1 ) log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); +#ifndef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) log_fatal( _("%s: can't create lock\n"), db_name ); +#endif /* !__riscos__ */ - memset( &rec, 0, sizeof rec ); - rec.r.ver.version = 2; - rec.r.ver.created = make_timestamp(); - rec.r.ver.marginals = opt.marginals_needed; - rec.r.ver.completes = opt.completes_needed; - rec.r.ver.cert_depth = opt.max_cert_depth; - rec.rectype = RECTYPE_VER; - rec.recnum = 0; - rc = tdbio_write_record( &rec ); - if( !rc ) - tdbio_sync(); + rc = create_version_record (); if( rc ) log_fatal( _("%s: failed to create version record: %s"), - fname, gpg_errstr(rc)); + fname, g10_errstr(rc)); /* and read again to check that we are okay */ if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) log_fatal( _("%s: invalid trustdb created\n"), db_name ); @@ -482,7 +512,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) return 0; } } - gcry_free(db_name); + m_free(db_name); db_name = fname; return 0; } @@ -499,27 +529,45 @@ tdbio_get_dbname() static void open_db() { - TRUSTREC rec; - assert( db_fd == -1 ); - - if( !lockhandle ) - lockhandle = create_dotlock( db_name ); - if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); - #ifdef HAVE_DOSISH_SYSTEM - db_fd = open( db_name, O_RDWR | O_BINARY ); - #else - db_fd = open( db_name, O_RDWR ); - #endif - if( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); - if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) - log_fatal( _("%s: invalid trustdb\n"), db_name ); + byte buf[10]; + int n; + TRUSTREC rec; + + assert( db_fd == -1 ); + + if (!lockhandle ) + lockhandle = create_dotlock( db_name ); + if (!lockhandle ) + log_fatal( _("%s: can't create lock\n"), db_name ); +#ifdef __riscos__ + if (make_dotlock( lockhandle, -1 ) ) + log_fatal( _("%s: can't make lock\n"), db_name ); +#endif /* __riscos__ */ +#ifdef HAVE_DOSISH_SYSTEM + db_fd = open (db_name, O_RDWR | O_BINARY ); +#else + db_fd = open (db_name, O_RDWR ); +#endif + if ( db_fd == -1 ) + log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + + /* check whether we need to do a version migration */ + do + n = read (db_fd, buf, 5); + while (n==-1 && errno == EINTR); + if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5)) + { + migrate_from_v2 (); + } + + /* read the version record */ + if (tdbio_read_record (0, &rec, RECTYPE_VER ) ) + log_fatal( _("%s: invalid trustdb\n"), db_name ); } /**************** - * Make a hashtable: type 0 = key hash, 1 = sdir hash + * Make a hashtable: type 0 = trust hash */ static void create_hashtable( TRUSTREC *vr, int type ) @@ -536,9 +584,8 @@ create_hashtable( TRUSTREC *vr, int type ) assert(recnum); /* this is will never be the first record */ if( !type ) - vr->r.ver.keyhashtbl = recnum; - else - vr->r.ver.sdirhashtbl = recnum; + vr->r.ver.trusthashtbl = recnum; + /* Now write the records */ n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; for(i=0; i < n; i++, recnum++ ) { @@ -548,7 +595,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_write_record( &rec ); if( rc ) log_fatal( _("%s: failed to create hashtable: %s\n"), - db_name, gpg_errstr(rc)); + db_name, g10_errstr(rc)); } /* update the version record */ rc = tdbio_write_record( vr ); @@ -556,7 +603,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_sync(); if( rc ) log_fatal( _("%s: error updating version record: %s\n"), - db_name, gpg_errstr(rc)); + db_name, g10_errstr(rc)); } @@ -572,7 +619,7 @@ tdbio_db_matches_options() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); if( !vr.r.ver.marginals && !vr.r.ver.completes && !vr.r.ver.cert_depth ) @@ -585,7 +632,7 @@ tdbio_db_matches_options() rc = tdbio_sync(); if( rc ) log_error( _("%s: error writing version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); } yes_no = vr.r.ver.marginals == opt.marginals_needed @@ -597,105 +644,70 @@ tdbio_db_matches_options() /**************** - * Return the modifiy stamp. - * if modify_down is true, the modify_down stamp will be - * returned, otherwise the modify_up stamp. + * Return the nextstamp value. */ ulong -tdbio_read_modify_stamp( int modify_down ) +tdbio_read_nextcheck () { TRUSTREC vr; int rc; - ulong mod; rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); - - mod = modify_down? vr.r.ver.mod_down : vr.r.ver.mod_up; - - /* Always return at least 1 to make comparison easier; - * this is still far back in history (before Led Zeppelin III :-) */ - return mod ? mod : 1; + db_name, g10_errstr(rc) ); + return vr.r.ver.nextcheck; } -void -tdbio_write_modify_stamp( int up, int down ) +/* Return true when the stamp was actually changed. */ +int +tdbio_write_nextcheck (ulong stamp) { TRUSTREC vr; int rc; - ulong stamp; - - if( !(up || down) ) - return; rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); - stamp = make_timestamp(); - if( down ) - vr.r.ver.mod_down = stamp; - if( up ) - vr.r.ver.mod_up = stamp; + if (vr.r.ver.nextcheck == stamp) + return 0; + vr.r.ver.nextcheck = stamp; rc = tdbio_write_record( &vr ); if( rc ) log_fatal( _("%s: error writing version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); + return 1; } + /**************** - * Return the record number of the keyhash tbl or create a new one. + * Return the record number of the trusthash tbl or create a new one. */ static ulong -get_keyhashrec(void) +get_trusthashrec(void) { - static ulong keyhashtbl; /* record number of the key hashtable */ + static ulong trusthashtbl; /* record number of the trust hashtable */ - if( !keyhashtbl ) { + if( !trusthashtbl ) { TRUSTREC vr; int rc; rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); - if( !vr.r.ver.keyhashtbl ) + db_name, g10_errstr(rc) ); + if( !vr.r.ver.trusthashtbl ) create_hashtable( &vr, 0 ); - keyhashtbl = vr.r.ver.keyhashtbl; + trusthashtbl = vr.r.ver.trusthashtbl; } - return keyhashtbl; + return trusthashtbl; } -/**************** - * Return the record number of the shadow direcory hash table - * or create a new one. - */ -static ulong -get_sdirhashrec(void) -{ - static ulong sdirhashtbl; /* record number of the hashtable */ - - if( !sdirhashtbl ) { - TRUSTREC vr; - int rc; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); - if( !vr.r.ver.sdirhashtbl ) - create_hashtable( &vr, 1 ); - - sdirhashtbl = vr.r.ver.sdirhashtbl; - } - return sdirhashtbl; -} /**************** @@ -719,7 +731,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { log_error( db_name, "upd_hashtable: read failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } @@ -729,7 +741,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( db_name, "upd_hashtable: write htbl failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } } @@ -738,7 +750,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "upd_hashtable: read item failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } @@ -747,7 +759,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } goto next_level; } @@ -763,8 +775,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST); if( rc ) { - log_error( "scan keyhashtbl read hlst failed: %s\n", - gpg_errstr(rc) ); + log_error( "upd_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); return rc; } } @@ -779,7 +791,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; /* done */ } } @@ -788,7 +800,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) &rec, RECTYPE_HLST ); if( rc ) { log_error( "upd_hashtable: read hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } } @@ -797,7 +809,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } memset( &rec, 0, sizeof rec ); @@ -807,14 +819,12 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write ext hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; /* done */ } } /* end loop over hlst slots */ } - else if( rec.rectype == RECTYPE_KEY - || rec.rectype == RECTYPE_DIR - || rec.rectype == RECTYPE_SDIR ) { /* insert a list record */ + else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */ if( rec.recnum == newrecnum ) { return 0; } @@ -827,7 +837,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write new hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } /* update the hashtable record */ @@ -835,14 +845,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &lastrec ); if( rc ) log_error( "upd_hashtable: update htbl failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; /* ready */ } else { 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 GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } } @@ -870,7 +880,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { log_error( db_name, "drop_from_hashtable: read failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } @@ -883,14 +893,14 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "drop_from_hashtable: read item failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } @@ -899,7 +909,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } goto next_level; } @@ -912,7 +922,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } } @@ -920,8 +930,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_read_record( rec.r.hlst.next, &rec, RECTYPE_HLST); if( rc ) { - log_error( "scan keyhashtbl read hlst failed: %s\n", - gpg_errstr(rc) ); + log_error( "drop_from_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); return rc; } } @@ -932,7 +942,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); - return GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } @@ -958,7 +968,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, 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", gpg_errstr(rc) ); + log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) ); return rc; } @@ -968,7 +978,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( item, rec, 0 ); if( rc ) { - log_error( db_name, "hashtable read failed: %s\n", gpg_errstr(rc) ); + log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) ); return rc; } if( rec->rectype == RECTYPE_HTBL ) { @@ -976,7 +986,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, level++; if( level >= keylen ) { log_error( db_name, "hashtable has invalid indirections\n"); - return GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } goto next_level; } @@ -991,7 +1001,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 ); if( rc ) { log_error( "lookup_hashtable: read item failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } if( (*cmpfnc)( cmpdata, &tmp ) ) { @@ -1004,7 +1014,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST ); if( rc ) { log_error( "lookup_hashtable: read hlst failed: %s\n", - gpg_errstr(rc) ); + g10_errstr(rc) ); return rc; } } @@ -1021,57 +1031,16 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, } - - /**************** - * Update the key hashtbl or create the table if it does not exist + * Update the trust hashtbl or create the table if it does not exist */ static int -update_keyhashtbl( TRUSTREC *kr ) +update_trusthashtbl( TRUSTREC *tr ) { - return upd_hashtable( get_keyhashrec(), - kr->r.key.fingerprint, - kr->r.key.fingerprint_len, kr->recnum ); + return upd_hashtable( get_trusthashrec(), + tr->r.trust.fingerprint, 20, tr->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 ); -} - -/**************** - * 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 ); -} - - void @@ -1079,7 +1048,6 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) { int i; ulong rnum = rec->recnum; - byte *p; fprintf(fp, "rec %5lu, ", rnum ); @@ -1087,116 +1055,18 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) case 0: fprintf(fp, "blank\n"); break; case RECTYPE_VER: fprintf(fp, - "version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d down=%s", - rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl, + "version, td=%lu, f=%lu, m/c/d=%d/%d/%d nc=%lu (%s)\n", + rec->r.ver.trusthashtbl, rec->r.ver.firstfree, rec->r.ver.marginals, rec->r.ver.completes, rec->r.ver.cert_depth, - strtimestamp(rec->r.ver.mod_down) ); - fprintf(fp, ", up=%s\n", strtimestamp(rec->r.ver.mod_up) ); + rec->r.ver.nextcheck, + strtimestamp(rec->r.ver.nextcheck) + ); break; case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next ); break; - case RECTYPE_DIR: - fprintf(fp, "dir %lu, keys=%lu, uids=%lu, t=%02x", - rec->r.dir.lid, - rec->r.dir.keylist, - rec->r.dir.uidlist, - rec->r.dir.ownertrust ); - 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 ); - if( rec->r.dir.dirflags & DIRF_EXPIRED ) - fputs(", expired", fp ); - if( rec->r.dir.dirflags & DIRF_REVOKED ) - fputs(", revoked", fp ); - if( rec->r.dir.dirflags & DIRF_NEWKEYS ) - fputs(", newkeys", fp ); - } - putc('\n', fp); - break; - case RECTYPE_KEY: - fprintf(fp, "key %lu, n=%lu a=%d ", - rec->r.key.lid, - rec->r.key.next, - rec->r.key.pubkey_algo ); - for(i=0; i < rec->r.key.fingerprint_len; i++ ) - fprintf(fp, "%02X", rec->r.key.fingerprint[i] ); - if( rec->r.key.keyflags & KEYF_CHECKED ) { - if( rec->r.key.keyflags & KEYF_VALID ) - fputs(", valid", fp ); - if( rec->r.key.keyflags & KEYF_EXPIRED ) - fputs(", expired", fp ); - if( rec->r.key.keyflags & KEYF_REVOKED ) - fputs(", revoked", fp ); - } - putc('\n', fp); - break; - case RECTYPE_UID: - fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X", - rec->r.uid.lid, - rec->r.uid.next, - rec->r.uid.prefrec, - rec->r.uid.siglist, - rec->r.uid.namehash[18], rec->r.uid.namehash[19]); - fprintf( fp, ", v=%02x", rec->r.uid.validity ); - if( rec->r.uid.uidflags & UIDF_CHECKED ) { - if( rec->r.uid.uidflags & UIDF_VALID ) - fputs(", valid", fp ); - if( rec->r.uid.uidflags & UIDF_REVOKED ) - fputs(", revoked", fp ); - } - putc('\n', fp); - break; - case RECTYPE_PREF: - fprintf(fp, "pref %lu, next=%lu,", - rec->r.pref.lid, rec->r.pref.next); - for(i=0,p=rec->r.pref.data; i < ITEMS_PER_PREF_RECORD; i+=2,p+=2 ) { - if( *p ) - fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' : - *p == PREFTYPE_HASH ? 'H' : - *p == PREFTYPE_COMPR ? 'Z' : '?', p[1]); - } - putc('\n', fp); - break; - case RECTYPE_SIG: - fprintf(fp, "sig %lu, next=%lu,", - rec->r.sig.lid, rec->r.sig.next ); - for(i=0; i < SIGS_PER_RECORD; i++ ) { - if( rec->r.sig.sig[i].lid ) { - 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_IGNORED) ? 'I':'-', - (rec->r.sig.sig[i].flag & SIGF_EXPIRED) ? 'E':'-', - (rec->r.sig.sig[i].flag & SIGF_REVOKED) ? 'R':'-'); - } - else if( rec->r.sig.sig[i].flag & SIGF_NOPUBKEY) - fputs("?--", fp); - else - fputs("---", 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; case RECTYPE_HTBL: fprintf(fp, "htbl,"); for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) @@ -1209,6 +1079,20 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) fprintf(fp, " %lu", rec->r.hlst.rnum[i] ); putc('\n', fp); break; + case RECTYPE_TRUST: + fprintf(fp, "trust "); + for(i=0; i < 20; i++ ) + fprintf(fp, "%02X", rec->r.trust.fingerprint[i] ); + fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust, + rec->r.trust.depth, rec->r.trust.validlist); + break; + case RECTYPE_VALID: + fprintf(fp, "valid "); + for(i=0; i < 20; i++ ) + fprintf(fp, "%02X", rec->r.valid.namehash[i] ); + fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity, + rec->r.valid.next); + break; default: fprintf(fp, "unknown type %d\n", rec->rectype ); break; @@ -1233,7 +1117,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( !buf ) { if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return GPGERR_READ_FILE; + return G10ERR_READ_FILE; } n = read( db_fd, readbuf, TRUST_RECORD_LEN); if( !n ) { @@ -1242,7 +1126,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) else if( n != TRUST_RECORD_LEN ) { log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) ); - return GPGERR_READ_FILE; + return G10ERR_READ_FILE; } buf = readbuf; } @@ -1253,7 +1137,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( expected && rec->rectype != expected ) { log_error("%lu: read expected rec type %d, got %d\n", recnum, expected, rec->rectype ); - return GPGERR_TRUSTDB; + return G10ERR_TRUSTDB; } p++; /* skip reserved byte */ switch( rec->rectype ) { @@ -1262,123 +1146,35 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case RECTYPE_VER: /* version record */ if( memcmp(buf+1, "gpg", 3 ) ) { log_error( _("%s: not a trustdb file\n"), db_name ); - rc = GPGERR_TRUSTDB; + rc = G10ERR_TRUSTDB; } - p += 2; /* skip "pgp" */ + p += 2; /* skip "gpg" */ rec->r.ver.version = *p++; rec->r.ver.marginals = *p++; rec->r.ver.completes = *p++; rec->r.ver.cert_depth = *p++; p += 4; /* lock flags */ rec->r.ver.created = buftoulong(p); p += 4; - rec->r.ver.mod_down = buftoulong(p); p += 4; - rec->r.ver.mod_up = buftoulong(p); p += 4; - rec->r.ver.keyhashtbl=buftoulong(p); p += 4; + rec->r.ver.nextcheck = buftoulong(p); p += 4; + p += 4; + p += 4; rec->r.ver.firstfree =buftoulong(p); p += 4; - rec->r.ver.sdirhashtbl =buftoulong(p); p += 4; + p += 4; + rec->r.ver.trusthashtbl =buftoulong(p); p += 4; if( recnum ) { log_error( _("%s: version record with recnum %lu\n"), db_name, (ulong)recnum ); - rc = GPGERR_TRUSTDB; + rc = G10ERR_TRUSTDB; } - else if( rec->r.ver.version != 2 ) { + else if( rec->r.ver.version != 3 ) { log_error( _("%s: invalid file version %d\n"), db_name, rec->r.ver.version ); - rc = GPGERR_TRUSTDB; + rc = G10ERR_TRUSTDB; } break; case RECTYPE_FREE: rec->r.free.next = buftoulong(p); p += 4; break; - case RECTYPE_DIR: /*directory record */ - rec->r.dir.lid = buftoulong(p); p += 4; - rec->r.dir.keylist = buftoulong(p); p += 4; - rec->r.dir.uidlist = buftoulong(p); p += 4; - rec->r.dir.cacherec = buftoulong(p); p += 4; - rec->r.dir.ownertrust = *p++; - 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: - case TRUST_NEVER: - case TRUST_MARGINAL: - case TRUST_FULLY: - case TRUST_ULTIMATE: - break; - default: - log_info("lid %lu: invalid validity value - cleared\n", recnum); - } - if( rec->r.dir.lid != recnum ) { - log_error( "%s: dir LID != recnum (%lu,%lu)\n", - db_name, rec->r.dir.lid, (ulong)recnum ); - rc = GPGERR_TRUSTDB; - } - break; - case RECTYPE_KEY: /* public key record */ - rec->r.key.lid = buftoulong(p); p += 4; - rec->r.key.next = buftoulong(p); p += 4; - p += 7; - rec->r.key.keyflags = *p++; - rec->r.key.pubkey_algo = *p++; - rec->r.key.fingerprint_len = *p++; - if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 ) - rec->r.key.fingerprint_len = 20; - memcpy( rec->r.key.fingerprint, p, 20); - break; - case RECTYPE_UID: /* user id record */ - rec->r.uid.lid = buftoulong(p); p += 4; - rec->r.uid.next = buftoulong(p); p += 4; - rec->r.uid.prefrec = buftoulong(p); p += 4; - rec->r.uid.siglist = buftoulong(p); p += 4; - rec->r.uid.uidflags = *p++; - rec->r.uid.validity = *p++; - switch( rec->r.uid.validity ) { - case 0: - case TRUST_UNDEFINED: - case TRUST_NEVER: - case TRUST_MARGINAL: - case TRUST_FULLY: - case TRUST_ULTIMATE: - break; - default: - log_info("lid %lu: invalid validity value - cleared\n", recnum); - } - memcpy( rec->r.uid.namehash, p, 20); - break; - case RECTYPE_PREF: /* preference record */ - rec->r.pref.lid = buftoulong(p); p += 4; - rec->r.pref.next = buftoulong(p); p += 4; - memcpy( rec->r.pref.data, p, 30 ); - break; - case RECTYPE_SIG: - rec->r.sig.lid = buftoulong(p); p += 4; - rec->r.sig.next = buftoulong(p); p += 4; - for(i=0; i < SIGS_PER_RECORD; i++ ) { - rec->r.sig.sig[i].lid = buftoulong(p); p += 4; - 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( "%s: sdir LID != recnum (%lu,%lu)\n", - db_name, rec->r.sdir.lid, (ulong)recnum ); - rc = GPGERR_TRUSTDB; - } - break; - case RECTYPE_CACH: /* cache record */ - rec->r.cache.lid = buftoulong(p); p += 4; - memcpy(rec->r.cache.blockhash, p, 20); p += 20; - rec->r.cache.trustlevel = *p++; - break; case RECTYPE_HTBL: for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { rec->r.htbl.item[i] = buftoulong(p); p += 4; @@ -1390,10 +1186,22 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) rec->r.hlst.rnum[i] = buftoulong(p); p += 4; } break; + case RECTYPE_TRUST: + memcpy( rec->r.trust.fingerprint, p, 20); p+=20; + rec->r.trust.ownertrust = *p++; + rec->r.trust.depth = *p++; + p += 2; + rec->r.trust.validlist = buftoulong(p); p += 4; + break; + case RECTYPE_VALID: + memcpy( rec->r.valid.namehash, p, 20); p+=20; + rec->r.valid.validity = *p++; + rec->r.valid.next = buftoulong(p); p += 4; + break; default: log_error( "%s: invalid record type %d at recnum %lu\n", db_name, rec->rectype, (ulong)recnum ); - rc = GPGERR_TRUSTDB; + rc = G10ERR_TRUSTDB; break; } @@ -1430,79 +1238,18 @@ tdbio_write_record( TRUSTREC *rec ) *p++ = rec->r.ver.cert_depth; p += 4; /* skip lock flags */ ulongtobuf(p, rec->r.ver.created); p += 4; - ulongtobuf(p, rec->r.ver.mod_down); p += 4; - ulongtobuf(p, rec->r.ver.mod_up); p += 4; - ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4; + ulongtobuf(p, rec->r.ver.nextcheck); p += 4; + p += 4; + p += 4; ulongtobuf(p, rec->r.ver.firstfree ); p += 4; - ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4; + p += 4; + ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4; break; case RECTYPE_FREE: ulongtobuf(p, rec->r.free.next); p += 4; break; - case RECTYPE_DIR: /*directory record */ - ulongtobuf(p, rec->r.dir.lid); p += 4; - ulongtobuf(p, rec->r.dir.keylist); p += 4; - ulongtobuf(p, rec->r.dir.uidlist); p += 4; - ulongtobuf(p, rec->r.dir.cacherec); p += 4; - *p++ = rec->r.dir.ownertrust; - *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; - - case RECTYPE_KEY: - ulongtobuf(p, rec->r.key.lid); p += 4; - ulongtobuf(p, rec->r.key.next); p += 4; - p += 7; - *p++ = rec->r.key.keyflags; - *p++ = rec->r.key.pubkey_algo; - *p++ = rec->r.key.fingerprint_len; - memcpy( p, rec->r.key.fingerprint, 20); p += 20; - break; - - case RECTYPE_UID: /* user id record */ - ulongtobuf(p, rec->r.uid.lid); p += 4; - ulongtobuf(p, rec->r.uid.next); p += 4; - ulongtobuf(p, rec->r.uid.prefrec); p += 4; - ulongtobuf(p, rec->r.uid.siglist); p += 4; - *p++ = rec->r.uid.uidflags; - *p++ = rec->r.uid.validity; - memcpy( p, rec->r.uid.namehash, 20 ); p += 20; - break; - - case RECTYPE_PREF: - ulongtobuf(p, rec->r.pref.lid); p += 4; - ulongtobuf(p, rec->r.pref.next); p += 4; - memcpy( p, rec->r.pref.data, 30 ); - break; - - case RECTYPE_SIG: - ulongtobuf(p, rec->r.sig.lid); p += 4; - ulongtobuf(p, rec->r.sig.next); p += 4; - for(i=0; i < SIGS_PER_RECORD; i++ ) { - ulongtobuf(p, rec->r.sig.sig[i].lid); p += 4; - *p++ = rec->r.sig.sig[i].flag; - } - 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: - ulongtobuf(p, rec->r.cache.lid); p += 4; - memcpy(p, rec->r.cache.blockhash, 20); p += 20; - *p++ = rec->r.cache.trustlevel; - break; case RECTYPE_HTBL: for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { @@ -1517,6 +1264,20 @@ tdbio_write_record( TRUSTREC *rec ) } break; + case RECTYPE_TRUST: + memcpy( p, rec->r.trust.fingerprint, 20); p += 20; + *p++ = rec->r.trust.ownertrust; + *p++ = rec->r.trust.depth; + p += 2; + ulongtobuf( p, rec->r.trust.validlist); p += 4; + break; + + case RECTYPE_VALID: + memcpy( p, rec->r.valid.namehash, 20); p += 20; + *p++ = rec->r.valid.validity; + ulongtobuf( p, rec->r.valid.next); p += 4; + break; + default: BUG(); } @@ -1524,10 +1285,8 @@ tdbio_write_record( TRUSTREC *rec ) rc = put_record_into_cache( recnum, buf ); if( rc ) ; - else if( rec->rectype == RECTYPE_KEY ) - rc = update_keyhashtbl( rec ); - else if( rec->rectype == RECTYPE_SDIR ) - rc = update_sdirhashtbl( rec ); + else if( rec->rectype == RECTYPE_TRUST ) + rc = update_trusthashtbl( rec ); return rc; } @@ -1542,10 +1301,10 @@ tdbio_delete_record( ulong recnum ) 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 ); + else if( rec.rectype == RECTYPE_TRUST ) { + rc = drop_from_hashtable( get_trusthashrec(), + rec.r.trust.fingerprint, 20, rec.recnum ); + } if( rc ) return rc; @@ -1554,7 +1313,7 @@ tdbio_delete_record( ulong recnum ) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); rec.recnum = recnum; rec.rectype = RECTYPE_FREE; @@ -1581,13 +1340,13 @@ tdbio_new_recnum() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); if( vr.r.ver.firstfree ) { recnum = vr.r.ver.firstfree; rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE ); if( rc ) { log_error( _("%s: error reading free record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); return rc; } /* update dir record */ @@ -1595,7 +1354,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &vr ); if( rc ) { log_error( _("%s: error writing dir record: %s\n"), - db_name, gpg_errstr(rc) ); + db_name, g10_errstr(rc) ); return rc; } /*zero out the new record */ @@ -1605,7 +1364,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &rec ); if( rc ) log_fatal(_("%s: failed to zero a record: %s\n"), - db_name, gpg_errstr(rc)); + db_name, g10_errstr(rc)); } else { /* not found, append a new record */ offset = lseek( db_fd, 0, SEEK_END ); @@ -1622,131 +1381,193 @@ tdbio_new_recnum() if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { log_error(_("trustdb rec %lu: lseek failed: %s\n"), recnum, strerror(errno) ); - rc = GPGERR_WRITE_FILE; + rc = G10ERR_WRITE_FILE; } else { int n = write( db_fd, &rec, TRUST_RECORD_LEN); if( n != TRUST_RECORD_LEN ) { log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), recnum, n, strerror(errno) ); - rc = GPGERR_WRITE_FILE; + rc = G10ERR_WRITE_FILE; } } if( rc ) log_fatal(_("%s: failed to append a record: %s\n"), - db_name, gpg_errstr(rc)); + db_name, g10_errstr(rc)); } return recnum ; } -/**************** - * Search the trustdb for a key which matches PK and return the dir record - * The local_id of PK is set to the correct value - */ -int -tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec ) -{ - byte fingerprint[MAX_FINGERPRINT_LEN]; - size_t fingerlen; - u32 keyid[2]; - int rc; - - keyid_from_pk( pk, keyid ); - fingerprint_from_pk( pk, fingerprint, &fingerlen ); - rc = tdbio_search_dir_byfpr( fingerprint, fingerlen, - pk->pubkey_algo, rec ); - - if( !rc ) { - if( pk->local_id && pk->local_id != rec->recnum ) - log_error("%s: found record, but LID from memory does " - "not match recnum (%lu,%lu)\n", - db_name, pk->local_id, rec->recnum ); - pk->local_id = rec->recnum; - } - return rc; -} - - static int -cmp_krec_fpr( void *dataptr, const TRUSTREC *rec ) +cmp_trec_fpr ( void *fpr, 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 ); + return rec->rectype == RECTYPE_TRUST + && !memcmp( rec->r.trust.fingerprint, fpr, 20); } + int -tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen, - int pubkey_algo, TRUSTREC *rec ) +tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec ) { - struct cmp_krec_fpr_struct cmpdata; - ulong recnum; int rc; - assert( fingerlen == 20 || fingerlen == 16 ); - - /* locate the key using the hash table */ - 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("%s: can't read dirrec %lu: %s\n", - db_name, recnum, gpg_errstr(rc) ); - } + /* locate the trust record using the hash table */ + rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20, + cmp_trec_fpr, (void*)fingerprint, rec ); return rc; } - - -static int -cmp_sdir( void *dataptr, const TRUSTREC *rec ) +int +tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec) { - const struct cmp_xdir_struct *d = dataptr; + byte fingerprint[MAX_FINGERPRINT_LEN]; + size_t fingerlen; - 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]; + fingerprint_from_pk( pk, fingerprint, &fingerlen ); + for (; fingerlen < 20; fingerlen++ ) + fingerprint[fingerlen] = 0; + return tdbio_search_trust_byfpr (fingerprint, rec); } -int -tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec ) -{ - struct cmp_xdir_struct cmpdata; - int rc; - 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; -} - void tdbio_invalid(void) { log_error(_( "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") ); - gpg_exit(2); + g10_exit(2); +} + +/* + * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) + * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs + * only to scan the tdb and insert new the new trust records. The old ones are + * obsolte from now on + */ +static void +migrate_from_v2 () +{ + TRUSTREC rec; + int i, n; + struct { + ulong keyrecno; + byte ot; + byte okay; + byte fpr[20]; + } *ottable; + int ottable_size, ottable_used; + byte oldbuf[40]; + ulong recno; + int rc, count; + + ottable_size = 5; + ottable = m_alloc (ottable_size * sizeof *ottable); + ottable_used = 0; + + /* We have some restrictions here. We can't use the version record + * and we can't use any of the old hashtables because we dropped the + * code. So we first collect all ownertrusts and then use a second + * pass fo find the associated keys. We have to do this all without using + * the regular record read functions. + */ + + /* get all the ownertrusts */ + if (lseek (db_fd, 0, SEEK_SET ) == -1 ) + log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); + for (recno=0;;recno++) + { + do + n = read (db_fd, oldbuf, 40); + while (n==-1 && errno == EINTR); + if (!n) + break; /* eof */ + if (n != 40) + log_fatal ("migrate_vfrom_v2: read error or short read\n"); + + if (*oldbuf != 2) + continue; + + /* v2 dir record */ + if (ottable_used == ottable_size) + { + ottable_size += 1000; + ottable = m_realloc (ottable, ottable_size * sizeof *ottable); + } + ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); + ottable[ottable_used].ot = oldbuf[18]; + ottable[ottable_used].okay = 0; + memset (ottable[ottable_used].fpr,0, 20); + if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) + ottable_used++; + } + log_info ("found %d ownertrust records\n", ottable_used); + + /* Read again and find the fingerprints */ + if (lseek (db_fd, 0, SEEK_SET ) == -1 ) + log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); + for (recno=0;;recno++) + { + do + n = read (db_fd, oldbuf, 40); + while (n==-1 && errno == EINTR); + if (!n) + break; /* eof */ + if (n != 40) + log_fatal ("migrate_from_v2: read error or short read\n"); + + if (*oldbuf != 3) + continue; + + /* v2 key record */ + for (i=0; i < ottable_used; i++) + { + if (ottable[i].keyrecno == recno) + { + memcpy (ottable[i].fpr, oldbuf+20, 20); + ottable[i].okay = 1; + break; + } + } + } + + /* got everything - create the v3 trustdb */ + if (ftruncate (db_fd, 0)) + log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); + if (create_version_record ()) + log_fatal ("failed to recreate version record of `%s'\n", db_name); + + /* access the hash table, so it is store just after the version record, + * this is not needed put a dump is more pretty */ + get_trusthashrec (); + + /* And insert the old ownertrust values */ + count = 0; + for (i=0; i < ottable_used; i++) + { + if (!ottable[i].okay) + continue; + + memset (&rec, 0, sizeof rec); + rec.recnum = tdbio_new_recnum (); + rec.rectype = RECTYPE_TRUST; + memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); + rec.r.trust.ownertrust = ottable[i].ot; + if (tdbio_write_record (&rec)) + log_fatal ("failed to write trust record of `%s'\n", db_name); + count++; + } + + revalidation_mark (); + rc = tdbio_sync (); + if (rc) + log_fatal ("failed to sync `%s'\n", db_name); + log_info ("migrated %d version 2 ownertrusts\n", count); + m_free (ottable); } + |