diff options
author | Werner Koch <[email protected]> | 2025-05-05 13:02:52 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2025-05-05 13:03:01 +0000 |
commit | 87d6da1188db3c7df899821e4c0d895c61504522 (patch) | |
tree | 4304e4775c4d828c6371cecc471463c81e396a89 | |
parent | New decrypt flags GPGME_DECRYPT_LISTONLY. (diff) | |
download | gpgme-87d6da1188db3c7df899821e4c0d895c61504522.tar.gz gpgme-87d6da1188db3c7df899821e4c0d895c61504522.zip |
Mark the subkey used to find a key.
* src/gpgme.h.in (struct _gpgme_subkey): New flag subkey_match.
* src/keylist.c (spacep): New.
(op_data_t): Add field requested_subkey.
(release_op_data): Free it.
(exact_match_pattern): New.
(maybe_setup_for_requested_subkey): New.
(gpgme_op_keylist_start): Call it here.
(gpgme_op_keylist_ext_start): Call it for each pattern until one
found.
(gpgme_op_keylist_next): Set the subkey_match field.
---
This is needed for
GnuPG-bug-id: 3325
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/gpgme.h.in | 5 | ||||
-rw-r--r-- | src/keylist.c | 99 | ||||
-rw-r--r-- | tests/run-keylist.c | 3 |
4 files changed, 106 insertions, 2 deletions
@@ -26,6 +26,7 @@ Noteworthy changes in version 2.0.0 (unreleased) GPGME_RANDOM_MODE_NORMAL NEW. GPGME_RANDOM_MODE_ZBASE32 NEW. GPGME_DECRYPT_LISTONLY NEW. + gpgme_subkey_t EXT: New field 'subkey_match'. gpgme_attr_t REMOVED. gpgme_get_sig_ulong_attr REMOVED. gpgme_get_sig_string_attr REMOVED. diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 69d9f54c..e56c293d 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -590,8 +590,11 @@ struct _gpgme_subkey /* The compliance mode (is_de_vs) has not yet been approved. */ unsigned int beta_compliance : 1; + /* The key was found by an exact fingerprint match on this subkey. */ + unsigned int subkey_match : 1; + /* Internal to GPGME, do not use. */ - unsigned int _unused : 16; + unsigned int _unused : 15; /* Public key algorithm supported by this subkey. */ gpgme_pubkey_algo_t pubkey_algo; diff --git a/src/keylist.c b/src/keylist.c index f8dd2962..11b68408 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -44,6 +44,10 @@ #include "ops.h" #include "debug.h" + +#define spacep(p) (*(p) == ' ' || *(p) == '\t') + + struct key_queue_item_s { @@ -69,6 +73,10 @@ typedef struct /* This points to the last sig in tmp_uid. */ gpgme_key_sig_t tmp_keysig; + /* Helper with a malloced uppercased fingerprint without '!' to be + * used to set the subkey_match flag. */ + char *requested_subkey; + /* Something new is available. */ int key_cond; struct key_queue_item_s *key_queue; @@ -87,6 +95,9 @@ release_op_data (void *hook) /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key, so we do not need to release them here. */ + if (opd->requested_subkey) + free (opd->requested_subkey); + while (key) { struct key_queue_item_s *next = key->next; @@ -1207,6 +1218,64 @@ _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data) } +/* Return true if PATTERN requests an extackt match. That is a + * sequence of at least 40 hexdigits followed by an exclamation mark + * and nothing else. Returns a pointer to the first hexdigit or + * NULL. */ +static const char * +exact_match_pattern (const char *pattern) +{ + const char *s; + int hexlen; + const char *start; + + for(s = pattern; *s && spacep (s); s++ ) /* Skip spaces. */ + ; + if (s[0] == '0' && s[1] == 'x') /* Skip an optional "0x" prefix. */ + s += 2; + start = s; + hexlen = strspn (s, "0123456789abcdefABCDEF"); + if (hexlen >= 40 && s[hexlen] == '!') + { + s += hexlen+1; + /* Skip trailing spaces and LFs. */ + for (; *s && (spacep (s) || *s == '\n' || *s == '\r'); s++ ) + ; + if (!*s) /* Only spaces seen. */ + return start; + } + return NULL; +} + + +/* Helper for gpgme_op_keylist_start and ..._start_ext. */ +static gpg_error_t +maybe_setup_for_requested_subkey (op_data_t opd, const char *pattern) +{ + const char *s; + char *p; + + if (pattern && (s=exact_match_pattern (pattern))) + { + free (opd->requested_subkey); + p = opd->requested_subkey = strdup (s); + if (!p) + return gpg_error_from_syserror (); + for (; *p; p++ ) + { + if (*p >= 'a' && *p <= 'z') + *p &= ~0x20; /* Upcase it. */ + else if (*p == '!') /* Remove the '!' suffix and stop. */ + { + *p = 0; + break; + } + } + } + return 0; +} + + /* Start a keylist operation within CTX, searching for keys which match PATTERN. If SECRET_ONLY is true, only secret keys are returned. */ @@ -1233,6 +1302,10 @@ gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only) if (err) return TRACE_ERR (err); + err = maybe_setup_for_requested_subkey (opd, pattern); + if (err) + return TRACE_ERR (err); + err = _gpgme_op_import_init_result (ctx); if (err) return TRACE_ERR (err); @@ -1277,6 +1350,22 @@ gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[], if (err) return TRACE_ERR (err); + if (pattern && pattern[0]) + { + int i; + + for (i=0; pattern[i]; i++) + { + err = maybe_setup_for_requested_subkey (opd, pattern[i]); + if (err) + return TRACE_ERR (err); + /* We can only handle one exact subnkey request. Thus we + * stop after the first seen. */ + if (opd->requested_subkey) + break; + } + } + err = _gpgme_op_import_init_result (ctx); if (err) return TRACE_ERR (err); @@ -1378,6 +1467,16 @@ gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key) *r_key = queue_item->key; free (queue_item); + if (opd->requested_subkey && (*r_key)->subkeys && (*r_key)->subkeys->fpr) + { + /* Time to set the mark. */ + gpgme_subkey_t subkey = (*r_key)->subkeys; + + for (; subkey; subkey = subkey->next) + if (subkey->fpr && !strcmp (subkey->fpr, opd->requested_subkey)) + subkey->subkey_match = 1; + } + TRACE_SUC ("key=%p (%s)", *r_key, ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? (*r_key)->subkeys->fpr : "invalid"); diff --git a/tests/run-keylist.c b/tests/run-keylist.c index 7bbb9769..44a16596 100644 --- a/tests/run-keylist.c +++ b/tests/run-keylist.c @@ -349,7 +349,8 @@ main (int argc, char **argv) { char *algostr; - printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr)); + printf ("fpr %2d: %s%s\n", nsub, nonnull (subkey->fpr), + subkey->subkey_match? " (match)":""); if (subkey->v5fpr) printf ("v5fpr %2d: %s\n", nsub, nonnull (subkey->v5fpr)); if (subkey->keygrip) |