mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-28 22:49:59 +01:00
gpg: New option --import-filter
* g10/gpg.c (oImportFilter): New. (opts): Add --import-filter. (main): Handle option. * g10/import.c: Include recsel.h, init.h, and mbox-util.h. (import_keep_uid): New global var. (cleanup_import_globals): New. (parse_and_set_import_filter): New. (filter_getval): New. (apply_keep_uid_filter): New. (import_one): Apply filter if set. -- Funny new option. It can for example be used to export a key with only one user id: gpg --no-options --import --import-options import-export \ --import-filter keep-uid='mbox=wk@gnupg.org' \ < full-key.pub > key-with-one-uid.pub More features will eventually be added. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
f015552374
commit
5137bf73cc
39
doc/gpg.texi
39
doc/gpg.texi
@ -2218,6 +2218,45 @@ opposite meaning. The options are:
|
|||||||
Defaults to no.
|
Defaults to no.
|
||||||
@end table
|
@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}
|
@item --export-options @code{parameters}
|
||||||
@opindex export-options
|
@opindex export-options
|
||||||
This is a space or comma delimited string that gives options for
|
This is a space or comma delimited string that gives options for
|
||||||
|
@ -300,6 +300,7 @@ enum cmd_and_opt_values
|
|||||||
oKeyServer,
|
oKeyServer,
|
||||||
oKeyServerOptions,
|
oKeyServerOptions,
|
||||||
oImportOptions,
|
oImportOptions,
|
||||||
|
oImportFilter,
|
||||||
oExportOptions,
|
oExportOptions,
|
||||||
oListOptions,
|
oListOptions,
|
||||||
oVerifyOptions,
|
oVerifyOptions,
|
||||||
@ -572,6 +573,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
|
ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
|
||||||
ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"),
|
ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"),
|
||||||
ARGPARSE_s_s (oImportOptions, "import-options", "@"),
|
ARGPARSE_s_s (oImportOptions, "import-options", "@"),
|
||||||
|
ARGPARSE_s_s (oImportFilter, "import-filter", "@"),
|
||||||
ARGPARSE_s_s (oExportOptions, "export-options", "@"),
|
ARGPARSE_s_s (oExportOptions, "export-options", "@"),
|
||||||
ARGPARSE_s_s (oListOptions, "list-options", "@"),
|
ARGPARSE_s_s (oListOptions, "list-options", "@"),
|
||||||
ARGPARSE_s_s (oVerifyOptions, "verify-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
|
/* This function called to initialized a new control object. It is
|
||||||
assumed that this object has been zeroed out before calling this
|
assumed that this object has been zeroed out before calling this
|
||||||
function. */
|
function. */
|
||||||
@ -3031,6 +3034,11 @@ main (int argc, char **argv)
|
|||||||
log_error(_("invalid import options\n"));
|
log_error(_("invalid import options\n"));
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case oExportOptions:
|
||||||
if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1))
|
if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1))
|
||||||
{
|
{
|
||||||
|
135
g10/import.c
135
g10/import.c
@ -1,6 +1,6 @@
|
|||||||
/* import.c - import a key into our key storage.
|
/* import.c - import a key into our key storage.
|
||||||
* Copyright (C) 1998-2007, 2010-2011 Free Software Foundation, Inc.
|
* 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.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -35,9 +35,13 @@
|
|||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "ttyio.h"
|
#include "ttyio.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
#include "recsel.h"
|
||||||
#include "keyserver-internal.h"
|
#include "keyserver-internal.h"
|
||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
#include "../common/membuf.h"
|
#include "../common/membuf.h"
|
||||||
|
#include "../common/init.h"
|
||||||
|
#include "../common/mbox-util.h"
|
||||||
|
|
||||||
|
|
||||||
struct import_stats_s
|
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,
|
static int import (ctrl_t ctrl,
|
||||||
IOBUF inp, const char* fname, struct import_stats_s *stats,
|
IOBUF inp, const char* fname, struct import_stats_s *stats,
|
||||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
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,
|
static int merge_keysigs (kbnode_t dst, kbnode_t src, int *n_sigs,
|
||||||
const char *fname, u32 *keyid );
|
const char *fname, u32 *keyid );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_import_globals (void)
|
||||||
|
{
|
||||||
|
recsel_release (import_keep_uid);
|
||||||
|
import_keep_uid = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
parse_import_options(char *str,unsigned int *options,int noisy)
|
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_stats_t
|
||||||
import_new_stats_handle (void)
|
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,
|
* Try to import one keyblock. Return an error only in serious cases,
|
||||||
* but never for an invalid keyblock. It uses log_error to increase
|
* 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. */
|
/* Get rid of deleted nodes. */
|
||||||
commit_kbnode (&keyblock);
|
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
|
/* 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
|
* if "import-export" is also active without --armor or the output
|
||||||
* file has explicily been given. */
|
* file has explicily been given. */
|
||||||
|
@ -349,6 +349,7 @@ typedef struct import_stats_s *import_stats_t;
|
|||||||
typedef gpg_error_t (*import_screener_t)(kbnode_t keyblock, void *arg);
|
typedef gpg_error_t (*import_screener_t)(kbnode_t keyblock, void *arg);
|
||||||
|
|
||||||
int parse_import_options(char *str,unsigned int *options,int noisy);
|
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,
|
void import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
||||||
import_stats_t stats_hd, unsigned int options);
|
import_stats_t stats_hd, unsigned int options);
|
||||||
int import_keys_stream (ctrl_t ctrl, iobuf_t inp, import_stats_t stats_hd,
|
int import_keys_stream (ctrl_t ctrl, iobuf_t inp, import_stats_t stats_hd,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user