core: Support writing the decrypt/verify output directly to a file

* src/engine-gpg.c (gpg_decrypt): Pass output file name to gpg if output
has file name set.
(gpg_verify): Ditto.

* tests/run-decrypt.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
Do not print output if --output is given.
* tests/run-verify.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
--

This change makes it possible to tell gpg to write the output (i.e. the
decrypted/verified data) directly to a file with given file name instead
of piping the output back to gpgme.

GnuPG-bug-id: 6550
This commit is contained in:
Ingo Klöcker 2023-12-19 11:26:15 +01:00
parent 963ace1f9f
commit 5efd3486a9
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
5 changed files with 79 additions and 13 deletions

3
NEWS
View File

@ -1,6 +1,9 @@
Noteworthy changes in version 1.23.3 (unrelease) Noteworthy changes in version 1.23.3 (unrelease)
------------------------------------------------- -------------------------------------------------
* Extended gpgme_op_decrypt* and gpgme_op_verify* to allow writing the
output directly to a file. [T6550]
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign* * Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
to allow reading the input data directly from a file. [T6550] to allow reading the input data directly from a file. [T6550]

View File

@ -5630,7 +5630,9 @@ An error code describing the reason why the key was found invalid.
The function @code{gpgme_op_decrypt} decrypts the ciphertext in the The function @code{gpgme_op_decrypt} decrypts the ciphertext in the
data object @var{cipher} or, if a file name is set on the data object, data object @var{cipher} or, if a file name is set on the data object,
the ciphertext stored in the corresponding file. The decrypted the ciphertext stored in the corresponding file. The decrypted
ciphertext is stored into the data object @var{plain}. ciphertext is stored into the data object @var{plain} or written to
the file set with @code{gpgme_data_set_file_name} for the data object
@var{plain}.
The function returns the error code @code{GPG_ERR_NO_ERROR} if the The function returns the error code @code{GPG_ERR_NO_ERROR} if the
ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE} ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE}
@ -5846,7 +5848,9 @@ writable data object that will contain the plaintext after successful
verification. If a file name is set on the data object @var{sig} (or 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 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 (resp. the data of the signed text) is not read from the data object
but from the file with the given file name. but from the file with the given file name. If a file name is set on
the data object @var{plain} then the plaintext is not stored in the
data object but it is written to a file with the given file name.
The results of the individual signature verifications can be retrieved The results of the individual signature verifications can be retrieved
with @code{gpgme_op_verify_result}. with @code{gpgme_op_verify_result}.

View File

@ -1899,12 +1899,18 @@ gpg_decrypt (void *engine,
} }
else else
{ {
const char *output = gpgme_data_get_file_name (plain);
if (!err) if (!err)
err = add_arg (gpg, "--output"); err = add_arg (gpg, "--output");
if (!err) if (!err && output)
err = add_arg (gpg, "-"); err = add_arg (gpg, output);
if (!err) else
err = add_data (gpg, plain, 1, 1); {
if (!err)
err = add_arg (gpg, "-");
if (!err)
err = add_data (gpg, plain, 1, 1);
}
if (!err) if (!err)
err = add_input_size_hint (gpg, ciph); err = add_input_size_hint (gpg, ciph);
if (!err) if (!err)
@ -3768,9 +3774,12 @@ gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig,
else if (plaintext) else if (plaintext)
{ {
/* Normal or cleartext signature. */ /* Normal or cleartext signature. */
const char *output = gpgme_data_get_file_name (plaintext);
err = add_arg (gpg, "--output"); err = add_arg (gpg, "--output");
if (!err) if (!err && output)
err = add_data (gpg, plaintext, -1, 1); err = add_arg (gpg, output);
else if (!err)
err = add_data (gpg, plaintext, -1, 1);
if (!err) if (!err)
err = add_input_size_hint (gpg, sig); err = add_input_size_hint (gpg, sig);
if (!err) if (!err)

View File

@ -91,6 +91,7 @@ show_usage (int ex)
" --unwrap remove only the encryption layer\n" " --unwrap remove only the encryption layer\n"
" --large-buffers use large I/O buffer\n" " --large-buffers use large I/O buffer\n"
" --sensitive mark data objects as sensitive\n" " --sensitive mark data objects as sensitive\n"
" --output FILE write output to FILE instead of stdout\n"
" --archive extract files from an encrypted archive\n" " --archive extract files from an encrypted archive\n"
" --directory DIR extract the files into the directory DIR\n" " --directory DIR extract the files into the directory DIR\n"
" --diagnostics print diagnostics\n" " --diagnostics print diagnostics\n"
@ -116,6 +117,7 @@ main (int argc, char **argv)
int export_session_key = 0; int export_session_key = 0;
const char *override_session_key = NULL; const char *override_session_key = NULL;
const char *request_origin = NULL; const char *request_origin = NULL;
const char *output = NULL;
const char *directory = NULL; const char *directory = NULL;
int no_symkey_cache = 0; int no_symkey_cache = 0;
int ignore_mdc_error = 0; int ignore_mdc_error = 0;
@ -210,6 +212,14 @@ main (int argc, char **argv)
raw_output = 1; raw_output = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--output"))
{
argc--; argv++;
if (!argc)
show_usage (1);
output = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive")) else if (!strcmp (*argv, "--archive"))
{ {
flags |= GPGME_DECRYPT_ARCHIVE; flags |= GPGME_DECRYPT_ARCHIVE;
@ -341,6 +351,16 @@ main (int argc, char **argv)
gpgme_strerror (err)); gpgme_strerror (err));
exit (1); exit (1);
} }
if (output && !(flags & GPGME_DECRYPT_ARCHIVE))
{
err = gpgme_data_set_file_name (out, output);
if (err)
{
fprintf (stderr, PGM ": error setting file name (out): %s\n",
gpgme_strerror (err));
exit (1);
}
}
if (directory && (flags & GPGME_DECRYPT_ARCHIVE)) if (directory && (flags & GPGME_DECRYPT_ARCHIVE))
{ {
err = gpgme_data_set_file_name (out, directory); err = gpgme_data_set_file_name (out, directory);
@ -407,11 +427,14 @@ main (int argc, char **argv)
{ {
if (!raw_output) if (!raw_output)
print_result (result); print_result (result);
if (!raw_output) if (!output)
fputs ("Begin Output:\n", stdout); {
print_data (out); if (!raw_output)
if (!raw_output) fputs ("Begin Output:\n", stdout);
fputs ("End Output.\n", stdout); print_data (out);
if (!raw_output)
fputs ("End Output.\n", stdout);
}
} }
gpgme_data_release (out); gpgme_data_release (out);

View File

@ -236,6 +236,7 @@ show_usage (int ex)
" --repeat N repeat the operation N times\n" " --repeat N repeat the operation N times\n"
" --auto-key-retrieve\n" " --auto-key-retrieve\n"
" --auto-key-import\n" " --auto-key-import\n"
" --output FILE write output to FILE instead of stdout\n"
" --archive extract files from a signed archive FILE\n" " --archive extract files from a signed archive FILE\n"
" --directory DIR extract the files into the directory DIR\n" " --directory DIR extract the files into the directory DIR\n"
" --diagnostics print diagnostics\n" " --diagnostics print diagnostics\n"
@ -254,6 +255,7 @@ main (int argc, char **argv)
gpgme_verify_flags_t flags = 0; gpgme_verify_flags_t flags = 0;
int print_status = 0; int print_status = 0;
const char *sender = NULL; const char *sender = NULL;
const char *output = NULL;
const char *directory = NULL; const char *directory = NULL;
int auto_key_retrieve = 0; int auto_key_retrieve = 0;
int auto_key_import = 0; int auto_key_import = 0;
@ -327,6 +329,14 @@ main (int argc, char **argv)
auto_key_import = 1; auto_key_import = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--output"))
{
argc--; argv++;
if (!argc)
show_usage (1);
output = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive")) else if (!strcmp (*argv, "--archive"))
{ {
flags |= GPGME_VERIFY_ARCHIVE; flags |= GPGME_VERIFY_ARCHIVE;
@ -484,6 +494,23 @@ main (int argc, char **argv)
} }
} }
if (output && !(flags & GPGME_VERIFY_ARCHIVE))
{
err = gpgme_data_new (&out);
if (err)
{
fprintf (stderr, PGM ": error allocating data object: %s\n",
gpgme_strerror (err));
exit (1);
}
err = gpgme_data_set_file_name (out, output);
if (err)
{
fprintf (stderr, PGM ": error setting file name (out): %s\n",
gpgme_strerror (err));
exit (1);
}
}
if (directory && (flags & GPGME_VERIFY_ARCHIVE)) if (directory && (flags & GPGME_VERIFY_ARCHIVE))
{ {
err = gpgme_data_new (&out); err = gpgme_data_new (&out);