@@ -1464,6 +1464,59 @@ TEST(SSLTest, test_SSL_get_servername_inside_select_certificate_cb) {
14641464}
14651465
14661466
1467+ /* *
1468+ * @brief This test exercises a leak in SSL_get_servername()
1469+ *
1470+ * If SSL_get_servername() was invoked multiple times from the same certificate
1471+ * selection callback, it was leaking the string value that was returned from
1472+ * the previous invocation(s).
1473+ *
1474+ * Note that the string returned by the _last_ SSL_get_servername() invocation,
1475+ * inside a certificate selection callback, does _not_ leak i.e. if
1476+ * SSL_get_servername() is only called once during a callback, there is no leak.
1477+ * It only leaks when SSL_get_servername() is called more than once during the
1478+ * same callback.
1479+ */
1480+ TEST (SSLTest, test_SSL_get_servername_leak_inside_select_certificate_cb) {
1481+ static const char SERVERNAME[] { " www.example.com" };
1482+
1483+ TempFile server_2_key_pem { server_2_key_pem_str };
1484+ TempFile server_2_cert_chain_pem { server_2_cert_chain_pem_str };
1485+
1486+ int sockets[2 ];
1487+ ASSERT_EQ (0 , socketpair (AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0 , sockets));
1488+ SocketCloser close[] { sockets[0 ], sockets[1 ] };
1489+
1490+ bssl::UniquePtr<SSL_CTX> server_ctx (SSL_CTX_new (TLS_server_method ()));
1491+ bssl::UniquePtr<SSL_CTX> client_ctx (SSL_CTX_new (TLS_client_method ()));
1492+
1493+ // Set up a certificate selection callback which calls SSL_get_servername() 5 times.
1494+ // This will result in 4 leaks if the SSL_get_servername() fix is not in place.
1495+ SSL_CTX_set_select_certificate_cb (server_ctx.get (), [](const SSL_CLIENT_HELLO *client_hello) -> ssl_select_cert_result_t {
1496+ SSL_get_servername (client_hello->ssl , TLSEXT_NAMETYPE_host_name);
1497+ SSL_get_servername (client_hello->ssl , TLSEXT_NAMETYPE_host_name);
1498+ SSL_get_servername (client_hello->ssl , TLSEXT_NAMETYPE_host_name);
1499+ SSL_get_servername (client_hello->ssl , TLSEXT_NAMETYPE_host_name);
1500+ SSL_get_servername (client_hello->ssl , TLSEXT_NAMETYPE_host_name);
1501+ return ssl_select_cert_success;
1502+ });
1503+ ASSERT_TRUE (SSL_CTX_use_certificate_chain_file (server_ctx.get (), server_2_cert_chain_pem.path ()));
1504+ ASSERT_TRUE (SSL_CTX_use_PrivateKey_file (server_ctx.get (), server_2_key_pem.path (), SSL_FILETYPE_PEM));
1505+ bssl::UniquePtr<SSL> server_ssl (SSL_new (server_ctx.get ()));
1506+ ASSERT_TRUE (SSL_set_fd (server_ssl.get (), sockets[0 ]));
1507+ SSL_set_accept_state (server_ssl.get ());
1508+
1509+ // Set up client
1510+ SSL_CTX_set_verify (client_ctx.get (), SSL_VERIFY_NONE, nullptr );
1511+ bssl::UniquePtr<SSL> client_ssl (SSL_new (client_ctx.get ()));
1512+ ASSERT_TRUE (SSL_set_fd (client_ssl.get (), sockets[1 ]));
1513+ ASSERT_TRUE (SSL_set_tlsext_host_name (client_ssl.get (), SERVERNAME));
1514+ SSL_set_connect_state (client_ssl.get ());
1515+
1516+ ASSERT_TRUE (CompleteHandshakes (client_ssl.get (), server_ssl.get ()));
1517+ }
1518+
1519+
14671520TEST (SSLTest, test_SSL_get_servername_null_inside_select_certificate_cb) {
14681521 TempFile server_2_key_pem { server_2_key_pem_str };
14691522 TempFile server_2_cert_chain_pem { server_2_cert_chain_pem_str };
0 commit comments