Make gpgv error message about a missing keyring more useful. This fixes
authorWerner Koch <wk@gnupg.org>
Fri, 3 Apr 2009 10:34:22 +0000 (10:34 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 3 Apr 2009 10:34:22 +0000 (10:34 +0000)
Debian#494040.  Also implement readonly semantic for extra safety.

g10/ChangeLog
g10/gpg.h
g10/gpgv.c
g10/keydb.c
g10/keyring.c
g10/keyring.h

index cf9a8c9..00fbfea 100644 (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>
 
        * gpg.c (main): Properly handle UTF8 usernames with --sign-key and
index c828c6d..b53303e 100644 (file)
--- 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          
index 88baaab..2797139 100644 (file)
@@ -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 ) ))
index 2859506..398be19 100644 (file)
@@ -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 */
index 00a5bb9..c01834a 100644 (file)
@@ -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);
index 584df40..928605c 100644 (file)
@@ -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);