core: Report failed encryption/signing if gpgtar didn't emit SUCCESS

src/encrypt-sign.c (encrypt_sym_status_handler): Add call of
_gpgme_encrypt_status_handler.
(encrypt_sign_start): Call _gpgme_op_encrypt_init_result with
success_required=1 if archive is created. Always call
_gpgme_op_sign_init_result with success_required=0 because the encrypt
status handler already checks for SUCCESS.
src/encrypt.c (op_data_t): Add success_seen flag.
(_gpgme_encrypt_status_handler): Return error if we didn't see a
required SUCCESS on GPGME_STATUS_EOF. Set success_seen flag on
GPGME_STATUS_SUCCESS.
(encrypt_sym_status_handler): Add call of _gpgme_encrypt_status_handler.
(_gpgme_op_encrypt_init_result): Add argument success_required. Set
success_seen flag if SUCCESS is not required.
(encrypt_start): Call _gpgme_op_encrypt_init_result with
success_required=1 if archive is created.
src/ops.h (_gpgme_op_sign_init_result, _gpgme_op_encrypt_init_result):
Add argument success_required to prototypes.
src/sign.c (op_data_t): Add success_seen flag.
(_gpgme_sign_status_handler): Return error if we didn't see a
required SUCCESS on GPGME_STATUS_EOF. Set success_seen flag on
GPGME_STATUS_SUCCESS.
(sign_init_result): Add argument success_required. Set success_seen
flag if SUCCESS is not required.
(_gpgme_op_sign_init_result): Add argument success_required and
forward it to sign_init_result.
(sign_start): Call sign_init_result with success_required=1 if archive
is created.
--

gpgtar emits a SUCCESS status just before successful termination. If the
process terminates unexpectedly (e.g. because it's killed) then gpgme
now reports GPG_ERR_EOF. The SUCCESS status is only required if a
signed and/or encrypted archive is created which is only supported for
OpenPGP. The other engines reject the GPGME_ENCRYPT_ARCHIVE flag so that
we don't need to check the protocol in the generic code.

This change also adds handling of invalid recipients in case symmetric
encryption is used which makes sense because one can combine symmetric
and public key encryption.

GnuPG-bug-id: 6554
This commit is contained in:
Ingo Klöcker 2024-09-20 10:05:30 +02:00
parent 9747f18962
commit 79ca846993
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
4 changed files with 36 additions and 10 deletions

View File

@ -56,6 +56,8 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = _gpgme_sign_status_handler (priv, code, args);
if (!err)
err = _gpgme_passphrase_status_handler (priv, code, args);
if (!err)
err = _gpgme_encrypt_status_handler (priv, code, args);
return err;
}
@ -82,11 +84,11 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
if (recp && !*recp)
return gpg_error (GPG_ERR_INV_VALUE);
err = _gpgme_op_encrypt_init_result (ctx);
err = _gpgme_op_encrypt_init_result (ctx, flags & GPGME_ENCRYPT_ARCHIVE);
if (err)
return err;
err = _gpgme_op_sign_init_result (ctx);
err = _gpgme_op_sign_init_result (ctx, 0);
if (err)
return err;

View File

@ -49,6 +49,9 @@ typedef struct
the list. This makes appending new invalid recipients painless
while preserving the order. */
gpgme_invalid_key_t *lastp;
/* Whether a SUCCESS status was seen. Emitted by gpgtar. */
unsigned int success_seen:1;
} *op_data_t;
@ -136,6 +139,8 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
if (opd->failure_code)
return opd->failure_code;
if (!opd->success_seen)
return gpg_error (GPG_ERR_EOF);
break;
case GPGME_STATUS_KEY_CONSIDERED:
@ -164,6 +169,10 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
/* Should not happen, because we require at least one recipient. */
return gpg_error (GPG_ERR_GENERAL);
case GPGME_STATUS_SUCCESS:
opd->success_seen = 1;
break;
default:
break;
}
@ -179,6 +188,8 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = _gpgme_progress_status_handler (priv, code, args);
if (!err)
err = _gpgme_passphrase_status_handler (priv, code, args);
if (!err)
err = _gpgme_encrypt_status_handler (priv, code, args);
return err;
}
@ -197,7 +208,7 @@ encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
gpgme_error_t
_gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)
_gpgme_op_encrypt_init_result (gpgme_ctx_t ctx, int success_required)
{
gpgme_error_t err;
void *hook;
@ -210,6 +221,7 @@ _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)
return err;
opd->lastp = &opd->result.invalid_recipients;
opd->success_seen = !success_required;
return 0;
}
@ -227,7 +239,7 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
if (err)
return err;
err = _gpgme_op_encrypt_init_result (ctx);
err = _gpgme_op_encrypt_init_result (ctx, flags & GPGME_ENCRYPT_ARCHIVE);
if (err)
return err;

View File

@ -102,7 +102,8 @@ void _gpgme_signers_clear (gpgme_ctx_t ctx);
/* Create an initial op data object for signing. Needs to be called
once before calling _gpgme_sign_status_handler. */
gpgme_error_t _gpgme_op_sign_init_result (gpgme_ctx_t ctx);
gpgme_error_t _gpgme_op_sign_init_result (gpgme_ctx_t ctx,
int success_required);
/* Process a status line for signing operations. */
gpgme_error_t _gpgme_sign_status_handler (void *priv,
@ -114,7 +115,8 @@ gpgme_error_t _gpgme_sign_status_handler (void *priv,
/* Create an initial op data object for encrypt. Needs to be called
once before calling _gpgme_encrypt_status_handler. */
gpgme_error_t _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx);
gpgme_error_t _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx,
int success_required);
/* Process a status line for encryption operations. */
gpgme_error_t _gpgme_encrypt_status_handler (void *priv,

View File

@ -60,6 +60,8 @@ typedef struct
unsigned int ignore_inv_recp:1;
unsigned int inv_sgnr_seen:1;
unsigned int sig_created_seen:1;
/* Whether a SUCCESS status was seen. Emitted by gpgtar. */
unsigned int success_seen:1;
} *op_data_t;
@ -377,6 +379,8 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
else if (!opd->sig_created_seen
&& ctx->protocol != GPGME_PROTOCOL_UISERVER)
err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_GENERAL);
else if (!opd->success_seen)
err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_EOF);
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
@ -384,6 +388,10 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
break;
case GPGME_STATUS_SUCCESS:
opd->success_seen = 1;
break;
default:
break;
}
@ -404,7 +412,7 @@ sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
static gpgme_error_t
sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp, int success_required)
{
gpgme_error_t err;
void *hook;
@ -421,13 +429,14 @@ sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
opd->ignore_inv_recp = !!ignore_inv_recp;
opd->inv_sgnr_seen = 0;
opd->sig_created_seen = 0;
opd->success_seen = !success_required;
return 0;
}
gpgme_error_t
_gpgme_op_sign_init_result (gpgme_ctx_t ctx)
_gpgme_op_sign_init_result (gpgme_ctx_t ctx, int success_required)
{
return sign_init_result (ctx, 0);
return sign_init_result (ctx, 0, success_required);
}
@ -444,7 +453,8 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
/* If we are using the CMS protocol, we ignore the INV_RECP status
code if a newer GPGSM is in use. GPGMS does not support combined
sign+encrypt and thus this can't harm. */
err = sign_init_result (ctx, (ctx->protocol == GPGME_PROTOCOL_CMS));
err = sign_init_result (ctx, (ctx->protocol == GPGME_PROTOCOL_CMS),
flags & GPGME_SIG_MODE_ARCHIVE);
if (err)
return err;