diff --git a/NEWS b/NEWS index 2475a877..81bd564a 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,13 @@ Noteworthy changes in version 1.23.3 (unrelease) ------------------------------------------------- + * Extended gpgme_op_encrypt* and gpgme_op_encrypt_sign* to allow reading + the input data directly from a file. [T6550] + + * Interface changes relative to the 1.23.2 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GPGME_ENCRYPT_FILE NEW. + Noteworthy changes in version 1.23.2 (2023-11-28) ------------------------------------------------- diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 11f90133..0ec70a55 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -6557,7 +6557,14 @@ file set with @code{gpgme_data_set_file_name} for the data object @var{cipher}. The type of the ciphertext created is determined by the @acronym{ASCII} armor (or, if that is not set, by the encoding specified for @var{cipher}) and the text mode attributes set for the context -@var{ctx}. +@var{ctx}. If a filename has been set with @code{gpgme_data_set_file_name} +for the data object @var{plain} then this filename is stored in the +ciphertext. + +If the flag @code{GPGME_ENCRYPT_FILE} is set and a filename has been set +with @code{gpgme_data_set_file_name} for the data object @var{plain}, +then this filename is passed to gpg, so that gpg reads the plaintext +directly from this file instead of from the data object @var{plain}. If the flag @code{GPGME_ENCRYPT_ARCHIVE} is set, then an encrypted archive is created from the files and directories given as NUL-separated @@ -6653,6 +6660,15 @@ NUL-separated list of file paths and directory paths that shall be encrypted into an archive. This feature is currently only supported for the OpenPGP crypto engine and requires GnuPG 2.4.1. +@item GPGME_ENCRYPT_FILE +@since{1.24.0} + +The @code{GPGME_ENCRYPT_FILE} symbol specifies that the filename set +with @code{gpgme_data_set_file_name} for the data object @var{plain} +is passed to gpg, so that gpg reads the plaintext directly from this +file instead of from the data object @var{plain}. 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 8c9f62fb..123760be 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2317,12 +2317,16 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, { engine_gpg_t gpg = engine; gpgme_error_t err = 0; + const char *file_name = NULL; gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE); if (gpg->flags.use_gpgtar && !have_usable_gpgtar (gpg)) return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (gpg->flags.use_gpgtar && (flags & GPGME_ENCRYPT_FILE)) + return gpg_error (GPG_ERR_INV_VALUE); + if (gpg->flags.use_gpgtar && (flags & GPGME_ENCRYPT_WRAP)) return gpg_error (GPG_ERR_INV_VALUE); @@ -2390,9 +2394,10 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, err = add_data (gpg, ciph, 1, 1); } } + if (!err) + file_name = gpgme_data_get_file_name (plain); if (gpg->flags.use_gpgtar) { - const char *file_name = gpgme_data_get_file_name (plain); if (!err && file_name) { err = add_arg (gpg, "--directory"); @@ -2411,9 +2416,17 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, if (!err) err = add_data (gpg, plain, 0, 0); } + else if (flags & GPGME_ENCRYPT_FILE) + { + if (!err) + err = add_arg (gpg, "--"); + if (!err && (!file_name || !*file_name)) + err = gpg_error (GPG_ERR_INV_VALUE); + if (!err) + err = add_arg (gpg, file_name); + } else { - const char *file_name = gpgme_data_get_file_name (plain); if (!err && file_name) err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0); if (!err) @@ -2440,12 +2453,16 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], { engine_gpg_t gpg = engine; gpgme_error_t err = 0; + const char *file_name = NULL; gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE); if (gpg->flags.use_gpgtar && !have_usable_gpgtar (gpg)) return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (gpg->flags.use_gpgtar && (flags & GPGME_ENCRYPT_FILE)) + return gpg_error (GPG_ERR_INV_VALUE); + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); @@ -2510,9 +2527,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], err = add_data (gpg, ciph, 1, 1); } } + if (!err) + file_name = gpgme_data_get_file_name (plain); if (gpg->flags.use_gpgtar) { - const char *file_name = gpgme_data_get_file_name (plain); if (!err && file_name) { err = add_arg (gpg, "--directory"); @@ -2531,9 +2549,17 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err) err = add_data (gpg, plain, 0, 0); } + else if (flags & GPGME_ENCRYPT_FILE) + { + if (!err) + err = add_arg (gpg, "--"); + if (!err && (!file_name || !*file_name)) + err = gpg_error (GPG_ERR_INV_VALUE); + if (!err) + err = add_arg (gpg, file_name); + } else { - const char *file_name = gpgme_data_get_file_name (plain); if (!err && file_name) err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0); if (!err) diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index 24b142c5..014507d4 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -1536,7 +1536,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, if (!recp && !recpstring) /* Symmetric only */ return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - if (flags & GPGME_ENCRYPT_ARCHIVE) + if (flags & (GPGME_ENCRYPT_ARCHIVE | GPGME_ENCRYPT_FILE)) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index a298bec6..a116feb9 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1145,7 +1145,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, else return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); - if (flags & GPGME_ENCRYPT_ARCHIVE) + if (flags & (GPGME_ENCRYPT_ARCHIVE | GPGME_ENCRYPT_FILE)) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); if (flags & GPGME_ENCRYPT_PREPARE) diff --git a/src/gpgme.h.in b/src/gpgme.h.in index d44994a6..ccc7b026 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1326,7 +1326,8 @@ typedef enum GPGME_ENCRYPT_THROW_KEYIDS = 64, GPGME_ENCRYPT_WRAP = 128, GPGME_ENCRYPT_WANT_ADDRESS = 256, - GPGME_ENCRYPT_ARCHIVE = 512 + GPGME_ENCRYPT_ARCHIVE = 512, + GPGME_ENCRYPT_FILE = 1024 } gpgme_encrypt_flags_t; diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c index 80c40729..8e8b559c 100644 --- a/tests/run-encrypt.c +++ b/tests/run-encrypt.c @@ -151,6 +151,7 @@ show_usage (int ex) " --no-symkey-cache disable the use of that cache\n" " --wrap assume input is valid OpenPGP message\n" " --symmetric encrypt symmetric (OpenPGP only)\n" + " --direct-file-io pass FILE instead of stream with content of FILE to backend\n" " --archive encrypt given file or directory into an archive\n" " --directory DIR switch to directory DIR before encrypting into an archive\n" " --output FILE write output to FILE instead of stdout\n" @@ -186,6 +187,7 @@ main (int argc, char **argv) int no_symkey_cache = 0; int diagnostics = 0; int sign = 0; + int direct_file_io = 0; if (argc) { argc--; argv++; } @@ -289,6 +291,11 @@ main (int argc, char **argv) no_symkey_cache = 1; argc--; argv++; } + else if (!strcmp (*argv, "--direct-file-io")) + { + direct_file_io = 1; + argc--; argv++; + } else if (!strcmp (*argv, "--archive")) { flags |= GPGME_ENCRYPT_ARCHIVE; @@ -378,6 +385,14 @@ main (int argc, char **argv) fail_if_err (err); } } + else if (direct_file_io) + { + flags |= GPGME_ENCRYPT_FILE; + err = gpgme_data_new (&in); + fail_if_err (err); + err = gpgme_data_set_file_name (in, *argv); + fail_if_err (err); + } else { err = gpgme_data_new_from_file (&in, *argv, 1);