aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/getkey.c')
-rw-r--r--g10/getkey.c705
1 files changed, 202 insertions, 503 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 8293fc673..5b013efa4 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -34,7 +34,6 @@
#include "trustdb.h"
#include "i18n.h"
-
#define MAX_UNK_CACHE_ENTRIES 1000 /* we use a linked list - so I guess
* this is a reasonable limit */
#define MAX_PK_CACHE_ENTRIES 200
@@ -45,60 +44,6 @@
#endif
-/* A map of the all characters valid used for word_match()
- * Valid characters are in in this table converted to uppercase.
- * because the upper 128 bytes have special meaning, we assume
- * that they are all valid.
- * Note: We must use numerical values here in case that this program
- * will be converted to those little blue HAL9000s with their strange
- * EBCDIC character set (user ids are UTF-8).
- * wk 2000-04-13: Hmmm, does this really make sense, given the fact that
- * we can run gpg now on a S/390 running GNU/Linux, where the code
- * translation is done by the device drivers?
- */
-static const byte word_match_chars[256] = {
- /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- /* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 40 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- /* 58 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 60 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 68 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- /* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
- /* 78 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- /* 88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
- /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
- /* 98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
- /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- /* a8 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
- /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- /* b8 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- /* c8 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
- /* d8 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
- /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
- /* e8 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
- /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- /* f8 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-typedef struct {
- int mode;
- u32 keyid[2];
- byte fprint[20];
- char *namebuf;
- const char *name;
-} getkey_item_t;
-
struct getkey_ctx_s {
int exact;
KBNODE keyblock;
@@ -107,10 +52,10 @@ struct getkey_ctx_s {
int last_rc;
int req_usage;
int req_algo;
- ulong count;
+ KEYDB_HANDLE kr_handle;
int not_allocated;
int nitems;
- getkey_item_t items[1];
+ KEYDB_SEARCH_DESC items[1];
};
#if 0
@@ -157,11 +102,8 @@ typedef struct user_id_db {
static user_id_db_t user_id_db;
static int uid_cache_entries; /* number of entries in uid cache */
-
-
-static char* prepare_word_match( const byte *name );
-static int lookup( GETKEY_CTX ctx, KBNODE *ret_kb, int secmode );
static void merge_selfsigs( KBNODE keyblock );
+static int lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode );
#if 0
@@ -426,10 +368,11 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
- ctx.items[0].mode = 11;
- ctx.items[0].keyid[0] = keyid[0];
- ctx.items[0].keyid[1] = keyid[1];
+ ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
+ ctx.items[0].u.kid[0] = keyid[0];
+ ctx.items[0].u.kid[1] = keyid[1];
ctx.req_algo = pk->req_algo;
ctx.req_usage = pk->req_usage;
rc = lookup( &ctx, &kb, 0 );
@@ -480,12 +423,13 @@ get_pubkeyblock( u32 *keyid )
KBNODE keyblock = NULL;
memset( &ctx, 0, sizeof ctx );
- /* co need to set exact here because we want the entire block */
+ /* no need to set exact here because we want the entire block */
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
- ctx.items[0].mode = 11;
- ctx.items[0].keyid[0] = keyid[0];
- ctx.items[0].keyid[1] = keyid[1];
+ ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
+ ctx.items[0].u.kid[0] = keyid[0];
+ ctx.items[0].u.kid[1] = keyid[1];
rc = lookup( &ctx, &keyblock, 0 );
get_pubkey_end( &ctx );
@@ -508,10 +452,11 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (1);
ctx.nitems = 1;
- ctx.items[0].mode = 11;
- ctx.items[0].keyid[0] = keyid[0];
- ctx.items[0].keyid[1] = keyid[1];
+ ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
+ ctx.items[0].u.kid[0] = keyid[0];
+ ctx.items[0].u.kid[1] = keyid[1];
ctx.req_algo = sk->req_algo;
ctx.req_usage = sk->req_usage;
rc = lookup( &ctx, &kb, 1 );
@@ -542,8 +487,13 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
int
seckey_available( u32 *keyid )
{
- KBPOS dummy_kbpos;
- return find_secret_keyblock_direct (&dummy_kbpos, keyid)? G10ERR_NO_SECKEY:0;
+ int rc;
+ KEYDB_HANDLE hd = keydb_new (1);
+ rc = keydb_search_kid (hd, keyid);
+ if ( rc == -1 )
+ rc = G10ERR_NO_SECKEY;
+ keydb_release (hd);
+ return rc;
}
@@ -638,36 +588,36 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
return 0;
case '.': /* an email address, compare from end */
- mode = 5;
+ mode = KEYDB_SEARCH_MODE_MAILEND;
s++;
break;
case '<': /* an email address */
- mode = 3;
+ mode = KEYDB_SEARCH_MODE_MAIL;
break;
case '@': /* part of an email address */
- mode = 4;
+ mode = KEYDB_SEARCH_MODE_MAILSUB;
s++;
break;
case '=': /* exact compare */
- mode = 1;
+ mode = KEYDB_SEARCH_MODE_EXACT;
s++;
break;
case '*': /* case insensitive substring search */
- mode = 2;
+ mode = KEYDB_SEARCH_MODE_SUBSTR;
s++;
break;
case '+': /* compare individual words */
- mode = 6;
+ mode = KEYDB_SEARCH_MODE_WORDS;
s++;
break;
case '#': /* local user id */
- mode = 12;
+ mode = KEYDB_SEARCH_MODE_TDBIDX;
s++;
if (keyid) {
if (keyid_from_lid(strtoul(s, NULL, 10), keyid))
@@ -696,7 +646,7 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
fprint[i]= 0;
}
s = se + 1;
- mode = 21;
+ mode = KEYDB_SEARCH_MODE_FPR;
}
break;
@@ -732,7 +682,7 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
keyid[0] = 0;
keyid[1] = strtoul( s, NULL, 16 );
}
- mode = 10;
+ mode = KEYDB_SEARCH_MODE_SHORT_KID;
}
else if (hexlength == 16
|| (!hexprefix && hexlength == 17 && *s == '0')) {
@@ -743,7 +693,7 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
mem2str(buf, s, 9 );
keyid[0] = strtoul( buf, NULL, 16 );
keyid[1] = strtoul( s+8, NULL, 16 );
- mode = 11;
+ mode = KEYDB_SEARCH_MODE_LONG_KID;
}
else if (hexlength == 32 || (!hexprefix && hexlength == 33
&& *s == '0')) {
@@ -752,7 +702,7 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
if (hexlength == 33)
s++;
if (fprint) {
- memset(fprint+16, 4, 0);
+ memset(fprint+16, 0, 4);
for (i=0; i < 16; i++, s+=2) {
int c = hextobyte(s);
if (c == -1)
@@ -760,7 +710,7 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
fprint[i] = c;
}
}
- mode = 16;
+ mode = KEYDB_SEARCH_MODE_FPR16;
}
else if (hexlength == 40 || (!hexprefix && hexlength == 41
&& *s == '0')) {
@@ -776,14 +726,14 @@ classify_user_id2( const char *name, u32 *keyid, byte *fprint,
fprint[i] = c;
}
}
- mode = 20;
+ mode = KEYDB_SEARCH_MODE_FPR20;
}
else {
if (hexprefix) /* This was a hex number with a prefix */
return 0; /* and a wrong length */
*force_exact = 0;
- mode = 2; /* Default is case insensitive substring search */
+ mode = KEYDB_SEARCH_MODE_SUBSTR; /* default mode */
}
}
@@ -815,7 +765,7 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
static int
key_byname( GETKEY_CTX *retctx, STRLIST namelist,
PKT_public_key *pk, PKT_secret_key *sk, int secmode,
- KBNODE *ret_kb )
+ KBNODE *ret_kb, KEYDB_HANDLE *ret_kdbhd )
{
int rc = 0;
int n;
@@ -824,24 +774,27 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
KBNODE help_kb = NULL;
int exact;
- if( retctx ) /* reset the returned context in case of error */
+ if( retctx ) {/* reset the returned context in case of error */
+ assert (!ret_kdbhd); /* not allowed because the handle is
+ stored in the context */
*retctx = NULL;
+ }
+ if (ret_kdbhd)
+ *ret_kdbhd = NULL;
/* build the search context */
- /* Performance hint: Use a static buffer if there is only one name */
- /* and we don't have mode 6 */
for(n=0, r=namelist; r; r = r->next )
n++;
- ctx = m_alloc_clear( sizeof *ctx + (n-1)*sizeof ctx->items );
+ ctx = m_alloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items );
ctx->nitems = n;
for(n=0, r=namelist; r; r = r->next, n++ ) {
int mode = classify_user_id2 ( r->d,
- ctx->items[n].keyid,
- ctx->items[n].fprint,
- &ctx->items[n].name,
+ ctx->items[n].u.kid,
+ ctx->items[n].u.fpr,
+ &ctx->items[n].u.name,
NULL, &exact );
-
+
if ( exact )
ctx->exact = 1;
ctx->items[n].mode = mode;
@@ -849,14 +802,9 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
m_free( ctx );
return G10ERR_INV_USER_ID;
}
- if( ctx->items[n].mode == 6 ) {
- ctx->items[n].namebuf = prepare_word_match(ctx->items[n].name);
- ctx->items[n].name = ctx->items[n].namebuf;
- }
}
-
-
+ ctx->kr_handle = keydb_new (secmode);
if ( !ret_kb )
ret_kb = &help_kb;
@@ -883,29 +831,34 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
release_kbnode ( help_kb );
- if( retctx ) /* caller wants the context */
+ if (retctx) /* caller wants the context */
*retctx = ctx;
else {
- /* Hmmm, why not get_pubkey-end here?? */
- enum_keyblocks( 2, &ctx->kbpos, NULL );
- memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
- for(n=0; n < ctx->nitems; n++ )
- m_free( ctx->items[n].namebuf );
- m_free( ctx );
+ if (ret_kdbhd) {
+ *ret_kdbhd = ctx->kr_handle;
+ ctx->kr_handle = NULL;
+ }
+ get_pubkey_end (ctx);
}
return rc;
}
+/*
+ * Find a public key from NAME and returh the keyblock or the key.
+ * If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is
+ * returned and the caller is responsible for closing it.
+ */
int
-get_pubkey_byname( GETKEY_CTX *retctx, PKT_public_key *pk,
- const char *name, KBNODE *ret_keyblock )
+get_pubkey_byname (PKT_public_key *pk,
+ const char *name, KBNODE *ret_keyblock,
+ KEYDB_HANDLE *ret_kdbhd )
{
int rc;
STRLIST namelist = NULL;
add_to_strlist( &namelist, name );
- rc = key_byname( retctx, namelist, pk, NULL, 0, ret_keyblock );
+ rc = key_byname( NULL, namelist, pk, NULL, 0, ret_keyblock, ret_kdbhd);
free_strlist( namelist );
return rc;
}
@@ -914,7 +867,7 @@ int
get_pubkey_bynames( GETKEY_CTX *retctx, PKT_public_key *pk,
STRLIST names, KBNODE *ret_keyblock )
{
- return key_byname( retctx, names, pk, NULL, 0, ret_keyblock );
+ return key_byname( retctx, names, pk, NULL, 0, ret_keyblock, NULL);
}
int
@@ -934,12 +887,8 @@ void
get_pubkey_end( GETKEY_CTX ctx )
{
if( ctx ) {
- int n;
-
- enum_keyblocks( 2, &ctx->kbpos, NULL );
memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
- for(n=0; n < ctx->nitems; n++ )
- m_free( ctx->items[n].namebuf );
+ keydb_release (ctx->kr_handle);
if( !ctx->not_allocated )
m_free( ctx );
}
@@ -967,9 +916,10 @@ get_pubkey_byfprint( PKT_public_key *pk,
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1 ;
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
- memcpy( ctx.items[0].fprint, fprint, fprint_len );
+ memcpy( ctx.items[0].u.fpr, fprint, fprint_len );
rc = lookup( &ctx, &kb, 0 );
if (!rc && pk )
pk_from_block ( &ctx, pk, kb );
@@ -996,9 +946,11 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
- ctx.items[0].mode = fprint_len;
- memcpy( ctx.items[0].fprint, fprint, fprint_len );
+ ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16
+ : KEYDB_SEARCH_MODE_FPR20;
+ memcpy( ctx.items[0].u.fpr, fprint, fprint_len );
rc = lookup( &ctx, ret_keyblock, 0 );
get_pubkey_end( &ctx );
}
@@ -1025,10 +977,11 @@ get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid )
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1;
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (0);
ctx.nitems = 1;
- ctx.items[0].mode = 12;
- ctx.items[0].keyid[0] = kid[0];
- ctx.items[0].keyid[1] = kid[1];
+ ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
+ ctx.items[0].u.kid[0] = kid[0];
+ ctx.items[0].u.kid[1] = kid[1];
rc = lookup( &ctx, ret_keyblock, 0 );
get_pubkey_end( &ctx );
@@ -1053,7 +1006,7 @@ get_seckey_byname2( GETKEY_CTX *retctx,
if( !name && opt.def_secret_key && *opt.def_secret_key ) {
add_to_strlist( &namelist, opt.def_secret_key );
- rc = key_byname( retctx, namelist, NULL, sk, 1, retblock );
+ rc = key_byname( retctx, namelist, NULL, sk, 1, retblock, NULL );
}
else if( !name ) { /* use the first one as default key */
struct getkey_ctx_s ctx;
@@ -1063,8 +1016,9 @@ get_seckey_byname2( GETKEY_CTX *retctx,
assert (!retblock);
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
+ ctx.kr_handle = keydb_new (1);
ctx.nitems = 1;
- ctx.items[0].mode = 15;
+ ctx.items[0].mode = KEYDB_SEARCH_MODE_FIRST;
rc = lookup( &ctx, &kb, 1 );
if (!rc && sk )
sk_from_block ( &ctx, sk, kb );
@@ -1073,7 +1027,7 @@ get_seckey_byname2( GETKEY_CTX *retctx,
}
else {
add_to_strlist( &namelist, name );
- rc = key_byname( retctx, namelist, NULL, sk, 1, retblock );
+ rc = key_byname( retctx, namelist, NULL, sk, 1, retblock, NULL );
}
free_strlist( namelist );
@@ -1095,7 +1049,7 @@ int
get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk,
STRLIST names, KBNODE *ret_keyblock )
{
- return key_byname( retctx, names, NULL, sk, 1, ret_keyblock );
+ return key_byname( retctx, names, NULL, sk, 1, ret_keyblock, NULL );
}
@@ -1120,150 +1074,6 @@ get_seckey_end( GETKEY_CTX ctx )
-/*******************************************************
- ************** compare functions **********************
- *******************************************************/
-
-/****************
- * Do a word match (original user id starts with a '+').
- * The pattern is already tokenized to a more suitable format:
- * There are only the real words in it delimited by one space
- * and all converted to uppercase.
- *
- * Returns: 0 if all words match.
- *
- * Note: This algorithm is a straightforward one and not very
- * fast. It works for UTF-8 strings. The uidlen should
- * be removed but due to the fact that old versions of
- * pgp don't use UTF-8 we still use the length; this should
- * be fixed in parse-packet (and replace \0 by some special
- * UTF-8 encoding)
- */
-static int
-word_match( const byte *uid, size_t uidlen, const byte *pattern )
-{
- size_t wlen, n;
- const byte *p;
- const byte *s;
-
- for( s=pattern; *s; ) {
- do {
- /* skip leading delimiters */
- while( uidlen && !word_match_chars[*uid] )
- uid++, uidlen--;
- /* get length of the word */
- n = uidlen; p = uid;
- while( n && word_match_chars[*p] )
- p++, n--;
- wlen = p - uid;
- /* and compare against the current word from pattern */
- for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) {
- if( word_match_chars[*p] != s[n] )
- break;
- }
- if( n == wlen && (s[n] == ' ' || !s[n]) )
- break; /* found */
- uid += wlen;
- uidlen -= wlen;
- } while( uidlen );
- if( !uidlen )
- return -1; /* not found */
-
- /* advance to next word in pattern */
- for(; *s != ' ' && *s ; s++ )
- ;
- if( *s )
- s++ ;
- }
- return 0; /* found */
-}
-
-/****************
- * prepare word word_match; that is parse the name and
- * build the pattern.
- * caller has to free the returned pattern
- */
-static char*
-prepare_word_match( const byte *name )
-{
- byte *pattern, *p;
- int c;
-
- /* the original length is always enough for the pattern */
- p = pattern = m_alloc(strlen(name)+1);
- do {
- /* skip leading delimiters */
- while( *name && !word_match_chars[*name] )
- name++;
- /* copy as long as we don't have a delimiter and convert
- * to uppercase.
- * fixme: how can we handle utf8 uppercasing */
- for( ; *name && (c=word_match_chars[*name]); name++ )
- *p++ = c;
- *p++ = ' '; /* append pattern delimiter */
- } while( *name );
- p[-1] = 0; /* replace last pattern delimiter by EOS */
-
- return pattern;
-}
-
-
-
-
-
-static int
-compare_name( const char *uid, size_t uidlen, const char *name, int mode )
-{
- int i;
- const char *s, *se;
-
- if( mode == 1 ) { /* exact match */
- for(i=0; name[i] && uidlen; i++, uidlen-- )
- if( uid[i] != name[i] )
- break;
- if( !uidlen && !name[i] )
- return 0; /* found */
- }
- else if( mode == 2 ) { /* case insensitive substring */
- if( ascii_memistr( uid, uidlen, name ) )
- return 0;
- }
- else if( mode >= 3 && mode <= 5 ) { /* look at the email address */
- for( i=0, s= uid; i < uidlen && *s != '<'; s++, i++ )
- ;
- if( i < uidlen ) {
- /* skip opening delim and one char and look for the closing one*/
- s++; i++;
- for( se=s+1, i++; i < uidlen && *se != '>'; se++, i++ )
- ;
- if( i < uidlen ) {
- i = se - s;
- if( mode == 3 ) { /* exact email address */
- if( strlen(name)-2 == i
- && !ascii_memcasecmp( s, name+1, i) )
- return 0;
- }
- else if( mode == 4 ) { /* email substring */
- if( ascii_memistr( s, i, name ) )
- return 0;
- }
- else { /* email from end */
- /* nyi */
- }
- }
- }
- }
- else if( mode == 6 )
- return word_match( uid, uidlen, name );
- else
- BUG();
-
- return -1; /* not found */
-}
-
-
-
-
/************************************************
************* Merging stuff ********************
************************************************/
@@ -1446,14 +1256,8 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
/* see whether we have the MDC feature */
uid->mdc_feature = 0;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n);
- if (!p)
- n=0;
- for (; n; n--, p++) {
- if (*p == 1) {
- uid->mdc_feature = 1;
- break;
- }
- }
+ if (p && n && (p[0] & 0x01))
+ uid->mdc_feature = 1;
}
@@ -1936,8 +1740,9 @@ merge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
/* This function checks that for every public subkey a corresponding
* secret subkey is avalable and deletes the public subkey otherwise.
- * We need this function becuase we can'tdelete it later when we
+ * We need this function because we can't delete it later when we
* actually merge the secret parts into the pubring.
+ & The function also plays some games with the node flags.
*/
static void
premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
@@ -1948,6 +1753,7 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
assert ( secblock->pkt->pkttype == PKT_SECRET_KEY );
for (pub=pubblock,last=NULL; pub; last = pub, pub = pub->next ) {
+ pub->flag &= ~3; /* reset bits 0 and 1 */
if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
KBNODE sec;
PKT_public_key *pk = pub->pkt->pkt.public_key;
@@ -1962,6 +1768,8 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
Fix the pubkey usage */
pk->pubkey_usage &= ~PUBKEY_USAGE_SIG;
}
+ /* transfer flag bits 0 and 1 to the pubblock */
+ pub->flag |= (sec->flag &3);
break;
}
}
@@ -1994,80 +1802,6 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
-/************************************************
- ************* Find stuff ***********************
- ************************************************/
-
-static PKT_user_id *
-find_by_name( KBNODE keyblock, const char *name, int mode )
-{
- KBNODE k;
-
- 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)) {
- return k->pkt->pkt.user_id;
- }
- }
-
- return NULL;
-}
-
-
-
-static KBNODE
-find_by_keyid( KBNODE keyblock, u32 *keyid, int mode )
-{
- KBNODE k;
-
- 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( aki[1] == keyid[1] && ( mode == 10 || aki[0] == keyid[0] ) ) {
- return k; /* found */
- }
- }
- }
- return NULL;
-}
-
-
-
-static KBNODE
-find_by_fpr( KBNODE keyblock, 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 ( mode == 21 ) {
- /* Unified fingerprint. The fingerprint is always 20 bytes*/
- while ( an < 20 )
- afp[an++] = 0;
- if ( !memcmp( afp, name, 20 ) )
- return k;
- }
- else {
- if( an == mode && !memcmp( afp, name, an) ) {
- return k;
- }
- }
- }
- }
- return NULL;
-}
-
-
-
-
/* See see whether the key fits
* our requirements and in case we do not
* request the primary key, we should select
@@ -2098,24 +1832,40 @@ find_by_fpr( KBNODE keyblock, const char *name, int mode )
*/
static int
-finish_lookup( GETKEY_CTX ctx, KBNODE foundk, PKT_user_id *foundu )
+finish_lookup (GETKEY_CTX ctx)
{
KBNODE keyblock = ctx->keyblock;
KBNODE k;
+ KBNODE foundk = NULL;
+ PKT_user_id *foundu = NULL;
#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC)
unsigned int req_usage = ( ctx->req_usage & USAGE_MASK );
u32 latest_date;
KBNODE latest_key;
u32 curtime = make_timestamp ();
- assert( !foundk || foundk->pkt->pkttype == PKT_PUBLIC_KEY
- || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY );
assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
ctx->found_key = NULL;
- if (!ctx->exact)
- foundk = NULL;
+ if (ctx->exact) {
+ for (k=keyblock; k; k = k->next) {
+ if ( (k->flag & 1) ) {
+ assert ( k->pkt->pkttype == PKT_PUBLIC_KEY
+ || k->pkt->pkttype == PKT_PUBLIC_SUBKEY );
+ foundk = k;
+ break;
+ }
+ }
+ }
+
+ for (k=keyblock; k; k = k->next) {
+ if ( (k->flag & 2) ) {
+ assert (k->pkt->pkttype == PKT_USER_ID);
+ foundu = k->pkt->pkt.user_id;
+ break;
+ }
+ }
if ( DBG_CACHE )
log_debug( "finish_lookup: checking key %08lX (%s)(req_usage=%x)\n",
@@ -2255,105 +2005,76 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk, PKT_user_id *foundu )
return 1; /* found */
}
-
+
static int
lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
{
int rc;
- int oldmode = set_packet_list_mode(0);
KBNODE secblock = NULL; /* helper */
int no_suitable_key = 0;
-
- if( !ctx->count ) /* first time */
- rc = enum_keyblocks( secmode? 5:0, &ctx->kbpos, NULL );
- else
- rc = 0;
- if( !rc ) {
- while( !(rc = enum_keyblocks( 1, &ctx->kbpos, &ctx->keyblock )) ) {
- int n;
- getkey_item_t *item;
-
- if ( secmode ) {
- /* find the correspondig public key and use this
- * this one for the selection process */
- u32 aki[2];
- KBNODE k = ctx->keyblock;
-
- if ( k->pkt->pkttype != PKT_SECRET_KEY )
- BUG();
- keyid_from_sk( k->pkt->pkt.secret_key, aki );
- k = get_pubkeyblock( aki );
- if( !k ) {
- if (!opt.quiet)
- log_info(_("key %08lX: secret key without public key "
- "- skipped\n"), (ulong)aki[1] );
- goto skip;
- }
- secblock = ctx->keyblock;
- ctx->keyblock = k;
- premerge_public_with_secret ( ctx->keyblock, secblock );
+
+ rc = 0;
+ while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems))) {
+ rc = keydb_get_keyblock (ctx->kr_handle, &ctx->keyblock);
+ if (rc) {
+ log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
+ rc = 0;
+ goto skip;
+ }
+
+ if ( secmode ) {
+ /* find the correspondig public key and use this
+ * this one for the selection process */
+ u32 aki[2];
+ KBNODE k = ctx->keyblock;
+
+ if (k->pkt->pkttype != PKT_SECRET_KEY)
+ BUG();
+
+ keyid_from_sk (k->pkt->pkt.secret_key, aki);
+ k = get_pubkeyblock (aki);
+ if( !k ) {
+ if (!opt.quiet)
+ log_info(_("key %08lX: secret key without public key "
+ "- skipped\n"), (ulong)aki[1] );
+ goto skip;
}
+ secblock = ctx->keyblock;
+ ctx->keyblock = k;
+ premerge_public_with_secret ( ctx->keyblock, secblock );
+ }
- /* loop over all the user ids we want to look for */
- item = ctx->items;
- for(n=0; n < ctx->nitems; n++, item++ ) {
- KBNODE k = NULL;
- int found = 0;
- PKT_user_id *found_uid = NULL;
-
- if( item->mode < 10 ) {
- found_uid = find_by_name( ctx->keyblock,
- item->name, item->mode );
- found = !!found_uid;
- }
- else if( item->mode >= 10 && item->mode <= 12 ) {
- k = find_by_keyid( ctx->keyblock,
- item->keyid, item->mode );
- found = !!k;
- }
- else if( item->mode == 15 ) {
- found = 1;
- }
- else if( item->mode == 16 || item->mode == 20
- || item->mode == 21 ) {
- k = find_by_fpr( ctx->keyblock,
- item->fprint, item->mode );
- found = !!k;
- }
- else
- BUG();
- if( found ) {
- /* this keyblock looks fine - do further investigation */
- merge_selfsigs ( ctx->keyblock );
- if ( finish_lookup( ctx, k, found_uid ) ) {
- no_suitable_key = 0;
- if ( secmode ) {
- merge_public_with_secret ( ctx->keyblock,
- secblock);
- release_kbnode (secblock);
- secblock = NULL;
- }
- goto found;
- }
- else
- no_suitable_key = 1;
- }
- }
- skip:
- /* release resources and try the next keyblock */
+ /* warning: node flag bits 0 and 1 should be preserved by
+ * merge_selfsigs. For secret keys, premerge did tranfer the
+ * keys to the keyblock */
+ merge_selfsigs ( ctx->keyblock );
+ if ( finish_lookup (ctx) ) {
+ no_suitable_key = 0;
if ( secmode ) {
- release_kbnode( secblock );
+ merge_public_with_secret ( ctx->keyblock,
+ secblock);
+ release_kbnode (secblock);
secblock = NULL;
}
- release_kbnode( ctx->keyblock );
- ctx->keyblock = NULL;
- }
- found:
- ;
+ goto found;
+ }
+ else
+ no_suitable_key = 1;
+
+ skip:
+ /* release resources and continue search */
+ if ( secmode ) {
+ release_kbnode( secblock );
+ secblock = NULL;
+ }
+ release_kbnode( ctx->keyblock );
+ ctx->keyblock = NULL;
}
+
+ found:
if( rc && rc != -1 )
- log_error("enum_keyblocks failed: %s\n", g10_errstr(rc));
+ log_error("enum_keyblocks_read failed: %s\n", g10_errstr(rc));
if( !rc ) {
*ret_keyblock = ctx->keyblock; /* return the keyblock */
@@ -2370,29 +2091,8 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
}
release_kbnode( ctx->keyblock );
ctx->keyblock = NULL;
- set_packet_list_mode(oldmode);
- #if 0
- if( opt.debug & DBG_MEMSTAT_VALUE ) {
- static int initialized;
-
- if( !initialized ) {
- initialized = 1;
- atexit( print_stats );
- }
-
- assert( ctx->mode < DIM(lkup_stats) );
- lkup_stats[ctx->mode].any = 1;
- if( !rc )
- lkup_stats[ctx->mode].okay_count++;
- else if ( rc == G10ERR_NO_PUBKEY || rc == G10ERR_NO_SECKEY )
- lkup_stats[ctx->mode].nokey_count++;
- else
- lkup_stats[ctx->mode].error_count++;
- }
- #endif
ctx->last_rc = rc;
- ctx->count++;
return rc;
}
@@ -2414,33 +2114,32 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
* to indicate EOF.
* 4) Always call this function a last time with SK set to NULL,
* so that can free it's context.
- *
- *
*/
int
enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
{
int rc=0;
- PACKET pkt;
- int save_mode;
struct {
int eof;
- int sequence;
- const char *name;
- IOBUF iobuf;
+ int first;
+ KEYDB_HANDLE hd;
+ KBNODE keyblock;
+ KBNODE node;
} *c = *context;
if( !c ) { /* make a new context */
c = m_alloc_clear( sizeof *c );
*context = c;
- c->sequence = 0;
- c->name = enum_keyblock_resources( &c->sequence, 1 );
+ c->hd = keydb_new (1);
+ c->first = 1;
+ c->keyblock = NULL;
+ c->node = NULL;
}
if( !sk ) { /* free the context */
- if( c->iobuf )
- iobuf_close(c->iobuf);
+ keydb_release (c->hd);
+ release_kbnode (c->keyblock);
m_free( c );
*context = NULL;
return 0;
@@ -2449,33 +2148,33 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
if( c->eof )
return -1;
- /* FIXME: This assumes a plain keyring file */
- for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) {
- if( !c->iobuf ) {
- if( !(c->iobuf = iobuf_open( c->name ) ) ) {
- log_error("enum_secret_keys: can't open `%s'\n", c->name );
- continue; /* try next file */
- }
- }
+ do {
+ /* get the next secret key from the current keyblock */
+ for (; c->node; c->node = c->node->next) {
+ if (c->node->pkt->pkttype == PKT_SECRET_KEY
+ || (with_subkeys
+ && c->node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
+ copy_secret_key (sk, c->node->pkt->pkt.secret_key );
+ c->node = c->node->next;
+ return 0; /* found */
+ }
+ }
+ release_kbnode (c->keyblock);
+ c->keyblock = c->node = NULL;
+
+ rc = c->first? keydb_search_first (c->hd) : keydb_search_next (c->hd);
+ c->first = 0;
+ if (rc) {
+ keydb_release (c->hd); c->hd = NULL;
+ c->eof = 1;
+ return -1; /* eof */
+ }
+
+ rc = keydb_get_keyblock (c->hd, &c->keyblock);
+ c->node = c->keyblock;
+ } while (!rc);
- save_mode = set_packet_list_mode(0);
- init_packet(&pkt);
- while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
- if( rc )
- ; /* e.g. unknown packet */
- else if( pkt.pkttype == PKT_SECRET_KEY
- || ( with_subkeys && pkt.pkttype == PKT_SECRET_SUBKEY ) ) {
- copy_secret_key( sk, pkt.pkt.secret_key );
- set_packet_list_mode(save_mode);
- return 0; /* found */
- }
- free_packet(&pkt);
- }
- set_packet_list_mode(save_mode);
- iobuf_close(c->iobuf); c->iobuf = NULL;
- }
- c->eof = 1;
- return -1;
+ return rc; /* error */
}