core: New context flag "ignore-mdc-error".

* src/context.h (gpgme_context): Add field ignore_mdc_error.
* src/gpgme.c (gpgme_set_ctx_flag, gpgme_get_ctx_flag): Set/get it.
* src/engine-gpg.c (engine_gpg): Add flags.ignore_mdc_error.
(gpg_set_engine_flags): Set it.
(build_argv): Pass option to gpg.
* src/decrypt.c (_gpgme_decrypt_status_handler): Take care of flag.
(gpgme_op_decrypt_result): Clear flag.
(gpgme_op_decrypt): Clear flag.
* src/decrypt-verify.c (gpgme_op_decrypt_verify): Clear flag
(gpgme_op_decrypt_ext): Clear flag.

* tests/run-decrypt.c (show_usage): Add option --ignore-mdc-error.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2018-06-01 01:29:20 +02:00
parent dd19cabe81
commit 662604c5bc
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
8 changed files with 65 additions and 4 deletions

1
NEWS
View File

@ -7,6 +7,7 @@ Noteworthy changes in version 1.11.2 (unreleased)
* Interface changes relative to the 1.11.1 release: * Interface changes relative to the 1.11.1 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_decrypt_result_t EXTENDED: New field legacy_cipher_nomdc. gpgme_decrypt_result_t EXTENDED: New field legacy_cipher_nomdc.
gpgme_set_ctx_flag EXTENDED: New flag 'ignore-mdc-error'.
cpp: DecryptionResult::sessionKey NEW. cpp: DecryptionResult::sessionKey NEW.
cpp: DecryptionResult::symkeyAlgo NEW. cpp: DecryptionResult::symkeyAlgo NEW.
cpp: Data::rewind NEW. cpp: Data::rewind NEW.

View File

@ -3078,7 +3078,7 @@ the time when you verified the signature.
The string given in @var{value} is passed to the GnuPG engines to The string given in @var{value} is passed to the GnuPG engines to
request restrictions based on the origin of the request. Valid values request restrictions based on the origin of the request. Valid values
are documented in the GnuPG manual and the gpg man page under the are documented in the GnuPG manual and the gpg man page under the
option ``--request-origin''. Requires at least GnuPG 2.2.6 to have an option @option{--request-origin}. Requires at least GnuPG 2.2.6 to have an
effect. effect.
@item "no-symkey-cache" @item "no-symkey-cache"
@ -3086,6 +3086,15 @@ For OpenPGP disable the passphrase cache used for symmetrical en- and
decryption. This cache is based on the message specific salt value. decryption. This cache is based on the message specific salt value.
Requires at least GnuPG 2.2.7 to have an effect. Requires at least GnuPG 2.2.7 to have an effect.
@item "ignore-mdc-error"
This flag passes the option @option{--ignore-mdc-error} to gpg. This
can be used to force decryption of a message which failed due to a
missing integrity check. This flag must be used with great caution
and only if it is a known non-corrupted old message and the decryption
result of the former try had the decryption result flag
@code{legacy_cipher_nomdc} set. For failsafe reasons this flag is
reset after each operation.
@end table @end table
This function returns @code{0} on success. This function returns @code{0} on success.

View File

@ -124,6 +124,10 @@ struct gpgme_context
/* Do not use the symmtric encryption passphrase cache. */ /* Do not use the symmtric encryption passphrase cache. */
unsigned int no_symkey_cache : 1; unsigned int no_symkey_cache : 1;
/* Pass --ignore-mdc-error to gpg. Note that this flag is reset
* after the operation. */
unsigned int ignore_mdc_error : 1;
/* Flags for keylist mode. */ /* Flags for keylist mode. */
gpgme_keylist_mode_t keylist_mode; gpgme_keylist_mode_t keylist_mode;

View File

@ -127,6 +127,7 @@ gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher,
err = decrypt_verify_start (ctx, 1, GPGME_DECRYPT_VERIFY, cipher, plain); err = decrypt_verify_start (ctx, 1, GPGME_DECRYPT_VERIFY, cipher, plain);
if (!err) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
ctx->ignore_mdc_error = 0; /* Always reset. */
return TRACE_ERR (err); return TRACE_ERR (err);
} }
@ -177,5 +178,6 @@ gpgme_op_decrypt_ext (gpgme_ctx_t ctx,
err = _gpgme_decrypt_start (ctx, 1, flags, cipher, plain); err = _gpgme_decrypt_start (ctx, 1, flags, cipher, plain);
if (!err) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
ctx->ignore_mdc_error = 0; /* Always reset. */
return TRACE_ERR (err); return TRACE_ERR (err);
} }

View File

@ -97,6 +97,8 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx)
TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx); TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
ctx->ignore_mdc_error = 0; /* Always reset this flag. */
err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL); err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
opd = hook; opd = hook;
if (err || !opd) if (err || !opd)
@ -362,7 +364,8 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
return opd->pkdecrypt_failed; return opd->pkdecrypt_failed;
else if (opd->failed && opd->any_no_seckey) else if (opd->failed && opd->any_no_seckey)
return gpg_error (GPG_ERR_NO_SECKEY); return gpg_error (GPG_ERR_NO_SECKEY);
else if (opd->failed || opd->not_integrity_protected) else if (opd->failed || (opd->not_integrity_protected
&& !ctx->ignore_mdc_error))
return gpg_error (GPG_ERR_DECRYPT_FAILED); return gpg_error (GPG_ERR_DECRYPT_FAILED);
else if (!opd->okay) else if (!opd->okay)
return gpg_error (GPG_ERR_NO_DATA); return gpg_error (GPG_ERR_NO_DATA);
@ -564,5 +567,6 @@ gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain); err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain);
if (!err) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
ctx->ignore_mdc_error = 0; /* Always reset. */
return TRACE_ERR (err); return TRACE_ERR (err);
} }

View File

@ -144,6 +144,7 @@ struct engine_gpg
struct { struct {
unsigned int no_symkey_cache : 1; unsigned int no_symkey_cache : 1;
unsigned int offline : 1; unsigned int offline : 1;
unsigned int ignore_mdc_error : 1;
} flags; } flags;
/* NULL or the data object fed to --override_session_key-fd. */ /* NULL or the data object fed to --override_session_key-fd. */
@ -646,9 +647,10 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx)
gpg->flags.no_symkey_cache = (ctx->no_symkey_cache gpg->flags.no_symkey_cache = (ctx->no_symkey_cache
&& have_gpg_version (gpg, "2.2.7")); && have_gpg_version (gpg, "2.2.7"));
gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23")); gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23"));
gpg->flags.ignore_mdc_error = !!ctx->ignore_mdc_error;
} }
@ -955,6 +957,19 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
argc++; argc++;
} }
if (gpg->flags.ignore_mdc_error)
{
argv[argc] = strdup ("--ignore-mdc-error");
if (!argv[argc])
{
int saved_err = gpg_error_from_syserror ();
free (fd_data_map);
free_argv (argv);
return saved_err;
}
argc++;
}
if (gpg->flags.offline) if (gpg->flags.offline)
{ {
argv[argc] = strdup ("--disable-dirmngr"); argv[argc] = strdup ("--disable-dirmngr");

View File

@ -542,6 +542,10 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
{ {
ctx->no_symkey_cache = abool; ctx->no_symkey_cache = abool;
} }
else if (!strcmp (name, "ignore-mdc-error"))
{
ctx->ignore_mdc_error = abool;
}
else else
err = gpg_error (GPG_ERR_UNKNOWN_NAME); err = gpg_error (GPG_ERR_UNKNOWN_NAME);
@ -591,6 +595,10 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
{ {
return ctx->no_symkey_cache? "1":""; return ctx->no_symkey_cache? "1":"";
} }
else if (!strcmp (name, "ignore-mdc-error"))
{
return ctx->ignore_mdc_error? "1":"";
}
else else
return NULL; return NULL;
} }

View File

@ -86,6 +86,7 @@ show_usage (int ex)
" --override-session-key STRING use STRING as session key\n" " --override-session-key STRING use STRING as session key\n"
" --request-origin STRING use STRING as request origin\n" " --request-origin STRING use STRING as request origin\n"
" --no-symkey-cache disable the use of that cache\n" " --no-symkey-cache disable the use of that cache\n"
" --ignore-mdc-error allow decryption of legacy data\n"
" --unwrap remove only the encryption layer\n" " --unwrap remove only the encryption layer\n"
, stderr); , stderr);
exit (ex); exit (ex);
@ -109,6 +110,7 @@ main (int argc, char **argv)
const char *override_session_key = NULL; const char *override_session_key = NULL;
const char *request_origin = NULL; const char *request_origin = NULL;
int no_symkey_cache = 0; int no_symkey_cache = 0;
int ignore_mdc_error = 0;
int raw_output = 0; int raw_output = 0;
if (argc) if (argc)
@ -170,6 +172,11 @@ main (int argc, char **argv)
no_symkey_cache = 1; no_symkey_cache = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--ignore-mdc-error"))
{
ignore_mdc_error = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--unwrap")) else if (!strcmp (*argv, "--unwrap"))
{ {
flags |= GPGME_DECRYPT_UNWRAP; flags |= GPGME_DECRYPT_UNWRAP;
@ -241,7 +248,18 @@ main (int argc, char **argv)
err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1"); err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
if (err) if (err)
{ {
fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n", fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n",
gpgme_strerror (err));
exit (1);
}
}
if (ignore_mdc_error)
{
err = gpgme_set_ctx_flag (ctx, "ignore-mdc-error", "1");
if (err)
{
fprintf (stderr, PGM ": error setting ignore-mdc-error: %s\n",
gpgme_strerror (err)); gpgme_strerror (err));
exit (1); exit (1);
} }