Fix session ticket and SNI
[openssl.git] / test / ssl_test.c
index 01ce5d5684d74f0fb11db6c5086bc59a4d7571c8..56dcef5510d7b1cc88d8b34efb1a4f1da549256d 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL licenses, (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
- * or in the file LICENSE in the source distribution.
  */
 
 #include <stdio.h>
+#include <string.h>
 
 #include <openssl/conf.h>
 #include <openssl/err.h>
@@ -44,8 +44,8 @@ static int check_result(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
 {
     if (result.result != test_ctx->expected_result) {
         fprintf(stderr, "ExpectedResult mismatch: expected %s, got %s.\n",
-                ssl_test_result_t_name(test_ctx->expected_result),
-                ssl_test_result_t_name(result.result));
+                ssl_test_result_name(test_ctx->expected_result),
+                ssl_test_result_name(result.result));
         return 0;
     }
     return 1;
@@ -123,6 +123,33 @@ static int check_protocol(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
     return 1;
 }
 
+static int check_servername(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
+{
+    if (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;
+    }
+    return 1;
+}
+
+static int check_session_ticket_expected(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
+{
+    if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_IGNORE)
+        return 1;
+    if (test_ctx->session_ticket_expected == SSL_TEST_SESSION_TICKET_BROKEN &&
+        result.session_ticket == SSL_TEST_SESSION_TICKET_NO)
+        return 1;
+    if (result.session_ticket != test_ctx->session_ticket_expected) {
+        fprintf(stderr, "Client SessionTicketExpected mismatch, expected %s, got %s\n.",
+                ssl_session_ticket_expected_name(test_ctx->session_ticket_expected),
+                ssl_session_ticket_expected_name(result.session_ticket));
+        return 0;
+    }
+    return 1;
+}
+
 /*
  * This could be further simplified by constructing an expected
  * HANDSHAKE_RESULT, and implementing comparison methods for
@@ -133,45 +160,77 @@ static int check_test(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
     int ret = 1;
     ret &= check_result(result, test_ctx);
     ret &= check_alerts(result, test_ctx);
-    if (result.result == SSL_TEST_SUCCESS)
+    if (result.result == SSL_TEST_SUCCESS) {
         ret &= check_protocol(result, test_ctx);
+        ret &= check_servername(result, test_ctx);
+        ret &= check_session_ticket_expected(result, test_ctx);
+        ret &= (result.session_ticket_do_not_call == 0);
+    }
     return ret;
 }
 
+static int servername_callback(SSL *s, int *ad, void *arg)
+{
+    const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
+    if (servername != NULL && !strcmp(servername, "server2")) {
+        SSL_CTX *new_ctx = (SSL_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));
+    }
+    return SSL_TLSEXT_ERR_OK;
+}
+
 static int execute_test(SSL_TEST_FIXTURE fixture)
 {
-    /* TODO(emilia): this is confusing. Flip to return 1 on success. */
-    int ret = 1;
-    SSL_CTX *server_ctx = NULL, *client_ctx = NULL;
+    int ret = 0;
+    SSL_CTX *server_ctx = NULL, *server2_ctx = NULL, *client_ctx = NULL;
     SSL_TEST_CTX *test_ctx = NULL;
     HANDSHAKE_RESULT result;
 
     server_ctx = SSL_CTX_new(TLS_server_method());
+    server2_ctx = SSL_CTX_new(TLS_server_method());
     client_ctx = SSL_CTX_new(TLS_client_method());
-    OPENSSL_assert(server_ctx != NULL && client_ctx != NULL);
+    OPENSSL_assert(server_ctx != NULL && server2_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(client_ctx, "client")) {
+        || !SSL_CTX_config(server2_ctx, "server2")
+        || !SSL_CTX_config(client_ctx, "client")) {
         goto err;
     }
 
+    /* link the two contexts for SNI purposes */
+    SSL_CTX_set_tlsext_servername_callback(server_ctx, servername_callback);
+    SSL_CTX_set_tlsext_servername_arg(server_ctx, server2_ctx);
+    /*
+     * 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_callback);
+
     test_ctx = SSL_TEST_CTX_create(conf, fixture.test_app);
     if (test_ctx == NULL)
         goto err;
 
-    result = do_handshake(server_ctx, client_ctx);
+    result = do_handshake(server_ctx, client_ctx, test_ctx);
 
-    if (check_test(result, test_ctx))
-        ret = 0;
+    ret = check_test(result, test_ctx);
 
 err:
     CONF_modules_unload(0);
     SSL_CTX_free(server_ctx);
+    SSL_CTX_free(server2_ctx);
     SSL_CTX_free(client_ctx);
     SSL_TEST_CTX_free(test_ctx);
-    if (ret != 0)
+    if (ret != 1)
         ERR_print_errors_fp(stderr);
     return ret;
 }
@@ -188,8 +247,8 @@ static void tear_down(SSL_TEST_FIXTURE fixture)
 static int test_handshake(int idx)
 {
     SETUP_SSL_TEST_FIXTURE();
-    snprintf(fixture.test_app, sizeof(fixture.test_app),
-             "test-%d", idx);
+    BIO_snprintf(fixture.test_app, sizeof(fixture.test_app),
+                 "test-%d", idx);
     EXECUTE_SSL_TEST();
 }
 
@@ -212,6 +271,5 @@ int main(int argc, char **argv)
     ADD_ALL_TESTS(test_handshake, (int)(num_tests));
     result = run_tests(argv[0]);
 
-    CONF_modules_free();
     return result;
 }