diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/encrypt-sign.c | 111 | ||||
-rw-r--r-- | src/encrypt.c | 106 | ||||
-rw-r--r-- | src/engine-backend.h | 2 | ||||
-rw-r--r-- | src/engine-gpg.c | 70 | ||||
-rw-r--r-- | src/engine-gpgsm.c | 58 | ||||
-rw-r--r-- | src/engine-uiserver.c | 59 | ||||
-rw-r--r-- | src/engine.c | 10 | ||||
-rw-r--r-- | src/engine.h | 2 | ||||
-rw-r--r-- | src/gpgme-json.c | 74 | ||||
-rw-r--r-- | src/gpgme.def | 5 | ||||
-rw-r--r-- | src/gpgme.h.in | 30 | ||||
-rw-r--r-- | src/libgpgme.vers | 9 |
12 files changed, 405 insertions, 131 deletions
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; |