diff --git a/NEWS b/NEWS index ba140796d..38c539116 100644 --- 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 diff --git a/doc/DETAILS b/doc/DETAILS index 03c200e71..17c417e18 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -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 diff --git a/doc/gpg.texi b/doc/gpg.texi index 9463bb5eb..71a3107d8 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -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 diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index b38ad4d72..078d2ad6a 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -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 ******************************************* diff --git a/g10/call-agent.c b/g10/call-agent.c index 42cc9ea1f..1b30b7fea 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -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) diff --git a/g10/gpg.c b/g10/gpg.c index fa3e8c210..bd4ca4057 100644 --- 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; diff --git a/g10/keygen.c b/g10/keygen.c index 0c954356e..5c898cc61 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -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); } diff --git a/g10/keylist.c b/g10/keylist.c index 1ecfce998..7d9fe230c 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -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); } diff --git a/g10/main.h b/g10/main.h index d8b9a4db5..2802cb5c3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -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); diff --git a/g10/options.h b/g10/options.h index c622a4639..0a604f9af 100644 --- a/g10/options.h +++ b/g10/options.h @@ -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; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 01f33e3ae..c813336ae 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -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; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 7c7ca7a20..83918cc9a 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -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 diff --git a/sm/keylist.c b/sm/keylist.c index f96c03f07..dab1295d0 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -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); diff --git a/sm/server.c b/sm/server.c index 201a34b3e..f399c8ec1 100644 --- a/sm/server.c +++ b/sm/server.c @@ -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);