From c9bb56577b8ff06e162baa3af134554d549f0abc Mon Sep 17 00:00:00 2001 From: cxl Date: Sat, 8 Apr 2017 21:32:22 +0000 Subject: [PATCH] Core: Socket::SSLServerNameIndicator, used in HttpRequest; fixes problems with connecting to some https server git-svn-id: svn://ultimatepp.org/upp/trunk@10990 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Http.cpp | 4 +++- uppsrc/Core/Inet.h | 3 ++- uppsrc/Core/SSL/Socket.cpp | 16 +++++++++++++++- uppsrc/Core/Socket.cpp | 5 +++++ uppsrc/Core/src.tpp/TcpSocket$en-us.tpp | 8 +++++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/uppsrc/Core/Http.cpp b/uppsrc/Core/Http.cpp index 08c9baf88..c537404c7 100644 --- a/uppsrc/Core/Http.cpp +++ b/uppsrc/Core/Http.cpp @@ -446,13 +446,15 @@ void HttpRequest::Start() p = ssl ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT; String h = use_proxy ? ssl ? ssl_proxy_host : proxy_host : host; LLOG("Using " << (use_proxy ? "proxy " : "") << h << ":" << p); + + SSLServerNameIndication(host); StartPhase(DNS); if(IsNull(GetTimeout()) && timeout == INT_MAX) { if(WhenWait) { addrinfo.Start(h, p); while(addrinfo.InProgress()) { - Sleep(GetWaitStep()); + Sleep(GetWaitStep()); WhenWait(); if(msecs(start_time) >= timeout) break; diff --git a/uppsrc/Core/Inet.h b/uppsrc/Core/Inet.h index bdb3c3add..d77b7c48a 100644 --- a/uppsrc/Core/Inet.h +++ b/uppsrc/Core/Inet.h @@ -128,7 +128,7 @@ class TcpSocket : NoCopy { One ssl; One sslinfo; - String cert, pkey; + String cert, pkey, sni; bool asn1; struct SSLImp; @@ -238,6 +238,7 @@ public: bool IsSSL() const { return ssl; } bool SSLHandshake(); void SSLCertificate(const String& cert, const String& pkey, bool asn1); + void SSLServerNameIndication(const String& name); const SSLInfo *GetSSLInfo() const { return ~sslinfo; } void Clear(); diff --git a/uppsrc/Core/SSL/Socket.cpp b/uppsrc/Core/SSL/Socket.cpp index 99d3e6fe5..57fea110b 100644 --- a/uppsrc/Core/SSL/Socket.cpp +++ b/uppsrc/Core/SSL/Socket.cpp @@ -89,7 +89,14 @@ void TcpSocket::SSLImp::SetSSLResError(const char *context, int res) socket.SetSockError(context); return; } - socket.SetSockError(context, code, GetErrorText(code)); + String txt = GetErrorText(code); + int err = ERR_get_error(); + if(err) { + char h[260]; + ERR_error_string(err, h); + txt << "; " << h; + } + socket.SetSockError(context, code, txt); } bool TcpSocket::SSLImp::IsAgain(int res) const @@ -125,6 +132,13 @@ bool TcpSocket::SSLImp::Start() SetSSLError("Start: SSL_new"); return false; } + + if(socket.sni.GetCount()) { + Buffer h(socket.sni.GetCount() + 1); + strcpy(~h, ~socket.sni); + SSL_set_tlsext_host_name(ssl, h); + } + if(!SSL_set_fd(ssl, (int)socket.GetSOCKET())) { SetSSLError("Start: SSL_set_fd"); return false; diff --git a/uppsrc/Core/Socket.cpp b/uppsrc/Core/Socket.cpp index 20257d61e..8d8e9df66 100644 --- a/uppsrc/Core/Socket.cpp +++ b/uppsrc/Core/Socket.cpp @@ -961,6 +961,11 @@ void TcpSocket::SSLCertificate(const String& cert_, const String& pkey_, bool as asn1 = asn1_; } +void TcpSocket::SSLServerNameIndication(const String& name) +{ + sni = name; +} + void TcpSocket::Clear() { ClearError(); diff --git a/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp b/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp index 580cda7c1..3c47fb97c 100644 --- a/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp +++ b/uppsrc/Core/src.tpp/TcpSocket$en-us.tpp @@ -277,12 +277,18 @@ tring][@(0.0.255) `&]_[*@3 pkey], [@(0.0.255) bool]_[*@3 asn1])&] (Note that clients usually do not need certificates, this is usually used on accepting sockets.)&] [s3;%% &] +[s4; &] +[s5;:Upp`:`:TcpSocket`:`:SSLServerNameIndication`(const Upp`:`:String`&`): [@(0.0.255) v +oid]_[* SSLServerNameIndication]([@(0.0.255) const]_[_^Upp`:`:String^ String][@(0.0.255) `& +]_[*@3 name])&] +[s2;%% Sets [^https`:`/`/cs`.wikipedia`.org`/wiki`/Server`_Name`_Indication^ SNI] +for SSL connection.&] +[s3;%% &] [s4;%% &] [s5;:TcpSocket`:`:GetSSLInfo`(`)const: [@(0.0.255) const]_[_^topic`:`/`/Core`/src`/TcpSocket`$en`-us`#SSLInfo`:`:struct^ S SLInfo]_`*[* GetSSLInfo]()_[@(0.0.255) const]&] [s2;%% Returns information about established (after handshake) SSL connection or NULL if such information is not available.&] -[s2;%% &] [s3;%% &] [s4;%% &] [s5;:TcpSocket`:`:Timeout`(int`): [_^topic`:`/`/Core`/src`/TcpSocket`$en`-us`#TcpSocket`:`:class^ T