diff --git a/httplib.h b/httplib.h index 1250e2b..3d11acc 100644 --- a/httplib.h +++ b/httplib.h @@ -1036,6 +1036,12 @@ public: void set_proxy_digest_auth(const char *username, const char *password); #endif +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + void set_ca_cert_path(const char *ca_cert_file_path, + const char *ca_cert_dir_path = nullptr); + void set_ca_cert_store(X509_STORE *ca_cert_store); +#endif + #ifdef CPPHTTPLIB_OPENSSL_SUPPORT void enable_server_certificate_verification(bool enabled); #endif @@ -1137,6 +1143,13 @@ protected: std::string proxy_digest_auth_password_; #endif +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + std::string ca_cert_file_path_; + std::string ca_cert_dir_path_; + + X509_STORE *ca_cert_store_ = nullptr; +#endif + #ifdef CPPHTTPLIB_OPENSSL_SUPPORT bool server_certificate_verification_ = true; #endif @@ -1415,9 +1428,6 @@ public: bool is_valid() const override; - void set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path = nullptr); - void set_ca_cert_store(X509_STORE *ca_cert_store); long get_openssl_verify_result() const; @@ -1450,8 +1460,6 @@ private: std::vector host_components_; - std::string ca_cert_file_path_; - std::string ca_cert_dir_path_; long verify_result_ = 0; friend class ClientImpl; @@ -5309,6 +5317,11 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) { proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_; proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_; #endif +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + ca_cert_file_path_ = rhs.ca_cert_file_path_; + ca_cert_dir_path_ = rhs.ca_cert_dir_path_; + ca_cert_store_ = rhs.ca_cert_store_; +#endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT server_certificate_verification_ = rhs.server_certificate_verification_; #endif @@ -5604,6 +5617,9 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT SSLClient cli(next_host.c_str(), next_port); cli.copy_settings(*this); + if (ca_cert_store_) { + cli.set_ca_cert_store(ca_cert_store_); + } return detail::redirect(cli, req, res, next_path, location, error); #else return false; @@ -6511,6 +6527,20 @@ inline void ClientImpl::set_proxy_digest_auth(const char *username, } #endif +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT +inline void ClientImpl::set_ca_cert_path(const char *ca_cert_file_path, + const char *ca_cert_dir_path) { + if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } + if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } +} + +inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { + if (ca_cert_store && ca_cert_store != ca_cert_store_) { + ca_cert_store_ = ca_cert_store; + } +} +#endif + #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline void ClientImpl::enable_server_certificate_verification(bool enabled) { server_certificate_verification_ = enabled; @@ -6901,12 +6931,6 @@ inline SSLClient::~SSLClient() { inline bool SSLClient::is_valid() const { return ctx_; } -inline void SSLClient::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { - if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } - if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } -} - inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { if (ca_cert_store) { if (ctx_) { @@ -7649,15 +7673,14 @@ inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT inline void Client::set_ca_cert_path(const char *ca_cert_file_path, const char *ca_cert_dir_path) { - if (is_ssl_) { - static_cast(*cli_).set_ca_cert_path(ca_cert_file_path, - ca_cert_dir_path); - } + cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path); } inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { if (is_ssl_) { static_cast(*cli_).set_ca_cert_store(ca_cert_store); + } else { + cli_->set_ca_cert_store(ca_cert_store); } } diff --git a/test/test.cc b/test/test.cc index 63fdf51..3f3296c 100644 --- a/test/test.cc +++ b/test/test.cc @@ -4456,4 +4456,38 @@ TEST(HttpsToHttpRedirectTest3, SimpleInterface) { ASSERT_TRUE(res); EXPECT_EQ(200, res->status); } + +TEST(HttpToHttpsRedirectTest, CertFile) { + Server svr; + ASSERT_TRUE(svr.is_valid()); + svr.Get("/index", [&](const Request &, Response &res) { + res.set_redirect("https://127.0.0.1:1235/index"); + svr.stop(); + }); + + SSLServer ssl_svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE); + ASSERT_TRUE(ssl_svr.is_valid()); + ssl_svr.Get("/index", [&](const Request &, Response &res) { + res.set_content("test", "text/plain"); + ssl_svr.stop(); + }); + + + thread t = thread([&]() { ASSERT_TRUE(svr.listen("127.0.0.1", PORT)); }); + thread t2 = thread([&]() { ASSERT_TRUE(ssl_svr.listen("127.0.0.1", 1235)); }); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + Client cli("127.0.0.1", PORT); + cli.set_ca_cert_path(SERVER_CERT2_FILE); + cli.enable_server_certificate_verification(true); + cli.set_follow_location(true); + cli.set_connection_timeout(30); + + auto res = cli.Get("/index"); + ASSERT_TRUE(res); + ASSERT_EQ(200, res->status); + + t.join(); + t2.join(); +} #endif