diff options
author | David Benjamin <davidben@google.com> | 2016-07-27 01:03:08 +0300 |
---|---|---|
committer | CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> | 2016-07-27 01:32:18 +0300 |
commit | 1d4f4c0123268eee5d83921adc8503cd1b8d6c93 (patch) | |
tree | 1b48937a3774eabafd82b7b074a95132668efa03 | |
parent | abaef2e869fefcb0fac237bdf1b96c16ce8e290b (diff) |
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>
-rw-r--r-- | include/openssl/ssl.h | 10 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 14 | ||||
-rw-r--r-- | ssl/test/bssl_shim.cc | 18 | ||||
-rw-r--r-- | ssl/test/runner/runner.go | 8 | ||||
-rw-r--r-- | ssl/test/test_config.cc | 1 | ||||
-rw-r--r-- | ssl/test/test_config.h | 1 |
6 files changed, 52 insertions, 0 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index e7a28385..22042f93 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -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. * diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 8328421d..2608d875 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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; diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index edf0fe0c..dd7d3a5d 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -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"); diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index f8cb4d94..8ad99626 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -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", diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc index d242f7a4..2fa1f170 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc @@ -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[] = { diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h index 690fbe72..f6a1f123 100644 --- a/ssl/test/test_config.h +++ b/ssl/test/test_config.h @@ -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); |