From 311cce5d417065690832b56b5c17ef749d315a87 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 16 Oct 2014 09:01:18 +0200 Subject: [PATCH] Allow TLS connections with unverified certificates refs #7244 --- lib/base/tlsstream.cpp | 17 +++++++++++++++-- lib/base/tlsstream.hpp | 4 ++++ lib/remote/apiclient.cpp | 12 +++++++++--- lib/remote/apiclient.hpp | 4 +++- lib/remote/apilistener.cpp | 17 ++++++++++++++--- lib/remote/apilistener.hpp | 2 -- 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/lib/base/tlsstream.cpp b/lib/base/tlsstream.cpp index fb7c762d6..9082a0f05 100644 --- a/lib/base/tlsstream.cpp +++ b/lib/base/tlsstream.cpp @@ -36,7 +36,7 @@ bool I2_EXPORT TlsStream::m_SSLIndexInitialized = false; * @param sslContext The SSL context for the client. */ TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const shared_ptr& sslContext) - : m_Eof(false), m_Socket(socket), m_Role(role) + : m_Eof(false), m_Socket(socket), m_Role(role), m_VerifyOK(false) { std::ostringstream msgbuf; char errbuf[120]; @@ -59,7 +59,7 @@ TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const share SSL_set_ex_data(m_SSL.get(), m_SSLIndex, this); - SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, &TlsStream::ValidateCertificate); socket->MakeNonBlocking(); @@ -71,6 +71,19 @@ TlsStream::TlsStream(const Socket::Ptr& socket, ConnectionRole role, const share SSL_set_connect_state(m_SSL.get()); } +int TlsStream::ValidateCertificate(int preverify_ok, X509_STORE_CTX *ctx) +{ + SSL *ssl = static_cast(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); + TlsStream *stream = static_cast(SSL_get_ex_data(ssl, m_SSLIndex)); + stream->m_VerifyOK = preverify_ok; + return 1; +} + +bool TlsStream::IsVerifyOK(void) const +{ + return m_VerifyOK; +} + /** * Retrieves the X509 certficate for this client. * diff --git a/lib/base/tlsstream.hpp b/lib/base/tlsstream.hpp index 227fb8e1f..00b24ce3b 100644 --- a/lib/base/tlsstream.hpp +++ b/lib/base/tlsstream.hpp @@ -52,11 +52,14 @@ public: virtual bool IsEof(void) const; + bool IsVerifyOK(void) const; + private: shared_ptr m_SSL; bool m_Eof; mutable boost::mutex m_SSLLock; mutable boost::mutex m_IOActionLock; + bool m_VerifyOK; Socket::Ptr m_Socket; ConnectionRole m_Role; @@ -64,6 +67,7 @@ private: static int m_SSLIndex; static bool m_SSLIndexInitialized; + static int ValidateCertificate(int preverify_ok, X509_STORE_CTX *ctx); static void NullCertificateDeleter(X509 *certificate); }; diff --git a/lib/remote/apiclient.cpp b/lib/remote/apiclient.cpp index 9b6117fe2..9f57aa72e 100644 --- a/lib/remote/apiclient.cpp +++ b/lib/remote/apiclient.cpp @@ -32,10 +32,11 @@ using namespace icinga; static Value SetLogPositionHandler(const MessageOrigin& origin, const Dictionary::Ptr& params); REGISTER_APIFUNCTION(SetLogPosition, log, &SetLogPositionHandler); -ApiClient::ApiClient(const String& identity, const Stream::Ptr& stream, ConnectionRole role) - : m_Identity(identity), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime()) +ApiClient::ApiClient(const String& identity, bool authenticated, const Stream::Ptr& stream, ConnectionRole role) + : m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), m_Role(role), m_Seen(Utility::GetTime()) { - m_Endpoint = Endpoint::GetByName(identity); + if (authenticated) + m_Endpoint = Endpoint::GetByName(identity); } void ApiClient::Start(void) @@ -49,6 +50,11 @@ String ApiClient::GetIdentity(void) const return m_Identity; } +bool ApiClient::IsAuthenticated(void) const +{ + return m_Authenticated; +} + Endpoint::Ptr ApiClient::GetEndpoint(void) const { return m_Endpoint; diff --git a/lib/remote/apiclient.hpp b/lib/remote/apiclient.hpp index 6f1f68074..480eb576e 100644 --- a/lib/remote/apiclient.hpp +++ b/lib/remote/apiclient.hpp @@ -45,11 +45,12 @@ class I2_REMOTE_API ApiClient : public Object public: DECLARE_PTR_TYPEDEFS(ApiClient); - ApiClient(const String& identity, const Stream::Ptr& stream, ConnectionRole role); + ApiClient(const String& identity, bool authenticated, const Stream::Ptr& stream, ConnectionRole role); void Start(void); String GetIdentity(void) const; + bool IsAuthenticated(void) const; Endpoint::Ptr GetEndpoint(void) const; Stream::Ptr GetStream(void) const; ConnectionRole GetRole(void) const; @@ -61,6 +62,7 @@ public: private: String m_Identity; + bool m_Authenticated; Endpoint::Ptr m_Endpoint; Stream::Ptr m_Stream; ConnectionRole m_Role; diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index d2015f345..17cc98fbb 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -291,16 +291,27 @@ void ApiListener::NewClientHandler(const Socket::Ptr& client, ConnectionRole rol return; } - Log(LogInformation, "ApiListener", "New client connection for identity '" + identity + "'"); + bool verify_ok = tlsStream->IsVerifyOK(); - Endpoint::Ptr endpoint = Endpoint::GetByName(identity); + std::ostringstream msgbuf; + msgbuf << "New client connection for identity '" << identity << "'"; + + if (!verify_ok) + msgbuf << " (unauthenticated)"; + + Log(LogInformation, "ApiListener", msgbuf.str()); + + Endpoint::Ptr endpoint; + + if (verify_ok) + endpoint = Endpoint::GetByName(identity); bool need_sync = false; if (endpoint) need_sync = !endpoint->IsConnected(); - ApiClient::Ptr aclient = make_shared(identity, tlsStream, role); + ApiClient::Ptr aclient = make_shared(identity, verify_ok, tlsStream, role); aclient->Start(); if (endpoint) { diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 855ae2df7..a02eb619f 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -85,8 +85,6 @@ private: void NewClientHandler(const Socket::Ptr& client, ConnectionRole role); void ListenerThreadProc(const Socket::Ptr& server); - void MessageHandler(const TlsStream::Ptr& sender, const String& identity, const Dictionary::Ptr& message); - WorkQueue m_RelayQueue; boost::mutex m_LogLock;