summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/handshake_helper.c118
-rw-r--r--test/ssl-tests/05-sni.conf107
-rw-r--r--test/ssl-tests/05-sni.conf.in57
-rw-r--r--test/ssl_test_ctx.c3
-rw-r--r--test/ssl_test_ctx.h5
5 files changed, 287 insertions, 3 deletions
diff --git a/test/handshake_helper.c b/test/handshake_helper.c
index c82581c576..88f6aec894 100644
--- a/test/handshake_helper.c
+++ b/test/handshake_helper.c
@@ -123,6 +123,67 @@ static int select_server_ctx(SSL *s, void *arg, int ignore)
}
}
+static int early_select_server_ctx(SSL *s, void *arg, int ignore)
+{
+ const char *servername;
+ const unsigned char *p;
+ size_t len, remaining;
+ HANDSHAKE_EX_DATA *ex_data =
+ (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));
+
+ /*
+ * The server_name extension was given too much extensibility when it
+ * was written, so parsing the normal case is a bit complex.
+ */
+ if (!SSL_early_get0_ext(s, TLSEXT_TYPE_server_name, &p, &remaining) ||
+ remaining <= 2)
+ return 0;
+ /* Extract the length of the supplied list of names. */
+ len = (*(p++) << 1);
+ len += *(p++);
+ if (len + 2 != remaining)
+ return 0;
+ remaining = len;
+ /*
+ * The list in practice only has a single element, so we only consider
+ * the first one.
+ */
+ if (remaining == 0 || *p++ != TLSEXT_NAMETYPE_host_name)
+ return 0;
+ remaining--;
+ /* Now we can finally pull out the byte array with the actual hostname. */
+ if (remaining <= 2)
+ return 0;
+ len = (*(p++) << 1);
+ len += *(p++);
+ if (len + 2 > remaining)
+ return 0;
+ remaining = len;
+ servername = (const char *)p;
+
+ if (len == strlen("server2") && strncmp(servername, "server2", len) == 0) {
+ SSL_CTX *new_ctx = arg;
+ SSL_set_SSL_CTX(s, new_ctx);
+ /*
+ * Copy over all the SSL_CTX options - reasonable behavior
+ * allows testing of cases where the options between two
+ * contexts differ/conflict
+ */
+ SSL_clear_options(s, 0xFFFFFFFFL);
+ SSL_set_options(s, SSL_CTX_get_options(new_ctx));
+
+ ex_data->servername = SSL_TEST_SERVERNAME_SERVER2;
+ return 1;
+ } else if (len == strlen("server1") &&
+ strncmp(servername, "server1", len) == 0) {
+ ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
+ return 1;
+ } else if (ignore) {
+ ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
+ return 1;
+ }
+ return 0;
+}
/*
* (RFC 6066):
* If the server understood the ClientHello extension but
@@ -144,6 +205,50 @@ static int servername_reject_cb(SSL *s, int *ad, void *arg)
return select_server_ctx(s, arg, 0);
}
+static int early_ignore_cb(SSL *s, int *al, void *arg)
+{
+ if (!early_select_server_ctx(s, arg, 1)) {
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ return 1;
+}
+
+static int early_reject_cb(SSL *s, int *al, void *arg)
+{
+ if (!early_select_server_ctx(s, arg, 0)) {
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ return 1;
+}
+
+static int early_nov12_cb(SSL *s, int *al, void *arg)
+{
+ int ret;
+ unsigned int v;
+ const unsigned char *p;
+
+ v = SSL_early_get0_legacy_version(s);
+ if (v > TLS1_2_VERSION || v < SSL3_VERSION) {
+ *al = SSL_AD_PROTOCOL_VERSION;
+ return 0;
+ }
+ (void)SSL_early_get0_session_id(s, &p);
+ if (p == NULL ||
+ SSL_early_get0_random(s, &p) == 0 ||
+ SSL_early_get0_ciphers(s, &p) == 0 ||
+ SSL_early_get0_compression_methods(s, &p) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ ret = early_select_server_ctx(s, arg, 0);
+ SSL_set_max_proto_version(s, TLS1_1_VERSION);
+ if (!ret)
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+ return ret;
+}
+
static unsigned char dummy_ocsp_resp_good_val = 0xff;
static unsigned char dummy_ocsp_resp_bad_val = 0xfe;
@@ -337,7 +442,10 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
break;
}
- /* link the two contexts for SNI purposes */
+ /*
+ * Link the two contexts for SNI purposes.
+ * Also do early callbacks here, as setting both early and SNI is bad.
+ */
switch (extra->server.servername_callback) {
case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
@@ -349,6 +457,14 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
break;
case SSL_TEST_SERVERNAME_CB_NONE:
break;
+ case SSL_TEST_SERVERNAME_EARLY_IGNORE_MISMATCH:
+ SSL_CTX_set_early_cb(server_ctx, early_ignore_cb, server2_ctx);
+ break;
+ case SSL_TEST_SERVERNAME_EARLY_REJECT_MISMATCH:
+ SSL_CTX_set_early_cb(server_ctx, early_reject_cb, server2_ctx);
+ break;
+ case SSL_TEST_SERVERNAME_EARLY_NO_V12:
+ SSL_CTX_set_early_cb(server_ctx, early_nov12_cb, server2_ctx);
}
if (extra->server.cert_status != SSL_TEST_CERT_STATUS_NONE) {
diff --git a/test/ssl-tests/05-sni.conf b/test/ssl-tests/05-sni.conf
index e1fb3d9d89..d5d350e399 100644
--- a/test/ssl-tests/05-sni.conf
+++ b/test/ssl-tests/05-sni.conf
@@ -1,6 +1,6 @@
# Generated with generate_ssl_tests.pl
-num_tests = 6
+num_tests = 9
test-0 = 0-SNI-switch-context
test-1 = 1-SNI-keep-context
@@ -8,6 +8,9 @@ test-2 = 2-SNI-no-server-support
test-3 = 3-SNI-no-client-support
test-4 = 4-SNI-bad-sni-ignore-mismatch
test-5 = 5-SNI-bad-sni-reject-mismatch
+test-6 = 6-SNI-bad-early-sni-ignore-mismatch
+test-7 = 7-SNI-bad-early-sni-reject-mismatch
+test-8 = 8-SNI-early-disable-v12
# ===========================================================
[0-SNI-switch-context]
@@ -201,3 +204,105 @@ ServerNameCallback = RejectMismatch
ServerName = invalid
+# ===========================================================
+
+[6-SNI-bad-early-sni-ignore-mismatch]
+ssl_conf = 6-SNI-bad-early-sni-ignore-mismatch-ssl
+
+[6-SNI-bad-early-sni-ignore-mismatch-ssl]
+server = 6-SNI-bad-early-sni-ignore-mismatch-server
+client = 6-SNI-bad-early-sni-ignore-mismatch-client
+server2 = 6-SNI-bad-early-sni-ignore-mismatch-server
+
+[6-SNI-bad-early-sni-ignore-mismatch-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[6-SNI-bad-early-sni-ignore-mismatch-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-6]
+ExpectedResult = Success
+ExpectedServerName = server1
+server = 6-SNI-bad-early-sni-ignore-mismatch-server-extra
+server2 = 6-SNI-bad-early-sni-ignore-mismatch-server-extra
+client = 6-SNI-bad-early-sni-ignore-mismatch-client-extra
+
+[6-SNI-bad-early-sni-ignore-mismatch-server-extra]
+ServerNameCallback = EarlyIgnoreMismatch
+
+[6-SNI-bad-early-sni-ignore-mismatch-client-extra]
+ServerName = invalid
+
+
+# ===========================================================
+
+[7-SNI-bad-early-sni-reject-mismatch]
+ssl_conf = 7-SNI-bad-early-sni-reject-mismatch-ssl
+
+[7-SNI-bad-early-sni-reject-mismatch-ssl]
+server = 7-SNI-bad-early-sni-reject-mismatch-server
+client = 7-SNI-bad-early-sni-reject-mismatch-client
+server2 = 7-SNI-bad-early-sni-reject-mismatch-server
+
+[7-SNI-bad-early-sni-reject-mismatch-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[7-SNI-bad-early-sni-reject-mismatch-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-7]
+ExpectedResult = ServerFail
+ExpectedServerAlert = UnrecognizedName
+server = 7-SNI-bad-early-sni-reject-mismatch-server-extra
+server2 = 7-SNI-bad-early-sni-reject-mismatch-server-extra
+client = 7-SNI-bad-early-sni-reject-mismatch-client-extra
+
+[7-SNI-bad-early-sni-reject-mismatch-server-extra]
+ServerNameCallback = EarlyRejectMismatch
+
+[7-SNI-bad-early-sni-reject-mismatch-client-extra]
+ServerName = invalid
+
+
+# ===========================================================
+
+[8-SNI-early-disable-v12]
+ssl_conf = 8-SNI-early-disable-v12-ssl
+
+[8-SNI-early-disable-v12-ssl]
+server = 8-SNI-early-disable-v12-server
+client = 8-SNI-early-disable-v12-client
+server2 = 8-SNI-early-disable-v12-server
+
+[8-SNI-early-disable-v12-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[8-SNI-early-disable-v12-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-8]
+ExpectedProtocol = TLSv1.1
+ExpectedServerName = server2
+server = 8-SNI-early-disable-v12-server-extra
+server2 = 8-SNI-early-disable-v12-server-extra
+client = 8-SNI-early-disable-v12-client-extra
+
+[8-SNI-early-disable-v12-server-extra]
+ServerNameCallback = EarlyNoV12
+
+[8-SNI-early-disable-v12-client-extra]
+ServerName = server2
+
+
diff --git a/test/ssl-tests/05-sni.conf.in b/test/ssl-tests/05-sni.conf.in
index 76003e7623..63b295dac8 100644
--- a/test/ssl-tests/05-sni.conf.in
+++ b/test/ssl-tests/05-sni.conf.in
@@ -13,6 +13,7 @@ use strict;
use warnings;
package ssltests;
+use OpenSSL::Test::Utils;
our @tests = (
{
@@ -109,4 +110,60 @@ our @tests = (
"ExpectedServerAlert" => "UnrecognizedName"
},
},
+ {
+ name => "SNI-bad-early-sni-ignore-mismatch",
+ server => {
+ extra => {
+ "ServerNameCallback" => "EarlyIgnoreMismatch",
+ },
+ },
+ client => {
+ extra => {
+ "ServerName" => "invalid",
+ },
+ },
+ test => {
+ "ExpectedServerName" => "server1",
+ "ExpectedResult" => "Success"
+ },
+ },
+ {
+ name => "SNI-bad-early-sni-reject-mismatch",
+ server => {
+ extra => {
+ "ServerNameCallback" => "EarlyRejectMismatch",
+ },
+ },
+ client => {
+ extra => {
+ "ServerName" => "invalid",
+ },
+ },
+ test => {
+ "ExpectedResult" => "ServerFail",
+ "ExpectedServerAlert" => "UnrecognizedName"
+ },
+ },
);
+
+our @tests_tls_1_1 = (
+ {
+ name => "SNI-early-disable-v12",
+ server => {
+ extra => {
+ "ServerNameCallback" => "EarlyNoV12",
+ },
+ },
+ client => {
+ extra => {
+ "ServerName" => "server2",
+ },
+ },
+ test => {
+ "ExpectedProtocol" => "TLSv1.1",
+ "ExpectedServerName" => "server2",
+ },
+ },
+);
+
+push @tests, @tests_tls_1_1 unless disabled("tls1_1");
diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c
index 66fb31ce5a..f9e74d11fd 100644
--- a/test/ssl_test_ctx.c
+++ b/test/ssl_test_ctx.c
@@ -237,6 +237,9 @@ static const test_enum ssl_servername_callbacks[] = {
{"None", SSL_TEST_SERVERNAME_CB_NONE},
{"IgnoreMismatch", SSL_TEST_SERVERNAME_IGNORE_MISMATCH},
{"RejectMismatch", SSL_TEST_SERVERNAME_REJECT_MISMATCH},
+ {"EarlyIgnoreMismatch", SSL_TEST_SERVERNAME_EARLY_IGNORE_MISMATCH},
+ {"EarlyRejectMismatch", SSL_TEST_SERVERNAME_EARLY_REJECT_MISMATCH},
+ {"EarlyNoV12", SSL_TEST_SERVERNAME_EARLY_NO_V12},
};
__owur static int parse_servername_callback(SSL_TEST_SERVER_CONF *server_conf,
diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h
index 1c66740fb7..499e314e3c 100644
--- a/test/ssl_test_ctx.h
+++ b/test/ssl_test_ctx.h
@@ -38,7 +38,10 @@ typedef enum {
typedef enum {
SSL_TEST_SERVERNAME_CB_NONE = 0, /* Default */
SSL_TEST_SERVERNAME_IGNORE_MISMATCH,
- SSL_TEST_SERVERNAME_REJECT_MISMATCH
+ SSL_TEST_SERVERNAME_REJECT_MISMATCH,
+ SSL_TEST_SERVERNAME_EARLY_IGNORE_MISMATCH,
+ SSL_TEST_SERVERNAME_EARLY_REJECT_MISMATCH,
+ SSL_TEST_SERVERNAME_EARLY_NO_V12
} ssl_servername_callback_t;
typedef enum {