소스 검색

Fix some bugs

yhirose 2 주 전
부모
커밋
bff54389c4
2개의 변경된 파일104개의 추가작업 그리고 100개의 파일을 삭제
  1. 14 89
      httplib.h
  2. 90 11
      test/test.cc

+ 14 - 89
httplib.h

@@ -1924,8 +1924,12 @@ protected:
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 public:
+  [[deprecated("Use load_ca_cert_store() instead")]]
   void set_ca_cert_store(X509_STORE *ca_cert_store);
+
+  [[deprecated("Use detail::tls::tls_create_ca_store() instead")]]
   X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
+
   void set_server_certificate_verifier(
       std::function<SSLVerifierResponse(SSL *ssl)> verifier);
 
@@ -2154,6 +2158,7 @@ private:
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 public:
+  [[deprecated("Use tls_context() instead")]]
   SSL_CTX *ssl_context() const;
 
   void set_server_certificate_verifier(
@@ -2161,11 +2166,6 @@ public:
 
   long get_openssl_verify_result() const;
 #endif
-
-#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
-public:
-  mbedtls_ssl_config *ssl_config() const;
-#endif
 };
 
 #ifdef CPPHTTPLIB_SSL_ENABLED
@@ -2219,27 +2219,21 @@ private:
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 public:
+  [[deprecated("Use SSLServer(PemMemory) or "
+               "SSLServer(std::function<bool(void*)>) instead")]]
   SSLServer(X509 *cert, EVP_PKEY *private_key,
             X509_STORE *client_ca_cert_store = nullptr);
 
+  [[deprecated("Use SSLServer(std::function<bool(void*)>) instead")]]
   SSLServer(
       const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback);
 
+  [[deprecated("Use tls_context() instead")]]
   SSL_CTX *ssl_context() const;
 
+  [[deprecated("Use update_certs_pem() instead")]]
   void update_certs(X509 *cert, EVP_PKEY *private_key,
                     X509_STORE *client_ca_cert_store = nullptr);
-
-private:
-  STACK_OF(X509_NAME) * extract_ca_names_from_x509_store(X509_STORE *store);
-#endif
-
-#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
-public:
-  SSLServer(
-      const std::function<bool(mbedtls_ssl_config &conf)> &setup_callback);
-
-  mbedtls_ssl_config *ssl_config() const;
 #endif
 };
 
@@ -2315,12 +2309,14 @@ private:
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 public:
+  [[deprecated("Use SSLClient(host, port, PemMemory) instead")]]
   explicit SSLClient(const std::string &host, int port, X509 *client_cert,
                      EVP_PKEY *client_key,
                      const std::string &private_key_password = std::string());
 
   long get_openssl_verify_result() const;
 
+  [[deprecated("Use tls_context() instead")]]
   SSL_CTX *ssl_context() const;
 
 private:
@@ -2328,11 +2324,6 @@ private:
   bool verify_host_with_subject_alt_name(X509 *server_cert) const;
   bool verify_host_with_common_name(X509 *server_cert) const;
 #endif
-
-#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
-public:
-  mbedtls_ssl_config *ssl_config() const;
-#endif
 };
 #endif // CPPHTTPLIB_SSL_ENABLED
 
@@ -10377,6 +10368,8 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) {
   if (error == Error::SSLPeerCouldBeClosed_) {
     assert(!ret);
     ret = send_(req, res, error);
+    // If still failing with SSLPeerCouldBeClosed_, convert to Read error
+    if (error == Error::SSLPeerCouldBeClosed_) { error = Error::Read; }
   }
   return ret;
 }
@@ -13877,44 +13870,6 @@ inline void SSLServer::update_certs(X509 *cert, EVP_PKEY *private_key,
                                              client_ca_cert_store);
 }
 
-inline STACK_OF(X509_NAME) * SSLServer::extract_ca_names_from_x509_store(
-                                 X509_STORE *store) {
-  if (!store) { return nullptr; }
-
-  auto ca_list = sk_X509_NAME_new_null();
-  if (!ca_list) { return nullptr; }
-
-  // Get all objects from the store
-  auto objs = X509_STORE_get0_objects(store);
-  if (!objs) {
-    sk_X509_NAME_free(ca_list);
-    return nullptr;
-  }
-
-  // Iterate through objects and extract certificate subject names
-  for (int i = 0; i < sk_X509_OBJECT_num(objs); i++) {
-    auto obj = sk_X509_OBJECT_value(objs, i);
-    if (X509_OBJECT_get_type(obj) == X509_LU_X509) {
-      auto cert = X509_OBJECT_get0_X509(obj);
-      if (cert) {
-        auto subject = X509_get_subject_name(cert);
-        if (subject) {
-          auto name_dup = X509_NAME_dup(subject);
-          if (name_dup) { sk_X509_NAME_push(ca_list, name_dup); }
-        }
-      }
-    }
-  }
-
-  // If no names were extracted, free the list and return nullptr
-  if (sk_X509_NAME_num(ca_list) == 0) {
-    sk_X509_NAME_free(ca_list);
-    return nullptr;
-  }
-
-  return ca_list;
-}
-
 // SSL HTTP client implementation
 inline SSLClient::SSLClient(const std::string &host)
     : SSLClient(host, 443, std::string(), std::string()) {}
@@ -15930,29 +15885,6 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
   return true;
 }
 
-inline mbedtls_ssl_config *SSLServer::ssl_config() const {
-  auto ctx = static_cast<detail::tls::MbedTlsContext *>(ctx_);
-  return ctx ? &ctx->conf : nullptr;
-}
-
-inline SSLServer::SSLServer(
-    const std::function<bool(mbedtls_ssl_config &conf)> &setup_callback) {
-  using namespace detail::tls;
-  ctx_ = tls_create_server_context();
-  if (ctx_) {
-    auto mbedtls_ctx = static_cast<MbedTlsContext *>(ctx_);
-    if (!setup_callback(mbedtls_ctx->conf)) {
-      tls_free_context(ctx_);
-      ctx_ = nullptr;
-    }
-  }
-}
-
-inline mbedtls_ssl_config *SSLClient::ssl_config() const {
-  auto ctx = static_cast<detail::tls::MbedTlsContext *>(ctx_);
-  return ctx ? &ctx->conf : nullptr;
-}
-
 #endif // CPPHTTPLIB_MBEDTLS_SUPPORT
 
 /*
@@ -17184,13 +17116,6 @@ inline long Client::get_openssl_verify_result() const {
 }
 #endif // CPPHTTPLIB_OPENSSL_SUPPORT
 
-#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
-inline mbedtls_ssl_config *Client::ssl_config() const {
-  if (is_ssl_) { return static_cast<SSLClient &>(*cli_).ssl_config(); }
-  return nullptr;
-}
-#endif // CPPHTTPLIB_MBEDTLS_SUPPORT
-
 // ----------------------------------------------------------------------------
 
 } // namespace httplib

+ 90 - 11
test/test.cc

@@ -2606,6 +2606,84 @@ TEST(BindServerTest, UpdateCerts) {
   X509_free(ca_cert);
   EVP_PKEY_free(key);
 }
+
+// Test that SSLServer(X509*, EVP_PKEY*, X509_STORE*) constructor sets
+// client CA list correctly for TLS handshake
+TEST(SSLClientServerTest, X509ConstructorSetsClientCAList) {
+  X509 *cert = readCertificate(SERVER_CERT_FILE);
+  X509 *ca_cert = readCertificate(CLIENT_CA_CERT_FILE);
+  EVP_PKEY *key = readPrivateKey(SERVER_PRIVATE_KEY_FILE);
+
+  ASSERT_TRUE(cert != nullptr);
+  ASSERT_TRUE(ca_cert != nullptr);
+  ASSERT_TRUE(key != nullptr);
+
+  X509_STORE *cert_store = X509_STORE_new();
+  X509_STORE_add_cert(cert_store, ca_cert);
+
+  // Use X509-based constructor (deprecated but should still work correctly)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+  SSLServer svr(cert, key, cert_store);
+#pragma GCC diagnostic pop
+
+  ASSERT_TRUE(svr.is_valid());
+
+  // Verify that client CA list is set in SSL_CTX
+  auto ssl_ctx = static_cast<SSL_CTX *>(svr.tls_context());
+  ASSERT_TRUE(ssl_ctx != nullptr);
+
+  STACK_OF(X509_NAME) *ca_list = SSL_CTX_get_client_CA_list(ssl_ctx);
+  ASSERT_TRUE(ca_list != nullptr);
+  EXPECT_GT(sk_X509_NAME_num(ca_list), 0);
+
+  X509_free(cert);
+  X509_free(ca_cert);
+  EVP_PKEY_free(key);
+}
+
+// Test that update_certs() updates client CA list correctly
+TEST(SSLClientServerTest, UpdateCertsSetsClientCAList) {
+  // Start with file-based constructor
+  SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
+  ASSERT_TRUE(svr.is_valid());
+
+  // Initially no client CA list should be set
+  auto ssl_ctx = static_cast<SSL_CTX *>(svr.tls_context());
+  ASSERT_TRUE(ssl_ctx != nullptr);
+
+  STACK_OF(X509_NAME) *ca_list_before = SSL_CTX_get_client_CA_list(ssl_ctx);
+  int count_before = ca_list_before ? sk_X509_NAME_num(ca_list_before) : 0;
+  EXPECT_EQ(0, count_before);
+
+  // Now update with client CA
+  X509 *cert = readCertificate(SERVER_CERT_FILE);
+  X509 *ca_cert = readCertificate(CLIENT_CA_CERT_FILE);
+  EVP_PKEY *key = readPrivateKey(SERVER_PRIVATE_KEY_FILE);
+
+  ASSERT_TRUE(cert != nullptr);
+  ASSERT_TRUE(ca_cert != nullptr);
+  ASSERT_TRUE(key != nullptr);
+
+  X509_STORE *cert_store = X509_STORE_new();
+  X509_STORE_add_cert(cert_store, ca_cert);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+  svr.update_certs(cert, key, cert_store);
+#pragma GCC diagnostic pop
+
+  ASSERT_TRUE(svr.is_valid());
+
+  // Now client CA list should be set
+  STACK_OF(X509_NAME) *ca_list_after = SSL_CTX_get_client_CA_list(ssl_ctx);
+  ASSERT_TRUE(ca_list_after != nullptr);
+  EXPECT_GT(sk_X509_NAME_num(ca_list_after), 0);
+
+  X509_free(cert);
+  X509_free(ca_cert);
+  EVP_PKEY_free(key);
+}
 #endif
 
 TEST(ErrorHandlerTest, ContentLength) {
@@ -9154,7 +9232,7 @@ TEST(SSLClientServerTest, CustomizeServerSSLCtxGeneric) {
 #endif
 
 // mbedTLS-specific callback constructor test
-// Tests that the mbedtls_ssl_config& callback can customize TLS settings
+// Tests that the void* callback can customize TLS settings via MbedTlsContext
 #ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
 TEST(SSLClientServerTest, CustomizeServerSSLCtxMbedTLS) {
   using namespace httplib::detail::tls;
@@ -9162,13 +9240,14 @@ TEST(SSLClientServerTest, CustomizeServerSSLCtxMbedTLS) {
   // Track if callback was invoked
   bool callback_invoked = false;
 
-  auto setup_callback = [&callback_invoked](mbedtls_ssl_config &conf) {
+  // The callback receives void* ctx which is actually MbedTlsContext*
+  // We can access the mbedtls_ssl_config via the context
+  auto setup_callback = [&callback_invoked](void *ctx) {
     callback_invoked = true;
 
-    // Load server certificate and key
-    // Note: The MbedTlsContext is accessed via the conf's parent
-    // For this test, we use tls_create_server_context() to set up certs
-    // and then configure the passed-in conf
+    // Cast to MbedTlsContext* to access the ssl config
+    auto *mbedtls_ctx = static_cast<MbedTlsContext *>(ctx);
+    mbedtls_ssl_config *conf = &mbedtls_ctx->conf;
 
     // Use static variables to hold certificate data (simplified for test)
     static mbedtls_x509_crt own_cert;
@@ -9202,15 +9281,15 @@ TEST(SSLClientServerTest, CustomizeServerSSLCtxMbedTLS) {
     }
 
     // Configure the SSL config
-    mbedtls_ssl_conf_own_cert(&conf, &own_cert, &own_key);
-    mbedtls_ssl_conf_ca_chain(&conf, &ca_chain, nullptr);
-    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+    mbedtls_ssl_conf_own_cert(conf, &own_cert, &own_key);
+    mbedtls_ssl_conf_ca_chain(conf, &ca_chain, nullptr);
+    mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
 
     // Set minimum TLS version using mbedTLS native API
 #if MBEDTLS_VERSION_MAJOR >= 3
-    mbedtls_ssl_conf_min_tls_version(&conf, MBEDTLS_SSL_VERSION_TLS1_2);
+    mbedtls_ssl_conf_min_tls_version(conf, MBEDTLS_SSL_VERSION_TLS1_2);
 #else
-    mbedtls_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3,
+    mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3,
                                  MBEDTLS_SSL_MINOR_VERSION_3);
 #endif