mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-01-19 04:52:08 +00:00
Enhance Windows certificate verification with additional tests and timeout handling
This commit is contained in:
12
httplib.h
12
httplib.h
@@ -7278,12 +7278,14 @@ inline bool verify_cert_with_windows_schannel(X509 *server_cert,
|
||||
// Setup chain parameters
|
||||
CERT_CHAIN_PARA chain_para = {};
|
||||
chain_para.cbSize = sizeof(chain_para);
|
||||
#if defined(_WIN32) && _WIN32_WINNT >= 0x0600
|
||||
// dwUrlRetrievalTimeout is available on Windows Vista and later
|
||||
chain_para.dwUrlRetrievalTimeout = static_cast<DWORD>(timeout_sec * 1000);
|
||||
#else
|
||||
|
||||
// Note: dwUrlRetrievalTimeout is not available in all Windows SDK versions.
|
||||
// In newer SDKs (10.0.26100+), this field doesn't exist in CERT_CHAIN_PARA.
|
||||
// We cannot reliably set the timeout across all SDK versions, so we rely on
|
||||
// the Windows API default timeout (typically 10-15 seconds for CAPI
|
||||
// operations). The timeout_sec parameter is kept for API compatibility and
|
||||
// future use.
|
||||
(void)timeout_sec;
|
||||
#endif
|
||||
|
||||
// Build certificate chain with revocation checking
|
||||
PCCERT_CHAIN_CONTEXT chain_context = nullptr;
|
||||
|
||||
142
test/test.cc
142
test/test.cc
@@ -142,6 +142,77 @@ void performance_test(const char *host) {
|
||||
<< "ms (Issue #1777). Timings: " << timings_str.str();
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
#ifdef _WIN32
|
||||
// Windows Certificate Verification Tests
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_DefaultEnabled) {
|
||||
// Test 1: Default behavior (Windows verification enabled)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should succeed or fail gracefully (may fail due to network)
|
||||
// The important thing is that Windows verification was enabled
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_DisableWindows) {
|
||||
// Test 2: Disable Windows verification (OpenSSL only)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
cli.enable_windows_certificate_verification(false);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should work with OpenSSL verification only
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_CustomTimeout) {
|
||||
// Test 3: Custom timeout
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
cli.set_windows_certificate_verification_timeout(2);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should complete within reasonable time
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_InvalidCertificate) {
|
||||
// Test 4: Invalid certificate (should fail)
|
||||
SSLClient cli("self-signed.badssl.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should fail due to invalid certificate
|
||||
EXPECT_FALSE(res);
|
||||
EXPECT_EQ(Error::SSLServerVerification, res.error());
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_CachingBehavior) {
|
||||
// Test 5: Multiple connections (test caching)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
// First connection
|
||||
auto res1 = cli.Get("/");
|
||||
auto start2 = std::chrono::high_resolution_clock::now();
|
||||
// Second connection (should use cache)
|
||||
auto res2 = cli.Get("/");
|
||||
auto end2 = std::chrono::high_resolution_clock::now();
|
||||
auto duration2 =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);
|
||||
|
||||
// Second connection should be fast (cache hit)
|
||||
if (res2) {
|
||||
EXPECT_NE(StatusCode::InternalServerError_500, res2->status);
|
||||
// Cache should make second connection faster (very loose bound)
|
||||
EXPECT_LT(duration2.count(), 5000); // Within 5 seconds
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST(BenchmarkTest, localhost) { performance_test("localhost"); }
|
||||
|
||||
TEST(BenchmarkTest, v6) { performance_test("::1"); }
|
||||
@@ -14119,74 +14190,3 @@ TEST(Issue2318Test, EmptyHostString) {
|
||||
EXPECT_EQ(httplib::Error::Connection, res.error());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
#ifdef _WIN32
|
||||
// Windows Certificate Verification Tests
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_DefaultEnabled) {
|
||||
// Test 1: Default behavior (Windows verification enabled)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should succeed or fail gracefully (may fail due to network)
|
||||
// The important thing is that Windows verification was enabled
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_DisableWindows) {
|
||||
// Test 2: Disable Windows verification (OpenSSL only)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
cli.enable_windows_certificate_verification(false);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should work with OpenSSL verification only
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_CustomTimeout) {
|
||||
// Test 3: Custom timeout
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
cli.set_windows_certificate_verification_timeout(2);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should complete within reasonable time
|
||||
if (res) { EXPECT_NE(StatusCode::InternalServerError_500, res->status); }
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_InvalidCertificate) {
|
||||
// Test 4: Invalid certificate (should fail)
|
||||
SSLClient cli("self-signed.badssl.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
auto res = cli.Get("/");
|
||||
// Should fail due to invalid certificate
|
||||
EXPECT_FALSE(res);
|
||||
EXPECT_EQ(Error::SSLServerVerification, res.error());
|
||||
}
|
||||
|
||||
TEST(SSLClientTest, WindowsCertificateVerification_CachingBehavior) {
|
||||
// Test 5: Multiple connections (test caching)
|
||||
SSLClient cli("www.google.com", 443);
|
||||
cli.enable_server_certificate_verification(true);
|
||||
|
||||
// First connection
|
||||
auto res1 = cli.Get("/");
|
||||
auto start2 = std::chrono::high_resolution_clock::now();
|
||||
// Second connection (should use cache)
|
||||
auto res2 = cli.Get("/");
|
||||
auto end2 = std::chrono::high_resolution_clock::now();
|
||||
auto duration2 =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);
|
||||
|
||||
// Second connection should be fast (cache hit)
|
||||
if (res2) {
|
||||
EXPECT_NE(StatusCode::InternalServerError_500, res2->status);
|
||||
// Cache should make second connection faster (very loose bound)
|
||||
EXPECT_LT(duration2.count(), 5000); // Within 5 seconds
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user