#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"
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;
+
+\f
+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)
}
+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
#endif /*ENABLE_CARD_SUPPORT*/
+/* Print the preferences line. Allowed values for MODE are:
+ * -1 - print to the TTY
+ * 0 - print to stdout.
+ * 1 - use log_info
+ */
+void
+show_preferences (PKT_user_id *uid, int indent, int mode, int verbose)
+{
+ estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
+ const prefitem_t fake = { 0, 0 };
+ const prefitem_t *prefs;
+ int i;
+
+ if (!uid)
+ return;
+
+ if (uid->prefs)
+ prefs = uid->prefs;
+ else if (verbose)
+ prefs = &fake;
+ else
+ return;
+
+ if (verbose)
+ {
+ int any, des_seen = 0, sha1_seen = 0, uncomp_seen = 0;
+
+ tty_fprintf (fp, "%*s %s", indent, "", _("Cipher: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_SYM)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!openpgp_cipher_test_algo (prefs[i].value)
+ && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", openpgp_cipher_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == CIPHER_ALGO_3DES)
+ des_seen = 1;
+ }
+ }
+ if (!des_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("AEAD: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_AEAD)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!openpgp_aead_test_algo (prefs[i].value)
+ && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", openpgp_aead_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ }
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Digest: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_HASH)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (!gcry_md_test_algo (prefs[i].value) && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", gcry_md_algo_name (prefs[i].value));
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == DIGEST_ALGO_SHA1)
+ sha1_seen = 1;
+ }
+ }
+ if (!sha1_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "%s", gcry_md_algo_name (DIGEST_ALGO_SHA1));
+ }
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Compression: "));
+ for (i = any = 0; prefs[i].type; i++)
+ {
+ if (prefs[i].type == PREFTYPE_ZIP)
+ {
+ const char *s = compress_algo_to_string (prefs[i].value);
+
+ if (any)
+ tty_fprintf (fp, ", ");
+ any = 1;
+ /* We don't want to display strings for experimental algos */
+ if (s && prefs[i].value < 100)
+ tty_fprintf (fp, "%s", s);
+ else
+ tty_fprintf (fp, "[%d]", prefs[i].value);
+ if (prefs[i].value == COMPRESS_ALGO_NONE)
+ uncomp_seen = 1;
+ }
+ }
+ if (!uncomp_seen)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ else
+ {
+ tty_fprintf (fp, "%s",
+ compress_algo_to_string (COMPRESS_ALGO_ZIP));
+ tty_fprintf (fp, ", ");
+ }
+ tty_fprintf (fp, "%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
+ }
+ if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
+ {
+ tty_fprintf (fp, "\n%*s %s", indent, "", _("Features: "));
+ any = 0;
+ if (uid->flags.mdc)
+ {
+ tty_fprintf (fp, "MDC");
+ any = 1;
+ }
+ if (uid->flags.aead)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, "AEAD");
+ }
+ if (!uid->flags.ks_modify)
+ {
+ if (any)
+ tty_fprintf (fp, ", ");
+ tty_fprintf (fp, _("Keyserver no-modify"));
+ }
+ }
+ tty_fprintf (fp, "\n");
+ }
+ else
+ {
+ tty_fprintf (fp, "%*s", indent, "");
+ for (i = 0; prefs[i].type; i++)
+ {
+ tty_fprintf (fp, " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
+ prefs[i].type == PREFTYPE_AEAD ? 'A' :
+ prefs[i].type == PREFTYPE_HASH ? 'H' :
+ prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
+ prefs[i].value);
+ }
+ if (uid->flags.mdc)
+ tty_fprintf (fp, " [mdc]");
+ if (uid->flags.aead)
+ tty_fprintf (fp, " [aead]");
+ if (!uid->flags.ks_modify)
+ tty_fprintf (fp, " [no-ks-modify]");
+ tty_fprintf (fp, "\n");
+ }
+}
+
+
/* Flags = 0x01 hashed 0x02 critical. */
static void
status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
}
-/* Helper for list_keyblock_print. */
+/* Helper for list_keyblock_print. The caller must have set
+ * NODFLG_MARK_B to indicate self-signatures. */
static void
list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
struct keylist_context *listctx)
case GPG_ERR_UNUSABLE_PUBKEY:
listctx->no_key++;
return;
+ case GPG_ERR_DIGEST_ALGO:
+ case GPG_ERR_PUBKEY_ALGO:
+ if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS))
+ return;
+ /* fallthru. */
default:
listctx->oth_err++;
sigrc = '%';
}
else
{
+ if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS)
+ && (gpg_err_code (openpgp_pk_test_algo (sig->pubkey_algo)
+ == GPG_ERR_PUBKEY_ALGO)
+ || gpg_err_code (openpgp_md_test_algo (sig->digest_algo)
+ == GPG_ERR_DIGEST_ALGO)
+ || (sig->digest_algo == DIGEST_ALGO_SHA1
+ && !(node->flag & NODFLG_MARK_B) /*no selfsig*/
+ && !opt.flags.allow_weak_key_signatures)))
+ return;
rc = 0;
sigrc = ' ';
}
es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
else if (sigrc == '?')
;
- else if (!opt.fast_list_mode)
+ else if ((node->flag & NODFLG_MARK_B))
+ es_fputs (_("[self-signature]"), es_stdout);
+ else if (!opt.fast_list_mode )
{
size_t n;
char *p = get_user_id (ctrl, sig->keyid, &n, NULL);
print_utf8_buffer (es_stdout, uid->name, uid->len);
es_putc ('\n', es_stdout);
+ if ((opt.list_options & LIST_SHOW_PREF_VERBOSE))
+ show_preferences (uid, indent+2, 0, 1);
+ else if ((opt.list_options & LIST_SHOW_PREF))
+ show_preferences (uid, indent+2, 0, 0);
+
if (opt.with_wkd_hash)
{
char *mbox, *hash, *p;
else if (opt.list_sigs
&& node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
{
- if ((opt.list_options & LIST_SORT_SIGS))
- {
- kbnode_t n;
- unsigned int sigcount = 0;
- kbnode_t *sigarray;
- unsigned int idx;
+ kbnode_t n;
+ unsigned int sigcount = 0;
+ kbnode_t *sigarray;
+ unsigned int idx;
- for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
- sigcount++;
- sigarray = xcalloc (sigcount, sizeof *sigarray);
+ for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
+ sigcount++;
+ sigarray = xcalloc (sigcount, sizeof *sigarray);
- sigcount = 0;
- for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
- {
- if (!keyid_cmp (mainkid, n->pkt->pkt.signature->keyid))
- n->flag |= NODFLG_MARK_B; /* Is a self-sig. */
- else
- n->flag &= ~NODFLG_MARK_B;
+ sigcount = 0;
+ for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
+ {
+ if (keyid_eq (mainkid, n->pkt->pkt.signature->keyid))
+ n->flag |= NODFLG_MARK_B; /* Is a self-sig. */
+ else
+ n->flag &= ~NODFLG_MARK_B;
- sigarray[sigcount++] = node = n;
- }
- /* Note that NODE is now at the last signature. */
+ sigarray[sigcount++] = node = n;
+ }
+ /* Note that NODE is now at the last signature. */
- qsort (sigarray, sigcount, sizeof *sigarray, cmp_signodes);
+ if ((opt.list_options & LIST_SORT_SIGS))
+ qsort (sigarray, sigcount, sizeof *sigarray, cmp_signodes);
- for (idx=0; idx < sigcount; idx++)
- list_signature_print (ctrl, keyblock, sigarray[idx], listctx);
- xfree (sigarray);
- }
- else
- list_signature_print (ctrl, keyblock, node, listctx);
+ for (idx=0; idx < sigcount; idx++)
+ list_signature_print (ctrl, keyblock, sigarray[idx], listctx);
+ xfree (sigarray);
}
}
es_putc ('\n', es_stdout);
do_reorder_keyblock (keyblock, 0);
}
+
static void
list_keyblock (ctrl_t ctrl,
KBNODE keyblock, int secret, int has_secret, int fpr,
{
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))