Implement SNI support for the TlsStream class

fixes #8610
This commit is contained in:
Gunnar Beutner 2015-03-05 14:15:42 +01:00
parent 4a2a6d999a
commit fd9dc32a3d
5 changed files with 16 additions and 10 deletions

View File

@ -39,7 +39,7 @@ bool I2_EXPORT TlsStream::m_SSLIndexInitialized = false;
* @param role The role of the client. * @param role The role of the client.
* @param sslContext The SSL context for the client. * @param sslContext The SSL context for the client.
*/ */
TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const boost::shared_ptr<SSL_CTX>& sslContext) TlsStream::TlsStream(const Socket::Ptr& socket, const String& hostname, ConnectionRole role, const boost::shared_ptr<SSL_CTX>& sslContext)
: SocketEvents(socket, this), m_Eof(false), m_HandshakeOK(false), m_VerifyOK(true), m_ErrorCode(0), : SocketEvents(socket, this), m_Eof(false), m_HandshakeOK(false), m_VerifyOK(true), m_ErrorCode(0),
m_ErrorOccurred(false), m_Socket(socket), m_Role(role), m_SendQ(new FIFO()), m_RecvQ(new FIFO()), m_ErrorOccurred(false), m_Socket(socket), m_Role(role), m_SendQ(new FIFO()), m_RecvQ(new FIFO()),
m_CurrentAction(TlsActionNone), m_Retry(false) m_CurrentAction(TlsActionNone), m_Retry(false)
@ -73,9 +73,15 @@ TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const boost
if (m_Role == RoleServer) if (m_Role == RoleServer)
SSL_set_accept_state(m_SSL.get()); SSL_set_accept_state(m_SSL.get());
else else {
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (!hostname.IsEmpty())
SSL_set_tlsext_host_name(m_SSL.get(), hostname.CStr());
#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
SSL_set_connect_state(m_SSL.get()); SSL_set_connect_state(m_SSL.get());
} }
}
TlsStream::~TlsStream(void) TlsStream::~TlsStream(void)
{ {

View File

@ -48,7 +48,7 @@ class I2_BASE_API TlsStream : public Stream, private SocketEvents
public: public:
DECLARE_PTR_TYPEDEFS(TlsStream); DECLARE_PTR_TYPEDEFS(TlsStream);
TlsStream(const Socket::Ptr& socket, ConnectionRole role, const boost::shared_ptr<SSL_CTX>& sslContext); TlsStream(const Socket::Ptr& socket, const String& hostname, ConnectionRole role, const boost::shared_ptr<SSL_CTX>& sslContext);
~TlsStream(void); ~TlsStream(void);
boost::shared_ptr<X509> GetClientCertificate(void) const; boost::shared_ptr<X509> GetClientCertificate(void) const;

View File

@ -153,7 +153,7 @@ int PkiUtility::SaveCert(const String& host, const String& port, const String& k
return 1; return 1;
} }
TlsStream::Ptr stream = new TlsStream(client, RoleClient, sslContext); TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext);
try { try {
stream->Handshake(); stream->Handshake();
@ -219,7 +219,7 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
return 1; return 1;
} }
TlsStream::Ptr stream = new TlsStream(client, RoleClient, sslContext); TlsStream::Ptr stream = new TlsStream(client, String(), RoleClient, sslContext);
try { try {
stream->Handshake(); stream->Handshake();

View File

@ -210,7 +210,7 @@ void ApiListener::ListenerThreadProc(const Socket::Ptr& server)
for (;;) { for (;;) {
try { try {
Socket::Ptr client = server->Accept(); Socket::Ptr client = server->Accept();
Utility::QueueAsyncCallback(boost::bind(&ApiListener::NewClientHandler, this, client, RoleServer), LowLatencyScheduler); Utility::QueueAsyncCallback(boost::bind(&ApiListener::NewClientHandler, this, client, String(), RoleServer), LowLatencyScheduler);
} catch (const std::exception&) { } catch (const std::exception&) {
Log(LogCritical, "ApiListener", "Cannot accept new connection."); Log(LogCritical, "ApiListener", "Cannot accept new connection.");
} }
@ -246,7 +246,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
try { try {
endpoint->SetConnecting(true); endpoint->SetConnecting(true);
client->Connect(host, port); client->Connect(host, port);
NewClientHandler(client, RoleClient); NewClientHandler(client, endpoint->GetName(), RoleClient);
endpoint->SetConnecting(false); endpoint->SetConnecting(false);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
endpoint->SetConnecting(false); endpoint->SetConnecting(false);
@ -265,7 +265,7 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
* *
* @param client The new client. * @param client The new client.
*/ */
void ApiListener::NewClientHandler(const Socket::Ptr& client, ConnectionRole role) void ApiListener::NewClientHandler(const Socket::Ptr& client, const String& hostname, ConnectionRole role)
{ {
CONTEXT("Handling new API client connection"); CONTEXT("Handling new API client connection");
@ -274,7 +274,7 @@ void ApiListener::NewClientHandler(const Socket::Ptr& client, ConnectionRole rol
{ {
ObjectLock olock(this); ObjectLock olock(this);
try { try {
tlsStream = new TlsStream(client, role, m_SSLContext); tlsStream = new TlsStream(client, hostname, role, m_SSLContext);
} catch (const std::exception&) { } catch (const std::exception&) {
Log(LogCritical, "ApiListener", "Cannot create TLS stream from client connection."); Log(LogCritical, "ApiListener", "Cannot create TLS stream from client connection.");
return; return;

View File

@ -86,7 +86,7 @@ private:
bool AddListener(const String& node, const String& service); bool AddListener(const String& node, const String& service);
void AddConnection(const Endpoint::Ptr& endpoint); void AddConnection(const Endpoint::Ptr& endpoint);
void NewClientHandler(const Socket::Ptr& client, ConnectionRole role); void NewClientHandler(const Socket::Ptr& client, const String& hostname, ConnectionRole role);
void ListenerThreadProc(const Socket::Ptr& server); void ListenerThreadProc(const Socket::Ptr& server);
WorkQueue m_RelayQueue; WorkQueue m_RelayQueue;