From a0cc6e01a8900b34cf231d8b5335ef3f85d01fdf Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 11 Aug 2017 19:13:44 +0200 Subject: [PATCH] g10: Add new delete operations that allow more flags. * NEWS: Document new interfaces. * doc/gpgme.texi: Document new interfaces. * src/gpgme.h.in (GPGME_DELETE_ALLOW_SECRET, GPGME_DELETE_FORCE, gpgme_op_delete_ext_start, gpgme_op_delete_ext): New. * src/delete.c (delete_start): Change allow_secret argument to flags. (gpgme_op_delete_ext, gpgme_op_delete_ext_start): New functions. * src/engine-backend.h (delete): Change allow_secret argument to flags. * src/engine.c (_gpgme_engine_op_delete): Likewise. * src/engine.h (_gpgme_engine_op_delete): Likewise (for prototype). * src/engine-gpgsm.c (gpgsm_delete): Likewise. * src/engine-gpg.c (gpg_delete): Likewise. Implement GPGME_DELETE_FORCE. * src/gpgme.def (gpgme_op_delete_ext, gpgme_op_delete_ext_start): New. * src/libgpgme.vers (gpgme_op_delete_ext, gpgme_op_delete_ext_start): New. Signed-off-by: Marcus Brinkmann GnuPG-bug-id: 2916 --- NEWS | 4 ++++ doc/gpgme.texi | 35 ++++++++++++++++++++++------ src/delete.c | 54 ++++++++++++++++++++++++++++++++++++++++---- src/engine-backend.h | 2 +- src/engine-gpg.c | 13 +++++++---- src/engine-gpgsm.c | 4 ++-- src/engine.c | 4 ++-- src/engine.h | 2 +- src/gpgme.def | 3 +++ src/gpgme.h.in | 9 ++++++++ src/libgpgme.vers | 2 ++ 11 files changed, 110 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index e193e003..24cf4836 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ Noteworthy changes in version 1.9.1 (unreleased) gpgme_decrypt_result_t EXTENDED: New field 'is_de_vs'. gpgme_signature_t EXTENDED: New field 'is_de_vs'. + gpgme_op_delete_ext NEW + gpgme_op_delete_ext_start NEW + GPGME_DELETE_ALLOW_SECRET NEW + GPGME_DELETE_FORCE NEW cpp: DecryptionResult::isDeVs NEW. cpp: Signature::isDeVs NEW. py: DecryptResult EXTENDED: New boolean field 'is_de_vs'. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index bf846293..78859cd1 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -4600,11 +4600,20 @@ operation is started on the context. @cindex key, delete @cindex key ring, delete from -@deftypefun gpgme_error_t gpgme_op_delete (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) -The function @code{gpgme_op_delete} deletes the key @var{key} from the -key ring of the crypto engine used by @var{ctx}. If -@var{allow_secret} is @code{0}, only public keys are deleted, -otherwise secret keys are deleted as well, if that is supported. +@deftypefun gpgme_error_t gpgme_op_delete_ext (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{unsigned int @var{flags}}) +The function @code{gpgme_op_delete_ext} deletes the key @var{key} from +the key ring of the crypto engine used by @var{ctx}. + +@var{flags} can be set to the bit-wise OR of the following flags: + +@table @code +@item GPGME_DELETE_ALLOW_SECRET +If not set, only public keys are deleted. If set, secret keys are +deleted as well, if that is supported. + +@item GPGME_DELETE_FORCE +If set, the user is not asked to confirm the deletion. +@end table The function returns the error code @code{GPG_ERR_NO_ERROR} if the key was deleted successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} or @@ -4615,8 +4624,8 @@ unambiguously, and @code{GPG_ERR_CONFLICT} if the secret key for @var{key} is available, but @var{allow_secret} is zero. @end deftypefun -@deftypefun gpgme_error_t gpgme_op_delete_start (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) -The function @code{gpgme_op_delete_start} initiates a +@deftypefun gpgme_error_t gpgme_op_delete_ext_start (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{unsigned int @var{flags}}) +The function @code{gpgme_op_delete_ext_start} initiates a @code{gpgme_op_delete} operation. It can be completed by calling @code{gpgme_wait} on the context. @xref{Waiting For Completion}. @@ -4625,6 +4634,18 @@ operation was started successfully, and @code{GPG_ERR_INV_VALUE} if @var{ctx} or @var{key} is not a valid pointer. @end deftypefun +The following functions allow only to use one particular flag. + +@deftypefun gpgme_error_t gpgme_op_delete (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) +Similar to @code{gpgme_op_delete_ext}, but only the flag +@code{GPGME_DELETE_ALLOW_SECRET} can be provided. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_delete_start (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) +Similar to @code{gpgme_op_delete_ext_start}, but only the flag +@code{GPGME_DELETE_ALLOW_SECRET} can be provided. +@end deftypefun + @node Changing Passphrases @subsection Changing Passphrases diff --git a/src/delete.c b/src/delete.c index fc99aacf..1bf1cb48 100644 --- a/src/delete.c +++ b/src/delete.c @@ -108,7 +108,7 @@ delete_status_handler (void *priv, gpgme_status_code_t code, char *args) static gpgme_error_t delete_start (gpgme_ctx_t ctx, int synchronous, const gpgme_key_t key, - int allow_secret) + unsigned int flags) { gpgme_error_t err; @@ -118,7 +118,7 @@ delete_start (gpgme_ctx_t ctx, int synchronous, const gpgme_key_t key, _gpgme_engine_set_status_handler (ctx->engine, delete_status_handler, ctx); - return _gpgme_engine_op_delete (ctx->engine, key, allow_secret); + return _gpgme_engine_op_delete (ctx->engine, key, flags); } @@ -130,7 +130,7 @@ gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, { gpgme_error_t err; - TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete", ctx, + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete_start", ctx, "key=%p (%s), allow_secret=%i", key, (key->subkeys && key->subkeys->fpr) ? key->subkeys->fpr : "invalid", allow_secret); @@ -138,7 +138,8 @@ gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = delete_start (ctx, 0, key, allow_secret); + err = delete_start (ctx, 0, key, + allow_secret ? GPGME_DELETE_ALLOW_SECRET : 0); return TRACE_ERR (err); } @@ -158,7 +159,50 @@ gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret) if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = delete_start (ctx, 1, key, allow_secret); + err = delete_start (ctx, 1, key, + allow_secret ? GPGME_DELETE_ALLOW_SECRET : 0); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +/* Delete KEY from the keyring. */ +gpgme_error_t +gpgme_op_delete_ext_start (gpgme_ctx_t ctx, const gpgme_key_t key, + unsigned int flags) +{ + gpgme_error_t err; + + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete_ext_start", ctx, + "key=%p (%s), flags=0x%x", key, + (key->subkeys && key->subkeys->fpr) ? + key->subkeys->fpr : "invalid", flags); + + if (!ctx) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + err = delete_start (ctx, 0, key, flags); + return TRACE_ERR (err); +} + + +/* Delete KEY from the keyring. */ +gpgme_error_t +gpgme_op_delete_ext (gpgme_ctx_t ctx, const gpgme_key_t key, + unsigned int flags) +{ + gpgme_error_t err; + + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete_ext", ctx, + "key=%p (%s), flags=0x%x", key, + (key->subkeys && key->subkeys->fpr) ? + key->subkeys->fpr : "invalid", flags); + + if (!ctx) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + err = delete_start (ctx, 1, key, flags); if (!err) err = _gpgme_wait_one (ctx); return err; diff --git a/src/engine-backend.h b/src/engine-backend.h index 53af6622..90328ecb 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -66,7 +66,7 @@ struct engine_ops gpgme_data_t ciph, gpgme_data_t plain, int export_session_key, const char *override_session_key); - gpgme_error_t (*delete) (void *engine, gpgme_key_t key, int allow_secret); + gpgme_error_t (*delete) (void *engine, gpgme_key_t key, unsigned int flags); gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key, gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */); gpgme_error_t (*encrypt) (void *engine, gpgme_key_t recp[], diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 0c3a63ee..c749c972 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1628,13 +1628,18 @@ gpg_decrypt (void *engine, } static gpgme_error_t -gpg_delete (void *engine, gpgme_key_t key, int allow_secret) +gpg_delete (void *engine, gpgme_key_t key, unsigned int flags) { engine_gpg_t gpg = engine; - gpgme_error_t err; + gpgme_error_t err = 0; + int allow_secret = flags & GPGME_DELETE_ALLOW_SECRET; + int force = flags & GPGME_DELETE_FORCE; - err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key" - : "--delete-key"); + if (force) + err = add_arg (gpg, "--yes"); + if (!err) + err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key" + : "--delete-key"); if (!err) err = add_arg (gpg, "--"); if (!err) diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index c3d5427f..a0fcb1f4 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1162,7 +1162,7 @@ gpgsm_decrypt (void *engine, static gpgme_error_t -gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret) +gpgsm_delete (void *engine, gpgme_key_t key, unsigned int flags) { engine_gpgsm_t gpgsm = engine; gpgme_error_t err; @@ -1171,7 +1171,7 @@ gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret) char *line; int length = 8; /* "DELKEYS " */ - (void)allow_secret; + (void)flags; if (!fpr) return gpg_error (GPG_ERR_INV_VALUE); diff --git a/src/engine.c b/src/engine.c index 278916d4..89a8552c 100644 --- a/src/engine.c +++ b/src/engine.c @@ -671,7 +671,7 @@ _gpgme_engine_op_decrypt (engine_t engine, gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, - int allow_secret) + unsigned int flags) { if (!engine) return gpg_error (GPG_ERR_INV_VALUE); @@ -679,7 +679,7 @@ _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, if (!engine->ops->delete) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->delete) (engine->engine, key, allow_secret); + return (*engine->ops->delete) (engine->engine, key, flags); } diff --git a/src/engine.h b/src/engine.h index dd0ef9c2..d25c1fa6 100644 --- a/src/engine.h +++ b/src/engine.h @@ -90,7 +90,7 @@ gpgme_error_t _gpgme_engine_op_decrypt (engine_t engine, int export_session_key, const char *override_session_key); gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, - int allow_secret); + unsigned int flags); gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key, gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */); diff --git a/src/gpgme.def b/src/gpgme.def index 51053cd9..a8918122 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -262,5 +262,8 @@ EXPORTS gpgme_op_decrypt_ext @195 gpgme_op_decrypt_ext_start @196 + gpgme_op_delete_ext @197 + gpgme_op_delete_ext_start @198 + ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 867219a4..29cda2c6 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1788,6 +1788,15 @@ gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret); +/* Flags for the key delete functions. */ +#define GPGME_DELETE_ALLOW_SECRET (1 << 0) /* Also delete secret key. */ +#define GPGME_DELETE_FORCE (1 << 1) /* Do not ask user to confirm. */ + +gpgme_error_t gpgme_op_delete_ext_start (gpgme_ctx_t ctx, const gpgme_key_t key, + unsigned int flags); +gpgme_error_t gpgme_op_delete_ext (gpgme_ctx_t ctx, const gpgme_key_t key, + unsigned int flags); + /* * Key signing interface diff --git a/src/libgpgme.vers b/src/libgpgme.vers index adc8d7d4..9a74b76f 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -209,6 +209,8 @@ GPGME_1.0 { gpgme_op_decrypt_verify_start; gpgme_op_delete; gpgme_op_delete_start; + gpgme_op_delete_ext; + gpgme_op_delete_ext_start; gpgme_op_edit; gpgme_op_edit_start; gpgme_op_encrypt;