aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog28
-rw-r--r--g10/getkey.c127
-rw-r--r--g10/import.c2
-rw-r--r--g10/keyedit.c3
-rw-r--r--g10/keylist.c7
-rw-r--r--g10/mainproc.c3
-rw-r--r--g10/pkclist.c1
7 files changed, 122 insertions, 49 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 9c468a8e0..e21ec46e9 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,29 @@
+2001-03-03 Werner Koch <[email protected]>
+
+ * getkey.c: Introduced a new lookup context flag "exact" and used
+ it in all place where we once used primary.
+ (classify_user_id2): Replaced the old function and add an extra
+ argument to return whether an exact keyID has been requested.
+ (key_byname): Removed the unused ctx.primary flag
+ (get_seckey_byname2): Ditto.
+ (finish_lookup): Changed debugging output.
+
+2001-03-02 Werner Koch <[email protected]>
+
+ * keylist.c (list_one): Remove the merge key calls.
+
+2001-03-01 Werner Koch <[email protected]>
+
+ * getkey.c (finish_lookup): Don't use it if we no specific usage
+ has been requested.
+ (merge_selfsigs_main): fix UID only if we have an signature.
+ (lookup): Return UNU_PUBKEY etc. instead of NO_PUBKEY if we found
+ a key but the requested usage does not allow this key.
+ * import.c (import_one): Take UNU_PUBKEY into account.
+ * mainproc.c (list_node): Ditto.
+ * keylist.c (list_keyblock): Ditto.
+ * keyedit.c (print_and_check_one_sig): Ditto.
+
2001-02-09 Werner Koch <[email protected]>
* delkey.c (delete_key): Removed that silly assert which rendered
@@ -121,7 +147,7 @@
* g10.c: New option --allow-secret-key-import.
* import.c (import_keys,import_keys_stream): Honor this option.
(import): New arg allow_secret and pass that arg down to ...
- (import_secret_one): to this and print a warnign if secret key
+ (import_secret_one): to this and print a warning if secret key
importing is not allowed.
2000-12-05 Werner Koch <[email protected]>
diff --git a/g10/getkey.c b/g10/getkey.c
index 25bd9ba23..b58dbccac 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -97,8 +97,7 @@ typedef struct {
} getkey_item_t;
struct getkey_ctx_s {
- /* make an array or a linked list from dome fields */
- int primary;
+ int exact;
KBNODE keyblock;
KBPOS kbpos;
KBNODE found_key; /* pointer into some keyblock */
@@ -418,6 +417,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
{ struct getkey_ctx_s ctx;
KBNODE kb = NULL;
memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
@@ -473,6 +473,7 @@ get_pubkeyblock( u32 *keyid )
KBNODE keyblock = NULL;
memset( &ctx, 0, sizeof ctx );
+ /* co need to set exact here because we want the entire block */
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
@@ -498,6 +499,7 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
KBNODE kb = NULL;
memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
@@ -536,6 +538,7 @@ seckey_available( u32 *keyid )
KBNODE kb = NULL;
memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
@@ -620,15 +623,16 @@ hextobyte( const byte *s )
* is not case sensitive.
*/
-int
-classify_user_id( const char *name, u32 *keyid, byte *fprint,
- const char **retstr, size_t *retlen )
+static int
+classify_user_id2( const char *name, u32 *keyid, byte *fprint,
+ const char **retstr, size_t *retlen, int *force_exact )
{
const char * s;
int mode = 0;
int hexprefix = 0;
int hexlength;
-
+
+ *force_exact = 0;
/* skip leading spaces. FIXME: what is with leading spaces? */
for(s = name; *s && isspace(*s); s++ )
;
@@ -707,6 +711,10 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
}
hexlength = strspn(s, "0123456789abcdefABCDEF");
+ if (hexlength >= 8 && s[hexlength] =='!') {
+ *force_exact = 1;
+ hexlength++; /* just for the following check */
+ }
/* check if a hexadecimal number is terminated by EOS or blank */
if (hexlength && s[hexlength] && !isspace(s[hexlength])) {
@@ -716,6 +724,9 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
hexlength = 0; /* a hex number, but really were not. */
}
+ if (*force_exact)
+ hexlength--;
+
if (hexlength == 8
|| (!hexprefix && hexlength == 9 && *s == '0')){
/* short keyid */
@@ -775,6 +786,7 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
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 */
}
}
@@ -787,14 +799,20 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
return mode;
}
-
+int
+classify_user_id( const char *name, u32 *keyid, byte *fprint,
+ const char **retstr, size_t *retlen )
+{
+ int dummy;
+ return classify_user_id2 (name, keyid, fprint, retstr, retlen, &dummy);
+}
/****************
* Try to get the pubkey by the userid. This function looks for the
* first pubkey certificate which has the given name in a user_id.
* if pk/sk has the pubkey algo set, the function will only return
* a pubkey with that algo.
- * The caller must provide provide storage for either the pk or the sk.
+ * The caller must provide storage for either the pk or the sk.
* If ret_kb is not NULL the funtion will return the keyblock there.
*/
@@ -807,6 +825,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
STRLIST r;
GETKEY_CTX ctx;
KBNODE help_kb = NULL;
+ int exact;
if( retctx ) /* reset the returned context in case of error */
*retctx = NULL;
@@ -820,18 +839,14 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
ctx->nitems = n;
for(n=0, r=namelist; r; r = r->next, n++ ) {
- int mode = classify_user_id( r->d,
- ctx->items[n].keyid,
- ctx->items[n].fprint,
- &ctx->items[n].name,
- NULL );
-
- /* if we don't use one of the exact key specifications, we assume that
- * the primary key is requested */
- if ( mode != 10 && mode != 11
- && mode != 16 && mode == 20 && mode != 21 )
- ctx->primary = 1;
-
+ int mode = classify_user_id2 ( r->d,
+ ctx->items[n].keyid,
+ ctx->items[n].fprint,
+ &ctx->items[n].name,
+ NULL, &exact );
+
+ if ( exact )
+ ctx->exact = 1;
ctx->items[n].mode = mode;
if( !ctx->items[n].mode ) {
m_free( ctx );
@@ -951,6 +966,7 @@ get_pubkey_byfprint( PKT_public_key *pk,
KBNODE kb = NULL;
memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1 ;
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = fprint_len;
@@ -1008,6 +1024,7 @@ get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid )
if( keyid_from_lid( lid, kid ) )
kid[0] = kid[1] = 0;
memset( &ctx, 0, sizeof ctx );
+ ctx.exact = 1;
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 12;
@@ -1047,7 +1064,6 @@ get_seckey_byname2( GETKEY_CTX *retctx,
assert (!retblock);
memset( &ctx, 0, sizeof ctx );
ctx.not_allocated = 1;
- ctx.primary = 1;
ctx.nitems = 1;
ctx.items[0].mode = 15;
rc = lookup( &ctx, &kb, 1 );
@@ -1255,7 +1271,11 @@ compare_name( const char *uid, size_t uidlen, const char *name, int mode )
/****************
* merge all selfsignatures with the keys.
* FIXME: replace this at least for the public key parts
- * by merge_selfsigs
+ * by merge_selfsigs.
+ * It is still used in keyedit.c and
+ * at 2 or 3 other places - check whether it is really needed.
+ * It might be needed by the key edit and import stuff because
+ * the keylock is changed.
*/
void
merge_keys_and_selfsig( KBNODE keyblock )
@@ -1516,7 +1536,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
}
}
}
- if ( uidnode ) {
+ if ( uidnode && signode ) {
fixup_uidnode ( uidnode, signode );
pk->is_valid = 1;
}
@@ -1961,14 +1981,14 @@ find_by_fpr( KBNODE keyblock, const char *name, int mode )
/* See see whether the key fits
* our requirements and in case we do not
- * request a the primary key, we should select
+ * request the primary key, we should select
* a suitable subkey.
* FIXME: Check against PGP 7 whether we still need a kludge
* to favor type 16 keys over type 20 keys when type 20
* has not been explitely requested.
* Returns: True when a suitable key has been found.
*
- * We have to distinguish four cases:
+ * We have to distinguish four cases: FIXME!
* 1. No usage and no primary key requested
* Examples for this case are that we have a keyID to be used
* for decrytion or verification.
@@ -1980,7 +2000,12 @@ find_by_fpr( KBNODE keyblock, const char *name, int mode )
* 4. Usage but no primary key requested
* FIXME
* FIXME: Tell what is going to happen here and something about the rationale
+ * Note: We don't use this function if no specific usage is requested;
+ * This way the getkey functions can be used for plain key listings.
*
+ * CTX ist the keyblock we are investigating, if FOUNDK is not NULL this
+ * is the key we actually found by looking at the keyid or a fingerprint and
+ * may eitehr point to the primary or one of the subkeys.
*/
static int
@@ -1998,17 +2023,29 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
ctx->found_key = NULL;
-
+
+ if (!ctx->exact)
+ foundk = NULL;
+
if ( DBG_CACHE )
- log_debug( "finish_lookup: checking %s (req_usage=%x)\n",
- foundk? "one key":"all keys", req_usage);
+ log_debug( "finish_lookup: checking key %08lX (%s)(req_usage=%x)\n",
+ (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL),
+ foundk? "one":"all", req_usage);
+ if (!req_usage) {
+ latest_key = foundk? foundk:keyblock;
+ goto found;
+ }
+
+ if (!req_usage) {
+ ctx->found_key = foundk;
+ cache_user_id( keyblock );
+ return 1; /* found */
+ }
+
latest_date = 0;
latest_key = NULL;
- /* We do check the subkeys only if we either have requested a specific
- * usage or have not requested to get the primary key. */
- if ( (req_usage || !ctx->primary)
- && (!foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
+ if ( !foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
KBNODE nextk;
/* either start a loop or check just this one subkey */
for (k=foundk?foundk:keyblock; k; k = nextk ) {
@@ -2019,6 +2056,9 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
if ( foundk )
nextk = NULL; /* what a hack */
pk = k->pkt->pkt.public_key;
+ if (DBG_CACHE)
+ log_debug( "\tchecking subkey %08lX\n",
+ (ulong)keyid_from_pk( pk, NULL));
if ( !pk->is_valid ) {
if (DBG_CACHE)
log_debug( "\tsubkey not valid\n");
@@ -2035,8 +2075,7 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
continue;
}
- if ( req_usage &&
- !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) {
+ if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) {
if (DBG_CACHE)
log_debug( "\tusage does not match: want=%x have=%x\n",
req_usage, pk->pubkey_usage );
@@ -2044,8 +2083,7 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
}
if (DBG_CACHE)
- log_debug( "\tconsidering key %08lX\n",
- (ulong)keyid_from_pk( pk, NULL));
+ log_debug( "\tsubkey looks fine\n");
if ( pk->created > latest_date ) {
latest_date = pk->created;
latest_key = k;
@@ -2053,7 +2091,9 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
}
}
- if ( !latest_key ) {
+ /* Okay now try the primary key unless we have want an exact
+ * key ID match on a subkey */
+ if ( !latest_key && !(ctx->exact && foundk != keyblock) ) {
PKT_public_key *pk;
if (DBG_CACHE && !foundk )
log_debug( "\tno suitable subkeys found - trying primary\n");
@@ -2070,10 +2110,10 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
if (DBG_CACHE)
log_debug( "\tprimary key has expired\n");
}
- else if ( req_usage
- && !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) {
+ else if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) {
if (DBG_CACHE)
- log_debug( "\tusage does not match: want=%x have=%x\n",
+ log_debug( "\tprimary key usage does not match: "
+ "want=%x have=%x\n",
req_usage, pk->pubkey_usage );
}
else { /* okay */
@@ -2090,6 +2130,7 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
return 0;
}
+ found:
if (DBG_CACHE)
log_debug( "\tusing key %08lX\n",
(ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) );
@@ -2117,6 +2158,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
byte namehash[20];
int use_namehash=0;
KBNODE secblock = NULL; /* helper */
+ int no_suitable_key = 0;
if( !ctx->count ) /* first time */
rc = enum_keyblocks( secmode? 5:0, &ctx->kbpos, NULL );
@@ -2180,6 +2222,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
/* this keyblock looks fine - do further investigation */
merge_selfsigs ( ctx->keyblock );
if ( finish_lookup( ctx, k ) ) {
+ no_suitable_key = 0;
if ( secmode ) {
merge_public_with_secret ( ctx->keyblock,
secblock);
@@ -2188,6 +2231,8 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
}
goto found;
}
+ else
+ no_suitable_key = 1;
}
}
skip:
@@ -2209,6 +2254,8 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
*ret_keyblock = ctx->keyblock; /* return the keyblock */
ctx->keyblock = NULL;
}
+ else if (rc == -1 && no_suitable_key)
+ rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY;
else if( rc == -1 )
rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY;
diff --git a/g10/import.c b/g10/import.c
index dc24edf48..fe0512b94 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -414,7 +414,7 @@ import_one( const char *fname, KBNODE keyblock, int fast )
/* do we have this key already in one of our pubrings ? */
pk_orig = m_alloc_clear( sizeof *pk_orig );
rc = get_pubkey( pk_orig, keyid );
- if( rc && rc != G10ERR_NO_PUBKEY ) {
+ if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) {
log_error( _("key %08lX: public key not found: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
}
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 8faf141d5..3141bceb8 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -100,7 +100,7 @@ get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
if( rc )
log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
else
- merge_keys_and_selfsig( *keyblock );
+ merge_keys_and_selfsig( *keyblock );
return rc;
}
@@ -131,6 +131,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
++*inv_sigs;
break;
case G10ERR_NO_PUBKEY:
+ case G10ERR_UNU_PUBKEY:
node->flag = NODFLG_NOKEY;
sigrc = '?';
if( no_key )
diff --git a/g10/keylist.c b/g10/keylist.c
index 9408b2782..da7fdb0d2 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -91,7 +91,7 @@ list_all( int secret )
putchar('-');
putchar('\n');
}
- merge_keys_and_selfsig( keyblock );
+ merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock ); keyblock = NULL;
}
@@ -199,7 +199,6 @@ list_one( STRLIST names, int secret )
return;
}
do {
- merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, 1 );
release_kbnode( keyblock );
} while( !get_seckey_next( ctx, NULL, &keyblock ) );
@@ -213,7 +212,6 @@ list_one( STRLIST names, int secret )
return;
}
do {
- merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, 0 );
release_kbnode( keyblock );
} while( !get_pubkey_next( ctx, NULL, &keyblock ) );
@@ -480,7 +478,8 @@ list_keyblock( KBNODE keyblock, int secret )
switch( rc ) {
case 0: sigrc = '!'; break;
case G10ERR_BAD_SIGN: sigrc = '-'; break;
- case G10ERR_NO_PUBKEY: sigrc = '?'; break;
+ case G10ERR_NO_PUBKEY:
+ case G10ERR_UNU_PUBKEY: sigrc = '?'; break;
default: sigrc = '%'; break;
}
}
diff --git a/g10/mainproc.c b/g10/mainproc.c
index bb990a032..6a2d123ad 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -926,7 +926,8 @@ list_node( CTX c, KBNODE node )
switch( (rc2=do_check_sig( c, node, &is_selfsig )) ) {
case 0: sigrc = '!'; break;
case G10ERR_BAD_SIGN: sigrc = '-'; break;
- case G10ERR_NO_PUBKEY: sigrc = '?'; break;
+ case G10ERR_NO_PUBKEY:
+ case G10ERR_UNU_PUBKEY: sigrc = '?'; break;
default: sigrc = '%'; break;
}
}
diff --git a/g10/pkclist.c b/g10/pkclist.c
index a65e01cda..e66d105be 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -819,7 +819,6 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
}
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
-
/* Skip the actual key if the key is already present
* in the list */
if (key_present_in_pk_list(pk_list, pk) == 0) {