You've already forked cpp-httplib
65
httplib.h
65
httplib.h
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user