diff options
author | Werner Koch <[email protected]> | 2022-11-25 15:04:54 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2022-11-25 15:04:54 +0000 |
commit | 1324dc3490b02c4ff818655db1474c594f04e4ec (patch) | |
tree | b9c72c1068de3d8e2d7238e2d9a7f3c1e1a82651 /g10/keylist.c | |
parent | dirmngr: Silence ocsp debug output. (diff) | |
download | gnupg-1324dc3490b02c4ff818655db1474c594f04e4ec.tar.gz gnupg-1324dc3490b02c4ff818655db1474c594f04e4ec.zip |
gpg: New option --list-filter
* g10/gpg.c (oListFilter): New.
(opts): Add --list-filter.
(main): Parse oListFilter.
* g10/keylist.c: Include init.h and recsel.h.
(struct list_filter_s, list_filter): New.
(release_list_filter): New.
(cleanup_keylist_globals): New.
(parse_and_set_list_filter): New.
(list_keyblock): Implement --list-filter type "select".
* g10/import.c (impex_filter_getval): Add scope support and new
property names "key-size", "algostr", "origin", "lastupd", and "url".
--
This option is pretty useful to select keys based on their properties.
The scope thing can be sued to limit a selection to just the primary
key or to subkeys. For example:
gpg -k --list-filter 'select=revoked-f && sub/algostr=ed25519'
Lists all non-revoked keys with an ed25519 (signing)-subkey.
Diffstat (limited to 'g10/keylist.c')
-rw-r--r-- | g10/keylist.c | 82 |
1 files changed, 78 insertions, 4 deletions
diff --git a/g10/keylist.c b/g10/keylist.c index f8e4ff32a..1ced732a4 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -44,6 +44,8 @@ #include "../common/mbox-util.h" #include "../common/zb32.h" #include "tofu.h" +#include "../common/init.h" +#include "../common/recsel.h" #include "../common/compliance.h" #include "../common/pkscreening.h" @@ -64,16 +66,26 @@ struct keylist_context int no_validity; /* Do not show validity. */ }; - -static void list_keyblock (ctrl_t ctrl, - kbnode_t keyblock, int secret, int has_secret, - int fpr, struct keylist_context *listctx); +/* An object and a global instance to store selectors created from + * --list-filter select=EXPR. + */ +struct list_filter_s +{ + recsel_expr_t selkey; +}; +struct list_filter_s list_filter; /* The stream used to write attribute packets to. */ static estream_t attrib_fp; + + +static void list_keyblock (ctrl_t ctrl, + kbnode_t keyblock, int secret, int has_secret, + int fpr, struct keylist_context *listctx); + /* Release resources from a keylist context. */ static void keylist_context_release (struct keylist_context *listctx) @@ -82,6 +94,49 @@ keylist_context_release (struct keylist_context *listctx) } +static void +release_list_filter (struct list_filter_s *filt) +{ + recsel_release (filt->selkey); + filt->selkey = NULL; +} + + +static void +cleanup_keylist_globals (void) +{ + release_list_filter (&list_filter); +} + + +/* Parse and set an list filter from string. STRING has the format + * "NAME=EXPR" with NAME being the name of the filter. Spaces before + * and after NAME are not allowed. If this function is all called + * several times all expressions for the same NAME are concatenated. + * Supported filter names are: + * + * - select :: If the expression evaluates to true for a certain key + * this key will be listed. The expression may use any + * variable defined for the export and import filters. + * + */ +gpg_error_t +parse_and_set_list_filter (const char *string) +{ + gpg_error_t err; + + /* Auto register the cleanup function. */ + register_mem_cleanup_func (cleanup_keylist_globals); + + if (!strncmp (string, "select=", 7)) + err = recsel_parse_expr (&list_filter.selkey, string+7); + else + err = gpg_error (GPG_ERR_INV_NAME); + + return err; +} + + /* List the keys. If list is NULL, all available keys are listed. * With LOCATE_MODE set the locate algorithm is used to find a key; if * in addition NO_LOCAL is set the locate does not look into the local @@ -2163,6 +2218,7 @@ reorder_keyblock (KBNODE keyblock) do_reorder_keyblock (keyblock, 0); } + static void list_keyblock (ctrl_t ctrl, KBNODE keyblock, int secret, int has_secret, int fpr, @@ -2170,6 +2226,24 @@ list_keyblock (ctrl_t ctrl, { reorder_keyblock (keyblock); + if (list_filter.selkey) + { + int selected = 0; + struct impex_filter_parm_s parm; + parm.ctrl = ctrl; + + for (parm.node = keyblock; parm.node; parm.node = parm.node->next) + { + if (recsel_select (list_filter.selkey, impex_filter_getval, &parm)) + { + selected = 1; + break; + } + } + if (!selected) + return; /* Skip this one. */ + } + if (opt.with_colons) list_keyblock_colon (ctrl, keyblock, secret, has_secret); else if ((opt.list_options & LIST_SHOW_ONLY_FPR_MBOX)) |