From f7700a016926f0d8e9cb3c0337837deb7fe01079 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Apr 2018 09:17:27 +0200 Subject: core: Add new context flag "no-symkey-cache". * src/gpgme.c (gpgme_set_ctx_flag): Set flag. (gpgme_get_ctx_flag): Get flag. * src/context.h (struct gpgme_context): Add field no_symkey_cache. * src/engine-gpg.c (struct engine_gpg): Ditto. (gpg_set_engine_flags): Set flag. (build_argv): Pass option --no-symkey-cache to gpg. * tests/run-decrypt.c (print_result): Fix segv for symmetric messages. (main): New option --no-symkey-cache. * tests/run-encrypt.c (main): New option --no-symkey-cache. Signed-off-by: Werner Koch --- src/context.h | 3 +++ src/engine-gpg.c | 23 ++++++++++++++++++++++- src/gpgme.c | 8 ++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/context.h b/src/context.h index 202cf168..c8e75ba0 100644 --- a/src/context.h +++ b/src/context.h @@ -121,6 +121,9 @@ struct gpgme_context /* True if the option --auto-key-retrieve shall be passed to gpg. */ unsigned int auto_key_retrieve : 1; + /* Do not use the symmtric encryption passphrase cache. */ + unsigned int no_symkey_cache : 1; + /* Flags for keylist mode. */ gpgme_keylist_mode_t keylist_mode; diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 3b9a6ff5..a37d1f7b 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -145,6 +145,10 @@ struct engine_gpg gpgme_pinentry_mode_t pinentry_mode; char request_origin[10]; + struct { + unsigned int no_symkey_cache : 1; + } flags; + /* NULL or the data object fed to --override_session_key-fd. */ gpgme_data_t override_session_key; }; @@ -642,6 +646,10 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx) else strcpy (gpg->request_origin, ctx->request_origin); } + else if (ctx->no_symkey_cache && have_gpg_version (gpg, "2.2.7")) + { + gpg->flags.no_symkey_cache = 1; + } else *gpg->request_origin = 0; } @@ -875,7 +883,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; if (!gpg->cmd.used) argc++; /* --batch */ - argc += 2; /* --no-sk-comments, --request-origin */ + argc += 3; /* --no-sk-comments, --request-origin, --no-symkey-cache */ argv = calloc (argc + 1, sizeof *argv); if (!argv) @@ -937,6 +945,19 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; } + if (gpg->flags.no_symkey_cache) + { + argv[argc] = strdup ("--no-symkey-cache"); + if (!argv[argc]) + { + int saved_err = gpg_error_from_syserror (); + free (fd_data_map); + free_argv (argv); + return saved_err; + } + argc++; + } + if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0")) { const char *s = NULL; diff --git a/src/gpgme.c b/src/gpgme.c index 9e65c50a..82d67478 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -538,6 +538,10 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value) if (!ctx->request_origin) err = gpg_error_from_syserror (); } + else if (!strcmp (name, "no-symkey-cache")) + { + ctx->no_symkey_cache = abool; + } else err = gpg_error (GPG_ERR_UNKNOWN_NAME); @@ -583,6 +587,10 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name) { return ctx->request_origin? ctx->request_origin : ""; } + else if (!strcmp (name, "no-symkey-cache")) + { + return ctx->no_symkey_cache? "1":""; + } else return NULL; } -- cgit v1.2.3 From 478d1650bbef84958ccce439fac982ef57b16cd0 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Apr 2018 20:26:00 +0200 Subject: core: For a failed verification return the sig's fingerprint. * src/verify.c (parse_new_sig): Parse the new ERRSIG fpr. -- This works only when the signatures features an ISSUER_FPR sub-packet and with GnuPG >= 2.2.7. If that is not the case the keyid is kept in the FPR field. Signed-off-by: Werner Koch --- src/verify.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/verify.c b/src/verify.c index ee730a34..4eab902b 100644 --- a/src/verify.c +++ b/src/verify.c @@ -284,6 +284,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args, gpgme_signature_t sig; char *end = strchr (args, ' '); char *tail; + int got_fpr = 0; if (end) { @@ -370,7 +371,23 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args, if (!*end) goto parse_err_sig_fail; - sig->status = strtoul (end, NULL, 10); + gpg_err_set_errno (0); + sig->status = strtoul (end, &tail, 10); + if (errno || end == tail || (*tail && *tail != ' ')) + goto parse_err_sig_fail; + if (!*tail) + goto parse_err_sig_ok; + end = tail; + while (*end == ' ') + end++; + + /* Parse the new fingerprint (from the ISSUER_FPR subpacket). */ + if (!*end || (*end == '-' && (end[1] == ' ' || !end[1]))) + goto parse_err_sig_ok; /* Okay (just trailing spaces). */ + sig->fpr = strdup (end); + if (!sig->fpr) + return gpg_error_from_syserror (); + got_fpr = 1; goto parse_err_sig_ok; parse_err_sig_fail: @@ -382,7 +399,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args, return gpg_error (GPG_ERR_GENERAL); } - if (*args) + if (*args && !got_fpr) { sig->fpr = strdup (args); if (!sig->fpr) -- cgit v1.2.3 From b99502274ae5efdf6df0d967900ec3d1e64373d7 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Apr 2018 20:36:30 +0200 Subject: core: Tweak STATUS_FAILURE handling. * src/op-support.c (_gpgme_parse_failure): Ignore failures with location "gpg-exit". * tests/gpg/t-verify.c (main): Adjust for the now working checking of the second key. Signed-off-by: Werner Koch --- src/op-support.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/op-support.c b/src/op-support.c index 43cb1c76..e55875f9 100644 --- a/src/op-support.c +++ b/src/op-support.c @@ -400,7 +400,13 @@ _gpgme_parse_plaintext (char *args, char **filenamep) /* Parse a FAILURE status line and return the error code. ARGS is - modified to contain the location part. */ + * modified to contain the location part. Note that for now we ignore + * failure codes with a location of gpg-exit; they are too trouble + * some. Instead we should eventually record that error in the + * context and provide a function to return a fuller error + * description; this could then also show the location of the error + * (e.g. "option- parser") to make it easier for the user to detect + * the actual error. */ gpgme_error_t _gpgme_parse_failure (char *args) { @@ -418,6 +424,8 @@ _gpgme_parse_failure (char *args) *where = '\0'; where = args; + if (!strcmp (where, "gpg-exit")) + return 0; return atoi (which); } -- cgit v1.2.3 From a1f76b3b54b75a150fe272b804d85ffd40a507a6 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 08:33:44 +0200 Subject: core: Add extended versions of the encrypt functions. * src/gpgme.h.in (gpgme_op_encrypt_ext_start) New. (gpgme_op_encrypt_ext): New. (gpgme_op_encrypt_sign_ext_start): New. (gpgme_op_encrypt_sign_ext): New. * src/libgpgme.vers, tests/run-encrypt.c: Add them. * src/encrypt.c (encrypt_start): Add arg recpstring. (gpgme_op_encrypt): Factor code out to ... (gpgme_op_encrypt_ext): new function with new arg recpstring. (gpgme_op_encrypt_start): Factor code out to ... (gpgme_op_encrypt_ext_start): new function with new arg recpstring. * src/encrypt-sign.c (encrypt_sign_start): Add arg recpstring. (gpgme_op_encrypt_sign): Factor code out to ... (gpgme_op_encrypt_sign_ext): new function with new arg recpstring. (gpgme_op_encrypt_sign_start): Factor code out to ... (gpgme_op_encrypt_sign_ext_start): new function with new arg recpstring. * src/engine-backend.h (struct engine_ops): Change fields encrypt and encrypt_sign. * src/engine.c (_gpgme_engine_op_encrypt): Add arg recpstring and pass to engine. (_gpgme_engine_op_encrypt_sign): Ditto. * src/engine-gpg.c (append_args_from_recipients_string): New. (gpg_encrypt): Add arg recpstring and call new function as needed. (gpg_encrypt_sign): Ditto. * src/engine-gpgsm.c (set_recipients_from_string): New. (gpgsm_encrypt): Add arg recpstring and call new function as needed. * src/engine-uiserver.c (set_recipients_from_string): New. (uiserver_encrypt): Add arg recpstring and call new function as needed. * tests/run-encrypt.c (xstrdup): New. (main): Add option --keystring. * src/gpgme-json.c (get_keys): Simplify. (op_encrypt): Modify to make use of the extended encrypt function. -- This new feature can be used to avoid the need for a key lookup and thus several extra calls to the backend. Note that run-test uses a semicolon as delimiter because that make testing the feature on the command line much easier. Signed-off-by: Werner Koch --- src/encrypt-sign.c | 111 ++++++++++++++++++++++++++++++++++---------------- src/encrypt.c | 106 ++++++++++++++++++++++++++++++++--------------- src/engine-backend.h | 2 + src/engine-gpg.c | 70 +++++++++++++++++++++++++++---- src/engine-gpgsm.c | 58 ++++++++++++++++++++++++-- src/engine-uiserver.c | 59 +++++++++++++++++++++++++-- src/engine.c | 10 +++-- src/engine.h | 2 + src/gpgme-json.c | 74 ++++++++++++++++----------------- src/gpgme.def | 5 +++ src/gpgme.h.in | 30 ++++++++++++-- src/libgpgme.vers | 9 +++- 12 files changed, 405 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/encrypt-sign.c b/src/encrypt-sign.c index af6de63e..4db46e25 100644 --- a/src/encrypt-sign.c +++ b/src/encrypt-sign.c @@ -62,6 +62,7 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args) static gpgme_error_t encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher) { @@ -72,7 +73,7 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], if (err) return err; - symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC); + symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC); if (!plain) return gpg_error (GPG_ERR_NO_DATA); @@ -103,43 +104,75 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], : encrypt_sign_status_handler, ctx); - return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, flags, plain, + return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, recpstring, + flags, plain, cipher, ctx->use_armor, ctx /* FIXME */); } -/* Encrypt plaintext PLAIN within CTX for the recipients RECP and - store the resulting ciphertext in CIPHER. Also sign the ciphertext - with the signers in CTX. */ +/* Old version of gpgme_op_encrypt_sign_ext_start w/o RECPSTRING. */ gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher) +{ + return gpgme_op_encrypt_sign_ext_start (ctx, recp, NULL, + flags, plain, cipher); +} + + +/* Old version of gpgme_op_encrypt_sign_ext w/o RECPSTRING. */ +gpgme_error_t +gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + return gpgme_op_encrypt_sign_ext (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + * store the resulting ciphertext in CIPHER. Also sign the ciphertext + * with the signers in CTX. */ +gpgme_error_t +gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) { gpgme_error_t err; - TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx, + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign", ctx, "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - if (_gpgme_debug_trace () && recp) + if (_gpgme_debug_trace () && (recp || recpstring)) { - int i = 0; - - while (recp[i]) - { - TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], - (recp[i]->subkeys && recp[i]->subkeys->fpr) ? - recp[i]->subkeys->fpr : "invalid"); - i++; - } + if (recp) + { + int i = 0; + + while (recp[i]) + { + TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], + (recp[i]->subkeys && recp[i]->subkeys->fpr) ? + recp[i]->subkeys->fpr : "invalid"); + i++; + } + } + else + { + TRACE_LOG1 ("recipients = '%s'", recpstring); + } } - err = encrypt_sign_start (ctx, 0, recp, flags, plain, cipher); - return err; + err = encrypt_sign_start (ctx, 1, recp, recpstring, flags, plain, cipher); + if (!err) + err = _gpgme_wait_one (ctx); + return TRACE_ERR (err); } @@ -147,33 +180,39 @@ gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[], store the resulting ciphertext in CIPHER. Also sign the ciphertext with the signers in CTX. */ gpgme_error_t -gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], - gpgme_encrypt_flags_t flags, - gpgme_data_t plain, gpgme_data_t cipher) +gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) { gpgme_error_t err; - TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign", ctx, + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx, "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - if (_gpgme_debug_trace () && recp) + if (_gpgme_debug_trace () && (recp || recpstring)) { - int i = 0; - - while (recp[i]) - { - TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], - (recp[i]->subkeys && recp[i]->subkeys->fpr) ? - recp[i]->subkeys->fpr : "invalid"); - i++; - } + if (recp) + { + int i = 0; + + while (recp[i]) + { + TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], + (recp[i]->subkeys && recp[i]->subkeys->fpr) ? + recp[i]->subkeys->fpr : "invalid"); + i++; + } + } + else + { + TRACE_LOG1 ("recipients = '%s'", recpstring); + } } - err = encrypt_sign_start (ctx, 1, recp, flags, plain, cipher); - if (!err) - err = _gpgme_wait_one (ctx); - return TRACE_ERR (err); + err = encrypt_sign_start (ctx, 0, recp, recpstring, flags, plain, cipher); + return err; } diff --git a/src/encrypt.c b/src/encrypt.c index 40236544..2318497e 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -214,6 +214,7 @@ _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx) static gpgme_error_t encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher) { @@ -228,13 +229,13 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], if (err) return err; - symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC); + symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC); if (!plain) return gpg_error (GPG_ERR_NO_DATA); if (!cipher) return gpg_error (GPG_ERR_INV_VALUE); - if (recp && ! *recp) + if (recp && !*recp) return gpg_error (GPG_ERR_INV_VALUE); if (symmetric && ctx->passphrase_cb) @@ -252,72 +253,111 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], : encrypt_status_handler, ctx); - return _gpgme_engine_op_encrypt (ctx->engine, recp, flags, plain, cipher, - ctx->use_armor); + return _gpgme_engine_op_encrypt (ctx->engine, recp, recpstring, + flags, plain, cipher, ctx->use_armor); } +/* Old version of gpgme_op_encrypt_ext without RECPSTRING. */ +gpgme_error_t +gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + return gpgme_op_encrypt_ext (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Old version of gpgme_op_encrypt_ext_start without RECPSTRING. */ gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher) +{ + return gpgme_op_encrypt_ext_start (ctx, recp, NULL, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + * store the resulting ciphertext in CIPHER. RECPSTRING can be used + * instead of the RECP array to directly specify recipients as LF + * delimited strings; these may be any kind of recipient specification + * patterns as supported by the backend. */ +gpgme_error_t +gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) { gpgme_error_t err; - TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx, + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt", ctx, "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - if (_gpgme_debug_trace () && recp) + if (_gpgme_debug_trace () && (recp || recpstring)) { - int i = 0; + if (recp) + { + int i = 0; - while (recp[i]) - { - TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], + while (recp[i]) + { + TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], (recp[i]->subkeys && recp[i]->subkeys->fpr) ? - recp[i]->subkeys->fpr : "invalid"); - i++; - } + recp[i]->subkeys->fpr : "invalid"); + i++; + } + } + else + { + TRACE_LOG1 ("recipients = '%s'", recpstring); + } } - err = encrypt_start (ctx, 0, recp, flags, plain, cipher); + err = encrypt_start (ctx, 1, recp, recpstring, flags, plain, cipher); + if (!err) + err = _gpgme_wait_one (ctx); return TRACE_ERR (err); } -/* Encrypt plaintext PLAIN within CTX for the recipients RECP and - store the resulting ciphertext in CIPHER. */ gpgme_error_t -gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], - gpgme_encrypt_flags_t flags, - gpgme_data_t plain, gpgme_data_t cipher) +gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) { gpgme_error_t err; - TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt", ctx, + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx, "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - if (_gpgme_debug_trace () && recp) + if (_gpgme_debug_trace () && (recp || recpstring)) { - int i = 0; - - while (recp[i]) - { - TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], - (recp[i]->subkeys && recp[i]->subkeys->fpr) ? - recp[i]->subkeys->fpr : "invalid"); - i++; - } + if (recp) + { + int i = 0; + + while (recp[i]) + { + TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], + (recp[i]->subkeys && recp[i]->subkeys->fpr) ? + recp[i]->subkeys->fpr : "invalid"); + i++; + } + } + else + { + TRACE_LOG1 ("recipients = '%s'", recpstring); + } } - err = encrypt_start (ctx, 1, recp, flags, plain, cipher); - if (!err) - err = _gpgme_wait_one (ctx); + err = encrypt_start (ctx, 0, recp, recpstring, flags, plain, cipher); return TRACE_ERR (err); } diff --git a/src/engine-backend.h b/src/engine-backend.h index 97cf6a10..f6926662 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -72,10 +72,12 @@ struct engine_ops 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[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor); gpgme_error_t (*encrypt_sign) (void *engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor, gpgme_ctx_t ctx /* FIXME */); diff --git a/src/engine-gpg.c b/src/engine-gpg.c index a37d1f7b..809806c4 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1914,17 +1914,64 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) } +/* Take recipients from the LF delimited STRING and add -r args. */ +static gpg_error_t +append_args_from_recipients_string (engine_gpg_t gpg, const char *string) +{ + gpg_error_t err = 0; + int any = 0; + const char *s; + int n; + + do + { + /* Skip leading white space */ + while (*string == ' ' || *string == '\t') + string++; + if (!*string) + break; + + /* Look for the LF. */ + s = strchr (string, '\n'); + if (s) + n = s - string; + else + n = strlen (string); + while (n && (string[n-1] == ' ' || string[n-1] == '\t')) + n--; + + /* Add arg if it is not empty. */ + if (n) + { + err = add_arg (gpg, "-r"); + if (!err) + err = add_arg_len (gpg, NULL, string, n); + if (!err) + any = 1; + } + + string += n + !!s; + } + while (!err); + + if (!err && !any) + err = gpg_error (GPG_ERR_MISSING_KEY); + return err; +} + + static gpgme_error_t -gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, + gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor) { engine_gpg_t gpg = engine; gpgme_error_t err = 0; - if (recp) + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); - if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) + if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring))) err = add_arg (gpg, "--symmetric"); if (!err && use_armor) @@ -1951,7 +1998,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); - if (recp) + if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ @@ -1961,7 +2008,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) err = add_arg (gpg, "--no-encrypt-to"); - if (!err) + if (!err && !recp && recpstring) + err = append_args_from_recipients_string (gpg, recpstring); + else if (!err) err = append_args_from_recipients (gpg, recp); } @@ -1995,6 +2044,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, static gpgme_error_t gpg_encrypt_sign (void *engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor, gpgme_ctx_t ctx /* FIXME */) @@ -2002,10 +2052,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], engine_gpg_t gpg = engine; gpgme_error_t err = 0; - if (recp) + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); - if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) + if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring))) err = add_arg (gpg, "--symmetric"); if (!err) @@ -2023,7 +2073,7 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); - if (recp) + if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ @@ -2033,7 +2083,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) err = add_arg (gpg, "--no-encrypt-to"); - if (!err) + if (!err && !recp && recpstring) + err = append_args_from_recipients_string (gpg, recpstring); + else if (!err) err = append_args_from_recipients (gpg, recp); } diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index b8e44e7c..da7e524f 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1327,8 +1327,57 @@ set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[]) } +/* Take recipients from the LF delimited STRING and send RECIPIENT + * commands to gpgsm. */ static gpgme_error_t -gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +set_recipients_from_string (engine_gpgsm_t gpgsm, const char *string) +{ + gpg_error_t err = 0; + char *line = NULL; + int no_pubkey = 0; + const char *s; + int n; + + for (;;) + { + while (*string == ' ' || *string == '\t') + string++; + if (!*string) + break; + + s = strchr (string, '\n'); + if (s) + n = s - string; + else + n = strlen (string); + while (n && (string[n-1] == ' ' || string[n-1] == '\t')) + n--; + + gpgrt_free (line); + if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0) + { + err = gpg_error_from_syserror (); + break; + } + string += n + !!s; + + err = gpgsm_assuan_simple_command (gpgsm, line, gpgsm->status.fnc, + gpgsm->status.fnc_value); + + /* Fixme: Improve error reporting. */ + if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) + no_pubkey++; + else if (err) + break; + } + gpgrt_free (line); + return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0; +} + + +static gpgme_error_t +gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, + gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor) { engine_gpgsm_t gpgsm = engine; @@ -1339,7 +1388,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!recp) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - if (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO) + if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) { err = gpgsm_assuan_simple_command (gpgsm, "OPTION no-encrypt-to", NULL, NULL); @@ -1359,7 +1408,10 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgsm_clear_fd (gpgsm, MESSAGE_FD); gpgsm->inline_data = NULL; - err = set_recipients (gpgsm, recp); + if (!recp && recpstring) + err = set_recipients_from_string (gpgsm, recpstring); + else + err = set_recipients (gpgsm, recp); if (!err) err = start (gpgsm, "ENCRYPT"); diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index fd5ac174..d8f4fce3 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1075,8 +1075,58 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[]) } +/* Take recipients from the LF delimited STRING and send RECIPIENT + * commands to gpgsm. */ static gpgme_error_t -uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +set_recipients_from_string (engine_uiserver_t uiserver, const char *string) +{ + gpg_error_t err = 0; + char *line = NULL; + int no_pubkey = 0; + const char *s; + int n; + + for (;;) + { + while (*string == ' ' || *string == '\t') + string++; + if (!*string) + break; + + s = strchr (string, '\n'); + if (s) + n = s - string; + else + n = strlen (string); + while (n && (string[n-1] == ' ' || string[n-1] == '\t')) + n--; + + gpgrt_free (line); + if (gpgrt_asprintf (&line, "RECIPIENT %.*s", n, string) < 0) + { + err = gpg_error_from_syserror (); + break; + } + string += n + !!s; + + err = uiserver_assuan_simple_command (uiserver, line, + uiserver->status.fnc, + uiserver->status.fnc_value); + + /* Fixme: Improve error reporting. */ + if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) + no_pubkey++; + else if (err) + break; + } + gpgrt_free (line); + return err? err : no_pubkey? gpg_error (GPG_ERR_NO_PUBKEY) : 0; +} + + +static gpgme_error_t +uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, + gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor) { engine_uiserver_t uiserver = engine; @@ -1140,9 +1190,12 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, uiserver->inline_data = NULL; - if (recp) + if (recp || recpstring) { - err = set_recipients (uiserver, recp); + if (recp) + err = set_recipients (uiserver, recp); + else + err = set_recipients_from_string (uiserver, recpstring); if (err) { gpgrt_free (cmd); diff --git a/src/engine.c b/src/engine.c index e51384f0..b716ca24 100644 --- a/src/engine.c +++ b/src/engine.c @@ -721,6 +721,7 @@ _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key, gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor) { @@ -730,13 +731,14 @@ _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[], if (!engine->ops->encrypt) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph, - use_armor); + return (*engine->ops->encrypt) (engine->engine, recp, recpstring, + flags, plain, ciph, use_armor); } gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor, gpgme_ctx_t ctx /* FIXME */) @@ -747,8 +749,8 @@ _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], if (!engine->ops->encrypt_sign) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->encrypt_sign) (engine->engine, recp, flags, - plain, ciph, use_armor, ctx); + return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring, + flags, plain, ciph, use_armor, ctx); } diff --git a/src/engine.h b/src/engine.h index 34bf8e90..8b692f2e 100644 --- a/src/engine.h +++ b/src/engine.h @@ -98,11 +98,13 @@ gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type, gpgme_ctx_t ctx /* FIXME */); gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor); gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, diff --git a/src/gpgme-json.c b/src/gpgme-json.c index b54d9a8a..4b1cd5b8 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -354,18 +354,19 @@ get_protocol (cjson_t json, gpgme_protocol_t *r_protocol) } -/* Extract the keys from the KEYS array in the JSON object. CTX is a - * GPGME context object. On success an array with the keys is stored - * at R_KEYS. In failure an error code is returned. */ +/* Extract the keys from the "keys" array in the JSON object. On + * success a string with the keys identifiers is stored at R_KEYS. + * The keys in that string are LF delimited. On failure an error code + * is returned. */ static gpg_error_t -get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys) +get_keys (cjson_t json, char **r_keystring) { - gpg_error_t err; cjson_t j_keys, j_item; int i, nkeys; - gpgme_key_t *keys; + char *p; + size_t length; - *r_keys = NULL; + *r_keystring = NULL; j_keys = cJSON_GetObjectItem (json, "keys"); if (!j_keys) @@ -373,8 +374,15 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys) if (!cjson_is_array (j_keys) && !cjson_is_string (j_keys)) return gpg_error (GPG_ERR_INV_VALUE); + /* Fixme: We should better use a membuf like thing. */ + length = 1; /* For the EOS. */ if (cjson_is_string (j_keys)) - nkeys = 1; + { + nkeys = 1; + length += strlen (j_keys->valuestring); + if (strchr (j_keys->valuestring, '\n')) + return gpg_error (GPG_ERR_INV_USER_ID); + } else { nkeys = cJSON_GetArraySize (j_keys); @@ -385,43 +393,37 @@ get_keys (gpgme_ctx_t ctx, cjson_t json, gpgme_key_t **r_keys) j_item = cJSON_GetArrayItem (j_keys, i); if (!j_item || !cjson_is_string (j_item)) return gpg_error (GPG_ERR_INV_VALUE); + if (i) + length++; /* Space for delimiter. */ + length += strlen (j_item->valuestring); + if (strchr (j_item->valuestring, '\n')) + return gpg_error (GPG_ERR_INV_USER_ID); } } - /* Now allocate an array to store the gpgme key objects. */ - keys = xcalloc (nkeys + 1, sizeof *keys); + p = *r_keystring = xtrymalloc (length); + if (!p) + return gpg_error_from_syserror (); if (cjson_is_string (j_keys)) { - err = gpgme_get_key (ctx, j_keys->valuestring, &keys[0], 0); - if (err) - goto leave; + strcpy (p, j_keys->valuestring); } else { for (i=0; i < nkeys; i++) { j_item = cJSON_GetArrayItem (j_keys, i); - err = gpgme_get_key (ctx, j_item->valuestring, &keys[i], 0); - if (err) - goto leave; + if (i) + *p++ = '\n'; /* Add delimiter. */ + p = stpcpy (p, j_item->valuestring); } } - err = 0; - *r_keys = keys; - keys = NULL; - - leave: - if (keys) - { - for (i=0; keys[i]; i++) - gpgme_key_unref (keys[i]); - xfree (keys); - } - return err; + return 0; } + /* * GPGME support functions. @@ -582,11 +584,11 @@ op_encrypt (cjson_t request, cjson_t result) gpgme_ctx_t ctx = NULL; gpgme_protocol_t protocol; int opt_base64; - gpgme_key_t *keys = NULL; + char *keystring = NULL; cjson_t j_input; gpgme_data_t input = NULL; gpgme_data_t output = NULL; - int abool, i; + int abool; gpgme_encrypt_flags_t encrypt_flags = 0; if ((err = get_protocol (request, &protocol))) @@ -622,7 +624,7 @@ op_encrypt (cjson_t request, cjson_t result) /* Get the keys. */ - err = get_keys (ctx, request, &keys); + err = get_keys (request, &keystring); if (err) { /* Provide a custom error response. */ @@ -674,7 +676,8 @@ op_encrypt (cjson_t request, cjson_t result) } /* Encrypt. */ - err = gpgme_op_encrypt (ctx, keys, encrypt_flags, input, output); + err = gpgme_op_encrypt_ext (ctx, NULL, keystring, encrypt_flags, + input, output); /* encrypt_result = gpgme_op_encrypt_result (ctx); */ if (err) { @@ -713,12 +716,7 @@ op_encrypt (cjson_t request, cjson_t result) } leave: - if (keys) - { - for (i=0; keys[i]; i++) - gpgme_key_unref (keys[i]); - xfree (keys); - } + xfree (keystring); release_context (ctx); gpgme_data_release (input); return err; diff --git a/src/gpgme.def b/src/gpgme.def index cad30f6c..a01d89a2 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -267,5 +267,10 @@ EXPORTS gpgme_op_conf_dir @199 + gpgme_op_encrypt_ext @200 + gpgme_op_encrypt_ext_start @201 + gpgme_op_encrypt_sign_ext @202 + gpgme_op_encrypt_sign_ext_start @203 + ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index e3198798..8aba5baa 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1274,10 +1274,22 @@ gpgme_encrypt_flags_t; store the resulting ciphertext in CIPHER. */ gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, - gpgme_data_t plain, gpgme_data_t cipher); + gpgme_data_t plain, + gpgme_data_t cipher); gpgme_error_t gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, - gpgme_data_t plain, gpgme_data_t cipher); + gpgme_data_t plain, + gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t cipher); /* Encrypt plaintext PLAIN within CTX for the recipients RECP and store the resulting ciphertext in CIPHER. Also sign the ciphertext @@ -1289,7 +1301,19 @@ gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_data_t cipher); gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, - gpgme_data_t plain, gpgme_data_t cipher); + gpgme_data_t plain, + gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, + gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *recpstring, + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t cipher); /* diff --git a/src/libgpgme.vers b/src/libgpgme.vers index a95befba..b49c86d9 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -215,10 +215,15 @@ GPGME_1.0 { gpgme_op_edit; gpgme_op_edit_start; gpgme_op_encrypt; - gpgme_op_encrypt_result; + gpgme_op_encrypt_start; + gpgme_op_encrypt_ext; + gpgme_op_encrypt_ext_start; gpgme_op_encrypt_sign; + gpgme_op_encrypt_sign_ext; gpgme_op_encrypt_sign_start; - gpgme_op_encrypt_start; + gpgme_op_encrypt_sign_ext_start; + gpgme_op_encrypt_result; + gpgme_op_export; gpgme_op_export_ext; gpgme_op_export_ext_start; -- cgit v1.2.3 From 86efba2be270d2cdd0bc66c9d3fe190495b7af2f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 09:40:27 +0200 Subject: core: New encryption flag GPGME_ENCRYPT_WANT_ADDRESS. * src/gpgme.h.in (GPGME_ENCRYPT_WANT_ADDRESS): New flag. * src/engine-gpg.c (add_arg_recipient): New. (add_arg_recipient_string): New. (append_args_from_recipients): Call new helper function. (append_args_from_recipients_string): Ditto. * src/gpgme-json.c (op_encrypt): Add flag "want-address". -- Signed-off-by: Werner Koch --- src/engine-gpg.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++------ src/gpgme-json.c | 5 ++++ src/gpgme.h.in | 3 ++- 3 files changed, 80 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 809806c4..90e3b89e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -43,6 +43,7 @@ #include "sema.h" #include "debug.h" #include "data.h" +#include "mbox-util.h" #include "engine-backend.h" @@ -1892,8 +1893,70 @@ gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out, } +/* Add a single argument from a key to an -r option. */ +static gpg_error_t +add_arg_recipient (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + gpgme_key_t key) +{ + gpg_error_t err; + + if ((flags & GPGME_ENCRYPT_WANT_ADDRESS)) + { + /* We have no way to figure out which mail address was + * requested. FIXME: It would be possible to figure this out by + * consulting the SENDER property of the context. */ + err = gpg_error (GPG_ERR_INV_USER_ID); + } + else + err = add_arg (gpg, key->subkeys->fpr); + + return err; +} + + +/* Add a single argument from a USERID string to an -r option. */ +static gpg_error_t +add_arg_recipient_string (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + const char *userid, int useridlen) +{ + gpg_error_t err; + + if ((flags & GPGME_ENCRYPT_WANT_ADDRESS)) + { + char *tmpstr, *mbox; + + tmpstr = malloc (useridlen + 1); + if (!tmpstr) + err = gpg_error_from_syserror (); + else + { + memcpy (tmpstr, userid, useridlen); + tmpstr[useridlen] = 0; + + mbox = _gpgme_mailbox_from_userid (tmpstr); + if (!mbox) + { + err = gpg_error_from_syserror (); + if (gpg_err_code (err) == GPG_ERR_EINVAL) + err = gpg_error (GPG_ERR_INV_USER_ID); + } + else + err = add_arg (gpg, mbox); + + free (mbox); + free (tmpstr); + } + } + else + err = add_arg_len (gpg, NULL, userid, useridlen); + + return err; +} + + static gpgme_error_t -append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) +append_args_from_recipients (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + gpgme_key_t recp[]) { gpgme_error_t err = 0; int i = 0; @@ -1905,7 +1968,7 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) if (!err) err = add_arg (gpg, "-r"); if (!err) - err = add_arg (gpg, recp[i]->subkeys->fpr); + err = add_arg_recipient (gpg, flags, recp[i]); if (err) break; i++; @@ -1916,7 +1979,9 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) /* Take recipients from the LF delimited STRING and add -r args. */ static gpg_error_t -append_args_from_recipients_string (engine_gpg_t gpg, const char *string) +append_args_from_recipients_string (engine_gpg_t gpg, + gpgme_encrypt_flags_t flags, + const char *string) { gpg_error_t err = 0; int any = 0; @@ -1945,7 +2010,7 @@ append_args_from_recipients_string (engine_gpg_t gpg, const char *string) { err = add_arg (gpg, "-r"); if (!err) - err = add_arg_len (gpg, NULL, string, n); + err = add_arg_recipient_string (gpg, flags, string, n); if (!err) any = 1; } @@ -2009,9 +2074,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, err = add_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) - err = append_args_from_recipients_string (gpg, recpstring); + err = append_args_from_recipients_string (gpg, flags, recpstring); else if (!err) - err = append_args_from_recipients (gpg, recp); + err = append_args_from_recipients (gpg, flags, recp); } /* Tell the gpg object about the data. */ @@ -2084,9 +2149,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], err = add_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) - err = append_args_from_recipients_string (gpg, recpstring); + err = append_args_from_recipients_string (gpg, flags, recpstring); else if (!err) - err = append_args_from_recipients (gpg, recp); + err = append_args_from_recipients (gpg, flags, recp); } if (!err) diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 4b1cd5b8..c73bebdb 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -569,6 +569,7 @@ static const char hlp_encrypt[] = "no-encrypt-to: Do not use a default recipient.\n" "no-compress: Do not compress the plaintext first.\n" "throw-keyids: Request the --throw-keyids option.\n" + "want-address: Require that the keys include a mail address.\n" "wrap: Assume the input is an OpenPGP message.\n" "\n" "Response on success:\n" @@ -621,6 +622,10 @@ op_encrypt (cjson_t request, cjson_t result) goto leave; if (abool) encrypt_flags |= GPGME_ENCRYPT_WRAP; + if ((err = get_boolean_flag (request, "want-address", 0, &abool))) + goto leave; + if (abool) + encrypt_flags |= GPGME_ENCRYPT_WANT_ADDRESS; /* Get the keys. */ diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 8aba5baa..860e0931 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1266,7 +1266,8 @@ typedef enum GPGME_ENCRYPT_NO_COMPRESS = 16, GPGME_ENCRYPT_SYMMETRIC = 32, GPGME_ENCRYPT_THROW_KEYIDS = 64, - GPGME_ENCRYPT_WRAP = 128 + GPGME_ENCRYPT_WRAP = 128, + GPGME_ENCRYPT_WANT_ADDRESS = 256 } gpgme_encrypt_flags_t; -- cgit v1.2.3 From 4bba3b8e2c350b8ff0d562ec63cc03a096448d84 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 10:04:20 +0200 Subject: core: Allow for --hidden keyword in OpenPGP recpstrings. * src/engine-gpg.c (append_args_from_recipients_string): Add special keywords. -- GnuPG-bug-id: 3775 Signed-off-by: Werner Koch --- src/engine-gpg.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 90e3b89e..49a1c75e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1985,6 +1985,8 @@ append_args_from_recipients_string (engine_gpg_t gpg, { gpg_error_t err = 0; int any = 0; + int ignore = 0; + int hidden = 0; const char *s; int n; @@ -2005,10 +2007,14 @@ append_args_from_recipients_string (engine_gpg_t gpg, while (n && (string[n-1] == ' ' || string[n-1] == '\t')) n--; - /* Add arg if it is not empty. */ - if (n) + if (!ignore && n == 2 && !memcmp (string, "--", 2)) + ignore = 1; + else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8)) + hidden = 1; + else if (n) { - err = add_arg (gpg, "-r"); + /* Add arg if it is not empty. */ + err = add_arg (gpg, hidden? "-R":"-r"); if (!err) err = add_arg_recipient_string (gpg, flags, string, n); if (!err) -- cgit v1.2.3 From c143ab692c7fc7cf2ec0aebe40b9479ee15eaba9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 11:06:27 +0200 Subject: core: For OpenPGP let offline mode disable dirmngr. * src/engine-gpg.c (struct engine_gpg): New flag.offline. (gpg_set_engine_flags): Set it. Also fix setting of no_symkey_cache. (build_argv): Pass --disable-dirmngr in offline mode. -- GnuPG-bug-id: 3831 Signed-off-by: Werner Koch --- src/engine-gpg.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 49a1c75e..fdb786a9 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -148,6 +148,7 @@ struct engine_gpg struct { unsigned int no_symkey_cache : 1; + unsigned int offline : 1; } flags; /* NULL or the data object fed to --override_session_key-fd. */ @@ -647,12 +648,14 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx) else strcpy (gpg->request_origin, ctx->request_origin); } - else if (ctx->no_symkey_cache && have_gpg_version (gpg, "2.2.7")) - { - gpg->flags.no_symkey_cache = 1; - } else *gpg->request_origin = 0; + + gpg->flags.no_symkey_cache = (ctx->no_symkey_cache + && have_gpg_version (gpg, "2.2.7")); + + gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23")); + } @@ -884,7 +887,8 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; if (!gpg->cmd.used) argc++; /* --batch */ - argc += 3; /* --no-sk-comments, --request-origin, --no-symkey-cache */ + argc += 4; /* --no-sk-comments, --request-origin, --no-symkey-cache */ + /* --disable-dirmngr */ argv = calloc (argc + 1, sizeof *argv); if (!argv) @@ -959,6 +963,19 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; } + if (gpg->flags.offline) + { + argv[argc] = strdup ("--disable-dirmngr"); + if (!argv[argc]) + { + int saved_err = gpg_error_from_syserror (); + free (fd_data_map); + free_argv (argv); + return saved_err; + } + argc++; + } + if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0")) { const char *s = NULL; -- cgit v1.2.3 From 3589da0500f1c80717e658d103a0cb2751d27b49 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 12:40:30 +0200 Subject: core: New keyword --file for OpenPGP recpstring. * src/engine-gpg.c (append_args_from_recipients_string): Add new flags. -- Now you can use gpgme to encrypt without first importing a key. Signed-off-by: Werner Koch --- src/engine-gpg.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index fdb786a9..173e940c 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2001,9 +2001,11 @@ append_args_from_recipients_string (engine_gpg_t gpg, const char *string) { gpg_error_t err = 0; + gpgme_encrypt_flags_t orig_flags = flags; int any = 0; int ignore = 0; int hidden = 0; + int file = 0; const char *s; int n; @@ -2028,10 +2030,22 @@ append_args_from_recipients_string (engine_gpg_t gpg, ignore = 1; else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8)) hidden = 1; - else if (n) + else if (!ignore && n == 11 && !memcmp (string, "--no-hidden", 11)) + hidden = 0; + else if (!ignore && n == 6 && !memcmp (string, "--file", 6)) { - /* Add arg if it is not empty. */ - err = add_arg (gpg, hidden? "-R":"-r"); + file = 1; + /* Because the key is used as is we need to ignore this flag: */ + flags &= ~GPGME_ENCRYPT_WANT_ADDRESS; + } + else if (!ignore && n == 9 && !memcmp (string, "--no-file", 9)) + { + file = 0; + flags = orig_flags; + } + else if (n) /* Not empty - use it. */ + { + err = add_arg (gpg, file? (hidden? "-F":"-f") : (hidden? "-R":"-r")); if (!err) err = add_arg_recipient_string (gpg, flags, string, n); if (!err) -- cgit v1.2.3 From 01435da498af9f7538d7ee810392d7eaa407957e Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 13:48:56 +0200 Subject: core: Extend decryption result with symkey_algo. * src/gpgme.h.in (gpgme_op_decrypt_result_t): Add field 'symkey_algo'. * src/decrypt.c (release_op_data): Free SYMKEY_ALGO. (gpgme_op_decrypt_result): Make sure SYMKEY_ALGO is not NULL. (parse_decryption_info): New. (_gpgme_decrypt_status_handler): Parse DECRYPTION_INFO status. * src/conversion.c (_gpgme_cipher_algo_name): New. (_gpgme_cipher_mode_name): New. * tests/run-decrypt.c (print_result): Print SYMKEY_ALGO * src/util.h (_gpgme_map_gnupg_error): Remove obsolete prototype. -- Signed-off-by: Werner Koch --- src/conversion.c | 46 +++++++++++++++++++++++++++++++++++++ src/decrypt.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-------- src/gpgme.h.in | 4 ++++ src/util.h | 5 ++-- 4 files changed, 114 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/conversion.c b/src/conversion.c index 5b84f672..4bfd3d3e 100644 --- a/src/conversion.c +++ b/src/conversion.c @@ -575,3 +575,49 @@ _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol) return algo; } + + +/* Return a string with a cipher algorithm. */ +const char * +_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol) +{ + if (protocol == GPGME_PROTOCOL_OPENPGP) + { + /* The algo is given according to OpenPGP specs. */ + switch (algo) + { + case 1: return "IDEA"; + case 2: return "3DES"; + case 3: return "CAST5"; + case 4: return "BLOWFISH"; + case 7: return "AES"; + case 8: return "AES192"; + case 9: return "AES256"; + case 10: return "TWOFISH"; + case 11: return "CAMELLIA128"; + case 12: return "CAMELLIA192"; + case 13: return "CAMELLIA256"; + } + } + + return "Unknown"; +} + + +/* Return a string with the cipher mode. */ +const char * +_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol) +{ + if (protocol == GPGME_PROTOCOL_OPENPGP) + { + /* The algo is given according to OpenPGP specs. */ + switch (algo) + { + case 0: return "CFB"; + case 1: return "EAX"; + case 2: return "OCB"; + } + } + + return "Unknown"; +} diff --git a/src/decrypt.c b/src/decrypt.c index 8c2cd4d7..e4de6e41 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -69,14 +69,10 @@ release_op_data (void *hook) op_data_t opd = (op_data_t) hook; gpgme_recipient_t recipient = opd->result.recipients; - if (opd->result.unsupported_algorithm) - free (opd->result.unsupported_algorithm); - - if (opd->result.file_name) - free (opd->result.file_name); - - if (opd->result.session_key) - free (opd->result.session_key); + free (opd->result.unsupported_algorithm); + free (opd->result.file_name); + free (opd->result.session_key); + free (opd->result.symkey_algo); while (recipient) { @@ -104,6 +100,17 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx) return NULL; } + /* Make sure that SYMKEY_ALGO has a value. */ + if (!opd->result.symkey_algo) + { + opd->result.symkey_algo = strdup ("?.?"); + if (!opd->result.symkey_algo) + { + TRACE_SUC0 ("result=(null)"); + return NULL; + } + } + if (_gpgme_debug_trace ()) { gpgme_recipient_t rcp; @@ -263,6 +270,49 @@ parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol) } +/* Parse the ARGS of a + * DECRYPTION_INFO [] + * status. Returns 0 on success and updates the OPD. + */ +static gpgme_error_t +parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol) +{ + char *field[3]; + int nfields; + char *args2; + int mdc, mode; + const char *algostr, *modestr; + + if (!args) + return trace_gpg_error (GPG_ERR_INV_ENGINE); + + args2 = strdup (args); /* Split modifies the input string. */ + nfields = _gpgme_split_fields (args2, field, DIM (field)); + if (nfields < 2) + { + free (args2); + return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing. */ + } + + mdc = atoi (field[0]); + algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol); + mode = nfields < 3? 0 : atoi (field[2]); + modestr = _gpgme_cipher_mode_name (mode, protocol); + + free (args2); + + free (opd->result.symkey_algo); + if (!mode && mdc != 2) + opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL); + else + opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL); + if (!opd->result.symkey_algo) + return gpg_error_from_syserror (); + + return 0; +} + + gpgme_error_t _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args) @@ -303,7 +353,9 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, break; case GPGME_STATUS_DECRYPTION_INFO: - /* Fixme: Provide a way to return the used symmetric algorithm. */ + err = parse_decryption_info (args, opd, ctx->protocol); + if (err) + return err; break; case GPGME_STATUS_DECRYPTION_OKAY: diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 860e0931..202859c3 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1368,6 +1368,10 @@ struct _gpgme_op_decrypt_result /* A textual representation of the session key used to decrypt the * message, if available */ char *session_key; + + /* A string with the symmetric encryption algorithm and mode using + * the format ".". */ + char *symkey_algo; }; typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t; diff --git a/src/util.h b/src/util.h index b4043ed1..da929eb4 100644 --- a/src/util.h +++ b/src/util.h @@ -165,10 +165,11 @@ time_t _gpgme_parse_timestamp (const char *timestamp, char **endp); * on error or missing timestamp. */ unsigned long _gpgme_parse_timestamp_ul (const char *timestamp); -gpgme_error_t _gpgme_map_gnupg_error (char *err); - int _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol); +const char *_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol); +const char *_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol); + /*-- b64dec.c --*/ -- cgit v1.2.3 From e69b175e8ed5430b56e2e8f3d68c16a45f0fed17 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 09:26:33 +0200 Subject: json: Add meta command ,read to gpgme-json. * src/gpgme-json.c: Include stat.h. (get_file): New. (process_meta_commands): Implement ",read". Signed-off-by: Werner Koch --- src/gpgme-json.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index c73bebdb..56d69469 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -33,6 +33,7 @@ #include #endif #include +#include #define GPGRT_ENABLE_ES_MACROS 1 #define GPGRT_ENABLE_LOG_MACROS 1 @@ -842,7 +843,6 @@ process_request (const char *request) xjson_AddStringToObject (response, "op", op); } - } } else /* Operation not supported. */ @@ -869,6 +869,48 @@ process_request (const char *request) * Driver code */ +static char * +get_file (const char *fname) +{ + gpg_error_t err; + estream_t fp; + struct stat st; + char *buf; + size_t buflen; + + fp = es_fopen (fname, "r"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error ("can't open '%s': %s\n", fname, gpg_strerror (err)); + return NULL; + } + + if (fstat (es_fileno(fp), &st)) + { + err = gpg_error_from_syserror (); + log_error ("can't stat '%s': %s\n", fname, gpg_strerror (err)); + es_fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (es_fread (buf, buflen, 1, fp) != 1) + { + err = gpg_error_from_syserror (); + log_error ("error reading '%s': %s\n", fname, gpg_strerror (err)); + es_fclose (fp); + xfree (buf); + return NULL; + } + buf[buflen] = 0; + es_fclose (fp); + + return buf; +} + + /* Return a malloced line or NULL on EOF. Terminate on read * error. */ static char * @@ -935,11 +977,26 @@ process_meta_commands (const char *request) result = process_request ("{ \"op\": \"help\"," " \"interactive_help\": " "\"\\nMeta commands:\\n" + " ,read FNAME Process data from FILE\\n" " ,help This help\\n" " ,quit Terminate process\"" "}"); else if (!strncmp (request, "quit", 4) && (spacep (request+4) || !request[4])) exit (0); + else if (!strncmp (request, "read", 4) && (spacep (request+4) || !request[4])) + { + if (!request[4]) + log_info ("usage: ,read FILENAME\n"); + else + { + char *buffer = get_file (request + 5); + if (buffer) + { + result = process_request (buffer); + xfree (buffer); + } + } + } else log_info ("invalid meta command\n"); -- cgit v1.2.3 From ed1052842df633bc149b14c4cb17859e3c66afe4 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 11:12:46 +0200 Subject: json: Add command "getmore" to gpgme-json. * src/gpgme-json.c (MIN_REPLY_CHUNK_SIZE): New const. (DEF_REPLY_CHUNK_SIZE): New const. (MAX_REPLY_CHUNK_SIZE): New const. (pending_data): New var. (add_base64_to_object): Chnage to take a plain data pointer. (get_chunksize): New. (make_data_object): New. (op_encrypt): Get chunksize and use make_data_object. (op_getmore): New. (process_request): Release pending data for all commands but "getmore" and "help". -- Native messaging has a limit on the data it may receive in one request. Thus the caller needs to watch for the "more" flag and request the remaining data using "getmore" in a loop. Signed-off-by: Werner Koch --- src/gpgme-json.c | 274 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 228 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 56d69469..576e63e5 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -49,6 +49,16 @@ int main (void){fputs ("Build with Libgpg-error >= 1.28!\n", stderr);return 1;} /* We don't allow a request with more than 64 MiB. */ #define MAX_REQUEST_SIZE (64 * 1024 * 1024) +/* Minimal, default and maximum chunk size for returned data. The + * first chunk is returned directly. If the "more" flag is also + * returned, a "getmore" command needs to be used to get the next + * chunk. Right now this value covers just the value of the "data" + * element; so to cover for the other returned objects this values + * needs to be lower than the maximum allowed size of the browser. */ +#define MIN_REPLY_CHUNK_SIZE 512 +#define DEF_REPLY_CHUNK_SIZE (512 * 1024) +#define MAX_REPLY_CHUNK_SIZE (10 * 1024 * 1024) + static void xoutofcore (const char *type) GPGRT_ATTR_NORETURN; static cjson_t error_object_v (cjson_t json, const char *message, @@ -64,6 +74,16 @@ static int opt_interactive; /* True is debug mode is active. */ static int opt_debug; +/* Pending data to be returned by a getmore command. */ +static struct +{ + char *buffer; /* Malloced data or NULL if not used. */ + size_t length; /* Length of that data. */ + size_t written; /* # of already written bytes from BUFFER. */ + const char *type;/* The "type" of the data. */ + int base64; /* The "base64" flag of the data. */ +} pending_data; + /* * Helper functions and macros @@ -147,11 +167,12 @@ xjson_AddBoolToObject (cjson_t object, const char *name, int abool) return ; } -/* This is similar to cJSON_AddStringToObject but takes a gpgme DATA - * object and adds it under NAME as a base 64 encoded string to - * OBJECT. Ownership of DATA is transferred to this function. */ +/* This is similar to cJSON_AddStringToObject but takes (DATA, + * DATALEN) and adds it under NAME as a base 64 encoded string to + * OBJECT. */ static gpg_error_t -add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data) +add_base64_to_object (cjson_t object, const char *name, + const void *data, size_t datalen) { #if GPGRT_VERSION_NUMBER < 0x011d00 /* 1.29 */ return gpg_error (GPG_ERR_NOT_SUPPORTED); @@ -161,7 +182,6 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data) gpgrt_b64state_t state = NULL; cjson_t j_str = NULL; void *buffer = NULL; - size_t buflen; fp = es_fopenmem (0, "rwb"); if (!fp) @@ -176,20 +196,9 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data) goto leave; } - gpgme_data_write (data, "", 1); /* Make sure we have a string. */ - buffer = gpgme_data_release_and_get_mem (data, &buflen); - data = NULL; - if (!buffer) - { - err = gpg_error_from_syserror (); - goto leave; - } - - err = gpgrt_b64enc_write (state, buffer, buflen); + err = gpgrt_b64enc_write (state, data, datalen); if (err) goto leave; - xfree (buffer); - buffer = NULL; err = gpgrt_b64enc_finish (state); state = NULL; @@ -227,7 +236,6 @@ add_base64_to_object (cjson_t object, const char *name, gpgme_data_t data) cJSON_Delete (j_str); gpgrt_b64enc_finish (state); es_fclose (fp); - gpgme_data_release (data); return err; #endif } @@ -355,6 +363,29 @@ get_protocol (cjson_t json, gpgme_protocol_t *r_protocol) } +/* Get the chunksize from JSON and store it at R_CHUNKSIZE. */ +static gpg_error_t +get_chunksize (cjson_t json, size_t *r_chunksize) +{ + cjson_t j_item; + + *r_chunksize = DEF_REPLY_CHUNK_SIZE; + j_item = cJSON_GetObjectItem (json, "chunksize"); + if (!j_item) + ; + else if (!cjson_is_number (j_item)) + return gpg_error (GPG_ERR_INV_VALUE); + else if ((size_t)j_item->valueint < MIN_REPLY_CHUNK_SIZE) + *r_chunksize = MIN_REPLY_CHUNK_SIZE; + else if ((size_t)j_item->valueint > MAX_REPLY_CHUNK_SIZE) + *r_chunksize = MAX_REPLY_CHUNK_SIZE; + else + *r_chunksize = (size_t)j_item->valueint; + + return 0; +} + + /* Extract the keys from the "keys" array in the JSON object. On * success a string with the keys identifiers is stored at R_KEYS. * The keys in that string are LF delimited. On failure an error code @@ -549,10 +580,80 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json) /* - * Implementaion of the commands. + * Implementation of the commands. */ +/* Create a "data" object and the "type", "base64" and "more" flags + * from DATA and append them to RESULT. Ownership if DATA is + * transferred to this function. TYPE must be a fixed string. + * CHUNKSIZE is the chunksize requested from the caller. Note that + * op_getmore has similar code but works on PENDING_DATA which is set + * here. */ +static gpg_error_t +make_data_object (cjson_t result, gpgme_data_t data, size_t chunksize, + const char *type, int base64) +{ + gpg_error_t err; + char *buffer; + size_t buflen; + int c; + + /* Adjust the chunksize if we need to do base64 conversion. */ + if (base64) + chunksize = (chunksize / 4) * 3; + + if (!base64) /* Make sure that we really have a string. */ + gpgme_data_write (data, "", 1); + + buffer = gpgme_data_release_and_get_mem (data, &buflen); + data = NULL; + if (!buffer) + { + err = gpg_error_from_syserror (); + goto leave; + } + + + xjson_AddStringToObject (result, "type", type); + xjson_AddBoolToObject (result, "base64", base64); + + if (buflen > chunksize) + { + xjson_AddBoolToObject (result, "more", 1); + + c = buffer[chunksize]; + buffer[chunksize] = 0; + if (base64) + err = add_base64_to_object (result, "data", buffer, chunksize); + else + err = cjson_AddStringToObject (result, "data", buffer); + buffer[chunksize] = c; + if (err) + goto leave; + + pending_data.buffer = buffer; + buffer = NULL; + pending_data.length = buflen; + pending_data.written = chunksize; + pending_data.type = type; + pending_data.base64 = base64; + } + else + { + if (base64) + err = add_base64_to_object (result, "data", buffer, buflen); + else + err = cjson_AddStringToObject (result, "data", buffer); + } + + leave: + gpgme_free (buffer); + return err; +} + + + static const char hlp_encrypt[] = "op: \"encrypt\"\n" "keys: Array of strings with the fingerprints or user-ids\n" @@ -562,6 +663,7 @@ static const char hlp_encrypt[] = "\n" "Optional parameters:\n" "protocol: Either \"openpgp\" (default) or \"cms\".\n" + "chunksize: Max number of bytes in the resulting \"data\".\n" "\n" "Optional boolean flags (default is false):\n" "base64: Input data is base64 encoded.\n" @@ -578,13 +680,15 @@ static const char hlp_encrypt[] = "data: Unless armor mode is used a Base64 encoded binary\n" " ciphertext. In armor mode a string with an armored\n" " OpenPGP or a PEM message.\n" - "base64: Boolean indicating whether data is base64 encoded."; + "base64: Boolean indicating whether data is base64 encoded.\n" + "more: Optional boolean indicating that \"getmore\" is required."; static gpg_error_t op_encrypt (cjson_t request, cjson_t result) { gpg_error_t err; gpgme_ctx_t ctx = NULL; gpgme_protocol_t protocol; + size_t chunksize; int opt_base64; char *keystring = NULL; cjson_t j_input; @@ -596,6 +700,8 @@ op_encrypt (cjson_t request, cjson_t result) if ((err = get_protocol (request, &protocol))) goto leave; ctx = get_context (protocol); + if ((err = get_chunksize (request, &chunksize))) + goto leave; if ((err = get_boolean_flag (request, "base64", 0, &opt_base64))) goto leave; @@ -693,43 +799,106 @@ op_encrypt (cjson_t request, cjson_t result) gpgme_data_release (input); input = NULL; - xjson_AddStringToObject (result, "type", "ciphertext"); - /* If armoring is used we do not need to base64 the output. */ - xjson_AddBoolToObject (result, "base64", !gpgme_get_armor (ctx)); - if (gpgme_get_armor (ctx)) + /* We need to base64 if armoring has not been requested. */ + err = make_data_object (result, output, chunksize, + "ciphertext", !gpgme_get_armor (ctx)); + output = NULL; + + leave: + xfree (keystring); + release_context (ctx); + gpgme_data_release (input); + gpgme_data_release (output); + return err; +} + + + +static const char hlp_getmore[] = + "op: \"getmore\"\n" + "\n" + "Optional parameters:\n" + "chunksize: Max number of bytes in the \"data\" object.\n" + "\n" + "Response on success:\n" + "type: Type of the pending data\n" + "data: The next chunk of data\n" + "base64: Boolean indicating whether data is base64 encoded\n" + "more: Optional boolean requesting another \"getmore\"."; +static gpg_error_t +op_getmore (cjson_t request, cjson_t result) +{ + gpg_error_t err; + int c; + size_t n; + size_t chunksize; + + if ((err = get_chunksize (request, &chunksize))) + goto leave; + + /* Adjust the chunksize if we need to do base64 conversion. */ + if (pending_data.base64) + chunksize = (chunksize / 4) * 3; + + /* Do we have anything pending? */ + if (!pending_data.buffer) { - char *buffer; + err = gpg_error (GPG_ERR_NO_DATA); + error_object (result, "Operation not possible: %s", gpg_strerror (err)); + goto leave; + } - /* Make sure that we really have a string. */ - gpgme_data_write (output, "", 1); - buffer = gpgme_data_release_and_get_mem (output, NULL); - if (!buffer) - { - err = gpg_error_from_syserror (); - goto leave; - } - err = cjson_AddStringToObject (result, "data", buffer); - gpgme_free (buffer); - if (err) - goto leave; + xjson_AddStringToObject (result, "type", pending_data.type); + xjson_AddBoolToObject (result, "base64", pending_data.base64); + + if (pending_data.written >= pending_data.length) + { + /* EOF reached. This should not happen but we return an empty + * string once in case of client errors. */ + gpgme_free (pending_data.buffer); + pending_data.buffer = NULL; + xjson_AddBoolToObject (result, "more", 0); + err = cjson_AddStringToObject (result, "data", ""); } else { - err = add_base64_to_object (result, "data", output); - output = NULL; - if (err) - goto leave; + n = pending_data.length - pending_data.written; + if (n > chunksize) + { + n = chunksize; + xjson_AddBoolToObject (result, "more", 1); + } + else + xjson_AddBoolToObject (result, "more", 0); + + c = pending_data.buffer[pending_data.written + n]; + pending_data.buffer[pending_data.written + n] = 0; + if (pending_data.base64) + err = add_base64_to_object (result, "data", + (pending_data.buffer + + pending_data.written), n); + else + err = cjson_AddStringToObject (result, "data", + (pending_data.buffer + + pending_data.written)); + pending_data.buffer[pending_data.written + n] = c; + if (!err) + { + pending_data.written += n; + if (pending_data.written >= pending_data.length) + { + gpgme_free (pending_data.buffer); + pending_data.buffer = NULL; + } + } } leave: - xfree (keystring); - release_context (ctx); - gpgme_data_release (input); return err; } - + static const char hlp_help[] = "The tool expects a JSON object with the request and responds with\n" "another JSON object. Even on error a JSON object is returned. The\n" @@ -739,6 +908,7 @@ static const char hlp_help[] = "returned. To list all operations it is allowed to leave out \"op\" in\n" "help mode. Supported values for \"op\" are:\n\n" " encrypt Encrypt data.\n" + " getmore Retrieve remaining data.\n" " help Help overview."; static gpg_error_t op_help (cjson_t request, cjson_t result) @@ -761,6 +931,10 @@ op_help (cjson_t request, cjson_t result) } + +/* + * Dispatcher + */ /* Process a request and return the response. The response is a newly * allocated string or NULL in case of an error. */ @@ -774,7 +948,7 @@ process_request (const char *request) } optbl[] = { { "encrypt", op_encrypt, hlp_encrypt }, - + { "getmore", op_getmore, hlp_getmore }, { "help", op_help, hlp_help }, { NULL } }; @@ -829,6 +1003,14 @@ process_request (const char *request) { gpg_error_t err; + /* If this is not the "getmore" command and we have any + * pending data release that data. */ + if (pending_data.buffer && optbl[idx].handler != op_getmore) + { + gpgme_free (pending_data.buffer); + pending_data.buffer = NULL; + } + err = optbl[idx].handler (json, response); if (err) { -- cgit v1.2.3 From 49a617f8bbff116884ca5c7238c2e0ea4e26ce59 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 11:34:16 +0200 Subject: json: Improve help meta command in gpgme-json. * src/gpgme-json.c (process_meta_commands): Add ",help CMD". Signed-off-by: Werner Koch --- src/gpgme-json.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 576e63e5..f63f1967 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -1156,13 +1156,23 @@ process_meta_commands (const char *request) request++; if (!strncmp (request, "help", 4) && (spacep (request+4) || !request[4])) - result = process_request ("{ \"op\": \"help\"," - " \"interactive_help\": " - "\"\\nMeta commands:\\n" - " ,read FNAME Process data from FILE\\n" - " ,help This help\\n" - " ,quit Terminate process\"" - "}"); + { + if (request[4]) + { + char *buf = xstrconcat ("{ \"help\":true, \"op\":\"", request+5, + "\" }", NULL); + result = process_request (buf); + xfree (buf); + } + else + result = process_request ("{ \"op\": \"help\"," + " \"interactive_help\": " + "\"\\nMeta commands:\\n" + " ,read FNAME Process data from FILE\\n" + " ,help CMD Print help for a command\\n" + " ,quit Terminate process\"" + "}"); + } else if (!strncmp (request, "quit", 4) && (spacep (request+4) || !request[4])) exit (0); else if (!strncmp (request, "read", 4) && (spacep (request+4) || !request[4])) -- cgit v1.2.3 From 23177e4410d05d590c0f2e1675dc645bbb4ad62c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 14:41:50 +0200 Subject: core: Fix possible compliance mode detection error. * src/verify.c (_gpgme_verify_status_handler): Insert missing break. -- Before the insertion of the compliance status checking the break in the default clause was used by the STATUS_PLAINTEXT code. That got lost. I don't see any actual harm due to different values currently in use for the compliance status. Fixes-commit: 05fa2a9c7764b28fdac35eb72631439df948ca0e Signed-off-by: Werner Koch --- src/verify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/verify.c b/src/verify.c index 4eab902b..c3afdef2 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1094,6 +1094,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) err = _gpgme_parse_plaintext (args, &opd->result.file_name); if (err) return err; + break; case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE: PARSE_COMPLIANCE_FLAGS (args, opd->current_sig); -- cgit v1.2.3 From 65479fe7b871ad6237d5a8959b73afcc7db784da Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 15:20:35 +0200 Subject: core: Add 'is_mime' flags to the verify and decrypt results. * src/op-support.c (_gpgme_parse_plaintext): Add arg r_mime. * src/decrypt.c (_gpgme_decrypt_status_handler): Ser mime flag. * src/verify.c (_gpgme_verify_status_handler): Ditto. * src/gpgme.h.in (gpgme_op_verify_result_t): Append fields 'is_mime' and '_unused'. (gpgme_op_decrypt_result_t): New field 'is_mime'. Shrink '_unused'. * tests/run-decrypt.c (print_result): Print MIME flag. * tests/run-verify.c (print_result): Ditto. -- Note that this flag (Liternal Data packet's 'm' mode) is only specified in RFC-4880bis. To use it you currently need to add "rfc4880bis" to the the gpg.conf. Signed-off-by: Werner Koch --- src/decrypt.c | 11 ++++++++--- src/gpgme.h.in | 11 ++++++++++- src/op-support.c | 6 ++++-- src/ops.h | 4 ++-- src/verify.c | 11 ++++++++--- 5 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/decrypt.c b/src/decrypt.c index e4de6e41..155e18ef 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -409,9 +409,14 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, break; case GPGME_STATUS_PLAINTEXT: - err = _gpgme_parse_plaintext (args, &opd->result.file_name); - if (err) - return err; + { + int mime = 0; + err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime); + if (err) + return err; + gpgrt_log_debug ("decrypt.c setting mime to %d\n", mime); + opd->result.is_mime = !!mime; + } break; case GPGME_STATUS_INQUIRE_MAXLEN: diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 202859c3..c81e882f 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1356,8 +1356,11 @@ struct _gpgme_op_decrypt_result * mode. */ unsigned int is_de_vs : 1; + /* The message claims that the content is a MIME object. */ + unsigned int is_mime : 1; + /* Internal to GPGME, do not use. */ - int _unused : 30; + int _unused : 29; gpgme_recipient_t recipients; @@ -1572,6 +1575,12 @@ struct _gpgme_op_verify_result /* The original file name of the plaintext message, if available. */ char *file_name; + + /* The message claims that the content is a MIME object. */ + unsigned int is_mime : 1; + + /* Internal to GPGME; do not use. */ + unsigned int _unused : 31; }; typedef struct _gpgme_op_verify_result *gpgme_verify_result_t; diff --git a/src/op-support.c b/src/op-support.c index e55875f9..03f274cf 100644 --- a/src/op-support.c +++ b/src/op-support.c @@ -358,7 +358,7 @@ _gpgme_parse_key_considered (const char *args, /* Parse the PLAINTEXT status line in ARGS and return the result in FILENAMEP. */ gpgme_error_t -_gpgme_parse_plaintext (char *args, char **filenamep) +_gpgme_parse_plaintext (char *args, char **filenamep, int *r_mime) { char *tail; @@ -367,7 +367,9 @@ _gpgme_parse_plaintext (char *args, char **filenamep) if (*args == '\0') return 0; - /* First argument is file type. */ + /* First argument is file type (a one byte uppercase hex value). */ + if (args[0] == '6' && args[1] == 'D') + *r_mime = 1; while (*args != ' ' && *args != '\0') args++; while (*args == ' ') diff --git a/src/ops.h b/src/ops.h index cc61dc4f..5955454c 100644 --- a/src/ops.h +++ b/src/ops.h @@ -68,8 +68,8 @@ gpgme_error_t _gpgme_parse_inv_recp (char *args, int for_signing, gpgme_invalid_key_t *key); /* Parse the PLAINTEXT status line in ARGS and return the result in - FILENAMEP. */ -gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep); + FILENAMEP and R_MIME. */ +gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep,int *r_mime); /* Parse a FAILURE status line and return the error code. ARGS is modified to contain the location part. */ diff --git a/src/verify.c b/src/verify.c index c3afdef2..bd437c9a 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1091,9 +1091,14 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_PLAINTEXT: if (++opd->plaintext_seen > 1) return gpg_error (GPG_ERR_BAD_DATA); - err = _gpgme_parse_plaintext (args, &opd->result.file_name); - if (err) - return err; + { + int mime = 0; + err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime); + if (err) + return err; + gpgrt_log_debug ("verify.c: setting mime to %d\n", mime); + opd->result.is_mime = !!mime; + } break; case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE: -- cgit v1.2.3 From e5273fc4431dfb597a2d9cf4af5172572476a2de Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 15:24:42 +0200 Subject: json: Add command "decrypt" to gpgme-json. * src/gpgme-json.c (make_data_object): Enable auto-detection of base-64. (op_encrypt): Support a 'mime' flag. (op_decrypt): New. (process_request): Add command "encrypt". Signed-off-by: Werner Koch --- src/gpgme-json.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index f63f1967..e7aa2284 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -587,7 +587,9 @@ data_from_base64_string (gpgme_data_t *r_data, cjson_t json) /* Create a "data" object and the "type", "base64" and "more" flags * from DATA and append them to RESULT. Ownership if DATA is * transferred to this function. TYPE must be a fixed string. - * CHUNKSIZE is the chunksize requested from the caller. Note that + * CHUNKSIZE is the chunksize requested from the caller. If BASE64 is + * -1 the need for base64 encoding is determined by the content of + * DATA, all other values are take as rtue or false. Note that * op_getmore has similar code but works on PENDING_DATA which is set * here. */ static gpg_error_t @@ -599,11 +601,7 @@ make_data_object (cjson_t result, gpgme_data_t data, size_t chunksize, size_t buflen; int c; - /* Adjust the chunksize if we need to do base64 conversion. */ - if (base64) - chunksize = (chunksize / 4) * 3; - - if (!base64) /* Make sure that we really have a string. */ + if (!base64 || base64 == -1) /* Make sure that we really have a string. */ gpgme_data_write (data, "", 1); buffer = gpgme_data_release_and_get_mem (data, &buflen); @@ -614,6 +612,23 @@ make_data_object (cjson_t result, gpgme_data_t data, size_t chunksize, goto leave; } + if (base64 == -1) + { + base64 = 0; + if (!buflen) + log_fatal ("Appended Nul byte got lost\n"); + if (memchr (buffer, 0, buflen-1)) + { + buflen--; /* Adjust for the extra nul byte. */ + base64 = 1; + } + /* Fixme: We might want to do more advanced heuristics than to + * only look for a Nul. */ + } + + /* Adjust the chunksize if we need to do base64 conversion. */ + if (base64) + chunksize = (chunksize / 4) * 3; xjson_AddStringToObject (result, "type", type); xjson_AddBoolToObject (result, "base64", base64); @@ -667,6 +682,7 @@ static const char hlp_encrypt[] = "\n" "Optional boolean flags (default is false):\n" "base64: Input data is base64 encoded.\n" + "mime: Indicate that data is a MIME object.\n" "armor: Request output in armored format.\n" "always-trust: Request --always-trust option.\n" "no-encrypt-to: Do not use a default recipient.\n" @@ -690,6 +706,7 @@ op_encrypt (cjson_t request, cjson_t result) gpgme_protocol_t protocol; size_t chunksize; int opt_base64; + int opt_mime; char *keystring = NULL; cjson_t j_input; gpgme_data_t input = NULL; @@ -705,6 +722,8 @@ op_encrypt (cjson_t request, cjson_t result) if ((err = get_boolean_flag (request, "base64", 0, &opt_base64))) goto leave; + if ((err = get_boolean_flag (request, "mime", 0, &opt_mime))) + goto leave; if ((err = get_boolean_flag (request, "armor", 0, &abool))) goto leave; @@ -777,6 +796,9 @@ op_encrypt (cjson_t request, cjson_t result) goto leave; } } + if (opt_mime) + gpgme_data_set_encoding (input, GPGME_DATA_ENCODING_MIME); + /* Create an output data object. */ err = gpgme_data_new (&output); @@ -813,6 +835,116 @@ op_encrypt (cjson_t request, cjson_t result) } + +static const char hlp_decrypt[] = + "op: \"decrypt\"\n" + "data: The encrypted data.\n" + "\n" + "Optional parameters:\n" + "protocol: Either \"openpgp\" (default) or \"cms\".\n" + "chunksize: Max number of bytes in the resulting \"data\".\n" + "\n" + "Optional boolean flags (default is false):\n" + "base64: Input data is base64 encoded.\n" + "\n" + "Response on success:\n" + "type: \"plaintext\"\n" + "data: The decrypted data. This may be base64 encoded.\n" + "base64: Boolean indicating whether data is base64 encoded.\n" + "mime: A Boolean indicating whether the data is a MIME object.\n" + "info: An optional object with extra information.\n" + "more: Optional boolean indicating that \"getmore\" is required."; +static gpg_error_t +op_decrypt (cjson_t request, cjson_t result) +{ + gpg_error_t err; + gpgme_ctx_t ctx = NULL; + gpgme_protocol_t protocol; + size_t chunksize; + int opt_base64; + cjson_t j_input; + gpgme_data_t input = NULL; + gpgme_data_t output = NULL; + gpgme_decrypt_result_t decrypt_result; + + if ((err = get_protocol (request, &protocol))) + goto leave; + ctx = get_context (protocol); + if ((err = get_chunksize (request, &chunksize))) + goto leave; + + if ((err = get_boolean_flag (request, "base64", 0, &opt_base64))) + goto leave; + + /* Get the data. Note that INPUT is a shallow data object with the + * storage hold in REQUEST. */ + j_input = cJSON_GetObjectItem (request, "data"); + if (!j_input) + { + err = gpg_error (GPG_ERR_NO_DATA); + goto leave; + } + if (!cjson_is_string (j_input)) + { + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + if (opt_base64) + { + err = data_from_base64_string (&input, j_input); + if (err) + { + error_object (result, "Error decoding Base-64 encoded 'data': %s", + gpg_strerror (err)); + goto leave; + } + } + else + { + err = gpgme_data_new_from_mem (&input, j_input->valuestring, + strlen (j_input->valuestring), 0); + if (err) + { + error_object (result, "Error getting 'data': %s", gpg_strerror (err)); + goto leave; + } + } + + /* Create an output data object. */ + err = gpgme_data_new (&output); + if (err) + { + error_object (result, "Error creating output data object: %s", + gpg_strerror (err)); + goto leave; + } + + /* Decrypt. */ + err = gpgme_op_decrypt_ext (ctx, GPGME_DECRYPT_VERIFY, + input, output); + decrypt_result = gpgme_op_decrypt_result (ctx); + if (err) + { + error_object (result, "Decryption failed: %s", gpg_strerror (err)); + goto leave; + } + gpgme_data_release (input); + input = NULL; + + if (decrypt_result->is_mime) + xjson_AddBoolToObject (result, "mime", 1); + + err = make_data_object (result, output, chunksize, "plaintext", -1); + output = NULL; + + leave: + release_context (ctx); + gpgme_data_release (input); + gpgme_data_release (output); + return err; +} + + static const char hlp_getmore[] = "op: \"getmore\"\n" @@ -947,7 +1079,7 @@ process_request (const char *request) const char * const helpstr; } optbl[] = { { "encrypt", op_encrypt, hlp_encrypt }, - + { "decrypt", op_decrypt, hlp_decrypt }, { "getmore", op_getmore, hlp_getmore }, { "help", op_help, hlp_help }, { NULL } -- cgit v1.2.3 From 55e9a94680370e584fbe5d21161a2cee3fe95744 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 17:59:29 +0200 Subject: core: New convenience constant GPGME_KEYLIST_MODE_LOCATE. * src/gpgme.h.in (GPGME_KEYLIST_MODE_LOCATE): New. Signed-off-by: Werner Koch --- src/gpgme-json.c | 3 +-- src/gpgme.h.in | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index e7aa2284..0beb78f4 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -20,8 +20,7 @@ /* This is tool implements the Native Messaging protocol of web * browsers and provides the server part of it. A Javascript based - * client can be found in lang/javascript. The used data format is - * similar to the API of openpgpjs. + * client can be found in lang/javascript. */ #include diff --git a/src/gpgme.h.in b/src/gpgme.h.in index c81e882f..e3a2eea0 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -373,6 +373,8 @@ gpgme_protocol_t; #define GPGME_KEYLIST_MODE_EPHEMERAL 128 #define GPGME_KEYLIST_MODE_VALIDATE 256 +#define GPGME_KEYLIST_MODE_LOCATE (1|2) + typedef unsigned int gpgme_keylist_mode_t; -- cgit v1.2.3 From 1ae83de262021d7e3676b1466c56d6ebc2ea70c8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 19:28:51 +0200 Subject: doc: Unify comment style in gpgme.h -- Signed-off-by: Werner Koch --- src/gpgme.h.in | 335 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 175 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/src/gpgme.h.in b/src/gpgme.h.in index e3a2eea0..84516f91 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -37,14 +37,14 @@ extern "C" { /* The version of this header should match the one of the library. Do - not use this symbol in your application, use gpgme_check_version - instead. The purpose of this macro is to let autoconf (using the - AM_PATH_GPGME macro) check that this header matches the installed - library. */ + * not use this symbol in your application, use gpgme_check_version + * instead. The purpose of this macro is to let autoconf (using the + * AM_PATH_GPGME macro) check that this header matches the installed + * library. */ #define GPGME_VERSION "@PACKAGE_VERSION@" /* The version number of this header. It may be used to handle minor - API incompatibilities. */ + * API incompatibilities. */ #define GPGME_VERSION_NUMBER @VERSION_NUMBER@ @@ -87,7 +87,7 @@ extern "C" { /* The macro _GPGME_DEPRECATED_OUTSIDE_GPGME suppresses warnings for - fields we must access in GPGME for ABI compatibility. */ + * fields we must access in GPGME for ABI compatibility. */ #ifdef _GPGME_IN_GPGME #define _GPGME_DEPRECATED_OUTSIDE_GPGME(a,b) #else @@ -113,7 +113,7 @@ extern "C" { */ /* The context holds some global state and configuration options, as - well as the results of a crypto operation. */ + * well as the results of a crypto operation. */ struct gpgme_context; typedef struct gpgme_context *gpgme_ctx_t; @@ -124,7 +124,8 @@ typedef struct gpgme_data *gpgme_data_t; /* - * Wrappers for the libgpg-error library. + * Wrappers for the libgpg-error library. They are generally not + * needed and the gpg-error versions may be used instead. */ typedef gpg_error_t gpgme_error_t; @@ -140,7 +141,7 @@ gpgme_err_make (gpgme_err_source_t source, gpgme_err_code_t code) /* The user can define GPGME_ERR_SOURCE_DEFAULT before including this - file to specify a default source for gpgme_error. */ + * file to specify a default source for gpgme_error. */ #ifndef GPGME_ERR_SOURCE_DEFAULT #define GPGME_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1 #endif @@ -167,45 +168,46 @@ gpgme_err_source (gpgme_error_t err) /* Return a pointer to a string containing a description of the error - code in the error value ERR. This function is not thread safe. */ + * code in the error value ERR. This function is not thread safe. */ const char *gpgme_strerror (gpgme_error_t err); /* Return the error string for ERR in the user-supplied buffer BUF of - size BUFLEN. This function is, in contrast to gpg_strerror, - thread-safe if a thread-safe strerror_r() function is provided by - the system. If the function succeeds, 0 is returned and BUF - contains the string describing the error. If the buffer was not - large enough, ERANGE is returned and BUF contains as much of the - beginning of the error string as fits into the buffer. */ + * size BUFLEN. This function is, in contrast to gpg_strerror, + * thread-safe if a thread-safe strerror_r() function is provided by + * the system. If the function succeeds, 0 is returned and BUF + * contains the string describing the error. If the buffer was not + * large enough, ERANGE is returned and BUF contains as much of the + * beginning of the error string as fits into the buffer. */ int gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen); /* Return a pointer to a string containing a description of the error - source in the error value ERR. */ + * source in the error value ERR. */ const char *gpgme_strsource (gpgme_error_t err); /* Retrieve the error code for the system error ERR. This returns - GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report - this). */ + * GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + * this). */ gpgme_err_code_t gpgme_err_code_from_errno (int err); /* Retrieve the system error for the error code CODE. This returns 0 - if CODE is not a system error code. */ + * if CODE is not a system error code. */ int gpgme_err_code_to_errno (gpgme_err_code_t code); /* Retrieve the error code directly from the ERRNO variable. This - returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped - (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ + * returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped + * (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ gpgme_err_code_t gpgme_err_code_from_syserror (void); /* Set the ERRNO variable. This function is the preferred way to set - ERRNO due to peculiarities on WindowsCE. */ + * ERRNO due to peculiarities on WindowsCE. */ void gpgme_err_set_errno (int err); /* Return an error value with the error source SOURCE and the system - error ERR. FIXME: Should be inline. */ + * error ERR. FIXME: Should be inline. */ gpgme_error_t gpgme_err_make_from_errno (gpgme_err_source_t source, int err); -/* Return an error value with the system error ERR. FIXME: Should be inline. */ +/* Return an error value with the system error ERR. + * inline. */ gpgme_error_t gpgme_error_from_errno (int err); @@ -419,7 +421,7 @@ struct _gpgme_sig_notation struct _gpgme_sig_notation *next; /* If NAME is a null pointer, then VALUE contains a policy URL - rather than a notation. */ + * rather than a notation. */ char *name; /* The value of the notation data. */ @@ -634,10 +636,10 @@ struct _gpgme_key_sig /* Same as in gpgme_signature_t. */ gpgme_error_t status; + /* Deprecated; use SIG_CLASS instead. */ #ifdef __cplusplus unsigned int _obsolete_class _GPGME_DEPRECATED(0,4); #else - /* Must be set to SIG_CLASS below. */ unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4); #endif @@ -876,10 +878,10 @@ gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto); gpgme_protocol_t gpgme_get_protocol (gpgme_ctx_t ctx); /* Set the crypto protocol to be used by CTX to PROTO. - gpgme_set_protocol actually sets the backend engine. This sets the - crypto protocol used in engines that support more than one crypto - prococol (for example, an UISERVER can support OpenPGP and CMS). - This is reset to the default with gpgme_set_protocol. */ + * gpgme_set_protocol actually sets the backend engine. This sets the + * crypto protocol used in engines that support more than one crypto + * prococol (for example, an UISERVER can support OpenPGP and CMS). + * This is reset to the default with gpgme_set_protocol. */ gpgme_error_t gpgme_set_sub_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto); @@ -931,47 +933,47 @@ gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_pinentry_mode_t gpgme_get_pinentry_mode (gpgme_ctx_t ctx); /* Set the passphrase callback function in CTX to CB. HOOK_VALUE is - passed as first argument to the passphrase callback function. */ + * passed as first argument to the passphrase callback function. */ void gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, void *hook_value); /* Get the current passphrase callback function in *CB and the current - hook value in *HOOK_VALUE. */ + * hook value in *HOOK_VALUE. */ void gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *cb, void **hook_value); /* Set the progress callback function in CTX to CB. HOOK_VALUE is - passed as first argument to the progress callback function. */ + * passed as first argument to the progress callback function. */ void gpgme_set_progress_cb (gpgme_ctx_t c, gpgme_progress_cb_t cb, void *hook_value); /* Get the current progress callback function in *CB and the current - hook value in *HOOK_VALUE. */ + * hook value in *HOOK_VALUE. */ void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb, void **hook_value); /* Set the status callback function in CTX to CB. HOOK_VALUE is - passed as first argument to the status callback function. */ + * passed as first argument to the status callback function. */ void gpgme_set_status_cb (gpgme_ctx_t c, gpgme_status_cb_t cb, void *hook_value); /* Get the current status callback function in *CB and the current - hook value in *HOOK_VALUE. */ + * hook value in *HOOK_VALUE. */ void gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *cb, void **hook_value); /* This function sets the locale for the context CTX, or the default - locale if CTX is a null pointer. */ + * locale if CTX is a null pointer. */ gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value); /* Get the information about the configured engines. A pointer to the - first engine in the statically allocated linked list is returned. - The returned data is valid until the next gpgme_ctx_set_engine_info. */ + * first engine in the statically allocated linked list is returned. + * The returned data is valid until the next gpgme_ctx_set_engine_info. */ gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx); /* Set the engine info for the context CTX, protocol PROTO, to the - file name FILE_NAME and the home directory HOME_DIR. */ + * file name FILE_NAME and the home directory HOME_DIR. */ gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto, const char *file_name, @@ -993,10 +995,10 @@ gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq); void gpgme_sig_notation_clear (gpgme_ctx_t ctx); /* Add the human-readable notation data with name NAME and value VALUE - to the context CTX, using the flags FLAGS. If NAME is NULL, then - VALUE should be a policy URL. The flag - GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation - data, and false for policy URLs. */ + * to the context CTX, using the flags FLAGS. If NAME is NULL, then + * VALUE should be a policy URL. The flag + * GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation + * data, and false for policy URLs. */ gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name, const char *value, gpgme_sig_notation_flags_t flags); @@ -1020,17 +1022,17 @@ const char *gpgme_get_sender (gpgme_ctx_t ctx); typedef gpgme_error_t (*gpgme_io_cb_t) (void *data, int fd); /* The type of a function that can register FNC as the I/O callback - function for the file descriptor FD with direction dir (0: for writing, - 1: for reading). FNC_DATA should be passed as DATA to FNC. The - function should return a TAG suitable for the corresponding - gpgme_remove_io_cb_t, and an error value. */ + * function for the file descriptor FD with direction dir (0: for writing, + * 1: for reading). FNC_DATA should be passed as DATA to FNC. The + * function should return a TAG suitable for the corresponding + * gpgme_remove_io_cb_t, and an error value. */ typedef gpgme_error_t (*gpgme_register_io_cb_t) (void *data, int fd, int dir, gpgme_io_cb_t fnc, void *fnc_data, void **tag); /* The type of a function that can remove a previously registered I/O - callback function given TAG as returned by the register - function. */ + * callback function given TAG as returned by the register + * function. */ typedef void (*gpgme_remove_io_cb_t) (void *tag); typedef enum @@ -1045,7 +1047,7 @@ gpgme_event_io_t; struct gpgme_io_event_done_data { /* A fatal IPC error or an operational error in state-less - protocols. */ + * protocols. */ gpgme_error_t err; /* An operational errors in session-based protocols. */ @@ -1054,7 +1056,7 @@ struct gpgme_io_event_done_data typedef struct gpgme_io_event_done_data *gpgme_io_event_done_data_t; /* The type of a function that is called when a context finished an - operation. */ + * operation. */ typedef void (*gpgme_event_io_cb_t) (void *data, gpgme_event_io_t type, void *type_data); @@ -1075,13 +1077,13 @@ void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs); void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs); /* Wrappers around the internal I/O functions for use with - gpgme_passphrase_cb_t and gpgme_interact_cb_t. */ + * gpgme_passphrase_cb_t and gpgme_interact_cb_t. */ @API__SSIZE_T@ gpgme_io_read (int fd, void *buffer, size_t count); @API__SSIZE_T@ gpgme_io_write (int fd, const void *buffer, size_t count); int gpgme_io_writen (int fd, const void *buffer, size_t count); /* Process the pending operation and, if HANG is non-zero, wait for - the pending operation to finish. */ + * the pending operation to finish. */ gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang); gpgme_ctx_t gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status, @@ -1100,21 +1102,21 @@ gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx); */ /* Read up to SIZE bytes into buffer BUFFER from the data object with - the handle HANDLE. Return the number of characters read, 0 on EOF - and -1 on error. If an error occurs, errno is set. */ + * the handle HANDLE. Return the number of characters read, 0 on EOF + * and -1 on error. If an error occurs, errno is set. */ typedef @API__SSIZE_T@ (*gpgme_data_read_cb_t) (void *handle, void *buffer, size_t size); /* Write up to SIZE bytes from buffer BUFFER to the data object with - the handle HANDLE. Return the number of characters written, or -1 - on error. If an error occurs, errno is set. */ + * the handle HANDLE. Return the number of characters written, or -1 + * on error. If an error occurs, errno is set. */ typedef @API__SSIZE_T@ (*gpgme_data_write_cb_t) (void *handle, const void *buffer, size_t size); /* Set the current position from where the next read or write starts - in the data object with the handle HANDLE to OFFSET, relativ to - WHENCE. Returns the new offset in bytes from the beginning of the - data object. */ + * in the data object with the handle HANDLE to OFFSET, relativ to + * WHENCE. Returns the new offset in bytes from the beginning of the + * data object. */ typedef @API__OFF_T@ (*gpgme_data_seek_cb_t) (void *handle, @API__OFF_T@ offset, int whence); @@ -1131,19 +1133,19 @@ struct gpgme_data_cbs typedef struct gpgme_data_cbs *gpgme_data_cbs_t; /* Read up to SIZE bytes into buffer BUFFER from the data object with - the handle DH. Return the number of characters read, 0 on EOF and - -1 on error. If an error occurs, errno is set. */ + * the handle DH. Return the number of characters read, 0 on EOF and + * -1 on error. If an error occurs, errno is set. */ @API__SSIZE_T@ gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size); /* Write up to SIZE bytes from buffer BUFFER to the data object with - the handle DH. Return the number of characters written, or -1 on - error. If an error occurs, errno is set. */ + * the handle DH. Return the number of characters written, or -1 on + * error. If an error occurs, errno is set. */ @API__SSIZE_T@ gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size); /* Set the current position from where the next read or write starts - in the data object with the handle DH to OFFSET, relativ to WHENCE. - Returns the new offset in bytes from the beginning of the data - object. */ + * in the data object with the handle DH to OFFSET, relativ to WHENCE. + * Returns the new offset in bytes from the beginning of the data + * object. */ @API__OFF_T@ gpgme_data_seek (gpgme_data_t dh, @API__OFF_T@ offset, int whence); /* Create a new data buffer and return it in R_DH. */ @@ -1153,19 +1155,19 @@ gpgme_error_t gpgme_data_new (gpgme_data_t *r_dh); void gpgme_data_release (gpgme_data_t dh); /* Create a new data buffer filled with SIZE bytes starting from - BUFFER. If COPY is zero, copying is delayed until necessary, and - the data is taken from the original location when needed. */ + * BUFFER. If COPY is zero, copying is delayed until necessary, and + * the data is taken from the original location when needed. */ gpgme_error_t gpgme_data_new_from_mem (gpgme_data_t *r_dh, const char *buffer, size_t size, int copy); /* Destroy the data buffer DH and return a pointer to its content. - The memory has be to released with gpgme_free() by the user. It's - size is returned in R_LEN. */ + * The memory has be to released with gpgme_free() by the user. It's + * size is returned in R_LEN. */ char *gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len); /* Release the memory returned by gpgme_data_release_and_get_mem() and - some other functions. */ + * some other functions. */ void gpgme_free (void *buffer); gpgme_error_t gpgme_data_new_from_cbs (gpgme_data_t *dh, @@ -1184,11 +1186,11 @@ gpgme_error_t gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc); /* Get the file name associated with the data object with handle DH, or - NULL if there is none. */ + * NULL if there is none. */ char *gpgme_data_get_file_name (gpgme_data_t dh); /* Set the file name associated with the data object with handle DH to - FILE_NAME. */ + * FILE_NAME. */ gpgme_error_t gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name); @@ -1201,15 +1203,15 @@ gpgme_data_type_t gpgme_data_identify (gpgme_data_t dh, int reserved); /* Create a new data buffer filled with the content of file FNAME. - COPY must be non-zero. For delayed read, please use - gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */ + * COPY must be non-zero. For delayed read, please use + * gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */ gpgme_error_t gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy); /* Create a new data buffer filled with LENGTH bytes starting from - OFFSET within the file FNAME or stream FP (exactly one must be - non-zero). */ + * OFFSET within the file FNAME or stream FP (exactly one must be + * non-zero). */ gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname, FILE *fp, @API__OFF_T@ offset, size_t length); @@ -1224,7 +1226,7 @@ gpgme_error_t gpgme_data_rewind (gpgme_data_t dh); */ /* Get the key with the fingerprint FPR from the crypto backend. If - SECRET is true, get the secret key. */ + * SECRET is true, get the secret key. */ gpgme_error_t gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key, int secret); @@ -1235,7 +1237,7 @@ gpgme_error_t gpgme_key_from_uid (gpgme_key_t *key, const char *name); void gpgme_key_ref (gpgme_key_t key); /* Release a reference to KEY. If this was the last one the key is - destroyed. */ + * destroyed. */ void gpgme_key_unref (gpgme_key_t key); void gpgme_key_release (gpgme_key_t key); @@ -1274,7 +1276,7 @@ typedef enum gpgme_encrypt_flags_t; /* Encrypt plaintext PLAIN within CTX for the recipients RECP and - store the resulting ciphertext in CIPHER. */ + * store the resulting ciphertext in CIPHER. */ gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgme_data_t plain, @@ -1295,8 +1297,8 @@ gpgme_error_t gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_data_t cipher); /* Encrypt plaintext PLAIN within CTX for the recipients RECP and - store the resulting ciphertext in CIPHER. Also sign the ciphertext - with the signers in CTX. */ + * store the resulting ciphertext in CIPHER. Also sign the ciphertext + * with the signers in CTX. */ gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, @@ -1344,6 +1346,7 @@ struct _gpgme_recipient }; typedef struct _gpgme_recipient *gpgme_recipient_t; + /* An object to return results from a decryption operation. * This structure shall be considered read-only and an application * must not allocate such a structure on its own. */ @@ -1367,22 +1370,24 @@ struct _gpgme_op_decrypt_result gpgme_recipient_t recipients; /* The original file name of the plaintext message, if - available. */ + * available. */ char *file_name; /* A textual representation of the session key used to decrypt the * message, if available */ char *session_key; - /* A string with the symmetric encryption algorithm and mode using - * the format ".". */ + /* A string with the symmetric encryption algorithm and mode using + * the format ".". */ char *symkey_algo; }; typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t; + /* Retrieve a pointer to the result of the decrypt operation. */ gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx); + /* The valid decryption flags. */ typedef enum { @@ -1391,15 +1396,16 @@ typedef enum } gpgme_decrypt_flags_t; + /* Decrypt ciphertext CIPHER within CTX and store the resulting - plaintext in PLAIN. */ + * plaintext in PLAIN. */ gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain); gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain); /* Decrypt ciphertext CIPHER and make a signature verification within - CTX and store the resulting plaintext in PLAIN. */ + * CTX and store the resulting plaintext in PLAIN. */ gpgme_error_t gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain); @@ -1441,7 +1447,7 @@ struct _gpgme_new_signature gpgme_hash_algo_t hash_algo; /* Internal to GPGME, do not use. Must be set to the same value as - CLASS below. */ + * CLASS below. */ unsigned long _obsolete_class; /* Signature creation time. */ @@ -1450,10 +1456,10 @@ struct _gpgme_new_signature /* The fingerprint of the signature. */ char *fpr; + /* Deprecated; use SIG_CLASS instead. */ #ifdef __cplusplus unsigned int _obsolete_class_2; #else - /* Must be set to SIG_CLASS below. */ unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4); #endif @@ -1474,6 +1480,7 @@ struct _gpgme_op_sign_result }; typedef struct _gpgme_op_sign_result *gpgme_sign_result_t; + /* Retrieve a pointer to the result of the signing operation. */ gpgme_sign_result_t gpgme_op_sign_result (gpgme_ctx_t ctx); @@ -1567,6 +1574,7 @@ struct _gpgme_signature }; typedef struct _gpgme_signature *gpgme_signature_t; + /* An object to return the results of a verify operation. * This structure shall be considered read-only and an application * must not allocate such a structure on its own. */ @@ -1586,6 +1594,7 @@ struct _gpgme_op_verify_result }; typedef struct _gpgme_op_verify_result *gpgme_verify_result_t; + /* Retrieve a pointer to the result of the verify operation. */ gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx); @@ -1630,6 +1639,7 @@ struct _gpgme_import_status }; typedef struct _gpgme_import_status *gpgme_import_status_t; + /* Import result object. * This structure shall be considered read-only and an application * must not allocate such a structure on its own. */ @@ -1685,6 +1695,7 @@ struct _gpgme_op_import_result }; typedef struct _gpgme_op_import_result *gpgme_import_result_t; + /* Retrieve a pointer to the result of the import operation. */ gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx); @@ -1742,6 +1753,7 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx, #define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */ #define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */ + /* An object to return result from a key generation. * This structure shall be considered read-only and an application * must not allocate such a structure on its own. */ @@ -1772,9 +1784,10 @@ struct _gpgme_op_genkey_result }; typedef struct _gpgme_op_genkey_result *gpgme_genkey_result_t; + /* Generate a new keypair and add it to the keyring. PUBKEY and - SECKEY should be null for now. PARMS specifies what keys should be - generated. */ + * SECKEY should be null for now. PARMS specifies what keys should be + * generated. */ gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey, gpgme_data_t seckey); gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, @@ -1840,7 +1853,7 @@ gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx); /* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret - keys are also deleted. */ + * keys are also deleted. */ gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret); gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, @@ -1959,7 +1972,7 @@ gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx); */ /* Change the passphrase for KEY. FLAGS is reserved for future use - and must be passed as 0. */ + * and must be passed as 0. */ gpgme_error_t gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags); gpgme_error_t gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key, @@ -2024,7 +2037,7 @@ gpgme_error_t gpgme_op_trustlist_end (gpgme_ctx_t ctx); void gpgme_trust_item_ref (gpgme_trust_item_t item); /* Release a reference to ITEM. If this was the last one the trust - item is destroyed. */ + * item is destroyed. */ void gpgme_trust_item_unref (gpgme_trust_item_t item); @@ -2054,8 +2067,8 @@ gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output, /* Run the command FILE with the arguments in ARGV. Connect stdin to - DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data - streams is NULL, connect to /dev/null instead. */ + * DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data + * streams is NULL, connect to /dev/null instead. */ gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t ctx, const char *file, const char *argv[], gpgme_data_t datain, @@ -2071,6 +2084,7 @@ gpgme_error_t gpgme_op_spawn (gpgme_ctx_t ctx, /* * Low-level Assuan protocol access. */ + typedef gpgme_error_t (*gpgme_assuan_data_cb_t) (void *opaque, const void *data, size_t datalen); @@ -2082,7 +2096,7 @@ typedef gpgme_error_t (*gpgme_assuan_status_cb_t) (void *opaque, const char *status, const char *args); /* Send the Assuan COMMAND and return results via the callbacks. - Asynchronous variant. */ + * Asynchronous variant. */ gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx, const char *command, gpgme_assuan_data_cb_t data_cb, @@ -2093,7 +2107,7 @@ gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx, void *stat_cb_value); /* Send the Assuan COMMAND and return results via the callbacks. - Synchronous variant. */ + * Synchronous variant. */ gpgme_error_t gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx, const char *command, gpgme_assuan_data_cb_t data_cb, @@ -2121,8 +2135,8 @@ typedef struct _gpgme_op_vfs_mount_result *gpgme_vfs_mount_result_t; gpgme_vfs_mount_result_t gpgme_op_vfs_mount_result (gpgme_ctx_t ctx); /* The container is automatically unmounted when the context is reset - or destroyed. Transmission errors are returned directly, - operational errors are returned in OP_ERR. */ + * or destroyed. Transmission errors are returned directly, + * operational errors are returned in OP_ERR. */ gpgme_error_t gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, const char *mount_dir, unsigned int flags, gpgme_error_t *op_err); @@ -2137,8 +2151,8 @@ gpgme_error_t gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], */ /* The expert level at which a configuration option or group of - options should be displayed. See the gpgconf(1) documentation for - more details. */ + * options should be displayed. See the gpgconf(1) documentation for + * more details. */ typedef enum { GPGME_CONF_BASIC = 0, @@ -2151,7 +2165,7 @@ gpgme_conf_level_t; /* The data type of a configuration option argument. See the gpgconf(1) - documentation for more details. */ + * documentation for more details. */ typedef enum { /* Basic types. */ @@ -2175,7 +2189,7 @@ gpgme_conf_type_t; /* This represents a single argument for a configuration option. - Which of the members of value is used depends on the ALT_TYPE. */ + * Which of the members of value is used depends on the ALT_TYPE. */ typedef struct gpgme_conf_arg { struct gpgme_conf_arg *next; @@ -2192,7 +2206,7 @@ typedef struct gpgme_conf_arg /* The flags of a configuration option. See the gpgconf - documentation for details. */ + * documentation for details. */ #define GPGME_CONF_GROUP (1 << 0) #define GPGME_CONF_OPTIONAL (1 << 1) #define GPGME_CONF_LIST (1 << 2) @@ -2204,7 +2218,7 @@ typedef struct gpgme_conf_arg /* The representation of a single configuration option. See the - gpg-conf documentation for details. */ + * gpg-conf documentation for details. */ typedef struct gpgme_conf_opt { struct gpgme_conf_opt *next; @@ -2249,7 +2263,7 @@ typedef struct gpgme_conf_opt /* The representation of a component that can be configured. See the - gpg-conf documentation for details. */ + * gpg-conf documentation for details. */ typedef struct gpgme_conf_comp { struct gpgme_conf_comp *next; @@ -2272,9 +2286,9 @@ typedef struct gpgme_conf_comp /* Allocate a new gpgme_conf_arg_t. If VALUE is NULL, a "no arg - default" is prepared. If type is a string type, VALUE should point - to the string. Else, it should point to an unsigned or signed - integer respectively. */ + * default" is prepared. If type is a string type, VALUE should point + * to the string. Else, it should point to an unsigned or signed + * integer respectively. */ gpgme_error_t gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, gpgme_conf_type_t type, const void *value); @@ -2282,10 +2296,10 @@ gpgme_error_t gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, void gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type); /* Register a change for the value of OPT to ARG. If RESET is 1 (do - not use any values but 0 or 1), ARG is ignored and the option is - not changed (reverting a previous change). Otherwise, if ARG is - NULL, the option is cleared or reset to its default. The change - is done with gpgconf's --runtime option to immediately take effect. */ + * not use any values but 0 or 1), ARG is ignored and the option is + * not changed (reverting a previous change). Otherwise, if ARG is + * NULL, the option is cleared or reset to its default. The change + * is done with gpgconf's --runtime option to immediately take effect. */ gpgme_error_t gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg); @@ -2376,16 +2390,17 @@ gpgme_query_swdb_result_t gpgme_op_query_swdb_result (gpgme_ctx_t ctx); int gpgme_set_global_flag (const char *name, const char *value); /* Check that the library fulfills the version requirement. Note: - This is here only for the case where a user takes a pointer from - the old version of this function. The new version and macro for - run-time checks are below. */ + * This is here only for the case where a user takes a pointer from + * the old version of this function. The new version and macro for + * run-time checks are below. */ const char *gpgme_check_version (const char *req_version); -/* Check that the library fulfills the version requirement and check - for struct layout mismatch involving bitfields. */ +/* Do not call this directly; use the macro below. */ const char *gpgme_check_version_internal (const char *req_version, size_t offset_sig_validity); +/* Check that the library fulfills the version requirement and check + * for struct layout mismatch involving bitfields. */ #define gpgme_check_version(req_version) \ gpgme_check_version_internal (req_version, \ offsetof (struct _gpgme_signature, validity)) @@ -2394,19 +2409,19 @@ const char *gpgme_check_version_internal (const char *req_version, const char *gpgme_get_dirinfo (const char *what); /* Get the information about the configured and installed engines. A - pointer to the first engine in the statically allocated linked list - is returned in *INFO. If an error occurs, it is returned. The - returned data is valid until the next gpgme_set_engine_info. */ + * pointer to the first engine in the statically allocated linked list + * is returned in *INFO. If an error occurs, it is returned. The + * returned data is valid until the next gpgme_set_engine_info. */ gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info); /* Set the default engine info for the protocol PROTO to the file name - FILE_NAME and the home directory HOME_DIR. */ + * FILE_NAME and the home directory HOME_DIR. */ gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto, const char *file_name, const char *home_dir); /* Verify that the engine implementing PROTO is installed and - available. */ + * available. */ gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto); @@ -2415,15 +2430,15 @@ void gpgme_result_ref (void *result); void gpgme_result_unref (void *result); /* Return a public key algorithm string (e.g. "rsa2048"). Caller must - free using gpgme_free. */ + * free using gpgme_free. */ char *gpgme_pubkey_algo_string (gpgme_subkey_t subkey); /* Return a statically allocated string with the name of the public - key algorithm ALGO, or NULL if that name is not known. */ + * key algorithm ALGO, or NULL if that name is not known. */ const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo); /* Return a statically allocated string with the name of the hash - algorithm ALGO, or NULL if that name is not known. */ + * algorithm ALGO, or NULL if that name is not known. */ const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo); /* Return the addr-spec from a user id. Caller must free the result @@ -2575,7 +2590,7 @@ gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key, _GPGME_DEPRECATED(1,7); /* The possible signature stati. Deprecated, use error value in sig - status. */ + * status. */ typedef enum { GPGME_SIG_STAT_NONE = 0, @@ -2592,7 +2607,7 @@ _gpgme_sig_stat_t; typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED(0,4); /* The available key and signature attributes. Deprecated, use the - individual result structures instead. */ + * individual result structures instead. */ typedef enum { GPGME_ATTR_KEYID = 1, @@ -2632,18 +2647,18 @@ _gpgme_attr_t; typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED(0,4); /* Retrieve the signature status of signature IDX in CTX after a - successful verify operation in R_STAT (if non-null). The creation - time stamp of the signature is returned in R_CREATED (if non-null). - The function returns a string containing the fingerprint. - Deprecated, use verify result directly. */ + * successful verify operation in R_STAT (if non-null). The creation + * time stamp of the signature is returned in R_CREATED (if non-null). + * The function returns a string containing the fingerprint. + * Deprecated, use verify result directly. */ const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, _gpgme_sig_stat_t *r_stat, time_t *r_created) _GPGME_DEPRECATED(0,4); /* Retrieve certain attributes of a signature. IDX is the index - number of the signature after a successful verify operation. WHAT - is an attribute where GPGME_ATTR_EXPIRE is probably the most useful - one. WHATIDX is to be passed as 0 for most attributes . */ + * number of the signature after a successful verify operation. WHAT + * is an attribute where GPGME_ATTR_EXPIRE is probably the most useful + * one. WHATIDX is to be passed as 0 for most attributes . */ unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx, _gpgme_attr_t what, int whatidx) _GPGME_DEPRECATED(0,4); @@ -2653,13 +2668,13 @@ const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx, /* Get the key used to create signature IDX in CTX and return it in - R_KEY. */ + * R_KEY. */ gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) _GPGME_DEPRECATED(0,4); /* Create a new data buffer which retrieves the data from the callback - function READ_CB. Deprecated, please use gpgme_data_new_from_cbs - instead. */ + * function READ_CB. Deprecated, please use gpgme_data_new_from_cbs + * instead. */ gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, int (*read_cb) (void*,char *, size_t,size_t*), @@ -2667,34 +2682,34 @@ gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of KEY, which has to be - representable by a string. IDX specifies the sub key or user ID - for attributes related to sub keys or user IDs. Deprecated, use - key structure directly instead. */ + * representable by a string. IDX specifies the sub key or user ID + * for attributes related to sub keys or user IDs. Deprecated, use + * key structure directly instead. */ const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what, const void *reserved, int idx) _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of KEY, which has to be - representable by an unsigned integer. IDX specifies the sub key or - user ID for attributes related to sub keys or user IDs. - Deprecated, use key structure directly instead. */ + * representable by an unsigned integer. IDX specifies the sub key or + * user ID for attributes related to sub keys or user IDs. + * Deprecated, use key structure directly instead. */ unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what, const void *reserved, int idx) _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of a signature on user ID - UID_IDX in KEY, which has to be representable by a string. IDX - specifies the signature. Deprecated, use key structure directly - instead. */ + * UID_IDX in KEY, which has to be representable by a string. IDX + * specifies the signature. Deprecated, use key structure directly + * instead. */ const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what, const void *reserved, int idx) _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of a signature on user ID - UID_IDX in KEY, which has to be representable by an unsigned - integer string. IDX specifies the signature. Deprecated, use key - structure directly instead. */ + * UID_IDX in KEY, which has to be representable by an unsigned + * integer string. IDX specifies the signature. Deprecated, use key + * structure directly instead. */ unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what, const void *reserved, int idx) @@ -2705,21 +2720,21 @@ gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr) _GPGME_DEPRECATED(0,4); /* Release the trust item ITEM. Deprecated, use - gpgme_trust_item_unref. */ + * gpgme_trust_item_unref. */ void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of ITEM, which has to be - representable by a string. Deprecated, use trust item structure - directly. */ + * representable by a string. Deprecated, use trust item structure + * directly. */ const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item, _gpgme_attr_t what, const void *reserved, int idx) _GPGME_DEPRECATED(0,4); /* Return the value of the attribute WHAT of KEY, which has to be - representable by an integer. IDX specifies a running index if the - attribute appears more than once in the key. Deprecated, use trust - item structure directly. */ + * representable by an integer. IDX specifies a running index if the + * attribute appears more than once in the key. Deprecated, use trust + * item structure directly. */ int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what, const void *reserved, int idx) _GPGME_DEPRECATED(0,4); -- cgit v1.2.3 From 67b4dafb6d3fe2b5ab889417126ca5d509c0e3ca Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 19:30:50 +0200 Subject: doc: Update copyright years and change two URLs. -- Signed-off-by: Werner Koch --- src/gpgme.h.in | 3 ++- src/versioninfo.rc.in | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 84516f91..49fafb90 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1,6 +1,6 @@ /* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*- * Copyright (C) 2000 Werner Koch (dd9jn) - * Copyright (C) 2001-2017 g10 Code GmbH + * Copyright (C) 2001-2018 g10 Code GmbH * * This file is part of GPGME. * @@ -16,6 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . + * SPDX-License-Identifier: LGPL-2.1+ * * Generated from gpgme.h.in for @GPGME_CONFIG_HOST@. */ diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in index 2b1cc811..88b662ea 100644 --- a/src/versioninfo.rc.in +++ b/src/versioninfo.rc.in @@ -39,7 +39,7 @@ BEGIN VALUE "FileDescription", "GPGME - GnuPG Made Easy\0" VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0" VALUE "InternalName", "gpgme\0" - VALUE "LegalCopyright", "Copyright © 2001-2017 g10 Code GmbH\0" + VALUE "LegalCopyright", "Copyright © 2001-2018 g10 Code GmbH\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "gpgme.dll\0" VALUE "PrivateBuild", "\0" -- cgit v1.2.3 From 8e34a14fe694a8c765973aaa3a8b2a2d2c3ba8b9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 18 Apr 2018 20:11:27 +0200 Subject: json: Add stpcpy replacement. * src/gpgme-json.c [!HAVE_STPCPY](_my_stpcpy): New. Signed-off-by: Werner Koch --- src/gpgme-json.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 0beb78f4..f1e9f256 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -114,6 +114,19 @@ static struct #define spacep(p) (*(p) == ' ' || *(p) == '\t') +#ifndef HAVE_STPCPY +static GPGRT_INLINE char * +_my_stpcpy (char *a, const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + return a; +} +#define stpcpy(a,b) _my_stpcpy ((a), (b)) +#endif /*!HAVE_STPCPY*/ + + static void xoutofcore (const char *type) -- cgit v1.2.3 From b52a91f5a6818db6b3dd7ce86c01b5d5f6700d0d Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 19 Apr 2018 10:34:32 +0200 Subject: core: Remove leftover debug output. * src/verify.c (_gpgme_verify_status_handler): Remove debug output. -- Actually this is a real bug because it uses a debug function available only in the new libgpg-error versions. Time to call Jenkins back from vacation; there are rumors that he has been seen in the city looking for a new Ryzen tail coat. Signed-off-by: Werner Koch --- src/verify.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/verify.c b/src/verify.c index bd437c9a..26b205aa 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1096,7 +1096,6 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime); if (err) return err; - gpgrt_log_debug ("verify.c: setting mime to %d\n", mime); opd->result.is_mime = !!mime; } break; -- cgit v1.2.3 From ab43d85b9a76fb5ba321f4c7280b4d72bfd67f59 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 19 Apr 2018 16:19:47 +0200 Subject: json: Remove the -noinstall flag used during development. * src/Makefile.am (gpgme-json_LDFLAGS): Remove. -- Reported-by: Alon Bar-Lev Signed-off-by: Werner Koch --- src/Makefile.am | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index c2d4a843..0a196e0c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -104,8 +104,6 @@ gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@ gpgme_json_SOURCES = gpgme-json.c cJSON.c cJSON.h gpgme_json_LDADD = -lm libgpgme.la $(GPG_ERROR_LIBS) -# We use -no-install temporary during development. -gpgme_json_LDFLAGS = -no-install if HAVE_W32_SYSTEM -- cgit v1.2.3 From f779362ffbc7b9334d98f9ee50bfe3c2dc177215 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 20 Apr 2018 10:32:37 +0200 Subject: core: Remove another debug output leftover. * src/decrypt.c (_gpgme_decrypt_status_handler): Remove log debug. Signed-off-by: Werner Koch --- src/decrypt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/decrypt.c b/src/decrypt.c index 155e18ef..0fc7019c 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -414,7 +414,6 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime); if (err) return err; - gpgrt_log_debug ("decrypt.c setting mime to %d\n", mime); opd->result.is_mime = !!mime; } break; -- cgit v1.2.3 From 7706fa2c922f5e02570b01f145ed474e82341042 Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Fri, 20 Apr 2018 14:30:53 +0200 Subject: core: Do not modify args for ignored failures * src/op-support.c (_gpgme_parse_failure): Ignore gpg-exit failures before modifying args. -- For op_decrypt_verify the status handler for both decrypt and verify would parse the failure when the first parser ignored the failure. This resulted in an ERR_INV_ENGINE as the first call to parse_failure modified the args. GnuPG-Bug-Id: T3919 --- src/op-support.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/op-support.c b/src/op-support.c index 03f274cf..9414e612 100644 --- a/src/op-support.c +++ b/src/op-support.c @@ -414,6 +414,9 @@ _gpgme_parse_failure (char *args) { char *where, *which; + if (!strncmp (args, "gpg-exit", 8)) + return 0; + where = strchr (args, ' '); if (!where) return trace_gpg_error (GPG_ERR_INV_ENGINE); @@ -425,9 +428,5 @@ _gpgme_parse_failure (char *args) if (where) *where = '\0'; - where = args; - if (!strcmp (where, "gpg-exit")) - return 0; - return atoi (which); } -- cgit v1.2.3