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
This commit is contained in:
Ingo Klöcker 2023-06-21 14:20:52 +02:00
parent e608315392
commit 1a9f192ab4
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
5 changed files with 111 additions and 33 deletions

3
NEWS
View File

@ -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]

View File

@ -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}.

View File

@ -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)

View File

@ -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,6 +236,8 @@ main (int argc, char **argv)
if (argc < 1 || argc > 2)
show_usage (1);
if (!direct_file_io)
{
fp_in = fopen (argv[0], "rb");
if (!fp_in)
{
@ -237,6 +246,7 @@ main (int argc, char **argv)
argv[0], gpgme_strerror (err));
exit (1);
}
}
init_gpgme (protocol);
@ -303,6 +313,9 @@ main (int argc, char **argv)
}
}
if (direct_file_io)
err = gpgme_data_new (&in);
else
err = gpgme_data_new_from_stream (&in, fp_in);
if (err)
{
@ -310,6 +323,16 @@ main (int argc, char **argv)
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)

View File

@ -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,6 +376,8 @@ main (int argc, char **argv)
printf ("Repeat: %i\n", i);
}
if (!direct_file_io)
{
fp_sig = fopen (argv[0], "rb");
if (!fp_sig)
{
@ -388,6 +397,7 @@ main (int argc, char **argv)
exit (1);
}
}
}
err = gpgme_new (&ctx);
fail_if_err (err);
@ -429,6 +439,9 @@ main (int argc, char **argv)
fail_if_err (err);
}
if (direct_file_io)
err = gpgme_data_new (&sig);
else
err = gpgme_data_new_from_stream (&sig, fp_sig);
if (err)
{
@ -437,8 +450,21 @@ main (int argc, char **argv)
exit (1);
}
gpgme_data_set_encoding (sig, encoding);
if (fp_msg)
if (direct_file_io)
{
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)
{
@ -446,6 +472,16 @@ main (int argc, char **argv)
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))