aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/getkey.c')
-rw-r--r--g10/getkey.c111
1 files changed, 100 insertions, 11 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index fb5f1bc3e..26fcda686 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1,5 +1,5 @@
/* getkey.c - Get a key from the database
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -45,7 +45,11 @@
* 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). */
+ * 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,
@@ -154,6 +158,7 @@ static int uid_cache_entries; /* number of entries in uid cache */
static char* prepare_word_match( const byte *name );
static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_kb );
static int lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_kb );
+static u32 subkeys_expiretime( KBNODE node, u32 *mainkid );
#if 0
@@ -696,6 +701,8 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
STRLIST r;
GETKEY_CTX ctx;
+ if( retctx ) /* reset the returned context in case of error */
+ *retctx = NULL;
assert( !pk ^ !sk );
/* build the search context */
@@ -1150,7 +1157,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode,
k = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !k )
BUG(); /* keyblock without primary key!!! */
- keyid_from_pk( knode->pkt->pkt.public_key, kid );
+ keyid_from_pk( k->pkt->pkt.public_key, kid );
}
else
keyid_from_pk( pk, kid );
@@ -1208,6 +1215,10 @@ merge_keys_and_selfsig( KBNODE keyblock )
pk = NULL; /* not needed for old keys */
else if( k->pkt->pkttype == PKT_PUBLIC_KEY )
keyid_from_pk( pk, kid );
+ else if( !pk->expiredate ) { /* and subkey */
+ /* insert the expiration date here */
+ pk->expiredate = subkeys_expiretime( k, kid );
+ }
sigdate = 0;
}
else if( k->pkt->pkttype == PKT_SECRET_KEY
@@ -1222,8 +1233,11 @@ merge_keys_and_selfsig( KBNODE keyblock )
else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x30 && sig->version > 3
+ && !(sig->sig_class == 0x18 || sig->sig_class == 0x28)
&& sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) {
/* okay this is a self-signature which can be used.
+ * This is not used for subkey binding signature, becuase this
+ * is done above.
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we must provide another
* way to handle this
@@ -1279,9 +1293,14 @@ find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name,
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
- rmd160_hash_buffer( namehash,
- k->pkt->pkt.user_id->name,
- k->pkt->pkt.user_id->len );
+ if( k->pkt->pkt.user_id->photo )
+ rmd160_hash_buffer( namehash,
+ k->pkt->pkt.user_id->photo,
+ k->pkt->pkt.user_id->photolen );
+ else
+ rmd160_hash_buffer( namehash,
+ k->pkt->pkt.user_id->name,
+ k->pkt->pkt.user_id->len );
*use_namehash = 1;
return kk;
}
@@ -1516,6 +1535,56 @@ find_by_fpr_sk( KBNODE keyblock, PKT_secret_key *sk,
}
+/****************
+ * Return the expiretime of a subkey.
+ */
+static u32
+subkeys_expiretime( KBNODE node, u32 *mainkid )
+{
+ KBNODE k;
+ PKT_signature *sig;
+ u32 expires = 0, sigdate = 0;
+
+ assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY );
+ for(k=node->next; k; k = k->next ) {
+ if( k->pkt->pkttype == PKT_SIGNATURE
+ && (sig=k->pkt->pkt.signature)->sig_class == 0x18
+ && sig->keyid[0] == mainkid[0]
+ && sig->keyid[1] == mainkid[1]
+ && sig->version > 3
+ && sig->timestamp > sigdate ) {
+ /* okay this is a key-binding which can be used.
+ * We use the latest self-signature.
+ * FIXME: We should only use this if the binding signature is valid
+ * but this is time consuming - we must provide another
+ * way to handle this
+ */
+ const byte *p;
+ u32 ed;
+
+ p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
+ ed = p? node->pkt->pkt.public_key->timestamp + buffer_to_u32(p):0;
+ sigdate = sig->timestamp;
+ expires = ed;
+ }
+ else if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+ break; /* stop at the next subkey */
+ }
+
+ return expires;
+}
+
+
+/****************
+ * Check whether the subkey has expired. Node must point to the subkey
+ */
+static int
+has_expired( KBNODE node, u32 *mainkid, u32 cur_time )
+{
+ u32 expires = subkeys_expiretime( node, mainkid );
+ return expires && expires <= cur_time;
+}
+
static void
finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
int use_namehash, int primary )
@@ -1534,6 +1603,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
+ u32 mainkid[2];
+ u32 cur_time = make_timestamp();
+
+ keyid_from_pk( keyblock->pkt->pkt.public_key, mainkid );
k = NULL;
/* kludge for pgp 5: which doesn't accept type 20:
@@ -1545,7 +1618,8 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
== PUBKEY_ALGO_ELGAMAL_E
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
- pk->pubkey_usage ) )
+ pk->pubkey_usage )
+ && !has_expired(k, mainkid, cur_time) )
break;
}
}
@@ -1555,7 +1629,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
- pk->pubkey_usage ) )
+ pk->pubkey_usage )
+ && ( pk->pubkey_usage != PUBKEY_USAGE_ENC
+ || !has_expired( k, mainkid, cur_time ) )
+ )
break;
}
}
@@ -1887,6 +1964,18 @@ get_user_id_string( u32 *keyid )
return p;
}
+
+char*
+get_user_id_string_native( u32 *keyid )
+{
+ char *p = get_user_id_string( keyid );
+ char *p2 = utf8_to_native( p, strlen(p) );
+
+ m_free(p);
+ return p2;
+}
+
+
char*
get_long_user_id_string( u32 *keyid )
{
@@ -1914,6 +2003,7 @@ get_user_id( u32 *keyid, size_t *rn )
user_id_db_t r;
char *p;
int pass=0;
+
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
@@ -1924,9 +2014,8 @@ get_user_id( u32 *keyid, size_t *rn )
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
- p = m_alloc( 19 );
- memcpy(p, "[User id not found]", 19 );
- *rn = 19;
+ p = m_strdup( _("[User id not found]") );
+ *rn = strlen(p);
return p;
}