g10: Fix default-key selection for signing, possibly by card.
authorNIIBE Yutaka <gniibe@fsij.org>
Mon, 22 May 2017 00:27:36 +0000 (09:27 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 22 May 2017 00:27:36 +0000 (09:27 +0900)
* g10/call-agent.c (warn_version_mismatch): Revert.
(start_agent): Suppress version mismatch if relevant.
* g10/getkey.c (get_seckey_default_or_card): New.
* g10/skclist.c (build_sk_list): Use get_seckey_default_or_card.

--

The change of 97a2394, which prefers available card than default key
specified is too strong.

Fixes-commit: 97a2394ecafaa6f58e4a1f70ecfd04408dc15606
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
g10/call-agent.c
g10/getkey.c
g10/keydb.h
g10/skclist.c

index 4698a25..e6dbb73 100644 (file)
@@ -184,8 +184,7 @@ default_inq_cb (void *opaque, const char *line)
 
 
 /* Print a warning if the server's version number is less than our
-   version number.  Returns an error code on a connection problem.
-   Ignore an error for scdaemon (MODE==2).  */
+   version number.  Returns an error code on a connection problem.  */
 static gpg_error_t
 warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode)
 {
@@ -194,7 +193,7 @@ warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode)
   const char *myversion = strusage (13);
 
   err = get_assuan_server_version (ctx, mode, &serverversion);
-  if (err && mode != 2)
+  if (err)
     log_error (_("error getting version from '%s': %s\n"),
                servername, gpg_strerror (err));
   else if (compare_version_strings (serverversion, myversion) < 0)
@@ -290,7 +289,8 @@ start_agent (ctrl_t ctrl, int flag_for_card)
 
       memset (&info, 0, sizeof info);
 
-      rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
+      if (!(flag_for_card & FLAG_FOR_CARD_SUPPRESS_ERRORS))
+        rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2);
       if (!rc)
         rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
                               NULL, NULL, NULL, NULL,
index d8c81c9..04ecf4f 100644 (file)
@@ -3960,6 +3960,58 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
     }
 }
 
+gpg_error_t
+get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
+                            const byte *fpr_card, size_t fpr_len)
+{
+  gpg_error_t err;
+  strlist_t namelist = NULL;
+
+  const char *def_secret_key = parse_def_secret_key (ctrl);
+
+  if (def_secret_key)
+    add_to_strlist (&namelist, def_secret_key);
+  else if (fpr_card)
+    return get_pubkey_byfprint (ctrl, pk, NULL, fpr_card, fpr_len);
+
+  if (!fpr_card
+      || (def_secret_key && def_secret_key[strlen (def_secret_key)-1] == '!'))
+    err = key_byname (ctrl, NULL, namelist, pk, 1, 0, NULL, NULL);
+  else
+    { /* Default key is specified and card key is also available.  */
+      kbnode_t k, keyblock = NULL;
+
+      err = key_byname (ctrl, NULL, namelist, pk, 1, 0, &keyblock, NULL);
+      if (!err)
+        for (k = keyblock; k; k = k->next)
+          {
+            PKT_public_key *pk_candidate;
+            char fpr[MAX_FINGERPRINT_LEN];
+
+            if (k->pkt->pkttype != PKT_PUBLIC_KEY
+                &&k->pkt->pkttype != PKT_PUBLIC_SUBKEY)
+              continue;
+
+            pk_candidate = k->pkt->pkt.public_key;
+            if (!pk_candidate->flags.valid)
+              continue;
+            if (!((pk_candidate->pubkey_usage & USAGE_MASK) & pk->req_usage))
+              continue;
+            fingerprint_from_pk (pk_candidate, fpr, NULL);
+            if (!memcmp (fpr_card, fpr, fpr_len))
+              {
+                release_public_key_parts (pk);
+                copy_public_key (pk, pk_candidate);
+                break;
+              }
+          }
+      release_kbnode (keyblock);
+    }
+
+  free_strlist (namelist);
+
+  return err;
+}
 \f
 /*********************************************
  ***********  User ID printing helpers *******
index 1da93a7..4016723 100644 (file)
@@ -351,6 +351,8 @@ const char *parse_def_secret_key (ctrl_t ctrl);
 
 /* Look up a secret key.  */
 gpg_error_t get_seckey_default (ctrl_t ctrl, PKT_public_key *pk);
+gpg_error_t get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk,
+                                        const byte *fpr, size_t fpr_len);
 
 /* Search for keys matching some criteria.  */
 gpg_error_t getkey_bynames (ctrl_t ctrl,
index 489277c..78890dc 100644 (file)
@@ -137,7 +137,7 @@ build_sk_list (ctrl_t ctrl,
       pk = xmalloc_clear (sizeof *pk);
       pk->req_usage = use;
 
-      /* Check if a card is available.  If any, use it.  */
+      /* Check if a card is available.  If any, use the key as a hint.  */
       err = agent_scd_serialno (&serialno, NULL);
       if (!err)
         {
@@ -146,19 +146,11 @@ build_sk_list (ctrl_t ctrl,
           if (err)
             log_error ("error retrieving key fingerprint from card: %s\n",
                        gpg_strerror (err));
-          else if (info.fpr1valid)
-            {
-              if ((err = get_pubkey_byfprint (ctrl, pk, NULL, info.fpr1, 20)))
-                {
-                  info.fpr1valid = 0;
-                  log_error ("error on card key to sign: %s, try default\n",
-                             gpg_strerror (err));
-                }
-            }
         }
 
-      if (!info.fpr1valid
-          && (err = getkey_byname (ctrl, NULL, pk, NULL, 1, NULL)))
+      err = get_seckey_default_or_card (ctrl, pk,
+                                        info.fpr1valid? info.fpr1 : NULL, 20);
+      if (err)
        {
          free_public_key (pk);
          pk = NULL;