diff --git a/NEWS b/NEWS index 51d79239..162212cf 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ Noteworthy changes in version 1.10.1 (unreleased) gpgme_op_encrypt_ext_start NEW. gpgme_op_encrypt_sign_ext NEW. gpgme_op_encrypt_sign_ext_start NEW. + GPGME_ENCRYPT_WANT_ADDRESS NEW. gpgme_import_result_t EXTENDED: New field 'skipped_v3_keys'. cpp: Key::locate NEW. cpp: Data::toString NEW. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 1df9c46e..330b167e 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -6094,7 +6094,7 @@ also expect a sign command. The @code{GPGME_ENCRYPT_SYMMETRIC} symbol specifies that the output should be additionally encrypted symmetrically even -if recipients are provided. This feature is only supported for +if recipients are provided. This feature is only supported for the OpenPGP crypto engine. @item GPGME_ENCRYPT_THROW_KEYIDS @@ -6113,6 +6113,18 @@ The @code{GPGME_ENCRYPT_WRAP} symbol specifies that the input is an OpenPGP message and not a plain data. This is the counterpart to @code{GPGME_DECRYPT_UNWRAP}. +@item GPGME_ENCRYPT_WANT_ADDRESS +@since{1.11.0} + +The @code{GPGME_ENCRYPT_WANT_ADDRESS} symbol requests that all +supplied keys or key specifications include a syntactically valid mail +address. If this is not the case the operation is not even tried and +the error code @code{GPG_ERR_INV_USER_ID} is returned. Only the +address part of the key specification is conveyed to the backend. As +of now the key must be specified using the @var{recpstring} argument +of the extended encrypt functions. This feature is currently only +supported for the OpenPGP crypto engine. + @end table If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in 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;