[openssl-commits] [openssl] master update

Rich Salz rsalz at openssl.org
Fri Jul 28 16:06:08 UTC 2017


The branch master has been updated
       via  190b9a03b72a8029c27e4bd0ab000129e240a413 (commit)
      from  3ca1f892a7d94fb1595408f5fe80dee51dceb3b8 (commit)


- Log -----------------------------------------------------------------
commit 190b9a03b72a8029c27e4bd0ab000129e240a413
Author: Paul Yang <yang.yang at baishancloud.com>
Date:   Wed Jun 28 15:46:13 2017 +0800

    Make SSL_set_tlsext_host_name no effect from server side
    
    Documentation and test cases are also updated
    
    Reviewed-by: Ben Kaduk <kaduk at mit.edu>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3783)

-----------------------------------------------------------------------

Summary of changes:
 .../SSL_CTX_set_tlsext_servername_callback.pod     |  14 +-
 ssl/ssl_lib.c                                      |   6 +
 test/build.info                                    |   7 +-
 .../{70-test_recordlen.t => 70-test_servername.t}  |  15 +-
 test/servername_test.c                             | 241 +++++++++++++++++++++
 util/private.num                                   |   1 +
 6 files changed, 274 insertions(+), 10 deletions(-)
 copy test/recipes/{70-test_recordlen.t => 70-test_servername.t} (64%)
 create mode 100644 test/servername_test.c

diff --git a/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod b/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
index 673d98f..151de16 100644
--- a/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_servername_callback.pod
@@ -3,8 +3,8 @@
 =head1 NAME
 
 SSL_CTX_set_tlsext_servername_callback, SSL_CTX_set_tlsext_servername_arg,
-SSL_get_servername_type, SSL_get_servername - handle server name indication
-(SNI)
+SSL_get_servername_type, SSL_get_servername,
+SSL_set_tlsext_host_name - handle server name indication (SNI)
 
 =head1 SYNOPSIS
 
@@ -17,6 +17,8 @@ SSL_get_servername_type, SSL_get_servername - handle server name indication
  const char *SSL_get_servername(const SSL *s, const int type);
  int SSL_get_servername_type(const SSL *s);
 
+ int SSL_set_tlsext_host_name(const SSL *s, const char *name);
+
 =head1 DESCRIPTION
 
 The functionality provided by the servername callback is superseded by
@@ -39,16 +41,24 @@ SSL_get_servername_type() returns the servername type or -1 if no servername
 is present. Currently the only supported type (defined in RFC3546) is
 B<TLSEXT_NAMETYPE_host_name>.
 
+SSL_set_tlsext_host_name() sets the server name indication ClientHello extension
+to contain the value B<name>. The type of server name indication extension is set
+to B<TLSEXT_NAMETYPE_host_name> (defined in RFC3546).
+
 =head1 NOTES
 
 Several callbacks are executed during ClientHello processing, including
 the early, ALPN, and servername callbacks.  The early callback is executed
 first, then the servername callback, followed by the ALPN callback.
 
+The SSL_set_tlsext_host_name() function should only be called on SSL objects
+that will act as clients; otherwise the configured B<name> will be ignored.
+
 =head1 RETURN VALUES
 
 SSL_CTX_set_tlsext_servername_callback() and
 SSL_CTX_set_tlsext_servername_arg() both always return 1 indicating success.
+SSL_set_tlsext_host_name() returns 1 on success, 0 in case of error.
 
 =head1 SEE ALSO
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 74767f6..ab8e443 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3315,6 +3315,12 @@ int SSL_do_handshake(SSL *s)
 
     s->method->ssl_renegotiate_check(s, 0);
 
+    if (SSL_is_server(s)) {
+        /* clear SNI settings at server-side */
+        OPENSSL_free(s->ext.hostname);
+        s->ext.hostname = NULL;
+    }
+
     if (SSL_in_init(s) || SSL_in_before(s)) {
         if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
             struct ssl_async_args args;
diff --git a/test/build.info b/test/build.info
index a73e6ca..db34a5f 100644
--- a/test/build.info
+++ b/test/build.info
@@ -44,7 +44,8 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
           pkey_meth_test uitest cipherbytes_test asn1_encode_test asn1_string_table_test \
           x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
           recordlentest drbgtest sslbuffertest \
-          time_offset_test pemtest ssl_cert_table_internal_test ciphername_test
+          time_offset_test pemtest ssl_cert_table_internal_test ciphername_test \
+          servername_test
 
   SOURCE[aborttest]=aborttest.c
   INCLUDE[aborttest]=../include
@@ -327,6 +328,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
   INCLUDE[ciphername_test]=.. ../include
   DEPEND[ciphername_test]=../libcrypto ../libssl libtestutil.a
 
+  SOURCE[servername_test]=servername_test.c
+  INCLUDE[servername_test]=.. ../include
+  DEPEND[servername_test]=../libcrypto ../libssl libtestutil.a
+
   IF[{- !$disabled{psk} -}]
     PROGRAMS_NO_INST=dtls_mtu_test
     SOURCE[dtls_mtu_test]=dtls_mtu_test.c ssltestlib.c
diff --git a/test/recipes/70-test_recordlen.t b/test/recipes/70-test_servername.t
similarity index 64%
copy from test/recipes/70-test_recordlen.t
copy to test/recipes/70-test_servername.t
index 12647a2..dae5d46 100644
--- a/test/recipes/70-test_recordlen.t
+++ b/test/recipes/70-test_servername.t
@@ -1,21 +1,22 @@
 #! /usr/bin/env perl
 # Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2017 BaishanCloud. All rights reserved.
 #
 # 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
 
+use strict;
+use warnings;
 
-use OpenSSL::Test::Utils;
-use OpenSSL::Test qw/:DEFAULT srctop_file/;
+use OpenSSL::Test::Simple;
+use OpenSSL::Test;
+use OpenSSL::Test::Utils qw(alldisabled available_protocols);
 
-setup("test_recordlen");
+setup("test_servername");
 
 plan skip_all => "No TLS/SSL protocols are supported by this OpenSSL build"
     if alldisabled(grep { $_ ne "ssl3" } available_protocols("tls"));
 
-plan tests => 1;
-
-ok(run(test(["recordlentest", srctop_file("apps", "server.pem"),
-             srctop_file("apps", "server.pem")])), "running recordlentest");
+simple_test("test_servername", "servername_test");
diff --git a/test/servername_test.c b/test/servername_test.c
new file mode 100644
index 0000000..afb7457
--- /dev/null
+++ b/test/servername_test.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 BaishanCloud. All rights reserved.
+ *
+ * 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
+ */
+
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <time.h>
+
+#include "../ssl/packet_locl.h"
+
+#include "testutil.h"
+#include "e_os.h"
+
+#define CLIENT_VERSION_LEN      2
+
+static const char *host = "dummy-host";
+
+static int get_sni_from_client_hello(BIO *bio, char **sni)
+{
+    long len;
+    unsigned char *data;
+    PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0}, pkt4 = {0}, pkt5 = {0};
+    unsigned int servname_type = 0, type = 0;
+    int ret = 0;
+
+    len = BIO_get_mem_data(bio, (char **)&data);
+    if (!TEST_true(PACKET_buf_init(&pkt, data, len))
+               /* Skip the record header */
+            || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)
+               /* Skip the handshake message header */
+            || !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
+               /* Skip client version and random */
+            || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
+                                               + SSL3_RANDOM_SIZE))
+               /* Skip session id */
+            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
+               /* Skip ciphers */
+            || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
+               /* Skip compression */
+            || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
+               /* Extensions len */
+            || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
+        goto end;
+
+    /* Loop through all extensions for SNI */
+    while (PACKET_remaining(&pkt2)) {
+        if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
+                || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
+            goto end;
+        if (type == TLSEXT_TYPE_server_name) {
+            if (!TEST_true(PACKET_get_length_prefixed_2(&pkt3, &pkt4))
+                    || !TEST_uint_ne(PACKET_remaining(&pkt4), 0)
+                    || !TEST_true(PACKET_get_1(&pkt4, &servname_type))
+                    || !TEST_uint_eq(servname_type, TLSEXT_NAMETYPE_host_name)
+                    || !TEST_true(PACKET_get_length_prefixed_2(&pkt4, &pkt5))
+                    || !TEST_uint_le(PACKET_remaining(&pkt5), TLSEXT_MAXLEN_host_name)
+                    || !TEST_false(PACKET_contains_zero_byte(&pkt5))
+                    || !TEST_true(PACKET_strndup(&pkt5, sni)))
+                goto end;
+            ret = 1;
+            goto end;
+        }
+    }
+end:
+    return ret;
+}
+
+static int client_setup_sni_before_state()
+{
+    SSL_CTX *ctx;
+    SSL *con = NULL;
+    BIO *rbio;
+    BIO *wbio;
+    char *hostname = NULL;
+    int ret = 0;
+
+    /* use TLS_method to blur 'side' */
+    ctx = SSL_CTX_new(TLS_method());
+    if (!TEST_ptr(ctx))
+        goto end;
+
+    con = SSL_new(ctx);
+    if (!TEST_ptr(con))
+        goto end;
+
+    /* set SNI before 'client side' is set */
+    SSL_set_tlsext_host_name(con, host);
+
+    rbio = BIO_new(BIO_s_mem());
+    wbio = BIO_new(BIO_s_mem());
+    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
+        BIO_free(rbio);
+        BIO_free(wbio);
+        goto end;
+    }
+
+    SSL_set_bio(con, rbio, wbio);
+
+    if (!TEST_int_le(SSL_connect(con), 0))
+        /* This shouldn't succeed because we don't have a server! */
+        goto end;
+    if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
+        /* no SNI in client hello */
+        goto end;
+    if (!TEST_str_eq(hostname, host))
+        /* incorrect SNI value */
+        goto end;
+    ret = 1;
+end:
+    OPENSSL_free(hostname);
+    SSL_free(con);
+    SSL_CTX_free(ctx);
+    return ret;
+}
+
+static int client_setup_sni_after_state()
+{
+    SSL_CTX *ctx;
+    SSL *con = NULL;
+    BIO *rbio;
+    BIO *wbio;
+    char *hostname = NULL;
+    int ret = 0;
+
+    /* use TLS_method to blur 'side' */
+    ctx = SSL_CTX_new(TLS_method());
+    if (!TEST_ptr(ctx))
+        goto end;
+
+    con = SSL_new(ctx);
+    if (!TEST_ptr(con))
+        goto end;
+
+    rbio = BIO_new(BIO_s_mem());
+    wbio = BIO_new(BIO_s_mem());
+    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
+        BIO_free(rbio);
+        BIO_free(wbio);
+        goto end;
+    }
+
+    SSL_set_bio(con, rbio, wbio);
+    SSL_set_connect_state(con);
+
+    /* set SNI after 'client side' is set */
+    SSL_set_tlsext_host_name(con, host);
+
+    if (!TEST_int_le(SSL_connect(con), 0))
+        /* This shouldn't succeed because we don't have a server! */
+        goto end;
+    if (!TEST_true(get_sni_from_client_hello(wbio, &hostname)))
+        /* no SNI in client hello */
+        goto end;
+    if (!TEST_str_eq(hostname, host))
+        /* incorrect SNI value */
+        goto end;
+    ret = 1;
+end:
+    OPENSSL_free(hostname);
+    SSL_free(con);
+    SSL_CTX_free(ctx);
+    return ret;
+}
+
+static int server_setup_sni()
+{
+    SSL_CTX *ctx;
+    SSL *con = NULL;
+    BIO *rbio;
+    BIO *wbio;
+    int ret = 0;
+
+    /* use TLS_server_method to choose 'server-side' */
+    ctx = SSL_CTX_new(TLS_server_method());
+    if (!TEST_ptr(ctx))
+        goto end;
+
+    con = SSL_new(ctx);
+    if (!TEST_ptr(con))
+        goto end;
+
+    rbio = BIO_new(BIO_s_mem());
+    wbio = BIO_new(BIO_s_mem());
+    if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
+        BIO_free(rbio);
+        BIO_free(wbio);
+        goto end;
+    }
+
+    SSL_set_bio(con, rbio, wbio);
+
+    /* set SNI at server side */
+    SSL_set_tlsext_host_name(con, host);
+
+    if (!TEST_int_le(SSL_accept(con), 0))
+        /* This shouldn't succeed because we have nothing to listen on */
+        goto end;
+    if (!TEST_ptr_null(SSL_get_servername(con, TLSEXT_NAMETYPE_host_name)))
+        /* SNI should be cleared by SSL_accpet */
+        goto end;
+    ret = 1;
+end:
+    SSL_free(con);
+    SSL_CTX_free(ctx);
+    return ret;
+}
+
+typedef int (*sni_test_fn)(void);
+
+static sni_test_fn sni_test_fns[3] = {
+    client_setup_sni_before_state,
+    client_setup_sni_after_state,
+    server_setup_sni
+};
+
+static int test_servername(int test)
+{
+    /*
+     * For each test set up an SSL_CTX and SSL and see
+     * what SNI behaves.
+     */
+    return sni_test_fns[test]();
+}
+
+int setup_tests(void)
+{
+    ADD_ALL_TESTS(test_servername, OSSL_NELEM(sni_test_fns));
+    return 1;
+}
diff --git a/util/private.num b/util/private.num
index ff45e56..f82a8f6 100644
--- a/util/private.num
+++ b/util/private.num
@@ -339,6 +339,7 @@ SSL_set_mtu                             define
 SSL_set_split_send_fragment             define
 SSL_set_time                            define
 SSL_set_timeout                         define
+SSL_set_tlsext_host_name                define
 SSL_set_tlsext_status_ocsp_resp         define
 SSL_set_tlsext_status_type              define
 SSL_set_tmp_dh                          define


More information about the openssl-commits mailing list