Add new option --with-secret.
authorWerner Koch <wk@gnupg.org>
Tue, 3 Jun 2014 19:35:59 +0000 (21:35 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 3 Jun 2014 19:35:59 +0000 (21:35 +0200)
* g10/gpg.c: Add option --with-secret.
* g10/options.h (struct opt): Add field with_secret.
* g10/keylist.c (public_key_list): Pass opt.with_secret to list_all
and list_one.
(list_all, list_one): Add arg mark_secret.
(list_keyblock_colon): Add arg has_secret.
* sm/gpgsm.c: Add option --with-secret.
* sm/server.c (option_handler): Add option "with-secret".
* sm/gpgsm.h (server_control_s): Add field with_secret.
* sm/keylist.c (list_cert_colon): Take care of with_secret.  Also move
the token string from the wrong field 14 to 15.
--

This option is useful for key managers which need to know whether a
key has a secret key.  This change allows to collect this information
in one pass.

14 files changed:
NEWS
doc/DETAILS
doc/gpg.texi
doc/gpgsm.texi
g10/call-agent.c
g10/gpg.c
g10/keygen.c
g10/keylist.c
g10/main.h
g10/options.h
sm/gpgsm.c
sm/gpgsm.h
sm/keylist.c
sm/server.c

diff --git a/NEWS b/NEWS
index ba14079..38c5391 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,8 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
 
  * New option --enable-pinpad-varlen for scdaemon.
 
+ * New option --with-secret for GPG and GPGSM.
+
  * Rename option --disable-pinpad for scdaemon (was: --disable-keypad).
 
  * Better support fo CCID readers.  Now, internal CCID driver supports
index 03c200e..17c417e 100644 (file)
@@ -194,7 +194,8 @@ described here.
 
     Used in sec/sbb to print the serial number of a token (internal
     protect mode 1002) or a '#' if that key is a simple stub (internal
-    protect mode 1001)
+    protect mode 1001).  If the option --with-secret is used and a
+    secret key is available for the public key, a '+' indicates this.
 
 *** Field 16 - Hash algorithm
 
index 9463bb5..71a3107 100644 (file)
@@ -2127,6 +2127,12 @@ of the output and may be used together with another command.
 @item --with-keygrip
 @opindex with-keygrip
 Include the keygrip in the key listings.
+
+@item --with-secret
+@opindex with-secret
+Include info about the presence of a secret key in public key listings
+done with @code{--with-colons}.
+
 @end ifset
 
 @end table
index b38ad4d..078d2ad 100644 (file)
@@ -581,6 +581,13 @@ certificate.
 Include the keygrip in standard key listings.  Note that the keygrip is
 always listed in --with-colons mode.
 
+@ifset gpgtwoone
+@item --with-secret
+@opindex with-secret
+Include info about the presence of a secret key in public key listings
+done with @code{--with-colons}.
+@end ifset
+
 @end table
 
 @c *******************************************
index 42cc9ea..1b30b7f 100644 (file)
@@ -1475,7 +1475,7 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
   return err;
 }
 
-/* Ask the agent whether a secret key is availabale for any of the
+/* Ask the agent whether a secret key is available for any of the
    keys (primary or sub) in KEYBLOCK.  Returns 0 if available.  */
 gpg_error_t
 agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
index fa3e8c2..bd4ca40 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -176,6 +176,7 @@ enum cmd_and_opt_values
     oFingerprint,
     oWithFingerprint,
     oWithKeygrip,
+    oWithSecret,
     oAnswerYes,
     oAnswerNo,
     oKeyring,
@@ -705,6 +706,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoUtf8Strings, "no-utf8-strings", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -2386,6 +2388,10 @@ main (int argc, char **argv)
             opt.with_keygrip = 1;
             break;
 
+         case oWithSecret:
+            opt.with_secret = 1;
+            break;
+
          case oSecretKeyring:
             /* Ignore this old option.  */
             break;
index 0c95435..5c898cc 100644 (file)
@@ -3974,7 +3974,7 @@ do_generate_keypair (struct para_data_s *para,
             {
               tty_printf (_("public and secret key created and signed.\n") );
               tty_printf ("\n");
-              list_keyblock (pub_root, 0, 1, NULL);
+              list_keyblock (pub_root, 0, 1, 1, NULL);
             }
 
 
index 1ecfce9..7d9fe23 100644 (file)
@@ -43,8 +43,8 @@
 #include "status.h"
 #include "call-agent.h"
 
-static void list_all (int);
-static void list_one (strlist_t names, int secret);
+static void list_all (int, int);
+static void list_one (strlist_t names, int secret, int mark_secret);
 static void locate_one (ctrl_t ctrl, strlist_t names);
 static void print_card_serialno (const char *serialno);
 
@@ -114,9 +114,9 @@ public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
   if (locate_mode)
     locate_one (ctrl, list);
   else if (!list)
-    list_all (0);
+    list_all (0, opt.with_secret);
   else
-    list_one (list, 0);
+    list_one (list, 0, opt.with_secret);
 }
 
 
@@ -128,9 +128,9 @@ secret_key_list (ctrl_t ctrl, strlist_t list)
   check_trustdb_stale ();
 
   if (!list)
-    list_all (1);
+    list_all (1, 0);
   else                         /* List by user id */
-    list_one (list, 1);
+    list_one (list, 1, 0);
 }
 
 void
@@ -427,12 +427,17 @@ print_signature_stats (struct sig_stats *s)
     tty_printf (_("%d signatures not checked due to errors\n"), s->oth_err);
 }
 
+
+/* List all keys.  If SECRET is true only secret keys are listed.  If
+   MARK_SECRET is true secret keys are indicated in a public key
+   listing.  */
 static void
-list_all (int secret)
+list_all (int secret, int mark_secret)
 {
   KEYDB_HANDLE hd;
   KBNODE keyblock = NULL;
   int rc = 0;
+  int any_secret;
   const char *lastresname, *resname;
   struct sig_stats stats;
 
@@ -459,7 +464,13 @@ list_all (int secret)
          log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
          goto leave;
        }
-      if (secret && agent_probe_any_secret_key (NULL, keyblock))
+
+      if (secret || mark_secret)
+        any_secret = !agent_probe_any_secret_key (NULL, keyblock);
+      else
+        any_secret = 0;
+
+      if (secret && !any_secret)
         ; /* Secret key listing requested but this isn't one.  */
       else
         {
@@ -478,7 +489,7 @@ list_all (int secret)
                 }
             }
           merge_keys_and_selfsig (keyblock);
-          list_keyblock (keyblock, secret, opt.fingerprint,
+          list_keyblock (keyblock, secret, any_secret, opt.fingerprint,
                          opt.check_sigs ? &stats : NULL);
         }
       release_kbnode (keyblock);
@@ -498,7 +509,7 @@ leave:
 
 
 static void
-list_one (strlist_t names, int secret)
+list_one (strlist_t names, int secret, int mark_secret)
 {
   int rc = 0;
   KBNODE keyblock = NULL;
@@ -537,7 +548,7 @@ list_one (strlist_t names, int secret)
             es_putc ('-', es_stdout);
           es_putc ('\n', es_stdout);
         }
-      list_keyblock (keyblock, secret, opt.fingerprint,
+      list_keyblock (keyblock, secret, mark_secret, opt.fingerprint,
                      (!secret && opt.check_sigs)? &stats : NULL);
       release_kbnode (keyblock);
     }
@@ -572,7 +583,7 @@ locate_one (ctrl_t ctrl, strlist_t names)
        {
          do
            {
-             list_keyblock (keyblock, 0, opt.fingerprint,
+             list_keyblock (keyblock, 0, 0, opt.fingerprint,
                             opt.check_sigs ? &stats : NULL);
              release_kbnode (keyblock);
            }
@@ -1128,8 +1139,12 @@ print_revokers (estream_t fp, PKT_public_key * pk)
     }
 }
 
+
+/* List a key in colon mode.  If SECRET is true this is a secret key
+   record (i.e. requested via --list-secret-key).  If HAS_SECRET a
+   secret key is available even if SECRET is not set.  */
 static void
-list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
+list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
 {
   int rc;
   KBNODE kbctx;
@@ -1154,14 +1169,14 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
     }
 
   pk = node->pkt->pkt.public_key;
-  if (secret || opt.with_keygrip || opt.with_key_data)
+  if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
     {
       rc = hexkeygrip_from_pk (pk, &hexgrip);
       if (rc)
         log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
     }
   stubkey = 0;
-  if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
+  if ((secret||has_secret) && agent_get_keyinfo (NULL, hexgrip, &serialno))
     stubkey = 1;  /* Key not found.  */
 
   keyid_from_pk (pk, keyid);
@@ -1197,12 +1212,14 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
   print_capabilities (pk, keyblock);
   es_putc (':', es_stdout);            /* End of field 13. */
   es_putc (':', es_stdout);            /* End of field 14. */
-  if (secret)
+  if (secret || has_secret)
     {
       if (stubkey)
        es_putc ('#', es_stdout);
       else if (serialno)
         es_fputs (serialno, es_stdout);
+      else if (has_secret)
+        es_putc ('+', es_stdout);
     }
   es_putc (':', es_stdout);            /* End of field 15. */
   es_putc (':', es_stdout);            /* End of field 16. */
@@ -1286,7 +1303,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
           pk2 = node->pkt->pkt.public_key;
           xfree (hexgrip); hexgrip = NULL;
           xfree (serialno); serialno = NULL;
-          if (secret || opt.with_keygrip || opt.with_key_data)
+          if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
             {
               rc = hexkeygrip_from_pk (pk2, &hexgrip);
               if (rc)
@@ -1294,7 +1311,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
                            gpg_strerror (rc));
             }
           stubkey = 0;
-          if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
+          if ((secret||has_secret)
+              && agent_get_keyinfo (NULL, hexgrip, &serialno))
             stubkey = 1;  /* Key not found.  */
 
          keyid_from_pk (pk2, keyid2);
@@ -1323,12 +1341,14 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
          print_capabilities (pk2, NULL);
           es_putc (':', es_stdout);    /* End of field 13. */
           es_putc (':', es_stdout);    /* End of field 14. */
-          if (secret)
+          if (secret || has_secret)
             {
               if (stubkey)
                 es_putc ('#', es_stdout);
               else if (serialno)
                 es_fputs (serialno, es_stdout);
+              else if (has_secret)
+                es_putc ('+', es_stdout);
             }
           es_putc (':', es_stdout);    /* End of field 15. */
           es_putc (':', es_stdout);    /* End of field 16. */
@@ -1529,11 +1549,12 @@ reorder_keyblock (KBNODE keyblock)
 }
 
 void
-list_keyblock (KBNODE keyblock, int secret, int fpr, void *opaque)
+list_keyblock (KBNODE keyblock, int secret, int has_secret, int fpr,
+               void *opaque)
 {
   reorder_keyblock (keyblock);
   if (opt.with_colons)
-    list_keyblock_colon (keyblock, secret, fpr);
+    list_keyblock_colon (keyblock, secret, has_secret, fpr);
   else
     list_keyblock_print (keyblock, secret, fpr, opaque);
 }
index d8b9a4d..2802cb5 100644 (file)
@@ -327,7 +327,8 @@ void public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode );
 void secret_key_list (ctrl_t ctrl, strlist_t list );
 void print_subpackets_colon(PKT_signature *sig);
 void reorder_keyblock (KBNODE keyblock);
-void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque );
+void list_keyblock (kbnode_t keyblock, int secret, int has_secret,
+                    int fpr, void *opaque);
 void print_fingerprint (estream_t fp, PKT_public_key *pk, int mode);
 void print_revokers (estream_t fp, PKT_public_key *pk);
 void show_policy_url(PKT_signature *sig,int indent,int mode);
index c622a46..0a604f9 100644 (file)
@@ -68,6 +68,7 @@ struct
   int with_key_data;
   int with_fingerprint; /* Option --with-fingerprint active.  */
   int with_keygrip;     /* Option --with-keygrip active.  */
+  int with_secret;      /* Option --with-secret active.  */
   int fingerprint; /* list fingerprints */
   int list_sigs;   /* list signatures */
   int no_armor;
index 01f33e3..c813336 100644 (file)
@@ -148,6 +148,7 @@ enum cmd_and_opt_values {
   oWithFingerprint,
   oWithMD5Fingerprint,
   oWithKeygrip,
+  oWithSecret,
   oAnswerYes,
   oAnswerNo,
   oKeyring,
@@ -383,6 +384,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
@@ -1333,6 +1335,7 @@ main ( int argc, char **argv)
 
         case oWithKeyData: opt.with_key_data=1; /* fall thru */
         case oWithColons: ctrl.with_colons = 1; break;
+        case oWithSecret: ctrl.with_secret = 1; break;
         case oWithValidation: ctrl.with_validation=1; break;
         case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break;
 
index 7c7ca7a..83918cc 100644 (file)
@@ -177,6 +177,7 @@ struct server_control_s
                          accessed.  */
 
   int with_colons;    /* Use column delimited output format */
+  int with_secret;    /* Mark secret keys in a public key listing.  */
   int with_chain;     /* Include the certifying certs in a listing */
   int with_validation;/* Validate each key while listing. */
   int with_ephemeral_keys;  /* Include ephemeral flagged keys in the
index f96c03f..dab1295 100644 (file)
@@ -457,7 +457,6 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
   algo = gpgsm_get_key_algo_info (cert, &nbits);
   es_fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
 
-  /* We assume --fixed-list-mode for gpgsm */
   ksba_cert_get_validity (cert, 0, t);
   print_time (t, fp);
   es_putc (':', fp);
@@ -495,19 +494,24 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
   es_putc (':', fp);
   /* Field 12, capabilities: */
   print_capabilities (cert, fp);
+  es_putc (':', fp);
   /* Field 13, not used: */
   es_putc (':', fp);
-  if (have_secret)
+  if (have_secret || ctrl->with_secret)
     {
       char *cardsn;
 
       p = gpgsm_get_keygrip_hexstring (cert);
-      if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn)
+      if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn)
+          && (cardsn || ctrl->with_secret))
         {
           /* Field 14, not used: */
           es_putc (':', fp);
-          /* Field 15:  Token serial number.  */
-          es_fputs (cardsn, fp);
+          /* Field 15:  Token serial number or secret key indicator.  */
+          if (cardsn)
+            es_fputs (cardsn, fp);
+          else if (ctrl->with_secret)
+            es_putc ('+', fp);
           es_putc (':', fp);
         }
       xfree (cardsn);
index 201a34b..f399c8e 100644 (file)
@@ -274,6 +274,11 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
       int i = *value? atoi (value) : 0;
       ctrl->with_validation = i;
     }
+  else if (!strcmp (key, "with-validation"))
+    {
+      int i = *value? atoi (value) : 0;
+      ctrl->with_secret = i;
+    }
   else if (!strcmp (key, "validation-model"))
     {
       int i = gpgsm_parse_validation_model (value);