aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2023-01-24 10:05:52 +0000
committerIngo Klöcker <[email protected]>2023-01-24 11:32:23 +0000
commit95ea3bf831aeac201108876e73750692aa1ba3f5 (patch)
treebff29ce413cb9ee4d55b5a3aa6f4c16888163e8a
parentcore: Allow setting the base directory when creating an archive (diff)
downloadgpgme-95ea3bf831aeac201108876e73750692aa1ba3f5.tar.gz
gpgme-95ea3bf831aeac201108876e73750692aa1ba3f5.zip
core: Support usage of gpgtar for decrypting an encrypted archive
* src/gpgme.h.in (GPGME_DECRYPT_ARCHIVE): New decryption flag. * src/engine-gpg.c (gpg_decrypt): Set use_gpgtar engine flag if GPGME_DECRYPT_ARCHIVE flag is set. Check for new enough gpg and incompatible flags. Use add_gpg_arg_with_value for gpg-only options with a value and add_gpg_arg for gpg-only options without a value. Set extra options for gpgtar and pass input data to stdin when using gpgtar. * tests/run-decrypt.c (show_usage): New options --archive and --directory. (main): Parse new options. Decrypt with gpgtar if --archive is given. Set file name of output data to value of --directory option. -- GnuPG-bug-id: 6342
-rw-r--r--NEWS4
-rw-r--r--doc/gpgme.texi17
-rw-r--r--src/engine-gpg.c67
-rw-r--r--src/gpgme.h.in1
-rw-r--r--tests/run-decrypt.c26
5 files changed, 93 insertions, 22 deletions
diff --git a/NEWS b/NEWS
index 3ccb371f..824faeb7 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,9 @@ Noteworthy changes in version 1.18.1 (unreleased)
gpgme_op_sign* to allow creating an encrypted and/or signed
archive. [T6342]
+ * Extended gpgme_op_decrypt* and gpgme_op_decrypt_verify* to allow
+ extracting an encrypted and/or signed archive. [T6342]
+
* cpp: Handle error when trying to sign expired keys. [T6155]
* cpp, qt: Fix building with C++11. [T6141]
@@ -30,6 +33,7 @@ Noteworthy changes in version 1.18.1 (unreleased)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
gpgme_set_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
+ GPGME_DECRYPT_ARCHIVE NEW.
GPGME_ENCRYPT_ARCHIVE NEW.
GPGME_SIG_MODE_ARCHIVE NEW.
cpp: GpgGenCardKeyInteractor::Curve NEW.
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index b8b90bb1..184b1afe 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -3172,8 +3172,8 @@ The string given in @var{value} is passed to the GnuPG engine to override
the session key for decryption. The format of that session key is
specific to GnuPG and can be retrieved during a decrypt operation when
the context flag "export-session-key" is enabled. Please be aware that
-using this feature with GnuPG < 2.1.16 will leak the session key on
-many platforms via ps(1).
+using this feature with GnuPG < 2.1.16 or when decrypting an archive
+will leak the session key on many platforms via ps(1).
@item "auto-key-retrieve"
Setting the @var{value} to "1" asks the backend to automatically
@@ -5589,6 +5589,12 @@ The function @code{gpgme_op_decrypt} decrypts the ciphertext in the
data object @var{cipher} and stores it into the data object
@var{plain}.
+If the flag @code(GPGME_DECRYPT_ARCHIVE) is set, then an encrypted
+archive in the data object @var{cipher} is decrypted and extracted.
+The content of the archive is extracted into a directory named
+@code{GPGARCH_n_} (where @code{n} is a number) or into the directory
+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
ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE}
if @var{ctx}, @var{cipher} or @var{plain} is not a valid pointer,
@@ -5632,6 +5638,13 @@ multiple of the following bit values:
The @code{GPGME_DECRYPT_VERIFY} symbol specifies that this function
shall exactly act as @code{gpgme_op_decrypt_verify}.
+@item GPGME_DECRYPT_ARCHIVE
+@since{1.19.0}
+
+The @code{GPGME_DECRYPT_ARCHIVE} symbol specifies that the input is an
+encrypted archive that shall be decrypted and extracted. This feature
+is currently only supported for the OpenPGP crypto engine.
+
@item GPGME_DECRYPT_UNWRAP
@since{1.8.0}
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 06eb3e18..86422112 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -310,7 +310,8 @@ add_gpg_arg (engine_gpg_t gpg, const char *arg)
}
static gpgme_error_t
-add_gpg_arg_with_value (engine_gpg_t gpg, const char *arg, const char *value, int front)
+add_gpg_arg_with_value (engine_gpg_t gpg, const char *arg, const char *value,
+ int front)
{
return _add_arg (gpg, arg, value, strlen (value), front, NULL, 1);
}
@@ -1829,6 +1830,14 @@ gpg_decrypt (void *engine,
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ gpg->flags.use_gpgtar = !!(flags & GPGME_DECRYPT_ARCHIVE);
+
+ if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.3.5"))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ if (gpg->flags.use_gpgtar && (flags & GPGME_DECRYPT_UNWRAP))
+ return gpg_error (GPG_ERR_INV_VALUE);
+
err = add_arg (gpg, "--decrypt");
if (!err && (flags & GPGME_DECRYPT_UNWRAP))
@@ -1840,17 +1849,17 @@ gpg_decrypt (void *engine,
}
if (!err && export_session_key)
- err = add_arg (gpg, "--show-session-key");
+ err = add_gpg_arg (gpg, "--show-session-key");
if (!err && auto_key_retrieve)
- err = add_arg (gpg, "--auto-key-retrieve");
+ err = add_gpg_arg (gpg, "--auto-key-retrieve");
if (!err && gpg->flags.auto_key_import)
- err = add_arg (gpg, "--auto-key-import");
+ err = add_gpg_arg (gpg, "--auto-key-import");
if (!err && override_session_key && *override_session_key)
{
- if (have_gpg_version (gpg, "2.1.16"))
+ if (have_gpg_version (gpg, "2.1.16") && !gpg->flags.use_gpgtar)
{
gpgme_data_release (gpg->override_session_key);
TRACE (DEBUG_ENGINE, "override", gpg, "seskey='%s' len=%zu\n",
@@ -1880,25 +1889,43 @@ gpg_decrypt (void *engine,
else
{
/* Using that option may leak the session key via ps(1). */
- err = add_arg (gpg, "--override-session-key");
- if (!err)
- err = add_arg (gpg, override_session_key);
+ err = add_gpg_arg_with_value (gpg, "--override-session-key=",
+ override_session_key, 0);
}
}
/* Tell the gpg object about the data. */
- if (!err)
- err = add_arg (gpg, "--output");
- if (!err)
- err = add_arg (gpg, "-");
- if (!err)
- err = add_data (gpg, plain, 1, 1);
- if (!err)
- err = add_input_size_hint (gpg, ciph);
- if (!err)
- err = add_arg (gpg, "--");
- if (!err)
- err = add_data (gpg, ciph, -1, 0);
+ if (gpg->flags.use_gpgtar)
+ {
+ const char *file_name = gpgme_data_get_file_name (plain);
+ if (!err && file_name)
+ {
+ err = add_arg (gpg, "--directory");
+ if (!err)
+ err = add_arg (gpg, file_name);
+ }
+ if (!err)
+ err = add_input_size_hint (gpg, ciph);
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, ciph, 0, 0);
+ }
+ else
+ {
+ if (!err)
+ err = add_arg (gpg, "--output");
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_data (gpg, plain, 1, 1);
+ if (!err)
+ err = add_input_size_hint (gpg, ciph);
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, ciph, -1, 0);
+ }
if (!err)
err = start (gpg);
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index fabba257..b498cd3b 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1426,6 +1426,7 @@ gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx);
typedef enum
{
GPGME_DECRYPT_VERIFY = 1,
+ GPGME_DECRYPT_ARCHIVE = 2,
GPGME_DECRYPT_UNWRAP = 128
}
gpgme_decrypt_flags_t;
diff --git a/tests/run-decrypt.c b/tests/run-decrypt.c
index cf719925..ee49ead6 100644
--- a/tests/run-decrypt.c
+++ b/tests/run-decrypt.c
@@ -91,6 +91,8 @@ show_usage (int ex)
" --unwrap remove only the encryption layer\n"
" --large-buffers use large I/O buffer\n"
" --sensitive mark data objects as sensitive\n"
+ " --archive extract files from an encrypted archive\n"
+ " --directory DIR extract the files into the directory DIR\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
@@ -113,6 +115,7 @@ main (int argc, char **argv)
int export_session_key = 0;
const char *override_session_key = NULL;
const char *request_origin = NULL;
+ const char *directory = NULL;
int no_symkey_cache = 0;
int ignore_mdc_error = 0;
int raw_output = 0;
@@ -205,6 +208,19 @@ main (int argc, char **argv)
raw_output = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--archive"))
+ {
+ flags |= GPGME_DECRYPT_ARCHIVE;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--directory"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ directory = *argv;
+ argc--; argv++;
+ }
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@@ -302,6 +318,16 @@ main (int argc, char **argv)
gpgme_strerror (err));
exit (1);
}
+ if (directory && (flags & GPGME_DECRYPT_ARCHIVE))
+ {
+ err = gpgme_data_set_file_name (out, directory);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error setting file name (out): %s\n",
+ gpgme_strerror (err));
+ exit (1);
+ }
+ }
if (large_buffers)
{
err = gpgme_data_set_flag (out, "io-buffer-size", "1000000");