1998-07-09 13:37:17 +00:00
|
|
|
|
/* tdbio.c
|
2002-06-29 13:46:34 +00:00
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
1998-07-09 13:37:17 +00:00
|
|
|
|
*
|
1998-12-23 12:41:40 +00:00
|
|
|
|
* This file is part of GnuPG.
|
1998-07-09 13:37:17 +00:00
|
|
|
|
*
|
1998-12-23 12:41:40 +00:00
|
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
1998-07-09 13:37:17 +00:00
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
1998-12-23 12:41:40 +00:00
|
|
|
|
* GnuPG is distributed in the hope that it will be useful,
|
1998-07-09 13:37:17 +00:00
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2005-05-31 08:39:18 +00:00
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
|
|
|
* USA.
|
1998-07-09 13:37:17 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include "errors.h"
|
|
|
|
|
#include "iobuf.h"
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#include "memory.h"
|
1998-07-09 13:37:17 +00:00
|
|
|
|
#include "util.h"
|
|
|
|
|
#include "options.h"
|
|
|
|
|
#include "main.h"
|
|
|
|
|
#include "i18n.h"
|
|
|
|
|
#include "trustdb.h"
|
|
|
|
|
#include "tdbio.h"
|
|
|
|
|
|
2002-11-13 17:19:22 +00:00
|
|
|
|
#if defined(HAVE_DOSISH_SYSTEM)
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#define ftruncate chsize
|
|
|
|
|
#endif
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
2002-11-13 17:19:22 +00:00
|
|
|
|
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
|
2002-09-11 07:27:54 +00:00
|
|
|
|
#define MY_O_BINARY O_BINARY
|
|
|
|
|
#else
|
|
|
|
|
#define MY_O_BINARY 0
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
1998-10-16 16:00:17 +00:00
|
|
|
|
/****************
|
|
|
|
|
* Yes, this is a very simple implementation. We should really
|
|
|
|
|
* use a page aligned buffer and read complete pages.
|
|
|
|
|
* To implement a simple trannsaction system, this is sufficient.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct cache_ctrl_struct *CACHE_CTRL;
|
|
|
|
|
struct cache_ctrl_struct {
|
|
|
|
|
CACHE_CTRL next;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned used:1;
|
|
|
|
|
unsigned dirty:1;
|
|
|
|
|
} flags;
|
|
|
|
|
ulong recno;
|
|
|
|
|
char data[TRUST_RECORD_LEN];
|
|
|
|
|
};
|
|
|
|
|
|
1999-07-07 11:28:26 +00:00
|
|
|
|
#define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */
|
|
|
|
|
#define MAX_CACHE_ENTRIES_HARD 10000 /* transaction to this one */
|
1998-10-16 16:00:17 +00:00
|
|
|
|
static CACHE_CTRL cache_list;
|
|
|
|
|
static int cache_entries;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
static int cache_is_dirty;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
/* a type used to pass infomation to cmp_krec_fpr */
|
|
|
|
|
struct cmp_krec_fpr_struct {
|
|
|
|
|
int pubkey_algo;
|
|
|
|
|
const char *fpr;
|
|
|
|
|
int fprlen;
|
|
|
|
|
};
|
|
|
|
|
|
1999-06-29 19:50:54 +00:00
|
|
|
|
/* a type used to pass infomation to cmp_[s]dir */
|
|
|
|
|
struct cmp_xdir_struct {
|
1998-10-12 20:16:38 +00:00
|
|
|
|
int pubkey_algo;
|
|
|
|
|
u32 keyid[2];
|
|
|
|
|
};
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *db_name;
|
1999-02-10 16:22:40 +00:00
|
|
|
|
static DOTLOCK lockhandle;
|
|
|
|
|
static int is_locked;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
static int db_fd = -1;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
static int in_transaction;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
static void open_db(void);
|
2002-06-29 13:46:34 +00:00
|
|
|
|
static void migrate_from_v2 (void);
|
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
|
|
|
|
/*************************************
|
|
|
|
|
************* record cache **********
|
|
|
|
|
*************************************/
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* Get the data from therecord cache and return a
|
|
|
|
|
* pointer into that cache. Caller should copy
|
|
|
|
|
* the return data. NULL is returned on a cache miss.
|
|
|
|
|
*/
|
|
|
|
|
static const char *
|
|
|
|
|
get_record_from_cache( ulong recno )
|
|
|
|
|
{
|
|
|
|
|
CACHE_CTRL r;
|
|
|
|
|
|
|
|
|
|
for( r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( r->flags.used && r->recno == recno )
|
|
|
|
|
return r->data;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
write_cache_item( CACHE_CTRL r )
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
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) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_WRITE_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
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) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_WRITE_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
r->flags.dirty = 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* Put data into the cache. This function may flush the
|
|
|
|
|
* some cache entries if there is not enough space available.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
put_record_into_cache( ulong recno, const char *data )
|
|
|
|
|
{
|
|
|
|
|
CACHE_CTRL r, unused;
|
|
|
|
|
int dirty_count = 0;
|
|
|
|
|
int clean_count = 0;
|
|
|
|
|
|
|
|
|
|
/* see whether we already cached this one */
|
|
|
|
|
for( unused = NULL, r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( !r->flags.used ) {
|
|
|
|
|
if( !unused )
|
|
|
|
|
unused = r;
|
|
|
|
|
}
|
|
|
|
|
else if( r->recno == recno ) {
|
|
|
|
|
if( !r->flags.dirty ) {
|
|
|
|
|
/* Hmmm: should we use a a copy and compare? */
|
1998-10-25 19:00:01 +00:00
|
|
|
|
if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
r->flags.dirty = 1;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 1;
|
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if( r->flags.used ) {
|
|
|
|
|
if( r->flags.dirty )
|
|
|
|
|
dirty_count++;
|
|
|
|
|
else
|
|
|
|
|
clean_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* not in the cache: add a new entry */
|
|
|
|
|
if( unused ) { /* reuse this entry */
|
|
|
|
|
r = unused;
|
|
|
|
|
r->flags.used = 1;
|
|
|
|
|
r->recno = recno;
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
r->flags.dirty = 1;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 1;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
cache_entries++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* see whether we reached the limit */
|
1998-10-25 19:00:01 +00:00
|
|
|
|
if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */
|
2002-06-29 13:46:34 +00:00
|
|
|
|
r = m_alloc( sizeof *r );
|
1998-10-16 16:00:17 +00:00
|
|
|
|
r->flags.used = 1;
|
|
|
|
|
r->recno = recno;
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
r->flags.dirty = 1;
|
|
|
|
|
r->next = cache_list;
|
|
|
|
|
cache_list = r;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 1;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
cache_entries++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* cache is full: discard some clean entries */
|
|
|
|
|
if( clean_count ) {
|
|
|
|
|
int n = clean_count / 3; /* discard a third of the clean entries */
|
|
|
|
|
if( !n )
|
|
|
|
|
n = 1;
|
|
|
|
|
for( unused = NULL, r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( r->flags.used && !r->flags.dirty ) {
|
|
|
|
|
if( !unused )
|
|
|
|
|
unused = r;
|
|
|
|
|
r->flags.used = 0;
|
|
|
|
|
cache_entries--;
|
|
|
|
|
if( !--n )
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert( unused );
|
|
|
|
|
r = unused;
|
|
|
|
|
r->flags.used = 1;
|
|
|
|
|
r->recno = recno;
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
r->flags.dirty = 1;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 1;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
cache_entries++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* no clean entries: have to flush some dirty entries */
|
1998-10-25 19:00:01 +00:00
|
|
|
|
if( in_transaction ) {
|
|
|
|
|
/* but we can't do this while in a transaction
|
|
|
|
|
* we increase the cache size instead */
|
|
|
|
|
if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */
|
1998-11-10 12:59:59 +00:00
|
|
|
|
if( opt.debug && !(cache_entries % 100) )
|
|
|
|
|
log_debug("increasing tdbio cache size\n");
|
2002-06-29 13:46:34 +00:00
|
|
|
|
r = m_alloc( sizeof *r );
|
1998-10-25 19:00:01 +00:00
|
|
|
|
r->flags.used = 1;
|
|
|
|
|
r->recno = recno;
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
r->flags.dirty = 1;
|
|
|
|
|
r->next = cache_list;
|
|
|
|
|
cache_list = r;
|
|
|
|
|
cache_is_dirty = 1;
|
|
|
|
|
cache_entries++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
1998-12-29 13:47:31 +00:00
|
|
|
|
log_info(_("trustdb transaction too large\n"));
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_RESOURCE_LIMIT;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
if( dirty_count ) {
|
|
|
|
|
int n = dirty_count / 5; /* discard some dirty entries */
|
|
|
|
|
if( !n )
|
|
|
|
|
n = 1;
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !is_locked ) {
|
|
|
|
|
if( make_dotlock( lockhandle, -1 ) )
|
|
|
|
|
log_fatal("can't acquire lock - giving up\n");
|
|
|
|
|
else
|
|
|
|
|
is_locked = 1;
|
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
for( unused = NULL, r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( r->flags.used && r->flags.dirty ) {
|
|
|
|
|
int rc = write_cache_item( r );
|
|
|
|
|
if( rc )
|
|
|
|
|
return rc;
|
|
|
|
|
if( !unused )
|
|
|
|
|
unused = r;
|
|
|
|
|
r->flags.used = 0;
|
|
|
|
|
cache_entries--;
|
|
|
|
|
if( !--n )
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-11-27 20:40:56 +00:00
|
|
|
|
if( !opt.lock_once ) {
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !release_dotlock( lockhandle ) )
|
|
|
|
|
is_locked = 0;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
assert( unused );
|
|
|
|
|
r = unused;
|
|
|
|
|
r->flags.used = 1;
|
|
|
|
|
r->recno = recno;
|
|
|
|
|
memcpy( r->data, data, TRUST_RECORD_LEN );
|
|
|
|
|
r->flags.dirty = 1;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 1;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
cache_entries++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
BUG();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-10-25 19:00:01 +00:00
|
|
|
|
int
|
|
|
|
|
tdbio_is_dirty()
|
|
|
|
|
{
|
|
|
|
|
return cache_is_dirty;
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
|
|
|
|
/****************
|
1998-10-25 19:00:01 +00:00
|
|
|
|
* Flush the cache. This cannot be used while in a transaction.
|
1998-10-16 16:00:17 +00:00
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
tdbio_sync()
|
|
|
|
|
{
|
|
|
|
|
CACHE_CTRL r;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
int did_lock = 0;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( db_fd == -1 )
|
|
|
|
|
open_db();
|
1998-10-25 19:00:01 +00:00
|
|
|
|
if( in_transaction )
|
|
|
|
|
log_bug("tdbio: syncing while in transaction\n");
|
|
|
|
|
|
|
|
|
|
if( !cache_is_dirty )
|
|
|
|
|
return 0;
|
|
|
|
|
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !is_locked ) {
|
|
|
|
|
if( make_dotlock( lockhandle, -1 ) )
|
|
|
|
|
log_fatal("can't acquire lock - giving up\n");
|
|
|
|
|
else
|
|
|
|
|
is_locked = 1;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
did_lock = 1;
|
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
for( r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( r->flags.used && r->flags.dirty ) {
|
|
|
|
|
int rc = write_cache_item( r );
|
|
|
|
|
if( rc )
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-25 19:00:01 +00:00
|
|
|
|
cache_is_dirty = 0;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
if( did_lock && !opt.lock_once ) {
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !release_dotlock( lockhandle ) )
|
|
|
|
|
is_locked = 0;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
}
|
1999-03-11 15:42:06 +00:00
|
|
|
|
|
1998-10-25 19:00:01 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
* parse-packet.c (parse_signature): No need to reserve 8 bytes for the
unhashed signature cache any longer.
* misc.c (pct_expando): Add two new expandos - signer's fingerprint (%g),
and signer's primary fingerprint (%p).
* Makefile.am: Include W32LIBS where appropriate.
* g10.c (main): Add --rfc2440 alias for --openpgp since in a few months,
they won't be the same thing.
* keyserver.c (parse_keyserver_uri): Accept "http" as an alias for "hkp",
since it is occasionally written that way. (keyserver_spawn): Use
ascii_isspace to avoid locale issues.
* keygen.c (ask_user_id): Make --allow-freeform-uid apply to the email
field as well as the name field, and allow mixing fields when it is set.
* options.skel: Use subkeys.pgp.net as the default keyserver.
* trustdb.c (validate_one_keyblock): Certifications on revoked or expired
uids do not count in the web of trust.
* signal.c (init_one_signal, pause_on_sigusr, do_block): Only use
sigprocmask() if we have sigset_t, and only use sigaction() if we have
struct sigaction. This is for Forte c89 on Solaris which seems to define
only the function call half of the two pairs by default.
(pause_on_sigusr): Typo. (do_block): If we can't use sigprocmask() and
sigset_t, try to get the number of signals from NSIG as well as MAXSIG,
and if we can't, fail with an explanation.
* signal.c, tdbio.c: Comment out the transaction code. It was not used in
this version, and was causing some build problems on quasi-posix platforms
(Solaris and Forte c89).
* keylist.c (list_keyblock_colon): Don't include validity values when
listing secret keys since they can be incorrect and/or misleading. This
is a temporary kludge, and will be handled properly in 1.9/2.0.
* mainproc.c (check_sig_and_print): Only show the "key available from"
preferred keyserver line if the key is not currently present.
* keyedit.c (sign_uids): Do not sign expired uids without --expert (same
behavior as revoked uids). Do not allow signing a user ID without a
self-signature. --expert overrides. Add additional prompt to the
signature level question. (menu_expire): When changing expiration dates,
don't replace selfsigs on revoked uids since this would effectively
unrevoke them. There is also no point in replacing expired selfsigs.
This is bug #181
* g10.c (add_notation_data): Make sure that only ascii is passed to
iscntrl. Noted by Christian Biere.
* getkey.c (classify_user_id2): Replaced isspace by spacep
* keygen.c (ask_user_id): Ditto. (get_parameter_algo): Ditto.
* keyedit.c (keyedit_menu): Ditto.
* tdbdump.c (import_ownertrust): Ditto. s/isxdigit/hexdigitp/.
* revoke.c (ask_revocation_reason):
* keyserver.c (keyserver_spawn): Dito.
2003-07-10 14:30:07 +00:00
|
|
|
|
#if 0
|
|
|
|
|
/* The transaction code is disabled in the 1.2.x branch, as it is not
|
|
|
|
|
yet used. It will be enabled in 1.3.x. */
|
1998-10-25 19:00:01 +00:00
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* Simple transactions system:
|
|
|
|
|
* Everything between begin_transaction and end/cancel_transaction
|
|
|
|
|
* is not immediatly written but at the time of end_transaction.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
tdbio_begin_transaction()
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
if( in_transaction )
|
|
|
|
|
log_bug("tdbio: nested transactions\n");
|
|
|
|
|
/* flush everything out */
|
|
|
|
|
rc = tdbio_sync();
|
|
|
|
|
if( rc )
|
|
|
|
|
return rc;
|
|
|
|
|
in_transaction = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
tdbio_end_transaction()
|
|
|
|
|
{
|
1998-11-03 19:38:58 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
1998-10-25 19:00:01 +00:00
|
|
|
|
if( !in_transaction )
|
|
|
|
|
log_bug("tdbio: no active transaction\n");
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !is_locked ) {
|
|
|
|
|
if( make_dotlock( lockhandle, -1 ) )
|
|
|
|
|
log_fatal("can't acquire lock - giving up\n");
|
|
|
|
|
else
|
|
|
|
|
is_locked = 1;
|
|
|
|
|
}
|
1998-11-03 19:38:58 +00:00
|
|
|
|
block_all_signals();
|
1998-10-25 19:00:01 +00:00
|
|
|
|
in_transaction = 0;
|
1998-11-03 19:38:58 +00:00
|
|
|
|
rc = tdbio_sync();
|
|
|
|
|
unblock_all_signals();
|
1998-11-27 20:40:56 +00:00
|
|
|
|
if( !opt.lock_once ) {
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( !release_dotlock( lockhandle ) )
|
|
|
|
|
is_locked = 0;
|
1998-11-27 20:40:56 +00:00
|
|
|
|
}
|
1998-11-03 19:38:58 +00:00
|
|
|
|
return rc;
|
1998-10-25 19:00:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
tdbio_cancel_transaction()
|
|
|
|
|
{
|
|
|
|
|
CACHE_CTRL r;
|
|
|
|
|
|
|
|
|
|
if( !in_transaction )
|
|
|
|
|
log_bug("tdbio: no active transaction\n");
|
|
|
|
|
|
|
|
|
|
/* remove all dirty marked entries, so that the original ones
|
|
|
|
|
* are read back the next time */
|
|
|
|
|
if( cache_is_dirty ) {
|
|
|
|
|
for( r = cache_list; r; r = r->next ) {
|
|
|
|
|
if( r->flags.used && r->flags.dirty ) {
|
|
|
|
|
r->flags.used = 0;
|
|
|
|
|
cache_entries--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cache_is_dirty = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
in_transaction = 0;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
* parse-packet.c (parse_signature): No need to reserve 8 bytes for the
unhashed signature cache any longer.
* misc.c (pct_expando): Add two new expandos - signer's fingerprint (%g),
and signer's primary fingerprint (%p).
* Makefile.am: Include W32LIBS where appropriate.
* g10.c (main): Add --rfc2440 alias for --openpgp since in a few months,
they won't be the same thing.
* keyserver.c (parse_keyserver_uri): Accept "http" as an alias for "hkp",
since it is occasionally written that way. (keyserver_spawn): Use
ascii_isspace to avoid locale issues.
* keygen.c (ask_user_id): Make --allow-freeform-uid apply to the email
field as well as the name field, and allow mixing fields when it is set.
* options.skel: Use subkeys.pgp.net as the default keyserver.
* trustdb.c (validate_one_keyblock): Certifications on revoked or expired
uids do not count in the web of trust.
* signal.c (init_one_signal, pause_on_sigusr, do_block): Only use
sigprocmask() if we have sigset_t, and only use sigaction() if we have
struct sigaction. This is for Forte c89 on Solaris which seems to define
only the function call half of the two pairs by default.
(pause_on_sigusr): Typo. (do_block): If we can't use sigprocmask() and
sigset_t, try to get the number of signals from NSIG as well as MAXSIG,
and if we can't, fail with an explanation.
* signal.c, tdbio.c: Comment out the transaction code. It was not used in
this version, and was causing some build problems on quasi-posix platforms
(Solaris and Forte c89).
* keylist.c (list_keyblock_colon): Don't include validity values when
listing secret keys since they can be incorrect and/or misleading. This
is a temporary kludge, and will be handled properly in 1.9/2.0.
* mainproc.c (check_sig_and_print): Only show the "key available from"
preferred keyserver line if the key is not currently present.
* keyedit.c (sign_uids): Do not sign expired uids without --expert (same
behavior as revoked uids). Do not allow signing a user ID without a
self-signature. --expert overrides. Add additional prompt to the
signature level question. (menu_expire): When changing expiration dates,
don't replace selfsigs on revoked uids since this would effectively
unrevoke them. There is also no point in replacing expired selfsigs.
This is bug #181
* g10.c (add_notation_data): Make sure that only ascii is passed to
iscntrl. Noted by Christian Biere.
* getkey.c (classify_user_id2): Replaced isspace by spacep
* keygen.c (ask_user_id): Ditto. (get_parameter_algo): Ditto.
* keyedit.c (keyedit_menu): Ditto.
* tdbdump.c (import_ownertrust): Ditto. s/isxdigit/hexdigitp/.
* revoke.c (ask_revocation_reason):
* keyserver.c (keyserver_spawn): Dito.
2003-07-10 14:30:07 +00:00
|
|
|
|
#endif
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************
|
|
|
|
|
**************** cached I/O functions ******************
|
|
|
|
|
********************************************************/
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
1999-01-07 17:05:48 +00:00
|
|
|
|
static void
|
|
|
|
|
cleanup(void)
|
|
|
|
|
{
|
1999-02-10 16:22:40 +00:00
|
|
|
|
if( is_locked ) {
|
|
|
|
|
if( !release_dotlock(lockhandle) )
|
|
|
|
|
is_locked = 0;
|
1999-01-07 17:05:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-04 00:05:11 +00:00
|
|
|
|
/* Caller must sync */
|
|
|
|
|
int
|
|
|
|
|
tdbio_update_version_record (void)
|
|
|
|
|
{
|
|
|
|
|
TRUSTREC rec;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
|
|
|
|
|
|
|
|
|
rc=tdbio_read_record( 0, &rec, RECTYPE_VER);
|
|
|
|
|
if(rc==0)
|
|
|
|
|
{
|
|
|
|
|
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.r.ver.trust_model = opt.trust_model;
|
|
|
|
|
rc=tdbio_write_record(&rec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
static int
|
|
|
|
|
create_version_record (void)
|
|
|
|
|
{
|
|
|
|
|
TRUSTREC rec;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
2002-12-04 00:05:11 +00:00
|
|
|
|
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;
|
* tdbio.c (create_version_record): Only create new trustdbs with
TM_CLASSIC or TM_PGP.
* trustdb.h, trustdb.c (trust_string, get_ownertrust_string,
get_validity_string, ask_ownertrust, validate_keys), pkclist.c
(do_edit_ownertrust): Rename trust_string to trust_value_to_string for
naming consistency.
* trustdb.h, trustdb.c (string_to_trust_value): New function to translate
a string to a trust value.
* g10.c (main): Use string_to_trust_value here for --force-ownertrust.
* options.h, g10.c (main), trustdb.c (trust_model_string, init_trustdb,
check_trustdb, update_trustdb, get_validity, validate_one_keyblock): An
"OpenPGP" trust model is misleading since there is no official OpenPGP
trust model. Use "PGP" instead.
2003-05-01 21:37:08 +00:00
|
|
|
|
if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
|
|
|
|
|
rec.r.ver.trust_model = opt.trust_model;
|
|
|
|
|
else
|
|
|
|
|
rec.r.ver.trust_model = TM_PGP;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rec.rectype = RECTYPE_VER;
|
|
|
|
|
rec.recnum = 0;
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( !rc )
|
|
|
|
|
tdbio_sync();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
int
|
|
|
|
|
tdbio_set_dbname( const char *new_dbname, int create )
|
|
|
|
|
{
|
|
|
|
|
char *fname;
|
1999-01-07 17:05:48 +00:00
|
|
|
|
static int initialized = 0;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
1999-01-07 17:05:48 +00:00
|
|
|
|
if( !initialized ) {
|
|
|
|
|
atexit( cleanup );
|
|
|
|
|
initialized = 1;
|
|
|
|
|
}
|
2003-01-12 15:46:17 +00:00
|
|
|
|
|
|
|
|
|
if(new_dbname==NULL)
|
|
|
|
|
fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "gpg", NULL);
|
|
|
|
|
else if (*new_dbname != DIRSEP_C )
|
|
|
|
|
{
|
|
|
|
|
if (strchr(new_dbname, DIRSEP_C) )
|
|
|
|
|
fname = make_filename (new_dbname, NULL);
|
|
|
|
|
else
|
|
|
|
|
fname = make_filename (opt.homedir, new_dbname, NULL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fname = m_strdup (new_dbname);
|
2002-06-29 13:46:34 +00:00
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
if( access( fname, R_OK ) ) {
|
|
|
|
|
if( errno != ENOENT ) {
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_error( _("can't access `%s': %s\n"), fname, strerror(errno) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
m_free(fname);
|
|
|
|
|
return G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
|
|
|
|
if( create ) {
|
1998-07-29 19:35:05 +00:00
|
|
|
|
FILE *fp;
|
|
|
|
|
TRUSTREC rec;
|
|
|
|
|
int rc;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
char *p = strrchr( fname, DIRSEP_C );
|
2002-08-08 19:09:34 +00:00
|
|
|
|
mode_t oldmask;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
assert(p);
|
|
|
|
|
*p = 0;
|
|
|
|
|
if( access( fname, F_OK ) ) {
|
2000-07-14 17:34:53 +00:00
|
|
|
|
try_make_homedir( fname );
|
|
|
|
|
log_fatal( _("%s: directory does not exist!\n"), fname );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
*p = DIRSEP_C;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
m_free(db_name);
|
|
|
|
|
db_name = fname;
|
|
|
|
|
#ifdef __riscos__
|
|
|
|
|
if( !lockhandle )
|
|
|
|
|
lockhandle = create_dotlock( db_name );
|
|
|
|
|
if( !lockhandle )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't create lock for `%s'\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
if( make_dotlock( lockhandle, -1 ) )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't lock `%s'\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#endif /* __riscos__ */
|
2002-08-08 19:09:34 +00:00
|
|
|
|
oldmask=umask(077);
|
2004-10-14 07:11:57 +00:00
|
|
|
|
if (is_secured_filename (fname)) {
|
|
|
|
|
fp = NULL;
|
|
|
|
|
errno = EPERM;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fp =fopen( fname, "wb" );
|
2002-08-08 19:09:34 +00:00
|
|
|
|
umask(oldmask);
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( !fp )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
fclose(fp);
|
2002-09-11 07:27:54 +00:00
|
|
|
|
db_fd = open( db_name, O_RDWR | MY_O_BINARY );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( db_fd == -1 )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#ifndef __riscos__
|
1999-02-13 13:17:29 +00:00
|
|
|
|
if( !lockhandle )
|
|
|
|
|
lockhandle = create_dotlock( db_name );
|
|
|
|
|
if( !lockhandle )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't create lock for `%s'\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#endif /* !__riscos__ */
|
1999-02-13 13:17:29 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = create_version_record ();
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: failed to create version record: %s"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
fname, g10_errstr(rc));
|
1998-07-29 19:35:05 +00:00
|
|
|
|
/* and read again to check that we are okay */
|
|
|
|
|
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
|
1998-12-29 13:47:31 +00:00
|
|
|
|
log_fatal( _("%s: invalid trustdb created\n"), db_name );
|
1998-10-21 17:34:36 +00:00
|
|
|
|
|
1999-04-18 08:18:52 +00:00
|
|
|
|
if( !opt.quiet )
|
|
|
|
|
log_info(_("%s: trustdb created\n"), db_name);
|
1998-10-21 17:34:36 +00:00
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return 0;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
m_free(db_name);
|
1998-07-09 13:37:17 +00:00
|
|
|
|
db_name = fname;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
tdbio_get_dbname()
|
|
|
|
|
{
|
|
|
|
|
return db_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
open_db()
|
|
|
|
|
{
|
2002-06-29 13:46:34 +00:00
|
|
|
|
byte buf[10];
|
|
|
|
|
int n;
|
|
|
|
|
TRUSTREC rec;
|
|
|
|
|
|
|
|
|
|
assert( db_fd == -1 );
|
|
|
|
|
|
|
|
|
|
if (!lockhandle )
|
|
|
|
|
lockhandle = create_dotlock( db_name );
|
|
|
|
|
if (!lockhandle )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't create lock for `%s'\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#ifdef __riscos__
|
|
|
|
|
if (make_dotlock( lockhandle, -1 ) )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't lock `%s'\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
#endif /* __riscos__ */
|
2002-09-11 07:27:54 +00:00
|
|
|
|
db_fd = open (db_name, O_RDWR | MY_O_BINARY );
|
|
|
|
|
if (db_fd == -1 && errno == EACCES) {
|
|
|
|
|
db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
|
|
|
|
|
if (db_fd != -1)
|
|
|
|
|
log_info (_("NOTE: trustdb not writable\n"));
|
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
if ( db_fd == -1 )
|
2004-10-14 07:11:57 +00:00
|
|
|
|
log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
|
2004-10-13 18:10:06 +00:00
|
|
|
|
register_secured_file (db_name);
|
2002-06-29 13:46:34 +00:00
|
|
|
|
|
|
|
|
|
/* 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 );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
/****************
|
2002-06-29 13:46:34 +00:00
|
|
|
|
* Make a hashtable: type 0 = trust hash
|
1998-10-12 20:16:38 +00:00
|
|
|
|
*/
|
|
|
|
|
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 )
|
2002-06-29 13:46:34 +00:00
|
|
|
|
vr->r.ver.trusthashtbl = recnum;
|
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
/* 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 );
|
1998-10-16 16:00:17 +00:00
|
|
|
|
rec.rectype = RECTYPE_HTBL;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
rec.recnum = recnum;
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: failed to create hashtable: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc));
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
/* update the version record */
|
|
|
|
|
rc = tdbio_write_record( vr );
|
1998-10-16 16:00:17 +00:00
|
|
|
|
if( !rc )
|
|
|
|
|
rc = tdbio_sync();
|
1998-10-12 20:16:38 +00:00
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: error updating version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc));
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-11-13 19:41:41 +00:00
|
|
|
|
int
|
|
|
|
|
tdbio_db_matches_options()
|
|
|
|
|
{
|
2002-12-04 06:06:56 +00:00
|
|
|
|
static int yes_no = -1;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
|
2002-12-04 06:06:56 +00:00
|
|
|
|
if( yes_no == -1 )
|
|
|
|
|
{
|
|
|
|
|
TRUSTREC vr;
|
|
|
|
|
int rc;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
|
2002-12-04 06:06:56 +00:00
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
|
|
|
|
if( rc )
|
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
|
|
|
|
db_name, g10_errstr(rc) );
|
1998-11-13 19:41:41 +00:00
|
|
|
|
|
2002-12-04 06:06:56 +00:00
|
|
|
|
yes_no = vr.r.ver.marginals == opt.marginals_needed
|
|
|
|
|
&& vr.r.ver.completes == opt.completes_needed
|
|
|
|
|
&& vr.r.ver.cert_depth == opt.max_cert_depth
|
|
|
|
|
&& vr.r.ver.trust_model == opt.trust_model;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
}
|
2002-12-04 06:06:56 +00:00
|
|
|
|
|
|
|
|
|
return yes_no;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-26 20:38:16 +00:00
|
|
|
|
byte
|
|
|
|
|
tdbio_read_model(void)
|
|
|
|
|
{
|
|
|
|
|
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, g10_errstr(rc) );
|
|
|
|
|
return vr.r.ver.trust_model;
|
|
|
|
|
}
|
1998-10-12 20:16:38 +00:00
|
|
|
|
|
1999-03-11 15:42:06 +00:00
|
|
|
|
/****************
|
2002-06-29 13:46:34 +00:00
|
|
|
|
* Return the nextstamp value.
|
1999-03-11 15:42:06 +00:00
|
|
|
|
*/
|
|
|
|
|
ulong
|
2002-06-29 13:46:34 +00:00
|
|
|
|
tdbio_read_nextcheck ()
|
1999-03-11 15:42:06 +00:00
|
|
|
|
{
|
|
|
|
|
TRUSTREC vr;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
|
|
|
|
if( rc )
|
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
|
|
|
|
return vr.r.ver.nextcheck;
|
1999-03-11 15:42:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
/* Return true when the stamp was actually changed. */
|
|
|
|
|
int
|
|
|
|
|
tdbio_write_nextcheck (ulong stamp)
|
1999-03-11 15:42:06 +00:00
|
|
|
|
{
|
|
|
|
|
TRUSTREC vr;
|
|
|
|
|
int rc;
|
1999-03-17 12:13:04 +00:00
|
|
|
|
|
1999-03-11 15:42:06 +00:00
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
|
|
|
|
if( rc )
|
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
1999-03-11 15:42:06 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
if (vr.r.ver.nextcheck == stamp)
|
|
|
|
|
return 0;
|
1999-03-11 15:42:06 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
vr.r.ver.nextcheck = stamp;
|
1999-03-11 15:42:06 +00:00
|
|
|
|
rc = tdbio_write_record( &vr );
|
1999-03-17 12:13:04 +00:00
|
|
|
|
if( rc )
|
1999-03-11 15:42:06 +00:00
|
|
|
|
log_fatal( _("%s: error writing version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
|
|
|
|
return 1;
|
1999-03-11 15:42:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
/****************
|
2002-06-29 13:46:34 +00:00
|
|
|
|
* Return the record number of the trusthash tbl or create a new one.
|
1998-07-29 19:35:05 +00:00
|
|
|
|
*/
|
|
|
|
|
static ulong
|
2002-06-29 13:46:34 +00:00
|
|
|
|
get_trusthashrec(void)
|
1998-07-29 19:35:05 +00:00
|
|
|
|
{
|
2002-06-29 13:46:34 +00:00
|
|
|
|
static ulong trusthashtbl; /* record number of the trust hashtable */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
if( !trusthashtbl ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
TRUSTREC vr;
|
|
|
|
|
int rc;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
1998-10-16 16:00:17 +00:00
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
|
|
|
|
if( !vr.r.ver.trusthashtbl )
|
1998-10-16 16:00:17 +00:00
|
|
|
|
create_hashtable( &vr, 0 );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
trusthashtbl = vr.r.ver.trusthashtbl;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return trusthashtbl;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************
|
1998-10-12 20:16:38 +00:00
|
|
|
|
* Update a hashtable.
|
|
|
|
|
* table gives the start of the table, key and keylen is the key,
|
|
|
|
|
* newrecnum is the record number to insert.
|
1998-07-29 19:35:05 +00:00
|
|
|
|
*/
|
|
|
|
|
static int
|
1998-10-12 20:16:38 +00:00
|
|
|
|
upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
|
1998-07-29 19:35:05 +00:00
|
|
|
|
{
|
|
|
|
|
TRUSTREC lastrec, rec;
|
|
|
|
|
ulong hashrec, item;
|
|
|
|
|
int msb;
|
|
|
|
|
int level=0;
|
|
|
|
|
int rc, i;
|
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
hashrec = table;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
next_level:
|
1998-10-12 20:16:38 +00:00
|
|
|
|
msb = key[level];
|
1998-07-29 19:35:05 +00:00
|
|
|
|
hashrec += msb / ITEMS_PER_HTBL_RECORD;
|
|
|
|
|
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
|
|
|
|
|
if( rc ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
|
1998-10-12 20:16:38 +00:00
|
|
|
|
if( !item ) { /* insert a new item into the hash table */
|
|
|
|
|
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("upd_hashtable: write htbl failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-12 20:16:38 +00:00
|
|
|
|
else if( item != newrecnum ) { /* must do an update */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
lastrec = rec;
|
|
|
|
|
rc = tdbio_read_record( item, &rec, 0 );
|
|
|
|
|
if( rc ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: read item failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
1998-10-16 16:00:17 +00:00
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( rec.rectype == RECTYPE_HTBL ) {
|
|
|
|
|
hashrec = item;
|
|
|
|
|
level++;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
if( level >= keylen ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "hashtable has invalid indirections.\n");
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
goto next_level;
|
|
|
|
|
}
|
|
|
|
|
else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
|
|
|
|
|
/* see whether the key is already in this list */
|
|
|
|
|
for(;;) {
|
|
|
|
|
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
1998-10-12 20:16:38 +00:00
|
|
|
|
if( rec.r.hlst.rnum[i] == newrecnum ) {
|
|
|
|
|
return 0; /* okay, already in the list */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( rec.r.hlst.next ) {
|
|
|
|
|
rc = tdbio_read_record( rec.r.hlst.next,
|
1998-10-12 20:16:38 +00:00
|
|
|
|
&rec, RECTYPE_HLST);
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( rc ) {
|
2002-06-29 13:46:34 +00:00
|
|
|
|
log_error( "upd_hashtable: read hlst failed: %s\n",
|
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
break; /* not there */
|
|
|
|
|
}
|
|
|
|
|
/* find the next free entry and put it in */
|
|
|
|
|
for(;;) {
|
|
|
|
|
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
|
|
|
|
if( !rec.r.hlst.rnum[i] ) {
|
1998-10-12 20:16:38 +00:00
|
|
|
|
rec.r.hlst.rnum[i] = newrecnum;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc )
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: write hlst failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
return rc; /* done */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( rec.r.hlst.next ) {
|
|
|
|
|
rc = tdbio_read_record( rec.r.hlst.next,
|
|
|
|
|
&rec, RECTYPE_HLST );
|
|
|
|
|
if( rc ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: read hlst failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { /* add a new list record */
|
|
|
|
|
rec.r.hlst.next = item = tdbio_new_recnum();
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: write hlst failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
|
|
|
|
rec.rectype = RECTYPE_HLST;
|
|
|
|
|
rec.recnum = item;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
rec.r.hlst.rnum[0] = newrecnum;
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
if( rc )
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: write ext hlst failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
return rc; /* done */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
1998-10-12 20:16:38 +00:00
|
|
|
|
} /* end loop over hlst slots */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */
|
1998-10-12 20:16:38 +00:00
|
|
|
|
if( rec.recnum == newrecnum ) {
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
item = rec.recnum; /* save number of key record */
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
|
|
|
|
rec.rectype = RECTYPE_HLST;
|
|
|
|
|
rec.recnum = tdbio_new_recnum();
|
|
|
|
|
rec.r.hlst.rnum[0] = item; /* old keyrecord */
|
1998-10-12 20:16:38 +00:00
|
|
|
|
rec.r.hlst.rnum[1] = newrecnum; /* and new one */
|
1998-07-29 19:35:05 +00:00
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc ) {
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: write new hlst failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
/* update the hashtable record */
|
|
|
|
|
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
|
|
|
|
|
rc = tdbio_write_record( &lastrec );
|
|
|
|
|
if( rc )
|
1998-10-16 16:00:17 +00:00
|
|
|
|
log_error( "upd_hashtable: update htbl failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-07-29 19:35:05 +00:00
|
|
|
|
return rc; /* ready */
|
|
|
|
|
}
|
|
|
|
|
else {
|
1999-06-29 19:50:54 +00:00
|
|
|
|
log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
|
|
|
|
|
table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
|
|
|
|
|
list_trustdb(NULL);
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-06-29 19:50:54 +00:00
|
|
|
|
/****************
|
|
|
|
|
* 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 ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("drop_from_hashtable: read failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1999-06-29 19:50:54 +00:00
|
|
|
|
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 )
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("drop_from_hashtable: write htbl failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1999-06-29 19:50:54 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = tdbio_read_record( item, &rec, 0 );
|
|
|
|
|
if( rc ) {
|
|
|
|
|
log_error( "drop_from_hashtable: read item failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1999-06-29 19:50:54 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( rec.rectype == RECTYPE_HTBL ) {
|
|
|
|
|
hashrec = item;
|
|
|
|
|
level++;
|
|
|
|
|
if( level >= keylen ) {
|
|
|
|
|
log_error( "hashtable has invalid indirections.\n");
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1999-06-29 19:50:54 +00:00
|
|
|
|
}
|
|
|
|
|
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 )
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("drop_from_hashtable: write htbl failed: %s\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1999-06-29 19:50:54 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( rec.r.hlst.next ) {
|
|
|
|
|
rc = tdbio_read_record( rec.r.hlst.next,
|
|
|
|
|
&rec, RECTYPE_HLST);
|
|
|
|
|
if( rc ) {
|
2002-06-29 13:46:34 +00:00
|
|
|
|
log_error( "drop_from_hashtable: read hlst failed: %s\n",
|
|
|
|
|
g10_errstr(rc) );
|
1999-06-29 19:50:54 +00:00
|
|
|
|
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);
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1999-06-29 19:50:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
/****************
|
|
|
|
|
* 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 ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("lookup_hashtable failed: %s\n", g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
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 ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error( "hashtable read failed: %s\n", g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
if( rec->rectype == RECTYPE_HTBL ) {
|
|
|
|
|
hashrec = item;
|
|
|
|
|
level++;
|
|
|
|
|
if( level >= keylen ) {
|
2003-12-30 00:46:42 +00:00
|
|
|
|
log_error("hashtable has invalid indirections\n");
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
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",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
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",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
g10_errstr(rc) );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return -1; /* not found */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( (*cmpfnc)( cmpdata, rec ) )
|
|
|
|
|
return 0; /* really found */
|
|
|
|
|
|
|
|
|
|
return -1; /* no: not found */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************
|
2002-06-29 13:46:34 +00:00
|
|
|
|
* Update the trust hashtbl or create the table if it does not exist
|
1998-10-12 20:16:38 +00:00
|
|
|
|
*/
|
|
|
|
|
static int
|
2002-06-29 13:46:34 +00:00
|
|
|
|
update_trusthashtbl( TRUSTREC *tr )
|
1998-10-12 20:16:38 +00:00
|
|
|
|
{
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return upd_hashtable( get_trusthashrec(),
|
|
|
|
|
tr->r.trust.fingerprint, 20, tr->recnum );
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
void
|
1998-07-21 12:53:38 +00:00
|
|
|
|
tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
1998-07-09 13:37:17 +00:00
|
|
|
|
{
|
1998-07-29 19:35:05 +00:00
|
|
|
|
int i;
|
1998-07-21 12:53:38 +00:00
|
|
|
|
ulong rnum = rec->recnum;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
1998-07-21 12:53:38 +00:00
|
|
|
|
fprintf(fp, "rec %5lu, ", rnum );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
switch( rec->rectype ) {
|
1998-10-07 13:30:43 +00:00
|
|
|
|
case 0: fprintf(fp, "blank\n");
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
case RECTYPE_VER: fprintf(fp,
|
2002-12-04 00:05:11 +00:00
|
|
|
|
"version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d nc=%lu (%s)\n",
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rec->r.ver.trusthashtbl,
|
1998-11-13 19:41:41 +00:00
|
|
|
|
rec->r.ver.firstfree,
|
|
|
|
|
rec->r.ver.marginals,
|
|
|
|
|
rec->r.ver.completes,
|
1999-03-11 15:42:06 +00:00
|
|
|
|
rec->r.ver.cert_depth,
|
2002-12-04 00:05:11 +00:00
|
|
|
|
rec->r.ver.trust_model,
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rec->r.ver.nextcheck,
|
|
|
|
|
strtimestamp(rec->r.ver.nextcheck)
|
|
|
|
|
);
|
1998-10-07 13:30:43 +00:00
|
|
|
|
break;
|
|
|
|
|
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
1998-07-14 17:10:28 +00:00
|
|
|
|
case RECTYPE_HTBL:
|
1998-07-29 19:35:05 +00:00
|
|
|
|
fprintf(fp, "htbl,");
|
|
|
|
|
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
|
|
|
|
|
fprintf(fp, " %lu", rec->r.htbl.item[i] );
|
|
|
|
|
putc('\n', fp);
|
1998-07-14 17:10:28 +00:00
|
|
|
|
break;
|
1998-07-21 12:53:38 +00:00
|
|
|
|
case RECTYPE_HLST:
|
1998-07-29 19:35:05 +00:00
|
|
|
|
fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
|
|
|
|
|
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
|
|
|
|
|
fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
|
|
|
|
|
putc('\n', fp);
|
1998-07-14 17:10:28 +00:00
|
|
|
|
break;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
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;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
default:
|
1998-07-21 12:53:38 +00:00
|
|
|
|
fprintf(fp, "unknown type %d\n", rec->rectype );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* read the record with number recnum
|
|
|
|
|
* returns: -1 on error, 0 on success
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
|
|
|
|
{
|
1998-10-16 16:00:17 +00:00
|
|
|
|
byte readbuf[TRUST_RECORD_LEN];
|
|
|
|
|
const byte *buf, *p;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
int rc = 0;
|
|
|
|
|
int n, i;
|
|
|
|
|
|
|
|
|
|
if( db_fd == -1 )
|
|
|
|
|
open_db();
|
1998-10-16 16:00:17 +00:00
|
|
|
|
buf = get_record_from_cache( recnum );
|
|
|
|
|
if( !buf ) {
|
|
|
|
|
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
|
|
|
|
|
log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_READ_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
n = read( db_fd, readbuf, TRUST_RECORD_LEN);
|
|
|
|
|
if( !n ) {
|
|
|
|
|
return -1; /* eof */
|
|
|
|
|
}
|
|
|
|
|
else if( n != TRUST_RECORD_LEN ) {
|
|
|
|
|
log_error(_("trustdb: read failed (n=%d): %s\n"), n,
|
|
|
|
|
strerror(errno) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_READ_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
buf = readbuf;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
1998-07-15 18:05:01 +00:00
|
|
|
|
rec->recnum = recnum;
|
1998-10-12 20:16:38 +00:00
|
|
|
|
rec->dirty = 0;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
p = buf;
|
|
|
|
|
rec->rectype = *p++;
|
|
|
|
|
if( expected && rec->rectype != expected ) {
|
|
|
|
|
log_error("%lu: read expected rec type %d, got %d\n",
|
|
|
|
|
recnum, expected, rec->rectype );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
1998-07-29 19:35:05 +00:00
|
|
|
|
p++; /* skip reserved byte */
|
1998-07-09 13:37:17 +00:00
|
|
|
|
switch( rec->rectype ) {
|
1998-07-29 19:35:05 +00:00
|
|
|
|
case 0: /* unused (free) record */
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case RECTYPE_VER: /* version record */
|
1998-07-14 17:10:28 +00:00
|
|
|
|
if( memcmp(buf+1, "gpg", 3 ) ) {
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( _("%s: not a trustdb file\n"), db_name );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
p += 2; /* skip "gpg" */
|
1998-07-09 13:37:17 +00:00
|
|
|
|
rec->r.ver.version = *p++;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
rec->r.ver.marginals = *p++;
|
|
|
|
|
rec->r.ver.completes = *p++;
|
|
|
|
|
rec->r.ver.cert_depth = *p++;
|
2002-12-04 00:05:11 +00:00
|
|
|
|
rec->r.ver.trust_model = *p++;
|
|
|
|
|
p += 3;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
rec->r.ver.created = buftoulong(p); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rec->r.ver.nextcheck = buftoulong(p); p += 4;
|
|
|
|
|
p += 4;
|
|
|
|
|
p += 4;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
rec->r.ver.firstfree =buftoulong(p); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
p += 4;
|
|
|
|
|
rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
if( recnum ) {
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( _("%s: version record with recnum %lu\n"), db_name,
|
1998-07-09 13:37:17 +00:00
|
|
|
|
(ulong)recnum );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
2002-06-29 13:46:34 +00:00
|
|
|
|
else if( rec->r.ver.version != 3 ) {
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( _("%s: invalid file version %d\n"), db_name,
|
1998-07-09 13:37:17 +00:00
|
|
|
|
rec->r.ver.version );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
case RECTYPE_FREE:
|
|
|
|
|
rec->r.free.next = buftoulong(p); p += 4;
|
|
|
|
|
break;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
case RECTYPE_HTBL:
|
|
|
|
|
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
|
|
|
|
rec->r.htbl.item[i] = buftoulong(p); p += 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case RECTYPE_HLST:
|
|
|
|
|
rec->r.hlst.next = buftoulong(p); p += 4;
|
|
|
|
|
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
|
|
|
|
rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
case RECTYPE_TRUST:
|
|
|
|
|
memcpy( rec->r.trust.fingerprint, p, 20); p+=20;
|
|
|
|
|
rec->r.trust.ownertrust = *p++;
|
|
|
|
|
rec->r.trust.depth = *p++;
|
* keyedit.c (print_and_check_one_sig, show_key_and_fingerprint,
menu_addrevoker), keylist.c (list_keyblock_print, print_fingerprint): Show
"T" or the trust depth for trust signatures, and add spaces to some
strings to make room for it.
* packet.h, parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt,
parse_signature): Parse trust signature values.
* tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record): Reserve a byte
for the minimum ownertrust value (for use with trust signatures).
2002-10-29 18:00:07 +00:00
|
|
|
|
rec->r.trust.min_ownertrust = *p++;
|
2002-12-11 17:50:38 +00:00
|
|
|
|
p++;
|
|
|
|
|
rec->r.trust.validlist = buftoulong(p); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
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;
|
2003-01-06 22:56:08 +00:00
|
|
|
|
rec->r.valid.full_count = *p++;
|
|
|
|
|
rec->r.valid.marginal_count = *p++;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
break;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
default:
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( "%s: invalid record type %d at recnum %lu\n",
|
|
|
|
|
db_name, rec->rectype, (ulong)recnum );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_TRUSTDB;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* Write the record at RECNUM
|
|
|
|
|
*/
|
|
|
|
|
int
|
1998-07-15 18:05:01 +00:00
|
|
|
|
tdbio_write_record( TRUSTREC *rec )
|
1998-07-09 13:37:17 +00:00
|
|
|
|
{
|
|
|
|
|
byte buf[TRUST_RECORD_LEN], *p;
|
|
|
|
|
int rc = 0;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
int i;
|
1998-07-15 18:05:01 +00:00
|
|
|
|
ulong recnum = rec->recnum;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
if( db_fd == -1 )
|
|
|
|
|
open_db();
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, TRUST_RECORD_LEN);
|
|
|
|
|
p = buf;
|
|
|
|
|
*p++ = rec->rectype; p++;
|
|
|
|
|
switch( rec->rectype ) {
|
|
|
|
|
case 0: /* unused record */
|
|
|
|
|
break;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
case RECTYPE_VER: /* version record */
|
|
|
|
|
if( recnum )
|
|
|
|
|
BUG();
|
|
|
|
|
memcpy(p-1, "gpg", 3 ); p += 2;
|
|
|
|
|
*p++ = rec->r.ver.version;
|
1998-11-13 19:41:41 +00:00
|
|
|
|
*p++ = rec->r.ver.marginals;
|
|
|
|
|
*p++ = rec->r.ver.completes;
|
|
|
|
|
*p++ = rec->r.ver.cert_depth;
|
2002-12-04 00:05:11 +00:00
|
|
|
|
*p++ = rec->r.ver.trust_model;
|
|
|
|
|
p += 3;
|
1998-07-29 19:35:05 +00:00
|
|
|
|
ulongtobuf(p, rec->r.ver.created); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
|
|
|
|
|
p += 4;
|
|
|
|
|
p += 4;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
p += 4;
|
|
|
|
|
ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RECTYPE_FREE:
|
|
|
|
|
ulongtobuf(p, rec->r.free.next); p += 4;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1998-07-14 17:10:28 +00:00
|
|
|
|
|
1998-07-29 19:35:05 +00:00
|
|
|
|
case RECTYPE_HTBL:
|
|
|
|
|
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
|
|
|
|
ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RECTYPE_HLST:
|
|
|
|
|
ulongtobuf( p, rec->r.hlst.next); p += 4;
|
|
|
|
|
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
|
|
|
|
ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
case RECTYPE_TRUST:
|
|
|
|
|
memcpy( p, rec->r.trust.fingerprint, 20); p += 20;
|
|
|
|
|
*p++ = rec->r.trust.ownertrust;
|
|
|
|
|
*p++ = rec->r.trust.depth;
|
* keyedit.c (print_and_check_one_sig, show_key_and_fingerprint,
menu_addrevoker), keylist.c (list_keyblock_print, print_fingerprint): Show
"T" or the trust depth for trust signatures, and add spaces to some
strings to make room for it.
* packet.h, parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt,
parse_signature): Parse trust signature values.
* tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record): Reserve a byte
for the minimum ownertrust value (for use with trust signatures).
2002-10-29 18:00:07 +00:00
|
|
|
|
*p++ = rec->r.trust.min_ownertrust;
|
2002-12-11 17:50:38 +00:00
|
|
|
|
p++;
|
|
|
|
|
ulongtobuf( p, rec->r.trust.validlist); p += 4;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
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;
|
2003-01-06 22:56:08 +00:00
|
|
|
|
*p++ = rec->r.valid.full_count;
|
|
|
|
|
*p++ = rec->r.valid.marginal_count;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1998-07-09 13:37:17 +00:00
|
|
|
|
default:
|
|
|
|
|
BUG();
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-16 16:00:17 +00:00
|
|
|
|
rc = put_record_into_cache( recnum, buf );
|
|
|
|
|
if( rc )
|
|
|
|
|
;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
else if( rec->rectype == RECTYPE_TRUST )
|
|
|
|
|
rc = update_trusthashtbl( rec );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
1998-07-21 12:53:38 +00:00
|
|
|
|
int
|
|
|
|
|
tdbio_delete_record( ulong recnum )
|
|
|
|
|
{
|
1998-10-07 13:30:43 +00:00
|
|
|
|
TRUSTREC vr, rec;
|
|
|
|
|
int rc;
|
|
|
|
|
|
1999-06-29 19:50:54 +00:00
|
|
|
|
/* Must read the record fist, so we can drop it from the hash tables */
|
|
|
|
|
rc = tdbio_read_record( recnum, &rec, 0 );
|
|
|
|
|
if( rc )
|
|
|
|
|
;
|
2002-06-29 13:46:34 +00:00
|
|
|
|
else if( rec.rectype == RECTYPE_TRUST ) {
|
|
|
|
|
rc = drop_from_hashtable( get_trusthashrec(),
|
|
|
|
|
rec.r.trust.fingerprint, 20, rec.recnum );
|
|
|
|
|
}
|
1999-06-29 19:50:54 +00:00
|
|
|
|
|
|
|
|
|
if( rc )
|
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
|
|
/* now we can chnage it to a free record */
|
1998-10-07 13:30:43 +00:00
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
1998-07-21 12:53:38 +00:00
|
|
|
|
|
|
|
|
|
rec.recnum = recnum;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
rec.rectype = RECTYPE_FREE;
|
|
|
|
|
rec.r.free.next = vr.r.ver.firstfree;
|
|
|
|
|
vr.r.ver.firstfree = recnum;
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( !rc )
|
|
|
|
|
rc = tdbio_write_record( &vr );
|
|
|
|
|
return rc;
|
1998-07-21 12:53:38 +00:00
|
|
|
|
}
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* create a new record and return its record number
|
|
|
|
|
*/
|
|
|
|
|
ulong
|
|
|
|
|
tdbio_new_recnum()
|
|
|
|
|
{
|
|
|
|
|
off_t offset;
|
|
|
|
|
ulong recnum;
|
1998-10-07 13:30:43 +00:00
|
|
|
|
TRUSTREC vr, rec;
|
1998-07-09 13:37:17 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
1998-10-07 13:30:43 +00:00
|
|
|
|
/* look for unused records */
|
|
|
|
|
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal( _("%s: error reading version record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
1998-10-07 13:30:43 +00:00
|
|
|
|
if( vr.r.ver.firstfree ) {
|
|
|
|
|
recnum = vr.r.ver.firstfree;
|
|
|
|
|
rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE );
|
|
|
|
|
if( rc ) {
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( _("%s: error reading free record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
1998-10-07 13:30:43 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
/* update dir record */
|
|
|
|
|
vr.r.ver.firstfree = rec.r.free.next;
|
|
|
|
|
rc = tdbio_write_record( &vr );
|
|
|
|
|
if( rc ) {
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_error( _("%s: error writing dir record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc) );
|
1998-10-07 13:30:43 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
/*zero out the new record */
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
|
|
|
|
rec.rectype = 0; /* unused record */
|
|
|
|
|
rec.recnum = recnum;
|
|
|
|
|
rc = tdbio_write_record( &rec );
|
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal(_("%s: failed to zero a record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc));
|
1998-10-07 13:30:43 +00:00
|
|
|
|
}
|
|
|
|
|
else { /* not found, append a new record */
|
|
|
|
|
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 */
|
|
|
|
|
/* we must write a record, so that the next call to this function
|
|
|
|
|
* returns another recnum */
|
|
|
|
|
memset( &rec, 0, sizeof rec );
|
|
|
|
|
rec.rectype = 0; /* unused record */
|
|
|
|
|
rec.recnum = recnum;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
rc = 0;
|
|
|
|
|
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
|
|
|
|
|
log_error(_("trustdb rec %lu: lseek failed: %s\n"),
|
|
|
|
|
recnum, strerror(errno) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_WRITE_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
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) );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
rc = G10ERR_WRITE_FILE;
|
1998-10-16 16:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-07 13:30:43 +00:00
|
|
|
|
if( rc )
|
1998-10-21 17:34:36 +00:00
|
|
|
|
log_fatal(_("%s: failed to append a record: %s\n"),
|
2002-06-29 13:46:34 +00:00
|
|
|
|
db_name, g10_errstr(rc));
|
1998-10-07 13:30:43 +00:00
|
|
|
|
}
|
1998-07-09 13:37:17 +00:00
|
|
|
|
return recnum ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
static int
|
2002-06-29 13:46:34 +00:00
|
|
|
|
cmp_trec_fpr ( void *fpr, const TRUSTREC *rec )
|
1998-10-12 20:16:38 +00:00
|
|
|
|
{
|
2002-06-29 13:46:34 +00:00
|
|
|
|
return rec->rectype == RECTYPE_TRUST
|
|
|
|
|
&& !memcmp( rec->r.trust.fingerprint, fpr, 20);
|
1998-10-12 20:16:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
|
1998-07-30 17:37:03 +00:00
|
|
|
|
int
|
2002-06-29 13:46:34 +00:00
|
|
|
|
tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec )
|
1998-07-30 17:37:03 +00:00
|
|
|
|
{
|
1998-07-09 13:37:17 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
/* locate the trust record using the hash table */
|
|
|
|
|
rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20,
|
|
|
|
|
cmp_trec_fpr, (void*)fingerprint, rec );
|
1998-07-09 13:37:17 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
int
|
|
|
|
|
tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
|
1998-08-07 08:53:38 +00:00
|
|
|
|
{
|
2002-06-29 13:46:34 +00:00
|
|
|
|
byte fingerprint[MAX_FINGERPRINT_LEN];
|
|
|
|
|
size_t fingerlen;
|
1998-08-07 08:53:38 +00:00
|
|
|
|
|
2002-06-29 13:46:34 +00:00
|
|
|
|
fingerprint_from_pk( pk, fingerprint, &fingerlen );
|
|
|
|
|
for (; fingerlen < 20; fingerlen++ )
|
|
|
|
|
fingerprint[fingerlen] = 0;
|
|
|
|
|
return tdbio_search_trust_byfpr (fingerprint, rec);
|
1998-08-07 08:53:38 +00:00
|
|
|
|
}
|
1998-07-09 13:37:17 +00:00
|
|
|
|
|
1998-10-12 20:16:38 +00:00
|
|
|
|
|
1998-07-21 12:53:38 +00:00
|
|
|
|
|
1999-03-11 15:42:06 +00:00
|
|
|
|
void
|
|
|
|
|
tdbio_invalid(void)
|
|
|
|
|
{
|
|
|
|
|
log_error(_(
|
1999-06-26 10:23:06 +00:00
|
|
|
|
"the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") );
|
2002-06-29 13:46:34 +00:00
|
|
|
|
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);
|
1999-03-11 15:42:06 +00:00
|
|
|
|
}
|