Make gpgv error message about a missing keyring more useful. This fixes

Debian#494040.  Also implement readonly semantic for extra safety.
This commit is contained in:
Werner Koch 2009-04-03 10:34:22 +00:00
parent 7d92a25561
commit 7c98dad98e
6 changed files with 63 additions and 20 deletions

View File

@ -1,3 +1,16 @@
2009-04-03 Werner Koch <wk@g10code.com>
* gpgv.c (main): Open keyrings readonly.
* keydb.c (keydb_add_resource): Add readonly flag bit.
(keydb_rebuild_caches): Don't act on readonly resources.
* keyring.c (keyring_register_filename): Add arg READONLY.
(struct keyring_name): Add field READONLY.
(keyring_is_writable): Implement readonly feature.
(keyring_update_keyblock): Return GPG_ERR_EACCES for readonly
keyrings.
(keyring_insert_keyblock, keyring_delete_keyblock):
2009-04-01 Werner Koch <wk@g10code.com> 2009-04-01 Werner Koch <wk@g10code.com>
* gpg.c (main): Properly handle UTF8 usernames with --sign-key and * gpg.c (main): Properly handle UTF8 usernames with --sign-key and

View File

@ -75,7 +75,7 @@ struct server_control_s
#define g10_errstr(a) gpg_strerror ((a)) #define g10_errstr(a) gpg_strerror ((a))
/* Mapping of the old erro codes to the gpg-error ones. Fixme: This /* Mapping of the old error codes to the gpg-error ones. Fixme: This
is just a temporary solution: We need to do all these gpg_error() is just a temporary solution: We need to do all these gpg_error()
calls in the code. */ calls in the code. */
#define G10ERR_BAD_KEY GPG_ERR_BAD_KEY #define G10ERR_BAD_KEY GPG_ERR_BAD_KEY

View File

@ -193,12 +193,13 @@ main( int argc, char **argv )
if (opt.verbose > 1) if (opt.verbose > 1)
set_packet_list_mode(1); set_packet_list_mode(1);
if (!nrings) /* no keyring given: use default one */ /* Note: We open all keyrings in read-only mode (flag value: 8). */
keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 0, 0); if (!nrings) /* No keyring given: use default one. */
keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 8, 0);
for (sl = nrings; sl; sl = sl->next) for (sl = nrings; sl; sl = sl->next)
keydb_add_resource (sl->d, 0, 0 ); keydb_add_resource (sl->d, 8, 0 );
FREE_STRLIST (nrings); FREE_STRLIST (nrings);
if ( (rc = verify_signatures( argc, argv ) )) if ( (rc = verify_signatures( argc, argv ) ))

View File

@ -1,6 +1,6 @@
/* keydb.c - key database dispatcher /* keydb.c - key database dispatcher
* Copyright (C) 2001, 2002, 2003, 2004, 2005, * Copyright (C) 2001, 2002, 2003, 2004, 2005,
* 2008 Free Software Foundation, Inc. * 2008, 2009 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -207,9 +207,10 @@ maybe_create_keyring (char *filename, int force)
* created if it does not exist. * created if it does not exist.
* Note: this function may be called before secure memory is * Note: this function may be called before secure memory is
* available. * available.
* Flag 1 == force * Flag 1 - Force.
* Flag 2 == mark resource as primary * Flag 2 - Mark resource as primary.
* Flag 4 == This is a default resources * Flag 4 - This is a default resources.
* Flag 8 - Open as read-only.
*/ */
int int
keydb_add_resource (const char *url, int flags, int secret) keydb_add_resource (const char *url, int flags, int secret)
@ -217,11 +218,15 @@ keydb_add_resource (const char *url, int flags, int secret)
static int any_secret, any_public; static int any_secret, any_public;
const char *resname = url; const char *resname = url;
char *filename = NULL; char *filename = NULL;
int force=(flags&1); int force = (flags&1);
int readonly = !!(flags&8);
int rc = 0; int rc = 0;
KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
void *token; void *token;
if (readonly)
force = 0;
/* Do we have an URL? /* Do we have an URL?
* gnupg-ring:filename := this is a plain keyring * gnupg-ring:filename := this is a plain keyring
* filename := See what is is, but create as plain keyring. * filename := See what is is, but create as plain keyring.
@ -249,10 +254,10 @@ keydb_add_resource (const char *url, int flags, int secret)
else else
filename = xstrdup (resname); filename = xstrdup (resname);
if (!force) if (!force && !readonly)
force = secret? !any_secret : !any_public; force = secret? !any_secret : !any_public;
/* see whether we can determine the filetype */ /* See whether we can determine the filetype. */
if (rt == KEYDB_RESOURCE_TYPE_NONE) { if (rt == KEYDB_RESOURCE_TYPE_NONE) {
FILE *fp = fopen( filename, "rb" ); FILE *fp = fopen( filename, "rb" );
@ -284,7 +289,7 @@ keydb_add_resource (const char *url, int flags, int secret)
if (rc) if (rc)
goto leave; goto leave;
if(keyring_register_filename (filename, secret, &token)) if(keyring_register_filename (filename, secret, readonly, &token))
{ {
if (used_resources >= MAX_KEYDB_RESOURCES) if (used_resources >= MAX_KEYDB_RESOURCES)
rc = G10ERR_RESOURCE_LIMIT; rc = G10ERR_RESOURCE_LIMIT;
@ -702,6 +707,8 @@ keydb_rebuild_caches (int noisy)
{ {
if (all_resources[i].secret) if (all_resources[i].secret)
continue; continue;
if (!keyring_is_writable (all_resources[i].token))
continue;
switch (all_resources[i].type) switch (all_resources[i].type)
{ {
case KEYDB_RESOURCE_TYPE_NONE: /* ignore */ case KEYDB_RESOURCE_TYPE_NONE: /* ignore */

View File

@ -50,9 +50,11 @@ typedef struct off_item **OffsetHashTable;
typedef struct keyring_name *KR_NAME; typedef struct keyring_name *KR_NAME;
struct keyring_name { struct keyring_name
{
struct keyring_name *next; struct keyring_name *next;
int secret; int secret;
int readonly;
DOTLOCK lockhd; DOTLOCK lockhd;
int is_locked; int is_locked;
int did_full_scan; int did_full_scan;
@ -199,7 +201,8 @@ update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off)
* if a new keyring was registered. * if a new keyring was registered.
*/ */
int int
keyring_register_filename (const char *fname, int secret, void **ptr) keyring_register_filename (const char *fname, int secret, int readonly,
void **ptr)
{ {
KR_NAME kr; KR_NAME kr;
@ -210,8 +213,11 @@ keyring_register_filename (const char *fname, int secret, void **ptr)
{ {
if (same_file_p (kr->fname, fname)) if (same_file_p (kr->fname, fname))
{ {
/* Already registered. */
if (readonly)
kr->readonly = 1;
*ptr=kr; *ptr=kr;
return 0; /* Already registered. */ return 0;
} }
} }
@ -221,6 +227,7 @@ keyring_register_filename (const char *fname, int secret, void **ptr)
kr = xmalloc (sizeof *kr + strlen (fname)); kr = xmalloc (sizeof *kr + strlen (fname));
strcpy (kr->fname, fname); strcpy (kr->fname, fname);
kr->secret = !!secret; kr->secret = !!secret;
kr->readonly = readonly;
kr->lockhd = NULL; kr->lockhd = NULL;
kr->is_locked = 0; kr->is_locked = 0;
kr->did_full_scan = 0; kr->did_full_scan = 0;
@ -242,7 +249,7 @@ keyring_is_writable (void *token)
{ {
KR_NAME r = token; KR_NAME r = token;
return r? !access (r->fname, W_OK) : 0; return r? (r->readonly || !access (r->fname, W_OK)) : 0;
} }
@ -499,6 +506,9 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb)
if (!hd->found.kr) if (!hd->found.kr)
return -1; /* no successful prior search */ return -1; /* no successful prior search */
if (hd->found.kr->readonly)
return gpg_error (GPG_ERR_EACCES);
if (!hd->found.n_packets) { if (!hd->found.n_packets) {
/* need to know the number of packets - do a dummy get_keyblock*/ /* need to know the number of packets - do a dummy get_keyblock*/
rc = keyring_get_keyblock (hd, NULL); rc = keyring_get_keyblock (hd, NULL);
@ -540,16 +550,24 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb)
if (!hd) if (!hd)
fname = NULL; fname = NULL;
else if (hd->found.kr) else if (hd->found.kr)
{
fname = hd->found.kr->fname; fname = hd->found.kr->fname;
if (hd->found.kr->readonly)
return gpg_error (GPG_ERR_EACCES);
}
else if (hd->current.kr) else if (hd->current.kr)
{
fname = hd->current.kr->fname; fname = hd->current.kr->fname;
if (hd->current.kr->readonly)
return gpg_error (GPG_ERR_EACCES);
}
else else
fname = hd->resource? hd->resource->fname:NULL; fname = hd->resource? hd->resource->fname:NULL;
if (!fname) if (!fname)
return G10ERR_GENERAL; return G10ERR_GENERAL;
/* close this one otherwise we will lose the position for /* Close this one otherwise we will lose the position for
* a next search. Fixme: it would be better to adjust the position * a next search. Fixme: it would be better to adjust the position
* after the write opertions. * after the write opertions.
*/ */
@ -575,6 +593,9 @@ keyring_delete_keyblock (KEYRING_HANDLE hd)
if (!hd->found.kr) if (!hd->found.kr)
return -1; /* no successful prior search */ return -1; /* no successful prior search */
if (hd->found.kr->readonly)
return gpg_error (GPG_ERR_EACCES);
if (!hd->found.n_packets) { if (!hd->found.n_packets) {
/* need to know the number of packets - do a dummy get_keyblock*/ /* need to know the number of packets - do a dummy get_keyblock*/
rc = keyring_get_keyblock (hd, NULL); rc = keyring_get_keyblock (hd, NULL);

View File

@ -23,7 +23,8 @@
typedef struct keyring_handle *KEYRING_HANDLE; typedef struct keyring_handle *KEYRING_HANDLE;
int keyring_register_filename (const char *fname, int secret, void **ptr); int keyring_register_filename (const char *fname, int secret, int readonly,
void **ptr);
int keyring_is_writable (void *token); int keyring_is_writable (void *token);
KEYRING_HANDLE keyring_new (void *token, int secret); KEYRING_HANDLE keyring_new (void *token, int secret);