aboutsummaryrefslogtreecommitdiffstats
path: root/g10/ringedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/ringedit.c')
-rw-r--r--g10/ringedit.c1240
1 files changed, 91 insertions, 1149 deletions
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 311cf41fc..de05ba6e2 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -48,9 +48,6 @@
#include <sys/stat.h>
#include <unistd.h> /* for truncate */
#include <assert.h>
-#ifdef HAVE_LIBGDBM
- #include <gdbm.h>
-#endif
#include <gcrypt.h>
#include "util.h"
@@ -71,47 +68,42 @@ struct resource_table_struct {
int secret; /* this is a secret keyring */
char *fname;
IOBUF iobuf;
- #ifdef HAVE_LIBGDBM
- GDBM_FILE dbf;
- #endif
enum resource_type rt;
DOTLOCK lockhd;
int is_locked;
};
typedef struct resource_table_struct RESTBL;
+
+struct keyblock_pos_struct {
+ int resno; /* resource number */
+ enum resource_type rt;
+ ulong offset; /* position information */
+ unsigned count; /* length of the keyblock in packets */
+ IOBUF fp; /* used by enum_keyblocks */
+ int secret; /* working on a secret keyring */
+ PACKET *pkt; /* ditto */
+ int valid;
+ ulong save_offset;
+};
+
+
+
+
#define MAX_RESOURCES 10
static RESTBL resource_table[MAX_RESOURCES];
static int default_public_resource;
static int default_secret_resource;
-static int search( PACKET *pkt, KBPOS *kbpos, int secret );
+static int keyring_enum( KBPOS kbpos, KBNODE *ret_root, int skipsigs );
+static int keyring_copy( KBPOS kbpos, int mode, KBNODE root );
-
-static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
- const char *fname );
-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 );
-
-static int do_kbxf_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
- const char *fname );
-static int do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root );
-static int do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
-static int do_kbxf_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 int do_kbxf_enum( KBPOS kbpos, KBNODE *ret_root, int skipsigs );
+static int do_kbxf_copy( KBPOS kbpos, int mode, KBNODE root );
static RESTBL *
-check_pos( KBPOS *kbpos )
+check_pos( KBPOS kbpos )
{
if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
return NULL;
@@ -120,15 +112,6 @@ 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 */
-
/****************
* Hmmm, how to avoid deadlock? They should not happen if everyone
@@ -208,7 +191,6 @@ add_keyblock_resource( const char *url, int force, int secret )
/* Do we have an URL?
- * gnupg-gdbm:filename := this is a GDBM resource
* gnupg-kbxf:filename := this is a KBX file resource
* gnupg-ring:filename := this is a plain keyring
* filename := See what is is, but create as plain keyring.
@@ -222,10 +204,6 @@ add_keyblock_resource( const char *url, int force, int secret )
rt = rt_KBXF;
resname += 11;
}
- else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
- rt = rt_GDBM;
- resname += 11;
- }
#ifndef HAVE_DRIVE_LETTERS
else if( strchr( resname, ':' ) ) {
log_error("%s: invalid URL\n", url );
@@ -263,22 +241,16 @@ add_keyblock_resource( const char *url, int force, int secret )
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 {
- char buf[8];
-
- rt = rt_RING;
- if( fread( buf, 8, 1, fp) == 1 ) {
- if( !memcmp( buf+4, "KBXf", 4 )
- && buf[0] == 1 && buf[1] == 1 ) {
- rt = rt_KBXF;
- }
- }
- }
- }
+ char buf[8];
+
+ rt = rt_RING;
+ if( fread( buf, 8, 1, fp) == 1 ) {
+ if( !memcmp( buf+4, "KBXf", 4 )
+ && buf[0] == 1 && buf[1] == 1 ) {
+ rt = rt_KBXF;
+ }
+ }
+ }
else /* maybe empty: assume ring */
rt = rt_RING;
fclose( fp );
@@ -348,21 +320,6 @@ add_keyblock_resource( const char *url, int force, int secret )
#endif
break;
- #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 = GPGERR_OPEN_FILE;
- goto leave;
- }
- break;
- #endif
default:
log_error("%s: unsupported resource type\n", url );
@@ -403,7 +360,7 @@ add_keyblock_resource( const char *url, int force, int secret )
* Return the resource name of the keyblock associated with KBPOS.
*/
const char *
-keyblock_resource_name( KBPOS *kbpos )
+keyblock_resource_name( KBPOS kbpos )
{
RESTBL *rentry;
@@ -419,7 +376,7 @@ keyblock_resource_name( KBPOS *kbpos )
* Using a filename of NULL returns the default resource
*/
int
-get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
+get_keyblock_handle( const char *filename, int secret, KBPOS kbpos )
{
int i = 0;
@@ -471,253 +428,21 @@ get_writable_keyblock_file( int secret )
}
-/****************
- * Search a keyblock which starts with the given packet and puts all
- * information into KBPOS, which can be used later to access this key block.
- * This function looks into all registered keyblock sources.
- * PACKET must be a packet with either a secret_key or a public_key
- *
- * This function is intended to check whether a given certificate
- * is already in a keyring or to prepare it for editing.
- *
- * Returns: 0 if found, -1 if not found or an errorcode.
- */
-static int
-search( PACKET *pkt, KBPOS *kbpos, int secret )
-{
- int i, rc, last_rc=-1;
-
- for(i=0; i < MAX_RESOURCES; i++ ) {
- if( resource_table[i].used && !resource_table[i].secret == !secret ) {
- switch( resource_table[i].rt ) {
- case rt_RING:
- rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
- resource_table[i].fname );
- break;
- case rt_KBXF:
- rc = do_kbxf_search( pkt, kbpos, resource_table[i].iobuf,
- resource_table[i].fname );
- break;
- #ifdef HAVE_LIBGDBM
- 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;
- return 0;
- }
- if( rc != -1 ) {
- log_error("error searching resource %d: %s\n",
- i, gpg_errstr(rc));
- last_rc = rc;
- }
- }
- }
- return last_rc;
-}
-
-
-/****************
- * Combined function to search for a username and get the position
- * of the keyblock.
- */
-int
-find_keyblock_byname( KBPOS *kbpos, const char *username )
-{
- PACKET pkt;
- PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
- int rc;
-
- rc = get_pubkey_byname( NULL, pk, username, NULL );
- if( rc ) {
- free_public_key(pk);
- return rc;
- }
-
- init_packet( &pkt );
- pkt.pkttype = PKT_PUBLIC_KEY;
- pkt.pkt.public_key = pk;
- rc = search( &pkt, kbpos, 0 );
- free_public_key(pk);
- return rc;
-}
-
-
-/****************
- * Combined function to search for a key and get the position
- * of the keyblock.
- */
-int
-find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
-{
- PACKET pkt;
- int rc;
-
- init_packet( &pkt );
- pkt.pkttype = PKT_PUBLIC_KEY;
- pkt.pkt.public_key = pk;
- rc = search( &pkt, kbpos, 0 );
- return rc;
-}
-
-/****************
- * Combined function to search for a key and get the position
- * of the keyblock.
- */
-int
-find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk )
-{
- PACKET pkt;
- int rc;
-
- init_packet( &pkt );
- pkt.pkttype = PKT_SECRET_KEY;
- pkt.pkt.secret_key = sk;
- rc = search( &pkt, kbpos, 0 );
- return rc;
-}
-
-
-/****************
- * Combined function to search for a username and get the position
- * of the keyblock. This function does not unprotect the secret key.
- */
-int
-find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
+void
+ringedit_copy_kbpos ( KBPOS d, KBPOS s )
{
- PACKET pkt;
- PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
- int rc;
-
- rc = get_seckey_byname( sk, username, 0 );
- if( rc ) {
- free_secret_key(sk);
- return rc;
- }
-
- init_packet( &pkt );
- pkt.pkttype = PKT_SECRET_KEY;
- pkt.pkt.secret_key = sk;
- rc = search( &pkt, kbpos, 1 );
- free_secret_key(sk);
- return rc;
+ *d = *s;
}
/****************
- * 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
- * GPGERR_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 ) {
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- any = 1;
- rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
- break;
- #endif
- default:
- rc = GPGERR_UNSUPPORTED;
- break;
- }
-
- if( !rc ) {
- kbpos->resno = i;
- kbpos->fp = NULL;
- return 0;
- }
- else if( rc != -1 && rc != GPGERR_UNSUPPORTED ) {
- log_error("error searching resource %d: %s\n",
- i, gpg_errstr(rc));
- last_rc = rc;
- }
- }
- }
-
- return (last_rc == -1 && !any)? GPGERR_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 GPGERR_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 ) {
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- any = 1;
- rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
- break;
- #endif
- default:
- rc = GPGERR_UNSUPPORTED;
- break;
- }
-
- if( !rc ) {
- kbpos->resno = i;
- kbpos->fp = NULL;
- return 0;
- }
- else if( rc != -1 && rc != GPGERR_UNSUPPORTED ) {
- log_error("error searching resource %d: %s\n",
- i, gpg_errstr(rc));
- last_rc = rc;
- }
- }
- }
-
- return (last_rc == -1 && !any)? GPGERR_UNSUPPORTED : last_rc;
-}
-
-
-
-
-/****************
* Lock the keyblock; wait until it's available
* This function may change the internal data in kbpos, in cases
* when the keyblock to be locked has been modified.
* fixme: remove this function and add an option to search()?
*/
-int
-lock_keyblock( KBPOS *kbpos )
+static int
+lock_keyblock( KBPOS kbpos )
{
if( !check_pos(kbpos) )
return GPGERR_GENERAL;
@@ -727,35 +452,13 @@ lock_keyblock( KBPOS *kbpos )
/****************
* Release a lock on a keyblock
*/
-void
-unlock_keyblock( KBPOS *kbpos )
+static void
+unlock_keyblock( KBPOS kbpos )
{
if( !check_pos(kbpos) )
BUG();
}
-/****************
- * Read a complete keyblock and return the root in ret_root.
- */
-int
-read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
-{
- if( !check_pos(kbpos) )
- return GPGERR_GENERAL;
-
- switch( kbpos->rt ) {
- case rt_RING:
- return keyring_read( kbpos, ret_root );
- case rt_KBXF:
- return do_kbxf_read( kbpos, ret_root );
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- return do_gdbm_read( kbpos, ret_root );
- #endif
- default: BUG();
- }
-}
-
/****************
* This functions can be used to read through a complete keyring.
@@ -765,13 +468,9 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
* 5 = open secret keyrings
* 11 = read but skip signature and comment packets.
* all others are reserved!
- * Note that you do not need a search prior to this function,
- * only a handle is needed.
- * NOTE: It is not allowed to do an insert/update/delete with this
- * keyblock, if you want to do this, use search/read!
*/
int
-enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
+enum_keyblocks( int mode, KBPOS kbpos, KBNODE *ret_root )
{
int rc = 0;
RESTBL *rentry;
@@ -811,12 +510,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
return GPGERR_OPEN_FILE;
}
break;
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- /* FIXME: make sure that there is only one enum at a time */
- kbpos->offset = 0;
- break;
- #endif
+
default: BUG();
}
kbpos->pkt = NULL;
@@ -836,11 +530,6 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
return GPGERR_GENERAL;
rc = do_kbxf_enum( kbpos, ret_root, mode == 11 );
break;
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- rc = do_gdbm_enum( kbpos, ret_root );
- break;
- #endif
default: BUG();
}
@@ -866,8 +555,6 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
kbpos->fp = NULL;
}
break;
- case rt_GDBM:
- break;
case rt_UNKNOWN:
/* this happens when we have no keyring at all */
return rc;
@@ -890,10 +577,10 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
* by KBPOS. This actually appends the data to the keyfile.
*/
int
-insert_keyblock( KBPOS *kbpos, KBNODE root )
+insert_keyblock( KBNODE root )
{
int rc;
-
+#if 0
if( !check_pos(kbpos) )
return GPGERR_GENERAL;
@@ -904,14 +591,9 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
case rt_KBXF:
rc = do_kbxf_copy( kbpos, 1, root );
break;
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- rc = do_gdbm_store( kbpos, root, 0 );
- break;
- #endif
default: BUG();
}
-
+#endif
return rc;
}
@@ -922,10 +604,10 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
* zero bytes are written.
*/
int
-delete_keyblock( KBPOS *kbpos )
+delete_keyblock( KBNODE keyblock )
{
int rc;
-
+ #if 0
if( !check_pos(kbpos) )
return GPGERR_GENERAL;
@@ -936,42 +618,43 @@ delete_keyblock( KBPOS *kbpos )
case rt_KBXF:
rc = do_kbxf_copy( kbpos, 2, NULL );
break;
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- log_debug("deleting gdbm keyblock is not yet implemented\n");
- rc = 0;
- break;
- #endif
default: BUG();
}
-
+ #endif
return rc;
}
/****************
- * Update the keyblock at KBPOS with the one in ROOT.
+ * Update the keyblock in the ring (or whatever resource) one in ROOT.
*/
int
-update_keyblock( KBPOS *kbpos, KBNODE root )
+update_keyblock( KBNODE root )
{
int rc;
+ struct WORK WORK WORK KBPOS kbpos;
+
+ /* We need to get the file position of original keyblock first */
+ if ( root->pkt->pkttype == PKT_PUBLIC_KEY )
+ rc = find_kblocation_bypk( &kbpos, root->pkt->pkt.public_key );
+ else if ( root->pkt->pkttype == PKT_SECRET_KEY )
+ rc = find_kblocation_bysk( &kbpos, root->pkt->pkt.secret_key );
+ else
+ BUG();
- if( !check_pos(kbpos) )
+ if ( rc )
+ return rc;
+
+ if( !check_pos(&kbpos) )
return GPGERR_GENERAL;
- switch( kbpos->rt ) {
+ switch( kbpos.rt ) {
case rt_RING:
- rc = keyring_copy( kbpos, 3, root );
+ rc = keyring_copy( &kbpos, 3, root );
break;
case rt_KBXF:
- rc = do_kbxf_copy( kbpos, 3, root );
- break;
- #ifdef HAVE_LIBGDBM
- case rt_GDBM:
- rc = do_gdbm_store( kbpos, root, 1 );
+ rc = do_kbxf_copy( &kbpos, 3, root );
break;
- #endif
default: BUG();
}
@@ -981,341 +664,34 @@ update_keyblock( KBPOS *kbpos, KBNODE root )
/****************************************************************
- ********** Implemenation of a user ID database **************
- ****************************************************************/
-#if 0
-/****************
- * Layout of the user ID db
- *
- * This user ID DB provides fast lookup of user ID, but the user ids are
- * not in any specific order.
- *
- * A string "GnuPG user db", a \n.
- * user ids of one key, delimited by \t,
- * a # or ^ followed by a 20 byte fingerprint, followed by an \n
- * The literal characters %, \n, \t, #, ^ must be replaced by a percent sign
- * and their hex value.
- *
- * (We use Boyer/Moore pattern matching)
- */
-
-/****************
- * This compiles pattern to the distance table, the table will be allocate
- * here and must be freed by using free().
- * Returns: Ptr to new allocated Table
- * Caller must free the table.
- */
-
-static size_t *
-compile_bm_table( const byte *pattern, size_t len )
-{
- ushort *dist;
- int i;
-
- dist = gcry_xcalloc( 1, 256 * sizeof *dist );
- for(i=0; i < 256; i++ )
- dist[i] = len;
- for(i=0; i < len-1; i++ )
- dTbl[p[i]] = len-i-1;
- return dist;
-}
-
-
-
-
-/****************
- * Search BUF of BUFLEN for pattern P of length PATLEN.
- * dist is the Boyer/Moore distance table of 256 Elements,
- * case insensitive search is done if IGNCASE is true (In this case
- * the distance table has to compiled from uppercase chacaters and
- * PAT must also be uppercase.
- * Returns: Prt to maching string in BUF, or NULL if not found.
- */
-
-static const *
-do_bm_search( const byte *buf, size_t buflen,
- const byte *pat, size_t patlen, size_t *dist, int igncase )
-{
- int i, j, k;
-
- if( igncase ) {
- int c, c1;
-
- for( i = --patlen; i < buflen; i += dist[c1] )
- for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
- j--, k--, c=toupper(buf[k]) ) {
- if( !j )
- return buf+k;
- }
- }
- else {
- for( i = --patlen; i < buflen; i += dist[buf[i]] )
- for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
- if( !j )
- return buf+k;
- }
- }
- return NULL;
-}
-
-
-typedef struct {
- size_t dist[256];
-} *SCAN_USER_HANDLE;
-
-static SCAN_USER_HANDLE
-scan_user_file_open( const byte *name )
-{
- SCAN_USER_HANDLE hd;
- size_t *dist;
- int i;
-
- hd = gcry_xcalloc( 1, sizeof *hd );
- dist = hd->dist;
- /* compile the distance table */
- for(i=0; i < 256; i++ )
- dist[i] = len;
- for(i=0; i < len-1; i++ )
- dTbl[p[i]] = len-i-1;
- /* setup other things */
-
- return hd;
-}
-
-static int
-scan_user_file_close( SCAN_USER_HANDLE hd )
-{
- gcry_free( hd );
-}
-
-static int
-scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
-{
- char record[1000];
-
- /* read a record */
-
-
-}
-#endif
-
-
-
-/****************************************************************
********** Functions which operates on regular keyrings ********
****************************************************************/
static int
-cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
-{
- int n,i;
-
- assert( req_sk->pubkey_algo == sk->pubkey_algo );
-
- n = pubkey_get_nskey( req_sk->pubkey_algo );
- for(i=0; i < n; i++ ) {
- /* Note: because v4 protected keys have nothing in the
- * mpis except for the first one, we skip all NULL MPIs.
- * This might not be always correct in cases where the both
- * keys do not match in their secret parts but we can ignore that
- * because the need for this function is quite ugly. */
- if( req_sk->skey[1] && sk->skey[i]
- && mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
- return -1;
- }
- return 0;
-}
-
-static int
-cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
-{
- int n, i;
-
- assert( req_pk->pubkey_algo == pk->pubkey_algo );
-
- n = pubkey_get_npkey( req_pk->pubkey_algo );
- for(i=0; i < n; i++ ) {
- if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] ) )
- return -1;
- }
- return 0;
-}
-
-/****************
- * search one keyring, return 0 if found, -1 if not found or an errorcode.
- */
-static int
-keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
-{
- 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);
- kbpos->rt = rt_RING;
- kbpos->valid = 0;
-
- #if HAVE_DOSISH_SYSTEM || 1
- assert(!iobuf);
- iobuf = iobuf_open( fname );
- if( !iobuf ) {
- log_error("%s: can't open keyring file\n", fname);
- rc = GPGERR_KEYRING_OPEN;
- goto leave;
- }
- #else
- if( iobuf_seek( iobuf, 0 ) ) {
- log_error("can't rewind keyring file\n");
- rc = GPGERR_KEYRING_OPEN;
- goto leave;
- }
- #endif
-
- 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( !rc ) {
- kbpos->offset = offset;
- kbpos->valid = 1;
- }
-
- leave:
- free_packet(&pkt);
- set_packet_list_mode(save_mode);
- #if HAVE_DOSISH_SYSTEM || 1
- iobuf_close(iobuf);
- #endif
- return rc;
-}
-
-
-static int
-keyring_read( KBPOS *kbpos, KBNODE *ret_root )
-{
- PACKET *pkt;
- int rc;
- RESTBL *rentry;
- KBNODE root = NULL;
- IOBUF a;
- int in_cert = 0;
-
- if( !(rentry=check_pos(kbpos)) )
- return GPGERR_GENERAL;
-
- a = iobuf_open( rentry->fname );
- if( !a ) {
- log_error("can't open `%s'\n", rentry->fname );
- return GPGERR_OPEN_FILE;
- }
-
- if( !kbpos->valid )
- log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
- if( iobuf_seek( a, kbpos->offset ) ) {
- log_error("can't seek to %lu\n", kbpos->offset);
- iobuf_close(a);
- return GPGERR_KEYRING_OPEN;
- }
-
- pkt = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- kbpos->count=0;
- while( (rc=parse_packet(a, pkt)) != -1 ) {
- if( rc ) { /* ignore errors */
- if( rc != GPGERR_UNKNOWN_PACKET ) {
- log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
- rc = GPGERR_INV_KEYRING;
- goto ready;
- }
- kbpos->count++;
- free_packet( pkt );
- init_packet( pkt );
- continue;
- }
- /* make a linked list of all packets */
- switch( pkt->pkttype ) {
- case PKT_COMPRESSED:
- log_error("skipped compressed packet in keyring\n" );
- free_packet(pkt);
- init_packet(pkt);
- break;
-
- 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 = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- break;
- }
- }
- ready:
- kbpos->valid = 0;
- if( rc == -1 && root )
- rc = 0;
-
- if( rc )
- release_kbnode( root );
- else
- *ret_root = root;
- free_packet( pkt );
- gcry_free( pkt );
- iobuf_close(a);
- return rc;
-}
-
-
-static int
keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
+ ulong offset, first_offset=0;
if( !(rentry=check_pos(kbpos)) )
return GPGERR_GENERAL;
if( kbpos->pkt ) {
root = new_kbnode( kbpos->pkt );
+ first_offset = kbpos->save_offset;
kbpos->pkt = NULL;
}
+ kbpos->valid = 0;
pkt = gcry_xmalloc( sizeof *pkt );
init_packet(pkt);
- while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
+ while( (rc=parse_packet(kbpos->fp, pkt, &offset )) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != GPGERR_UNKNOWN_PACKET ) {
- log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+ log_error("keyring_enum: read error: %s\n", gpg_errstr(rc) );
rc = GPGERR_INV_KEYRING;
goto ready;
}
@@ -1333,12 +709,14 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
- if( root ) { /* store this packet */
+ if( root ) { /* save this packet */
kbpos->pkt = pkt;
+ kbpos->save_offset = offset;
pkt = NULL;
goto ready;
}
root = new_kbnode( pkt );
+ first_offset = offset;
pkt = gcry_xmalloc( sizeof *pkt );
init_packet(pkt);
break;
@@ -1368,8 +746,13 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
if( rc )
release_kbnode( root );
- else
+ else {
+ if ( root ) {
+ kbpos->offset = first_offset;
+ kbpos->valid = 1;
+ }
*ret_root = root;
+ }
free_packet( pkt );
gcry_free( pkt );
@@ -1391,11 +774,11 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
int rc=0;
char *bakfname = NULL;
char *tmpfname = NULL;
+#warning We need to lock the keyring while we are editing it.
+ /* rethink this whole module */
if( !(rentry = check_pos( kbpos )) )
return GPGERR_GENERAL;
- if( kbpos->fp )
- BUG(); /* not allowed with such a handle */
if( opt.dry_run )
return 0;
@@ -1403,6 +786,13 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
lock_rentry( rentry );
/* open the source file */
+ if( kbpos->fp ) {
+ /* BUG(); not allowed with such a handle */
+ log_debug("keyring_copy: closing fp %p\n", kbpos->fp );
+ iobuf_close (kbpos->fp);
+ kbpos->fp = NULL;
+ kbpos->valid = 0;
+ }
fp = iobuf_open( rentry->fname );
if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
KBNODE kbctx, node;
@@ -1612,159 +1002,6 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
********** Functions which operate on KBX files ****************
****************************************************************/
-/****************
- * search a KBX file return 0 if found, -1 if not found or an errorcode.
- */
-static int
-do_kbxf_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
-{
- 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);
- kbpos->rt = rt_RING;
- kbpos->valid = 0;
-
- #if HAVE_DOSISH_SYSTEM || 1
- assert(!iobuf);
- iobuf = iobuf_open( fname );
- if( !iobuf ) {
- log_error("%s: can't open keyring file\n", fname);
- rc = GPGERR_KEYRING_OPEN;
- goto leave;
- }
- #else
- if( iobuf_seek( iobuf, 0 ) ) {
- log_error("can't rewind keyring file\n");
- rc = GPGERR_KEYRING_OPEN;
- goto leave;
- }
- #endif
-
- 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( !rc ) {
- kbpos->offset = offset;
- kbpos->valid = 1;
- }
-
- leave:
- free_packet(&pkt);
- set_packet_list_mode(save_mode);
- #if HAVE_DOSISH_SYSTEM || 1
- iobuf_close(iobuf);
- #endif
- return rc;
-}
-
-
-static int
-do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root )
-{
- PACKET *pkt;
- int rc;
- RESTBL *rentry;
- KBNODE root = NULL;
- IOBUF a;
- int in_cert = 0;
-
- if( !(rentry=check_pos(kbpos)) )
- return GPGERR_GENERAL;
-
- a = iobuf_open( rentry->fname );
- if( !a ) {
- log_error("can't open `%s'\n", rentry->fname );
- return GPGERR_OPEN_FILE;
- }
-
- if( !kbpos->valid )
- log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
- if( iobuf_seek( a, kbpos->offset ) ) {
- log_error("can't seek to %lu\n", kbpos->offset);
- iobuf_close(a);
- return GPGERR_KEYRING_OPEN;
- }
-
- pkt = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- kbpos->count=0;
- while( (rc=parse_packet(a, pkt)) != -1 ) {
- if( rc ) { /* ignore errors */
- if( rc != GPGERR_UNKNOWN_PACKET ) {
- log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
- rc = GPGERR_INV_KEYRING;
- goto ready;
- }
- kbpos->count++;
- free_packet( pkt );
- init_packet( pkt );
- continue;
- }
- /* make a linked list of all packets */
- switch( pkt->pkttype ) {
- case PKT_COMPRESSED:
- log_error("skipped compressed packet in keyring\n" );
- free_packet(pkt);
- init_packet(pkt);
- break;
-
- 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 = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- break;
- }
- }
- ready:
- kbpos->valid = 0;
- if( rc == -1 && root )
- rc = 0;
-
- if( rc )
- release_kbnode( root );
- else
- *ret_root = root;
- free_packet( pkt );
- gcry_free( pkt );
- iobuf_close(a);
- return rc;
-}
-
-
static int
do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
{
@@ -1783,10 +1020,10 @@ do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
pkt = gcry_xmalloc( sizeof *pkt );
init_packet(pkt);
- while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
+ while( (rc=parse_packet(kbpos->fp, pkt, NULL)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != GPGERR_UNKNOWN_PACKET ) {
- log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+ log_error("do_kbxf_enum: read error: %s\n", gpg_errstr(rc) );
rc = GPGERR_INV_KEYRING;
goto ready;
}
@@ -2079,300 +1316,5 @@ do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root )
}
-
-#ifdef HAVE_LIBGDBM
-/****************************************************************
- ********** 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 GPGERR_GENERAL;
-
- if( opt.dry_run )
- return 0;
-
- /* 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, gpg_errstr(rc) );
- rc = GPGERR_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 == 1 && !update )
- rc = gdbm_store( rentry->dbf, key, content, GDBM_REPLACE );
-
- if( rc ) {
- log_error("%s: gdbm_store failed: %s\n", rentry->fname,
- rc == 1 ? "already stored"
- : gdbm_strerror(gdbm_errno) );
- rc = GPGERR_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_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 gcry_free() here */
- return GPGERR_INV_KEYRING;
- }
- if( *content.dptr != 2 ) {
- log_error("gdbm_fetch returned unexpected type %d\n",
- *(byte*)content.dptr );
- free( content.dptr ); /* can't use gcry_free() here */
- return GPGERR_INV_KEYRING;
- }
- if( content.dsize < 21 ) {
- log_error("gdbm_fetch did not return a complete fingerprint\n" );
- free( content.dptr ); /* can't use gcry_free() here */
- return GPGERR_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 gcry_free() here */
- return rc;
-}
-
-
-
-static int
-do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
-{
- PACKET *pkt;
- int rc;
- RESTBL *rentry;
- KBNODE root = NULL;
- IOBUF a;
- datum key, content;
-
- if( !(rentry=check_pos(kbpos)) )
- return GPGERR_GENERAL;
-
- 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 GPGERR_INV_KEYRING;
- }
- if( content.dsize < 2 ) {
- log_error("gdbm_fetch did not return enough data\n" );
- free( content.dptr ); /* can't use gcry_free() here */
- return GPGERR_INV_KEYRING;
- }
- if( *content.dptr != 1 ) {
- log_error("gdbm_fetch returned unexpected type %d\n",
- *(byte*)content.dptr );
- free( content.dptr ); /* can't use gcry_free() here */
- return GPGERR_INV_KEYRING;
- }
-
- a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 );
- free( content.dptr ); /* can't use gcry_free() here */
-
- pkt = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- kbpos->count=0;
- while( (rc=parse_packet(a, pkt)) != -1 ) {
- if( rc ) { /* ignore errors */
- if( rc != GPGERR_UNKNOWN_PACKET ) {
- log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
- rc = GPGERR_INV_KEYRING;
- break;
- }
- kbpos->count++;
- free_packet( pkt );
- init_packet( pkt );
- continue;
- }
- /* make a linked list of all packets */
- kbpos->count++;
- if( !root )
- root = new_kbnode( pkt );
- else
- add_kbnode( root, new_kbnode( pkt ) );
- pkt = gcry_xmalloc( sizeof *pkt );
- init_packet(pkt);
- }
- if( rc == -1 && root )
- rc = 0;
- if( rc )
- release_kbnode( root );
- else
- *ret_root = root;
- free_packet( pkt );
- gcry_free( pkt );
- iobuf_close(a);
- return rc;
-}
-
-
-/****************
- * Enum over keyblok data
- */
-static int
-do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root )
-{
- RESTBL *rentry;
- datum key, helpkey;
-
- if( !(rentry=check_pos(kbpos)) )
- return GPGERR_GENERAL;
-
- if( !kbpos->offset ) {
- kbpos->offset = 1;
- key = gdbm_firstkey( rentry->dbf );
- }
- else {
- helpkey.dptr = kbpos->keybuf;
- helpkey.dsize= 21;
- key = gdbm_nextkey( rentry->dbf, helpkey );
- }
- while( key.dptr && (!key.dsize || *key.dptr != 1) ) {
- helpkey = key;
- key = gdbm_nextkey( rentry->dbf, helpkey );
- free( helpkey.dptr ); /* free and not gcry_free() ! */
- }
- if( !key.dptr )
- return -1; /* eof */
-
- if( key.dsize < 21 ) {
- free( key.dptr ); /* free and not gcry_free() ! */
- log_error("do_gdm_enum: key is too short\n" );
- return GPGERR_INV_KEYRING;
- }
- memcpy( kbpos->keybuf, key.dptr, 21 );
- free( key.dptr ); /* free and not gcry_free() ! */
- return do_gdbm_read( kbpos, ret_root );
-}
-#endif /*HAVE_LIBGDBM*/