mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2025-11-04 09:32:00 +00:00
vendor : update cpp-httplib to 0.27.0 (#16846)
Signed-off-by: Adrien Gallouët <angt@huggingface.co>
This commit is contained in:
264
vendor/cpp-httplib/httplib.h
vendored
264
vendor/cpp-httplib/httplib.h
vendored
@@ -8,8 +8,8 @@
|
|||||||
#ifndef CPPHTTPLIB_HTTPLIB_H
|
#ifndef CPPHTTPLIB_HTTPLIB_H
|
||||||
#define CPPHTTPLIB_HTTPLIB_H
|
#define CPPHTTPLIB_HTTPLIB_H
|
||||||
|
|
||||||
#define CPPHTTPLIB_VERSION "0.26.0"
|
#define CPPHTTPLIB_VERSION "0.27.0"
|
||||||
#define CPPHTTPLIB_VERSION_NUM "0x001A00"
|
#define CPPHTTPLIB_VERSION_NUM "0x001B00"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform compatibility check
|
* Platform compatibility check
|
||||||
@@ -1052,6 +1052,9 @@ private:
|
|||||||
|
|
||||||
ssize_t write_headers(Stream &strm, const Headers &headers);
|
ssize_t write_headers(Stream &strm, const Headers &headers);
|
||||||
|
|
||||||
|
std::string make_host_and_port_string(const std::string &host, int port,
|
||||||
|
bool is_ssl);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
@@ -1129,6 +1132,8 @@ public:
|
|||||||
Server &
|
Server &
|
||||||
set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
|
set_header_writer(std::function<ssize_t(Stream &, Headers &)> const &writer);
|
||||||
|
|
||||||
|
Server &set_trusted_proxies(const std::vector<std::string> &proxies);
|
||||||
|
|
||||||
Server &set_keep_alive_max_count(size_t count);
|
Server &set_keep_alive_max_count(size_t count);
|
||||||
Server &set_keep_alive_timeout(time_t sec);
|
Server &set_keep_alive_timeout(time_t sec);
|
||||||
|
|
||||||
@@ -1167,6 +1172,9 @@ protected:
|
|||||||
const std::function<void(Request &)> &setup_request);
|
const std::function<void(Request &)> &setup_request);
|
||||||
|
|
||||||
std::atomic<socket_t> svr_sock_{INVALID_SOCKET};
|
std::atomic<socket_t> svr_sock_{INVALID_SOCKET};
|
||||||
|
|
||||||
|
std::vector<std::string> trusted_proxies_;
|
||||||
|
|
||||||
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
|
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
|
||||||
time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
|
time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
|
||||||
time_t read_timeout_sec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND;
|
time_t read_timeout_sec_ = CPPHTTPLIB_SERVER_READ_TIMEOUT_SECOND;
|
||||||
@@ -1719,8 +1727,6 @@ private:
|
|||||||
const std::string &boundary, const UploadFormDataItems &items,
|
const std::string &boundary, const UploadFormDataItems &items,
|
||||||
const FormDataProviderItems &provider_items) const;
|
const FormDataProviderItems &provider_items) const;
|
||||||
|
|
||||||
std::string adjust_host_string(const std::string &host) const;
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
process_socket(const Socket &socket,
|
process_socket(const Socket &socket,
|
||||||
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
||||||
@@ -1953,14 +1959,17 @@ public:
|
|||||||
void update_certs(X509 *cert, EVP_PKEY *private_key,
|
void update_certs(X509 *cert, EVP_PKEY *private_key,
|
||||||
X509_STORE *client_ca_cert_store = nullptr);
|
X509_STORE *client_ca_cert_store = nullptr);
|
||||||
|
|
||||||
|
int ssl_last_error() const { return last_ssl_error_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool process_and_close_socket(socket_t sock) override;
|
bool process_and_close_socket(socket_t sock) override;
|
||||||
|
|
||||||
|
STACK_OF(X509_NAME) * extract_ca_names_from_x509_store(X509_STORE *store);
|
||||||
|
|
||||||
SSL_CTX *ctx_;
|
SSL_CTX *ctx_;
|
||||||
std::mutex ctx_mutex_;
|
std::mutex ctx_mutex_;
|
||||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
||||||
int last_ssl_error_ = 0;
|
int last_ssl_error_ = 0;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SSLClient final : public ClientImpl {
|
class SSLClient final : public ClientImpl {
|
||||||
@@ -4596,13 +4605,35 @@ inline bool zstd_decompressor::decompress(const char *data, size_t data_length,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
inline bool is_prohibited_header_name(const std::string &name) {
|
||||||
|
using udl::operator""_t;
|
||||||
|
|
||||||
|
switch (str2tag(name)) {
|
||||||
|
case "REMOTE_ADDR"_t:
|
||||||
|
case "REMOTE_PORT"_t:
|
||||||
|
case "LOCAL_ADDR"_t:
|
||||||
|
case "LOCAL_PORT"_t: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline bool has_header(const Headers &headers, const std::string &key) {
|
inline bool has_header(const Headers &headers, const std::string &key) {
|
||||||
|
if (is_prohibited_header_name(key)) { return false; }
|
||||||
return headers.find(key) != headers.end();
|
return headers.find(key) != headers.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *get_header_value(const Headers &headers,
|
inline const char *get_header_value(const Headers &headers,
|
||||||
const std::string &key, const char *def,
|
const std::string &key, const char *def,
|
||||||
size_t id) {
|
size_t id) {
|
||||||
|
if (is_prohibited_header_name(key)) {
|
||||||
|
#ifndef CPPHTTPLIB_NO_EXCEPTIONS
|
||||||
|
std::string msg = "Prohibited header name '" + key + "' is specified.";
|
||||||
|
throw std::invalid_argument(msg);
|
||||||
|
#else
|
||||||
|
return "";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
auto rng = headers.equal_range(key);
|
auto rng = headers.equal_range(key);
|
||||||
auto it = rng.first;
|
auto it = rng.first;
|
||||||
std::advance(it, static_cast<ssize_t>(id));
|
std::advance(it, static_cast<ssize_t>(id));
|
||||||
@@ -7261,6 +7292,30 @@ inline bool RegexMatcher::match(Request &request) const {
|
|||||||
return std::regex_match(request.path, request.matches, regex_);
|
return std::regex_match(request.path, request.matches, regex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string make_host_and_port_string(const std::string &host, int port,
|
||||||
|
bool is_ssl) {
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// Enclose IPv6 address in brackets (but not if already enclosed)
|
||||||
|
if (host.find(':') == std::string::npos ||
|
||||||
|
(!host.empty() && host[0] == '[')) {
|
||||||
|
// IPv4, hostname, or already bracketed IPv6
|
||||||
|
result = host;
|
||||||
|
} else {
|
||||||
|
// IPv6 address without brackets
|
||||||
|
result = "[" + host + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append port if not default
|
||||||
|
if ((!is_ssl && port == 80) || (is_ssl && port == 443)) {
|
||||||
|
; // do nothing
|
||||||
|
} else {
|
||||||
|
result += ":" + std::to_string(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
// HTTP server implementation
|
// HTTP server implementation
|
||||||
@@ -7473,6 +7528,12 @@ inline Server &Server::set_header_writer(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Server &
|
||||||
|
Server::set_trusted_proxies(const std::vector<std::string> &proxies) {
|
||||||
|
trusted_proxies_ = proxies;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline Server &Server::set_keep_alive_max_count(size_t count) {
|
inline Server &Server::set_keep_alive_max_count(size_t count) {
|
||||||
keep_alive_max_count_ = count;
|
keep_alive_max_count_ = count;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -8261,6 +8322,40 @@ inline bool Server::dispatch_request_for_content_reader(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string
|
||||||
|
get_client_ip(const std::string &x_forwarded_for,
|
||||||
|
const std::vector<std::string> &trusted_proxies) {
|
||||||
|
// X-Forwarded-For is a comma-separated list per RFC 7239
|
||||||
|
std::vector<std::string> ip_list;
|
||||||
|
detail::split(x_forwarded_for.data(),
|
||||||
|
x_forwarded_for.data() + x_forwarded_for.size(), ',',
|
||||||
|
[&](const char *b, const char *e) {
|
||||||
|
auto r = detail::trim(b, e, 0, static_cast<size_t>(e - b));
|
||||||
|
ip_list.emplace_back(std::string(b + r.first, b + r.second));
|
||||||
|
});
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ip_list.size(); ++i) {
|
||||||
|
auto ip = ip_list[i];
|
||||||
|
|
||||||
|
auto is_trusted_proxy =
|
||||||
|
std::any_of(trusted_proxies.begin(), trusted_proxies.end(),
|
||||||
|
[&](const std::string &proxy) { return ip == proxy; });
|
||||||
|
|
||||||
|
if (is_trusted_proxy) {
|
||||||
|
if (i == 0) {
|
||||||
|
// If the trusted proxy is the first IP, there's no preceding client IP
|
||||||
|
return ip;
|
||||||
|
} else {
|
||||||
|
// Return the IP immediately before the trusted proxy
|
||||||
|
return ip_list[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no trusted proxy is found, return the first IP in the list
|
||||||
|
return ip_list.front();
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
Server::process_request(Stream &strm, const std::string &remote_addr,
|
Server::process_request(Stream &strm, const std::string &remote_addr,
|
||||||
int remote_port, const std::string &local_addr,
|
int remote_port, const std::string &local_addr,
|
||||||
@@ -8324,15 +8419,16 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
|
|||||||
connection_closed = true;
|
connection_closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.remote_addr = remote_addr;
|
if (!trusted_proxies_.empty() && req.has_header("X-Forwarded-For")) {
|
||||||
|
auto x_forwarded_for = req.get_header_value("X-Forwarded-For");
|
||||||
|
req.remote_addr = get_client_ip(x_forwarded_for, trusted_proxies_);
|
||||||
|
} else {
|
||||||
|
req.remote_addr = remote_addr;
|
||||||
|
}
|
||||||
req.remote_port = remote_port;
|
req.remote_port = remote_port;
|
||||||
req.set_header("REMOTE_ADDR", req.remote_addr);
|
|
||||||
req.set_header("REMOTE_PORT", std::to_string(req.remote_port));
|
|
||||||
|
|
||||||
req.local_addr = local_addr;
|
req.local_addr = local_addr;
|
||||||
req.local_port = local_port;
|
req.local_port = local_port;
|
||||||
req.set_header("LOCAL_ADDR", req.local_addr);
|
|
||||||
req.set_header("LOCAL_PORT", std::to_string(req.local_port));
|
|
||||||
|
|
||||||
if (req.has_header("Accept")) {
|
if (req.has_header("Accept")) {
|
||||||
const auto &accept_header = req.get_header_value("Accept");
|
const auto &accept_header = req.get_header_value("Accept");
|
||||||
@@ -8522,7 +8618,7 @@ inline ClientImpl::ClientImpl(const std::string &host, int port,
|
|||||||
const std::string &client_cert_path,
|
const std::string &client_cert_path,
|
||||||
const std::string &client_key_path)
|
const std::string &client_key_path)
|
||||||
: host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
|
: host_(detail::escape_abstract_namespace_unix_domain(host)), port_(port),
|
||||||
host_and_port_(adjust_host_string(host_) + ":" + std::to_string(port)),
|
host_and_port_(detail::make_host_and_port_string(host_, port, is_ssl())),
|
||||||
client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
|
client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
|
||||||
|
|
||||||
inline ClientImpl::~ClientImpl() {
|
inline ClientImpl::~ClientImpl() {
|
||||||
@@ -8703,8 +8799,9 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(socket_mutex_);
|
std::lock_guard<std::mutex> guard(socket_mutex_);
|
||||||
|
|
||||||
// Set this to false immediately - if it ever gets set to true by the end of
|
// Set this to false immediately - if it ever gets set to true by the end
|
||||||
// the request, we know another thread instructed us to close the socket.
|
// of the request, we know another thread instructed us to close the
|
||||||
|
// socket.
|
||||||
socket_should_be_closed_when_request_is_done_ = false;
|
socket_should_be_closed_when_request_is_done_ = false;
|
||||||
|
|
||||||
auto is_alive = false;
|
auto is_alive = false;
|
||||||
@@ -8720,10 +8817,10 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!is_alive) {
|
if (!is_alive) {
|
||||||
// Attempt to avoid sigpipe by shutting down non-gracefully if it seems
|
// Attempt to avoid sigpipe by shutting down non-gracefully if it
|
||||||
// like the other side has already closed the connection Also, there
|
// seems like the other side has already closed the connection Also,
|
||||||
// cannot be any requests in flight from other threads since we locked
|
// there cannot be any requests in flight from other threads since we
|
||||||
// request_mutex_, so safe to close everything immediately
|
// locked request_mutex_, so safe to close everything immediately
|
||||||
const bool shutdown_gracefully = false;
|
const bool shutdown_gracefully = false;
|
||||||
shutdown_ssl(socket_, shutdown_gracefully);
|
shutdown_ssl(socket_, shutdown_gracefully);
|
||||||
shutdown_socket(socket_);
|
shutdown_socket(socket_);
|
||||||
@@ -9027,7 +9124,8 @@ inline bool ClientImpl::create_redirect_client(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// New method for robust client setup (based on basic_manual_redirect.cpp logic)
|
// New method for robust client setup (based on basic_manual_redirect.cpp
|
||||||
|
// logic)
|
||||||
template <typename ClientType>
|
template <typename ClientType>
|
||||||
inline void ClientImpl::setup_redirect_client(ClientType &client) {
|
inline void ClientImpl::setup_redirect_client(ClientType &client) {
|
||||||
// Copy basic settings first
|
// Copy basic settings first
|
||||||
@@ -9131,18 +9229,8 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req,
|
|||||||
// curl behavior)
|
// curl behavior)
|
||||||
if (address_family_ == AF_UNIX) {
|
if (address_family_ == AF_UNIX) {
|
||||||
req.set_header("Host", "localhost");
|
req.set_header("Host", "localhost");
|
||||||
} else if (is_ssl()) {
|
|
||||||
if (port_ == 443) {
|
|
||||||
req.set_header("Host", host_);
|
|
||||||
} else {
|
|
||||||
req.set_header("Host", host_and_port_);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (port_ == 80) {
|
req.set_header("Host", host_and_port_);
|
||||||
req.set_header("Host", host_);
|
|
||||||
} else {
|
|
||||||
req.set_header("Host", host_and_port_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9409,12 +9497,6 @@ inline Result ClientImpl::send_with_content_provider(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string
|
|
||||||
ClientImpl::adjust_host_string(const std::string &host) const {
|
|
||||||
if (host.find(':') != std::string::npos) { return "[" + host + "]"; }
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ClientImpl::output_log(const Request &req,
|
inline void ClientImpl::output_log(const Request &req,
|
||||||
const Response &res) const {
|
const Response &res) const {
|
||||||
if (logger_) {
|
if (logger_) {
|
||||||
@@ -9538,8 +9620,8 @@ inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
|
|||||||
const FormDataProviderItems &provider_items) const {
|
const FormDataProviderItems &provider_items) const {
|
||||||
size_t cur_item = 0;
|
size_t cur_item = 0;
|
||||||
size_t cur_start = 0;
|
size_t cur_start = 0;
|
||||||
// cur_item and cur_start are copied to within the std::function and maintain
|
// cur_item and cur_start are copied to within the std::function and
|
||||||
// state between successive calls
|
// maintain state between successive calls
|
||||||
return [&, cur_item, cur_start](size_t offset,
|
return [&, cur_item, cur_start](size_t offset,
|
||||||
DataSink &sink) mutable -> bool {
|
DataSink &sink) mutable -> bool {
|
||||||
if (!offset && !items.empty()) {
|
if (!offset && !items.empty()) {
|
||||||
@@ -10251,8 +10333,8 @@ inline void ClientImpl::stop() {
|
|||||||
// If there is anything ongoing right now, the ONLY thread-safe thing we can
|
// If there is anything ongoing right now, the ONLY thread-safe thing we can
|
||||||
// do is to shutdown_socket, so that threads using this socket suddenly
|
// do is to shutdown_socket, so that threads using this socket suddenly
|
||||||
// discover they can't read/write any more and error out. Everything else
|
// discover they can't read/write any more and error out. Everything else
|
||||||
// (closing the socket, shutting ssl down) is unsafe because these actions are
|
// (closing the socket, shutting ssl down) is unsafe because these actions
|
||||||
// not thread-safe.
|
// are not thread-safe.
|
||||||
if (socket_requests_in_flight_ > 0) {
|
if (socket_requests_in_flight_ > 0) {
|
||||||
shutdown_socket(socket_);
|
shutdown_socket(socket_);
|
||||||
|
|
||||||
@@ -10705,6 +10787,19 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
|
|||||||
SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path,
|
SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path,
|
||||||
client_ca_cert_dir_path);
|
client_ca_cert_dir_path);
|
||||||
|
|
||||||
|
// Set client CA list to be sent to clients during TLS handshake
|
||||||
|
if (client_ca_cert_file_path) {
|
||||||
|
auto ca_list = SSL_load_client_CA_file(client_ca_cert_file_path);
|
||||||
|
if (ca_list != nullptr) {
|
||||||
|
SSL_CTX_set_client_CA_list(ctx_, ca_list);
|
||||||
|
} else {
|
||||||
|
// Failed to load client CA list, but we continue since
|
||||||
|
// SSL_CTX_load_verify_locations already succeeded and
|
||||||
|
// certificate verification will still work
|
||||||
|
last_ssl_error_ = static_cast<int>(ERR_get_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SSL_CTX_set_verify(
|
SSL_CTX_set_verify(
|
||||||
ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
||||||
}
|
}
|
||||||
@@ -10729,6 +10824,15 @@ inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
|
|||||||
} else if (client_ca_cert_store) {
|
} else if (client_ca_cert_store) {
|
||||||
SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
|
SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
|
||||||
|
|
||||||
|
// Extract CA names from the store and set them as the client CA list
|
||||||
|
auto ca_list = extract_ca_names_from_x509_store(client_ca_cert_store);
|
||||||
|
if (ca_list) {
|
||||||
|
SSL_CTX_set_client_CA_list(ctx_, ca_list);
|
||||||
|
} else {
|
||||||
|
// Failed to extract CA names, record the error
|
||||||
|
last_ssl_error_ = static_cast<int>(ERR_get_error());
|
||||||
|
}
|
||||||
|
|
||||||
SSL_CTX_set_verify(
|
SSL_CTX_set_verify(
|
||||||
ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
||||||
}
|
}
|
||||||
@@ -10809,6 +10913,44 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// SSL HTTP client implementation
|
||||||
inline SSLClient::SSLClient(const std::string &host)
|
inline SSLClient::SSLClient(const std::string &host)
|
||||||
: SSLClient(host, 443, std::string(), std::string()) {}
|
: SSLClient(host, 443, std::string(), std::string()) {}
|
||||||
@@ -10889,7 +11031,8 @@ inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
|||||||
if (ca_cert_store) {
|
if (ca_cert_store) {
|
||||||
if (ctx_) {
|
if (ctx_) {
|
||||||
if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) {
|
if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) {
|
||||||
// Free memory allocated for old cert and use new store `ca_cert_store`
|
// Free memory allocated for old cert and use new store
|
||||||
|
// `ca_cert_store`
|
||||||
SSL_CTX_set_cert_store(ctx_, ca_cert_store);
|
SSL_CTX_set_cert_store(ctx_, ca_cert_store);
|
||||||
ca_cert_store_ = ca_cert_store;
|
ca_cert_store_ = ca_cert_store;
|
||||||
}
|
}
|
||||||
@@ -10911,10 +11054,15 @@ inline long SSLClient::get_openssl_verify_result() const {
|
|||||||
inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; }
|
inline SSL_CTX *SSLClient::ssl_context() const { return ctx_; }
|
||||||
|
|
||||||
inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
|
inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
|
||||||
return is_valid() && ClientImpl::create_and_connect_socket(socket, error);
|
if (!is_valid()) {
|
||||||
|
error = Error::SSLConnection;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ClientImpl::create_and_connect_socket(socket, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes that socket_mutex_ is locked and that there are no requests in flight
|
// Assumes that socket_mutex_ is locked and that there are no requests in
|
||||||
|
// flight
|
||||||
inline bool SSLClient::connect_with_proxy(
|
inline bool SSLClient::connect_with_proxy(
|
||||||
Socket &socket,
|
Socket &socket,
|
||||||
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
std::chrono::time_point<std::chrono::steady_clock> start_time,
|
||||||
@@ -11128,6 +11276,11 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx_ == nullptr) {
|
||||||
|
error = Error::SSLConnection;
|
||||||
|
last_openssl_error_ = ERR_get_error();
|
||||||
|
}
|
||||||
|
|
||||||
shutdown_socket(socket);
|
shutdown_socket(socket);
|
||||||
close_socket(socket);
|
close_socket(socket);
|
||||||
return false;
|
return false;
|
||||||
@@ -11221,21 +11374,22 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const {
|
|||||||
|
|
||||||
for (decltype(count) i = 0; i < count && !dsn_matched; i++) {
|
for (decltype(count) i = 0; i < count && !dsn_matched; i++) {
|
||||||
auto val = sk_GENERAL_NAME_value(alt_names, i);
|
auto val = sk_GENERAL_NAME_value(alt_names, i);
|
||||||
if (val->type == type) {
|
if (!val || val->type != type) { continue; }
|
||||||
auto name =
|
|
||||||
reinterpret_cast<const char *>(ASN1_STRING_get0_data(val->d.ia5));
|
|
||||||
auto name_len = static_cast<size_t>(ASN1_STRING_length(val->d.ia5));
|
|
||||||
|
|
||||||
switch (type) {
|
auto name =
|
||||||
case GEN_DNS: dsn_matched = check_host_name(name, name_len); break;
|
reinterpret_cast<const char *>(ASN1_STRING_get0_data(val->d.ia5));
|
||||||
|
if (name == nullptr) { continue; }
|
||||||
|
|
||||||
case GEN_IPADD:
|
auto name_len = static_cast<size_t>(ASN1_STRING_length(val->d.ia5));
|
||||||
if (!memcmp(&addr6, name, addr_len) ||
|
|
||||||
!memcmp(&addr, name, addr_len)) {
|
switch (type) {
|
||||||
ip_matched = true;
|
case GEN_DNS: dsn_matched = check_host_name(name, name_len); break;
|
||||||
}
|
|
||||||
break;
|
case GEN_IPADD:
|
||||||
|
if (!memcmp(&addr6, name, addr_len) || !memcmp(&addr, name, addr_len)) {
|
||||||
|
ip_matched = true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user