You've already forked cpp-httplib
21
httplib.h
21
httplib.h
@@ -10429,6 +10429,13 @@ inline void ClientImpl::set_error_logger(ErrorLogger error_logger) {
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
namespace detail {
|
||||
|
||||
inline bool is_ip_address(const std::string &host) {
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
return inet_pton(AF_INET, host.c_str(), &addr4) == 1 ||
|
||||
inet_pton(AF_INET6, host.c_str(), &addr6) == 1;
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex,
|
||||
U SSL_connect_or_accept, V setup) {
|
||||
@@ -11087,14 +11094,18 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
||||
return true;
|
||||
},
|
||||
[&](SSL *ssl2) {
|
||||
// Set SNI only if host is not IP address
|
||||
if (!detail::is_ip_address(host_)) {
|
||||
#if defined(OPENSSL_IS_BORINGSSL)
|
||||
SSL_set_tlsext_host_name(ssl2, host_.c_str());
|
||||
SSL_set_tlsext_host_name(ssl2, host_.c_str());
|
||||
#else
|
||||
// NOTE: Direct call instead of using the OpenSSL macro to suppress
|
||||
// -Wold-style-cast warning
|
||||
SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name,
|
||||
static_cast<void *>(const_cast<char *>(host_.c_str())));
|
||||
// NOTE: Direct call instead of using the OpenSSL macro to suppress
|
||||
// -Wold-style-cast warning
|
||||
SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME,
|
||||
TLSEXT_NAMETYPE_host_name,
|
||||
static_cast<void *>(const_cast<char *>(host_.c_str())));
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
42
test/test.cc
42
test/test.cc
@@ -7366,6 +7366,48 @@ TEST(KeepAliveTest, SSLClientReconnectionPost) {
|
||||
ASSERT_TRUE(result);
|
||||
EXPECT_EQ(200, result->status);
|
||||
}
|
||||
|
||||
TEST(SNI_AutoDetectionTest, SNI_Logic) {
|
||||
{
|
||||
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
|
||||
ASSERT_TRUE(svr.is_valid());
|
||||
|
||||
svr.Get("/sni", [&](const Request &req, Response &res) {
|
||||
std::string expected;
|
||||
if (req.ssl) {
|
||||
if (const char *sni =
|
||||
SSL_get_servername(req.ssl, TLSEXT_NAMETYPE_host_name)) {
|
||||
expected = sni;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(expected, req.get_param_value("expected"));
|
||||
res.set_content("ok", "text/plain");
|
||||
});
|
||||
|
||||
auto listen_thread = std::thread([&svr] { svr.listen(HOST, PORT); });
|
||||
auto se = detail::scope_exit([&] {
|
||||
svr.stop();
|
||||
listen_thread.join();
|
||||
ASSERT_FALSE(svr.is_running());
|
||||
});
|
||||
|
||||
svr.wait_until_ready();
|
||||
|
||||
{
|
||||
SSLClient cli("localhost", PORT);
|
||||
cli.enable_server_certificate_verification(false);
|
||||
auto res = cli.Get("/sni?expected=localhost");
|
||||
ASSERT_TRUE(res);
|
||||
}
|
||||
|
||||
{
|
||||
SSLClient cli("::1", PORT);
|
||||
cli.enable_server_certificate_verification(false);
|
||||
auto res = cli.Get("/sni?expected=");
|
||||
ASSERT_TRUE(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(ClientProblemDetectionTest, ContentProvider) {
|
||||
|
Reference in New Issue
Block a user