diff --git a/g10/ChangeLog b/g10/ChangeLog index cf9a8c919..00fbfead2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2009-04-03 Werner Koch + + * 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 * gpg.c (main): Properly handle UTF8 usernames with --sign-key and diff --git a/g10/gpg.h b/g10/gpg.h index c828c6dce..b53303e13 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -75,7 +75,7 @@ struct server_control_s #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() calls in the code. */ #define G10ERR_BAD_KEY GPG_ERR_BAD_KEY diff --git a/g10/gpgv.c b/g10/gpgv.c index 88baaabab..2797139e3 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -193,12 +193,13 @@ main( int argc, char **argv ) if (opt.verbose > 1) set_packet_list_mode(1); - - if (!nrings) /* no keyring given: use default one */ - keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 0, 0); + + /* Note: We open all keyrings in read-only mode (flag value: 8). */ + if (!nrings) /* No keyring given: use default one. */ + keydb_add_resource ("trustedkeys" EXTSEP_S "gpg", 8, 0); for (sl = nrings; sl; sl = sl->next) - keydb_add_resource (sl->d, 0, 0 ); - + keydb_add_resource (sl->d, 8, 0 ); + FREE_STRLIST (nrings); if ( (rc = verify_signatures( argc, argv ) )) diff --git a/g10/keydb.c b/g10/keydb.c index 28595061a..398be19d6 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1,6 +1,6 @@ /* keydb.c - key database dispatcher * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2008 Free Software Foundation, Inc. + * 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -207,9 +207,10 @@ maybe_create_keyring (char *filename, int force) * created if it does not exist. * Note: this function may be called before secure memory is * available. - * Flag 1 == force - * Flag 2 == mark resource as primary - * Flag 4 == This is a default resources + * Flag 1 - Force. + * Flag 2 - Mark resource as primary. + * Flag 4 - This is a default resources. + * Flag 8 - Open as read-only. */ int 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; const char *resname = url; char *filename = NULL; - int force=(flags&1); + int force = (flags&1); + int readonly = !!(flags&8); int rc = 0; KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; void *token; + if (readonly) + 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. @@ -249,10 +254,10 @@ keydb_add_resource (const char *url, int flags, int secret) else filename = xstrdup (resname); - if (!force) + if (!force && !readonly) 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) { FILE *fp = fopen( filename, "rb" ); @@ -284,7 +289,7 @@ keydb_add_resource (const char *url, int flags, int secret) if (rc) goto leave; - if(keyring_register_filename (filename, secret, &token)) + if(keyring_register_filename (filename, secret, readonly, &token)) { if (used_resources >= MAX_KEYDB_RESOURCES) rc = G10ERR_RESOURCE_LIMIT; @@ -702,6 +707,8 @@ keydb_rebuild_caches (int noisy) { if (all_resources[i].secret) continue; + if (!keyring_is_writable (all_resources[i].token)) + continue; switch (all_resources[i].type) { case KEYDB_RESOURCE_TYPE_NONE: /* ignore */ diff --git a/g10/keyring.c b/g10/keyring.c index 00a5bb986..c01834a6a 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -50,9 +50,11 @@ typedef struct off_item **OffsetHashTable; typedef struct keyring_name *KR_NAME; -struct keyring_name { +struct keyring_name +{ struct keyring_name *next; int secret; + int readonly; DOTLOCK lockhd; int is_locked; 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. */ 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; @@ -210,8 +213,11 @@ keyring_register_filename (const char *fname, int secret, void **ptr) { if (same_file_p (kr->fname, fname)) { + /* Already registered. */ + if (readonly) + kr->readonly = 1; *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)); strcpy (kr->fname, fname); kr->secret = !!secret; + kr->readonly = readonly; kr->lockhd = NULL; kr->is_locked = 0; kr->did_full_scan = 0; @@ -242,7 +249,7 @@ keyring_is_writable (void *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) return -1; /* no successful prior search */ + if (hd->found.kr->readonly) + return gpg_error (GPG_ERR_EACCES); + if (!hd->found.n_packets) { /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); @@ -540,16 +550,24 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) if (!hd) fname = NULL; else if (hd->found.kr) + { fname = hd->found.kr->fname; + if (hd->found.kr->readonly) + return gpg_error (GPG_ERR_EACCES); + } else if (hd->current.kr) + { fname = hd->current.kr->fname; + if (hd->current.kr->readonly) + return gpg_error (GPG_ERR_EACCES); + } else fname = hd->resource? hd->resource->fname:NULL; if (!fname) 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 * after the write opertions. */ @@ -575,6 +593,9 @@ keyring_delete_keyblock (KEYRING_HANDLE hd) if (!hd->found.kr) return -1; /* no successful prior search */ + if (hd->found.kr->readonly) + return gpg_error (GPG_ERR_EACCES); + if (!hd->found.n_packets) { /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); diff --git a/g10/keyring.h b/g10/keyring.h index 584df409e..928605cd1 100644 --- a/g10/keyring.h +++ b/g10/keyring.h @@ -23,7 +23,8 @@ 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); KEYRING_HANDLE keyring_new (void *token, int secret);