aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/encrypt-sign.c111
-rw-r--r--src/encrypt.c106
-rw-r--r--src/engine-backend.h2
-rw-r--r--src/engine-gpg.c70
-rw-r--r--src/engine-gpgsm.c58
-rw-r--r--src/engine-uiserver.c59
-rw-r--r--src/engine.c10
-rw-r--r--src/engine.h2
-rw-r--r--src/gpgme-json.c74
-rw-r--r--src/gpgme.def5
-rw-r--r--src/gpgme.h.in30
-rw-r--r--src/libgpgme.vers9
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;