aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/getkey.c162
1 files changed, 100 insertions, 62 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 886d53cc9..6e4c34592 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -33,27 +33,11 @@
#include "main.h"
#include "i18n.h"
-#define MAX_PK_CACHE_ENTRIES 500
+#define MAX_UNK_CACHE_ENTRIES 1000
+#define MAX_PK_CACHE_ENTRIES 50
+#define MAX_UID_CACHE_ENTRIES 50
-typedef struct keyid_list {
- struct keyid_list *next;
- u32 keyid[2];
-} *keyid_list_t;
-
-typedef struct user_id_db {
- struct user_id_db *next;
- u32 keyid[2];
- int len;
- char name[1];
-} *user_id_db_t;
-
-typedef struct pk_cache_entry {
- struct pk_cache_entry *next;
- u32 keyid[2];
- PKT_public_key *pk;
-} *pk_cache_entry_t;
-
typedef struct enum_seckey_context {
int eof;
STRLIST sl;
@@ -64,10 +48,39 @@ typedef struct enum_seckey_context {
static STRLIST keyrings;
static STRLIST secret_keyrings;
-static keyid_list_t unknown_keyids;
+#if MAX_UNK_CACHE_ENTRIES
+ typedef struct keyid_list {
+ struct keyid_list *next;
+ u32 keyid[2];
+ } *keyid_list_t;
+ static keyid_list_t unknown_keyids;
+ static int unk_cache_entries; /* number of entries in unknown keys cache */
+ static int unk_cache_disabled;
+#endif
+
+#if MAX_PK_CACHE_ENTRIES
+ typedef struct pk_cache_entry {
+ struct pk_cache_entry *next;
+ u32 keyid[2];
+ PKT_public_key *pk;
+ } *pk_cache_entry_t;
+ static pk_cache_entry_t pk_cache;
+ static int pk_cache_entries; /* number of entries in pk cache */
+ static int pk_cache_disabled;
+#endif
+
+#if MAX_UID_CACHE_ENTRIES < 5
+ #error we really need the userid cache
+#endif
+typedef struct user_id_db {
+ struct user_id_db *next;
+ u32 keyid[2];
+ int len;
+ char name[1];
+} *user_id_db_t;
static user_id_db_t user_id_db;
-static pk_cache_entry_t pk_cache;
-static int pk_cache_entries; /* number of entries in pk cache */
+static int uid_cache_entries; /* number of entries in uid cache */
+
static int lookup( PKT_public_key *pk,
@@ -166,9 +179,13 @@ add_secret_keyring( const char *name )
static void
cache_public_key( PKT_public_key *pk )
{
+ #if MAX_PK_CACHE_ENTRIES
pk_cache_entry_t ce;
u32 keyid[2];
+ if( pk_cache_disabled )
+ return;
+
if( is_ELGAMAL(pk->pubkey_algo)
|| pk->pubkey_algo == PUBKEY_ALGO_DSA
|| is_RSA(pk->pubkey_algo) ) {
@@ -184,24 +201,20 @@ cache_public_key( PKT_public_key *pk )
return;
}
- if( pk_cache_entries > MAX_PK_CACHE_ENTRIES ) {
- /* FIMXE: use another algorithm to free some cache slots */
- if( pk_cache_entries == MAX_PK_CACHE_ENTRIES ) {
- pk_cache_entries++;
- log_info("too many entries in pk cache - disabled\n");
- }
- ce = pk_cache;
- free_public_key( ce->pk );
- }
- else {
- pk_cache_entries++;
- ce = m_alloc( sizeof *ce );
- ce->next = pk_cache;
- pk_cache = ce;
+ if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) {
+ /* fixme: use another algorithm to free some cache slots */
+ pk_cache_disabled=1;
+ log_info("too many entries in pk cache - disabled\n");
+ return;
}
+ pk_cache_entries++;
+ ce = m_alloc( sizeof *ce );
+ ce->next = pk_cache;
+ pk_cache = ce;
ce->pk = copy_public_key( NULL, pk );
ce->keyid[0] = keyid[0];
ce->keyid[1] = keyid[1];
+ #endif
}
@@ -220,6 +233,13 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
return;
}
+ if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) {
+ /* fixme: use another algorithm to free some cache slots */
+ r = user_id_db;
+ user_id_db = r->next;
+ m_free(r);
+ uid_cache_entries--;
+ }
r = m_alloc( sizeof *r + uid->len-1 );
r->keyid[0] = keyid[0];
r->keyid[1] = keyid[1];
@@ -227,6 +247,7 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
memcpy(r->name, uid->name, r->len);
r->next = user_id_db;
user_id_db = r;
+ uid_cache_entries++;
}
@@ -239,23 +260,30 @@ cache_user_id( PKT_user_id *uid, u32 *keyid )
int
get_pubkey( PKT_public_key *pk, u32 *keyid )
{
- keyid_list_t kl;
int internal = 0;
int rc = 0;
- pk_cache_entry_t ce;
- /* let's see whether we checked the keyid already */
- for( kl = unknown_keyids; kl; kl = kl->next )
- if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
- return G10ERR_NO_PUBKEY; /* already checked and not found */
-
- /* Try to get it from our cache */
- for( ce = pk_cache; ce; ce = ce->next )
- if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
- if( pk )
- copy_public_key( pk, ce->pk );
- return 0;
+ #if MAX_UNK_CACHE_ENTRIES
+ { /* let's see whether we checked the keyid already */
+ keyid_list_t kl;
+ for( kl = unknown_keyids; kl; kl = kl->next )
+ if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
+ return G10ERR_NO_PUBKEY; /* already checked and not found */
+ }
+ #endif
+
+ #if MAX_PK_CACHE_ENTRIES
+ { /* Try to get it from the cache */
+ pk_cache_entry_t ce;
+ for( ce = pk_cache; ce; ce = ce->next ) {
+ if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
+ if( pk )
+ copy_public_key( pk, ce->pk );
+ return 0;
+ }
}
+ }
+ #endif
/* more init stuff */
if( !pk ) {
pk = m_alloc_clear( sizeof *pk );
@@ -268,12 +296,24 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
if( !rc )
goto leave;
+ #if MAX_UNK_CACHE_ENTRIES
/* not found: store it for future reference */
- kl = m_alloc( sizeof *kl );
- kl->keyid[0] = keyid[0];
- kl->keyid[1] = keyid[1];
- kl->next = unknown_keyids;
- unknown_keyids = kl;
+ if( unk_cache_disabled )
+ ;
+ else if( ++unk_cache_entries > MAX_UNK_CACHE_ENTRIES ) {
+ unk_cache_disabled = 1;
+ log_info("too many entries in unk cache - disabled\n");
+ }
+ else {
+ keyid_list_t kl;
+
+ kl = m_alloc( sizeof *kl );
+ kl->keyid[0] = keyid[0];
+ kl->keyid[1] = keyid[1];
+ kl->next = unknown_keyids;
+ unknown_keyids = kl;
+ }
+ #endif
rc = G10ERR_NO_PUBKEY;
leave:
@@ -829,9 +869,10 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
break;
}
else if( mode == 16 || mode == 20 ) {
+ byte afp[MAX_FINGERPRINT_LEN];
size_t an;
- byte *afp = fingerprint_from_pk(
- k->pkt->pkt.public_key, NULL, &an );
+
+ fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
if( DBG_CACHE ) {
u32 aki[2];
@@ -845,10 +886,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo) ) {
- m_free(afp);
break;
}
- m_free(afp);
}
else
BUG();
@@ -1008,16 +1047,15 @@ lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name,
}
else if( mode == 16 || mode == 20 ) {
size_t an;
- byte *afp = fingerprint_from_sk(
- k->pkt->pkt.secret_key, NULL, &an );
+ byte afp[MAX_FINGERPRINT_LEN];
+
+ fingerprint_from_sk(k->pkt->pkt.secret_key, afp, &an );
if( an == mode && !memcmp( afp, name, an)
&& ( !sk->pubkey_algo
|| sk->pubkey_algo
== k->pkt->pkt.secret_key->pubkey_algo) ) {
- m_free(afp);
break;
}
- m_free(afp);
}
else
BUG();