Compare commits

..

8 Commits

Author SHA1 Message Date
yhirose d3076f5a70 v0.12.6 2023-06-10 07:02:38 +09:00
yhirose ed129f057f Fixed C++11 warnings and code format 2023-06-09 20:49:46 +09:00
Jiwoo Park eab5ea01d7 Load in-memory CA certificates (#1579)
* Load in-memory CA certs

* Add test cases for in-memory cert loading

* Don't use the IIFE style
2023-06-09 16:34:51 +09:00
Petr Hosek 3e287b3a26 Provide a CMake option to disable C++ exceptions (#1580)
This allows disabling the use of C++ exceptions at CMake configure time.
The value is encoded in the generated httplibTargets.cmake file and will
be used by CMake projects that import it.
2023-06-06 16:56:26 +09:00
v1gnesh 4f33637b43 Add support for zOS (#1581)
Signed-off-by: v1gnesh <v1gnesh@users.noreply.github.com>
2023-06-06 14:14:06 +09:00
db-src 698a1e51ec Move, not copy, Logger and Handler functors (#1576)
* Explicitly #include <utility> for use of std::move

* Move not copy Logger arg from Client to ClientImpl

* Move not copy, set_error_handler Handler to lambda

* Remove null statement in non-empty if/else block

I guess it was a relic from a time before the other statement was added.

---------

Co-authored-by: Daniel Boles <daniel.boles@voltalis.com>
2023-06-02 15:40:00 +09:00
yhirose 27c0e1186c Release v12.0.5 2023-05-30 16:09:42 +09:00
Niccolò Iardella c54c71a3e5 Add HTTPLIB_INSTALL CMake option (#1575)
* Add HTTPLIB_INSTALL CMake option

* Proper formatting of HTTPLIB_INSTALL block

Co-authored-by: Jiwoo Park <jiwoo_90@naver.com>

---------

Co-authored-by: Niccolò Iardella <niccolo.iardella@doriansrl.it>
Co-authored-by: Jiwoo Park <jiwoo_90@naver.com>
2023-05-30 16:08:58 +09:00
3 changed files with 122 additions and 27 deletions
+27 -17
View File
@@ -9,6 +9,7 @@
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
* HTTPLIB_REQUIRE_BROTLI (default off)
* HTTPLIB_COMPILE (default off)
* HTTPLIB_INSTALL (default on)
* HTTPLIB_TEST (default off)
* BROTLI_USE_STATIC_LIBS - tells Cmake to use the static Brotli libs (only works if you have them installed).
* OPENSSL_USE_STATIC_LIBS - tells Cmake to use the static OpenSSL libs (only works if you have them installed).
@@ -74,6 +75,10 @@ string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")
project(httplib VERSION ${_httplib_version} LANGUAGES CXX)
# Lets you disable C++ exception during CMake configure time.
# The value is used in the install CMake config file.
option(HTTPLIB_NO_EXCEPTIONS "Disable the use of C++ exceptions" OFF)
# Change as needed to set an OpenSSL minimum version.
# This is used in the installed Cmake config file.
set(_HTTPLIB_OPENSSL_MIN_VER "1.1.1")
@@ -87,6 +92,8 @@ option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable H
option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable Zlib compression support." ON)
# Lets you compile the program as a regular library instead of header-only
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
# Lets you disable the installation (useful when fetched from another CMake project)
option(HTTPLIB_INSTALL "Enables the installation target" ON)
# Just setting this variable here for people building in-tree
if(HTTPLIB_COMPILE)
set(HTTPLIB_IS_COMPILED TRUE)
@@ -226,6 +233,7 @@ target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
# Set the definitions to enable optional features
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
$<$<BOOL:${HTTPLIB_NO_EXCEPTIONS}>:CPPHTTPLIB_NO_EXCEPTIONS>
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
@@ -262,31 +270,33 @@ else()
)
endif()
# Creates the export httplibTargets.cmake
# This is strictly what holds compilation requirements
# and linkage information (doesn't find deps though).
install(TARGETS ${PROJECT_NAME}
EXPORT httplibTargets
)
if(HTTPLIB_INSTALL)
# Creates the export httplibTargets.cmake
# This is strictly what holds compilation requirements
# and linkage information (doesn't find deps though).
install(TARGETS ${PROJECT_NAME}
EXPORT httplibTargets
)
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)
install(FILES
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
# Install it so it can be used later by the httplibConfig.cmake file.
# Put it in the same dir as our config file instead of a global path so we don't potentially stomp on other packages.
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBrotli.cmake"
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)
# NOTE: This path changes depending on if it's on Windows or Linux
install(EXPORT httplibTargets
# Puts the targets into the httplib namespace
# So this makes httplib::httplib linkable after doing find_package(httplib)
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)
# NOTE: This path changes depending on if it's on Windows or Linux
install(EXPORT httplibTargets
# Puts the targets into the httplib namespace
# So this makes httplib::httplib linkable after doing find_package(httplib)
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)
endif()
if(HTTPLIB_TEST)
include(CTest)
+52 -10
View File
@@ -8,7 +8,7 @@
#ifndef CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_HTTPLIB_H
#define CPPHTTPLIB_VERSION "0.12.4"
#define CPPHTTPLIB_VERSION "0.12.6"
/*
* Configuration
@@ -172,9 +172,15 @@ using socket_t = SOCKET;
#else // not _WIN32
#include <arpa/inet.h>
#ifndef _AIX
#if !defined(_AIX) && !defined(__MVS__)
#include <ifaddrs.h>
#endif
#ifdef __MVS__
#include <strings.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#endif
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
@@ -223,6 +229,7 @@ using socket_t = int;
#include <string>
#include <sys/stat.h>
#include <thread>
#include <utility>
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
#ifdef _WIN32
@@ -1117,6 +1124,7 @@ public:
void set_ca_cert_path(const std::string &ca_cert_file_path,
const std::string &ca_cert_dir_path = std::string());
void set_ca_cert_store(X509_STORE *ca_cert_store);
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size);
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
@@ -1497,6 +1505,7 @@ public:
const std::string &ca_cert_dir_path = std::string());
void set_ca_cert_store(X509_STORE *ca_cert_store);
void load_ca_cert_store(const char *ca_cert, std::size_t size);
long get_openssl_verify_result() const;
@@ -1556,6 +1565,7 @@ public:
bool is_valid() const override;
void set_ca_cert_store(X509_STORE *ca_cert_store);
void load_ca_cert_store(const char *ca_cert, std::size_t size);
long get_openssl_verify_result() const;
@@ -2804,7 +2814,7 @@ inline bool bind_ip_address(socket_t sock, const std::string &host) {
return ret;
}
#if !defined _WIN32 && !defined ANDROID && !defined _AIX
#if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__
#define USE_IF2IP
#endif
@@ -5272,7 +5282,6 @@ inline Server &Server::set_logger(Logger logger) {
inline Server &
Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) {
expect_100_continue_handler_ = std::move(handler);
return *this;
}
@@ -6801,7 +6810,6 @@ inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
req.set_header("Transfer-Encoding", "chunked");
} else {
req.body.assign(body, content_length);
;
}
}
@@ -7571,9 +7579,7 @@ inline void ClientImpl::set_proxy_digest_auth(const std::string &username,
proxy_digest_auth_username_ = username;
proxy_digest_auth_password_ = password;
}
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path,
const std::string &ca_cert_dir_path) {
ca_cert_file_path_ = ca_cert_file_path;
@@ -7585,9 +7591,34 @@ inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
ca_cert_store_ = ca_cert_store;
}
}
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
inline X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert,
std::size_t size) {
auto mem = BIO_new_mem_buf(ca_cert, static_cast<int>(size));
if (!mem) return nullptr;
auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr);
if (!inf) {
BIO_free_all(mem);
return nullptr;
}
auto cts = X509_STORE_new();
if (cts) {
for (auto first = 0, last = sk_X509_INFO_num(inf); first < last; ++first) {
auto itmp = sk_X509_INFO_value(inf, first);
if (!itmp) { continue; }
if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); }
if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); }
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free);
BIO_free_all(mem);
return cts;
}
inline void ClientImpl::enable_server_certificate_verification(bool enabled) {
server_certificate_verification_ = enabled;
}
@@ -7985,6 +8016,11 @@ inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
}
}
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
std::size_t size) {
set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size));
}
inline long SSLClient::get_openssl_verify_result() const {
return verify_result_;
}
@@ -8750,7 +8786,9 @@ inline void Client::enable_server_certificate_verification(bool enabled) {
}
#endif
inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); }
inline void Client::set_logger(Logger logger) {
cli_->set_logger(std::move(logger));
}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path,
@@ -8766,6 +8804,10 @@ inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) {
}
}
inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) {
set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size));
}
inline long Client::get_openssl_verify_result() const {
if (is_ssl_) {
return static_cast<SSLClient &>(*cli_).get_openssl_verify_result();
+43
View File
@@ -4710,6 +4710,49 @@ TEST(SSLClientTest, ServerCertificateVerification4) {
ASSERT_EQ(200, res->status);
}
TEST(SSLClientTest, ServerCertificateVerification5_Online) {
std::string cert;
detail::read_file(CA_CERT_FILE, cert);
SSLClient cli("google.com");
cli.load_ca_cert_store(cert.data(), cert.size());
const auto res = cli.Get("/");
ASSERT_TRUE(res);
ASSERT_EQ(301, res->status);
}
TEST(SSLClientTest, ServerCertificateVerification6_Online) {
// clang-format off
static constexpr char cert[] =
"GlobalSign Root CA\n"
"==================\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx\n"
"GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds\n"
"b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV\n"
"BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD\n"
"VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa\n"
"DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc\n"
"THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb\n"
"Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP\n"
"c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX\n"
"gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
"HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF\n"
"AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj\n"
"Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG\n"
"j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH\n"
"hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC\n"
"X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n"
"-----END CERTIFICATE-----\n";
// clang-format on
SSLClient cli("google.com");
cli.load_ca_cert_store(cert, sizeof(cert));
const auto res = cli.Get("/");
ASSERT_TRUE(res);
ASSERT_EQ(301, res->status);
}
TEST(SSLClientTest, WildcardHostNameMatch_Online) {
SSLClient cli("www.youtube.com");