@@ -1246,6 +1246,17 @@ class Result {
1246
1246
Headers &&request_headers = Headers{})
1247
1247
: res_(std::move(res)), err_(err),
1248
1248
request_headers_ (std::move(request_headers)) {}
1249
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1250
+ Result (std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
1251
+ int ssl_error)
1252
+ : res_(std::move(res)), err_(err),
1253
+ request_headers_(std::move(request_headers)), ssl_error_(ssl_error) {}
1254
+ Result (std::unique_ptr<Response> &&res, Error err, Headers &&request_headers,
1255
+ int ssl_error, unsigned long ssl_openssl_error)
1256
+ : res_(std::move(res)), err_(err),
1257
+ request_headers_(std::move(request_headers)), ssl_error_(ssl_error),
1258
+ ssl_openssl_error_(ssl_openssl_error) {}
1259
+ #endif
1249
1260
// Response
1250
1261
operator bool () const { return res_ != nullptr ; }
1251
1262
bool operator ==(std::nullptr_t ) const { return res_ == nullptr ; }
@@ -1260,6 +1271,13 @@ class Result {
1260
1271
// Error
1261
1272
Error error () const { return err_; }
1262
1273
1274
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1275
+ // SSL Error
1276
+ int ssl_error () const { return ssl_error_; }
1277
+ // OpenSSL Error
1278
+ unsigned long ssl_openssl_error () const { return ssl_openssl_error_; }
1279
+ #endif
1280
+
1263
1281
// Request Headers
1264
1282
bool has_request_header (const std::string &key) const ;
1265
1283
std::string get_request_header_value (const std::string &key,
@@ -1273,6 +1291,10 @@ class Result {
1273
1291
std::unique_ptr<Response> res_;
1274
1292
Error err_ = Error::Unknown;
1275
1293
Headers request_headers_;
1294
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1295
+ int ssl_error_ = 0 ;
1296
+ unsigned long ssl_openssl_error_ = 0 ;
1297
+ #endif
1276
1298
};
1277
1299
1278
1300
class ClientImpl {
@@ -1570,6 +1592,11 @@ class ClientImpl {
1570
1592
1571
1593
Logger logger_;
1572
1594
1595
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1596
+ int last_ssl_error_ = 0 ;
1597
+ unsigned long last_openssl_error_ = 0 ;
1598
+ #endif
1599
+
1573
1600
private:
1574
1601
bool send_ (Request &req, Response &res, Error &error);
1575
1602
Result send_ (Request &&req);
@@ -1840,6 +1867,9 @@ class SSLServer : public Server {
1840
1867
1841
1868
SSL_CTX *ctx_;
1842
1869
std::mutex ctx_mutex_;
1870
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1871
+ int last_ssl_error_ = 0 ;
1872
+ #endif
1843
1873
};
1844
1874
1845
1875
class SSLClient final : public ClientImpl {
@@ -8173,7 +8203,12 @@ inline Result ClientImpl::send_(Request &&req) {
8173
8203
auto res = detail::make_unique<Response>();
8174
8204
auto error = Error::Success;
8175
8205
auto ret = send (req, *res, error);
8206
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
8207
+ return Result{ret ? std::move (res) : nullptr , error, std::move (req.headers ),
8208
+ last_ssl_error_, last_openssl_error_};
8209
+ #else
8176
8210
return Result{ret ? std::move (res) : nullptr , error, std::move (req.headers )};
8211
+ #endif
8177
8212
}
8178
8213
8179
8214
inline bool ClientImpl::handle_request (Stream &strm, Request &req,
@@ -8723,7 +8758,12 @@ inline Result ClientImpl::send_with_content_provider(
8723
8758
req, body, content_length, std::move (content_provider),
8724
8759
std::move (content_provider_without_length), content_type, error);
8725
8760
8761
+ #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
8762
+ return Result{std::move (res), error, std::move (req.headers ), last_ssl_error_,
8763
+ last_openssl_error_};
8764
+ #else
8726
8765
return Result{std::move (res), error, std::move (req.headers )};
8766
+ #endif
8727
8767
}
8728
8768
8729
8769
inline std::string
@@ -9790,8 +9830,8 @@ inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl, socket_t sock,
9790
9830
template <typename U>
9791
9831
bool ssl_connect_or_accept_nonblocking (socket_t sock, SSL *ssl,
9792
9832
U ssl_connect_or_accept,
9793
- time_t timeout_sec,
9794
- time_t timeout_usec ) {
9833
+ time_t timeout_sec, time_t timeout_usec,
9834
+ int *ssl_error ) {
9795
9835
auto res = 0 ;
9796
9836
while ((res = ssl_connect_or_accept (ssl)) != 1 ) {
9797
9837
auto err = SSL_get_error (ssl, res);
@@ -9804,6 +9844,7 @@ bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl,
9804
9844
break ;
9805
9845
default : break ;
9806
9846
}
9847
+ if (ssl_error) { *ssl_error = err; }
9807
9848
return false ;
9808
9849
}
9809
9850
return true ;
@@ -9897,9 +9938,10 @@ inline ssize_t SSLSocketStream::read(char *ptr, size_t size) {
9897
9938
if (ret >= 0 ) { return ret; }
9898
9939
err = SSL_get_error (ssl_, ret);
9899
9940
} else {
9900
- return - 1 ;
9941
+ break ;
9901
9942
}
9902
9943
}
9944
+ assert (ret < 0 );
9903
9945
}
9904
9946
return ret;
9905
9947
} else {
@@ -9929,9 +9971,10 @@ inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) {
9929
9971
if (ret >= 0 ) { return ret; }
9930
9972
err = SSL_get_error (ssl_, ret);
9931
9973
} else {
9932
- return - 1 ;
9974
+ break ;
9933
9975
}
9934
9976
}
9977
+ assert (ret < 0 );
9935
9978
}
9936
9979
return ret;
9937
9980
}
@@ -9982,6 +10025,7 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
9982
10025
SSL_CTX_use_PrivateKey_file (ctx_, private_key_path, SSL_FILETYPE_PEM) !=
9983
10026
1 ||
9984
10027
SSL_CTX_check_private_key (ctx_) != 1 ) {
10028
+ last_ssl_error_ = static_cast <int >(ERR_get_error ());
9985
10029
SSL_CTX_free (ctx_);
9986
10030
ctx_ = nullptr ;
9987
10031
} 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) {
10055
10099
sock, ctx_, ctx_mutex_,
10056
10100
[&](SSL *ssl2) {
10057
10101
return detail::ssl_connect_or_accept_nonblocking (
10058
- sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_);
10102
+ sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_,
10103
+ &last_ssl_error_);
10059
10104
},
10060
10105
[](SSL * /* ssl2*/ ) { return true ; });
10061
10106
@@ -10123,6 +10168,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
10123
10168
SSL_FILETYPE_PEM) != 1 ||
10124
10169
SSL_CTX_use_PrivateKey_file (ctx_, client_key_path.c_str (),
10125
10170
SSL_FILETYPE_PEM) != 1 ) {
10171
+ last_openssl_error_ = ERR_get_error ();
10126
10172
SSL_CTX_free (ctx_);
10127
10173
ctx_ = nullptr ;
10128
10174
}
@@ -10149,6 +10195,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
10149
10195
10150
10196
if (SSL_CTX_use_certificate (ctx_, client_cert) != 1 ||
10151
10197
SSL_CTX_use_PrivateKey (ctx_, client_key) != 1 ) {
10198
+ last_openssl_error_ = ERR_get_error ();
10152
10199
SSL_CTX_free (ctx_);
10153
10200
ctx_ = nullptr ;
10154
10201
}
@@ -10292,11 +10339,13 @@ inline bool SSLClient::load_certs() {
10292
10339
if (!ca_cert_file_path_.empty ()) {
10293
10340
if (!SSL_CTX_load_verify_locations (ctx_, ca_cert_file_path_.c_str (),
10294
10341
nullptr )) {
10342
+ last_openssl_error_ = ERR_get_error ();
10295
10343
ret = false ;
10296
10344
}
10297
10345
} else if (!ca_cert_dir_path_.empty ()) {
10298
10346
if (!SSL_CTX_load_verify_locations (ctx_, nullptr ,
10299
10347
ca_cert_dir_path_.c_str ())) {
10348
+ last_openssl_error_ = ERR_get_error ();
10300
10349
ret = false ;
10301
10350
}
10302
10351
} else {
@@ -10329,7 +10378,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
10329
10378
10330
10379
if (!detail::ssl_connect_or_accept_nonblocking (
10331
10380
socket.sock , ssl2, SSL_connect, connection_timeout_sec_,
10332
- connection_timeout_usec_)) {
10381
+ connection_timeout_usec_, &last_ssl_error_ )) {
10333
10382
error = Error::SSLConnection;
10334
10383
return false ;
10335
10384
}
@@ -10342,6 +10391,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
10342
10391
}
10343
10392
10344
10393
if (verification_status == SSLVerifierResponse::CertificateRejected) {
10394
+ last_openssl_error_ = ERR_get_error ();
10345
10395
error = Error::SSLServerVerification;
10346
10396
return false ;
10347
10397
}
@@ -10350,6 +10400,7 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
10350
10400
verify_result_ = SSL_get_verify_result (ssl2);
10351
10401
10352
10402
if (verify_result_ != X509_V_OK) {
10403
+ last_openssl_error_ = static_cast <unsigned long >(verify_result_);
10353
10404
error = Error::SSLServerVerification;
10354
10405
return false ;
10355
10406
}
@@ -10358,12 +10409,14 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
10358
10409
auto se = detail::scope_exit ([&] { X509_free (server_cert); });
10359
10410
10360
10411
if (server_cert == nullptr ) {
10412
+ last_openssl_error_ = ERR_get_error ();
10361
10413
error = Error::SSLServerVerification;
10362
10414
return false ;
10363
10415
}
10364
10416
10365
10417
if (server_hostname_verification_) {
10366
10418
if (!verify_host (server_cert)) {
10419
+ last_openssl_error_ = X509_V_ERR_HOSTNAME_MISMATCH;
10367
10420
error = Error::SSLServerHostnameVerification;
10368
10421
return false ;
10369
10422
}
0 commit comments