]> granicus.if.org Git - icinga2/commitdiff
Allow TLS connections with unverified certificates
authorGunnar Beutner <gunnar@beutner.name>
Thu, 16 Oct 2014 07:01:18 +0000 (09:01 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Thu, 16 Oct 2014 07:01:18 +0000 (09:01 +0200)
refs #7244

lib/base/tlsstream.cpp
lib/base/tlsstream.hpp
lib/remote/apiclient.cpp
lib/remote/apiclient.hpp
lib/remote/apilistener.cpp
lib/remote/apilistener.hpp

index fb7c762d60e30058ea852db29852eefc57f60ee5..9082a0f050ac17ecce8c347b958dd36552ae731d 100644 (file)
@@ -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<SSL_CTX>& 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<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+       TlsStream *stream = static_cast<TlsStream *>(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.
  *
index 227fb8e1f426fe5ed0a18fef17a47ff86ae86eb7..00b24ce3b2f0779f90af037493660ddeffef0298 100644 (file)
@@ -52,11 +52,14 @@ public:
 
        virtual bool IsEof(void) const;
 
+       bool IsVerifyOK(void) const;
+
 private:
        shared_ptr<SSL> 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);
 };
 
index 9b6117fe2dc606f770fc2ba291656efe86527e09..9f57aa72e012752853a34a36e769c29990751d64 100644 (file)
@@ -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;
index 6f1f68074799739c97599fc127566fa3a848f615..480eb576e7528e8c6e0d67209a7c9f68bda7428f 100644 (file)
@@ -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;
index d2015f345fcff1e72274fd0f909dc8d5cd133bca..17cc98fbb4b5eaf7d2096f2a366ec37662e6a9f7 100644 (file)
@@ -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<ApiClient>(identity, tlsStream, role);
+       ApiClient::Ptr aclient = make_shared<ApiClient>(identity, verify_ok, tlsStream, role);
        aclient->Start();
 
        if (endpoint) {
index 855ae2df72fd3eb67dac8237ec5de3e9f5910176..a02eb619f3d9d677ba088f20261094ffef44f243 100644 (file)
@@ -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;