From 0ca45e48b45af1978027e6fe26c7e406fd5ec74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Thu, 19 Jan 2023 10:45:04 +0100 Subject: [PATCH] core: Support usage of gpgtar for creating a signed archive * src/gpgme.h.in (GPGME_SIG_MODE_ARCHIVE): New signature mode. * src/engine-gpg.c (append_args_from_sender, append_args_from_sig_notations): Use add_gpg_arg_with_value for gpg-only options with a value. (gpg_sign): Set use_gpgtar engine flag if GPGME_SIG_MODE_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. * src/sign.c (sign_start): Add GPGME_SIG_MODE_ARCHIVE as valid mode. * tests/run-sign.c (show_usage): New options --archive and --diagnostics. (main): Parse new options. Sign with gpgtar if --archive is given. Print stderr of gpg/gpgtar if --diagnostics is given. -- With this change the gpgme_op_sign* functions get support for creating a signed archive from files and/or directories passed as NUL-separated list in the "in" data with gpgtar. GnuPG-bug-id: 6342 --- src/engine-gpg.c | 70 ++++++++++++++++++++++++++++-------------------- src/gpgme.h.in | 3 ++- src/sign.c | 2 +- tests/run-sign.c | 53 ++++++++++++++++++++++++++++++++---- 4 files changed, 92 insertions(+), 36 deletions(-) diff --git a/src/engine-gpg.c b/src/engine-gpg.c index a15975d7..67cc6570 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1982,16 +1982,11 @@ append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) static gpgme_error_t append_args_from_sender (engine_gpg_t gpg, gpgme_ctx_t ctx) { - gpgme_error_t err; + gpgme_error_t err = 0; if (ctx->sender && have_gpg_version (gpg, "2.1.15")) - { - err = add_arg (gpg, "--sender"); - if (!err) - err = add_arg (gpg, ctx->sender); - } - else - err = 0; + err = add_gpg_arg_with_value (gpg, "--sender=", ctx->sender, 0); + return err; } @@ -2045,14 +2040,12 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */, if (!err) { if ((flags & NOTATION_FLAG_SET)) - err = add_arg (gpg, "--set-notation"); + err = add_gpg_arg_with_value (gpg, "--set-notation=", arg, 0); else if ((flags & NOTATION_FLAG_CERT)) - err = add_arg (gpg, "--cert-notation"); + err = add_gpg_arg_with_value (gpg, "--cert-notation=", arg, 0); else - err = add_arg (gpg, "--sig-notation"); + err = add_gpg_arg_with_value (gpg, "--sig-notation=", arg, 0); } - if (!err) - err = add_arg (gpg, arg); if (arg) free (arg); @@ -2079,9 +2072,7 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */, value = notation->value; if (!err) - err = add_arg (gpg, "--sig-policy-url"); - if (!err) - err = add_arg (gpg, value); + err = add_gpg_arg_with_value (gpg, "--sig-policy-url=", value, 0); if (value != notation->value) free (value); @@ -3540,6 +3531,11 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, (void)include_certs; + gpg->flags.use_gpgtar = mode == GPGME_SIG_MODE_ARCHIVE; + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.3.5")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (mode == GPGME_SIG_MODE_CLEAR) err = add_arg (gpg, "--clearsign"); else @@ -3548,19 +3544,19 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, if (!err && mode == GPGME_SIG_MODE_DETACH) err = add_arg (gpg, "--detach"); if (!err && use_armor) - err = add_arg (gpg, "--armor"); + err = add_gpg_arg (gpg, "--armor"); if (!err) { if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME && have_gpg_version (gpg, "2.1.14")) - err = add_arg (gpg, "--mimemode"); + err = add_gpg_arg (gpg, "--mimemode"); else if (use_textmode) - err = add_arg (gpg, "--textmode"); + err = add_gpg_arg (gpg, "--textmode"); } } if (!err && gpg->flags.include_key_block) - err = add_arg (gpg, "--include-key-block"); + err = add_gpg_arg (gpg, "--include-key-block"); if (!err) err = append_args_from_signers (gpg, ctx); if (!err) @@ -3571,18 +3567,34 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, if (gpgme_data_get_file_name (in)) { if (!err) - err = add_arg (gpg, "--set-filename"); - if (!err) - err = add_arg (gpg, gpgme_data_get_file_name (in)); + err = add_gpg_arg_with_value (gpg, "--set-filename=", gpgme_data_get_file_name (in), 0); } /* Tell the gpg object about the data. */ - if (!err) - err = add_input_size_hint (gpg, in); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, in, -1, 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, in, 0, 0); + } + else + { + if (!err) + err = add_input_size_hint (gpg, in); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, in, -1, 0); + } + if (!err) err = add_data (gpg, out, 1, 1); diff --git a/src/gpgme.h.in b/src/gpgme.h.in index db1f8f13..fabba257 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -308,7 +308,8 @@ typedef enum { GPGME_SIG_MODE_NORMAL = 0, GPGME_SIG_MODE_DETACH = 1, - GPGME_SIG_MODE_CLEAR = 2 + GPGME_SIG_MODE_CLEAR = 2, + GPGME_SIG_MODE_ARCHIVE = 3 } gpgme_sig_mode_t; diff --git a/src/sign.c b/src/sign.c index 31db9bde..7617d27f 100644 --- a/src/sign.c +++ b/src/sign.c @@ -447,7 +447,7 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain, return err; if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH - && mode != GPGME_SIG_MODE_CLEAR) + && mode != GPGME_SIG_MODE_CLEAR && mode != GPGME_SIG_MODE_ARCHIVE) return gpg_error (GPG_ERR_INV_VALUE); if (!plain) diff --git a/tests/run-sign.c b/tests/run-sign.c index 37211d72..73a970d0 100644 --- a/tests/run-sign.c +++ b/tests/run-sign.c @@ -87,6 +87,8 @@ show_usage (int ex) " --sender MBOX use MBOX as sender address\n" " --include-key-block use this option with gpg\n" " --clear create a clear text signature\n" + " --archive create a signed archive with the given file or directory\n" + " --diagnostics print diagnostics\n" , stderr); exit (ex); } @@ -106,6 +108,7 @@ main (int argc, char **argv) int print_status = 0; int use_loopback = 0; int include_key_block = 0; + int diagnostics = 0; const char *sender = NULL; const char *s; @@ -178,6 +181,16 @@ main (int argc, char **argv) sigmode = GPGME_SIG_MODE_CLEAR; argc--; argv++; } + else if (!strcmp (*argv, "--archive")) + { + sigmode = GPGME_SIG_MODE_ARCHIVE; + argc--; argv++; + } + else if (!strcmp (*argv, "--diagnostics")) + { + diagnostics = 1; + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) show_usage (1); @@ -236,12 +249,20 @@ main (int argc, char **argv) } } - err = gpgme_data_new_from_file (&in, *argv, 1); - if (err) + if (sigmode == GPGME_SIG_MODE_ARCHIVE) { - fprintf (stderr, PGM ": error reading `%s': %s\n", - *argv, gpg_strerror (err)); - exit (1); + const char *path = *argv; + err = gpgme_data_new_from_mem (&in, path, strlen (path), 0); + } + else + { + err = gpgme_data_new_from_file (&in, *argv, 1); + if (err) + { + fprintf (stderr, PGM ": error reading `%s': %s\n", + *argv, gpg_strerror (err)); + exit (1); + } } err = gpgme_data_new (&out); @@ -249,6 +270,28 @@ main (int argc, char **argv) err = gpgme_op_sign (ctx, in, out, sigmode); result = gpgme_op_sign_result (ctx); + + if (diagnostics) + { + gpgme_data_t diag; + gpgme_error_t diag_err; + + gpgme_data_new (&diag); + diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG); + if (diag_err) + { + fprintf (stderr, PGM ": getting diagnostics failed: %s\n", + gpgme_strerror (diag_err)); + } + else + { + fputs ("Begin Diagnostics:\n", stdout); + print_data (diag); + fputs ("End Diagnostics.\n", stdout); + } + gpgme_data_release (diag); + } + if (result) print_result (result, sigmode); if (err)