mirror of
https://github.com/openssl/openssl.git
synced 2025-02-17 14:32:04 +08:00
Tests for SSL early callback
Plumb things through in the same place as the SNI callback, since we recommend that the early callback replace (and supplement) the SNI callback, and add a few test cases. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2279)
This commit is contained in:
parent
6b1bb98fad
commit
80de0c5947
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user