Description
First of all, thanks for providing such a great library!
I had a problem to get connections to certain HTTPS hosts working with using httplib::SSLClient
. After investigating with openssl s_client, I found that the problem is that the host sends the wrong certificate to the client. This is because, the server doesn't know for which site the client expects the certificate if multiple sites/certificates are on the same host (i.e. on a virtual server).
The solution to this problem in TLS is the extension RFC 6066, Server Name Indication. Using this TLS extension the client will send during the handshake the servername for which he wants to receive the certificate, so that the correct certificate can be supplied to the client. The extension is already implemented in openssl and can be used with the "-servername" parameter, i.e. openssl s_client -connect httpbin.org:443 -servername httpbin.org
SNI (Server Name Indication) is widely used on the internet and I think it would be a valuable addition to cpp-httplib.
A minimal example which shows the problem using httplib::SSLClient (openssl-1.0.2l, Visual Studio 2017):
#include <iostream>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
int main(int argc, char* argv[]) {
httplib::SSLClient cli("httpbin.org", 443);
auto res = cli.get("/get");
if (res && res->status == 200) {
std::cout << res->body << std::endl;
}
return 0;
}
One possible workaround in read_and_close_socket_ssl
is:
SSL_set_bio(ssl, bio, bio);
SSL_set_tlsext_host_name(ssl, "httpbin.org"); // workaround
SSL_connect_or_accept(ssl);
It would be more elegant, if the hostname would come from the Client::host_
, but it is not accessible from there with the current interface.