diff options
author | David Benjamin <davidben@chromium.org> | 2015-02-24 09:23:21 +0300 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2015-02-26 00:22:35 +0300 |
commit | 6f5c0f4471469f290c91af9b35c6df063f041de2 (patch) | |
tree | 56bcf612e5e80792b419c0503c27d822a902f1ce | |
parent | 7c21925a10d451ed13ab201e0161dea40b974397 (diff) |
Add tests for installing the certificate on the early callback.
Test both asynchronous and synchronous versions. This callback is somewhat
different from others. It's NOT called a second time when the handshake is
resumed. This appears to be intentional and not a mismerge from the internal
patch. The caller is expected to set up any state before resuming the handshake
state machine.
Also test the early callback returning an error.
Change-Id: If5e6eddd7007ea5cdd7533b4238e456106b95cbd
Reviewed-on: https://boringssl-review.googlesource.com/3590
Reviewed-by: Adam Langley <agl@google.com>
-rw-r--r-- | include/openssl/ssl.h | 3 | ||||
-rw-r--r-- | ssl/test/bssl_shim.cc | 88 | ||||
-rw-r--r-- | ssl/test/runner/runner.go | 20 | ||||
-rw-r--r-- | ssl/test/test_config.cc | 6 | ||||
-rw-r--r-- | ssl/test/test_config.h | 2 |
5 files changed, 81 insertions, 38 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index c5645a4c..9cc8d3f2 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -805,7 +805,8 @@ struct ssl_ctx_st { * before the decision whether to resume a session is made. It may return one * to continue the handshake or zero to cause the handshake loop to return * with an error and cause SSL_get_error to return - * SSL_ERROR_PENDING_CERTIFICATE. */ + * SSL_ERROR_PENDING_CERTIFICATE. Note: when the handshake loop is resumed, it + * will not call the callback a second time. */ int (*select_certificate_cb)(const struct ssl_early_callback_ctx *); /* quiet_shutdown is true if the connection should not send a close_notify on diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc index 28846ca5..ad4fa1ad 100644 --- a/ssl/test/bssl_shim.cc +++ b/ssl/test/bssl_shim.cc @@ -139,39 +139,51 @@ static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) { const TestConfig *config = GetConfigPtr(ctx->ssl); GetTestState(ctx->ssl)->early_callback_called = true; - if (config->expected_server_name.empty()) { - return 1; - } + if (!config->expected_server_name.empty()) { + const uint8_t *extension_data; + size_t extension_len; + CBS extension, server_name_list, host_name; + uint8_t name_type; + + if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, + &extension_data, + &extension_len)) { + fprintf(stderr, "Could not find server_name extension.\n"); + return -1; + } - const uint8_t *extension_data; - size_t extension_len; - CBS extension, server_name_list, host_name; - uint8_t name_type; + CBS_init(&extension, extension_data, extension_len); + if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || + CBS_len(&extension) != 0 || + !CBS_get_u8(&server_name_list, &name_type) || + name_type != TLSEXT_NAMETYPE_host_name || + !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || + CBS_len(&server_name_list) != 0) { + fprintf(stderr, "Could not decode server_name extension.\n"); + return -1; + } - if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name, - &extension_data, - &extension_len)) { - fprintf(stderr, "Could not find server_name extension.\n"); - return -1; + if (!CBS_mem_equal(&host_name, + (const uint8_t*)config->expected_server_name.data(), + config->expected_server_name.size())) { + fprintf(stderr, "Server name mismatch.\n"); + } } - CBS_init(&extension, extension_data, extension_len); - if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || - CBS_len(&extension) != 0 || - !CBS_get_u8(&server_name_list, &name_type) || - name_type != TLSEXT_NAMETYPE_host_name || - !CBS_get_u16_length_prefixed(&server_name_list, &host_name) || - CBS_len(&server_name_list) != 0) { - fprintf(stderr, "Could not decode server_name extension.\n"); + if (config->fail_early_callback) { return -1; } - if (!CBS_mem_equal(&host_name, - (const uint8_t*)config->expected_server_name.data(), - config->expected_server_name.size())) { - fprintf(stderr, "Server name mismatch.\n"); + // Install the certificate in the early callback. + if (config->use_early_callback) { + if (config->async) { + // Install the certificate asynchronously. + return 0; + } + if (!InstallCertificate(ctx->ssl)) { + return -1; + } } - return 1; } @@ -464,6 +476,9 @@ static bool RetryAsync(SSL *ssl, int ret, BIO *async, GetTestState(ssl)->session = std::move(GetTestState(ssl)->pending_session); return true; + case SSL_ERROR_PENDING_CERTIFICATE: + // The handshake will resume without a second call to the early callback. + return InstallCertificate(ssl); default: return false; } @@ -492,12 +507,13 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx, !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) { return false; } - if (config->async) { - // TODO(davidben): Also test |s->ctx->client_cert_cb| on the client and - // |s->ctx->select_certificate_cb| on the server. - SSL_set_cert_cb(ssl.get(), CertCallback, NULL); - } else if (!InstallCertificate(ssl.get())) { - return false; + if (!config->use_early_callback) { + if (config->async) { + // TODO(davidben): Also test |s->ctx->client_cert_cb| on the client. + SSL_set_cert_cb(ssl.get(), CertCallback, NULL); + } else if (!InstallCertificate(ssl.get())) { + return false; + } } if (config->require_any_client_certificate) { SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, @@ -650,6 +666,11 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx, return false; } + if (config->is_server && !GetTestState(ssl.get())->early_callback_called) { + fprintf(stderr, "early callback not called\n"); + return false; + } + if (!config->expected_server_name.empty()) { const char *server_name = SSL_get_servername(ssl.get(), TLSEXT_NAMETYPE_host_name); @@ -658,11 +679,6 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx, server_name, config->expected_server_name.c_str()); return false; } - - if (!GetTestState(ssl.get())->early_callback_called) { - fprintf(stderr, "early callback not called\n"); - return false; - } } if (!config->expected_certificate_types.empty()) { diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 1c844407..40798634 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -780,6 +780,14 @@ var testCases = []testCase{ shouldFail: true, expectedError: ":UNEXPECTED_RECORD:", }, + { + testType: serverTest, + name: "FailEarlyCallback", + flags: []string{"-fail-early-callback"}, + shouldFail: true, + expectedError: ":CONNECTION_REJECTED:", + expectedLocalError: "remote error: access denied", + }, } func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error { @@ -1657,6 +1665,18 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) flags: append(flags, "-implicit-handshake"), resumeSession: true, }) + testCases = append(testCases, testCase{ + protocol: protocol, + testType: serverTest, + name: "Basic-Server-EarlyCallback" + suffix, + config: Config{ + Bugs: ProtocolBugs{ + MaxHandshakeRecordLength: maxHandshakeRecordLength, + }, + }, + flags: append(flags, "-use-early-callback"), + resumeSession: true, + }) // TLS client auth. testCases = append(testCases, testCase{ diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc index afcb1067..4db72b4f 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc @@ -73,6 +73,8 @@ const Flag<bool> kBoolFlags[] = { &TestConfig::enable_signed_cert_timestamps }, { "-fastradio-padding", &TestConfig::fastradio_padding }, { "-implicit-handshake", &TestConfig::implicit_handshake }, + { "-use-early-callback", &TestConfig::use_early_callback }, + { "-fail-early-callback", &TestConfig::fail_early_callback }, }; const Flag<std::string> kStringFlags[] = { @@ -138,7 +140,9 @@ TestConfig::TestConfig() min_version(0), max_version(0), mtu(0), - implicit_handshake(false) { + implicit_handshake(false), + use_early_callback(false), + fail_early_callback(false) { } bool ParseConfig(int argc, char **argv, TestConfig *out_config) { diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h index 61b25c04..a54fb230 100644 --- a/ssl/test/test_config.h +++ b/ssl/test/test_config.h @@ -68,6 +68,8 @@ struct TestConfig { int max_version; int mtu; bool implicit_handshake; + bool use_early_callback; + bool fail_early_callback; }; bool ParseConfig(int argc, char **argv, TestConfig *out_config); |