Merge branch 'wk-gpg-keybox'

This commit is contained in:
Werner Koch 2011-04-29 15:10:36 +02:00
commit c36deeea8b
11 changed files with 466 additions and 391 deletions

View File

@ -1,3 +1,16 @@
2011-04-29 Werner Koch <wk@g10code.com>
* keydb.c (keydb_get_keyblock, keydb_add_resource): Use gpg_error.
(keydb_get_keyblock): Return VALUE_NOT_FOUND instead of -1.
(keydb_update_keyblock, keydb_insert_keyblock)
(keydb_delete_keyblock): Ditto.
(keydb_locate_writable): Ditto.
(keydb_search_reset): Ditto.
(keydb_search2): Return GPG_ERR_NOT_FOUND instead of -1. Change
all callers.
(keydb_search_first, keydb_search_next, keydb_search_kid)
(keydb_search_fpr): Ditto.
2011-04-29 Marcus Brinkmann <marcus@g10code.com>
* import.c (import_secret_one): Leave all checks to import_one.

View File

@ -1185,7 +1185,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
iobuf_put (out, ')');
iobuf_put (out, '\n');
}
if (err == -1)
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
err = 0;
leave:

View File

@ -431,7 +431,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
hd = keydb_new ();
rc = keydb_search_kid (hd, keyid);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
keydb_release (hd);
return G10ERR_NO_PUBKEY;
@ -992,7 +992,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
hd = keydb_new ();
rc = keydb_search_fpr (hd, fprbuf);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
keydb_release (hd);
return G10ERR_NO_PUBKEY;
@ -2488,7 +2488,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
}
found:
if (rc && rc != -1)
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search failed: %s\n", g10_errstr (rc));
if (!rc)
@ -2496,9 +2496,9 @@ found:
*ret_keyblock = ctx->keyblock; /* Return the keyblock. */
ctx->keyblock = NULL;
}
else if (rc == -1 && no_suitable_key)
else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key)
rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY;
else if (rc == -1)
else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY;
release_kbnode (ctx->keyblock);

View File

@ -1,6 +1,6 @@
/* keydb.c - key database dispatcher
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2008, 2009 Free Software Foundation, Inc.
* 2008, 2009, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -39,10 +39,11 @@
static int active_handles;
typedef enum {
typedef enum
{
KEYDB_RESOURCE_TYPE_NONE = 0,
KEYDB_RESOURCE_TYPE_KEYRING
} KeydbResourceType;
} KeydbResourceType;
#define MAX_KEYDB_RESOURCES 40
struct resource_item
@ -58,11 +59,12 @@ static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
static int used_resources;
static void *primary_keyring=NULL;
struct keydb_handle {
struct keydb_handle
{
int locked;
int found;
int current;
int used; /* items in active */
int used; /* Number of items in ACTIVE. */
struct resource_item active[MAX_KEYDB_RESOURCES];
};
@ -212,122 +214,132 @@ maybe_create_keyring (char *filename, int force)
* Flag 4 - This is a default resources.
* Flag 8 - Open as read-only.
*/
int
gpg_error_t
keydb_add_resource (const char *url, int flags)
{
static int any_public;
const char *resname = url;
char *filename = NULL;
int force = (flags&1);
int read_only = !!(flags&8);
int rc = 0;
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
void *token;
static int any_public;
const char *resname = url;
char *filename = NULL;
int force = (flags&1);
int read_only = !!(flags&8);
int rc = 0;
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
void *token;
if (read_only)
force = 0;
if (read_only)
force = 0;
/* 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;
/* 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;
}
else if (strchr (resname, ':'))
{
log_error ("invalid key resource URL `%s'\n", url );
rc = gpg_error (GPG_ERR_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);
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 = xstrdup (resname);
else
filename = xstrdup (resname);
if (!force && !read_only)
force = !any_public;
if (!force && !read_only)
force = !any_public;
/* See whether we can determine the filetype. */
if (rt == KEYDB_RESOURCE_TYPE_NONE) {
FILE *fp = fopen( filename, "rb" );
/* See whether we can determine the filetype. */
if (rt == KEYDB_RESOURCE_TYPE_NONE)
{
FILE *fp = fopen (filename, "rb");
if (fp) {
u32 magic;
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;
if (fread( &magic, 4, 1, fp) == 1 )
{
if (magic == 0x13579ace || magic == 0xce9a5713)
; /* GDBM magic - not anymore supported. */
else
rt = KEYDB_RESOURCE_TYPE_KEYRING;
}
else /* maybe empty: assume ring */
rt = KEYDB_RESOURCE_TYPE_KEYRING;
fclose( fp );
else /* Maybe empty: assume keyring. */
rt = KEYDB_RESOURCE_TYPE_KEYRING;
fclose( fp );
}
else /* no file yet: create ring */
rt = KEYDB_RESOURCE_TYPE_KEYRING;
else /* No file yet: create keyring. */
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;
switch (rt)
{
case KEYDB_RESOURCE_TYPE_NONE:
log_error ("unknown type of key resource `%s'\n", url );
rc = gpg_error (GPG_ERR_GENERAL);
goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = maybe_create_keyring (filename, force);
if (rc)
goto leave;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = maybe_create_keyring (filename, force);
if (rc)
goto leave;
if(keyring_register_filename (filename, read_only, &token))
{
if (used_resources >= MAX_KEYDB_RESOURCES)
rc = G10ERR_RESOURCE_LIMIT;
else
{
if(flags&2)
primary_keyring=token;
all_resources[used_resources].type = rt;
all_resources[used_resources].u.kr = NULL; /* Not used here */
all_resources[used_resources].token = token;
used_resources++;
}
}
else
{
/* This keyring was already registered, so ignore it.
However, we can still mark it as primary even if it was
already registered. */
if(flags&2)
primary_keyring=token;
}
break;
if (keyring_register_filename (filename, read_only, &token))
{
if (used_resources >= MAX_KEYDB_RESOURCES)
rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
else
{
if (flags&2)
primary_keyring = token;
all_resources[used_resources].type = rt;
all_resources[used_resources].u.kr = NULL; /* Not used here */
all_resources[used_resources].token = token;
used_resources++;
}
}
else
{
/* This keyring was already registered, so ignore it.
However, we can still mark it as primary even if it was
already registered. */
if (flags&2)
primary_keyring = token;
}
break;
default:
log_error ("resource type of `%s' not supported\n", url);
rc = G10ERR_GENERAL;
rc = gpg_error (GPG_ERR_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
any_public = 1;
xfree (filename);
return rc;
leave:
if (rc)
log_error (_("keyblock resource `%s': %s\n"), filename, gpg_strerror (rc));
else
any_public = 1;
xfree (filename);
return rc;
}
@ -370,25 +382,27 @@ keydb_new (void)
void
keydb_release (KEYDB_HANDLE hd)
{
int i;
int i;
if (!hd)
return;
assert (active_handles > 0);
active_handles--;
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;
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;
}
}
xfree (hd);
xfree (hd);
}
@ -403,29 +417,30 @@ keydb_release (KEYDB_HANDLE hd)
const char *
keydb_get_resource_name (KEYDB_HANDLE hd)
{
int idx;
const char *s = NULL;
int idx;
const char *s = NULL;
if (!hd)
return 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;
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;
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: "";
return s? s: "";
}
@ -433,54 +448,62 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
static int
lock_all (KEYDB_HANDLE hd)
{
int i, rc = 0;
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;
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;
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;
else
hd->locked = 1;
return rc;
return rc;
}
static void
unlock_all (KEYDB_HANDLE hd)
{
int i;
int i;
if (!hd->locked)
return;
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;
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;
hd->locked = 0;
}
@ -490,148 +513,153 @@ unlock_all (KEYDB_HANDLE hd)
* the public key used to locate the keyblock or flag bit 1 set for
* the user ID node.
*/
int
gpg_error_t
keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
{
int rc = 0;
gpg_error_t err = 0;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if (hd->found < 0 || hd->found >= hd->used)
return gpg_error (GPG_ERR_VALUE_NOT_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;
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
err = gpg_error (GPG_ERR_GENERAL); /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
break;
}
return rc;
return err;
}
/*
* update the current keyblock with KB
* Update the current keyblock with the keyblock KB
*/
int
keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb)
gpg_error_t
keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
int rc = 0;
gpg_error_t rc;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if (hd->found < 0 || hd->found >= hd->used)
return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
if( opt.dry_run )
return 0;
if (opt.dry_run)
return 0;
rc = lock_all (hd);
if (rc)
return rc;
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;
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_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;
unlock_all (hd);
return rc;
}
/*
* Insert a new KB into one of the resources.
*/
int
keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb)
gpg_error_t
keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
{
int rc = -1;
int idx;
int rc;
int idx;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if( opt.dry_run )
return 0;
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;
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 gpg_error (GPG_ERR_GENERAL);
rc = lock_all (hd);
if (rc)
return rc;
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;
switch (hd->active[idx].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL); /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
break;
}
unlock_all (hd);
return rc;
unlock_all (hd);
return rc;
}
/*
* The current keyblock will be deleted.
* Delete the current keyblock.
*/
int
gpg_error_t
keydb_delete_keyblock (KEYDB_HANDLE hd)
{
int rc = -1;
gpg_error_t rc;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);
if ( hd->found < 0 || hd->found >= hd->used)
return -1; /* nothing found */
if (hd->found < 0 || hd->found >= hd->used)
return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
if( opt.dry_run )
return 0;
if (opt.dry_run)
return 0;
rc = lock_all (hd);
if (rc)
return rc;
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;
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
rc = gpg_error (GPG_ERR_GENERAL);
break;
case KEYDB_RESOURCE_TYPE_KEYRING:
rc = keyring_delete_keyblock (hd->active[hd->found].u.kr);
break;
}
unlock_all (hd);
return rc;
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
gpg_error_t
keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
{
int rc;
gpg_error_t rc;
(void)reserved;
@ -643,7 +671,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
return rc;
/* If we have a primary set, try that one first */
if(primary_keyring)
if (primary_keyring)
{
for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++)
{
@ -675,7 +703,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved)
}
}
return -1;
return gpg_error (GPG_ERR_NOT_FOUND);
}
/*
@ -709,101 +737,116 @@ keydb_rebuild_caches (int noisy)
/*
* Start the next search on this handle right at the beginning
*/
int
gpg_error_t
keydb_search_reset (KEYDB_HANDLE hd)
{
int i, rc = 0;
gpg_error_t rc = 0;
int i;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_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;
hd->current = 0;
hd->found = -1;
/* Now 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;
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.
* Search through all keydb resources, starting at the current
* position, for a keyblock which contains one of the keys described
* in the DESC array. Returns GPG_ERR_NOT_FOUND if no matching
* keyring was found.
*/
int
gpg_error_t
keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex)
{
int rc = -1;
gpg_error_t rc;
if (!hd)
return G10ERR_INV_ARG;
if (!hd)
return gpg_error (GPG_ERR_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, descindex);
break;
rc = -1;
while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
&& 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, descindex);
break;
}
if (rc == -1) /* EOF -> switch to next resource */
hd->current++;
else if (!rc)
hd->found = hd->current;
if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
{
/* EOF -> switch to next resource */
hd->current++;
}
else if (!rc)
hd->found = hd->current;
}
return rc;
return ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
? gpg_error (GPG_ERR_NOT_FOUND)
: rc);
}
int
gpg_error_t
keydb_search_first (KEYDB_HANDLE hd)
{
KEYDB_SEARCH_DESC desc;
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
return keydb_search (hd, &desc, 1);
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_FIRST;
return keydb_search (hd, &desc, 1);
}
int
gpg_error_t
keydb_search_next (KEYDB_HANDLE hd)
{
KEYDB_SEARCH_DESC desc;
KEYDB_SEARCH_DESC desc;
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_NEXT;
return keydb_search (hd, &desc, 1);
memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_NEXT;
return keydb_search (hd, &desc, 1);
}
int
gpg_error_t
keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
{
KEYDB_SEARCH_DESC desc;
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);
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
gpg_error_t
keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
{
KEYDB_SEARCH_DESC desc;
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);
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);
}

View File

@ -132,25 +132,24 @@ union pref_hint
Flag 1 == force
Flag 2 == default
*/
int keydb_add_resource (const char *url, int flags);
gpg_error_t keydb_add_resource (const char *url, int flags);
KEYDB_HANDLE keydb_new (void);
void keydb_release (KEYDB_HANDLE hd);
const char *keydb_get_resource_name (KEYDB_HANDLE hd);
int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb);
int keydb_delete_keyblock (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb);
gpg_error_t keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb);
gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb);
gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd);
gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
void keydb_rebuild_caches (int noisy);
int keydb_search_reset (KEYDB_HANDLE hd);
gpg_error_t keydb_search_reset (KEYDB_HANDLE hd);
#define keydb_search(a,b,c) keydb_search2((a),(b),(c),NULL)
int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex);
int keydb_search_first (KEYDB_HANDLE hd);
int keydb_search_next (KEYDB_HANDLE hd);
int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
gpg_error_t keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex);
gpg_error_t keydb_search_first (KEYDB_HANDLE hd);
gpg_error_t keydb_search_next (KEYDB_HANDLE hd);
gpg_error_t keydb_search_kid (KEYDB_HANDLE hd, u32 *kid);
gpg_error_t keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
/*-- pkclist.c --*/
void show_revocation_reason( PKT_public_key *pk, int mode );

View File

@ -434,12 +434,12 @@ list_all (int secret)
hd = keydb_new ();
if (!hd)
rc = G10ERR_GENERAL;
rc = gpg_error (GPG_ERR_GENERAL);
else
rc = keydb_search_first (hd);
if (rc)
{
if (rc != -1)
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search_first failed: %s\n", g10_errstr (rc));
goto leave;
}
@ -479,7 +479,7 @@ list_all (int secret)
keyblock = NULL;
}
while (!(rc = keydb_search_next (hd)));
if (rc && rc != -1)
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("keydb_search_next failed: %s\n", g10_errstr (rc));
if (opt.check_sigs && !opt.with_colons)

View File

@ -1236,8 +1236,8 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
}
}
if(rc==-1)
rc=0;
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
rc = 0;
leave:
if(rc)

View File

@ -2107,7 +2107,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
desc.skipfnc = search_skipfnc;
desc.skipfncvalue = full_trust;
rc = keydb_search (hd, &desc, 1);
if (rc == -1)
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
keys[nkeys].keyblock = NULL;
return keys;
@ -2181,7 +2181,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
keyblock = NULL;
}
while ( !(rc = keydb_search (hd, &desc, 1)) );
if (rc && rc != -1)
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
{
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
xfree (keys);

View File

@ -1,3 +1,12 @@
2011-04-28 Werner Koch <wk@g10code.com>
* keybox-openpgp.c: Include ../common/openpgpdefs.h.
(enum packet_types): Remove.
(_keybox_parse_openpgp): Update NPARSED also on errors.
(parse_key): Take care of ecc algorithms.
* kbxutil.c (import_openpgp): Do not print an error for non-RSA v3
packets.
2010-07-23 Werner Koch <wk@g10code.com>
* keybox-blob.c (_keybox_create_x509_blob): Fix reallocation bug.
@ -365,7 +374,7 @@
Copyright 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008 Free Software Foundation, Inc.
2007, 2008, 2011 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without

View File

@ -1,5 +1,5 @@
/* kbxutil.c - The Keybox utility
* Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
* Copyright (C) 2000, 2001, 2004, 2007, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -389,8 +389,18 @@ import_openpgp (const char *filename)
{
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
break;
log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
filename, gpg_strerror (err));
if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
{
/* This is likely a v3 key packet with a non-RSA
algorithm. These are keys from very early versions
of GnuPG (pre-OpenPGP). */
}
else
{
fflush (stdout);
log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
filename, gpg_strerror (err));
}
}
else
{

View File

@ -1,5 +1,5 @@
/* keybox-openpgp.c - OpenPGP key parsing
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
* Copyright (C) 2001, 2003, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -35,41 +35,16 @@
#include <gcrypt.h>
enum packet_types
{
PKT_NONE =0,
PKT_PUBKEY_ENC =1, /* public key encrypted packet */
PKT_SIGNATURE =2, /* secret key encrypted packet */
PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/
PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/
PKT_SECRET_KEY =5, /* secret key */
PKT_PUBLIC_KEY =6, /* public key */
PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */
PKT_COMPRESSED =8, /* compressed data packet */
PKT_ENCRYPTED =9, /* conventional encrypted data */
PKT_MARKER =10, /* marker packet (OpenPGP) */
PKT_PLAINTEXT =11, /* plaintext data with filename and mode */
PKT_RING_TRUST =12, /* keyring trust packet */
PKT_USER_ID =13, /* user id packet */
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
PKT_ATTRIBUTE =17, /* PGP's attribute packet */
PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
PKT_MDC =19, /* manipulation detection code packet */
PKT_COMMENT =61, /* new comment packet (private) */
PKT_GPG_CONTROL =63 /* internal control packet */
};
#include "../common/openpgpdefs.h"
/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
which is of amaximum length as stored at BUFLEN. Return the header
which has a maximum length as stored at BUFLEN. Return the header
information of that packet and advance the pointer stored at BUFPTR
to the next packet; also adjust the length stored at BUFLEN to
match the remaining bytes. If there are no more packets, store NULL
at BUFPTR. Return an non-zero error code on failure or the
follwing data on success:
following data on success:
R_DATAPKT = Pointer to the begin of the packet data.
R_DATALEN = Length of this data. This has already been checked to fit
@ -166,8 +141,8 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
return gpg_error (GPG_ERR_UNEXPECTED);
}
if (pktlen == 0xffffffff)
return gpg_error (GPG_ERR_INV_PACKET);
if (pktlen == (unsigned long)(-1))
return gpg_error (GPG_ERR_INV_PACKET);
if (pktlen > len)
return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */
@ -201,6 +176,7 @@ parse_key (const unsigned char *data, size_t datalen,
const unsigned char *mpi_n = NULL;
size_t mpi_n_len = 0, mpi_e_len = 0;
gcry_md_hd_t md;
int is_ecc = 0;
if (datalen < 5)
return gpg_error (GPG_ERR_INV_PACKET);
@ -219,7 +195,6 @@ parse_key (const unsigned char *data, size_t datalen,
return gpg_error (GPG_ERR_INV_PACKET);
ndays = ((data[0]<<8)|(data[1]));
data +=2; datalen -= 2;
if (ndays)
expiredate = ndays? (timestamp + ndays * 86400L) : 0;
}
else
@ -245,9 +220,11 @@ parse_key (const unsigned char *data, size_t datalen,
break;
case 18: /* ECDH */
npkey = 3;
is_ecc = 1;
break;
case 19: /* ECDSA */
npkey = 2;
is_ecc = 1;
break;
default: /* Unknown algorithm. */
return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
@ -259,20 +236,34 @@ parse_key (const unsigned char *data, size_t datalen,
if (datalen < 2)
return gpg_error (GPG_ERR_INV_PACKET);
nbits = ((data[0]<<8)|(data[1]));
data += 2; datalen -=2;
nbytes = (nbits+7) / 8;
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
/* For use by v3 fingerprint calculation we need to know the RSA
modulus and exponent. */
if (i==0)
if (is_ecc && (i == 0 || i == 2))
{
mpi_n = data;
mpi_n_len = nbytes;
nbytes = data[0];
if (nbytes < 2 || nbytes > 254)
return gpg_error (GPG_ERR_INV_PACKET);
nbytes++; /* The size byte itself. */
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
}
else
{
nbits = ((data[0]<<8)|(data[1]));
data += 2;
datalen -= 2;
nbytes = (nbits+7) / 8;
if (datalen < nbytes)
return gpg_error (GPG_ERR_INV_PACKET);
/* For use by v3 fingerprint calculation we need to know the RSA
modulus and exponent. */
if (i==0)
{
mpi_n = data;
mpi_n_len = nbytes;
}
else if (i==1)
mpi_e_len = nbytes;
}
else if (i==1)
mpi_e_len = nbytes;
data += nbytes; datalen -= nbytes;
}
@ -297,7 +288,7 @@ parse_key (const unsigned char *data, size_t datalen,
if (mpi_n_len < 8)
{
/* Moduli less than 64 bit are out of the specs scope. Zero
them out becuase this is what gpg does too. */
them out because this is what gpg does too. */
memset (ki->keyid, 0, 8);
}
else
@ -307,10 +298,10 @@ parse_key (const unsigned char *data, size_t datalen,
{
/* Its a pitty that we need to prefix the buffer with the tag
and a length header: We can't simply pass it to the fast
hashing fucntion for that reason. It might be a good idea to
hashing function for that reason. It might be a good idea to
have a scatter-gather enabled hash function. What we do here
is to use a static buffer if this one is large enough and
only use the regular hash fucntions if this buffer is not
only use the regular hash functions if this buffer is not
large enough. */
if ( 3 + n < sizeof hashbuffer )
{
@ -344,19 +335,19 @@ parse_key (const unsigned char *data, size_t datalen,
/* The caller must pass the address of an INFO structure which will
get filled on success with information pertaining to the OpenPGP
keyblock IMAGE of length IMAGELEN. Note that a caller does only
need to release this INFO structure when the function returns
need to release this INFO structure if the function returns
success. If NPARSED is not NULL the actual number of bytes parsed
will be stored at this address. */
gpg_error_t
_keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
size_t *nparsed,
keybox_openpgp_info_t info)
size_t *nparsed, keybox_openpgp_info_t info)
{
gpg_error_t err = 0;
const unsigned char *image_start, *data;
size_t n, datalen;
int pkttype;
int first = 1;
int read_error = 0;
struct _keybox_openpgp_key_info *k, **ktail = NULL;
struct _keybox_openpgp_uid_info *u, **utail = NULL;
@ -369,7 +360,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
{
err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n);
if (err)
break;
{
read_error = 1;
break;
}
if (first)
{
@ -380,6 +374,8 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
else
{
err = gpg_error (GPG_ERR_UNEXPECTED);
if (nparsed)
*nparsed += n;
break;
}
first = 0;
@ -439,9 +435,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
if (err)
{
info->nsubkeys--;
if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM)
break;
/* We ignore subkeys with unknown algorithms. */
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
err = 0;
if (err)
break;
}
else
ktail = &info->subkeys.next;
@ -459,9 +458,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
{
xfree (k);
info->nsubkeys--;
if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM)
break;
/* We ignore subkeys with unknown algorithms. */
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
err = 0;
if (err)
break;
}
else
{
@ -475,11 +477,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
if (err)
{
_keybox_destroy_openpgp_info (info);
if (!first
&& (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM
|| gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM))
if (!read_error)
{
/* We are able to skip to the end of this keyblock. */
/* Packet parsing worked, thus we should be able to skip the
rest of the keyblock. */
while (image)
{
if (next_packet (&image, &imagelen,