summaryrefslogtreecommitdiffstats
path: root/test/handshake_helper.c
diff options
context:
space:
mode:
authorEmilia Kasper <emilia@openssl.org>2016-06-20 17:20:25 +0200
committerEmilia Kasper <emilia@openssl.org>2016-06-28 17:26:24 +0200
commitd2b23cd2b077de8507c49f632e20dfcdb653a35b (patch)
tree3a8a980e199c680d7e296468439c6f53d05fa1a0 /test/handshake_helper.c
parent2cdce3e32f0f70470d676352410557b626bc9d01 (diff)
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>
Diffstat (limited to 'test/handshake_helper.c')
-rw-r--r--test/handshake_helper.c77
1 files changed, 68 insertions, 9 deletions
diff --git a/test/handshake_helper.c b/test/handshake_helper.c
index a60c9c6845..8a8dab02bb 100644
--- a/test/handshake_helper.c
+++ b/test/handshake_helper.c
@@ -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)