New mode to list a v5 fingerprint for v4 packets.

* src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_V5FPR): New.
(struct _gpgme_subkey): Add field v5fpr.
* src/engine-gpg.c (gpg_keylist_build_options): Pass new option to
gpg.
* src/key.c (gpgme_key_unref): Free new field.
* src/keylist.c (op_data_t): Parse and add "fp2" line.

* tests/run-keylist.c (show_usage): Add option --v5fpr.

* src/keylist.c (op_data_t): Add field failure_code.
(keylist_status_handler): Handle special value.
(gpgme_op_keylist_end): Return an error if a FAILURE line has been
seen.
--

Note that the failure code part has been added to better diagnose
problems if a wrong gpg version is used.  If verything works right we
should not get this because we check that the gnupg version sis either
>= 2.4.4 or less than 2.3 and >= 2.2.42.

Note further that the v5fpr field may also be used to get the SHA-256
fingerprint of X.509 certificates (even without passing the new mode
flag).

GnuPG-bug-id: 6705
This commit is contained in:
Werner Koch 2023-09-04 17:03:01 +02:00
parent b80d52a1f7
commit e36b2d1bce
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 78 additions and 4 deletions

3
NEWS
View File

@ -3,10 +3,13 @@ Noteworthy changes in version 1.23.0 (unreleased)
* Support GPGME_ENCRYPT_ALWAYS_TRUST also for S/MIME. [T6559]
* New keylist mode GPGME_KEYLIST_MODE_WITH_V5FPR. [T6705]
* qt: Support refreshing keys via WKD. [T6672]
* Interface changes relative to the 1.22.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_WITH_V5FPR NEW.
qt: Protocol::wkdRefreshJob NEW.
qt: WKDRefreshJob NEW.

View File

@ -2901,6 +2901,12 @@ option also makes sure that the keygrip is available in the output.
The @code{GPGME_KEYLIST_MODE_EPHEMERAL} symbol specifies that keys
flagged as ephemeral are included in the listing.
@item GPGME_KEYLIST_MODE_WITH_V5FPR
@since{1.23.0}
The @code{GPGME_KEYLIST_MODE_WITH_V5FPR} symbol specifies that key
listings shall also provide v5 style fingerprints for v4 OpenPGp keys.
@item GPGME_KEYLIST_MODE_VALIDATE
@since{0.4.5}
@ -3610,6 +3616,10 @@ This is the key ID of the subkey in hexadecimal digits.
This is the fingerprint of the subkey in hexadecimal digits, if
available.
@item char *v5fpr
For a v4 OpenPGP key this is its v5 style fingerprint of the subkey in
hexadecimal digits, if available.
@item char *keygrip
@since{1.7.0}

View File

@ -3267,6 +3267,12 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
err = add_arg (gpg, "--with-fingerprint");
}
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_V5FPR)
&& (have_gpg_version (gpg, "2.4.4")
|| (have_gpg_version (gpg, "2.2.42")
&& !have_gpg_version (gpg, "2.3.0"))))
err = add_arg (gpg, "--with-v5-fingerprint");
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
&& have_gpg_version (gpg, "2.1.16"))
err = add_arg (gpg, "--with-tofu-info");

View File

@ -384,6 +384,7 @@ gpgme_protocol_t;
#define GPGME_KEYLIST_MODE_EPHEMERAL 128
#define GPGME_KEYLIST_MODE_VALIDATE 256
#define GPGME_KEYLIST_MODE_FORCE_EXTERN 512
#define GPGME_KEYLIST_MODE_WITH_V5FPR 1024
#define GPGME_KEYLIST_MODE_LOCATE (1|2)
#define GPGME_KEYLIST_MODE_LOCATE_EXTERNAL (1|2|512)
@ -616,6 +617,9 @@ struct _gpgme_subkey
/* The keygrip of the subkey in hex digit form or NULL if not available. */
char *keygrip;
/* For OpenPGP the v5 fpr of a v4 key. For X.509 the SHA256 fingerprint. */
char *v5fpr;
};
typedef struct _gpgme_subkey *gpgme_subkey_t;

View File

@ -342,6 +342,7 @@ gpgme_key_unref (gpgme_key_t key)
{
gpgme_subkey_t next = subkey->next;
free (subkey->fpr);
free (subkey->v5fpr);
free (subkey->curve);
free (subkey->keygrip);
free (subkey->card_number);

View File

@ -58,6 +58,9 @@ typedef struct
/* The error code from ERROR keydb_search. */
gpgme_error_t keydb_search_err;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
gpgme_key_t tmp_key;
/* This points to the last uid in tmp_key. */
@ -146,6 +149,13 @@ keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = 0;
break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
if (opd->failure_code && !strcmp (args, "option-parser")
&& gpg_err_code (opd->failure_code) == GPG_ERR_GENERAL)
err = gpg_error (GPG_ERR_INV_ENGINE);
break;
case GPGME_STATUS_IMPORT_OK:
case GPGME_STATUS_IMPORT_PROBLEM:
case GPGME_STATUS_IMPORT_RES:
@ -570,7 +580,7 @@ keylist_colon_handler (void *priv, char *line)
gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
enum
{
RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_GRP,
RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_FP2, RT_GRP,
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
}
rectype = RT_NONE;
@ -623,6 +633,8 @@ keylist_colon_handler (void *priv, char *line)
rectype = RT_CRS;
else if (!strcmp (field[0], "fpr") && key)
rectype = RT_FPR;
else if (!strcmp (field[0], "fp2") && key)
rectype = RT_FP2;
else if (!strcmp (field[0], "grp") && key)
rectype = RT_GRP;
else if (!strcmp (field[0], "uid") && key)
@ -914,6 +926,27 @@ keylist_colon_handler (void *priv, char *line)
}
break;
case RT_FP2:
/* Either the SHA256 fingerprint of an X.509 cert or the
* alternate fingerprint of a v4 OpenPGP packet. (We take only
* the first one). */
if (fields >= 10 && field[9] && *field[9])
{
/* Need to apply it to the last subkey because all subkeys
do have fingerprints. */
subkey = key->_last_subkey;
if (!subkey->v5fpr)
{
subkey->v5fpr = strdup (field[9]);
if (!subkey->v5fpr)
return gpg_error_from_syserror ();
}
/* Note that we don't store a copy in the key object as we
* do with the standard fingerprint. */
}
break;
case RT_GRP:
/* Field 10 has the keygrip. */
if (fields >= 10 && field[9] && *field[9])
@ -1299,12 +1332,21 @@ gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
gpgme_error_t
gpgme_op_keylist_end (gpgme_ctx_t ctx)
{
void *hook;
op_data_t opd;
gpg_error_t err;
TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx, "");
if (!ctx)
return gpg_error (GPG_ERR_INV_VALUE);
return 0;
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
opd = hook;
if (!err && opd && opd->failure_code)
err = opd->failure_code;
return err;
}

View File

@ -55,6 +55,7 @@ show_usage (int ex)
" --tofu use GPGME_KEYLIST_MODE_TOFU\n"
" --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n"
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
" --v5fpr use GPGME_KEYLIST_MODE_V5FPR\n"
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
" --import import all keys\n"
" --offline use offline mode\n"
@ -179,9 +180,14 @@ main (int argc, char **argv)
mode |= GPGME_KEYLIST_MODE_VALIDATE;
argc--; argv++;
}
else if (!strcmp (*argv, "--with-secret"))
else if (!strcmp (*argv, "--validate"))
{
mode |= GPGME_KEYLIST_MODE_WITH_SECRET;
mode |= GPGME_KEYLIST_MODE_VALIDATE;
argc--; argv++;
}
else if (!strcmp (*argv, "--v5fpr"))
{
mode |= GPGME_KEYLIST_MODE_WITH_V5FPR;
argc--; argv++;
}
else if (!strcmp (*argv, "--import"))
@ -305,6 +311,8 @@ main (int argc, char **argv)
for (nsub=0; subkey; subkey = subkey->next, nsub++)
{
printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr));
if (subkey->v5fpr)
printf ("v5fpr %2d: %s\n", nsub, nonnull (subkey->v5fpr));
if (subkey->keygrip)
printf ("grip %2d: %s\n", nsub, subkey->keygrip);
if (subkey->curve)