1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Epxerimenta support for GDBM keyings.

This commit is contained in:
Werner Koch 1998-10-21 17:34:36 +00:00
parent 6e16296864
commit e309a875cb
36 changed files with 1049 additions and 558 deletions

View file

@ -1,3 +1,27 @@
Wed Oct 21 18:19:36 1998 Michael Roth <mroth@nessie.de>
* ringedit.c (add_keyblock_resource): Directory is now created.
* tdbio.c (tdbio_set_dbname): New info message.
Wed Oct 21 11:52:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (update_trustdb): released keyblock in loop.
* keylist.c (list_block): New.
(list_all): Changed to use list_block.
* trustdb.c: Completed support for GDBM
* sign.c (only_old_style): Changed the way force_v3 is handled
(sign_file): Ditto.
(clearsign_file): Ditto.
* keygen.c (has_invalid_email_chars): Splitted into mailbox and
host part.
* keylist.c (list_one): Add a merge_keys_and_selfsig.
* mainproc.c (proc_tree): Ditto.
Sun Oct 18 11:49:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* sign.c (only_old_style): Add option force_v3_sigs

View file

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
EXTRA_DIST = OPTIONS pubring.asc
OMIT_DEPENDENCIES = zlib.h zconf.h
LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@
@ -76,7 +76,7 @@ gpgm_SOURCES = dearmor.c \
# $(common_source)
LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@
LDADD = $(needed_libs) @ZLIBS@ @INTLLIBS@
gpgm_LDADD = g10maint.o $(LDADD)

View file

@ -1,4 +1,4 @@
/* delkey.c - delte keys
/* delkey.c - delete keys
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.

View file

@ -683,6 +683,182 @@ merge_keys_and_selfsig( KBNODE keyblock )
}
static KBNODE
find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name,
int mode, byte *namehash, int *use_namehash )
{
KBNODE k, kk;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_USER_ID
&& !compare_name( k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len, name, mode)) {
/* we found a matching name, look for the key */
for(kk=keyblock; kk; kk = kk->next ) {
if( ( kk->pkt->pkttype == PKT_PUBLIC_KEY
|| kk->pkt->pkttype == PKT_PUBLIC_SUBKEY )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== kk->pkt->pkt.public_key->pubkey_algo)
&& ( !pk->pubkey_usage
|| !check_pubkey_algo2(
kk->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ))
)
break;
}
if( kk ) {
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
rmd160_hash_buffer( namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
*use_namehash = 1;
return kk;
}
else if( is_RSA(pk->pubkey_algo) )
log_error("RSA key cannot be used in this version\n");
else
log_error("No key for userid\n");
}
}
return NULL;
}
static KBNODE
find_by_keyid( KBNODE keyblock, PKT_public_key *pk, u32 *keyid, int mode )
{
KBNODE k;
if( DBG_CACHE )
log_debug("lookup keyid=%08lx%08lx req_algo=%d mode=%d\n",
(ulong)keyid[0], (ulong)keyid[1], pk->pubkey_algo, mode );
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
if( DBG_CACHE )
log_debug(" aki=%08lx%08lx algo=%d\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo );
if( aki[1] == keyid[1]
&& ( mode == 10 || aki[0] == keyid[0] )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo) ){
KBNODE kk;
/* cache the userid */
for(kk=keyblock; kk; kk = kk->next )
if( kk->pkt->pkttype == PKT_USER_ID )
break;
if( kk )
cache_user_id( kk->pkt->pkt.user_id, aki );
else
log_error("No userid for key\n");
return k; /* found */
}
}
}
return NULL;
}
static KBNODE
find_first( KBNODE keyblock, PKT_public_key *pk )
{
KBNODE k;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY )
{
if( !pk->pubkey_algo
|| pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo )
return k;
}
}
return NULL;
}
static KBNODE
find_by_fpr( KBNODE keyblock, PKT_public_key *pk, const char *name, int mode )
{
KBNODE k;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
if( DBG_CACHE ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
log_debug(" aki=%08lx%08lx algo=%d mode=%d an=%u\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo, mode, an );
}
if( an == mode
&& !memcmp( afp, name, an)
&& ( !pk->pubkey_algo
|| pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo) )
return k;
}
}
return NULL;
}
static void
finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
int use_namehash, int primary )
{
assert( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY );
assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
if( primary && !pk->pubkey_usage ) {
copy_public_key_new_namehash( pk, keyblock->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, keyblock );
}
else {
if( primary && pk->pubkey_usage
&& check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
for( ; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
break;
}
if( !k )
k = save_k;
else
log_info(_("using secondary key %08lX "
"instead of primary key %08lX\n"),
(ulong)keyid_from_pk( k->pkt->pkt.public_key, NULL),
(ulong)keyid_from_pk( save_k->pkt->pkt.public_key, NULL)
);
}
copy_public_key_new_namehash( pk, k->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, k );
}
}
@ -709,175 +885,87 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
{
int rc;
KBNODE keyblock = NULL;
KBNODE k;
KBPOS kbpos;
int oldmode = set_packet_list_mode(0);
byte namehash[20];
int use_namehash=0;
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( rc ) {
if( rc == -1 )
rc = G10ERR_NO_PUBKEY;
else if( rc )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
/* try the quick functions */
k = NULL;
switch( mode ) {
case 10:
case 11:
rc = locate_keyblock_by_keyid( &kbpos, keyid, mode==10, 0 );
if( !rc )
rc = read_keyblock( &kbpos, &keyblock );
if( !rc )
k = find_by_keyid( keyblock, pk, keyid, mode );
break;
case 16:
case 20:
rc = locate_keyblock_by_fpr( &kbpos, name, mode, 0 );
if( !rc )
rc = read_keyblock( &kbpos, &keyblock );
if( !rc )
k = find_by_fpr( keyblock, pk, name, mode );
break;
default: rc = G10ERR_UNSUPPORTED;
}
if( !rc ) {
if( !k ) {
log_error("lookup: key has been located but was not found\n");
rc = G10ERR_INV_KEYRING;
}
else
finish_lookup( keyblock, pk, k, namehash, 0, primary );
}
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
KBNODE k, kk;
if( mode < 10 ) { /* name lookup */
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_USER_ID
&& !compare_name( k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len, name, mode)) {
/* we found a matching name, look for the key */
for(kk=keyblock; kk; kk = kk->next ) {
if( ( kk->pkt->pkttype == PKT_PUBLIC_KEY
|| kk->pkt->pkttype == PKT_PUBLIC_SUBKEY )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== kk->pkt->pkt.public_key->pubkey_algo)
&& ( !pk->pubkey_usage
|| !check_pubkey_algo2(
kk->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ))
)
break;
}
if( kk ) {
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
rmd160_hash_buffer( namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
use_namehash = 1;
k = kk;
break;
}
else
log_error("No key for userid\n");
/* if this was not possible, loop over all keyblocks
* fixme: If one of the resources in the quick functions above
* works, but the key was not found, we will not find it
* in the other resources */
if( rc == G10ERR_UNSUPPORTED ) {
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( !rc ) {
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
if( mode < 10 )
k = find_by_name( keyblock, pk, name, mode,
namehash, &use_namehash);
else if( mode == 10 || mode == 11 )
k = find_by_keyid( keyblock, pk, keyid, mode );
else if( mode == 15 )
k = find_first( keyblock, pk );
else if( mode == 16 || mode == 20 )
k = find_by_fpr( keyblock, pk, name, mode );
else
BUG();
if( k ) {
finish_lookup( keyblock, pk, k, namehash,
use_namehash, primary );
break; /* found */
}
}
}
else { /* keyid or fingerprint lookup */
if( DBG_CACHE && (mode== 10 || mode==11) ) {
log_debug("lookup keyid=%08lx%08lx req_algo=%d mode=%d\n",
(ulong)keyid[0], (ulong)keyid[1],
pk->pubkey_algo, mode );
}
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
if( mode == 10 || mode == 11 ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
if( DBG_CACHE ) {
log_debug(" aki=%08lx%08lx algo=%d\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo );
}
if( aki[1] == keyid[1]
&& ( mode == 10 || aki[0] == keyid[0] )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo) ){
/* cache the userid */
for(kk=keyblock; kk; kk = kk->next )
if( kk->pkt->pkttype == PKT_USER_ID )
break;
if( kk )
cache_user_id( kk->pkt->pkt.user_id, aki );
else
log_error("No userid for key\n");
break; /* found */
}
}
else if( mode == 15 ) { /* get the first key */
if( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo )
break;
}
else if( mode == 16 || mode == 20 ) {
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
if( DBG_CACHE ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
log_debug(" aki=%08lx%08lx algo=%d mode=%d an=%u\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo,
mode, an );
}
if( an == mode && !memcmp( afp, name, an)
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo) ) {
break;
}
}
else
BUG();
} /* end compare public keys */
}
}
if( k ) { /* found */
assert( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY );
assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
if( primary && !pk->pubkey_usage ) {
copy_public_key_new_namehash( pk, keyblock->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, keyblock );
}
else {
if( primary && pk->pubkey_usage
&& check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
for( ; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
break;
}
if( !k )
k = save_k;
else
log_info(_("using secondary key %08lX "
"instead of primary key %08lX\n"),
(ulong)keyid_from_pk( k->pkt->pkt.public_key, NULL),
(ulong)keyid_from_pk( save_k->pkt->pkt.public_key, NULL)
);
}
copy_public_key_new_namehash( pk, k->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, k );
}
if( ret_keyblock ) {
*ret_keyblock = keyblock;
release_kbnode( keyblock );
keyblock = NULL;
}
break; /* enumeration */
}
release_kbnode( keyblock );
keyblock = NULL;
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
if( rc && rc != -1 )
log_error("enum_keyblocks failed: %s\n", g10_errstr(rc));
}
if( rc == -1 )
rc = G10ERR_NO_PUBKEY;
else if( rc )
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
leave:
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
if( !rc ) {
if( ret_keyblock ) {
*ret_keyblock = keyblock;
keyblock = NULL;
}
}
else if( rc == -1 )
rc = G10ERR_NO_PUBKEY;
release_kbnode( keyblock );
set_packet_list_mode(oldmode);
if( opt.debug & DBG_MEMSTAT_VALUE ) {

View file

@ -46,6 +46,7 @@ new_kbnode( PACKET *pkt )
n->pkt = pkt;
n->flag = 0;
n->private_flag=0;
n->recno = 0;
return n;
}

View file

@ -46,6 +46,7 @@ struct kbnode_struct {
PACKET *pkt;
int flag;
int private_flag;
ulong recno; /* used while updating the trustdb */
};
@ -69,6 +70,7 @@ struct keyblock_pos_struct {
int secret; /* working on a secret keyring */
#ifdef HAVE_LIBGDBM
GDBM_FILE dbf;
byte keybuf[21];
#endif
PACKET *pkt; /* ditto */
};
@ -172,6 +174,10 @@ const char *enum_keyblock_resources( int *sequence, int secret );
int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
int fprlen, int secret );
int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,
int shortkid, int secret );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
int find_keyblock_byname( KBPOS *kbpos, const char *username );
int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );

View file

@ -541,10 +541,18 @@ ask_expiredate()
static int
has_invalid_email_chars( const char *s )
{
int at_seen=0;
for( ; *s; s++ ) {
if( *s & 0x80 )
return 1;
if( !strchr("01234567890abcdefghijklmnopqrstuvwxyz_-.@", *s ) )
if( *s == '@' )
at_seen=1;
else if( !at_seen
&& !strchr("01234567890abcdefghijklmnopqrstuvwxyz_-.+", *s ))
return 1;
else if( at_seen
&& !strchr("01234567890abcdefghijklmnopqrstuvwxyz_-.", *s ) )
return 1;
}
return 0;

View file

@ -37,6 +37,7 @@
static void list_all(int);
static void list_one(const char *name, int secret);
static void list_keyblock( KBNODE keyblock, int secret );
static void fingerprint( PKT_public_key *pk, PKT_secret_key *sk );
@ -70,63 +71,87 @@ secret_key_list( int nnames, char **names )
static void
list_all( int secret )
{
int i, seq=0;
const char *s;
IOBUF a;
KBPOS kbpos;
KBNODE keyblock = NULL;
int rc=0;
int lastresno;
/* FIXME: this assumes a keyring resource is a plain keyring file */
while( (s = enum_keyblock_resources( &seq, secret )) ) {
if( !(a = iobuf_open(s)) ) {
log_error(_("can't open %s: %s\n"), s, strerror(errno));
continue;
}
if( seq > 1 )
putchar('\n');
printf("%s\n", s );
for(i=strlen(s); i; i-- )
putchar('-');
putchar('\n');
proc_packets( a );
iobuf_close(a);
rc = enum_keyblocks( secret? 5:0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
}
lastresno = -1;
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
if( lastresno != kbpos.resno ) {
const char *s = keyblock_resource_name( &kbpos );
int i;
lastresno = kbpos.resno;
printf("%s\n", s );
for(i=strlen(s); i; i-- )
putchar('-');
putchar('\n');
}
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock ); keyblock = NULL;
}
if( rc && rc != -1 )
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
leave:
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
}
static void
list_one( const char *name, int secret )
{
int rc = 0;
KBNODE keyblock = NULL;
KBPOS kbpos;
rc = secret? find_secret_keyblock_byname( &kbpos, name )
: find_keyblock_byname( &kbpos, name );
if( rc ) {
log_error("%s: user not found\n", name );
return;
}
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: keyblock read problem: %s\n", name, g10_errstr(rc) );
return;
}
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock );
}
static void
list_keyblock( KBNODE keyblock, int secret )
{
int rc = 0;
KBNODE kbctx;
KBNODE node;
KBPOS kbpos;
PKT_public_key *pk;
PKT_secret_key *sk;
u32 keyid[2];
int any=0;
int trustletter = 0;
/* search the userid */
rc = secret? find_secret_keyblock_byname( &kbpos, name )
: find_keyblock_byname( &kbpos, name );
if( rc ) {
log_error("%s: user not found\n", name );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: keyblock read problem: %s\n", name, g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
if( !node ) {
log_error("Oops; key lost!\n");
goto leave;
return;
}
if( secret ) {
@ -336,12 +361,10 @@ list_one( const char *name, int secret )
putchar(':');
putchar('\n');
}
leave:
release_kbnode( keyblock );
}
static void
fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
{

View file

@ -886,10 +886,14 @@ proc_tree( CTX c, KBNODE node )
c->local_id = 0;
c->trustletter = ' ';
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
merge_keys_and_selfsig( node );
list_node( c, node );
else if( node->pkt->pkttype == PKT_SECRET_KEY )
}
else if( node->pkt->pkttype == PKT_SECRET_KEY ) {
merge_keys_and_selfsig( node );
list_node( c, node );
}
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
/* check all signatures */
if( !c->have_data ) {

View file

@ -35,8 +35,6 @@
*
* - Delete a key block
*
* FIXME: Keep track of all nodes, so that a change is propagated
* to all nodes. (or use shallow copies and ref-counting?)
*/
@ -59,10 +57,10 @@
#include "mpi.h"
#include "iobuf.h"
#include "keydb.h"
#include "host2net.h"
#include "options.h"
#include "i18n.h"
#undef HAVE_LIBGDBM /* <--- not ready */
struct resource_table_struct {
int used;
@ -88,6 +86,14 @@ static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
#ifdef HAVE_LIBGDBM
static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
const byte *fpr, int fprlen );
static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );
static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root );
static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root );
#endif
static RESTBL *
@ -100,6 +106,14 @@ check_pos( KBPOS *kbpos )
return resource_table + kbpos->resno;
}
#ifdef HAVE_LIBGDBM
static void
fatal_gdbm_error( const char *string )
{
log_fatal("gdbm failed: %s\n", string);
}
#endif /* HAVE_LIBGDBM */
/****************************************************************
****************** public functions ****************************
@ -188,9 +202,33 @@ add_keyblock_resource( const char *url, int force, int secret )
goto leave;
}
/* see whether we can determine the filetype */
if( rt == rt_UNKNOWN ) {
FILE *fp = fopen( filename, "rb" );
if( fp ) {
u32 magic;
if( fread( &magic, 4, 1, fp) == 1 ) {
if( magic == 0x13579ace )
rt = rt_GDBM;
else if( magic == 0xce9a5713 )
log_error("%s: endianess does not match\n", url );
else
rt = rt_RING;
}
fclose( fp );
}
else /* no file yet: create ring */
rt = rt_RING;
}
switch( rt ) {
case rt_UNKNOWN:
log_error("%s: unknown resource type\n", url );
rc = G10ERR_GENERAL;
goto leave;
case rt_RING:
iobuf = iobuf_fopen( filename, "rb" );
if( !iobuf && !force ) {
@ -199,20 +237,46 @@ add_keyblock_resource( const char *url, int force, int secret )
}
if( !iobuf ) {
char *last_slash_in_filename;
last_slash_in_filename = strrchr(filename, '/');
*last_slash_in_filename = 0;
if( access(filename, F_OK) ) {
if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
#if __MINGW32__
if( mkdir(filename) )
#else
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
#endif
{
log_error( _("%s: can't create directory: %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else
log_info( _("%s: directory created\n"), filename );
}
else
{
rc = G10ERR_OPEN_FILE;
goto leave;
}
}
*last_slash_in_filename = '/';
iobuf = iobuf_create( filename );
if( !iobuf ) {
log_error("%s: can't create: %s\n", filename, strerror(errno));
log_error("%s: can't create keyring: %s\n", filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else
log_info("%s: keyring created\n", filename );
}
/* fixme: see whether it is really a ring or if type is unknown,
* try to figure out of what type it is
*/
rt = rt_RING; /* <--- FIXME */
#ifdef __MINGW32__
/* must close it again */
iobuf_close( iobuf );
@ -222,6 +286,17 @@ add_keyblock_resource( const char *url, int force, int secret )
#ifdef HAVE_LIBGDBM
case rt_GDBM:
resource_table[i].dbf = gdbm_open( filename, 0,
force? GDBM_WRCREAT : GDBM_WRITER,
S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
fatal_gdbm_error );
if( !resource_table[i].dbf ) {
log_error("%s: can't open gdbm file: %s\n",
filename, gdbm_strerror(gdbm_errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
break;
#endif
@ -310,14 +385,21 @@ search( PACKET *pkt, KBPOS *kbpos, int secret )
resource_table[i].fname );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM
rc = do_gdbm_search( pkt, kbpos, resource_table[i].dbf,
resource_table[i].fname );
case rt_GDBM: {
PKT_public_key *req_pk = pkt->pkt.public_key;
byte fpr[20];
size_t fprlen;
fingerprint_from_pk( req_pk, fpr, &fprlen );
rc = do_gdbm_locate( resource_table[i].dbf,
kbpos, fpr, fprlen );
}
break;
#endif
default: BUG();
}
kbpos->rt = resource_table[i].rt;
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
@ -404,6 +486,92 @@ find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
}
/****************
* Locate a keyblock in a database which is capable of direct access
* Put all information into KBPOS, which can be later be to access this
* key block.
* This function looks into all registered keyblock sources.
*
* Returns: 0 if found,
* -1 if not found
* G10ERR_UNSUPPORTED if no resource is able to handle this
* or another errorcode.
*/
int
locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret )
{
RESTBL *rentry;
int i, rc, any=0, last_rc=-1;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
case rt_GDBM:
any = 1;
rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
break;
default:
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
}
int
locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret )
{
RESTBL *rentry;
int i, rc, any=0, last_rc=-1;
if( shortkid )
return G10ERR_UNSUPPORTED;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
case rt_GDBM:
any = 1;
rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
break;
default:
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
}
/****************
* Lock the keyblock; wait until it's available
@ -502,7 +670,8 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME!!!! */
/* FIXME: make sure that there is only one enum at a time */
kbpos->offset = 0;
break;
#endif
default: BUG();
@ -521,7 +690,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME!!!! */
rc = do_gdbm_enum( kbpos, ret_root );
break;
#endif
default: BUG();
@ -548,11 +717,8 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
kbpos->fp = NULL;
}
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME!!!! */
break;
#endif
default: BUG();
}
/* release pending packet */
@ -583,7 +749,7 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME!!!! */
rc = do_gdbm_store( kbpos, root, 0 );
break;
#endif
default: BUG();
@ -639,7 +805,7 @@ update_keyblock( KBPOS *kbpos, KBNODE root )
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME!!!! */
rc = do_gdbm_store( kbpos, root, 1 );
break;
#endif
default: BUG();
@ -1129,58 +1295,179 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
********** Functions which operates on GDM files ***************
****************************************************************/
#if MAX_FINGERPRINT_LEN > 20
#error A GDBM keyring assumes that fingerprints are less than 21
#endif
/****************
* Insert the keyblock into the GDBM database
*/
static int
do_gdbm_store( KBPOS *kbpos, KBNODE root, int update )
{
RESTBL *rentry;
PKT_public_key *pk;
KBNODE kbctx, node;
IOBUF fp = NULL;
byte fpr[20];
byte contbuf[21];
byte keybuf[21];
size_t fprlen;
datum key, content;
int i, rc;
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
/* construct the fingerprint which is used as the primary key */
node = find_kbnode( root, PKT_PUBLIC_KEY );
if( !node )
log_bug("a gdbm database can't store secret keys\n");
pk = node->pkt->pkt.public_key;
fingerprint_from_pk( pk, fpr, &fprlen );
for(i=fprlen; i < DIM(fpr); i++ )
fpr[i] = 0;
/* build the keyblock */
kbctx=NULL;
fp = iobuf_temp();
iobuf_put( fp, 1 ); /* data is a keyblock */
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( fp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
/* store data and key */
*keybuf = 1; /* key is a padded fingerprint */
memcpy(keybuf+1, fpr, 20 );
key.dptr = keybuf;
key.dsize = 21;
content.dptr = iobuf_get_temp_buffer( fp );
content.dsize = iobuf_get_temp_length( fp );
rc = gdbm_store( rentry->dbf, key, content,
update? GDBM_REPLACE : GDBM_INSERT );
if( rc ) {
log_error("%s: gdbm_store failed: %s\n", rentry->fname,
rc == 1 ? "already stored"
: gdbm_strerror(gdbm_errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
/* now store all keyids */
*contbuf = 2; /* data is a list of fingerprints */
memcpy(contbuf+1, fpr, 20 );
content.dptr = contbuf;
content.dsize= 21;
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 aki[2];
keyid_from_pk( node->pkt->pkt.public_key, aki );
*keybuf = 2; /* key is a 8 byte keyid */
u32tobuf( keybuf+1 , aki[0] );
u32tobuf( keybuf+5, aki[1] );
key.dptr = keybuf;
key.dsize= 9;
/* fixme: must be more clever when a insert failed:
* build a list of fingerprints in this case */
rc = gdbm_store( rentry->dbf, key, content,
update? GDBM_REPLACE : GDBM_INSERT );
if( rc ) {
log_info("%s: gdbm_store keyid failed: %s\n", rentry->fname,
rc == 1 ? "already stored"
: gdbm_strerror(gdbm_errno) );
rc = 0;
}
}
}
leave:
iobuf_close(fp); /* don't need a cancel because it is a temp iobuf */
return rc;
}
/****************
* search one keybox, return 0 if found, -1 if not found or an errorcode.
*/
static int
do_gdbm_search( PACKET *req, KBPOS *kbpos, GDBM_FILE dbf, const char *fname )
do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen )
{
byte *keybuf = kbpos->keybuf;
datum key;
int i;
*keybuf = 1;
for(i=0; i < fprlen; i++ )
keybuf[i+1] = fpr[i];
for(; i < 20; i++ )
keybuf[i+1] = 0;
/* fetch the data */
key.dptr = keybuf;
key.dsize = 21;
if( !gdbm_exists( dbf, key ) )
return -1; /* not found */
return 0;
}
/****************
* locate by keyid.
* FIXME: we must have a way to enumerate thru the list opf fingerprints
*/
static int
do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
{
byte keybuf[9];
datum key, content;
int rc;
PACKET pkt;
int save_mode;
ulong offset;
int pkttype = req->pkttype;
PKT_public_key *req_pk = req->pkt.public_key;
PKT_secret_key *req_sk = req->pkt.secret_key;
init_packet(&pkt);
save_mode = set_packet_list_mode(0);
/* construct the fingerprint which is used as the primary key */
*keybuf = 2;
u32tobuf( keybuf+1, keyid[0] );
u32tobuf( keybuf+5, keyid[1] );
/* fetch the data */
key.dptr = keybuf;
key.dsize = 9;
content = gdbm_fetch( dbf, key );
if( !content.dptr )
return -1;
while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
if( pkt.pkttype == PKT_SECRET_KEY ) {
PKT_secret_key *sk = pkt.pkt.secret_key;
if( req_sk->timestamp == sk->timestamp
&& req_sk->pubkey_algo == sk->pubkey_algo
&& !cmp_seckey( req_sk, sk) )
break; /* found */
}
else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
PKT_public_key *pk = pkt.pkt.public_key;
if( req_pk->timestamp == pk->timestamp
&& req_pk->pubkey_algo == pk->pubkey_algo
&& !cmp_pubkey( req_pk, pk ) )
break; /* found */
}
else
BUG();
free_packet(&pkt);
if( content.dsize < 2 ) {
log_error("gdbm_fetch did not return enough data\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( !rc )
kbpos->offset = offset;
if( *content.dptr != 2 ) {
log_error("gdbm_fetch returned unexpected type %d\n",
*(byte*)content.dptr );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( content.dsize < 21 ) {
log_error("gdbm_fetch did not return a complete fingerprint\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( content.dsize > 21 )
log_info("gdbm_fetch: warning: more than one fingerprint\n" );
leave:
free_packet(&pkt);
set_packet_list_mode(save_mode);
#if __MINGW32__
iobuf_close(iobuf);
#endif
rc = do_gdbm_locate( dbf, kbpos, content.dptr+1, 20 );
free( content.dptr ); /* can't use m_free() here */
return rc;
}
static int
do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
{
@ -1189,22 +1476,32 @@ do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
RESTBL *rentry;
KBNODE root = NULL;
IOBUF a;
int in_cert = 0;
datum key, content;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
a = iobuf_fopen( rentry->fname, "rb" );
if( !a ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
key.dptr = kbpos->keybuf;
key.dsize = 21;
content = gdbm_fetch( rentry->dbf, key );
if( !content.dptr ) {
log_error("gdbm_fetch failed: %s\n", gdbm_strerror(gdbm_errno) );
return G10ERR_INV_KEYRING;
}
if( content.dsize < 2 ) {
log_error("gdbm_fetch did not return enough data\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( *content.dptr != 1 ) {
log_error("gdbm_fetch returned unexpected type %d\n",
*(byte*)content.dptr );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( iobuf_seek( a, kbpos->offset ) ) {
log_error("can't seek to %lu\n", kbpos->offset);
iobuf_close(a);
return G10ERR_KEYRING_OPEN;
}
a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 );
free( content.dptr ); /* can't use m_free() here */
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
@ -1214,7 +1511,7 @@ do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
break;
}
kbpos->count++;
free_packet( pkt );
@ -1222,27 +1519,16 @@ do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
if( in_cert )
goto ready;
in_cert = 1;
default:
kbpos->count++;
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
kbpos->count++;
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
}
ready:
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
@ -1254,84 +1540,43 @@ do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
}
/****************
* Enum over keyblok data
*/
static int
do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
datum key, helpkey;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
if( kbpos->pkt ) {
root = new_kbnode( kbpos->pkt );
kbpos->pkt = NULL;
if( !kbpos->offset ) {
kbpos->offset = 1;
key = gdbm_firstkey( rentry->dbf );
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
if( root ) { /* store this packet */
kbpos->pkt = pkt;
pkt = NULL;
goto ready;
}
root = new_kbnode( pkt );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
default:
/* skip pakets at the beginning of a keyring, until we find
* a start packet; issue a warning if it is not a comment */
if( !root && pkt->pkttype != PKT_COMMENT
&& pkt->pkttype != PKT_OLD_COMMENT ) {
log_info("keyring_enum: skipped packet of type %d\n",
pkt->pkttype );
break;
}
if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
||pkt->pkttype == PKT_COMMENT
||pkt->pkttype == PKT_OLD_COMMENT )) ) {
init_packet(pkt);
break;
}
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
else {
helpkey.dptr = kbpos->keybuf;
helpkey.dsize= 21;
key = gdbm_nextkey( rentry->dbf, helpkey );
}
ready:
if( rc == -1 && root )
rc = 0;
while( key.dptr && (!key.dsize || *key.dptr != 1) ) {
helpkey = key;
key = gdbm_nextkey( rentry->dbf, helpkey );
free( helpkey.dptr ); /* free and not m_free() ! */
}
if( !key.dptr )
return -1; /* eof */
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
return rc;
if( key.dsize < 21 ) {
free( key.dptr ); /* free and not m_free() ! */
log_error("do_gdm_enum: key is too short\n" );
return G10ERR_INV_KEYRING;
}
memcpy( kbpos->keybuf, key.dptr, 21 );
free( key.dptr ); /* free and not m_free() ! */
return do_gdbm_read( kbpos, ret_root );
}
#endif /*HAVE_LIBGDBM*/

View file

@ -108,9 +108,6 @@ only_old_style( SK_LIST sk_list )
SK_LIST sk_rover = NULL;
int old_style = 0;
if( opt.force_v3_sigs )
return 1;
/* if there are only old style capable key we use the old sytle */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
@ -159,7 +156,6 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
int compr_algo = -1; /* unknown */
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
memset( &mfx, 0, sizeof mfx);
@ -181,6 +177,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
goto leave;
if( !old_style )
old_style = only_old_style( sk_list );
if( encrypt ) {
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) )
goto leave;
@ -372,7 +369,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
/* build the signature packet */
/* fixme: this code is partly duplicated in make_keysig_packet */
sig = m_alloc_clear( sizeof *sig );
sig->version = old_style? 3 : sk->version;
sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version;
keyid_from_sk( sk, sig->keyid );
sig->digest_algo = hash_for(sk->pubkey_algo);
sig->pubkey_algo = sk->pubkey_algo;
@ -608,7 +605,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
/* build the signature packet */
/* fixme: this code is duplicated above */
sig = m_alloc_clear( sizeof *sig );
sig->version = old_style? 3 : sk->version;
sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version;
keyid_from_sk( sk, sig->keyid );
sig->digest_algo = hash_for(sk->pubkey_algo);
sig->pubkey_algo = sk->pubkey_algo;

View file

@ -269,7 +269,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( access( fname, R_OK ) ) {
if( errno != ENOENT ) {
log_error_f( fname, _("can't access: %s\n"), strerror(errno) );
log_error( _("%s: can't access: %s\n"), fname, strerror(errno) );
m_free(fname);
return G10ERR_TRUSTDB;
}
@ -289,17 +289,19 @@ tdbio_set_dbname( const char *new_dbname, int create )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
#endif
log_fatal_f( fname, _("can't create directory: %s\n"),
strerror(errno) );
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else
log_info( _("%s: directory created\n"), fname );
}
else
log_fatal_f(fname, _("directory does not exist!\n") );
log_fatal( _("%s: directory does not exist!\n"), fname );
}
*p = '/';
fp =fopen( fname, "wb" );
if( !fp )
log_fatal_f( fname, _("can't create: %s\n"), strerror(errno) );
log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) );
fclose(fp);
m_free(db_name);
db_name = fname;
@ -309,7 +311,7 @@ tdbio_set_dbname( const char *new_dbname, int create )
db_fd = open( db_name, O_RDWR );
#endif
if( db_fd == -1 )
log_fatal_f( db_name, _("can't open: %s\n"), strerror(errno) );
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
memset( &rec, 0, sizeof rec );
rec.r.ver.version = 2;
@ -320,11 +322,14 @@ tdbio_set_dbname( const char *new_dbname, int create )
if( !rc )
tdbio_sync();
if( rc )
log_fatal_f( fname, _("failed to create version record: %s"),
g10_errstr(rc));
log_fatal( _("%s: failed to create version record: %s"),
fname, g10_errstr(rc));
/* and read again to check that we are okay */
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal_f( db_name, "invalid trust-db created\n" );
log_fatal( _("%s: invalid trust-db created\n"), db_name );
log_info(_("%s: trust-db created\n"), db_name);
return 0;
}
}
@ -354,9 +359,9 @@ open_db()
db_fd = open( db_name, O_RDWR );
#endif
if( db_fd == -1 )
log_fatal_f( db_name, _("can't open: %s\n"), strerror(errno) );
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal_f( db_name, _("invalid trust-db\n") );
log_fatal( _("%s: invalid trust-db\n"), db_name );
/* fixme: check ->locked and other stuff */
}
@ -390,16 +395,16 @@ create_hashtable( TRUSTREC *vr, int type )
rec.recnum = recnum;
rc = tdbio_write_record( &rec );
if( rc )
log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
g10_errstr(rc));
log_fatal( _("%s: failed to create hashtable: %s\n"),
db_name, g10_errstr(rc));
}
/* update the version record */
rc = tdbio_write_record( vr );
if( !rc )
rc = tdbio_sync();
if( rc )
log_fatal_f( db_name, _("error updating version record: %s\n"),
g10_errstr(rc));
log_fatal( _("%s: error updating version record: %s\n"),
db_name, g10_errstr(rc));
}
@ -418,8 +423,8 @@ get_keyhashrec()
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal_f( db_name, _("error reading version record: %s\n"),
g10_errstr(rc) );
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.keyhashtbl )
create_hashtable( &vr, 0 );
@ -443,8 +448,8 @@ get_sdirhashrec()
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal_f( db_name, _("error reading version record: %s\n"),
g10_errstr(rc) );
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.sdirhashtbl )
create_hashtable( &vr, 1 );
@ -744,14 +749,14 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.dir.uidlist,
rec->r.dir.cacherec,
rec->r.dir.ownertrust );
if( rec->r.dir.dirflags & DIRF_ERROR )
fputs(", error", fp );
if( rec->r.dir.dirflags & DIRF_CHECKED )
fputs(", checked", fp );
if( rec->r.dir.dirflags & DIRF_REVOKED )
fputs(", revoked", fp );
if( rec->r.dir.dirflags & DIRF_MISKEY )
fputs(", miskey", fp );
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 );
}
putc('\n', fp);
break;
case RECTYPE_KEY:
@ -761,8 +766,14 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
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_REVOKED )
fputs(", revoked", fp );
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:
@ -772,12 +783,12 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
if( rec->r.uid.uidflags & UIDF_CHECKED )
fputs(", checked", fp );
if( rec->r.uid.uidflags & UIDF_VALID )
fputs(", valid", fp );
if( rec->r.uid.uidflags & UIDF_REVOKED )
fputs(", revoked", fp );
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:
@ -795,9 +806,19 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
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:%02x", rec->r.sig.sig[i].lid,
rec->r.sig.sig[i].flag );
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_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;
@ -876,7 +897,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
break;
case RECTYPE_VER: /* version record */
if( memcmp(buf+1, "gpg", 3 ) ) {
log_error_f( db_name, _("not a trustdb file\n") );
log_error( _("%s: not a trustdb file\n"), db_name );
rc = G10ERR_TRUSTDB;
}
p += 2; /* skip "pgp" */
@ -890,12 +911,12 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.ver.firstfree =buftoulong(p); p += 4;
rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
if( recnum ) {
log_error_f( db_name, "version record with recnum %lu\n",
log_error( _("%s: version record with recnum %lu\n"), db_name,
(ulong)recnum );
rc = G10ERR_TRUSTDB;
}
else if( rec->r.ver.version != 2 ) {
log_error_f( db_name, "invalid file version %d\n",
log_error( _("%s: invalid file version %d\n"), db_name,
rec->r.ver.version );
rc = G10ERR_TRUSTDB;
}
@ -911,8 +932,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.dir.ownertrust = *p++;
rec->r.dir.dirflags = *p++;
if( rec->r.dir.lid != recnum ) {
log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n",
rec->r.dir.lid, (ulong)recnum );
log_error( "%s: dir LID != recnum (%lu,%lu)\n",
db_name, rec->r.dir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
@ -957,8 +978,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
p += 3;
rec->r.sdir.hintlist = buftoulong(p);
if( rec->r.sdir.lid != recnum ) {
log_error_f( db_name, "sdir LID != recnum (%lu,%lu)\n",
rec->r.sdir.lid, (ulong)recnum );
log_error( "%s: sdir LID != recnum (%lu,%lu)\n",
db_name, rec->r.sdir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
@ -979,8 +1000,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
}
break;
default:
log_error_f( db_name, "invalid record type %d at recnum %lu\n",
rec->rectype, (ulong)recnum );
log_error( "%s: invalid record type %d at recnum %lu\n",
db_name, rec->rectype, (ulong)recnum );
rc = G10ERR_TRUSTDB;
break;
}
@ -1122,8 +1143,8 @@ tdbio_delete_record( ulong recnum )
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal_f( db_name, _("error reading version record: %s\n"),
g10_errstr(rc) );
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
rec.recnum = recnum;
rec.rectype = RECTYPE_FREE;
@ -1149,22 +1170,22 @@ tdbio_new_recnum()
/* look for unused records */
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal_f( db_name, _("error reading version record: %s\n"),
g10_errstr(rc) );
log_fatal( _("%s: error reading version record: %s\n"),
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_f( db_name, _("error reading free record: %s\n"),
g10_errstr(rc) );
log_error( _("%s: error reading free record: %s\n"),
db_name, g10_errstr(rc) );
return rc;
}
/* update dir record */
vr.r.ver.firstfree = rec.r.free.next;
rc = tdbio_write_record( &vr );
if( rc ) {
log_error_f( db_name, _("error writing dir record: %s\n"),
g10_errstr(rc) );
log_error( _("%s: error writing dir record: %s\n"),
db_name, g10_errstr(rc) );
return rc;
}
/*zero out the new record */
@ -1173,8 +1194,8 @@ tdbio_new_recnum()
rec.recnum = recnum;
rc = tdbio_write_record( &rec );
if( rc )
log_fatal_f(db_name,_("failed to zero a record: %s\n"),
g10_errstr(rc));
log_fatal(_("%s: failed to zero a record: %s\n"),
db_name, g10_errstr(rc));
}
else { /* not found, append a new record */
offset = lseek( db_fd, 0, SEEK_END );
@ -1203,8 +1224,8 @@ tdbio_new_recnum()
}
if( rc )
log_fatal_f(db_name,_("failed to append a record: %s\n"),
g10_errstr(rc));
log_fatal(_("%s: failed to append a record: %s\n"),
db_name, g10_errstr(rc));
}
return recnum ;
}
@ -1230,10 +1251,9 @@ tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
if( !rc ) {
if( pk->local_id && pk->local_id != rec->recnum )
log_error_f(db_name,
"found record, but LID from memory does "
log_error("%s: found record, but LID from memory does "
"not match recnum (%lu,%lu)\n",
pk->local_id, rec->recnum );
db_name, pk->local_id, rec->recnum );
pk->local_id = rec->recnum;
}
return rc;
@ -1272,8 +1292,8 @@ tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
/* Now read the dir record */
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
if( rc )
log_error_f(db_name, "can't read dirrec %lu: %s\n",
recnum, g10_errstr(rc) );
log_error("%s: can't read dirrec %lu: %s\n",
db_name, recnum, g10_errstr(rc) );
}
return rc;
}

View file

@ -21,6 +21,7 @@
#ifndef G10_TDBIO_H
#define G10_TDBIO_H
#include "host2net.h"
#define TRUST_RECORD_LEN 40
#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5)
@ -46,15 +47,14 @@
#define RECTYPE_FREE 254
#define DIRF_CHECKED 1 /* everything has been checked, the other bits are
valid */
#define DIRF_MISKEY 2 /* not all signatures are checked */
/* this flag is used as a quick hint, that we */
/* do not need to look at the sig records */
#define DIRF_ERROR 4 /* severe errors: the key is not valid for some reasons
but we mark it to avoid duplicate checks */
#define DIRF_CHECKED 1 /* has been checkd - other bits are valid */
#define DIRF_VALID 2 /* This key is valid: There is at least */
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
#define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */
@ -64,6 +64,7 @@
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
#define SIGF_VALID 2 /* the signature is valid */
#define SIGF_EXPIRED 4 /* the key of this signature has expired */
#define SIGF_REVOKED 8 /* this signature has been revoked */
#define SIGF_NOPUBKEY 128 /* there is no pubkey for this sig */
@ -176,22 +177,4 @@ int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
#define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
(*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
#define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
#define ulongtobuf( p, a ) do { \
((byte*)p)[0] = a >> 24; \
((byte*)p)[1] = a >> 16; \
((byte*)p)[2] = a >> 8; \
((byte*)p)[3] = a ; \
} while(0)
#define ushorttobuf( p, a ) do { \
((byte*)p)[0] = a >> 8; \
((byte*)p)[1] = a ; \
} while(0)
#define buftou32( p) buftoulong( (p) )
#define u32tobuf( p, a) ulongtobuf( (p), (a) )
#endif /*G10_TDBIO_H*/

View file

@ -1370,6 +1370,8 @@ update_trustdb( )
else
log_info("lid %lu: updated\n",
lid_from_keyblock(keyblock) );
release_kbnode( keyblock ); keyblock = NULL;
}
}
if( rc && rc != -1 )
@ -1910,7 +1912,6 @@ upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list )
}
if( recno ) { /* yes */
ins_recno_list( recno_list, recno, RECTYPE_KEY );
/* here we would compare/update the keyflags */
}
else { /* no: insert this new key */
memset( &krec, 0, sizeof(krec) );
@ -2110,6 +2111,8 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
}
}
else if( sig->sig_class == 0x18 ) { /* key binding */
/* get the corresponding key */
/* FIXME */
}
else if( sig->sig_class == 0x20 ) { /* key revocation */
@ -2427,6 +2430,7 @@ update_trust_record( KBNODE keyblock )
ulong uidrecno = 0;
byte uidhash[20];
RECNO_LIST recno_list = NULL; /* list of verified records */
/* fixme: replace recno_list by a lookup on node->recno */
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
primary_pk = node->pkt->pkt.public_key;
@ -2459,6 +2463,7 @@ update_trust_record( KBNODE keyblock )
case PKT_SIGNATURE:
if( drec.dirty ) { /* upd_sig_recrod may read the drec */
write_record( &drec );
drec.dirty = 0;
}