summaryrefslogtreecommitdiffstats
path: root/g10/keydb.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keydb.c')
-rw-r--r--g10/keydb.c686
1 files changed, 0 insertions, 686 deletions
diff --git a/g10/keydb.c b/g10/keydb.c
deleted file mode 100644
index d8dd83fe6..000000000
--- a/g10/keydb.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/* keydb.c - key database dispatcher
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "util.h"
-#include "options.h"
-#include "main.h" /*try_make_homedir ()*/
-#include "packet.h"
-#include "keyring.h"
-#include "keydb.h"
-#include "i18n.h"
-
-static int active_handles;
-
-typedef enum {
- KEYDB_RESOURCE_TYPE_NONE = 0,
- KEYDB_RESOURCE_TYPE_KEYRING
-} KeydbResourceType;
-#define MAX_KEYDB_RESOURCES 20
-
-struct resource_item {
- 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;
- int used; /* items in active */
- struct resource_item active[MAX_KEYDB_RESOURCES];
-};
-
-
-static int lock_all (KEYDB_HANDLE hd);
-static void unlock_all (KEYDB_HANDLE hd);
-
-
-/*
- * Register a resource (which currently may only be a keyring file).
- * The first keyring which is added by this function is
- * created if it does not exist.
- * Note: this function may be called before secure memory is
- * available.
- */
-int
-keydb_add_resource (const char *url, int force, int secret)
-{
- static int any_secret, any_public;
- const char *resname = url;
- IOBUF iobuf = NULL;
- char *filename = NULL;
- int rc = 0;
- KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
- void *token;
-
- /* Do we have an URL?
- * gnupg-ring:filename := this is a plain keyring
- * filename := See what is is, but create as plain keyring.
- */
- if (strlen (resname) > 11) {
- if (!strncmp( resname, "gnupg-ring:", 11) ) {
- rt = KEYDB_RESOURCE_TYPE_KEYRING;
- resname += 11;
- }
- #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
- else if (strchr (resname, ':')) {
- log_error ("invalid key resource URL `%s'\n", url );
- rc = G10ERR_GENERAL;
- goto leave;
- }
- #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
- }
-
- if (*resname != DIRSEP_C ) { /* do tilde expansion etc */
- if (strchr(resname, DIRSEP_C) )
- filename = make_filename (resname, NULL);
- else
- filename = make_filename (opt.homedir, resname, NULL);
- }
- else
- filename = m_strdup (resname);
-
- if (!force)
- force = secret? !any_secret : !any_public;
-
- /* see whether we can determine the filetype */
- if (rt == KEYDB_RESOURCE_TYPE_NONE) {
- FILE *fp = fopen( filename, "rb" );
-
- if (fp) {
- u32 magic;
-
- if (fread( &magic, 4, 1, fp) == 1 ) {
- if (magic == 0x13579ace || magic == 0xce9a5713)
- ; /* GDBM magic - no more support */
- else
- rt = KEYDB_RESOURCE_TYPE_KEYRING;
- }
- else /* maybe empty: assume ring */
- rt = KEYDB_RESOURCE_TYPE_KEYRING;
- fclose( fp );
- }
- else /* no file yet: create ring */
- rt = KEYDB_RESOURCE_TYPE_KEYRING;
- }
-
- switch (rt) {
- case KEYDB_RESOURCE_TYPE_NONE:
- log_error ("unknown type of key resource `%s'\n", url );
- rc = G10ERR_GENERAL;
- goto leave;
-
- case KEYDB_RESOURCE_TYPE_KEYRING:
- if (access(filename, F_OK))
- { /* file does not exist */
- mode_t oldmask;
- char *last_slash_in_filename;
-
- if (!force)
- {
- rc = G10ERR_OPEN_FILE;
- goto leave;
- }
-
- last_slash_in_filename = strrchr (filename, DIRSEP_C);
- *last_slash_in_filename = 0;
- if (access(filename, F_OK))
- { /* on the first time we try to create the default
- homedir and in this case the process will be
- terminated, so that on the next invocation it can
- read the options file in on startup */
- try_make_homedir (filename);
- rc = G10ERR_OPEN_FILE;
- *last_slash_in_filename = DIRSEP_C;
- goto leave;
- }
- *last_slash_in_filename = DIRSEP_C;
-
- oldmask=umask(077);
- iobuf = iobuf_create (filename);
- umask(oldmask);
- if (!iobuf)
- {
- log_error ( _("error creating keyring `%s': %s\n"),
- filename, strerror(errno));
- rc = G10ERR_OPEN_FILE;
- goto leave;
- }
-
- if (!opt.quiet)
- log_info (_("keyring `%s' created\n"), filename);
- iobuf_close (iobuf);
- iobuf = NULL;
- /* must invalidate that ugly cache */
- iobuf_ioctl (NULL, 2, 0, (char*)filename);
- } /* end file creation */
-
- 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:
- log_error ("resource type of `%s' not supported\n", url);
- rc = G10ERR_GENERAL;
- goto leave;
- }
-
- /* fixme: check directory permissions and print a warning */
-
- leave:
- if (rc)
- log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc));
- else if (secret)
- any_secret = 1;
- else
- any_public = 1;
- m_free (filename);
- return rc;
-}
-
-
-
-
-KEYDB_HANDLE
-keydb_new (int secret)
-{
- 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;
- }
- }
- hd->used = j;
-
- active_handles++;
- return hd;
-}
-
-void
-keydb_release (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd)
- return;
- assert (active_handles > 0);
- active_handles--;
-
- unlock_all (hd);
- for (i=0; i < hd->used; i++) {
- switch (hd->active[i].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- keyring_release (hd->active[i].u.kr);
- break;
- }
- }
-
- m_free (hd);
-}
-
-
-/*
- * Return the name of the current resource. This is function first
- * looks for the last found found, then for the current search
- * position, and last returns the first available resource. The
- * returned string is only valid as long as the handle exists. This
- * function does only return NULL if no handle is specified, in all
- * other error cases an empty string is returned.
- */
-const char *
-keydb_get_resource_name (KEYDB_HANDLE hd)
-{
- int idx;
- const char *s = NULL;
-
- if (!hd)
- return NULL;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- idx = 0;
-
- switch (hd->active[idx].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- s = NULL;
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- s = keyring_get_resource_name (hd->active[idx].u.kr);
- break;
- }
-
- return s? s: "";
-}
-
-
-
-static int
-lock_all (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- for (i=0; !rc && i < hd->used; i++) {
- switch (hd->active[i].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_lock (hd->active[i].u.kr, 1);
- break;
- }
- }
-
- if (rc) {
- /* revert the already set locks */
- for (i--; i >= 0; i--) {
- switch (hd->active[i].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- keyring_lock (hd->active[i].u.kr, 0);
- break;
- }
- }
- }
- else
- hd->locked = 1;
-
- return rc;
-}
-
-static void
-unlock_all (KEYDB_HANDLE hd)
-{
- int i;
-
- if (!hd->locked)
- return;
-
- for (i=hd->used-1; i >= 0; i--) {
- switch (hd->active[i].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- keyring_lock (hd->active[i].u.kr, 0);
- break;
- }
- }
- hd->locked = 0;
-}
-
-
-/*
- * Return the last found keyring. Caller must free it.
- * The returned keyblock has the kbode flag bit 0 set for the node with
- * the public key used to locate the keyblock or flag bit 1 set for
- * the user ID node.
- */
-int
-keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
- break;
- }
-
- return rc;
-}
-
-/*
- * update the current keyblock with KB
- */
-int
-keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * Insert a new KB into one of the resources.
- */
-int
-keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
-{
- int rc = -1;
- int idx;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if( opt.dry_run )
- return 0;
-
- if ( hd->found >= 0 && hd->found < hd->used)
- idx = hd->found;
- else if ( hd->current >= 0 && hd->current < hd->used)
- idx = hd->current;
- else
- return G10ERR_GENERAL;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[idx].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * The current keyblock will be deleted.
- */
-int
-keydb_delete_keyblock (KEYDB_HANDLE hd)
-{
- int rc = -1;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
-
- if( opt.dry_run )
- return 0;
-
- rc = lock_all (hd);
- if (rc)
- return rc;
-
- switch (hd->active[hd->found].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- rc = G10ERR_GENERAL; /* oops */
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
- break;
- }
-
- unlock_all (hd);
- return rc;
-}
-
-
-/*
- * Locate the default writable key resource, so that the next
- * operation (which is only relevant for inserts) will be done on this
- * resource.
- */
-int
-keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
-{
- int rc;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- rc = keydb_search_reset (hd); /* this does reset hd->current */
- if (rc)
- return rc;
-
- 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 -1;
-}
-
-/*
- * Rebuild the caches of all key resources.
- */
-void
-keydb_rebuild_caches (void)
-{
- int i, rc;
-
- 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;
- }
- }
-}
-
-
-
-/*
- * Start the next search on this handle right at the beginning
- */
-int
-keydb_search_reset (KEYDB_HANDLE hd)
-{
- int i, rc = 0;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- hd->current = 0;
- hd->found = -1;
- /* and reset all resources */
- for (i=0; !rc && i < hd->used; i++) {
- switch (hd->active[i].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_search_reset (hd->active[i].u.kr);
- break;
- }
- }
- return rc;
-}
-
-
-/*
- * Search through all keydb resources, starting at the current position,
- * for a keyblock which contains one of the keys described in the DESC array.
- */
-int
-keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
-{
- int rc = -1;
-
- if (!hd)
- return G10ERR_INV_ARG;
-
- while (rc == -1 && hd->current >= 0 && hd->current < hd->used) {
- switch (hd->active[hd->current].type) {
- case KEYDB_RESOURCE_TYPE_NONE:
- BUG(); /* we should never see it here */
- break;
- case KEYDB_RESOURCE_TYPE_KEYRING:
- rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc);
- break;
- }
- if (rc == -1) /* EOF -> switch to next resource */
- hd->current++;
- else if (!rc)
- hd->found = hd->current;
- }
-
- return rc;
-}
-
-
-int
-keydb_search_first (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FIRST;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_next (KEYDB_HANDLE hd)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_NEXT;
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
- desc.u.kid[0] = kid[0];
- desc.u.kid[1] = kid[1];
- return keydb_search (hd, &desc, 1);
-}
-
-int
-keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
-{
- KEYDB_SEARCH_DESC desc;
-
- memset (&desc, 0, sizeof desc);
- desc.mode = KEYDB_SEARCH_MODE_FPR;
- memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
- return keydb_search (hd, &desc, 1);
-}
-
-
-