Add new keylist mode GPGME_KEYLIST_MODE_WITH_SECRET.

* src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_SECRET): New.
* src/engine-gpg.c (gpg_keylist_build_options): Handle new mode.
* src/engine-gpgsm.c (gpgsm_keylist, gpgsm_keylist_ext): Ditto.
* src/keylist.c (parse_sec_field15): Add arg key and take care of
--with-secret output.

* src/gpgme-tool.c (gt_get_keylist_mode, cmd_keylist_mode): Add
"with_secret".  Print card info and and secret flag for subkeys.
--

Note: This mode may only be used with GnuPG >= 2.1.
This commit is contained in:
Werner Koch 2014-06-04 09:57:54 +02:00
parent ee0f17736e
commit 4dc9af2415
7 changed files with 64 additions and 13 deletions

6
NEWS
View File

@ -1,6 +1,12 @@
Noteworthy changes in version 1.5.1 (unreleased) [C__/A__/R_] Noteworthy changes in version 1.5.1 (unreleased) [C__/A__/R_]
------------------------------------------------------------- -------------------------------------------------------------
* Add support for GnuPG 2.1's --with-secret option.
* Interface changes relative to the 1.5.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_WITH_SECRET NEW.
Noteworthy changes in version 1.5.0 (2014-05-21) [C23/A12/R0] Noteworthy changes in version 1.5.0 (2014-05-21) [C23/A12/R0]
------------------------------------------------------------- -------------------------------------------------------------

View File

@ -2472,6 +2472,13 @@ signature notations on key signatures should be included in the listed
keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also
enabled. enabled.
@item GPGME_KEYLIST_MODE_WITH_SECRET
The @code{GPGME_KEYLIST_MODE_WITH_SECRET} returns information about
the presence of a corresponding secret key in a public key listing. A
public key listing with this mode is slower than a standard listing
but can be used instead of a second run to list the secret keys. This
is only supported for GnuPG versions >= 2.1.
@item GPGME_KEYLIST_MODE_EPHEMERAL @item GPGME_KEYLIST_MODE_EPHEMERAL
The @code{GPGME_KEYLIST_MODE_EPHEMERAL} symbol specifies that keys The @code{GPGME_KEYLIST_MODE_EPHEMERAL} symbol specifies that keys
flagged as ephemeral are included in the listing. flagged as ephemeral are included in the listing.
@ -2712,9 +2719,11 @@ This is true if the subkey can be used for qualified signatures
according to local government regulations. according to local government regulations.
@item unsigned int secret : 1 @item unsigned int secret : 1
This is true if the subkey is a secret key. Note that it will be false This is true if the subkey is a secret key. Note that it will be
if the key is actually a stub key; i.e. a secret key operation is false if the key is actually a stub key; i.e. a secret key operation
currently not possible (offline-key). is currently not possible (offline-key). This is only set if a
listing of secret keys has been requested or if
@code{GPGME_KEYLIST_MODE_WITH_SECRET} is active.
@item gpgme_pubkey_algo_t pubkey_algo @item gpgme_pubkey_algo_t pubkey_algo
This is the public key algorithm supported by this subkey. This is the public key algorithm supported by this subkey.
@ -2905,9 +2914,10 @@ This is true if the key can be used for qualified signatures according
to local government regulations. to local government regulations.
@item unsigned int secret : 1 @item unsigned int secret : 1
This is true if the key is a secret key. Note, that this will always be This is true if the key is a secret key. Note, that this will always
true even if the corresponding subkey flag may be false (offline/stub be true even if the corresponding subkey flag may be false
keys). (offline/stub keys). This is only set if a listing of secret keys has
been requested or if @code{GPGME_KEYLIST_MODE_WITH_SECRET} is active.
@item gpgme_protocol_t protocol @item gpgme_protocol_t protocol
This is the protocol supported by this key. This is the protocol supported by this key.

View File

@ -2194,6 +2194,8 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
err = add_arg (gpg, "--with-fingerprint"); err = add_arg (gpg, "--with-fingerprint");
if (!err) if (!err)
err = add_arg (gpg, "--with-fingerprint"); err = add_arg (gpg, "--with-fingerprint");
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
err = add_arg (gpg, "--with-secret");
if (!err if (!err
&& (mode & GPGME_KEYLIST_MODE_SIGS) && (mode & GPGME_KEYLIST_MODE_SIGS)
&& (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)) && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))

View File

@ -1551,7 +1551,7 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
the agent. However on a fresh installation no public keys are the agent. However on a fresh installation no public keys are
available and thus there is no need for gpgsm to ask the agent available and thus there is no need for gpgsm to ask the agent
whether a secret key exists for the public key. */ whether a secret key exists for the public key. */
if (secret_only) if (secret_only || (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "GETINFO agent-check", gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "GETINFO agent-check",
NULL, NULL); NULL, NULL);
@ -1580,6 +1580,11 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
"OPTION with-ephemeral-keys=1": "OPTION with-ephemeral-keys=1":
"OPTION with-ephemeral-keys=0" , "OPTION with-ephemeral-keys=0" ,
NULL, NULL); NULL, NULL);
gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
(mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
/* Length is "LISTSECRETKEYS " + p + '\0'. */ /* Length is "LISTSECRETKEYS " + p + '\0'. */
@ -1645,6 +1650,11 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
"OPTION with-validation=1": "OPTION with-validation=1":
"OPTION with-validation=0" , "OPTION with-validation=0" ,
NULL, NULL); NULL, NULL);
gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
(mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
if (pattern && *pattern) if (pattern && *pattern)

View File

@ -1861,6 +1861,8 @@ gt_get_keylist_mode (gpgme_tool_t gt)
modes[idx++] = "sigs"; modes[idx++] = "sigs";
if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
modes[idx++] = "sig_notations"; modes[idx++] = "sig_notations";
if (mode & GPGME_KEYLIST_MODE_WITH_SECRET)
modes[idx++] = "with_secret";
if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
modes[idx++] = "ephemeral"; modes[idx++] = "ephemeral";
if (mode & GPGME_KEYLIST_MODE_VALIDATE) if (mode & GPGME_KEYLIST_MODE_VALIDATE)
@ -2591,6 +2593,8 @@ cmd_keylist_mode (assuan_context_t ctx, char *line)
mode |= GPGME_KEYLIST_MODE_SIGS; mode |= GPGME_KEYLIST_MODE_SIGS;
if (strstr (line, "sig_notations")) if (strstr (line, "sig_notations"))
mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS; mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
if (strstr (line, "with_secret"))
mode |= GPGME_KEYLIST_MODE_WITH_SECRET;
if (strstr (line, "ephemeral")) if (strstr (line, "ephemeral"))
mode |= GPGME_KEYLIST_MODE_EPHEMERAL; mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
if (strstr (line, "validate")) if (strstr (line, "validate"))
@ -3299,6 +3303,12 @@ cmd_keylist (assuan_context_t ctx, char *line)
result_xml_tag_start (&state, "subkey", NULL); result_xml_tag_start (&state, "subkey", NULL);
/* FIXME: more data */ /* FIXME: more data */
result_add_fpr (&state, "fpr", subkey->fpr); result_add_fpr (&state, "fpr", subkey->fpr);
result_add_value (&state, "secret", subkey->secret);
result_add_value (&state, "is_cardkey", subkey->is_cardkey);
if (subkey->card_number)
result_add_string (&state, "card_number", subkey->card_number);
if (subkey->curve)
result_add_string (&state, "curve", subkey->curve);
result_xml_tag_end (&state); /* subkey */ result_xml_tag_end (&state); /* subkey */
subkey = subkey->next; subkey = subkey->next;
} }

View File

@ -370,6 +370,7 @@ gpgme_protocol_t;
#define GPGME_KEYLIST_MODE_EXTERN 2 #define GPGME_KEYLIST_MODE_EXTERN 2
#define GPGME_KEYLIST_MODE_SIGS 4 #define GPGME_KEYLIST_MODE_SIGS 4
#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8 #define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
#define GPGME_KEYLIST_MODE_WITH_SECRET 16
#define GPGME_KEYLIST_MODE_EPHEMERAL 128 #define GPGME_KEYLIST_MODE_EPHEMERAL 128
#define GPGME_KEYLIST_MODE_VALIDATE 256 #define GPGME_KEYLIST_MODE_VALIDATE 256

View File

@ -367,7 +367,7 @@ set_ownertrust (gpgme_key_t key, const char *src)
reference to smartcards. FIELD is the content of the field and we reference to smartcards. FIELD is the content of the field and we
are allowed to modify it. */ are allowed to modify it. */
static gpg_error_t static gpg_error_t
parse_sec_field15 (gpgme_subkey_t subkey, char *field) parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field)
{ {
if (!*field) if (!*field)
; /* Empty. */ ; /* Empty. */
@ -375,17 +375,25 @@ parse_sec_field15 (gpgme_subkey_t subkey, char *field)
{ {
/* This is a stub for an offline key. We reset the SECRET flag /* This is a stub for an offline key. We reset the SECRET flag
of the subkey here. Note that the secret flag of the entire of the subkey here. Note that the secret flag of the entire
key will be true even then. */ key will be true even then. We even explicitly set
key->secret to make it works for GPGME_KEYLIST_MODE_WITH_SECRET. */
subkey->secret = 0; subkey->secret = 0;
key->secret = 1;
} }
else if (strchr ("01234567890ABCDEFabcdef", *field)) else if (strchr ("01234567890ABCDEFabcdef", *field))
{ {
/* Fields starts with a hex digit; thus it is a serial number. */ /* Fields starts with a hex digit; thus it is a serial number. */
key->secret = 1;
subkey->is_cardkey = 1; subkey->is_cardkey = 1;
subkey->card_number = strdup (field); subkey->card_number = strdup (field);
if (!subkey->card_number) if (!subkey->card_number)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
} }
else if (*field == '+')
{
key->secret = 1;
subkey->secret = 1;
}
else else
{ {
/* RFU. */ /* RFU. */
@ -578,9 +586,11 @@ keylist_colon_handler (void *priv, char *line)
set_mainkey_capability (key, field[11]); set_mainkey_capability (key, field[11]);
/* Field 15 carries special flags of a secret key. */ /* Field 15 carries special flags of a secret key. */
if (fields >= 15 && key->secret) if (fields >= 15
&& (key->secret
|| (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
{ {
err = parse_sec_field15 (subkey, field[14]); err = parse_sec_field15 (key, subkey, field[14]);
if (err) if (err)
return err; return err;
} }
@ -649,9 +659,11 @@ keylist_colon_handler (void *priv, char *line)
set_subkey_capability (subkey, field[11]); set_subkey_capability (subkey, field[11]);
/* Field 15 carries special flags of a secret key. */ /* Field 15 carries special flags of a secret key. */
if (fields >= 15 && key->secret) if (fields >= 15
&& (key->secret
|| (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
{ {
err = parse_sec_field15 (subkey, field[14]); err = parse_sec_field15 (key, subkey, field[14]);
if (err) if (err)
return err; return err;
} }