From b80aa7fee31a8712b1d3cae05c1d9e7f5c436e3d Mon Sep 17 00:00:00 2001 From: CarlosLeeGit <928540663@qq.com> Date: Fri, 15 Oct 2021 19:13:16 +0800 Subject: [PATCH] support custom ssl ctx configuration for SSLServer (#1073) --- httplib.h | 14 +++++++++++ test/test.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/httplib.h b/httplib.h index 9128dc7..b26f257 100644 --- a/httplib.h +++ b/httplib.h @@ -1364,6 +1364,9 @@ public: SSLServer(X509 *cert, EVP_PKEY *private_key, X509_STORE *client_ca_cert_store = nullptr); + SSLServer( + const std::function &setup_ssl_ctx_callback); + ~SSLServer() override; bool is_valid() const override; @@ -7105,6 +7108,17 @@ inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key, } } +inline SSLServer::SSLServer( + const std::function &setup_ssl_ctx_callback) { + ctx_ = SSL_CTX_new(TLS_method()); + if (ctx_) { + if (!setup_ssl_ctx_callback(*ctx_)) { + SSL_CTX_free(ctx_); + ctx_ = nullptr; + } + } +} + inline SSLServer::~SSLServer() { if (ctx_) { SSL_CTX_free(ctx_); } } diff --git a/test/test.cc b/test/test.cc index fcbf6a1..2c45773 100644 --- a/test/test.cc +++ b/test/test.cc @@ -4392,6 +4392,75 @@ TEST(SSLClientServerTest, SSLConnectTimeout) { svr.stop(); t.join(); } + +TEST(SSLClientServerTest, CustomizeServerSSLCtx) { + auto setup_ssl_ctx_callback = [](SSL_CTX &ssl_ctx) { + SSL_CTX_set_options(&ssl_ctx, SSL_OP_NO_COMPRESSION); + SSL_CTX_set_options(&ssl_ctx, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); + SSL_CTX_set_options(&ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(&ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(&ssl_ctx, SSL_OP_NO_TLSv1); + SSL_CTX_set_options(&ssl_ctx, SSL_OP_NO_TLSv1_1); + auto ciphers = "ECDHE-RSA-AES128-SHA256:" + "ECDHE-DSS-AES128-SHA256:" + "ECDHE-RSA-AES256-SHA256:" + "ECDHE-DSS-AES256-SHA256:"; + SSL_CTX_set_cipher_list(&ssl_ctx, ciphers); + if (SSL_CTX_use_certificate_chain_file(&ssl_ctx, SERVER_CERT_FILE) != 1 || + SSL_CTX_use_PrivateKey_file(&ssl_ctx, SERVER_PRIVATE_KEY_FILE, + SSL_FILETYPE_PEM) != 1) { + return false; + } + SSL_CTX_load_verify_locations(&ssl_ctx, CLIENT_CA_CERT_FILE, + CLIENT_CA_CERT_DIR); + SSL_CTX_set_verify( + &ssl_ctx, + SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE, + nullptr); + return true; + }; + SSLServer svr(setup_ssl_ctx_callback); + ASSERT_TRUE(svr.is_valid()); + + svr.Get("/test", [&](const Request &req, Response &res) { + res.set_content("test", "text/plain"); + svr.stop(); + ASSERT_TRUE(true); + + auto peer_cert = SSL_get_peer_certificate(req.ssl); + ASSERT_TRUE(peer_cert != nullptr); + + auto subject_name = X509_get_subject_name(peer_cert); + ASSERT_TRUE(subject_name != nullptr); + + std::string common_name; + { + char name[BUFSIZ]; + auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName, + name, sizeof(name)); + common_name.assign(name, static_cast(name_len)); + } + + EXPECT_EQ("Common Name", common_name); + + X509_free(peer_cert); + }); + + thread t = thread([&]() { ASSERT_TRUE(svr.listen(HOST, PORT)); }); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + SSLClient cli(HOST, PORT, CLIENT_CERT_FILE, CLIENT_PRIVATE_KEY_FILE); + cli.enable_server_certificate_verification(false); + cli.set_connection_timeout(30); + + auto res = cli.Get("/test"); + ASSERT_TRUE(res); + ASSERT_EQ(200, res->status); + + t.join(); +} #endif #ifdef _WIN32