aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2020-10-27 14:33:51 +0000
committerIngo Klöcker <[email protected]>2020-10-29 11:57:10 +0000
commitf3407d0ee4e34ed33be18de5f886a4da2affbf9f (patch)
treeffdd4777a07af84a034e58b0c9459e37013a61d7 /src
parentpython: Handle the when case __doc__ is None. (diff)
downloadgpgme-f3407d0ee4e34ed33be18de5f886a4da2affbf9f.tar.gz
gpgme-f3407d0ee4e34ed33be18de5f886a4da2affbf9f.zip
core: New function gpgme_op_revsig.
* src/gpgme.h.in (gpgme_op_revsig_start, gpgme_op_revsig): New. (GPGME_REVSIG_LFSEP): New. * src/context.h (ctx_op_data_id_t): Add OPDATA_REVSIG. * src/revsig.c: New. * src/Makefile.am (main_sources): Add revsig. * src/libgpgme.vers, src/gpgme.def: Add gpgme_op_revsig and gpgme_op_revsig_start. * src/engine.h, src/engine.c: (_gpgme_engine_op_revsig): New. * src/engine-backend.h (engine_ops): Add 'revsig' and adjust all engine initializers. * src/engine-gpg.c (gpg_revsig): New. (_gpgme_engine_ops_gpg): Set revsig to gpg_revsig. * doc/gpgme.texi: Document new functions. * tests/run-keysign.c: Add option --revoke. -- This extends GPGME to support the --quick-revoke-sig command added by GnuPG 2.2.24. This allows revoking key signatures. GnuPG-bug-id: 5094
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/context.h2
-rw-r--r--src/engine-assuan.c1
-rw-r--r--src/engine-backend.h3
-rw-r--r--src/engine-g13.c1
-rw-r--r--src/engine-gpg.c47
-rw-r--r--src/engine-gpgconf.c1
-rw-r--r--src/engine-gpgsm.c1
-rw-r--r--src/engine-spawn.c1
-rw-r--r--src/engine-uiserver.c1
-rw-r--r--src/engine.c14
-rw-r--r--src/engine.h5
-rw-r--r--src/gpgme.def3
-rw-r--r--src/gpgme.h.in14
-rw-r--r--src/libgpgme.vers3
-rw-r--r--src/revsig.c203
16 files changed, 300 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1061995c..35add9c8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@ main_sources = \
encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
sign.c passphrase.c progress.c \
key.c keylist.c keysign.c trust-item.c trustlist.c tofupolicy.c \
+ revsig.c \
import.c export.c genkey.c delete.c edit.c getauditlog.c \
setexpire.c \
opassuan.c passwd.c spawn.c assuan-support.c \
diff --git a/src/context.h b/src/context.h
index 7f745a52..3ed38188 100644
--- a/src/context.h
+++ b/src/context.h
@@ -39,7 +39,7 @@ typedef enum
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
OPDATA_PASSWD, OPDATA_EXPORT, OPDATA_KEYSIGN, OPDATA_TOFU_POLICY,
- OPDATA_QUERY_SWDB, OPDATA_SETEXPIRE
+ OPDATA_QUERY_SWDB, OPDATA_SETEXPIRE, OPDATA_REVSIG
} ctx_op_data_id_t;
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index eb6d2a8e..ab9d05a9 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -833,6 +833,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
NULL, /* keylist_ext */
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* verify */
diff --git a/src/engine-backend.h b/src/engine-backend.h
index 791dd3f9..8f90b6c7 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -108,6 +108,9 @@ struct engine_ops
gpgme_key_t key, const char *userid,
unsigned long expires, unsigned int flags,
gpgme_ctx_t ctx);
+ gpgme_error_t (*revsig) (void *engine,
+ gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags);
gpgme_error_t (*tofu_policy) (void *engine,
gpgme_key_t key,
gpgme_tofu_policy_t policy);
diff --git a/src/engine-g13.c b/src/engine-g13.c
index 82f26305..3c111496 100644
--- a/src/engine-g13.c
+++ b/src/engine-g13.c
@@ -804,6 +804,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
NULL, /* keylist_ext */
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* verify */
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 8832572a..02a10ecb 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -3211,6 +3211,52 @@ gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
static gpgme_error_t
+gpg_revsig (void *engine, gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+ const char *s;
+
+ if (!key || !key->fpr)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (!have_gpg_version (gpg, "2.2.24"))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ err = add_arg (gpg, "--quick-revoke-sig");
+
+ if (!err)
+ err = add_arg (gpg, "--");
+
+ if (!err)
+ err = add_arg (gpg, key->fpr);
+
+ if (!err)
+ err = add_arg (gpg, signing_key->fpr);
+
+ if (!err && userid)
+ {
+ if ((flags & GPGME_REVSIG_LFSEP))
+ {
+ for (; !err && (s = strchr (userid, '\n')); userid = s + 1)
+ if ((s - userid))
+ err = add_arg_len (gpg, "=", userid, s - userid);
+ if (!err && *userid)
+ err = add_arg_pfx (gpg, "=", userid);
+ }
+ else
+ err = add_arg_pfx (gpg, "=", userid);
+ }
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy)
{
engine_gpg_t gpg = engine;
@@ -3513,6 +3559,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
gpg_keylist_ext,
gpg_keylist_data,
gpg_keysign,
+ gpg_revsig,
gpg_tofu_policy, /* tofu_policy */
gpg_sign,
gpg_verify,
diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c
index fba8f23b..28f91158 100644
--- a/src/engine-gpgconf.c
+++ b/src/engine-gpgconf.c
@@ -1302,6 +1302,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
NULL, /* keylist_ext */
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* verify */
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index 37022421..d5f0d7a9 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -2322,6 +2322,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
gpgsm_keylist_ext,
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
gpgsm_sign,
gpgsm_verify,
diff --git a/src/engine-spawn.c b/src/engine-spawn.c
index 4025b83a..368280f3 100644
--- a/src/engine-spawn.c
+++ b/src/engine-spawn.c
@@ -464,6 +464,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
NULL, /* keylist_ext */
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* verify */
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index 3693dc3b..9fce1de4 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -1435,6 +1435,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
NULL, /* keylist_ext */
NULL, /* keylist_data */
NULL, /* keysign */
+ NULL, /* revsig */
NULL, /* tofu_policy */
uiserver_sign,
uiserver_verify,
diff --git a/src/engine.c b/src/engine.c
index aeb30c67..8280c520 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -825,6 +825,20 @@ _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
gpgme_error_t
+_gpgme_engine_op_revsig (engine_t engine, gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->revsig)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->revsig) (engine->engine, key, signing_key, userid, flags);
+}
+
+
+gpgme_error_t
_gpgme_engine_op_tofu_policy (engine_t engine,
gpgme_key_t key, gpgme_tofu_policy_t policy)
{
diff --git a/src/engine.h b/src/engine.h
index 74082851..d7ff542c 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -131,6 +131,11 @@ gpgme_error_t _gpgme_engine_op_keysign (engine_t engine,
unsigned long expires,
unsigned int flags,
gpgme_ctx_t ctx);
+gpgme_error_t _gpgme_engine_op_revsig (engine_t engine,
+ gpgme_key_t key,
+ gpgme_key_t signing_key,
+ const char *userid,
+ unsigned int flags);
gpgme_error_t _gpgme_engine_op_tofu_policy (engine_t engine,
gpgme_key_t key,
gpgme_tofu_policy_t policy);
diff --git a/src/gpgme.def b/src/gpgme.def
index 6666a1c7..6644caef 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -277,5 +277,8 @@ EXPORTS
gpgme_op_setexpire @205
gpgme_op_setexpire_start @206
+ gpgme_op_revsig @207
+ gpgme_op_revsig_start @208
+
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index d1bc30de..ec2b3b0d 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1919,6 +1919,20 @@ gpgme_error_t gpgme_op_keysign (gpgme_ctx_t ctx,
unsigned int flags);
+/* Flags for the signature revoking functions. */
+#define GPGME_REVSIG_LFSEP (1 << 8) /* Indicate LF separated user ids. */
+
+/* Revoke the signatures made with SIGNING_KEY on the USERID(s) of KEY. */
+gpgme_error_t gpgme_op_revsig_start (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ gpgme_key_t signing_key,
+ const char *userid,
+ unsigned int flags);
+gpgme_error_t gpgme_op_revsig (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ gpgme_key_t signing_key,
+ const char *userid,
+ unsigned int flags);
/*
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index a740b72d..8e86e4e4 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -276,6 +276,9 @@ GPGME_1.0 {
gpgme_op_setexpire;
gpgme_op_setexpire_start;
+ gpgme_op_revsig;
+ gpgme_op_revsig_start;
+
local:
*;
diff --git a/src/revsig.c b/src/revsig.c
new file mode 100644
index 00000000..8c61f730
--- /dev/null
+++ b/src/revsig.c
@@ -0,0 +1,203 @@
+/* revsig.c - Revoke signature helpers.
+ * Copyright (C) 2020 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <https://gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+
+#include "gpgme.h"
+#include "debug.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
+ /* The error code from certain ERROR status lines or 0. */
+ gpg_error_t error_code;
+
+} *op_data_t;
+
+
+/* Parse an error status line. Return the error location and the
+ error code. The function may modify ARGS. */
+static char *
+parse_error (char *args, gpg_error_t *r_err)
+{
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ {
+ *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ return NULL;
+ }
+
+ *r_err = atoi (which);
+
+ return where;
+}
+
+
+static gpgme_error_t
+revsig_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ char *loc;
+
+ /* Pipe the status code through the progress status handler. */
+ err = _gpgme_progress_status_handler (ctx, code, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_REVSIG, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_ERROR:
+ loc = parse_error (args, &err);
+ if (!loc)
+ return err;
+ if (!opd->error_code)
+ opd->error_code = err;
+ break;
+
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
+ case GPGME_STATUS_EOF:
+ if (opd->error_code)
+ return opd->error_code;
+ else if (opd->failure_code)
+ return opd->failure_code;
+ break;
+
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ if (ctx->status_cb && !ctx->full_status)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
+ if (err)
+ return err;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+/* Revoke the signature(s) on USERID of KEY made with SIGNING_KEY.
+ * If USERID is NULL, revoke signatures on all user ids. To put several
+ * user ids into USERID, separate them by LF and set the flag
+ * GPGME_REVSIG_LFSEP. */
+static gpgme_error_t
+revsig_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+ return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ if (!key)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_REVSIG, &hook, sizeof (*opd),
+ NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, revsig_status_handler, ctx);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx);
+ if (err)
+ return err;
+ }
+
+ return _gpgme_engine_op_revsig (ctx->engine, key, signing_key, userid, flags);
+}
+
+
+gpgme_error_t
+gpgme_op_revsig_start (gpgme_ctx_t ctx, gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG (DEBUG_CTX, "gpgme_op_revsig_start", ctx,
+ "key=%p, uid='%s' flags=0x%x", key, userid, flags);
+
+ err = revsig_start (ctx, 0, key, signing_key, userid, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_revsig (gpgme_ctx_t ctx, gpgme_key_t key, gpgme_key_t signing_key,
+ const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG (DEBUG_CTX, "gpgme_op_revsig", ctx,
+ "key=%p, uid='%s' flags=0x%x", key, userid, flags);
+
+ err = revsig_start (ctx, 1, key, signing_key, userid, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}