From 1a9f192ab450288aea7a889527e78afd2c067b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Wed, 21 Jun 2023 14:20:52 +0200 Subject: [PATCH] core: Support reading the archive to decrypt/verify directly from a file * src/engine-gpg.c (add_file_name_arg_or_data): New. (gpg_decrypt): Use add_file_name_arg_or_data instead of add_data for the ciphertext. (gpg_verify): Use add_file_name_arg_or_data instead of add_data for the signature and the signed text. * tests/run-decrypt.c (show_usage): New option --direct-file-io. (main): Parse new option. If option is given, then don't open input file, create simple data object instead of data object from stream and set input file name on input data. * tests/run-verify.c (show_usage): New option --direct-file-io. (main): Parse new option. If option is given, then don't open input files, create simple data objects instead of data objects from stream and set input file names on input data objects. -- This change makes it possible to tell gpg (and gpgtar) to read the input (i.e. the signed/encrypted data or the signature or the created archive) directly from the files with given file names instead of from streams piped through GpgME's Data IO. GnuPG-bug-id: 6530 --- NEWS | 3 ++ doc/gpgme.texi | 10 +++++-- src/engine-gpg.c | 24 ++++++++++++---- tests/run-decrypt.c | 37 +++++++++++++++++++----- tests/run-verify.c | 70 ++++++++++++++++++++++++++++++++++----------- 5 files changed, 111 insertions(+), 33 deletions(-) diff --git a/NEWS b/NEWS index ce72d610..7712c7d9 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ Noteworthy changes in version 1.21.0 (unreleased) gpgme_op_sign* to allow writing the output directly to a file. [T6530] + * Extended gpgme_op_decrypt* and gpgme_op_verify* to allow + reading the input data directly from files. [T6530] + * qt: Allow writing the created archives directly to a file. [T6530] diff --git a/doc/gpgme.texi b/doc/gpgme.texi index cf0525fc..fb604f30 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -5592,8 +5592,9 @@ An error code describing the reason why the key was found invalid. @deftypefun gpgme_error_t gpgme_op_decrypt (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{cipher}}, @w{gpgme_data_t @var{plain}}) The function @code{gpgme_op_decrypt} decrypts the ciphertext in the -data object @var{cipher} and stores it into the data object -@var{plain}. +data object @var{cipher} or, if a file name is set on the data object, +the ciphertext stored in the corresponding file. The decrypted +ciphertext is stored into the data object @var{plain}. The function returns the error code @code{GPG_ERR_NO_ERROR} if the ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE} @@ -5806,7 +5807,10 @@ detached signature, then the signed text should be provided in Otherwise, if @var{sig} is a normal (or cleartext) signature, @var{signed_text} should be a null pointer and @var{plain} should be a writable data object that will contain the plaintext after successful -verification. +verification. If a file name is set on the data object @var{sig} (or +on the data object @var{signed_text}), then the data of the signature +(resp. the data of the signed text) is not read from the data object +but from the file with the given file name. The results of the individual signature verifications can be retrieved with @code{gpgme_op_verify_result}. diff --git a/src/engine-gpg.c b/src/engine-gpg.c index ba45e55a..355d42fd 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -365,6 +365,18 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) return add_data_ext (gpg, data, dup_to, inbound, 0); } + +static gpgme_error_t +add_file_name_arg_or_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) +{ + const char *file_name = gpgme_data_get_file_name (data); + if (file_name) + return add_arg (gpg, file_name); + else + return add_data (gpg, data, dup_to, inbound); +} + + /* Return true if the engine's version is at least VERSION. */ static int have_gpg_version (engine_gpg_t gpg, const char *version) @@ -1883,7 +1895,7 @@ gpg_decrypt (void *engine, if (!err) err = add_arg (gpg, "--"); if (!err) - err = add_data (gpg, ciph, 0, 0); + err = add_file_name_arg_or_data (gpg, ciph, 0, 0); } else { @@ -1898,7 +1910,7 @@ gpg_decrypt (void *engine, if (!err) err = add_arg (gpg, "--"); if (!err) - err = add_data (gpg, ciph, -1, 0); + err = add_file_name_arg_or_data (gpg, ciph, -1, 0); } if (!err) @@ -3707,7 +3719,7 @@ gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, if (!err) err = add_arg (gpg, "--"); if (!err) - err = add_data (gpg, sig, 0, 0); + err = add_file_name_arg_or_data (gpg, sig, 0, 0); } else if (plaintext) { @@ -3720,7 +3732,7 @@ gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, if (!err) err = add_arg (gpg, "--"); if (!err) - err = add_data (gpg, sig, -1, 0); + err = add_file_name_arg_or_data (gpg, sig, -1, 0); if (!err) err = add_data (gpg, plaintext, 1, 1); } @@ -3732,9 +3744,9 @@ gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, if (!err) err = add_arg (gpg, "--"); if (!err) - err = add_data (gpg, sig, -1, 0); + err = add_file_name_arg_or_data (gpg, sig, -1, 0); if (!err && signed_text) - err = add_data (gpg, signed_text, -1, 0); + err = add_file_name_arg_or_data (gpg, signed_text, -1, 0); } if (!err) diff --git a/tests/run-decrypt.c b/tests/run-decrypt.c index ee49ead6..de082d6f 100644 --- a/tests/run-decrypt.c +++ b/tests/run-decrypt.c @@ -94,6 +94,7 @@ show_usage (int ex) " --archive extract files from an encrypted archive\n" " --directory DIR extract the files into the directory DIR\n" " --diagnostics print diagnostics\n" + " --direct-file-io pass FILE instead of stream with content of FILE to backend\n" , stderr); exit (ex); } @@ -122,6 +123,7 @@ main (int argc, char **argv) int large_buffers = 0; int sensitive = 0; int diagnostics = 0; + int direct_file_io = 0; if (argc) { argc--; argv++; } @@ -221,6 +223,11 @@ main (int argc, char **argv) directory = *argv; argc--; argv++; } + else if (!strcmp (*argv, "--direct-file-io")) + { + direct_file_io = 1; + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) show_usage (1); @@ -229,13 +236,16 @@ main (int argc, char **argv) if (argc < 1 || argc > 2) show_usage (1); - fp_in = fopen (argv[0], "rb"); - if (!fp_in) + if (!direct_file_io) { - err = gpgme_error_from_syserror (); - fprintf (stderr, PGM ": can't open `%s': %s\n", - argv[0], gpgme_strerror (err)); - exit (1); + fp_in = fopen (argv[0], "rb"); + if (!fp_in) + { + err = gpgme_error_from_syserror (); + fprintf (stderr, PGM ": can't open `%s': %s\n", + argv[0], gpgme_strerror (err)); + exit (1); + } } init_gpgme (protocol); @@ -303,13 +313,26 @@ main (int argc, char **argv) } } - err = gpgme_data_new_from_stream (&in, fp_in); + if (direct_file_io) + err = gpgme_data_new (&in); + else + err = gpgme_data_new_from_stream (&in, fp_in); if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", gpgme_strerror (err)); exit (1); } + if (direct_file_io) + { + err = gpgme_data_set_file_name (in, argv[0]); + if (err) + { + fprintf (stderr, PGM ": error setting file name (in): %s\n", + gpgme_strerror (err)); + exit (1); + } + } err = gpgme_data_new (&out); if (err) diff --git a/tests/run-verify.c b/tests/run-verify.c index 8a400589..dba45557 100644 --- a/tests/run-verify.c +++ b/tests/run-verify.c @@ -239,6 +239,7 @@ show_usage (int ex) " --archive extract files from a signed archive FILE\n" " --directory DIR extract the files into the directory DIR\n" " --diagnostics print diagnostics\n" + " --direct-file-io pass file names instead of streams with content of files to backend\n" , stderr); exit (ex); } @@ -258,6 +259,7 @@ main (int argc, char **argv) int auto_key_import = 0; gpgme_data_encoding_t encoding = GPGME_DATA_ENCODING_NONE; int diagnostics = 0; + int direct_file_io = 0; int repeats = 1; int i; @@ -343,6 +345,11 @@ main (int argc, char **argv) diagnostics = 1; argc--; argv++; } + else if (!strcmp (*argv, "--direct-file-io")) + { + direct_file_io = 1; + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) show_usage (1); @@ -369,24 +376,27 @@ main (int argc, char **argv) printf ("Repeat: %i\n", i); } - fp_sig = fopen (argv[0], "rb"); - if (!fp_sig) + if (!direct_file_io) { - err = gpgme_error_from_syserror (); - fprintf (stderr, PGM ": can't open `%s': %s\n", - argv[0], gpgme_strerror (err)); - exit (1); - } - if (argc > 1) - { - fp_msg = fopen (argv[1], "rb"); - if (!fp_msg) + fp_sig = fopen (argv[0], "rb"); + if (!fp_sig) { err = gpgme_error_from_syserror (); fprintf (stderr, PGM ": can't open `%s': %s\n", - argv[1], gpgme_strerror (err)); + argv[0], gpgme_strerror (err)); exit (1); } + if (argc > 1) + { + fp_msg = fopen (argv[1], "rb"); + if (!fp_msg) + { + err = gpgme_error_from_syserror (); + fprintf (stderr, PGM ": can't open `%s': %s\n", + argv[1], gpgme_strerror (err)); + exit (1); + } + } } err = gpgme_new (&ctx); @@ -429,7 +439,10 @@ main (int argc, char **argv) fail_if_err (err); } - err = gpgme_data_new_from_stream (&sig, fp_sig); + if (direct_file_io) + err = gpgme_data_new (&sig); + else + err = gpgme_data_new_from_stream (&sig, fp_sig); if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", @@ -437,15 +450,38 @@ main (int argc, char **argv) exit (1); } gpgme_data_set_encoding (sig, encoding); - if (fp_msg) + if (direct_file_io) { - err = gpgme_data_new_from_stream (&msg, fp_msg); + err = gpgme_data_set_file_name (sig, argv[0]); + if (err) + { + fprintf (stderr, PGM ": error setting file name (sig): %s\n", + gpgme_strerror (err)); + exit (1); + } + } + if (argc > 1) + { + if (direct_file_io) + err = gpgme_data_new (&msg); + else + err = gpgme_data_new_from_stream (&msg, fp_msg); if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", gpgme_strerror (err)); exit (1); } + if (direct_file_io) + { + err = gpgme_data_set_file_name (msg, argv[1]); + if (err) + { + fprintf (stderr, PGM ": error setting file name (msg): %s\n", + gpgme_strerror (err)); + exit (1); + } + } } if (directory && (flags & GPGME_VERIFY_ARCHIVE)) @@ -454,14 +490,14 @@ main (int argc, char **argv) if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", - gpgme_strerror (err)); + gpgme_strerror (err)); exit (1); } err = gpgme_data_set_file_name (out, directory); if (err) { fprintf (stderr, PGM ": error setting file name (out): %s\n", - gpgme_strerror (err)); + gpgme_strerror (err)); exit (1); } }