From: Gunnar Beutner Date: Fri, 27 Apr 2012 09:44:34 +0000 (+0200) Subject: Disallow connections to endpoints we're already connected to. X-Git-Tag: v0.0.1~573 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d873b50fb8aecbd07e08b0bdd9288d3c87f2ffe;p=icinga2 Disallow connections to endpoints we're already connected to. --- diff --git a/base/utility.cpp b/base/utility.cpp index bc9663505..53919e1be 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -86,3 +86,23 @@ string Utility::GetCertificateCN(const shared_ptr& certificate) return buffer; } + +shared_ptr Utility::GetX509Certificate(string pemfile) +{ + X509 *cert; + BIO *fpcert = BIO_new(BIO_s_file()); + + if (fpcert == NULL) + throw OpenSSLException("BIO_new failed", ERR_get_error()); + + if (BIO_read_filename(fpcert, pemfile.c_str()) < 0) + throw OpenSSLException("BIO_read_filename failed", ERR_get_error()); + + cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL); + if (cert == NULL) + throw OpenSSLException("PEM_read_bio_X509_AUX failed", ERR_get_error()); + + BIO_free(fpcert); + + return shared_ptr(cert, X509_free); +} diff --git a/base/utility.h b/base/utility.h index 785ff8127..ef95d885f 100644 --- a/base/utility.h +++ b/base/utility.h @@ -46,6 +46,7 @@ public: static shared_ptr MakeSSLContext(string pubkey, string privkey, string cakey); static string GetCertificateCN(const shared_ptr& certificate); + static shared_ptr GetX509Certificate(string pemfile); }; } diff --git a/icinga-app/icinga.conf b/icinga-app/icinga.conf index c7ec54767..621a96513 100644 --- a/icinga-app/icinga.conf +++ b/icinga-app/icinga.conf @@ -4,7 +4,7 @@ "demo": { "replicate": "0" } }, "rpcconnection": { - "kekslistener": { "replicate": "0", "hostname": "127.0.0.1", "port": "7777" } + "kekslistener": { "replicate": "0", "hostname": "::1", "port": "7777" } }, "rpclistener": { "kekslistener": { "replicate": "0", "port": "7777" } diff --git a/icinga/discoverycomponent.cpp b/icinga/discoverycomponent.cpp index 2b09a0705..a4682c2c7 100644 --- a/icinga/discoverycomponent.cpp +++ b/icinga/discoverycomponent.cpp @@ -11,7 +11,7 @@ void DiscoveryComponent::Start(void) { m_DiscoveryEndpoint = make_shared(); m_DiscoveryEndpoint->RegisterMethodHandler("message::Welcome", - bind_weak(&DiscoveryComponent::GetPeersMessageHandler, shared_from_this())); + bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this())); m_DiscoveryEndpoint->RegisterMethodSource("discovery::PeerAvailable"); m_DiscoveryEndpoint->RegisterMethodHandler("discovery::GetPeers", @@ -28,8 +28,34 @@ void DiscoveryComponent::Stop(void) mgr->UnregisterEndpoint(m_DiscoveryEndpoint); } +int DiscoveryComponent::CheckExistingEndpoint(Endpoint::Ptr endpoint, const NewEndpointEventArgs& neea) +{ + if (endpoint == neea.Endpoint) + return 0; + + if (endpoint->GetIdentity() == neea.Endpoint->GetIdentity()) { + Application::Log("Detected duplicate identity (" + endpoint->GetIdentity() + " - Disconnecting endpoint."); + + endpoint->Stop(); + GetEndpointManager()->UnregisterEndpoint(endpoint); + } + + return 0; +} + int DiscoveryComponent::WelcomeMessageHandler(const NewRequestEventArgs& neea) { + if (neea.Sender->GetIdentity() == GetEndpointManager()->GetIdentity()) { + Application::Log("Detected loop-back connection - Disconnecting endpoint."); + + neea.Sender->Stop(); + GetEndpointManager()->UnregisterEndpoint(neea.Sender); + + return 0; + } + + GetEndpointManager()->ForeachEndpoint(bind(&DiscoveryComponent::CheckExistingEndpoint, this, neea.Sender, _1)); + JsonRpcRequest request; request.SetMethod("discovery::GetPeers"); GetEndpointManager()->SendUnicastRequest(m_DiscoveryEndpoint, neea.Sender, request); diff --git a/icinga/discoverycomponent.h b/icinga/discoverycomponent.h index 7d5e65008..c9ba90034 100644 --- a/icinga/discoverycomponent.h +++ b/icinga/discoverycomponent.h @@ -14,6 +14,8 @@ private: int WelcomeMessageHandler(const NewRequestEventArgs& neea); int GetPeersMessageHandler(const NewRequestEventArgs& nrea); + int CheckExistingEndpoint(Endpoint::Ptr endpoint, const NewEndpointEventArgs& neea); + public: virtual string GetName(void) const; virtual void Start(void); diff --git a/icinga/endpoint.h b/icinga/endpoint.h index 1980fdd48..785a24bee 100644 --- a/icinga/endpoint.h +++ b/icinga/endpoint.h @@ -53,6 +53,8 @@ public: virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message) = 0; virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message) = 0; + virtual void Stop(void) = 0; + Event OnNewMethodSink; Event OnNewMethodSource; diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index ae869ea8b..76d094da9 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -2,11 +2,17 @@ using namespace icinga; -EndpointManager::EndpointManager(shared_ptr sslContext) +EndpointManager::EndpointManager(string identity, shared_ptr sslContext) { + m_Identity = identity; m_SSLContext = sslContext; } +string EndpointManager::GetIdentity(void) const +{ + return m_Identity; +} + void EndpointManager::AddListener(unsigned short port) { stringstream s; @@ -160,8 +166,13 @@ void EndpointManager::ForeachEndpoint(function::iterator i = m_Endpoints.begin(); i != m_Endpoints.end(); i++) { - neea.Endpoint = *i; + + list::iterator prev, i; + for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) { + prev = i; + i++; + + neea.Endpoint = *prev; callback(neea); } } diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h index 6a04d9f38..864d31246 100644 --- a/icinga/endpointmanager.h +++ b/icinga/endpointmanager.h @@ -11,7 +11,9 @@ struct I2_ICINGA_API NewEndpointEventArgs : public EventArgs class I2_ICINGA_API EndpointManager : public Object { + string m_Identity; shared_ptr m_SSLContext; + list m_Servers; list m_Endpoints; @@ -27,7 +29,9 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - EndpointManager(shared_ptr sslContext); + EndpointManager(string identity, shared_ptr sslContext); + + string GetIdentity(void) const; void AddListener(unsigned short port); void AddConnection(string host, unsigned short port); diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 2b3ed95b5..ff1408607 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -22,9 +22,14 @@ int IcingaApplication::Main(const vector& args) return EXIT_FAILURE; } + shared_ptr cert = Utility::GetX509Certificate("icinga-c1.crt"); + string identity = Utility::GetCertificateCN(cert); + + Application::Log("My identity: " + identity); + shared_ptr sslContext = Utility::MakeSSLContext("icinga-c1.crt", "icinga-c1.key", "ca.crt"); - m_EndpointManager = make_shared(sslContext); + m_EndpointManager = make_shared(identity, sslContext); string componentDirectory = GetExeDirectory() + "/../lib/icinga"; AddComponentSearchDir(componentDirectory); diff --git a/icinga/jsonrpcendpoint.cpp b/icinga/jsonrpcendpoint.cpp index 0fd58ae0a..1b56009d5 100644 --- a/icinga/jsonrpcendpoint.cpp +++ b/icinga/jsonrpcendpoint.cpp @@ -199,3 +199,11 @@ int JsonRpcEndpoint::VerifyCertificateHandler(const VerifyCertificateEventArgs& return 0; } + +void JsonRpcEndpoint::Stop(void) +{ + if (m_Client) { + m_Client->Close(); + m_Client = JsonRpcClient::Ptr(); + } +} diff --git a/icinga/jsonrpcendpoint.h b/icinga/jsonrpcendpoint.h index b2340386a..b04cb78f3 100644 --- a/icinga/jsonrpcendpoint.h +++ b/icinga/jsonrpcendpoint.h @@ -50,6 +50,8 @@ public: virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message); virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message); + + virtual void Stop(void); }; } diff --git a/icinga/virtualendpoint.cpp b/icinga/virtualendpoint.cpp index b22f2420e..fd43080d2 100644 --- a/icinga/virtualendpoint.cpp +++ b/icinga/virtualendpoint.cpp @@ -83,3 +83,8 @@ bool VirtualEndpoint::IsAllowedMethodSource(string method) const { return true; } + +void VirtualEndpoint::Stop(void) +{ + /* Nothing to do here. */ +} diff --git a/icinga/virtualendpoint.h b/icinga/virtualendpoint.h index e363dd025..7c7cfbe71 100644 --- a/icinga/virtualendpoint.h +++ b/icinga/virtualendpoint.h @@ -38,6 +38,8 @@ public: virtual void ProcessRequest(Endpoint::Ptr sender, const JsonRpcRequest& message); virtual void ProcessResponse(Endpoint::Ptr sender, const JsonRpcResponse& message); + + virtual void Stop(void); }; }