Add SSL_send_fatal_alert.

WebRTC want to be able to send a random alert. Add an API for this.

Change-Id: Id3113d68f25748729fd9e9a91dbbfa93eead12c3
Reviewed-on: https://boringssl-review.googlesource.com/8950
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2016-07-26 18:03:08 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent abaef2e869
commit 1d4f4c0123
6 changed files with 52 additions and 0 deletions

View File

@ -2687,6 +2687,16 @@ OPENSSL_EXPORT const char *SSL_alert_type_string_long(int value);
* alert description or "unknown" if unknown. */
OPENSSL_EXPORT const char *SSL_alert_desc_string_long(int value);
/* SSL_send_fatal_alert sends a fatal alert over |ssl| of the specified type,
* which should be one of the |SSL_AD_*| constants. It returns one on success
* and <= 0 on error. The caller should pass the return value into
* |SSL_get_error| to determine how to proceed. Once this function has been
* called, future calls to |SSL_write| will fail.
*
* If retrying a failed operation due to |SSL_ERROR_WANT_WRITE|, subsequent
* calls must use the same |alert| parameter. */
OPENSSL_EXPORT int SSL_send_fatal_alert(SSL *ssl, uint8_t alert);
/* ex_data functions.
*

View File

@ -737,6 +737,20 @@ int SSL_shutdown(SSL *ssl) {
return ssl->s3->recv_shutdown == ssl_shutdown_close_notify;
}
int SSL_send_fatal_alert(SSL *ssl, uint8_t alert) {
if (ssl->s3->alert_dispatch) {
if (ssl->s3->send_alert[0] != SSL3_AL_FATAL ||
ssl->s3->send_alert[1] != alert) {
/* We are already attempting to write a different alert. */
OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
return -1;
}
return ssl->method->dispatch_alert(ssl);
}
return ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
}
int SSL_get_error(const SSL *ssl, int ret_code) {
int reason;
uint32_t err;

View File

@ -1017,6 +1017,17 @@ static int DoShutdown(SSL *ssl) {
return ret;
}
// DoSendFatalAlert calls |SSL_send_fatal_alert|, resolving any asynchronous
// operations. It returns the result of the final |SSL_send_fatal_alert| call.
static int DoSendFatalAlert(SSL *ssl, uint8_t alert) {
const TestConfig *config = GetTestConfig(ssl);
int ret;
do {
ret = SSL_send_fatal_alert(ssl, alert);
} while (config->async && RetryAsync(ssl, ret));
return ret;
}
// CheckHandshakeProperties checks, immediately after |ssl| completes its
// initial handshake (or False Starts), whether all the properties are
// consistent with the test configuration and invariants.
@ -1472,6 +1483,13 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
}
}
if (config->send_alert) {
if (DoSendFatalAlert(ssl.get(), SSL_AD_DECOMPRESSION_FAILURE) < 0) {
return false;
}
return true;
}
if (config->write_different_record_sizes) {
if (config->is_dtls) {
fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");

View File

@ -3335,6 +3335,14 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
})
}
tests = append(tests, testCase{
name: "ShimSendAlert",
flags: []string{"-send-alert"},
shimWritesFirst: true,
shouldFail: true,
expectedLocalError: "remote error: decompression failure",
})
if config.protocol == tls {
tests = append(tests, testCase{
name: "Renegotiate-Client",

View File

@ -104,6 +104,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-use-old-client-cert-callback",
&TestConfig::use_old_client_cert_callback },
{ "-use-null-client-ca-list", &TestConfig::use_null_client_ca_list },
{ "-send-alert", &TestConfig::send_alert },
};
const Flag<std::string> kStringFlags[] = {

View File

@ -112,6 +112,7 @@ struct TestConfig {
bool use_old_client_cert_callback = false;
int initial_timeout_duration_ms = 0;
bool use_null_client_ca_list = false;
bool send_alert = false;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);