mirror of
https://github.com/openssl/openssl.git
synced 2024-11-21 01:15:20 +08:00
SSL test framework: port SNI tests
Observe that the old tests were partly ill-defined: setting sn_server1 but not sn_server2 in ssltest_old.c does not enable the SNI callback. Fix this, and also explicitly test both flavours of SNI mismatch (ignore / fatal alert). Tests still pass. Reviewed-by: Rich Salz <rsalz@openssl.org>
This commit is contained in:
parent
2cdce3e32f
commit
d2b23cd2b0
@ -61,6 +61,7 @@ The test section supports the following options:
|
||||
|
||||
* ClientVerifyCallback - the client's custom certificate verify callback.
|
||||
Used to test callback behaviour. One of
|
||||
- None - no custom callback (default)
|
||||
- AcceptAll - accepts all certificates.
|
||||
- RejectAll - rejects all certificates.
|
||||
|
||||
@ -70,6 +71,12 @@ The test section supports the following options:
|
||||
- None - do not use SNI (default)
|
||||
- server1 - the initial context
|
||||
- server2 - the secondary context
|
||||
- invalid - an unknown context
|
||||
|
||||
* ServerNameCallback - the SNI switching callback to use
|
||||
- None - no callback (default)
|
||||
- IgnoreMismatch - continue the handshake on SNI mismatch
|
||||
- RejectMismatch - abort the handshake on SNI mismatch
|
||||
|
||||
* SessionTicketExpected - whether or not a session ticket is expected
|
||||
- Ignore - do not check for a session ticket (default)
|
||||
|
@ -24,6 +24,7 @@ typedef struct handshake_ex_data {
|
||||
int alert_sent;
|
||||
int alert_received;
|
||||
int session_ticket_do_not_call;
|
||||
ssl_servername_t servername;
|
||||
} HANDSHAKE_EX_DATA;
|
||||
|
||||
static int ex_data_idx;
|
||||
@ -41,10 +42,25 @@ static void info_cb(const SSL *s, int where, int ret)
|
||||
}
|
||||
}
|
||||
|
||||
static int servername_cb(SSL *s, int *ad, void *arg)
|
||||
/*
|
||||
* Select the appropriate server CTX.
|
||||
* Returns SSL_TLSEXT_ERR_OK if a match was found.
|
||||
* If |ignore| is 1, returns SSL_TLSEXT_ERR_NOACK on mismatch.
|
||||
* Otherwise, returns SSL_TLSEXT_ERR_ALERT_FATAL on mismatch.
|
||||
* An empty SNI extension also returns SSL_TSLEXT_ERR_NOACK.
|
||||
*/
|
||||
static int select_server_ctx(SSL *s, void *arg, int ignore)
|
||||
{
|
||||
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername != NULL && !strcmp(servername, "server2")) {
|
||||
HANDSHAKE_EX_DATA *ex_data =
|
||||
(HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx));
|
||||
|
||||
if (servername == NULL) {
|
||||
ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
if (strcmp(servername, "server2") == 0) {
|
||||
SSL_CTX *new_ctx = (SSL_CTX*)arg;
|
||||
SSL_set_SSL_CTX(s, new_ctx);
|
||||
/*
|
||||
@ -54,8 +70,40 @@ static int servername_cb(SSL *s, int *ad, void *arg)
|
||||
*/
|
||||
SSL_clear_options(s, 0xFFFFFFFFL);
|
||||
SSL_set_options(s, SSL_CTX_get_options(new_ctx));
|
||||
|
||||
ex_data->servername = SSL_TEST_SERVERNAME_SERVER2;
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
} else if (strcmp(servername, "server1") == 0) {
|
||||
ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
} else if (ignore) {
|
||||
ex_data->servername = SSL_TEST_SERVERNAME_SERVER1;
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
} else {
|
||||
/* Don't set an explicit alert, to test library defaults. */
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* (RFC 6066):
|
||||
* If the server understood the ClientHello extension but
|
||||
* does not recognize the server name, the server SHOULD take one of two
|
||||
* actions: either abort the handshake by sending a fatal-level
|
||||
* unrecognized_name(112) alert or continue the handshake.
|
||||
*
|
||||
* This behaviour is up to the application to configure; we test both
|
||||
* configurations to ensure the state machine propagates the result
|
||||
* correctly.
|
||||
*/
|
||||
static int servername_ignore_cb(SSL *s, int *ad, void *arg)
|
||||
{
|
||||
return select_server_ctx(s, arg, 1);
|
||||
}
|
||||
|
||||
static int servername_reject_cb(SSL *s, int *ad, void *arg)
|
||||
{
|
||||
return select_server_ctx(s, arg, 0);
|
||||
}
|
||||
|
||||
static int verify_reject_cb(X509_STORE_CTX *ctx, void *arg) {
|
||||
@ -106,14 +154,27 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
|
||||
}
|
||||
|
||||
/* link the two contexts for SNI purposes */
|
||||
SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_cb);
|
||||
SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
|
||||
switch (test_ctx->servername_callback) {
|
||||
case SSL_TEST_SERVERNAME_IGNORE_MISMATCH:
|
||||
SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_ignore_cb);
|
||||
SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
|
||||
break;
|
||||
case SSL_TEST_SERVERNAME_REJECT_MISMATCH:
|
||||
SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_reject_cb);
|
||||
SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The initial_ctx/session_ctx always handles the encrypt/decrypt of the
|
||||
* session ticket. This ticket_key callback is assigned to the second
|
||||
* session (assigned via SNI), and should never be invoked
|
||||
*/
|
||||
SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx, do_not_call_session_ticket_cb);
|
||||
if (server2_ctx != NULL)
|
||||
SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx,
|
||||
do_not_call_session_ticket_cb);
|
||||
|
||||
if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_BROKEN) {
|
||||
SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb);
|
||||
@ -333,9 +394,7 @@ HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
|
||||
ret.client_alert_received = server_ex_data.alert_received;
|
||||
ret.server_protocol = SSL_version(server);
|
||||
ret.client_protocol = SSL_version(client);
|
||||
ret.servername = ((SSL_get_SSL_CTX(server) == server_ctx)
|
||||
? SSL_TEST_SERVERNAME_SERVER1
|
||||
: SSL_TEST_SERVERNAME_SERVER2);
|
||||
ret.servername = server_ex_data.servername;
|
||||
if ((sess = SSL_get0_session(client)) != NULL)
|
||||
SSL_SESSION_get0_ticket(sess, &tick, &len);
|
||||
if (tick == NULL || len == 0)
|
||||
|
@ -79,7 +79,7 @@ my $client_sess="client.ss";
|
||||
# new format in ssl_test.c and add recipes to 80-test_ssl_new.t instead.
|
||||
plan tests =>
|
||||
1 # For testss
|
||||
+ 13 # For the first testssl
|
||||
+ 12 # For the first testssl
|
||||
;
|
||||
|
||||
subtest 'test_ss' => sub {
|
||||
@ -579,25 +579,6 @@ sub testssl {
|
||||
}
|
||||
};
|
||||
|
||||
subtest 'SNI tests' => sub {
|
||||
|
||||
plan tests => 7;
|
||||
|
||||
SKIP: {
|
||||
skip "TLSv1.x is not supported by this OpenSSL build", 7
|
||||
if $no_tls1 && $no_tls1_1 && $no_tls1_2;
|
||||
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "foo"])));
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_server1", "foo"])));
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "foo", "-sn_server1", "foo", "-sn_expect1"])));
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "foo", "-sn_server1", "bar", "-sn_expect1"])));
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "foo", "-sn_server1", "foo", "-sn_server2", "bar", "-sn_expect1"])));
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "bar", "-sn_server1", "foo", "-sn_server2", "bar", "-sn_expect2"])));
|
||||
# Negative test - make sure it doesn't crash, and doesn't switch contexts
|
||||
ok(run(test([@ssltest, "-bio_pair", "-sn_client", "foobar", "-sn_server1", "foo", "-sn_server2", "bar", "-sn_expect1"])));
|
||||
}
|
||||
};
|
||||
|
||||
subtest 'ALPN tests' => sub {
|
||||
######################################################################
|
||||
|
||||
|
@ -1,35 +1,193 @@
|
||||
# Generated with generate_ssl_tests.pl
|
||||
|
||||
num_tests = 1
|
||||
num_tests = 6
|
||||
|
||||
test-0 = 0-SNI-default
|
||||
test-0 = 0-SNI-switch-context
|
||||
test-1 = 1-SNI-keep-context
|
||||
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
|
||||
# ===========================================================
|
||||
|
||||
[0-SNI-default]
|
||||
ssl_conf = 0-SNI-default-ssl
|
||||
[0-SNI-switch-context]
|
||||
ssl_conf = 0-SNI-switch-context-ssl
|
||||
|
||||
[0-SNI-default-ssl]
|
||||
server = 0-SNI-default-server
|
||||
server2 = 0-SNI-default-server2
|
||||
client = 0-SNI-default-client
|
||||
[0-SNI-switch-context-ssl]
|
||||
server = 0-SNI-switch-context-server
|
||||
server2 = 0-SNI-switch-context-server2
|
||||
client = 0-SNI-switch-context-client
|
||||
|
||||
[0-SNI-default-server]
|
||||
[0-SNI-switch-context-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[0-SNI-default-server2]
|
||||
[0-SNI-switch-context-server2]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[0-SNI-default-client]
|
||||
[0-SNI-switch-context-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-0]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
|
||||
|
||||
# ===========================================================
|
||||
|
||||
[1-SNI-keep-context]
|
||||
ssl_conf = 1-SNI-keep-context-ssl
|
||||
|
||||
[1-SNI-keep-context-ssl]
|
||||
server = 1-SNI-keep-context-server
|
||||
server2 = 1-SNI-keep-context-server2
|
||||
client = 1-SNI-keep-context-client
|
||||
|
||||
[1-SNI-keep-context-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[1-SNI-keep-context-server2]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[1-SNI-keep-context-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-1]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
|
||||
|
||||
# ===========================================================
|
||||
|
||||
[2-SNI-no-server-support]
|
||||
ssl_conf = 2-SNI-no-server-support-ssl
|
||||
|
||||
[2-SNI-no-server-support-ssl]
|
||||
server = 2-SNI-no-server-support-server
|
||||
client = 2-SNI-no-server-support-client
|
||||
|
||||
[2-SNI-no-server-support-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[2-SNI-no-server-support-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-2]
|
||||
ExpectedResult = Success
|
||||
ServerName = server1
|
||||
|
||||
|
||||
# ===========================================================
|
||||
|
||||
[3-SNI-no-client-support]
|
||||
ssl_conf = 3-SNI-no-client-support-ssl
|
||||
|
||||
[3-SNI-no-client-support-ssl]
|
||||
server = 3-SNI-no-client-support-server
|
||||
server2 = 3-SNI-no-client-support-server2
|
||||
client = 3-SNI-no-client-support-client
|
||||
|
||||
[3-SNI-no-client-support-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[3-SNI-no-client-support-server2]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[3-SNI-no-client-support-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-3]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
|
||||
|
||||
# ===========================================================
|
||||
|
||||
[4-SNI-bad-sni-ignore-mismatch]
|
||||
ssl_conf = 4-SNI-bad-sni-ignore-mismatch-ssl
|
||||
|
||||
[4-SNI-bad-sni-ignore-mismatch-ssl]
|
||||
server = 4-SNI-bad-sni-ignore-mismatch-server
|
||||
server2 = 4-SNI-bad-sni-ignore-mismatch-server2
|
||||
client = 4-SNI-bad-sni-ignore-mismatch-client
|
||||
|
||||
[4-SNI-bad-sni-ignore-mismatch-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[4-SNI-bad-sni-ignore-mismatch-server2]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[4-SNI-bad-sni-ignore-mismatch-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-4]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = invalid
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
|
||||
|
||||
# ===========================================================
|
||||
|
||||
[5-SNI-bad-sni-reject-mismatch]
|
||||
ssl_conf = 5-SNI-bad-sni-reject-mismatch-ssl
|
||||
|
||||
[5-SNI-bad-sni-reject-mismatch-ssl]
|
||||
server = 5-SNI-bad-sni-reject-mismatch-server
|
||||
server2 = 5-SNI-bad-sni-reject-mismatch-server2
|
||||
client = 5-SNI-bad-sni-reject-mismatch-client
|
||||
|
||||
[5-SNI-bad-sni-reject-mismatch-server]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[5-SNI-bad-sni-reject-mismatch-server2]
|
||||
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
|
||||
CipherString = DEFAULT
|
||||
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
|
||||
|
||||
[5-SNI-bad-sni-reject-mismatch-client]
|
||||
CipherString = DEFAULT
|
||||
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
|
||||
VerifyMode = Peer
|
||||
|
||||
[test-5]
|
||||
ExpectedResult = ServerFail
|
||||
ServerAlert = UnrecognizedName
|
||||
ServerName = invalid
|
||||
ServerNameCallback = RejectMismatch
|
||||
|
||||
|
||||
|
@ -16,11 +16,64 @@ package ssltests;
|
||||
|
||||
our @tests = (
|
||||
{
|
||||
name => "SNI-default",
|
||||
name => "SNI-switch-context",
|
||||
server => { },
|
||||
server2 => { },
|
||||
client => { },
|
||||
test => { "ServerName" => "server2",
|
||||
"ExpectedResult" => "Success" },
|
||||
"ExpectedServerName" => "server2",
|
||||
"ServerNameCallback" => "IgnoreMismatch",
|
||||
"ExpectedResult" => "Success" },
|
||||
},
|
||||
{
|
||||
name => "SNI-keep-context",
|
||||
server => { },
|
||||
server2 => { },
|
||||
client => { },
|
||||
test => { "ServerName" => "server1",
|
||||
"ExpectedServerName" => "server1",
|
||||
"ServerNameCallback" => "IgnoreMismatch",
|
||||
"ExpectedResult" => "Success" },
|
||||
},
|
||||
{
|
||||
name => "SNI-no-server-support",
|
||||
server => { },
|
||||
client => { },
|
||||
test => { "ServerName" => "server1",
|
||||
"ExpectedResult" => "Success" },
|
||||
},
|
||||
{
|
||||
name => "SNI-no-client-support",
|
||||
server => { },
|
||||
server2 => { },
|
||||
client => { },
|
||||
test => {
|
||||
# We expect that the callback is still called
|
||||
# to let the application decide whether they tolerate
|
||||
# missing SNI (as our test callback does).
|
||||
"ExpectedServerName" => "server1",
|
||||
"ServerNameCallback" => "IgnoreMismatch",
|
||||
"ExpectedResult" => "Success"
|
||||
},
|
||||
},
|
||||
{
|
||||
name => "SNI-bad-sni-ignore-mismatch",
|
||||
server => { },
|
||||
server2 => { },
|
||||
client => { },
|
||||
test => { "ServerName" => "invalid",
|
||||
"ExpectedServerName" => "server1",
|
||||
"ServerNameCallback" => "IgnoreMismatch",
|
||||
"ExpectedResult" => "Success" },
|
||||
},
|
||||
{
|
||||
name => "SNI-bad-sni-reject-mismatch",
|
||||
server => { },
|
||||
server2 => { },
|
||||
client => { },
|
||||
test => { "ServerName" => "invalid",
|
||||
"ServerNameCallback" => "RejectMismatch",
|
||||
"ExpectedResult" => "ServerFail",
|
||||
"ServerAlert" => "UnrecognizedName"},
|
||||
},
|
||||
);
|
||||
|
@ -83,7 +83,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-1]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = Yes
|
||||
|
||||
|
||||
@ -117,7 +119,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-2]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = Yes
|
||||
|
||||
|
||||
@ -151,7 +155,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-3]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = Yes
|
||||
|
||||
|
||||
@ -185,7 +191,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-4]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -219,7 +227,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-5]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -253,7 +263,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-6]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -287,7 +299,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-7]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -321,7 +335,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-8]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -355,7 +371,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-9]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -389,7 +407,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-10]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -423,7 +443,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-11]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -457,7 +479,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-12]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -491,7 +515,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-13]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -525,7 +551,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-14]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -559,7 +587,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-15]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server1
|
||||
ServerName = server1
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
@ -593,7 +623,9 @@ VerifyMode = Peer
|
||||
|
||||
[test-16]
|
||||
ExpectedResult = Success
|
||||
ExpectedServerName = server2
|
||||
ServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = No
|
||||
|
||||
|
||||
|
@ -36,6 +36,9 @@ sub generate_tests() {
|
||||
},
|
||||
"test" => {
|
||||
"ServerName" => $n,
|
||||
"ExpectedServerName" => $n,
|
||||
# We don't test mismatch here.
|
||||
"ServerNameCallback" => "IgnoreMismatch",
|
||||
"ExpectedResult" => "Success",
|
||||
"SessionTicketExpected" => $result,
|
||||
}
|
||||
|
@ -125,14 +125,13 @@ static int check_protocol(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
|
||||
|
||||
static int check_servername(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
|
||||
{
|
||||
if (test_ctx->servername != SSL_TEST_SERVERNAME_NONE
|
||||
&& result.servername != test_ctx->servername) {
|
||||
fprintf(stderr, "Client ServerName mismatch, expected %s, got %s\n.",
|
||||
ssl_servername_name(test_ctx->servername),
|
||||
ssl_servername_name(result.servername));
|
||||
return 0;
|
||||
if (result.servername != test_ctx->expected_servername) {
|
||||
fprintf(stderr, "Client ServerName mismatch, expected %s, got %s\n.",
|
||||
ssl_servername_name(test_ctx->expected_servername),
|
||||
ssl_servername_name(result.servername));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_session_ticket(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
|
||||
@ -176,40 +175,42 @@ static int execute_test(SSL_TEST_FIXTURE fixture)
|
||||
SSL_CTX *server_ctx = NULL, *server2_ctx = NULL, *client_ctx = NULL;
|
||||
SSL_TEST_CTX *test_ctx = NULL;
|
||||
HANDSHAKE_RESULT result;
|
||||
const char *server2;
|
||||
|
||||
test_ctx = SSL_TEST_CTX_create(conf, fixture.test_app);
|
||||
if (test_ctx == NULL)
|
||||
goto err;
|
||||
|
||||
/* Use ServerName to detect if we're testing SNI. */
|
||||
server2 = (test_ctx->servername != SSL_TEST_SERVERNAME_NONE) ? "server2"
|
||||
: "server";
|
||||
|
||||
#ifndef OPENSSL_NO_DTLS
|
||||
if (test_ctx->method == SSL_TEST_METHOD_DTLS) {
|
||||
server_ctx = SSL_CTX_new(DTLS_server_method());
|
||||
server2_ctx = SSL_CTX_new(DTLS_server_method());
|
||||
if (test_ctx->servername_callback != SSL_TEST_SERVERNAME_CB_NONE) {
|
||||
server2_ctx = SSL_CTX_new(DTLS_server_method());
|
||||
OPENSSL_assert(server2_ctx != NULL);
|
||||
}
|
||||
client_ctx = SSL_CTX_new(DTLS_client_method());
|
||||
}
|
||||
#endif
|
||||
if (test_ctx->method == SSL_TEST_METHOD_TLS) {
|
||||
server_ctx = SSL_CTX_new(TLS_server_method());
|
||||
server2_ctx = SSL_CTX_new(TLS_server_method());
|
||||
if (test_ctx->servername_callback != SSL_TEST_SERVERNAME_CB_NONE) {
|
||||
server2_ctx = SSL_CTX_new(TLS_server_method());
|
||||
OPENSSL_assert(server2_ctx != NULL);
|
||||
}
|
||||
client_ctx = SSL_CTX_new(TLS_client_method());
|
||||
}
|
||||
|
||||
OPENSSL_assert(server_ctx != NULL && server2_ctx != NULL &&
|
||||
client_ctx != NULL);
|
||||
OPENSSL_assert(server_ctx != NULL && client_ctx != NULL);
|
||||
|
||||
OPENSSL_assert(CONF_modules_load(conf, fixture.test_app, 0) > 0);
|
||||
|
||||
if (!SSL_CTX_config(server_ctx, "server")
|
||||
|| !SSL_CTX_config(server2_ctx, server2)
|
||||
|| !SSL_CTX_config(client_ctx, "client")) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (server2_ctx != NULL && !SSL_CTX_config(server2_ctx, "server2"))
|
||||
goto err;
|
||||
|
||||
result = do_handshake(server_ctx, server2_ctx, client_ctx, test_ctx);
|
||||
|
||||
ret = check_test(result, test_ctx);
|
||||
|
@ -82,6 +82,7 @@ const char *ssl_test_result_name(ssl_test_result_t result)
|
||||
static const test_enum ssl_alerts[] = {
|
||||
{"UnknownCA", SSL_AD_UNKNOWN_CA},
|
||||
{"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
|
||||
{"UnrecognizedName", SSL_AD_UNRECOGNIZED_NAME},
|
||||
};
|
||||
|
||||
__owur static int parse_alert(int *alert, const char *value)
|
||||
@ -164,6 +165,7 @@ static const test_enum ssl_servername[] = {
|
||||
{"None", SSL_TEST_SERVERNAME_NONE},
|
||||
{"server1", SSL_TEST_SERVERNAME_SERVER1},
|
||||
{"server2", SSL_TEST_SERVERNAME_SERVER2},
|
||||
{"invalid", SSL_TEST_SERVERNAME_INVALID},
|
||||
};
|
||||
|
||||
__owur static int parse_servername(SSL_TEST_CTX *test_ctx,
|
||||
@ -178,12 +180,52 @@ __owur static int parse_servername(SSL_TEST_CTX *test_ctx,
|
||||
return 1;
|
||||
}
|
||||
|
||||
__owur static int parse_expected_servername(SSL_TEST_CTX *test_ctx,
|
||||
const char *value)
|
||||
{
|
||||
int ret_value;
|
||||
if (!parse_enum(ssl_servername, OSSL_NELEM(ssl_servername),
|
||||
&ret_value, value)) {
|
||||
return 0;
|
||||
}
|
||||
test_ctx->expected_servername = ret_value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ssl_servername_name(ssl_servername_t server)
|
||||
{
|
||||
return enum_name(ssl_servername, OSSL_NELEM(ssl_servername),
|
||||
server);
|
||||
}
|
||||
|
||||
/***********************/
|
||||
/* ServerNameCallback. */
|
||||
/***********************/
|
||||
|
||||
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},
|
||||
};
|
||||
|
||||
__owur static int parse_servername_callback(SSL_TEST_CTX *test_ctx,
|
||||
const char *value)
|
||||
{
|
||||
int ret_value;
|
||||
if (!parse_enum(ssl_servername_callbacks,
|
||||
OSSL_NELEM(ssl_servername_callbacks), &ret_value, value)) {
|
||||
return 0;
|
||||
}
|
||||
test_ctx->servername_callback = ret_value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
|
||||
{
|
||||
return enum_name(ssl_servername_callbacks,
|
||||
OSSL_NELEM(ssl_servername_callbacks), callback);
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* SessionTicketExpected */
|
||||
/*************************/
|
||||
@ -254,6 +296,8 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
|
||||
{ "Protocol", &parse_protocol },
|
||||
{ "ClientVerifyCallback", &parse_client_verify_callback },
|
||||
{ "ServerName", &parse_servername },
|
||||
{ "ExpectedServerName", &parse_expected_servername },
|
||||
{ "ServerNameCallback", &parse_servername_callback },
|
||||
{ "SessionTicketExpected", &parse_session_ticket },
|
||||
{ "Method", &parse_test_method },
|
||||
};
|
||||
|
@ -29,9 +29,17 @@ typedef enum {
|
||||
typedef enum {
|
||||
SSL_TEST_SERVERNAME_NONE = 0, /* Default */
|
||||
SSL_TEST_SERVERNAME_SERVER1,
|
||||
SSL_TEST_SERVERNAME_SERVER2
|
||||
SSL_TEST_SERVERNAME_SERVER2,
|
||||
SSL_TEST_SERVERNAME_INVALID
|
||||
} ssl_servername_t;
|
||||
|
||||
typedef enum {
|
||||
SSL_TEST_SERVERNAME_CB_NONE = 0, /* Default */
|
||||
SSL_TEST_SERVERNAME_IGNORE_MISMATCH,
|
||||
SSL_TEST_SERVERNAME_REJECT_MISMATCH
|
||||
} ssl_servername_callback_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SSL_TEST_SESSION_TICKET_IGNORE = 0, /* Default */
|
||||
SSL_TEST_SESSION_TICKET_YES,
|
||||
@ -61,6 +69,18 @@ typedef struct ssl_test_ctx {
|
||||
ssl_verify_callback_t client_verify_callback;
|
||||
/* One of a number of predefined server names use by the client */
|
||||
ssl_servername_t servername;
|
||||
/*
|
||||
* The expected SNI context to use.
|
||||
* We test server-side that the server switched to the expected context.
|
||||
* Set by the callback upon success, so if the callback wasn't called or
|
||||
* terminated with an alert, the servername will match with
|
||||
* SSL_TEST_SERVERNAME_NONE.
|
||||
* Note: in the event that the servername was accepted, the client should
|
||||
* also receive an empty SNI extension back but we have no way of probing
|
||||
* client-side via the API that this was the case.
|
||||
*/
|
||||
ssl_servername_t expected_servername;
|
||||
ssl_servername_callback_t servername_callback;
|
||||
ssl_session_ticket_t session_ticket_expected;
|
||||
/* Whether the server/client CTX should use DTLS or TLS. */
|
||||
ssl_test_method_t method;
|
||||
@ -71,6 +91,8 @@ const char *ssl_alert_name(int alert);
|
||||
const char *ssl_protocol_name(int protocol);
|
||||
const char *ssl_verify_callback_name(ssl_verify_callback_t verify_callback);
|
||||
const char *ssl_servername_name(ssl_servername_t server);
|
||||
const char *ssl_servername_callback_name(ssl_servername_callback_t
|
||||
servername_callback);
|
||||
const char *ssl_session_ticket_name(ssl_session_ticket_t server);
|
||||
const char *ssl_test_method_name(ssl_test_method_t method);
|
||||
|
||||
|
@ -70,6 +70,18 @@ static int SSL_TEST_CTX_equal(SSL_TEST_CTX *ctx, SSL_TEST_CTX *ctx2)
|
||||
ssl_servername_name(ctx2->servername));
|
||||
return 0;
|
||||
}
|
||||
if (ctx->expected_servername != ctx2->expected_servername) {
|
||||
fprintf(stderr, "ExpectedServerName mismatch: %s vs %s.\n",
|
||||
ssl_servername_name(ctx->expected_servername),
|
||||
ssl_servername_name(ctx2->expected_servername));
|
||||
return 0;
|
||||
}
|
||||
if (ctx->servername_callback != ctx2->servername_callback) {
|
||||
fprintf(stderr, "ServerNameCallback mismatch: %s vs %s.\n",
|
||||
ssl_servername_callback_name(ctx->servername_callback),
|
||||
ssl_servername_callback_name(ctx2->servername_callback));
|
||||
return 0;
|
||||
}
|
||||
if (ctx->session_ticket_expected != ctx2->session_ticket_expected) {
|
||||
fprintf(stderr, "SessionTicketExpected mismatch: %s vs %s.\n",
|
||||
ssl_session_ticket_name(ctx->session_ticket_expected),
|
||||
@ -155,6 +167,9 @@ static int test_good_configuration()
|
||||
fixture.expected_ctx->protocol = TLS1_1_VERSION;
|
||||
fixture.expected_ctx->client_verify_callback = SSL_TEST_VERIFY_REJECT_ALL;
|
||||
fixture.expected_ctx->servername = SSL_TEST_SERVERNAME_SERVER2;
|
||||
fixture.expected_ctx->expected_servername = SSL_TEST_SERVERNAME_SERVER2;
|
||||
fixture.expected_ctx->servername_callback =
|
||||
SSL_TEST_SERVERNAME_IGNORE_MISMATCH;
|
||||
fixture.expected_ctx->session_ticket_expected = SSL_TEST_SESSION_TICKET_YES;
|
||||
fixture.expected_ctx->method = SSL_TEST_METHOD_DTLS;
|
||||
EXECUTE_SSL_TEST_CTX_TEST();
|
||||
@ -167,6 +182,7 @@ static const char *bad_configurations[] = {
|
||||
"ssltest_unknown_protocol",
|
||||
"ssltest_unknown_verify_callback",
|
||||
"ssltest_unknown_servername",
|
||||
"ssltest_unknown_servername_callback",
|
||||
"ssltest_unknown_session_ticket_expected",
|
||||
"ssltest_unknown_method",
|
||||
};
|
||||
|
@ -6,6 +6,8 @@ ClientAlert = UnknownCA
|
||||
Protocol = TLSv1.1
|
||||
ClientVerifyCallback = RejectAll
|
||||
ServerName = server2
|
||||
ExpectedServerName = server2
|
||||
ServerNameCallback = IgnoreMismatch
|
||||
SessionTicketExpected = Yes
|
||||
Method = DTLS
|
||||
|
||||
@ -27,9 +29,11 @@ ClientVerifyCallback = Foo
|
||||
[ssltest_unknown_servername]
|
||||
ServerName = Foo
|
||||
|
||||
[ssltest_unknown_servername_callback]
|
||||
ServerNameCallback = Foo
|
||||
|
||||
[ssltest_unknown_session_ticket_expected]
|
||||
SessionTicketExpected = Foo
|
||||
|
||||
[ssltest_unknown_method]
|
||||
Method = TLS2
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user