summaryrefslogtreecommitdiffstats
path: root/g10/ringedit.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-10-21 19:34:36 +0200
committerWerner Koch <wk@gnupg.org>1998-10-21 19:34:36 +0200
commite309a875cb938dff76983d00552ebcc08a5e90c1 (patch)
treea10cbf247317e67fcb623d7c10dfa4b4c58edbfd /g10/ringedit.c
parentSnapshot release 0.4.2 (diff)
downloadgnupg2-e309a875cb938dff76983d00552ebcc08a5e90c1.tar.xz
gnupg2-e309a875cb938dff76983d00552ebcc08a5e90c1.zip
Epxerimenta support for GDBM keyings.
Diffstat (limited to 'g10/ringedit.c')
-rw-r--r--g10/ringedit.c551
1 files changed, 398 insertions, 153 deletions
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 119cd67d0..e414d0513 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -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
+
/****************
- * search one keybox, return 0 if found, -1 if not found or an errorcode.
+ * Insert the keyblock into the GDBM database
*/
+
static int
-do_gdbm_search( PACKET *req, KBPOS *kbpos, GDBM_FILE dbf, const char *fname )
+do_gdbm_store( KBPOS *kbpos, KBNODE root, int update )
{
- 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);
-
+ 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;
- while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
- if( pkt.pkttype == PKT_SECRET_KEY ) {
- PKT_secret_key *sk = pkt.pkt.secret_key;
+ if( !(rentry = check_pos( kbpos )) )
+ return G10ERR_GENERAL;
- if( req_sk->timestamp == sk->timestamp
- && req_sk->pubkey_algo == sk->pubkey_algo
- && !cmp_seckey( req_sk, sk) )
- break; /* found */
+ /* 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;
}
- 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 */
+ }
+ /* 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;
+ }
}
- else
- BUG();
- free_packet(&pkt);
}
- if( !rc )
- kbpos->offset = offset;
leave:
- free_packet(&pkt);
- set_packet_list_mode(save_mode);
- #if __MINGW32__
- iobuf_close(iobuf);
- #endif
+ 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_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;
+
+ /* 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;
+
+ 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 != 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" );
+
+ 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,23 +1476,33 @@ 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( iobuf_seek( a, kbpos->offset ) ) {
- log_error("can't seek to %lu\n", kbpos->offset);
- iobuf_close(a);
- return G10ERR_KEYRING_OPEN;
+ 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;
}
+ 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);
kbpos->count=0;
@@ -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;
-
- if( rc )
- release_kbnode( root );
- else
- *ret_root = root;
- free_packet( pkt );
- m_free( pkt );
+ 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 */
- 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*/
-
-