gpg: Take care of keydb_new returning NULL.
authorWerner Koch <wk@gnupg.org>
Thu, 3 Dec 2015 11:18:32 +0000 (12:18 +0100)
committerWerner Koch <wk@gnupg.org>
Thu, 3 Dec 2015 11:18:32 +0000 (12:18 +0100)
* g10/keydb.c (keydb_new): Print an error message if needed.  Also use
xtrycalloc because we return an error anyway.
* g10/delkey.c (do_delete_key): Handle error retruned by keydb_new.
* g10/export.c (do_export_stream): Ditto.
* g10/getkey.c (get_pubkey): Ditto.
(get_pubkey_fast): Ditto.
(get_pubkeyblock): Ditto.
(get_seckey): Ditto.
(key_byname): Ditto.
(get_pubkey_byfprint): Ditto.
(get_pubkey_byfprint_fast): Ditto.
(parse_def_secret_key): Ditto.
(have_secret_key_with_kid): Ditto.
* g10/import.c (import_one): Ditto.
(import_revoke_cert): Ditto.
* g10/keyedit.c (keyedit_quick_adduid): Ditto.
* g10/keygen.c (quick_generate_keypair): Ditto.
(do_generate_keypair): Ditto.
* g10/trustdb.c (validate_keys): Ditto.
* g10/keyserver.c (keyidlist): Ditto.
* g10/revoke.c (gen_desig_revoke): Ditto.
(gen_revoke): Ditto.
* g10/gpg.c (check_user_ids): Ditto.
(main): Do not print an error message for keydb_new error.
* g10/keylist.c (list_all): Use actual error code returned by
keydb_new.

* g10/t-keydb-get-keyblock.c (do_test): Abort on keydb_new error.
* g10/t-keydb.c (do_test): Ditto.

* g10/keyring.c (keyring_new): Actually return an error so that the
existing keydb_new error checking makes sense for a keyring resource.
(keyring_rebuild_cache): Take care of keyring_new returning an error.
--

Commit 04a6b903 changed keydb_new to return an error.  However the
error was not checked at most places which we fix with this patch.  To
make things easier keydb_new prints an error message itself.

Signed-off-by: Werner Koch <wk@gnupg.org>
16 files changed:
g10/delkey.c
g10/export.c
g10/getkey.c
g10/gpg.c
g10/import.c
g10/keydb.c
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/keylist.c
g10/keyring.c
g10/keyserver.c
g10/revoke.c
g10/t-keydb-get-keyblock.c
g10/t-keydb.c
g10/trustdb.c

index 063de78..b8c03a1 100644 (file)
@@ -65,6 +65,8 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
   *r_sec_avail = 0;
 
   hd = keydb_new ();
+  if (!hd)
+    return gpg_error_from_syserror ();
 
   /* Search the userid.  */
   err = classify_user_id (username, &desc, 1);
index 1d71c1c..f7ad1b2 100644 (file)
@@ -857,6 +857,8 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
   *any = 0;
   init_packet (&pkt);
   kdbhd = keydb_new ();
+  if (!kdbhd)
+    return gpg_error_from_syserror ();
 
   /* For the DANE format override the options.  */
   if ((options & EXPORT_DANE_FORMAT))
index 7d69912..b09d967 100644 (file)
@@ -424,6 +424,11 @@ get_pubkey (PKT_public_key * pk, u32 * keyid)
     ctx.exact = 1; /* Use the key ID exactly as given.  */
     ctx.not_allocated = 1;
     ctx.kr_handle = keydb_new ();
+    if (!ctx.kr_handle)
+      {
+        rc = gpg_error_from_syserror ();
+        goto leave;
+      }
     ctx.nitems = 1;
     ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
     ctx.items[0].u.kid[0] = keyid[0];
@@ -482,6 +487,8 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
 #endif
 
   hd = keydb_new ();
+  if (!hd)
+    return gpg_error_from_syserror ();
   rc = keydb_search_kid (hd, keyid);
   if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
@@ -528,6 +535,8 @@ get_pubkeyblock (u32 * keyid)
   /* No need to set exact here because we want the entire block.  */
   ctx.not_allocated = 1;
   ctx.kr_handle = keydb_new ();
+  if (!ctx.kr_handle)
+    return NULL;
   ctx.nitems = 1;
   ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
   ctx.items[0].u.kid[0] = keyid[0];
@@ -552,6 +561,8 @@ get_seckey (PKT_public_key *pk, u32 *keyid)
   ctx.exact = 1; /* Use the key ID exactly as given.  */
   ctx.not_allocated = 1;
   ctx.kr_handle = keydb_new ();
+  if (!ctx.kr_handle)
+    return gpg_error_from_syserror ();
   ctx.nitems = 1;
   ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
   ctx.items[0].u.kid[0] = keyid[0];
@@ -748,6 +759,13 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
 
   ctx->want_secret = want_secret;
   ctx->kr_handle = keydb_new ();
+  if (!ctx->kr_handle)
+    {
+      rc = gpg_error_from_syserror ();
+      getkey_end (ctx);
+      return rc;
+    }
+
   if (!ret_kb)
     ret_kb = &help_kb;
 
@@ -1068,6 +1086,9 @@ get_pubkey_byfprint (PKT_public_key *pk, kbnode_t *r_keyblock,
       ctx.exact = 1;
       ctx.not_allocated = 1;
       ctx.kr_handle = keydb_new ();
+      if (!ctx.kr_handle)
+        return gpg_error_from_syserror ();
+
       ctx.nitems = 1;
       ctx.items[0].mode = fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16
        : KEYDB_SEARCH_MODE_FPR20;
@@ -1106,6 +1127,9 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
     fprbuf[i++] = 0;
 
   hd = keydb_new ();
+  if (!hd)
+    return gpg_error_from_syserror ();
+
   rc = keydb_search_fpr (hd, fprbuf);
   if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
@@ -1156,10 +1180,15 @@ parse_def_secret_key (ctrl_t ctrl)
         }
 
       if (! hd)
-        hd = keydb_new ();
+        {
+          hd = keydb_new ();
+          if (!hd)
+            return NULL;
+        }
       else
         keydb_search_reset (hd);
 
+
       err = keydb_search (hd, &desc, 1, NULL);
       if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
         continue;
@@ -3148,7 +3177,11 @@ parse_auto_key_locate (char *options)
 }
 
 
-/* For documentation see keydb.h.  */
+/* Returns true if a secret key is available for the public key with
+   key id KEYID; returns false if not.  This function ignores legacy
+   keys.  Note: this is just a fast check and does not tell us whether
+   the secret key is valid; this check merely indicates whether there
+   is some secret key with the specified key id.  */
 int
 have_secret_key_with_kid (u32 *keyid)
 {
@@ -3160,6 +3193,8 @@ have_secret_key_with_kid (u32 *keyid)
   int result = 0;
 
   kdbhd = keydb_new ();
+  if (!kdbhd)
+    return 0;
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
   desc.u.kid[0] = keyid[0];
@@ -3187,9 +3222,8 @@ have_secret_key_with_kid (u32 *keyid)
               assert (node->pkt->pkttype == PKT_PUBLIC_KEY
                       || node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
 
-              if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key) == 0)
-               /* Not available.  */
-               result = 1;
+              if (!agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
+               result = 1; /* Secret key available.  */
              else
                result = 0;
 
index 225ca9a..34d436f 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2155,7 +2155,14 @@ check_user_ids (strlist_t *sp,
                   t->d, option);
 
       if (! hd)
-        hd = keydb_new ();
+        {
+          hd = keydb_new ();
+          if (!hd)
+            {
+              rc = gpg_error_from_syserror ();
+              break;
+            }
+        }
       else
         keydb_search_reset (hd);
 
@@ -2295,8 +2302,7 @@ check_user_ids (strlist_t *sp,
 
   strlist_rev (&s2);
 
-  if (hd)
-    keydb_release (hd);
+  keydb_release (hd);
 
   free_strlist (s);
   *sp = s2;
@@ -4728,10 +4734,7 @@ main (int argc, char **argv)
 
          hd = keydb_new ();
          if (! hd)
-           {
-             log_error (_("Failed to open the keyring DB.\n"));
-             g10_exit (1);
-           }
+            g10_exit (1);
 
          for (i = 1; i < argc; i ++)
            {
index e1577b8..518e97f 100644 (file)
@@ -1071,7 +1071,11 @@ import_one (ctrl_t ctrl,
     }
   else if (rc )  /* Insert this key. */
     {
-      KEYDB_HANDLE hd = keydb_new ();
+      KEYDB_HANDLE hd;
+
+      hd = keydb_new ();
+      if (!hd)
+        return gpg_error_from_syserror ();
 
       rc = keydb_locate_writable (hd);
       if (rc)
@@ -1136,6 +1140,11 @@ import_one (ctrl_t ctrl,
       /* Now read the original keyblock again so that we can use
          that handle for updating the keyblock.  */
       hd = keydb_new ();
+      if (!hd)
+        {
+          rc = gpg_error_from_syserror ();
+          goto leave;
+        }
       keydb_disable_caching (hd);
       rc = keydb_search_fpr (hd, fpr2);
       if (rc )
@@ -1846,6 +1855,12 @@ import_revoke_cert( const char *fname, kbnode_t node, struct stats_s *stats )
 
   /* Read the original keyblock. */
   hd = keydb_new ();
+  if (!hd)
+    {
+      rc = gpg_error_from_syserror ();
+      goto leave;
+    }
+
   {
     byte afp[MAX_FINGERPRINT_LEN];
     size_t an;
index 8a68980..97dfb5f 100644 (file)
@@ -754,17 +754,26 @@ keydb_dump_stats (void)
 }
 
 
+/* Create a new database handle.  A database handle is similar to a
+   file handle: it contains a local file position.  This is used when
+   searching: subsequent searches resume where the previous search
+   left off.  To rewind the position, use keydb_search_reset().  This
+   function returns NULL on error, sets ERRNO, and prints an error
+   diagnostic. */
 KEYDB_HANDLE
 keydb_new (void)
 {
   KEYDB_HANDLE hd;
   int i, j;
   int die = 0;
+  int reterrno;
 
   if (DBG_CLOCK)
     log_clock ("keydb_new");
 
-  hd = xmalloc_clear (sizeof *hd);
+  hd = xtrycalloc (1, sizeof *hd);
+  if (!hd)
+    goto leave;
   hd->found = -1;
   hd->saved_found = -1;
   hd->is_reset = 1;
@@ -781,7 +790,10 @@ keydb_new (void)
           hd->active[j].token  = all_resources[i].token;
           hd->active[j].u.kr = keyring_new (all_resources[i].token);
           if (!hd->active[j].u.kr)
-           die = 1;
+            {
+              reterrno = errno;
+              die = 1;
+            }
           j++;
           break;
         case KEYDB_RESOURCE_TYPE_KEYBOX:
@@ -789,7 +801,10 @@ keydb_new (void)
           hd->active[j].token  = all_resources[i].token;
           hd->active[j].u.kb   = keybox_new_openpgp (all_resources[i].token, 0);
           if (!hd->active[j].u.kb)
-           die = 1;
+            {
+              reterrno = errno;
+              die = 1;
+            }
           j++;
           break;
         }
@@ -801,9 +816,15 @@ keydb_new (void)
   if (die)
     {
       keydb_release (hd);
+      gpg_err_set_errno (reterrno);
       hd = NULL;
     }
 
+ leave:
+  if (!hd)
+    log_error (_("error opening key DB: %s\n"),
+               gpg_strerror (gpg_error_from_syserror()));
+
   return hd;
 }
 
index 1848316..919f3fd 100644 (file)
@@ -186,10 +186,8 @@ gpg_error_t keydb_add_resource (const char *url, unsigned int flags);
 /* Dump some statistics to the log.  */
 void keydb_dump_stats (void);
 
-/* Create a new database handle.  A database handle is similar to a
-   file handle: it contains a local file position.  This is used when
-   searching: subsequent searches resume where the previous search
-   left off.  To rewind the position, use keydb_search_reset().  */
+/* Create a new database handle.  Returns NULL on error, sets ERRNO,
+   and prints an error diagnostic. */
 KEYDB_HANDLE keydb_new (void);
 
 /* Free all resources owned by the database handle.  */
@@ -580,11 +578,8 @@ int get_pubkey_byfprint (PKT_public_key *pk,  kbnode_t *r_keyblock,
 int get_pubkey_byfprint_fast (PKT_public_key *pk,
                               const byte *fprint, size_t fprint_len);
 
-/* Return whether a secret key is available for the public key with
-   key id KEYID.  This function ignores legacy keys.  Note: this is
-   just a fast check and does not tell us whether the secret key is
-   valid; this check merely indicates whether there is some secret key
-   with the specified key id.  */
+/* Returns true if a secret key is available for the public key with
+   key id KEYID.  */
 int have_secret_key_with_kid (u32 *keyid);
 
 /* Parse the --default-key parameter.  Returns the last key (in terms
index a3feb79..0a4766e 100644 (file)
@@ -2386,6 +2386,12 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 
   /* Search the key; we don't want the whole getkey stuff here.  */
   kdbhd = keydb_new ();
+  if (!kdbhd)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
   err = classify_user_id (username, &desc, 1);
   if (!err)
     err = keydb_search (kdbhd, &desc, 1, NULL);
index b3367a4..a1f449e 100644 (file)
@@ -3533,6 +3533,9 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid)
     desc.u.name = uid;
 
     kdbhd = keydb_new ();
+    if (!kdbhd)
+      goto leave;
+
     err = keydb_search (kdbhd, &desc, 1, NULL);
     keydb_release (kdbhd);
     if (gpg_err_code (err) != GPG_ERR_NOT_FOUND)
@@ -4148,12 +4151,18 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
     }
   else if (!err) /* Write to the standard keyrings.  */
     {
-      KEYDB_HANDLE pub_hd = keydb_new ();
+      KEYDB_HANDLE pub_hd;
 
-      err = keydb_locate_writable (pub_hd);
-      if (err)
-        log_error (_("no writable public keyring found: %s\n"),
-                   gpg_strerror (err));
+      pub_hd = keydb_new ();
+      if (!pub_hd)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          err = keydb_locate_writable (pub_hd);
+          if (err)
+            log_error (_("no writable public keyring found: %s\n"),
+                       gpg_strerror (err));
+        }
 
       if (!err && opt.verbose)
         {
index 58c0a96..b2836e8 100644 (file)
@@ -505,7 +505,7 @@ list_all (ctrl_t ctrl, int secret, int mark_secret)
 
   hd = keydb_new ();
   if (!hd)
-    rc = gpg_error (GPG_ERR_GENERAL);
+    rc = gpg_error_from_syserror ();
   else
     rc = keydb_search_first (hd);
   if (rc)
index cf67eb0..6ba5202 100644 (file)
@@ -250,7 +250,7 @@ keyring_is_writable (void *token)
 
 \f
 /* Create a new handle for the resource associated with TOKEN.
-
+   On error NULL is returned and ERRNO is set.
    The returned handle must be released using keyring_release (). */
 KEYRING_HANDLE
 keyring_new (void *token)
@@ -260,7 +260,9 @@ keyring_new (void *token)
 
   assert (resource);
 
-  hd = xmalloc_clear (sizeof *hd);
+  hd = xtrycalloc (1, sizeof *hd);
+  if (!hd)
+    return hd;
   hd->resource = resource;
   active_handles++;
   return hd;
@@ -1487,6 +1489,8 @@ keyring_rebuild_cache (void *token,int noisy)
   ulong count = 0, sigcount = 0;
 
   hd = keyring_new (token);
+  if (!hd)
+    return gpg_error_from_syserror ();
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
 
index ab0eb62..e9de496 100644 (file)
@@ -1190,10 +1190,13 @@ keyserver_import_keyid (ctrl_t ctrl,
 static int
 keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 {
-  int rc=0,ndesc,num=100;
-  KBNODE keyblock=NULL,node;
+  int rc = 0;
+  int num = 100;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
   KEYDB_HANDLE kdbhd;
-  KEYDB_SEARCH_DESC *desc;
+  int ndesc;
+  KEYDB_SEARCH_DESC *desc = NULL;
   strlist_t sl;
 
   *count=0;
@@ -1201,6 +1204,11 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
   *klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);
 
   kdbhd = keydb_new ();
+  if (!kdbhd)
+    {
+      rc = gpg_error_from_syserror ();
+      goto leave;
+    }
   keydb_disable_caching (kdbhd);  /* We are looping the search.  */
 
   if(!users)
index 99242d1..ba87f35 100644 (file)
@@ -220,6 +220,11 @@ gen_desig_revoke (ctrl_t ctrl, const char *uname, strlist_t locusr)
     afx = new_armor_context ();
 
     kdbhd = keydb_new ();
+    if (!kdbhd)
+      {
+        rc = gpg_error_from_syserror ();
+        goto leave;
+      }
     rc = classify_user_id (uname, &desc, 1);
     if (!rc)
       rc = keydb_search (kdbhd, &desc, 1, NULL);
@@ -609,6 +614,11 @@ gen_revoke (const char *uname)
 
   /* Search the userid; we don't want the whole getkey stuff here.  */
   kdbhd = keydb_new ();
+  if (!kdbhd)
+    {
+      rc = gpg_error_from_syserror ();
+      goto leave;
+    }
   rc = classify_user_id (uname, &desc, 1);
   if (!rc)
     rc = keydb_search (kdbhd, &desc, 1, NULL);
index 2fbcb73..c12bab1 100644 (file)
@@ -45,6 +45,8 @@ do_test (int argc, char *argv[])
     ABORT ("Failed to open keyring.");
 
   hd1 = keydb_new ();
+  if (!hd1)
+    ABORT ("");
 
   rc = classify_user_id ("8061 5870 F5BA D690 3336  86D0 F2AD 85AC 1E42 B367",
                         &desc1, 0);
index 17a7611..f0b7778 100644 (file)
@@ -42,7 +42,11 @@ do_test (int argc, char *argv[])
     ABORT ("Failed to open keyring.");
 
   hd1 = keydb_new ();
+  if (!hd1)
+    ABORT ("");
   hd2 = keydb_new ();
+  if (!hd2)
+    ABORT ("");
 
   rc = classify_user_id ("2689 5E25 E844 6D44 A26D  8FAF 2F79 98F3 DBFC 6AD9",
                         &desc1, 0);
index fbb806d..af839d1 100644 (file)
@@ -1896,13 +1896,16 @@ validate_keys (int interactive)
      trust. */
   keydb_rebuild_caches(0);
 
+  kdb = keydb_new ();
+  if (!kdb)
+    return gpg_error_from_syserror ();
+
   start_time = make_timestamp ();
   next_expire = 0xffffffff; /* set next expire to the year 2106 */
   stored = new_key_hash_table ();
   used = new_key_hash_table ();
   full_trust = new_key_hash_table ();
 
-  kdb = keydb_new ();
   reset_trust_records();
 
   /* Fixme: Instead of always building a UTK list, we could just build it