aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keydb.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keydb.c')
-rw-r--r--g10/keydb.c166
1 files changed, 112 insertions, 54 deletions
diff --git a/g10/keydb.c b/g10/keydb.c
index 6cd3cf93f..8fb6b115a 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -42,21 +42,26 @@ typedef enum {
KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING
} KeydbResourceType;
-#define MAX_KEYDB_RESOURCES 1
+#define MAX_KEYDB_RESOURCES 20
struct resource_item {
- KeydbResourceType type;
- union {
- KEYRING_HANDLE kr;
- } u;
+ KeydbResourceType type;
+ union {
+ KEYRING_HANDLE kr;
+ } u;
+ void *token;
+ int secret;
};
+static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
+static int used_resources;
struct keydb_handle {
- int locked;
- int found;
- int current;
- struct resource_item active[MAX_KEYDB_RESOURCES];
+ int locked;
+ int found;
+ int current;
+ int used; /* items in active */
+ struct resource_item active[MAX_KEYDB_RESOURCES];
};
@@ -193,7 +198,21 @@ keydb_add_resource (const char *url, int force, int secret)
iobuf = NULL;
if (created_fname) /* must invalidate that ugly cache */
iobuf_ioctl (NULL, 2, 0, (char*)created_fname);
- keyring_register_filename (filename, secret);
+ {
+ void *token = keyring_register_filename (filename, secret);
+ if (!token)
+ ; /* already registered - ignore it */
+ else if (used_resources >= MAX_KEYDB_RESOURCES)
+ rc = G10ERR_RESOURCE_LIMIT;
+ else
+ {
+ all_resources[used_resources].type = rt;
+ all_resources[used_resources].u.kr = NULL; /* Not used here */
+ all_resources[used_resources].token = token;
+ all_resources[used_resources].secret = secret;
+ used_resources++;
+ }
+ }
break;
default:
@@ -221,24 +240,38 @@ keydb_add_resource (const char *url, int force, int secret)
KEYDB_HANDLE
keydb_new (int secret)
{
- KEYDB_HANDLE hd;
- int i=0;
-
- hd = m_alloc_clear (sizeof *hd);
- hd->found = -1;
-
- hd->active[i].type = KEYDB_RESOURCE_TYPE_KEYRING;
- hd->active[i].u.kr = keyring_new (secret);
- if (!hd->active[i].u.kr) {
- m_free (hd);
- return NULL;
+ KEYDB_HANDLE hd;
+ int i, j;
+
+ hd = m_alloc_clear (sizeof *hd);
+ hd->found = -1;
+
+ assert (used_resources <= MAX_KEYDB_RESOURCES);
+ for (i=j=0; i < used_resources; i++)
+ {
+ if (!all_resources[i].secret != !secret)
+ continue;
+ switch (all_resources[i].type)
+ {
+ case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
+ break;
+ case KEYDB_RESOURCE_TYPE_KEYRING:
+ hd->active[j].type = all_resources[i].type;
+ hd->active[j].token = all_resources[i].token;
+ hd->active[j].secret = all_resources[i].secret;
+ hd->active[j].u.kr = keyring_new (all_resources[i].token, secret);
+ if (!hd->active[j].u.kr) {
+ m_free (hd);
+ return NULL; /* fixme: release all previously allocated handles*/
+ }
+ j++;
+ break;
+ }
}
- i++;
-
-
- assert (i <= MAX_KEYDB_RESOURCES);
- active_handles++;
- return hd;
+ hd->used = j;
+
+ active_handles++;
+ return hd;
}
void
@@ -252,7 +285,7 @@ keydb_release (KEYDB_HANDLE hd)
active_handles--;
unlock_all (hd);
- for (i=0; i < MAX_KEYDB_RESOURCES; i++) {
+ for (i=0; i < hd->used; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
@@ -283,9 +316,9 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
if (!hd)
return NULL;
- if ( hd->found >= 0 && hd->found < MAX_KEYDB_RESOURCES)
+ if ( hd->found >= 0 && hd->found < hd->used)
idx = hd->found;
- else if ( hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES)
+ else if ( hd->current >= 0 && hd->current < hd->used)
idx = hd->current;
else
idx = 0;
@@ -309,7 +342,7 @@ lock_all (KEYDB_HANDLE hd)
{
int i, rc = 0;
- for (i=0; !rc && i < MAX_KEYDB_RESOURCES; i++) {
+ for (i=0; !rc && i < hd->used; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
@@ -345,7 +378,7 @@ unlock_all (KEYDB_HANDLE hd)
if (!hd->locked)
return;
- for (i=MAX_KEYDB_RESOURCES-1; i >= 0; i--) {
+ for (i=hd->used-1; i >= 0; i--) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
@@ -372,7 +405,7 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
if (!hd)
return G10ERR_INV_ARG;
- if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
+ if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
switch (hd->active[hd->found].type) {
@@ -398,7 +431,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
if (!hd)
return G10ERR_INV_ARG;
- if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
+ if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if( opt.dry_run )
@@ -437,9 +470,9 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
if( opt.dry_run )
return 0;
- if ( hd->found >= 0 && hd->found < MAX_KEYDB_RESOURCES)
+ if ( hd->found >= 0 && hd->found < hd->used)
idx = hd->found;
- else if ( hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES)
+ else if ( hd->current >= 0 && hd->current < hd->used)
idx = hd->current;
else
return G10ERR_GENERAL;
@@ -473,7 +506,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
if (!hd)
return G10ERR_INV_ARG;
- if ( hd->found < 0 || hd->found >= MAX_KEYDB_RESOURCES)
+ if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if( opt.dry_run )
@@ -505,16 +538,30 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
int
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
{
- int rc;
-
- if (!hd)
- return G10ERR_INV_ARG;
+ int rc;
+
+ if (!hd)
+ return G10ERR_INV_ARG;
+
+ rc = keydb_search_reset (hd); /* this does reset hd->current */
+ if (rc)
+ return rc;
- rc = keydb_search_reset (hd);
- if (!rc) {
- /* fixme: set forward to a writable one */
+ for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
+ {
+ switch (hd->active[hd->current].type)
+ {
+ case KEYDB_RESOURCE_TYPE_NONE:
+ BUG();
+ break;
+ case KEYDB_RESOURCE_TYPE_KEYRING:
+ if (keyring_is_writable (hd->active[hd->current].token))
+ return 0; /* found (hd->current is set to it) */
+ break;
+ }
}
- return rc;
+
+ return -1;
}
/*
@@ -523,13 +570,24 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
void
keydb_rebuild_caches (void)
{
- int rc;
+ int i, rc;
- rc = keyring_rebuild_cache ();
- if (rc)
- log_error (_("failed to rebuild all keyring caches: %s\n"),
- g10_errstr (rc));
- /* add other types here */
+ for (i=0; i < used_resources; i++)
+ {
+ if (all_resources[i].secret)
+ continue;
+ switch (all_resources[i].type)
+ {
+ case KEYDB_RESOURCE_TYPE_NONE: /* ignore */
+ break;
+ case KEYDB_RESOURCE_TYPE_KEYRING:
+ rc = keyring_rebuild_cache (all_resources[i].token);
+ if (rc)
+ log_error (_("failed to rebuild keyring cache: %s\n"),
+ g10_errstr (rc));
+ break;
+ }
+ }
}
@@ -548,7 +606,7 @@ keydb_search_reset (KEYDB_HANDLE hd)
hd->current = 0;
hd->found = -1;
/* and reset all resources */
- for (i=0; !rc && i < MAX_KEYDB_RESOURCES; i++) {
+ for (i=0; !rc && i < hd->used; i++) {
switch (hd->active[i].type) {
case KEYDB_RESOURCE_TYPE_NONE:
break;
@@ -573,10 +631,10 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
if (!hd)
return G10ERR_INV_ARG;
- while (rc == -1 && hd->current >= 0 && hd->current < MAX_KEYDB_RESOURCES) {
+ while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
switch (hd->active[hd->current].type) {
case KEYDB_RESOURCE_TYPE_NONE:
- rc = -1; /* no resource = eof */
+ BUG(); /* we should never see it here */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc);