Fix ossl_shim SNI handling
authorBenjamin Kaduk <bkaduk@akamai.com>
Wed, 25 Jul 2018 19:48:30 +0000 (14:48 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Thu, 26 Jul 2018 20:06:53 +0000 (15:06 -0500)
To start with, actually set an SNI callback (copied from bssl_shim); we
weren't actually testing much otherwise (and just happened to have been
passing due to buggy libssl behavior prior to
commit 1c4aa31d79821dee9be98e915159d52cc30d8403).

Also use proper C++ code for handling C strings -- when a C API
(SSL_get_servername()) returns NULL instead of a string, special-case
that instead of blindly trying to compare NULL against a std::string,
and perform the comparsion using the std::string operators instead of
falling back to pointer comparison.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6792)

test/ossl_shim/ossl_shim.cc

index b1067e842092c717ed504d2eecd1d4e549578a4b..90d1f1ef402706049ea865f4f1f57563c6c91f79 100644 (file)
@@ -459,6 +459,20 @@ static int CustomExtensionParseCallback(SSL *ssl, unsigned extension_value,
   return 1;
 }
 
   return 1;
 }
 
+static int ServerNameCallback(SSL *ssl, int *out_alert, void *arg) {
+  // SNI must be accessible from the SNI callback.
+  const TestConfig *config = GetTestConfig(ssl);
+  const char *server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (server_name == nullptr ||
+      std::string(server_name) != config->expected_server_name) {
+    fprintf(stderr, "servername mismatch (got %s; want %s)\n", server_name,
+            config->expected_server_name.c_str());
+    return SSL_TLSEXT_ERR_ALERT_FATAL;
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
 // Connect returns a new socket connected to localhost on |port| or -1 on
 // error.
 static int Connect(uint16_t port) {
 // Connect returns a new socket connected to localhost on |port| or -1 on
 // error.
 static int Connect(uint16_t port) {
@@ -645,6 +659,10 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(const TestConfig *config) {
                                       sizeof(sess_id_ctx) - 1))
     return nullptr;
 
                                       sizeof(sess_id_ctx) - 1))
     return nullptr;
 
+  if (!config->expected_server_name.empty()) {
+    SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(), ServerNameCallback);
+  }
+
   return ssl_ctx;
 }
 
   return ssl_ctx;
 }
 
@@ -809,7 +827,8 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
   if (!config->expected_server_name.empty()) {
     const char *server_name =
         SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
   if (!config->expected_server_name.empty()) {
     const char *server_name =
         SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-    if (server_name != config->expected_server_name) {
+    if (server_name == nullptr ||
+            std::string(server_name) != config->expected_server_name) {
       fprintf(stderr, "servername mismatch (got %s; want %s)\n",
               server_name, config->expected_server_name.c_str());
       return false;
       fprintf(stderr, "servername mismatch (got %s; want %s)\n",
               server_name, config->expected_server_name.c_str());
       return false;