core: New API functions gpgme_set_sender, gpgme_get_sender.
* src/context.h (struct gpgme_context): Add field 'sender'. * src/gpgme.c: Include mbox-util.h. (gpgme_release): Free SENDER. (gpgme_set_sender): New. (gpgme_get_sender): New. * src/gpgme.def, src/libgpgme.vers: Add new functions. * src/engine-gpg.c (append_args_from_sender): New. (gpg_encrypt_sign, gpg_sign): Call append_args_from_sender. (gpg_verify): Add arg CTX. Call append_args_from_sender/ * src/engine-gpgsm.c (gpgsm_verify): Add dummy arg CTX. * src/engine-uiserver.c (uiserver_verify): Ditto. * src/engine.c (_gpgme_engine_op_verify): Add arg CTX. * src/verify.c (verify_start): Pass CTX to engine function. * tests/gpg/t-verify.c (main): Add some checks for new functions. * tests/run-sign.c (main): Add option --sender. * tests/run-verify.c (main): Ditto. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
26cbba3c9c
commit
b8159eadb5
6
NEWS
6
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)
|
||||
------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -1645,6 +1645,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 */)
|
||||
{
|
||||
@ -1892,6 +1909,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
|
||||
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);
|
||||
|
||||
@ -2793,6 +2813,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);
|
||||
|
||||
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
47
src/gpgme.c
47
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)
|
||||
|
@ -246,5 +246,8 @@ EXPORTS
|
||||
|
||||
gpgme_addrspec_from_uid @186
|
||||
|
||||
gpgme_set_sender @187
|
||||
gpgme_get_sender @188
|
||||
|
||||
; END
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -119,6 +119,9 @@ GPGME_1.1 {
|
||||
gpgme_op_interact;
|
||||
|
||||
gpgme_addrspec_from_uid;
|
||||
|
||||
gpgme_set_sender;
|
||||
gpgme_get_sender;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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, "foo@example.org");
|
||||
fail_if_err (err);
|
||||
s = gpgme_get_sender (ctx);
|
||||
if (!s || strcmp (s, "foo@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
err = gpgme_set_sender (ctx, "<bar@example.org>");
|
||||
fail_if_err (err);
|
||||
s = gpgme_get_sender (ctx);
|
||||
if (!s || strcmp (s, "bar@example.org"))
|
||||
{
|
||||
fprintf (stderr, "%s:%i: gpgme_{set,get}_sender mismatch\n",
|
||||
__FILE__, __LINE__);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
err = gpgme_set_sender (ctx, "Foo bar (comment) <foo@example.org>");
|
||||
fail_if_err (err);
|
||||
s = gpgme_get_sender (ctx);
|
||||
if (!s || strcmp (s, "foo@example.org"))
|
||||
{
|
||||
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, "foo@example.org"))
|
||||
{
|
||||
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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user