1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

New key db.

This commit is contained in:
Neal H. Walfield 2015-10-29 10:18:13 +01:00
parent 19362a8dd7
commit 6da0e52af3
6 changed files with 1570 additions and 29 deletions

View File

@ -30,7 +30,7 @@ include $(top_srcdir)/am/cmacros.am
AM_CFLAGS = $(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS) \ AM_CFLAGS = $(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS) \
$(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS)
needed_libs = ../kbx/libkeybox.a $(libcommon) needed_libs = ../kbx/libkeybox.a $(libcommon) $(SQLITE3_LIBS)
bin_PROGRAMS = gpg2 bin_PROGRAMS = gpg2
if !HAVE_W32CE_SYSTEM if !HAVE_W32CE_SYSTEM
@ -58,7 +58,7 @@ trust_source = trustdb.c trustdb.h tdbdump.c tdbio.c tdbio.h
endif endif
if USE_TOFU if USE_TOFU
tofu_source = tofu.h tofu.c sqlite.c sqlite.h tofu_source = tofu.h tofu.c
else else
tofu_source = tofu_source =
endif endif
@ -102,7 +102,9 @@ common_source = \
sig-check.c \ sig-check.c \
keylist.c \ keylist.c \
pkglue.c pkglue.h \ pkglue.c pkglue.h \
ecdh.c ecdh.c \
kdb.c kdb.h \
sqlite.c sqlite.h
gpg2_SOURCES = gpg.c \ gpg2_SOURCES = gpg.c \
server.c \ server.c \
@ -148,7 +150,7 @@ gpgv2_SOURCES = gpgv.c \
LDADD = $(needed_libs) ../common/libgpgrl.a \ LDADD = $(needed_libs) ../common/libgpgrl.a \
$(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS)
gpg2_LDADD = $(LDADD) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ gpg2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
$(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
$(LIBICONV) $(resource_objs) $(extra_sys_libs) $(LIBICONV) $(resource_objs) $(extra_sys_libs)
gpg2_LDFLAGS = $(extra_bin_ldflags) gpg2_LDFLAGS = $(extra_bin_ldflags)

View File

@ -1154,6 +1154,9 @@ import_one (ctrl_t ctrl,
goto leave; goto leave;
} }
assert (strcmp (keystr_from_pk(keyblock_orig->pkt->pkt.public_key),
keystr_from_pk(pk)) == 0);
/* Make sure the original direct key sigs are all sane. */ /* Make sure the original direct key sigs are all sane. */
n_sigs_cleaned = fix_bad_direct_key_sigs (keyblock_orig, keyid); n_sigs_cleaned = fix_bad_direct_key_sigs (keyblock_orig, keyid);
if (n_sigs_cleaned) if (n_sigs_cleaned)

1349
g10/kdb.c Normal file

File diff suppressed because it is too large Load Diff

29
g10/kdb.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef GNUPG_KDB_H
#define GNUPG_KDB_H
#include "keydb.h"
typedef struct keydb_handle *KDB_HANDLE;
gpg_error_t kdb_register_file (const char *fname, int read_only, void **ptr);
int kdb_is_writable (void *token);
KDB_HANDLE kdb_new (void *token);
void kdb_release (KDB_HANDLE hd);
void kdb_push_found_state (KDB_HANDLE hd);
void kdb_pop_found_state (KDB_HANDLE hd);
const char *kdb_get_resource_name (KDB_HANDLE hd);
int kdb_lock (KDB_HANDLE hd, int yes);
int kdb_get_keyblock (KDB_HANDLE hd, iobuf_t *iobuf,
int *pk_no, int *uid_no, u32 **sigstatus);
int kdb_update_keyblock (KDB_HANDLE hd, kbnode_t kb,
const void *image, size_t imagelen);
gpg_error_t kdb_insert_keyblock (KDB_HANDLE hd, kbnode_t kb,
const void *image, size_t imagelen,
u32 *sigstatus);
int kdb_delete (KDB_HANDLE hd);
int kdb_search_reset (KDB_HANDLE hd);
int kdb_search (KDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex);
#endif

View File

@ -37,6 +37,7 @@
#include "../kbx/keybox.h" #include "../kbx/keybox.h"
#include "keydb.h" #include "keydb.h"
#include "i18n.h" #include "i18n.h"
#include "kdb.h"
static int active_handles; static int active_handles;
@ -44,7 +45,8 @@ typedef enum
{ {
KEYDB_RESOURCE_TYPE_NONE = 0, KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING, KEYDB_RESOURCE_TYPE_KEYRING,
KEYDB_RESOURCE_TYPE_KEYBOX KEYDB_RESOURCE_TYPE_KEYBOX,
KEYDB_RESOURCE_TYPE_KEYDB
} KeydbResourceType; } KeydbResourceType;
#define MAX_KEYDB_RESOURCES 40 #define MAX_KEYDB_RESOURCES 40
@ -54,6 +56,7 @@ struct resource_item
union { union {
KEYRING_HANDLE kr; KEYRING_HANDLE kr;
KEYBOX_HANDLE kb; KEYBOX_HANDLE kb;
KDB_HANDLE kdb;
} u; } u;
void *token; void *token;
}; };
@ -251,13 +254,14 @@ keyblock_cache_clear (struct keydb_handle *hd)
/* Handle the creation of a keyring or a keybox if it does not yet /* Handle the creation of a keyring or a keybox if it does not yet
exist. Take into account that other processes might have the exist. Take into account that other processes might have the
keyring/keybox already locked. This lock check does not work if keyring/keybox already locked. This lock check does not work if
the directory itself is not yet available. If IS_BOX is true the the directory itself is not yet available. RT is the type of
filename is expected to refer to a keybox. If FORCE_CREATE is true resource being created. If FORCE_CREATE is true the keyring or
the keyring or keybox will be created. keybox will be created.
Return 0 if it is okay to access the specified file. */ Return 0 if it is okay to access the specified file. */
static int static int
maybe_create_keyring_or_box (char *filename, int is_box, int force_create) maybe_create_resource (char *filename, KeydbResourceType rt,
int force_create)
{ {
dotlock_t lockhd = NULL; dotlock_t lockhd = NULL;
IOBUF iobuf; IOBUF iobuf;
@ -361,12 +365,25 @@ maybe_create_keyring_or_box (char *filename, int is_box, int force_create)
if (!iobuf) if (!iobuf)
{ {
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
if (is_box) switch (rt)
log_error (_("error creating keybox '%s': %s\n"), {
filename, gpg_strerror (rc)); case KEYDB_RESOURCE_TYPE_NONE:
else log_fatal ("Bad value for resource type: %d\n", rt);
log_error (_("error creating keyring '%s': %s\n"), break;
filename, gpg_strerror (rc));
case KEYDB_RESOURCE_TYPE_KEYRING:
log_error (_("error creating keyring '%s': %s\n"),
filename, gpg_strerror (rc));
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
log_error (_("error creating keybox '%s': %s\n"),
filename, gpg_strerror (rc));
break;
case KEYDB_RESOURCE_TYPE_KEYDB:
log_error (_("error creating keydb '%s': %s\n"),
filename, gpg_strerror (rc));
break;
}
goto leave; goto leave;
} }
@ -376,7 +393,7 @@ maybe_create_keyring_or_box (char *filename, int is_box, int force_create)
/* Make sure that at least one record is in a new keybox file, so /* Make sure that at least one record is in a new keybox file, so
that the detection magic will work the next time it is used. */ that the detection magic will work the next time it is used. */
if (is_box) if (rt == KEYDB_RESOURCE_TYPE_KEYBOX)
{ {
FILE *fp = fopen (filename, "w"); FILE *fp = fopen (filename, "w");
if (!fp) if (!fp)
@ -388,22 +405,29 @@ maybe_create_keyring_or_box (char *filename, int is_box, int force_create)
} }
if (rc) if (rc)
{ {
if (is_box) log_error (_("error creating keybox '%s': %s\n"),
log_error (_("error creating keybox '%s': %s\n"), filename, gpg_strerror (rc));
filename, gpg_strerror (rc));
else
log_error (_("error creating keyring '%s': %s\n"),
filename, gpg_strerror (rc));
goto leave; goto leave;
} }
} }
if (!opt.quiet) if (!opt.quiet)
{ {
if (is_box) switch (rt)
log_info (_("keybox '%s' created\n"), filename); {
else case KEYDB_RESOURCE_TYPE_NONE:
log_info (_("keyring '%s' created\n"), filename); log_fatal ("Bad value for resource type: %d\n", rt);
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
log_info (_("keyring '%s' created\n"), filename);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
log_info (_("keybox '%s' created\n"), filename);
break;
case KEYDB_RESOURCE_TYPE_KEYDB:
log_info (_("keydb '%s' created\n"), filename);
break;
}
} }
rc = 0; rc = 0;
@ -445,6 +469,8 @@ rt_from_file (const char *filename, int *r_found, int *r_openpgp)
{ {
if (magic == 0x13579ace || magic == 0xce9a5713) if (magic == 0x13579ace || magic == 0xce9a5713)
; /* GDBM magic - not anymore supported. */ ; /* GDBM magic - not anymore supported. */
else if (memcmp (&magic, "SQLi", 4) == 0)
rt = KEYDB_RESOURCE_TYPE_KEYDB;
else if (fread (&verbuf, 4, 1, fp) == 1 else if (fread (&verbuf, 4, 1, fp) == 1
&& verbuf[0] == 1 && verbuf[0] == 1
&& fread (&magic, 4, 1, fp) == 1 && fread (&magic, 4, 1, fp) == 1
@ -559,6 +585,11 @@ keydb_add_resource (const char *url, unsigned int flags)
rt = KEYDB_RESOURCE_TYPE_KEYBOX; rt = KEYDB_RESOURCE_TYPE_KEYBOX;
resname += 10; resname += 10;
} }
else if (strlen (resname) > 10 && !strncmp (resname, "gnupg-kdb:", 10) )
{
rt = KEYDB_RESOURCE_TYPE_KEYDB;
resname += 10;
}
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
else if (strchr (resname, ':')) else if (strchr (resname, ':'))
{ {
@ -662,7 +693,8 @@ keydb_add_resource (const char *url, unsigned int flags)
goto leave; goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING: case KEYDB_RESOURCE_TYPE_KEYRING:
rc = maybe_create_keyring_or_box (filename, 0, create); rc = maybe_create_resource (filename, KEYDB_RESOURCE_TYPE_KEYRING,
create);
if (rc) if (rc)
goto leave; goto leave;
@ -692,7 +724,8 @@ keydb_add_resource (const char *url, unsigned int flags)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
{ {
rc = maybe_create_keyring_or_box (filename, 1, create); rc = maybe_create_resource (filename, KEYDB_RESOURCE_TYPE_KEYBOX,
create);
if (rc) if (rc)
goto leave; goto leave;
@ -727,6 +760,36 @@ keydb_add_resource (const char *url, unsigned int flags)
} }
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
{
rc = maybe_create_resource (filename, KEYDB_RESOURCE_TYPE_KEYDB, create);
if (rc)
goto leave;
rc = kdb_register_file (filename, read_only, &token);
if (rc == 0)
{
if (used_resources >= MAX_KEYDB_RESOURCES)
rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
else
{
/* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
/* primary_keyring = token; */
all_resources[used_resources].type = rt;
all_resources[used_resources].u.kb = NULL; /* Not used here */
all_resources[used_resources].token = token;
used_resources++;
}
}
/* XXX: How to mark this as a primary if it was already
registered. */
/* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
/* primary_keyring = token; */
}
break;
default: default:
log_error ("resource type of '%s' not supported\n", url); log_error ("resource type of '%s' not supported\n", url);
rc = gpg_error (GPG_ERR_GENERAL); rc = gpg_error (GPG_ERR_GENERAL);
@ -792,6 +855,14 @@ keydb_new (void)
die = 1; die = 1;
j++; j++;
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
hd->active[j].type = all_resources[i].type;
hd->active[j].token = all_resources[i].token;
hd->active[j].u.kdb = kdb_new (all_resources[i].token);
if (!hd->active[j].u.kdb)
die = 1;
j++;
break;
} }
} }
hd->used = j; hd->used = j;
@ -831,6 +902,9 @@ keydb_release (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
keybox_release (hd->active[i].u.kb); keybox_release (hd->active[i].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
kdb_release (hd->active[i].u.kdb);
break;
} }
} }
@ -873,6 +947,9 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
s = keybox_get_resource_name (hd->active[idx].u.kb); s = keybox_get_resource_name (hd->active[idx].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
s = kdb_get_resource_name (hd->active[idx].u.kdb);
break;
} }
return s? s: ""; return s? s: "";
@ -904,6 +981,9 @@ lock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_lock (hd->active[i].u.kb, 1); rc = keybox_lock (hd->active[i].u.kb, 1);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
rc = kdb_lock (hd->active[i].u.kdb, 1);
break;
} }
} }
@ -922,6 +1002,9 @@ lock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_lock (hd->active[i].u.kb, 0); rc = keybox_lock (hd->active[i].u.kb, 0);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
rc = kdb_lock (hd->active[i].u.kdb, 0);
break;
} }
} }
} }
@ -952,6 +1035,9 @@ unlock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
keybox_lock (hd->active[i].u.kb, 0); keybox_lock (hd->active[i].u.kb, 0);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
kdb_lock (hd->active[i].u.kdb, 0);
break;
} }
} }
hd->locked = 0; hd->locked = 0;
@ -981,6 +1067,9 @@ keydb_push_found_state (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
keybox_push_found_state (hd->active[hd->found].u.kb); keybox_push_found_state (hd->active[hd->found].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
kdb_push_found_state (hd->active[hd->found].u.kdb);
break;
} }
hd->saved_found = hd->found; hd->saved_found = hd->found;
@ -1009,6 +1098,9 @@ keydb_pop_found_state (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
keybox_pop_found_state (hd->active[hd->found].u.kb); keybox_pop_found_state (hd->active[hd->found].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
kdb_pop_found_state (hd->active[hd->found].u.kdb);
break;
} }
} }
@ -1254,6 +1346,23 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
} }
} }
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
{
iobuf_t iobuf;
u32 *sigstatus;
int pk_no, uid_no;
err = kdb_get_keyblock (hd->active[hd->found].u.kdb, &iobuf,
&pk_no, &uid_no, &sigstatus);
if (!err)
{
err = parse_keyblock_image (iobuf, pk_no, uid_no, sigstatus,
ret_kb);
xfree (sigstatus);
iobuf_close (iobuf);
}
break;
}
} }
if (hd->keyblock_cache.state != KEYBLOCK_CACHE_FILLED) if (hd->keyblock_cache.state != KEYBLOCK_CACHE_FILLED)
@ -1399,6 +1508,20 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
} }
} }
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
{
iobuf_t iobuf;
err = build_keyblock_image (kb, &iobuf, NULL);
if (!err)
{
err = kdb_update_keyblock (hd->active[hd->found].u.kdb, kb,
iobuf_get_temp_buffer (iobuf),
iobuf_get_temp_length (iobuf));
iobuf_close (iobuf);
}
}
break;
} }
unlock_all (hd); unlock_all (hd);
@ -1460,6 +1583,23 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
} }
} }
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
{
iobuf_t iobuf;
u32 *sigstatus;
err = build_keyblock_image (kb, &iobuf, &sigstatus);
if (!err)
{
err = kdb_insert_keyblock (hd->active[idx].u.kdb, kb,
iobuf_get_temp_buffer (iobuf),
iobuf_get_temp_length (iobuf),
sigstatus);
xfree (sigstatus);
iobuf_close (iobuf);
}
}
break;
} }
unlock_all (hd); unlock_all (hd);
@ -1499,6 +1639,9 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_delete (hd->active[hd->found].u.kb); rc = keybox_delete (hd->active[hd->found].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
rc = kdb_delete (hd->active[hd->found].u.kdb);
break;
} }
unlock_all (hd); unlock_all (hd);
@ -1553,6 +1696,10 @@ keydb_locate_writable (KEYDB_HANDLE hd)
if (keybox_is_writable (hd->active[hd->current].token)) if (keybox_is_writable (hd->active[hd->current].token))
return 0; /* found (hd->current is set to it) */ return 0; /* found (hd->current is set to it) */
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
if (kdb_is_writable (hd->active[hd->current].token))
return 0; /* found (hd->current is set to it) */
break;
} }
} }
@ -1581,6 +1728,9 @@ keydb_rebuild_caches (int noisy)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
/* N/A. */ /* N/A. */
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
/* N/A. */
break;
} }
} }
} }
@ -1626,6 +1776,9 @@ keydb_search_reset (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_KEYBOX:
rc = keybox_search_reset (hd->active[i].u.kb); rc = keybox_search_reset (hd->active[i].u.kb);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
rc = kdb_search_reset (hd->active[i].u.kdb);
break;
} }
} }
hd->is_reset = 1; hd->is_reset = 1;
@ -1717,6 +1870,10 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
descindex, &hd->skipped_long_blobs); descindex, &hd->skipped_long_blobs);
while (rc == GPG_ERR_LEGACY_KEY); while (rc == GPG_ERR_LEGACY_KEY);
break; break;
case KEYDB_RESOURCE_TYPE_KEYDB:
rc = kdb_search (hd->active[hd->current].u.kdb, desc,
ndesc, descindex);
break;
} }
if (DBG_LOOKUP) if (DBG_LOOKUP)

View File

@ -1716,7 +1716,8 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
desc.skipfnc = search_skipfnc; desc.skipfnc = search_skipfnc;
desc.skipfncvalue = full_trust; desc.skipfncvalue = full_trust;
rc = keydb_search (hd, &desc, 1, NULL); rc = keydb_search (hd, &desc, 1, NULL);
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND) if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND
|| gpg_err_code (rc) == GPG_ERR_EOF)
{ {
keys[nkeys].keyblock = NULL; keys[nkeys].keyblock = NULL;
return keys; return keys;