aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/gpg.texi39
-rw-r--r--g10/gpg.c8
-rw-r--r--g10/import.c135
-rw-r--r--g10/main.h1
4 files changed, 182 insertions, 1 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 6f0249ab1..9a0622199 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2218,6 +2218,45 @@ opposite meaning. The options are:
Defaults to no.
@end table
+@item --import-filter @code{@var{name}=@var{expr}}
+@opindex import-filter
+This option defines an import filter which is implied to the imported
+keyblock right before it will be stored. @var{name} defines the type
+of filter to use, @var{expr} the expression to evaluate. The option
+can be used several times which then appends more expression to the
+same @var{name}.
+
+@noindent
+The available filter types are:
+
+@table @asis
+
+ @item keep-uid
+ This filter will keep a user id packet and its dependent packets in
+ the keyblock if the expression evaluates to true.
+
+@end table
+
+The syntax for the expression is defined in the appendix (FIXME). The
+property names for the expressions depend on the actual filter type
+and are indicated in the following table.
+
+The available properties are:
+
+@table @asis
+
+ @item uid
+ A string with the user id. (keep-uid)
+
+ @item mbox
+ The addr-spec part of a user id with mailbox or the empty string.
+ (keep-uid)
+
+ @item primary
+ Boolean indicating whether the user id is the primary one. (keep-uid)
+
+@end table
+
@item --export-options @code{parameters}
@opindex export-options
This is a space or comma delimited string that gives options for
diff --git a/g10/gpg.c b/g10/gpg.c
index b1d6c3464..009b84c0b 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -300,6 +300,7 @@ enum cmd_and_opt_values
oKeyServer,
oKeyServerOptions,
oImportOptions,
+ oImportFilter,
oExportOptions,
oListOptions,
oVerifyOptions,
@@ -572,6 +573,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"),
ARGPARSE_s_s (oImportOptions, "import-options", "@"),
+ ARGPARSE_s_s (oImportFilter, "import-filter", "@"),
ARGPARSE_s_s (oExportOptions, "export-options", "@"),
ARGPARSE_s_s (oListOptions, "list-options", "@"),
ARGPARSE_s_s (oVerifyOptions, "verify-options", "@"),
@@ -2033,6 +2035,7 @@ parse_tofu_db_format (const char *db_format)
}
}
+
/* This function called to initialized a new control object. It is
assumed that this object has been zeroed out before calling this
function. */
@@ -3031,6 +3034,11 @@ main (int argc, char **argv)
log_error(_("invalid import options\n"));
}
break;
+ case oImportFilter:
+ rc = parse_and_set_import_filter (pargs.r.ret_str);
+ if (rc)
+ log_error (_("invalid filter option: %s\n"), gpg_strerror (rc));
+ break;
case oExportOptions:
if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1))
{
diff --git a/g10/import.c b/g10/import.c
index 332e2667a..deb2787ea 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1,6 +1,6 @@
/* import.c - import a key into our key storage.
* Copyright (C) 1998-2007, 2010-2011 Free Software Foundation, Inc.
- * Copyright (C) 2014 Werner Koch
+ * Copyright (C) 2014, 2016 Werner Koch
*
* This file is part of GnuPG.
*
@@ -35,9 +35,13 @@
#include "i18n.h"
#include "ttyio.h"
#include "status.h"
+#include "recsel.h"
#include "keyserver-internal.h"
#include "call-agent.h"
#include "../common/membuf.h"
+#include "../common/init.h"
+#include "../common/mbox-util.h"
+
struct import_stats_s
{
@@ -60,6 +64,16 @@ struct import_stats_s
};
+/* A global variable to store the selector created from
+ * --import-filter keep-uid=EXPR.
+ *
+ * FIXME: We should put this into the CTRL object but that requires a
+ * lot more changes right now.
+ */
+static recsel_expr_t import_keep_uid;
+
+
+
static int import (ctrl_t ctrl,
IOBUF inp, const char* fname, struct import_stats_s *stats,
unsigned char **fpr, size_t *fpr_len, unsigned int options,
@@ -95,6 +109,16 @@ static int merge_sigs (kbnode_t dst, kbnode_t src, int *n_sigs,
static int merge_keysigs (kbnode_t dst, kbnode_t src, int *n_sigs,
const char *fname, u32 *keyid );
+
+
+static void
+cleanup_import_globals (void)
+{
+ recsel_release (import_keep_uid);
+ import_keep_uid = NULL;
+}
+
+
int
parse_import_options(char *str,unsigned int *options,int noisy)
{
@@ -143,6 +167,39 @@ parse_import_options(char *str,unsigned int *options,int noisy)
}
+/* Parse and set an import 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:
+ *
+ * - keep-uid :: If the expression evaluates to true for a certain
+ * user ID packet, that packet and all it dependencies
+ * will be imported. The expression may use these
+ * variables:
+ *
+ * - uid :: The entire user ID.
+ * - mbox :: The mail box part of the user ID.
+ * - primary :: Evaluate to true for the primary user ID.
+ */
+gpg_error_t
+parse_and_set_import_filter (const char *string)
+{
+ gpg_error_t err;
+
+ /* Auto register the cleanup function. */
+ register_mem_cleanup_func (cleanup_import_globals);
+
+ if (!strncmp (string, "keep-uid=", 9))
+ err = recsel_parse_expr (&import_keep_uid, string+9);
+ else
+ err = gpg_error (GPG_ERR_INV_NAME);
+
+ return err;
+}
+
+
+
import_stats_t
import_new_stats_handle (void)
{
@@ -983,6 +1040,74 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
}
+/* Helper for apply_keep_uid_filter. */
+static const char *
+filter_getval (void *cookie, const char *propname)
+{
+ kbnode_t node = cookie;
+ const char *result;
+
+ if (node->pkt->pkttype == PKT_USER_ID)
+ {
+ if (!strcmp (propname, "uid"))
+ result = node->pkt->pkt.user_id->name;
+ else if (!strcmp (propname, "mbox"))
+ {
+ if (!node->pkt->pkt.user_id->mbox)
+ {
+ node->pkt->pkt.user_id->mbox
+ = mailbox_from_userid (node->pkt->pkt.user_id->name);
+ }
+ return node->pkt->pkt.user_id->mbox;
+ }
+ else if (!strcmp (propname, "primary"))
+ result = node->pkt->pkt.user_id->is_primary? "1":"0";
+ else
+ result = NULL;
+ }
+ else
+ result = NULL;
+
+ return result;
+}
+
+/*
+ * Apply the keep-uid filter to the keyblock. The deleted nodes are
+ * marked and thus the caller should call commit_kbnode afterwards.
+ * KEYBLOCK must not have any blocks marked as deleted.
+ */
+static void
+apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
+{
+ kbnode_t node;
+
+ for (node = keyblock->next; node; node = node->next )
+ {
+ if (node->pkt->pkttype == PKT_USER_ID)
+ {
+ if (!recsel_select (selector, filter_getval, node))
+ {
+
+ /* log_debug ("keep-uid: deleting '%s'\n", */
+ /* node->pkt->pkt.user_id->name); */
+ /* The UID packet and all following packets up to the
+ * next UID or a subkey. */
+ delete_kbnode (node);
+ for (; node->next
+ && node->next->pkt->pkttype != PKT_USER_ID
+ && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY
+ && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ;
+ node = node->next)
+ delete_kbnode (node->next);
+ }
+ /* else */
+ /* log_debug ("keep-uid: keeping '%s'\n", */
+ /* node->pkt->pkt.user_id->name); */
+ }
+ }
+}
+
+
/*
* Try to import one keyblock. Return an error only in serious cases,
* but never for an invalid keyblock. It uses log_error to increase
@@ -1116,6 +1241,14 @@ import_one (ctrl_t ctrl,
/* Get rid of deleted nodes. */
commit_kbnode (&keyblock);
+ /* Apply import filter. */
+ if (import_keep_uid)
+ {
+ apply_keep_uid_filter (keyblock, import_keep_uid);
+ commit_kbnode (&keyblock);
+ }
+
+
/* Show the key in the form it is merged or inserted. We skip this
* if "import-export" is also active without --armor or the output
* file has explicily been given. */
diff --git a/g10/main.h b/g10/main.h
index 322f43c53..58f2a73f8 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -349,6 +349,7 @@ typedef struct import_stats_s *import_stats_t;
typedef gpg_error_t (*import_screener_t)(kbnode_t keyblock, void *arg);
int parse_import_options(char *str,unsigned int *options,int noisy);
+gpg_error_t parse_and_set_import_filter (const char *string);
void import_keys (ctrl_t ctrl, char **fnames, int nnames,
import_stats_t stats_hd, unsigned int options);
int import_keys_stream (ctrl_t ctrl, iobuf_t inp, import_stats_t stats_hd,