From 29cfcd316d1bfc98ca663369a9503cc169dd3447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Thu, 19 Jan 2023 11:08:42 +0100 Subject: [PATCH] core: Support usage of gpgtar for creating an encrypted signed archive * src/engine-gpg.c (gpg_encrypt_sign): Set use_gpgtar engine flag if GPGME_ENCRYPT_ARCHIVE mode is set. Check for new enough gpg. 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-encrypt.c (print_result): Rename to print_encrypt_result. Print header. (print_sign_result): New. (show_usage): New option --sign. (main): Parse new option. Sign and encrypt --sign is given. Print results of signing additionally to results of encryption. -- With this change the gpgme_op_encrypt_sign* functions get support for creating an encrypted and signed archive from files and/or directories passed as NUL-separated list in the "plain" data with gpgtar. GnuPG-bug-id: 6342 --- src/engine-gpg.c | 52 +++++++++++++++++++++++++++++-------------- tests/run-encrypt.c | 54 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 23 deletions(-) diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 67cc6570..16dfcc48 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2415,6 +2415,11 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], engine_gpg_t gpg = engine; gpgme_error_t err = 0; + gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.3.5")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); @@ -2424,30 +2429,30 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err) err = add_arg (gpg, "--sign"); if (!err && use_armor) - err = add_arg (gpg, "--armor"); + err = add_gpg_arg (gpg, "--armor"); if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) - err = add_arg (gpg, "--compress-algo=none"); + err = add_gpg_arg (gpg, "--compress-algo=none"); if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) - err = add_arg (gpg, "--throw-keyids"); + err = add_gpg_arg (gpg, "--throw-keyids"); if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME && have_gpg_version (gpg, "2.1.14")) - err = add_arg (gpg, "--mimemode"); + err = add_gpg_arg (gpg, "--mimemode"); if (!err && gpg->flags.include_key_block) - err = add_arg (gpg, "--include-key-block"); + err = add_gpg_arg (gpg, "--include-key-block"); if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) - err = add_arg (gpg, "--always-trust"); + err = add_gpg_arg (gpg, "--always-trust"); if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) - err = add_arg (gpg, "--no-encrypt-to"); + err = add_gpg_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) err = append_args_from_recipients_string (gpg, flags, recpstring); @@ -2474,16 +2479,31 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (gpgme_data_get_file_name (plain)) { if (!err) - err = add_arg (gpg, "--set-filename"); - if (!err) - err = add_arg (gpg, gpgme_data_get_file_name (plain)); + err = add_gpg_arg_with_value (gpg, "--set-filename=", gpgme_data_get_file_name (plain), 0); + } + if (gpg->flags.use_gpgtar) + { + if (!err) + err = add_arg (gpg, "--files-from"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_arg (gpg, "--null"); + if (!err) + err = add_arg (gpg, "--utf8-strings"); + /* Pass the filenames to gpgtar's stdin. */ + if (!err) + err = add_data (gpg, plain, 0, 0); + } + else + { + if (!err) + err = add_input_size_hint (gpg, plain); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, plain, -1, 0); } - if (!err) - err = add_input_size_hint (gpg, plain); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, plain, -1, 0); if (!err) err = start (gpg); diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c index a38dabcb..82a2cead 100644 --- a/tests/run-encrypt.c +++ b/tests/run-encrypt.c @@ -77,10 +77,11 @@ progress_cb (void *opaque, const char *what, int type, int current, int total) static void -print_result (gpgme_encrypt_result_t result) +print_encrypt_result (gpgme_encrypt_result_t result) { gpgme_invalid_key_t invkey; + printf ("\nEncryption results\n"); for (invkey = result->invalid_recipients; invkey; invkey = invkey->next) printf ("Encryption key `%s' not used: %s <%s>\n", nonnull (invkey->fpr), @@ -88,6 +89,30 @@ print_result (gpgme_encrypt_result_t result) } +static void +print_sign_result (gpgme_sign_result_t result) +{ + gpgme_invalid_key_t invkey; + gpgme_new_signature_t sig; + + printf ("\nSigning results\n"); + for (invkey = result->invalid_signers; invkey; invkey = invkey->next) + printf ("Signing key `%s' not used: %s <%s>\n", + nonnull (invkey->fpr), + gpg_strerror (invkey->reason), gpg_strsource (invkey->reason)); + + for (sig = result->signatures; sig; sig = sig->next) + { + printf ("Key fingerprint: %s\n", nonnull (sig->fpr)); + printf ("Signature type : %d\n", sig->type); + printf ("Public key algo: %d\n", sig->pubkey_algo); + printf ("Hash algo .....: %d\n", sig->hash_algo); + printf ("Creation time .: %ld\n", sig->timestamp); + printf ("Sig class .....: 0x%u\n", sig->sig_class); + } +} + + static int show_usage (int ex) @@ -95,6 +120,7 @@ show_usage (int ex) fputs ("usage: " PGM " [options] FILE\n\n" "Options:\n" " --verbose run in verbose mode\n" + " --sign sign data before encryption\n" " --status print status lines from the backend\n" " --progress print progress info\n" " --openpgp use the OpenPGP protocol (default)\n" @@ -122,7 +148,8 @@ main (int argc, char **argv) gpgme_ctx_t ctx; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_data_t in, out; - gpgme_encrypt_result_t result; + gpgme_encrypt_result_t encrypt_result; + gpgme_sign_result_t sign_result; int print_status = 0; int print_progress = 0; int use_loopback = 0; @@ -135,6 +162,7 @@ main (int argc, char **argv) gpgme_off_t offset; int no_symkey_cache = 0; int diagnostics = 0; + int sign = 0; if (argc) { argc--; argv++; } @@ -157,6 +185,11 @@ main (int argc, char **argv) verbose = 1; argc--; argv++; } + else if (!strcmp (*argv, "--sign")) + { + sign = 1; + argc--; argv++; + } else if (!strcmp (*argv, "--status")) { print_status = 1; @@ -336,9 +369,12 @@ main (int argc, char **argv) err = gpgme_data_new (&out); fail_if_err (err); - err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring, - flags, in, out); - result = gpgme_op_encrypt_result (ctx); + if (sign) + err = gpgme_op_encrypt_sign_ext (ctx, keycount ? keys : NULL, keystring, + flags, in, out); + else + err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring, + flags, in, out); if (diagnostics) { @@ -361,8 +397,12 @@ main (int argc, char **argv) gpgme_data_release (diag); } - if (result) - print_result (result); + sign_result = gpgme_op_sign_result (ctx); + if (sign_result) + print_sign_result (sign_result); + encrypt_result = gpgme_op_encrypt_result (ctx); + if (encrypt_result) + print_encrypt_result (encrypt_result); if (err) { fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));