1
0
mirror of synced 2025-07-17 17:40:57 +03:00
* Fix #1416

* Update

* Update
This commit is contained in:
yhirose
2025-07-05 15:17:53 -04:00
committed by GitHub
parent 120405beac
commit cb85e573de
3 changed files with 178 additions and 16 deletions

View File

@ -1246,6 +1246,17 @@ public:
Headers &&request_headers = Headers{})
: res_(std::move(res)), err_(err),
request_headers_(std::move(request_headers)) {}
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
Result(std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
int ssl_error)
: res_(std::move(res)), err_(err),
request_headers_(std::move(request_headers)), ssl_error_(ssl_error) {}
Result(std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
int ssl_error, unsigned long ssl_openssl_error)
: res_(std::move(res)), err_(err),
request_headers_(std::move(request_headers)), ssl_error_(ssl_error),
ssl_openssl_error_(ssl_openssl_error) {}
#endif
// Response
operator bool() const { return res_ != nullptr; }
bool operator==(std::nullptr_t) const { return res_ == nullptr; }
@ -1260,6 +1271,13 @@ public:
// Error
Error error() const { return err_; }
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
// SSL Error
int ssl_error() const { return ssl_error_; }
// OpenSSL Error
unsigned long ssl_openssl_error() const { return ssl_openssl_error_; }
#endif
// Request Headers
bool has_request_header(const std::string &key) const;
std::string get_request_header_value(const std::string &key,
@ -1273,6 +1291,10 @@ private:
std::unique_ptr<Response> res_;
Error err_ = Error::Unknown;
Headers request_headers_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
int ssl_error_ = 0;
unsigned long ssl_openssl_error_ = 0;
#endif
};
class ClientImpl {
@ -1570,6 +1592,11 @@ protected:
Logger logger_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
int last_ssl_error_ = 0;
unsigned long last_openssl_error_ = 0;
#endif
private:
bool send_(Request &req, Response &res, Error &error);
Result send_(Request &&req);
@ -1840,6 +1867,9 @@ private:
SSL_CTX *ctx_;
std::mutex ctx_mutex_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
int last_ssl_error_ = 0;
#endif
};
class SSLClient final : public ClientImpl {
@ -8173,7 +8203,12 @@ inline Result ClientImpl::send_(Request &&req) {
auto res = detail::make_unique<Response>();
auto error = Error::Success;
auto ret = send(req, *res, error);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
return Result{ret ? std::move(res) : nullptr, error, std::move(req.headers),
last_ssl_error_, last_openssl_error_};
#else
return Result{ret ? std::move(res) : nullptr, error, std::move(req.headers)};
#endif
}
inline bool ClientImpl::handle_request(Stream &strm, Request &req,
@ -8723,7 +8758,12 @@ inline Result ClientImpl::send_with_content_provider(
req, body, content_length, std::move(content_provider),
std::move(content_provider_without_length), content_type, error);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
return Result{std::move(res), error, std::move(req.headers), last_ssl_error_,
last_openssl_error_};
#else
return Result{std::move(res), error, std::move(req.headers)};
#endif
}
inline std::string
@ -9790,8 +9830,8 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
template <typename U>
bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl,
U ssl_connect_or_accept,
time_t timeout_sec,
time_t timeout_usec) {
time_t timeout_sec, time_t timeout_usec,
int *ssl_error) {
auto res = 0;
while ((res = ssl_connect_or_accept(ssl)) != 1) {
auto err = SSL_get_error(ssl, res);
@ -9804,6 +9844,7 @@ bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl,
break;
default: break;
}
if (ssl_error) { *ssl_error = err; }
return false;
}
return true;
@ -9897,9 +9938,10 @@ inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
if (ret >= 0) { return ret; }
err = SSL_get_error(ssl_, ret);
} else {
return -1;
break;
}
}
assert(ret < 0);
}
return ret;
} else {
@ -9929,9 +9971,10 @@ inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
if (ret >= 0) { return ret; }
err = SSL_get_error(ssl_, ret);
} else {
return -1;
break;
}
}
assert(ret < 0);
}
return ret;
}
@ -9982,6 +10025,7 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) !=
1 ||
SSL_CTX_check_private_key(ctx_) != 1) {
last_ssl_error_ = static_cast<int>(ERR_get_error());
SSL_CTX_free(ctx_);
ctx_ = nullptr;
} else if (client_ca_cert_file_path || client_ca_cert_dir_path) {
@ -10055,7 +10099,8 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
sock, ctx_, ctx_mutex_,
[&](SSL *ssl2) {
return detail::ssl_connect_or_accept_nonblocking(
sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_);
sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_,
&last_ssl_error_);
},
[](SSL * /*ssl2*/) { return true; });
@ -10123,6 +10168,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
SSL_FILETYPE_PEM) != 1 ||
SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(),
SSL_FILETYPE_PEM) != 1) {
last_openssl_error_ = ERR_get_error();
SSL_CTX_free(ctx_);
ctx_ = nullptr;
}
@ -10149,6 +10195,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 ||
SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) {
last_openssl_error_ = ERR_get_error();
SSL_CTX_free(ctx_);
ctx_ = nullptr;
}
@ -10292,11 +10339,13 @@ inline bool SSLClient::load_certs() {
if (!ca_cert_file_path_.empty()) {
if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(),
nullptr)) {
last_openssl_error_ = ERR_get_error();
ret = false;
}
} else if (!ca_cert_dir_path_.empty()) {
if (!SSL_CTX_load_verify_locations(ctx_, nullptr,
ca_cert_dir_path_.c_str())) {
last_openssl_error_ = ERR_get_error();
ret = false;
}
} else {
@ -10329,7 +10378,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
if (!detail::ssl_connect_or_accept_nonblocking(
socket.sock, ssl2, SSL_connect, connection_timeout_sec_,
connection_timeout_usec_)) {
connection_timeout_usec_, &last_ssl_error_)) {
error = Error::SSLConnection;
return false;
}
@ -10342,6 +10391,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
}
if (verification_status == SSLVerifierResponse::CertificateRejected) {
last_openssl_error_ = ERR_get_error();
error = Error::SSLServerVerification;
return false;
}
@ -10350,6 +10400,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
verify_result_ = SSL_get_verify_result(ssl2);
if (verify_result_ != X509_V_OK) {
last_openssl_error_ = static_cast<unsigned long>(verify_result_);
error = Error::SSLServerVerification;
return false;
}
@ -10358,12 +10409,14 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
auto se = detail::scope_exit([&] { X509_free(server_cert); });
if (server_cert == nullptr) {
last_openssl_error_ = ERR_get_error();
error = Error::SSLServerVerification;
return false;
}
if (server_hostname_verification_) {
if (!verify_host(server_cert)) {
last_openssl_error_ = X509_V_ERR_HOSTNAME_MISMATCH;
error = Error::SSLServerHostnameVerification;
return false;
}