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_]
-------------------------------------------------------------
* 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]
-------------------------------------------------------------

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
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
The @code{GPGME_KEYLIST_MODE_EPHEMERAL} symbol specifies that keys
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.
@item unsigned int secret : 1
This is true if the subkey is a secret key. Note that it will be false
if the key is actually a stub key; i.e. a secret key operation is
currently not possible (offline-key).
This is true if the subkey is a secret key. Note that it will be
false if the key is actually a stub key; i.e. a secret key operation
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
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.
@item unsigned int secret : 1
This is true if the key is a secret key. Note, that this will always be
true even if the corresponding subkey flag may be false (offline/stub
keys).
This is true if the key is a secret key. Note, that this will always
be true even if the corresponding subkey flag may be false
(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
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");
if (!err)
err = add_arg (gpg, "--with-fingerprint");
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
err = add_arg (gpg, "--with-secret");
if (!err
&& (mode & GPGME_KEYLIST_MODE_SIGS)
&& (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
available and thus there is no need for gpgsm to ask the agent
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",
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=0" ,
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'. */
@ -1645,6 +1650,11 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
"OPTION with-validation=1":
"OPTION with-validation=0" ,
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)

View File

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

View File

@ -370,6 +370,7 @@ gpgme_protocol_t;
#define GPGME_KEYLIST_MODE_EXTERN 2
#define GPGME_KEYLIST_MODE_SIGS 4
#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
#define GPGME_KEYLIST_MODE_WITH_SECRET 16
#define GPGME_KEYLIST_MODE_EPHEMERAL 128
#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
are allowed to modify it. */
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)
; /* 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
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;
key->secret = 1;
}
else if (strchr ("01234567890ABCDEFabcdef", *field))
{
/* Fields starts with a hex digit; thus it is a serial number. */
key->secret = 1;
subkey->is_cardkey = 1;
subkey->card_number = strdup (field);
if (!subkey->card_number)
return gpg_error_from_syserror ();
}
else if (*field == '+')
{
key->secret = 1;
subkey->secret = 1;
}
else
{
/* RFU. */
@ -578,9 +586,11 @@ keylist_colon_handler (void *priv, char *line)
set_mainkey_capability (key, field[11]);
/* 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)
return err;
}
@ -649,9 +659,11 @@ keylist_colon_handler (void *priv, char *line)
set_subkey_capability (subkey, field[11]);
/* 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)
return err;
}