aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--doc/gpgme.texi43
-rw-r--r--src/context.h8
-rw-r--r--src/engine-backend.h3
-rw-r--r--src/engine-gpg.c31
-rw-r--r--src/engine-gpgsm.c4
-rw-r--r--src/engine-uiserver.c7
-rw-r--r--src/engine.c6
-rw-r--r--src/engine.h3
-rw-r--r--src/gpgme.c47
-rw-r--r--src/gpgme.def3
-rw-r--r--src/gpgme.h.in6
-rw-r--r--src/libgpgme.vers3
-rw-r--r--src/verify.c3
-rw-r--r--tests/gpg/t-verify.c49
-rw-r--r--tests/run-sign.c16
-rw-r--r--tests/run-verify.c16
17 files changed, 234 insertions, 20 deletions
diff --git a/NEWS b/NEWS
index f5d7ce06..38f38d6d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ Noteworthy changes in version 1.7.2 (unreleased)
------------------------------------------------
+ * Interface changes relative to the 1.7.1 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgme_set_sender NEW.
+ gpgme_get_sender NEW.
+
+
Noteworthy changes in version 1.7.1 (2016-10-18)
------------------------------------------------
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index cc598887..9fae9aaf 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -186,6 +186,7 @@ Context Attributes
* Protocol Selection:: Selecting the protocol used by a context.
* Crypto Engine:: Configuring the crypto engine.
+* Setting the Sender:: How to tell the engine the sender.
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
* Text Mode:: Choosing canonical text mode.
* Offline Mode:: Choosing offline mode.
@@ -2366,6 +2367,7 @@ started. In fact, these references are accessed through the
@menu
* Protocol Selection:: Selecting the protocol used by a context.
* Crypto Engine:: Configuring the crypto engine.
+* Setting the Sender:: How to tell the engine the sender.
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
* Text Mode:: Choosing canonical text mode.
* Offline Mode:: Choosing offline mode.
@@ -2448,6 +2450,47 @@ successful, or an eror code on failure.
@end deftypefun
+@node Setting the Sender
+@subsection How to tell the engine the sender.
+@cindex context, sender
+@cindex sender
+@cindex From:
+
+Some engines can make use of the sender’s address, for example to
+figure out the best user id in certain trust models. For verification
+and signing of mails, it is thus suggested to let the engine know the
+sender ("From:") address. @acronym{GPGME} provides two functions to
+accomplish that. Note that the esoteric use of multiple "From:"
+addresses is not supported.
+
+@deftypefun gpgme_error_t gpgme_set_sender @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{int @var{address}})
+
+The function @code{gpgme_set_sender} specifies the sender address for
+use in sign and verify operations. @var{address} is expected to be
+the ``addr-spec'' part of an address but my also be a complete mailbox
+address, in which case this function extracts the ``addr-spec'' from
+it. Using @code{NULL} for @var{address} clears the sender address.
+
+The function returns 0 on success or an error code on failure. The
+most likely failure is that no valid ``addr-spec'' was found in
+@var{address}.
+
+@end deftypefun
+
+@deftypefun @w{const char *} gpgme_get_sender @
+ (@w{gpgme_ctx_t @var{ctx}})
+
+The function @code{gpgme_get_sender} returns the current sender
+address from the context, or NULL if none was set. The returned
+value is valid as long as the @var{ctx} is valid and
+@code{gpgme_set_sender} has not been called again.
+
+@end deftypefun
+
+
+
@c FIXME: Unfortunately, using @acronym here breaks texi2dvi.
@node ASCII Armor
@subsection @acronym{ASCII} Armor
diff --git a/src/context.h b/src/context.h
index 4b12c3bd..f6c1ad1e 100644
--- a/src/context.h
+++ b/src/context.h
@@ -119,16 +119,18 @@ struct gpgme_context
/* Number of certs to be included. */
unsigned int include_certs;
- /* The number of keys in signers. */
+ /* The actual number of keys in SIGNERS, the allocated size of the
+ * array, and the array with the signing keys. */
unsigned int signers_len;
-
- /* Size of the following array. */
unsigned int signers_size;
gpgme_key_t *signers;
/* The signature notations for this context. */
gpgme_sig_notation_t sig_notations;
+ /* The sender's addr-spec or NULL. */
+ char *sender;
+
/* The locale for the pinentry. */
char *lc_ctype;
char *lc_messages;
diff --git a/src/engine-backend.h b/src/engine-backend.h
index ccab0e3e..e02c7157 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -111,7 +111,8 @@ struct engine_ops
gpgme_ctx_t ctx /* FIXME */);
gpgme_error_t (*trustlist) (void *engine, const char *pattern);
gpgme_error_t (*verify) (void *engine, gpgme_data_t sig,
- gpgme_data_t signed_text, gpgme_data_t plaintext);
+ gpgme_data_t signed_text, gpgme_data_t plaintext,
+ gpgme_ctx_t ctx);
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
unsigned int flags);
gpgme_error_t (*opassuan_transact) (void *engine,
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 4415c946..cb52dea7 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -1646,6 +1646,23 @@ append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
static gpgme_error_t
+append_args_from_sender (engine_gpg_t gpg, gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+
+ if (ctx->sender && have_gpg_version (gpg, "2.1.15"))
+ {
+ err = add_arg (gpg, "--sender");
+ if (!err)
+ err = add_arg (gpg, ctx->sender);
+ }
+ else
+ err = 0;
+ return err;
+}
+
+
+static gpgme_error_t
append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
{
gpgme_error_t err = 0;
@@ -1893,6 +1910,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
err = append_args_from_signers (gpg, ctx);
if (!err)
+ err = append_args_from_sender (gpg, ctx);
+
+ if (!err)
err = append_args_from_sig_notations (gpg, ctx);
/* Tell the gpg object about the data. */
@@ -2794,6 +2814,8 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (!err)
err = append_args_from_signers (gpg, ctx);
if (!err)
+ err = append_args_from_sender (gpg, ctx);
+ if (!err)
err = append_args_from_sig_notations (gpg, ctx);
if (gpgme_data_get_file_name (in))
@@ -2845,12 +2867,15 @@ gpg_trustlist (void *engine, const char *pattern)
static gpgme_error_t
gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
- gpgme_data_t plaintext)
+ gpgme_data_t plaintext, gpgme_ctx_t ctx)
{
engine_gpg_t gpg = engine;
- gpgme_error_t err = 0;
+ gpgme_error_t err;
- if (plaintext)
+ err = append_args_from_sender (gpg, ctx);
+ if (err)
+ ;
+ else if (plaintext)
{
/* Normal or cleartext signature. */
err = add_arg (gpg, "--output");
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index e7e2a20d..0ce4a6d1 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -1901,11 +1901,13 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
static gpgme_error_t
gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
- gpgme_data_t plaintext)
+ gpgme_data_t plaintext, gpgme_ctx_t ctx)
{
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
+ (void)ctx;
+
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index 63e77de6..76fa4d79 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -1243,13 +1243,16 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
/* FIXME: Missing a way to specify --silent. */
static gpgme_error_t
uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
- gpgme_data_t plaintext)
+ gpgme_data_t plaintext, gpgme_ctx_t ctx)
{
engine_uiserver_t uiserver = engine;
gpgme_error_t err;
const char *protocol;
char *cmd;
+ (void)ctx; /* FIXME: We should to add a --sender option to the
+ * UISever protocol. */
+
if (!uiserver)
return gpg_error (GPG_ERR_INV_VALUE);
if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
@@ -1395,6 +1398,6 @@ struct engine_ops _gpgme_engine_ops_uiserver =
uiserver_cancel,
NULL, /* cancel_op */
NULL, /* passwd */
- NULL, /* set_pinentry_mode */
+ NULL, /* set_pinentry_mode */
NULL /* opspawn */
};
diff --git a/src/engine.c b/src/engine.c
index a1173a07..f5dfe51f 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -902,7 +902,8 @@ _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
gpgme_error_t
_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
- gpgme_data_t signed_text, gpgme_data_t plaintext)
+ gpgme_data_t signed_text, gpgme_data_t plaintext,
+ gpgme_ctx_t ctx)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -910,7 +911,8 @@ _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
if (!engine->ops->verify)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
+ return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
+ ctx);
}
diff --git a/src/engine.h b/src/engine.h
index 4ce2bed1..2999ab64 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -152,7 +152,8 @@ gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine,
const char *pattern);
gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
gpgme_data_t signed_text,
- gpgme_data_t plaintext);
+ gpgme_data_t plaintext,
+ gpgme_ctx_t ctx);
gpgme_error_t _gpgme_engine_op_getauditlog (engine_t engine,
gpgme_data_t output,
diff --git a/src/gpgme.c b/src/gpgme.c
index d59f8080..6d0dbffa 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -38,6 +38,7 @@
#include "debug.h"
#include "priv-io.h"
#include "sys-util.h"
+#include "mbox-util.h"
/* The default locale. */
@@ -275,12 +276,10 @@ gpgme_release (gpgme_ctx_t ctx)
_gpgme_release_result (ctx);
_gpgme_signers_clear (ctx);
_gpgme_sig_notation_clear (ctx);
- if (ctx->signers)
- free (ctx->signers);
- if (ctx->lc_ctype)
- free (ctx->lc_ctype);
- if (ctx->lc_messages)
- free (ctx->lc_messages);
+ free (ctx->sender);
+ free (ctx->signers);
+ free (ctx->lc_ctype);
+ free (ctx->lc_messages);
_gpgme_engine_info_release (ctx->engine_info);
ctx->engine_info = NULL;
DESTROY_LOCK (ctx->lock);
@@ -459,6 +458,42 @@ gpgme_get_protocol_name (gpgme_protocol_t protocol)
}
}
+
+/* Store the sender's address in the context. ADDRESS is addr-spec of
+ * mailbox but my also be a complete mailbox, in which case this
+ * function extracts the addr-spec from it. Returns 0 on success or
+ * an error code if no valid addr-spec could be extracted from
+ * ADDRESS. */
+gpgme_error_t
+gpgme_set_sender (gpgme_ctx_t ctx, const char *address)
+{
+ char *p = NULL;
+
+ TRACE_BEG1 (DEBUG_CTX, "gpgme_set_sender", ctx, "sender='%s'",
+ address?address:"(null)");
+
+ if (!ctx || (address && !(p = _gpgme_mailbox_from_userid (address))))
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ free (ctx->sender);
+ ctx->sender = p;
+ return TRACE_ERR (0);
+}
+
+
+/* Return the sender's address (addr-spec part) from the context or
+ * NULL if none was set. The returned value is valid as long as the
+ * CTX is valid and gpgme_set_sender has not been used. */
+const char *
+gpgme_get_sender (gpgme_ctx_t ctx)
+{
+ TRACE1 (DEBUG_CTX, "gpgme_get_sender", ctx, "sender='%s'",
+ ctx?ctx->sender:"");
+
+ return ctx->sender;
+}
+
+
/* Enable or disable the use of an ascii armor for all output. */
void
gpgme_set_armor (gpgme_ctx_t ctx, int use_armor)
diff --git a/src/gpgme.def b/src/gpgme.def
index c94c9607..d633df57 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -246,5 +246,8 @@ EXPORTS
gpgme_addrspec_from_uid @186
+ gpgme_set_sender @187
+ gpgme_get_sender @188
+
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 5c914ae7..94ef51de 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1161,6 +1161,12 @@ gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
/* Get the sig notations for this context. */
gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx);
+/* Store a sender address in the context. */
+gpgme_error_t gpgme_set_sender (gpgme_ctx_t ctx, const char *address);
+
+/* Get the sender address from the context. */
+const char *gpgme_get_sender (gpgme_ctx_t ctx);
+
/*
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index d3962db0..42f00d5a 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -119,6 +119,9 @@ GPGME_1.1 {
gpgme_op_interact;
gpgme_addrspec_from_uid;
+
+ gpgme_set_sender;
+ gpgme_get_sender;
};
diff --git a/src/verify.c b/src/verify.c
index eb1cc108..faa8deb9 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -1104,7 +1104,8 @@ verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
if (!sig)
return gpg_error (GPG_ERR_NO_DATA);
- return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
+ return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext,
+ ctx);
}
diff --git a/tests/gpg/t-verify.c b/tests/gpg/t-verify.c
index 9842d3af..f955cc9d 100644
--- a/tests/gpg/t-verify.c
+++ b/tests/gpg/t-verify.c
@@ -209,6 +209,7 @@ main (int argc, char *argv[])
gpgme_error_t err;
gpgme_data_t sig, text;
gpgme_verify_result_t result;
+ const char *s;
(void)argc;
(void)argv;
@@ -270,6 +271,54 @@ main (int argc, char *argv[])
exit (1);
}
+ /* Checking that set/get_sernder works. */
+ err = gpgme_set_sender (ctx, "[email protected]");
+ fail_if_err (err);
+ s = gpgme_get_sender (ctx);
+ if (!s || strcmp (s, "[email protected]"))
+ {
+ fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ err = gpgme_set_sender (ctx, "<[email protected]>");
+ fail_if_err (err);
+ s = gpgme_get_sender (ctx);
+ if (!s || strcmp (s, "[email protected]"))
+ {
+ fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ err = gpgme_set_sender (ctx, "Foo bar (comment) <[email protected]>");
+ fail_if_err (err);
+ s = gpgme_get_sender (ctx);
+ if (!s || strcmp (s, "[email protected]"))
+ {
+ fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ err = gpgme_set_sender (ctx, "foo");
+ if (gpgme_err_code (err) != GPG_ERR_INV_VALUE)
+ {
+ fprintf (stderr, "%s:%i: gpgme_set_sender didn't detect bogus address\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+ /* (the former address should still be there.) */
+ s = gpgme_get_sender (ctx);
+ if (!s || strcmp (s, "[email protected]"))
+ {
+ fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+
gpgme_data_release (sig);
gpgme_data_release (text);
gpgme_release (ctx);
diff --git a/tests/run-sign.c b/tests/run-sign.c
index 70853ed6..f790cb64 100644
--- a/tests/run-sign.c
+++ b/tests/run-sign.c
@@ -83,6 +83,7 @@ show_usage (int ex)
" --uiserver use the UI server\n"
" --loopback use a loopback pinentry\n"
" --key NAME use key NAME for signing\n"
+ " --sender MBOX use MBOX as sender address\n"
, stderr);
exit (ex);
}
@@ -101,6 +102,7 @@ main (int argc, char **argv)
gpgme_sign_result_t result;
int print_status = 0;
int use_loopback = 0;
+ const char *sender = NULL;
if (argc)
{ argc--; argv++; }
@@ -148,6 +150,14 @@ main (int argc, char **argv)
key_string = *argv;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--sender"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ sender = *argv;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--loopback"))
{
use_loopback = 1;
@@ -192,6 +202,12 @@ main (int argc, char **argv)
gpgme_key_unref (akey);
}
+ if (sender)
+ {
+ err = gpgme_set_sender (ctx, sender);
+ fail_if_err (err);
+ }
+
err = gpgme_data_new_from_file (&in, *argv, 1);
if (err)
{
diff --git a/tests/run-verify.c b/tests/run-verify.c
index ebc20d97..22242c00 100644
--- a/tests/run-verify.c
+++ b/tests/run-verify.c
@@ -221,6 +221,7 @@ show_usage (int ex)
" --status print status lines from the backend\n"
" --openpgp use the OpenPGP protocol (default)\n"
" --cms use the CMS protocol\n"
+ " --sender MBOX use MBOX as sender address\n"
, stderr);
exit (ex);
}
@@ -239,6 +240,7 @@ main (int argc, char **argv)
gpgme_data_t msg = NULL;
gpgme_verify_result_t result;
int print_status = 0;
+ const char *sender = NULL;
if (argc)
{ argc--; argv++; }
@@ -273,6 +275,14 @@ main (int argc, char **argv)
protocol = GPGME_PROTOCOL_CMS;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--sender"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ sender = *argv;
+ argc--; argv++;
+ }
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@@ -313,6 +323,12 @@ main (int argc, char **argv)
}
/* gpgme_set_ctx_flag (ctx, "raw-description", "1"); */
+ if (sender)
+ {
+ err = gpgme_set_sender (ctx, sender);
+ fail_if_err (err);
+ }
+
err = gpgme_data_new_from_stream (&sig, fp_sig);
if (err)
{