diff --git a/src/engine-backend.h b/src/engine-backend.h index 75ed49cd..07ea8f14 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -122,9 +122,9 @@ struct engine_ops gpgme_sig_mode_t mode, int use_armor, int use_textmode, int include_certs, gpgme_ctx_t ctx /* FIXME */); - gpgme_error_t (*verify) (void *engine, gpgme_data_t sig, - gpgme_data_t signed_text, gpgme_data_t plaintext, - gpgme_ctx_t ctx); + gpgme_error_t (*verify) (void *engine, gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext, gpgme_ctx_t ctx); gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output, unsigned int flags); gpgme_error_t (*setexpire) (void *engine, gpgme_key_t key, diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 86422112..2f63d6ff 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -3666,20 +3666,43 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, } static gpgme_error_t -gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, - gpgme_data_t plaintext, gpgme_ctx_t ctx) +gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext, gpgme_ctx_t ctx) { engine_gpg_t gpg = engine; gpgme_error_t err; + gpg->flags.use_gpgtar = !!(flags & GPGME_VERIFY_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.3.5")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + err = append_args_from_sender (gpg, ctx); if (!err && gpg->flags.auto_key_import) - err = add_arg (gpg, "--auto-key-import"); + err = add_gpg_arg (gpg, "--auto-key-import"); if (!err && ctx->auto_key_retrieve) - err = add_arg (gpg, "--auto-key-retrieve"); + err = add_gpg_arg (gpg, "--auto-key-retrieve"); if (err) ; + else if (gpg->flags.use_gpgtar) + { + const char *file_name = gpgme_data_get_file_name (plaintext); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } + /* gpgtar uses --decrypt also for signed-only archives */ + err = add_arg (gpg, "--decrypt"); + if (!err) + err = add_input_size_hint (gpg, sig); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, sig, 0, 0); + } else if (plaintext) { /* Normal or cleartext signature. */ diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index 4632ef6c..fdc85dd6 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -2112,8 +2112,9 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out, static gpgme_error_t -gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, - gpgme_data_t plaintext, gpgme_ctx_t ctx) +gpgsm_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext, + gpgme_ctx_t ctx) { engine_gpgsm_t gpgsm = engine; gpgme_error_t err; @@ -2123,6 +2124,9 @@ gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, if (!gpgsm) return gpg_error (GPG_ERR_INV_VALUE); + if (flags & GPGME_VERIFY_ARCHIVE) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpgsm->input_cb.data = sig; err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data)); if (err) diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index 232eb4b4..7aa9cfe3 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -1294,8 +1294,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, /* FIXME: Missing a way to specify --silent. */ static gpgme_error_t -uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, - gpgme_data_t plaintext, gpgme_ctx_t ctx) +uiserver_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext, + gpgme_ctx_t ctx) { engine_uiserver_t uiserver = engine; gpgme_error_t err; @@ -1316,6 +1317,9 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, else return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + if (flags & GPGME_VERIFY_ARCHIVE) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + if (gpgrt_asprintf (&cmd, "VERIFY%s", protocol) < 0) return gpg_error_from_syserror (); diff --git a/src/engine.c b/src/engine.c index 895b7e1a..2397f88d 100644 --- a/src/engine.c +++ b/src/engine.c @@ -940,9 +940,9 @@ _gpgme_engine_op_trustlist (engine_t engine, const char *pattern) gpgme_error_t -_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, - gpgme_data_t signed_text, gpgme_data_t plaintext, - gpgme_ctx_t ctx) +_gpgme_engine_op_verify (engine_t engine, gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext, gpgme_ctx_t ctx) { if (!engine) return gpg_error (GPG_ERR_INV_VALUE); @@ -950,8 +950,8 @@ _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, if (!engine->ops->verify) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext, - ctx); + return (*engine->ops->verify) (engine->engine, flags, sig, signed_text, + plaintext, ctx); } diff --git a/src/engine.h b/src/engine.h index d580d997..e5654047 100644 --- a/src/engine.h +++ b/src/engine.h @@ -166,7 +166,9 @@ gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_ctx_t ctx /* FIXME */); gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine, const char *pattern); -gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, +gpgme_error_t _gpgme_engine_op_verify (engine_t engine, + gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, gpgme_data_t plaintext, gpgme_ctx_t ctx); diff --git a/src/gpgme.def b/src/gpgme.def index d8ccd4ca..67c189c7 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -283,5 +283,7 @@ EXPORTS gpgme_op_receive_keys @209 gpgme_op_receive_keys_start @210 + gpgme_op_verify_ext @211 + gpgme_op_verify_ext_start @212 ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index b498cd3b..a337a124 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1634,6 +1634,13 @@ typedef struct _gpgme_op_verify_result *gpgme_verify_result_t; /* Retrieve a pointer to the result of the verify operation. */ gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx); +/* The valid verify flags. */ +typedef enum + { + GPGME_VERIFY_ARCHIVE = 1 + } +gpgme_verify_flags_t; + /* Verify within CTX that SIG is a valid signature for TEXT. */ gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, @@ -1641,6 +1648,16 @@ gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, gpgme_data_t plaintext); +gpgme_error_t gpgme_op_verify_ext_start (gpgme_ctx_t ctx, + gpgme_verify_flags_t flags, + gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); +gpgme_error_t gpgme_op_verify_ext (gpgme_ctx_t ctx, + gpgme_verify_flags_t flags, + gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); /* diff --git a/src/libgpgme.vers b/src/libgpgme.vers index 86d2a5df..20ae9fea 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -282,6 +282,9 @@ GPGME_1.0 { gpgme_op_receive_keys; gpgme_op_receive_keys_start; + gpgme_op_verify_ext; + gpgme_op_verify_ext_start; + local: *; diff --git a/src/verify.c b/src/verify.c index 81b2ff92..a8467156 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1135,8 +1135,9 @@ _gpgme_op_verify_init_result (gpgme_ctx_t ctx) static gpgme_error_t -verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig, - gpgme_data_t signed_text, gpgme_data_t plaintext) +verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) { gpgme_error_t err; @@ -1153,26 +1154,45 @@ verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig, if (!sig) return gpg_error (GPG_ERR_NO_DATA); - return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext, - ctx); + return _gpgme_engine_op_verify (ctx->engine, flags, sig, signed_text, + plaintext, ctx); } -/* Decrypt ciphertext CIPHER and make a signature verification within - CTX and store the resulting plaintext in PLAIN. */ +/* Old version of gpgme_op_verify_ext_start without FLAGS. */ gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, gpgme_data_t plaintext) +{ + return gpgme_op_verify_ext_start (ctx, 0, sig, signed_text, plaintext); +} + + +/* Old version of gpgme_op_verify_ext without FLAGS. */ +gpgme_error_t +gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) +{ + return gpgme_op_verify_ext (ctx, 0, sig, signed_text, plaintext); +} + + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_verify_ext_start (gpgme_ctx_t ctx, gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) { gpg_error_t err; TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_start", ctx, - "sig=%p, signed_text=%p, plaintext=%p", - sig, signed_text, plaintext); + "flags=0x%x, sig=%p, signed_text=%p, plaintext=%p", + flags, sig, signed_text, plaintext); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = verify_start (ctx, 0, sig, signed_text, plaintext); + err = verify_start (ctx, 0, flags, sig, signed_text, plaintext); return TRACE_ERR (err); } @@ -1180,19 +1200,20 @@ gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, /* Decrypt ciphertext CIPHER and make a signature verification within CTX and store the resulting plaintext in PLAIN. */ gpgme_error_t -gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, - gpgme_data_t plaintext) +gpgme_op_verify_ext (gpgme_ctx_t ctx, gpgme_verify_flags_t flags, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) { gpgme_error_t err; TRACE_BEG (DEBUG_CTX, "gpgme_op_verify", ctx, - "sig=%p, signed_text=%p, plaintext=%p", - sig, signed_text, plaintext); + "flags=0x%x, sig=%p, signed_text=%p, plaintext=%p", + flags, sig, signed_text, plaintext); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = verify_start (ctx, 1, sig, signed_text, plaintext); + err = verify_start (ctx, 1, flags, sig, signed_text, plaintext); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); diff --git a/tests/run-verify.c b/tests/run-verify.c index f131f491..831c4614 100644 --- a/tests/run-verify.c +++ b/tests/run-verify.c @@ -235,6 +235,9 @@ show_usage (int ex) " --repeat N repeat the operation N times\n" " --auto-key-retrieve\n" " --auto-key-import\n" + " --archive extract files from a signed archive FILE\n" + " --directory DIR extract the files into the directory DIR\n" + " --diagnostics print diagnostics\n" , stderr); exit (ex); } @@ -246,10 +249,13 @@ main (int argc, char **argv) int last_argc = -1; const char *s; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; + gpgme_verify_flags_t flags = 0; int print_status = 0; const char *sender = NULL; + const char *directory = NULL; int auto_key_retrieve = 0; int auto_key_import = 0; + int diagnostics = 0; int repeats = 1; int i; @@ -312,12 +318,30 @@ main (int argc, char **argv) auto_key_import = 1; argc--; argv++; } + else if (!strcmp (*argv, "--archive")) + { + flags |= GPGME_VERIFY_ARCHIVE; + argc--; argv++; + } + else if (!strcmp (*argv, "--directory")) + { + argc--; argv++; + if (!argc) + show_usage (1); + directory = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--diagnostics")) + { + diagnostics = 1; + argc--; argv++; + } else if (!strncmp (*argv, "--", 2)) show_usage (1); } - if (argc < 1 || argc > 2) + if (argc < 1 || argc > 2 || (argc > 1 && (flags & GPGME_VERIFY_ARCHIVE))) show_usage (1); init_gpgme (protocol); @@ -330,6 +354,7 @@ main (int argc, char **argv) gpgme_data_t sig = NULL; FILE *fp_msg = NULL; gpgme_data_t msg = NULL; + gpgme_data_t out = NULL; gpgme_verify_result_t result; if (repeats > 1) @@ -415,8 +440,48 @@ main (int argc, char **argv) } } - err = gpgme_op_verify (ctx, sig, msg, NULL); + if (directory && (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, directory); + if (err) + { + fprintf (stderr, PGM ": error setting file name (out): %s\n", + gpgme_strerror (err)); + exit (1); + } + } + + err = gpgme_op_verify_ext (ctx, flags, sig, msg, out); result = gpgme_op_verify_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); if (err) @@ -425,6 +490,7 @@ main (int argc, char **argv) exit (1); } + gpgme_data_release (out); gpgme_data_release (msg); gpgme_data_release (sig);