From 21ef4836ee49ce5b9f398644ef088275202f8b03 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 24 Apr 2012 14:02:15 +0200 Subject: [PATCH] Implement SSL support. --- base/application.cpp | 128 ++++++++++++++++++++++++++++++++++- base/base.vcxproj | 6 +- base/component.cpp | 28 ++++++++ base/condvar.cpp | 36 +++++++++- base/configcollection.cpp | 48 ++++++++++++- base/configcollection.h | 3 +- base/confighive.cpp | 43 +++++++++++- base/confighive.h | 1 + base/configobject.cpp | 73 ++++++++++++++++++++ base/i2-base.h | 5 ++ base/object.h | 13 ---- base/socket.cpp | 6 +- base/socket.h | 2 +- base/tcpclient.cpp | 15 +++- base/tcpclient.h | 18 ++++- base/tcpserver.cpp | 6 +- base/tcpserver.h | 6 +- base/tlsclient.cpp | 119 ++++++++++++++++++++++++++++++++ base/tlsclient.h | 41 +++++++++++ base/utility.cpp | 34 ++++++++++ base/utility.h | 6 ++ icinga-app/ca.crt | 17 +++++ icinga-app/ca.key | 16 +++++ icinga-app/icinga-c1.crt | 17 +++++ icinga-app/icinga-c1.key | 16 +++++ icinga-app/icinga-c2.crt | 17 +++++ icinga-app/icinga-c2.key | 16 +++++ icinga/endpointmanager.cpp | 9 ++- icinga/endpointmanager.h | 3 + icinga/icingaapplication.cpp | 9 ++- icinga/icingaapplication.h | 2 - icinga/jsonrpcendpoint.cpp | 4 +- icinga/jsonrpcendpoint.h | 4 +- jsonrpc/jsonrpcclient.cpp | 10 ++- jsonrpc/jsonrpcclient.h | 6 +- jsonrpc/jsonrpcserver.cpp | 4 +- jsonrpc/jsonrpcserver.h | 2 +- 37 files changed, 735 insertions(+), 54 deletions(-) create mode 100644 base/tlsclient.cpp create mode 100644 base/tlsclient.h create mode 100644 icinga-app/ca.crt create mode 100644 icinga-app/ca.key create mode 100644 icinga-app/icinga-c1.crt create mode 100644 icinga-app/icinga-c1.key create mode 100644 icinga-app/icinga-c2.crt create mode 100644 icinga-app/icinga-c2.key diff --git a/base/application.cpp b/base/application.cpp index def10cce6..945ee7c0b 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -8,6 +8,11 @@ using namespace icinga; Application::Ptr I2_EXPORT Application::Instance; +/** + * Application + * + * Constructor for the Application class. + */ Application::Application(void) { #ifdef _WIN32 @@ -29,8 +34,14 @@ Application::Application(void) m_ConfigHive = make_shared(); } +/** + * ~Application + * + * Destructor for the application class. + */ Application::~Application(void) { + /* stop all components */ for (map::iterator i = m_Components.begin(); i != m_Components.end(); i++) { i->second->Stop(); @@ -45,6 +56,11 @@ Application::~Application(void) #endif /* _WIN32 */ } +/** + * RunEventLoop + * + * Processes events (e.g. sockets and timers). + */ void Application::RunEventLoop(void) { while (!m_ShuttingDown) { @@ -141,16 +157,38 @@ void Application::RunEventLoop(void) } } +/** + * Shutdown + * + * Signals the application to shut down during the next + * execution of the event loop. + */ void Application::Shutdown(void) { m_ShuttingDown = true; } +/** + * GetConfigHive + * + * Returns the application's configuration hive. + * + * @returns The config hive. + */ ConfigHive::Ptr Application::GetConfigHive(void) const { return m_ConfigHive; } +/** + * LoadComponent + * + * Loads a component from a library. + * + * @param path The path of the component library. + * @param componentConfig The configuration for the component. + * @returns The component. + */ Component::Ptr Application::LoadComponent(const string& path, const ConfigObject::Ptr& componentConfig) { @@ -186,6 +224,13 @@ Component::Ptr Application::LoadComponent(const string& path, return component; } +/** + * RegisterComponent + * + * Registers a component object and starts it. + * + * @param component The component. + */ void Application::RegisterComponent(Component::Ptr component) { component->SetApplication(static_pointer_cast(shared_from_this())); @@ -194,18 +239,33 @@ void Application::RegisterComponent(Component::Ptr component) component->Start(); } +/** + * UnregisterComponent + * + * Unregisters a component object and stops it. + * + * @param component The component. + */ void Application::UnregisterComponent(Component::Ptr component) { string name = component->GetName(); Log("Unloading component '%s'", name.c_str()); map::iterator i = m_Components.find(name); - if (i != m_Components.end()) { + if (i != m_Components.end()) m_Components.erase(i); - component->Stop(); - } + + component->Stop(); } +/** + * GetComponent + * + * Finds a loaded component by name. + * + * @param name The name of the component. + * @returns The component or a null pointer if the component could not be found. + */ Component::Ptr Application::GetComponent(const string& name) { map::iterator ci = m_Components.find(name); @@ -216,6 +276,14 @@ Component::Ptr Application::GetComponent(const string& name) return ci->second; } +/** + * Log + * + * Logs a message. + * + * @param format The format string. + * @param ... Additional parameters for the format string. + */ void Application::Log(const char *format, ...) { char message[512]; @@ -229,16 +297,37 @@ void Application::Log(const char *format, ...) fprintf(stderr, "%s\n", message); } +/** + * SetArguments + * + * Sets the application's arguments. + * + * @param arguments The arguments. + */ void Application::SetArguments(const vector& arguments) { m_Arguments = arguments; } +/** + * GetArguments + * + * Retrieves the application's arguments. + * + * @returns The arguments. + */ const vector& Application::GetArguments(void) const { return m_Arguments; } +/** + * GetExeDirectory + * + * Retrieves the directory the application's binary is contained in. + * + * @returns The directory. + */ string Application::GetExeDirectory(void) const { static string ExePath; @@ -314,6 +403,13 @@ string Application::GetExeDirectory(void) const return ExePath; } +/** + * AddComponentSearchDir + * + * Adds a directory to the component search path. + * + * @param componentDirectory The directory. + */ void Application::AddComponentSearchDir(const string& componentDirectory) { #ifdef _WIN32 @@ -323,14 +419,30 @@ void Application::AddComponentSearchDir(const string& componentDirectory) #endif /* _WIN32 */ } +/** + * IsDebugging + * + * Retrieves the debugging mode of the application. + * + * @returns true if the application is being debugged, false otherwise + */ bool Application::IsDebugging(void) const { return m_Debugging; } #ifndef _WIN32 +/** + * ApplicationSigIntHandler + * + * Signal handler for SIGINT. + * + * @param signum The signal number. + */ static void ApplicationSigIntHandler(int signum) { + assert(signum == SIGINT); + Application::Instance->Shutdown(); struct sigaction sa; @@ -340,6 +452,16 @@ static void ApplicationSigIntHandler(int signum) } #endif /* _WIN32 */ +/** + * RunApplication + * + * Runs the specified application. + * + * @param argc The number of arguments. + * @param argv The arguments that should be passed to the application. + * @param instance The application instance. + * @returns The application's exit code. + */ int icinga::RunApplication(int argc, char **argv, Application *instance) { int result; diff --git a/base/base.vcxproj b/base/base.vcxproj index 964475906..50b13abfa 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -29,6 +29,7 @@ + @@ -56,6 +57,7 @@ + @@ -103,7 +105,7 @@ Windows true - ws2_32.lib;shlwapi.lib;%(AdditionalDependencies) + ws2_32.lib;shlwapi.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies) ws2_32.lib;shlwapi.lib @@ -125,7 +127,7 @@ true true true - ws2_32.lib;shlwapi.lib;%(AdditionalDependencies) + ws2_32.lib;shlwapi.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies) ws2_32.lib;shlwapi.lib diff --git a/base/component.cpp b/base/component.cpp index 4c37bda00..8f06cf391 100644 --- a/base/component.cpp +++ b/base/component.cpp @@ -2,21 +2,49 @@ using namespace icinga; +/** + * SetApplication + * + * Sets the application this component belongs to. + * + * @param application The application. + */ void Component::SetApplication(const Application::WeakPtr& application) { m_Application = application; } +/** + * GetApplication + * + * Retrieves the application this component belongs to. + * + * @returns The application. + */ Application::Ptr Component::GetApplication(void) const { return m_Application.lock(); } +/** + * SetConfig + * + * Sets the configuration for this component. + * + * @param componentConfig The configuration. + */ void Component::SetConfig(const ConfigObject::Ptr& componentConfig) { m_Config = componentConfig; } +/** + * GetConfig + * + * Retrieves the configuration for this component. + * + * @returns The configuration. + */ ConfigObject::Ptr Component::GetConfig(void) const { return m_Config; diff --git a/base/condvar.cpp b/base/condvar.cpp index c0c479c4a..ccc744940 100644 --- a/base/condvar.cpp +++ b/base/condvar.cpp @@ -2,6 +2,11 @@ using namespace icinga; +/** + * CondVar + * + * Constructor for the CondVar class. + */ CondVar::CondVar(void) { #ifdef _WIN32 @@ -11,6 +16,11 @@ CondVar::CondVar(void) #endif /* _WIN32 */ } +/** + * ~CondVar + * + * Destructor for the CondVar class. + */ CondVar::~CondVar(void) { #ifdef _WIN32 @@ -20,6 +30,14 @@ CondVar::~CondVar(void) #endif /* _WIN32 */ } +/** + * Wait + * + * Waits for the condition variable to be signaled. Releases the specified mutex + * before it begins to wait and re-acquires the mutex after waiting. + * + * @param mtx The mutex that should be released during waiting. + */ void CondVar::Wait(Mutex& mtx) { #ifdef _WIN32 @@ -29,6 +47,11 @@ void CondVar::Wait(Mutex& mtx) #endif /* _WIN32 */ } +/** + * Signal + * + * Wakes up at least one waiting thread. + */ void CondVar::Signal(void) { #ifdef _WIN32 @@ -38,6 +61,11 @@ void CondVar::Signal(void) #endif /* _WIN32 */ } +/** + * Broadcast + * + * Wakes up all waiting threads. + */ void CondVar::Broadcast(void) { #ifdef _WIN32 @@ -47,7 +75,13 @@ void CondVar::Broadcast(void) #endif /* _WIN32 */ } - +/** + * Get + * + * Retrieves the platform-specific condition variable handle. + * + * @returns The platform-specific condition variable handle. + */ #ifdef _WIN32 CONDITION_VARIABLE *CondVar::Get(void) #else /* _WIN32 */ diff --git a/base/configcollection.cpp b/base/configcollection.cpp index aecca6de1..a4c0d640d 100644 --- a/base/configcollection.cpp +++ b/base/configcollection.cpp @@ -2,16 +2,37 @@ using namespace icinga; +/** + * SetHive + * + * Sets the hive this collection belongs to. + * + * @param hive The hive. + */ void ConfigCollection::SetHive(const ConfigHive::WeakPtr& hive) { m_Hive = hive; } +/** + * GetHive + * + * Retrieves the hive this collection belongs to. + * + * @returns The hive. + */ ConfigHive::WeakPtr ConfigCollection::GetHive(void) const { return m_Hive; } +/** + * AddObject + * + * Adds a new object to this collection. + * + * @param object The new object. + */ void ConfigCollection::AddObject(const ConfigObject::Ptr& object) { RemoveObject(object); @@ -27,6 +48,13 @@ void ConfigCollection::AddObject(const ConfigObject::Ptr& object) hive->OnObjectCreated(ea); } +/** + * RemoveObject + * + * Removes an object from this collection + * + * @param object The object that is to be removed. + */ void ConfigCollection::RemoveObject(const ConfigObject::Ptr& object) { ObjectIterator oi = Objects.find(object->GetName()); @@ -44,9 +72,18 @@ void ConfigCollection::RemoveObject(const ConfigObject::Ptr& object) } } -ConfigObject::Ptr ConfigCollection::GetObject(const string& name) +/** + * GetObject + * + * Retrieves an object by name. + * + * @param name The name of the object. + * @returns The object or a null pointer if the specified object + * could not be found. + */ +ConfigObject::Ptr ConfigCollection::GetObject(const string& name) const { - ObjectIterator oi = Objects.find(name); + ObjectConstIterator oi = Objects.find(name); if (oi == Objects.end()) return ConfigObject::Ptr(); @@ -54,6 +91,13 @@ ConfigObject::Ptr ConfigCollection::GetObject(const string& name) return oi->second; } +/** + * ForEachObject + * + * Invokes the specified callback for each object contained in this collection. + * + * @param callback The callback. + */ void ConfigCollection::ForEachObject(function callback) { EventArgs ea; diff --git a/base/configcollection.h b/base/configcollection.h index dd9658c2f..6dc1a66ba 100644 --- a/base/configcollection.h +++ b/base/configcollection.h @@ -16,6 +16,7 @@ public: typedef weak_ptr WeakPtr; typedef map::iterator ObjectIterator; + typedef map::const_iterator ObjectConstIterator; map Objects; void SetHive(const weak_ptr& hive); @@ -23,7 +24,7 @@ public: void AddObject(const ConfigObject::Ptr& object); void RemoveObject(const ConfigObject::Ptr& object); - ConfigObject::Ptr GetObject(const string& name = string()); + ConfigObject::Ptr GetObject(const string& name = string()) const; void ForEachObject(function callback); diff --git a/base/confighive.cpp b/base/confighive.cpp index b51c15d8c..b077b6ac1 100644 --- a/base/confighive.cpp +++ b/base/confighive.cpp @@ -2,25 +2,59 @@ using namespace icinga; +/** + * AddObject + * + * Adds a new object to this hive. + * + * @param object The new object. + */ void ConfigHive::AddObject(const ConfigObject::Ptr& object) { object->SetHive(static_pointer_cast(shared_from_this())); GetCollection(object->GetType())->AddObject(object); } +/** + * RemoveObject + * + * Removes an object from this hive. + * + * @param object The object that is to be removed. + */ void ConfigHive::RemoveObject(const ConfigObject::Ptr& object) { GetCollection(object->GetType())->RemoveObject(object); } +/** + * GetObject + * + * Retrieves an object by type and name. + * + * @param type The type of the object. + * @param name The name of the object. + * @returns The object or a null pointer if the specified object + * could not be found. + */ ConfigObject::Ptr ConfigHive::GetObject(const string& type, const string& name) { return GetCollection(type)->GetObject(name); } +/** + * GetCollection + * + * Retrieves a collection by name. Creates an empty collection + * if the collection doesn't already exist. + * + * @param collection The name of the collection. + * @returns The collection or a null pointer if the specified collection + * could not be found. + */ ConfigCollection::Ptr ConfigHive::GetCollection(const string& collection) { - CollectionIterator ci = Collections.find(collection); + CollectionConstIterator ci = Collections.find(collection); if (ci == Collections.end()) { Collections[collection] = make_shared(); @@ -30,6 +64,13 @@ ConfigCollection::Ptr ConfigHive::GetCollection(const string& collection) return ci->second; } +/** + * ForEachObject + * + * Invokes the specified callback for each object contained in this hive. + * + * @param callback The callback. + */ void ConfigHive::ForEachObject(const string& type, function callback) { diff --git a/base/confighive.h b/base/confighive.h index e5b3bfb6d..52701ebfe 100644 --- a/base/confighive.h +++ b/base/confighive.h @@ -11,6 +11,7 @@ public: typedef weak_ptr WeakPtr; typedef map::iterator CollectionIterator; + typedef map::const_iterator CollectionConstIterator; map Collections; void AddObject(const ConfigObject::Ptr& object); diff --git a/base/configobject.cpp b/base/configobject.cpp index 2999a6aa9..2189348fe 100644 --- a/base/configobject.cpp +++ b/base/configobject.cpp @@ -2,6 +2,14 @@ using namespace icinga; +/** + * ConfigObject + * + * Constructor for the ConfigObject class. + * + * @param type The type of the object. + * @param name The name of the object. + */ ConfigObject::ConfigObject(const string& type, const string& name) { m_Type = type; @@ -9,6 +17,13 @@ ConfigObject::ConfigObject(const string& type, const string& name) m_Replicated = false; } +/** + * SetHive + * + * Sets the hive this object belongs to. + * + * @param hive The hive. + */ void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) { if (m_Hive.lock()) @@ -18,41 +33,99 @@ void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive) OnPropertyChanged += bind_weak(&ConfigObject::PropertyChangedHandler, shared_from_this()); } +/** + * GetHive + * + * Retrieves the hive this object belongs to. + * + * @returns The hive. + */ ConfigHive::WeakPtr ConfigObject::GetHive(void) const { return m_Hive; } +/** + * SetName + * + * Sets the name of this object. + * + * @param name The name. + */ void ConfigObject::SetName(const string& name) { m_Name = name; } +/** + * GetName + * + * Retrieves the name of this object. + * + * @returns The name. + */ string ConfigObject::GetName(void) const { return m_Name; } +/** + * SetType + * + * Sets the type of this object. + * + * @param type The type. + */ void ConfigObject::SetType(const string& type) { m_Type = type; } +/** + * GetType + * + * Retrieves the type of this object. + * + * @returns The type. + */ string ConfigObject::GetType(void) const { return m_Type; } +/** + * SetReplicated + * + * Sets whether this object was replicated. + * + * @param replicated Whether this object was replicated. + */ void ConfigObject::SetReplicated(bool replicated) { m_Replicated = replicated; } +/** + * GetReplicated + * + * Retrieves whether this object was replicated. + * + * @returns Whether this object was replicated. + */ bool ConfigObject::GetReplicated(void) const { return m_Replicated; } +/** + * PropertyChangedHandler + * + * Handles changed properties by propagating them to the hive + * and collection this object is contained in. + * + * @param dpcea The event arguments. + * @returns 0. + */ int ConfigObject::PropertyChangedHandler(const PropertyChangedEventArgs& dpcea) { ConfigHive::Ptr hive = m_Hive.lock(); diff --git a/base/i2-base.h b/base/i2-base.h index 96dcbb6b8..16388deb0 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -26,6 +26,10 @@ #include #include +#include +#include +#include + #ifdef HAVE_GCC_ABI_DEMANGLE # include #endif /* HAVE_GCC_ABI_DEMANGLE */ @@ -81,6 +85,7 @@ using namespace std::tr1::placeholders; #include "tcpsocket.h" #include "tcpclient.h" #include "tcpserver.h" +#include "tlsclient.h" #include "configobject.h" #include "configcollection.h" #include "confighive.h" diff --git a/base/object.h b/base/object.h index cfb5e15f5..f250d769b 100644 --- a/base/object.h +++ b/base/object.h @@ -44,19 +44,6 @@ public: } }; -typedef function factory_function; - -/** - * factory - * - * Returns a new object of type T. - */ -template -Object::Ptr factory(void) -{ - return make_shared(); -} - } #endif /* OBJECT_H */ diff --git a/base/socket.cpp b/base/socket.cpp index 77b497ff7..7e3770eda 100644 --- a/base/socket.cpp +++ b/base/socket.cpp @@ -11,7 +11,7 @@ Socket::Socket(void) Socket::~Socket(void) { - Close(true); + CloseInternal(true); } void Socket::Start(void) @@ -45,10 +45,10 @@ SOCKET Socket::GetFD(void) const void Socket::Close(void) { - Close(false); + CloseInternal(false); } -void Socket::Close(bool from_dtor) +void Socket::CloseInternal(bool from_dtor) { if (m_FD != INVALID_SOCKET) { closesocket(m_FD); diff --git a/base/socket.h b/base/socket.h index 9be92459b..1e6aa9881 100644 --- a/base/socket.h +++ b/base/socket.h @@ -23,7 +23,7 @@ protected: Socket(void); void HandleSocketError(void); - void Close(bool from_dtor); + virtual void CloseInternal(bool from_dtor); public: typedef shared_ptr Ptr; diff --git a/base/tcpclient.cpp b/base/tcpclient.cpp index ff057a2f6..7b13db5ce 100644 --- a/base/tcpclient.cpp +++ b/base/tcpclient.cpp @@ -2,14 +2,21 @@ using namespace icinga; -TCPClient::TCPClient(void) +TCPClient::TCPClient(TCPClientRole role) { + m_Role = role; + m_SendQueue = make_shared(); m_RecvQueue = make_shared(); m_PeerPort = 0; } +TCPClientRole TCPClient::GetRole(void) const +{ + return m_Role; +} + void TCPClient::Start(void) { TCPSocket::Start(); @@ -44,6 +51,7 @@ void TCPClient::Connect(const string& hostname, unsigned short port) HandleSocketError(); } + m_Role = RoleOutbound; m_PeerHost = hostname; m_PeerPort = port; } @@ -123,3 +131,8 @@ bool TCPClient::WantsToWrite(void) const { return (m_SendQueue->GetSize() > 0); } + +TCPClient::Ptr icinga::TCPClientFactory(TCPClientRole role) +{ + return make_shared(role); +} diff --git a/base/tcpclient.h b/base/tcpclient.h index bc7ac4cf7..7395e5f3e 100644 --- a/base/tcpclient.h +++ b/base/tcpclient.h @@ -4,23 +4,33 @@ namespace icinga { +enum I2_BASE_API TCPClientRole +{ + RoleInbound, + RoleOutbound +}; + class I2_BASE_API TCPClient : public TCPSocket { private: + TCPClientRole m_Role; + string m_PeerHost; int m_PeerPort; FIFO::Ptr m_SendQueue; FIFO::Ptr m_RecvQueue; - int ReadableEventHandler(const EventArgs& ea); - int WritableEventHandler(const EventArgs& ea); + virtual int ReadableEventHandler(const EventArgs& ea); + virtual int WritableEventHandler(const EventArgs& ea); public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - TCPClient(void); + TCPClient(TCPClientRole role); + + TCPClientRole GetRole(void) const; virtual void Start(void); @@ -38,6 +48,8 @@ public: Event OnDataAvailable; }; +TCPClient::Ptr TCPClientFactory(TCPClientRole role); + } #endif /* TCPCLIENT_H */ diff --git a/base/tcpserver.cpp b/base/tcpserver.cpp index 2f5f03f52..b857c96d0 100644 --- a/base/tcpserver.cpp +++ b/base/tcpserver.cpp @@ -4,15 +4,15 @@ using namespace icinga; TCPServer::TCPServer(void) { - m_ClientFactory = factory; + m_ClientFactory = bind(&TCPClientFactory, RoleInbound); } -void TCPServer::SetClientFactory(factory_function clientFactory) +void TCPServer::SetClientFactory(function clientFactory) { m_ClientFactory = clientFactory; } -factory_function TCPServer::GetFactoryFunction(void) +function TCPServer::GetFactoryFunction(void) const { return m_ClientFactory; } diff --git a/base/tcpserver.h b/base/tcpserver.h index 2641c4501..8f551e40d 100644 --- a/base/tcpserver.h +++ b/base/tcpserver.h @@ -17,7 +17,7 @@ class I2_BASE_API TCPServer : public TCPSocket private: int ReadableEventHandler(const EventArgs& ea); - factory_function m_ClientFactory; + function m_ClientFactory; public: typedef shared_ptr Ptr; @@ -25,8 +25,8 @@ public: TCPServer(void); - void SetClientFactory(factory_function function); - factory_function GetFactoryFunction(void); + void SetClientFactory(function function); + function GetFactoryFunction(void) const; virtual void Start(); diff --git a/base/tlsclient.cpp b/base/tlsclient.cpp new file mode 100644 index 000000000..f749d1397 --- /dev/null +++ b/base/tlsclient.cpp @@ -0,0 +1,119 @@ +#include "i2-base.h" + +using namespace icinga; + +TLSClient::TLSClient(TCPClientRole role, shared_ptr sslContext) : TCPClient(role) +{ + m_SSLContext = sslContext; +} + +shared_ptr TLSClient::GetClientCertificate(void) const +{ + return shared_ptr(SSL_get_certificate(m_SSL.get()), X509_free); +} + +shared_ptr TLSClient::GetPeerCertificate(void) const +{ + return shared_ptr(SSL_get_peer_certificate(m_SSL.get()), X509_free); +} + +void TLSClient::Start(void) +{ + TCPClient::Start(); + + m_SSL = shared_ptr(SSL_new(m_SSLContext.get()), SSL_free); + + if (!m_SSL) + ; /* TODO: deal with error */ + + BIO *bio = BIO_new_socket(GetFD(), 0); + SSL_set_bio(m_SSL.get(), bio, bio); + + if (GetRole() == RoleInbound) + SSL_set_accept_state(m_SSL.get()); + else + SSL_set_connect_state(m_SSL.get()); +} + +int TLSClient::ReadableEventHandler(const EventArgs& ea) +{ + int rc; + + size_t bufferSize = FIFO::BlockSize / 2; + char *buffer = (char *)GetRecvQueue()->GetWriteBuffer(&bufferSize); + rc = SSL_read(m_SSL.get(), buffer, bufferSize); + + if (rc <= 0) { + switch (SSL_get_error(m_SSL.get(), rc)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + return 0; + case SSL_ERROR_ZERO_RETURN: + Close(); + + return 0; + default: + /* TODO: deal with error */ + + return 0; + } + } + + GetRecvQueue()->Write(NULL, rc); + + EventArgs dea; + dea.Source = shared_from_this(); + OnDataAvailable(dea); + + return 0; +} + +int TLSClient::WritableEventHandler(const EventArgs& ea) +{ + int rc; + + rc = SSL_write(m_SSL.get(), (const char *)GetSendQueue()->GetReadBuffer(), GetSendQueue()->GetSize()); + + if (rc <= 0) { + switch (SSL_get_error(m_SSL.get(), rc)) { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + return 0; + case SSL_ERROR_ZERO_RETURN: + Close(); + + return 0; + default: + /* TODO: deal with error */ + + return 0; + } + } + + GetSendQueue()->Read(NULL, rc); + + return 0; +} + +bool TLSClient::WantsToWrite(void) const +{ + if (SSL_want_write(m_SSL.get())) + return true; + + if (SSL_state(m_SSL.get()) != SSL_ST_OK) + return false; + + return TCPClient::WantsToWrite(); +} + +void TLSClient::CloseInternal(bool from_dtor) +{ + SSL_shutdown(m_SSL.get()); + + TCPClient::CloseInternal(from_dtor); +} + +TCPClient::Ptr icinga::TLSClientFactory(TCPClientRole role, shared_ptr sslContext) +{ + return make_shared(role, sslContext); +} diff --git a/base/tlsclient.h b/base/tlsclient.h new file mode 100644 index 000000000..8e28b188f --- /dev/null +++ b/base/tlsclient.h @@ -0,0 +1,41 @@ +#ifndef TLSCLIENT_H +#define TLSCLIENT_H + +namespace icinga +{ + +struct I2_BASE_API VerifyCertificateEventArgs : public EventArgs +{ + bool ValidCertificate; + X509_STORE_CTX *Context; +}; + +class I2_BASE_API TLSClient : public TCPClient +{ +private: + shared_ptr m_SSLContext; + shared_ptr m_SSL; + + virtual int ReadableEventHandler(const EventArgs& ea); + virtual int WritableEventHandler(const EventArgs& ea); + + virtual void CloseInternal(bool from_dtor); + +public: + TLSClient(TCPClientRole role, shared_ptr sslContext); + + shared_ptr GetClientCertificate(void) const; + shared_ptr GetPeerCertificate(void) const; + + virtual void Start(void); + + virtual bool WantsToWrite(void) const; + + Event OnVerifyCertificate; +}; + +TCPClient::Ptr TLSClientFactory(TCPClientRole role, shared_ptr sslContext); + +} + +#endif /* TLSCLIENT_H */ diff --git a/base/utility.cpp b/base/utility.cpp index f1bd7e970..4dd4c7b7a 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -2,6 +2,8 @@ using namespace icinga; +bool I2_EXPORT Utility::m_SSLInitialized = false; + /** * Daemonize * @@ -40,3 +42,35 @@ void Utility::Daemonize(void) { throw PosixException("setsid failed", errno); #endif } + +void Utility::InitializeOpenSSL(void) +{ + if (!m_SSLInitialized) { + SSL_library_init(); + SSL_load_error_strings(); + + m_SSLInitialized = true; + } +} + +shared_ptr Utility::MakeSSLContext(string pubkey, string privkey, string cakey) +{ + InitializeOpenSSL(); + + SSL_METHOD *sslMethod = (SSL_METHOD *)TLSv1_method(); + + shared_ptr sslContext = shared_ptr(SSL_CTX_new(sslMethod), SSL_CTX_free); + + SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.c_str())) + throw InvalidArgumentException("Could not load public X509 key file."); + + if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM)) + throw InvalidArgumentException("Could not load private X509 key file."); + + if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL)) + throw InvalidArgumentException("Could not load public CA key file."); + + return sslContext; +} diff --git a/base/utility.h b/base/utility.h index d4c7f8471..18c310d81 100644 --- a/base/utility.h +++ b/base/utility.h @@ -12,8 +12,12 @@ namespace icinga class I2_BASE_API Utility { private: + static bool m_SSLInitialized; + Utility(void); + static void InitializeOpenSSL(void); + public: /** * GetTypeName @@ -39,6 +43,8 @@ public: } static void Daemonize(void); + + static shared_ptr MakeSSLContext(string pubkey, string privkey, string cakey); }; } diff --git a/icinga-app/ca.crt b/icinga-app/ca.crt new file mode 100644 index 000000000..051a17fa3 --- /dev/null +++ b/icinga-app/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICnjCCAgegAwIBAgIJAOP3gULX9+xgMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMRIwEAYDVQQHDAlOdXJlbWJlcmcxFTAT +BgNVBAoMDE5FVFdBWVMgR21iSDEcMBoGA1UEAwwTSWNpbmdhIFNuYWtlIE9pbCBD +QTAeFw0xMjA0MjQxMTQyMzFaFw0yMjA0MjIxMTQyMzFaMGgxCzAJBgNVBAYTAkRF +MRAwDgYDVQQIDAdCYXZhcmlhMRIwEAYDVQQHDAlOdXJlbWJlcmcxFTATBgNVBAoM +DE5FVFdBWVMgR21iSDEcMBoGA1UEAwwTSWNpbmdhIFNuYWtlIE9pbCBDQTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyxlEqY9AcY0YwpMIsirzy/6o9M29LRa4 +ziHURLugpyTKugtAkS5c2Gyt9lf7gdZBcVZ8KD6cszanQqKlZrl0h74E/S13tDqM +rhR4DHeZssstn5LNK57WYx/vw84bmd6Yq6SeP4geq0JfO+y3Ruu+eePtQSOSzS9F +wGpKyAHo4AcCAwEAAaNQME4wHQYDVR0OBBYEFNVJHVPJNwqEcG51lpqZJWVPaysF +MB8GA1UdIwQYMBaAFNVJHVPJNwqEcG51lpqZJWVPaysFMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADgYEAA1CMZgzQuQAslZ/i6OpFmRzuT/0KAfd6s8n6rf+6 +xRvbgLlop8b8XfhhC/IwwoHU0i86o3vV3ZJjEVcdwTDEwpnyCfhFjhXzNZFqL8Ak +Olqy5HFd/+xysTLbdmhHtBIdOeUK1qz/u9I14A71XWiknjcxHya2Ghxg4yIZVdKh +oTQ= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/icinga-app/ca.key b/icinga-app/ca.key new file mode 100644 index 000000000..852997071 --- /dev/null +++ b/icinga-app/ca.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMsZRKmPQHGNGMKT +CLIq88v+qPTNvS0WuM4h1ES7oKckyroLQJEuXNhsrfZX+4HWQXFWfCg+nLM2p0Ki +pWa5dIe+BP0td7Q6jK4UeAx3mbLLLZ+SzSue1mMf78POG5nemKuknj+IHqtCXzvs +t0brvnnj7UEjks0vRcBqSsgB6OAHAgMBAAECgYBg4Ku06cUGpRQjc/lY604hh1bW +dvD++fCrOs3C/3DRaaZd+hIRbnkRLz4H3M32j9nlkyhkFgGvJqnACk81Yc8oOu86 +Pm7bOdEj8v31qq943NCps5tdKHepXM0Z6A8GjaR2ias39NKxVDacBoFzSDAVArTL +p6dyqLjsW5Y3INeHmQJBAPB6w9iqa31GLXMEMeP5LA4+2p3aHPQ25ptMCUcp/Vc6 +40GOSIlLb8rfE+q1ZacChv94jSNLybR+U9++8DLIxnMCQQDYNORSo57mVSebDr7e +Gx8BDbyC+yAgiAi+qfJRekQ0I+R1SxfkCIBSWNrQ944isn0eRcr7+BWVl/WOrVSk +vccdAkBEwbURU9ib3t7Lzd0941ZXVF1JWL2CjdftexYEBNtsf2fOrJHMv4bdKF8X +cnn4AF782EjyWI75Tk1I4dzniERFAkBKZ9lzvy9+ISwiJq71DOxclnebtATYbThl +NWNZOvSh5QBIhXFRXsOak02qwKc/taFte6Nhl30GIGe3lFse3tjZAkBguOZFeSOO +hIAxMD+QpDUHZRYEjhDtPn3oAkLgBNUdeajffLdt4SmRa26t4QnSAE8kkbadIm6A +z52CJc8G2ALA +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/icinga-app/icinga-c1.crt b/icinga-app/icinga-c1.crt new file mode 100644 index 000000000..02201e448 --- /dev/null +++ b/icinga-app/icinga-c1.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtzCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJERTEQ +MA4GA1UECAwHQmF2YXJpYTESMBAGA1UEBwwJTnVyZW1iZXJnMRUwEwYDVQQKDAxO +RVRXQVlTIEdtYkgxHDAaBgNVBAMME0ljaW5nYSBTbmFrZSBPaWwgQ0EwHhcNMTIw +NDI0MTE0NzQ2WhcNMTMwNDI0MTE0NzQ2WjBeMQswCQYDVQQGEwJERTEQMA4GA1UE +CAwHQmF2YXJpYTESMBAGA1UEBwwJTnVyZW1iZXJnMRUwEwYDVQQKDAxORVRXQVlT +IEdtYkgxEjAQBgNVBAMMCWljaW5nYS1jMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAysHrzHs9WfQR4cEUx2hFZQmbM+Ssi5L63yqnzxEvVQ3GlM+uIceK1Kvx +9EexoUDLhxJOaUmigc6Pcs2mAjcpEwObnzW4pLuMKa7ngGLrnUpmmDXdGoxkCbi7 +CP3s5yC7ZZ6bDiPMhRi/TRvY6+uQf+yew5daA3p87jocgRjhRicCAwEAAaN7MHkw +CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy +dGlmaWNhdGUwHQYDVR0OBBYEFPzsYbQZdbq+pcFJWoenWREW6WhMMB8GA1UdIwQY +MBaAFNVJHVPJNwqEcG51lpqZJWVPaysFMA0GCSqGSIb3DQEBBQUAA4GBAMLP1GJf +0hFdrEpGq+NvxTVx7wD30enAot5x2HLx4HuFohQJz/VZ45v+srrA+HEXbBFXPOd4 +nB2XtcDDidFKTt5E03HBwDGGZvnB3f1KXYi7B50imKrwVVzgp5nGBM4hSzWGovEX +EYofmhk0fQg9qiKQrjwNib/4/b0srwEswfdj +-----END CERTIFICATE----- diff --git a/icinga-app/icinga-c1.key b/icinga-app/icinga-c1.key new file mode 100644 index 000000000..9f28765bb --- /dev/null +++ b/icinga-app/icinga-c1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMrB68x7PVn0EeHB +FMdoRWUJmzPkrIuS+t8qp88RL1UNxpTPriHHitSr8fRHsaFAy4cSTmlJooHOj3LN +pgI3KRMDm581uKS7jCmu54Bi651KZpg13RqMZAm4uwj97Ocgu2Wemw4jzIUYv00b +2OvrkH/snsOXWgN6fO46HIEY4UYnAgMBAAECgYBj/1QOG1HcxXT0REe9OP3QoPY8 +l7FJfQnheqYch7syVYL07aBR5Jnh3ZONCLbgcpZuXWbyonBVWMyCsE4Jla7ZYnBB +plZPMYmzGxEbTM5Bu+PZ0M1NLvdLCRq24IVwTZwBBZ3sr7rVSnAYi2Li0SWQEaCN +P+PbZP1P9i9WiI+VIQJBAPYBfVWNk3gY1V0YuuH9fmYRBg5/B1qy8bYS9FLVIq2z +5r7eI1EypcVtyTx6yMmLuWj4mpNOKv5sxQsHalzRo18CQQDS/qPoDqMkDB9r9XeZ +qS2XQdX6YxzGisqL8vWcZ/Y6YX81qm3Lpp2wEexUXvWXRI5RdguctZFKTVyG/Mic +C9o5AkAEtvKX+SaiXpd4OUkbm6gYfKsJDBYv/s3zF1nnXH5VpeT+M3Op0raqmfgJ +WLEQa8UZ5enQeOcKCTudgn7fWIUxAkEAmXWfXP6YZXVzvR+xt08225aEvTItEbKM +krFJNlLe4aNb1Hp6lO5ALnk6vDq8wSKZqGIFHBtq6vHNZFiix+xO8QJAIZ3pB/Bz +Il8NjZMg8t/1sJdn32Xe9D0lZRtZTKC8zF/78NDFEo9qqE4Sr1CUfqlx18HXOxCO +Vg4lv6+jUj+LmA== +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/icinga-app/icinga-c2.crt b/icinga-app/icinga-c2.crt new file mode 100644 index 000000000..b3aaa1b7d --- /dev/null +++ b/icinga-app/icinga-c2.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtzCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJERTEQ +MA4GA1UECAwHQmF2YXJpYTESMBAGA1UEBwwJTnVyZW1iZXJnMRUwEwYDVQQKDAxO +RVRXQVlTIEdtYkgxHDAaBgNVBAMME0ljaW5nYSBTbmFrZSBPaWwgQ0EwHhcNMTIw +NDI0MTE0NzU1WhcNMTMwNDI0MTE0NzU1WjBeMQswCQYDVQQGEwJERTEQMA4GA1UE +CAwHQmF2YXJpYTESMBAGA1UEBwwJTnVyZW1iZXJnMRUwEwYDVQQKDAxORVRXQVlT +IEdtYkgxEjAQBgNVBAMMCWljaW5nYS1jMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEArOcVui1AWojbPuK/7We9uwIBLaOLfBxQRI3+k6PzzjdtaXT4ijT/DSav +Q5U4wGOLYh0yuSyqS88QX/DsqDGLXnSVs8mT37bioMOw2XinqaNQ6xK4vyi0FYxS +ewI6YOkYi7135NEaSUgd82hk4wFtiIb67T7hkHRc7Aui6FmT/SkCAwEAAaN7MHkw +CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy +dGlmaWNhdGUwHQYDVR0OBBYEFGvpolD5na6L70kNFO1tYGYIwDhqMB8GA1UdIwQY +MBaAFNVJHVPJNwqEcG51lpqZJWVPaysFMA0GCSqGSIb3DQEBBQUAA4GBAIhhjKWw +5JKirNidgG9PuD8x47VsRTkESLlq/pS7KjkE1nWCG9JpR5oVSzx2WXomiaAZ4q2C +WS1z4HD9HF4NbhY+xVBi0Fj/kotuXCCweRo5EVp7Q4fabm1maJemFwMTHGhBLu7a +v4dquYyOk9Dhkwcjajyn+KWceCoUTdI3LB2t +-----END CERTIFICATE----- \ No newline at end of file diff --git a/icinga-app/icinga-c2.key b/icinga-app/icinga-c2.key new file mode 100644 index 000000000..6ddda8609 --- /dev/null +++ b/icinga-app/icinga-c2.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKznFbotQFqI2z7i +v+1nvbsCAS2ji3wcUESN/pOj8843bWl0+Io0/w0mr0OVOMBji2IdMrksqkvPEF/w +7Kgxi150lbPJk9+24qDDsNl4p6mjUOsSuL8otBWMUnsCOmDpGIu9d+TRGklIHfNo +ZOMBbYiG+u0+4ZB0XOwLouhZk/0pAgMBAAECgYEAkbEavslYm7EMRX4dyXcMCaNT +yNgxNcBJ5qpbpJ6XVuGfoSf+Mb8cV0GMl38K1hpLHb6Kujwntz9ghedmEwfEbcw0 +TkSaNz1+7omM+485S2YvXJyR1kO8eEKONVlGuxgO/ItiR+e1J6wMnY5JhctgRH6W +aOqy+5Ua1ATIdiOYrI0CQQDku3CNDOipwDmguBIrlxa+6NsATJRjqFmHqWdu2pYh +KRl3Sypn+LfhdFRbo3licU5a1OqydGmVpRTpQPJO7MoHAkEAwYPQIGZd/60O2LWV +M5eLnwKrrQSfrQ/Lngz0Qko4Yo913Ef2PC2QQ6p9cOt3vMPZDK5znlzQbBCa6cAH +tBvzTwJAT+uaaP5wsRdkS17lomt5XB1aoCEh3Cxvk/JCHL6tpEqLBl6yI4AJJ/KQ +ozBccmQqv5wToWUBm3MB+nph7+fWswJAMKcQQ6UZCvganHeCzJbUXqUQPo7ECoHH +IrSFEMmSRY1mB3z8NoMKG0kZArPgxc/DmUGfBfi12gWOvSgvh6PjVwJBALKECoe5 +nmxhHTFbs4+UCFTzp6BGtSBdr6to0ID7ykZWT6kBX/BHUnoJUEpDtNLXzbek/KeI +ymg0LgRkHoWNpLY= +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index 6e499fed8..1f0d482cc 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -2,6 +2,11 @@ using namespace icinga; +EndpointManager::EndpointManager(shared_ptr sslContext) +{ + m_SSLContext = sslContext; +} + void EndpointManager::SetIdentity(string identity) { m_Identity = identity; @@ -14,7 +19,7 @@ string EndpointManager::GetIdentity(void) const void EndpointManager::AddListener(unsigned short port) { - JsonRpcServer::Ptr server = make_shared(); + JsonRpcServer::Ptr server = make_shared(m_SSLContext); RegisterServer(server); server->MakeSocket(); @@ -26,7 +31,7 @@ void EndpointManager::AddListener(unsigned short port) void EndpointManager::AddConnection(string host, unsigned short port) { JsonRpcEndpoint::Ptr endpoint = make_shared(); - endpoint->Connect(host, port); + endpoint->Connect(host, port, m_SSLContext); RegisterEndpoint(endpoint); } diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h index 34815d735..567a0e001 100644 --- a/icinga/endpointmanager.h +++ b/icinga/endpointmanager.h @@ -11,6 +11,7 @@ struct I2_ICINGA_API NewEndpointEventArgs : public EventArgs class I2_ICINGA_API EndpointManager : public Object { + shared_ptr m_SSLContext; list m_Servers; list m_Endpoints; string m_Identity; @@ -27,6 +28,8 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; + EndpointManager(shared_ptr sslContext); + void SetIdentity(string identity); string GetIdentity(void) const; diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 9a736c1ba..6e7f8ad86 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -9,11 +9,6 @@ using namespace icinga; -IcingaApplication::IcingaApplication(void) -{ - m_EndpointManager = make_shared(); -} - int IcingaApplication::Main(const vector& args) { #ifdef _WIN32 @@ -27,6 +22,10 @@ int IcingaApplication::Main(const vector& args) return EXIT_FAILURE; } + shared_ptr sslContext = Utility::MakeSSLContext("icinga-c1.crt", "icinga-c1.key", "ca.crt"); + + m_EndpointManager = make_shared(sslContext); + string componentDirectory = GetExeDirectory() + "/../lib/icinga"; AddComponentSearchDir(componentDirectory); diff --git a/icinga/icingaapplication.h b/icinga/icingaapplication.h index 3205d6897..6904e3dac 100644 --- a/icinga/icingaapplication.h +++ b/icinga/icingaapplication.h @@ -23,8 +23,6 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - IcingaApplication(void); - int Main(const vector& args); void PrintUsage(const string& programPath); diff --git a/icinga/jsonrpcendpoint.cpp b/icinga/jsonrpcendpoint.cpp index fcff316a4..edb25c8bb 100644 --- a/icinga/jsonrpcendpoint.cpp +++ b/icinga/jsonrpcendpoint.cpp @@ -59,13 +59,13 @@ bool JsonRpcEndpoint::IsAllowedMethodSource(string method) const return false; } -void JsonRpcEndpoint::Connect(string host, unsigned short port) +void JsonRpcEndpoint::Connect(string host, unsigned short port, shared_ptr sslContext) { char portStr[20]; sprintf(portStr, "%d", port); SetAddress("jsonrpc-tcp://" + host + ":" + portStr); - JsonRpcClient::Ptr client = make_shared(); + JsonRpcClient::Ptr client = make_shared(RoleOutbound, sslContext); client->MakeSocket(); client->Connect(host, port); client->Start(); diff --git a/icinga/jsonrpcendpoint.h b/icinga/jsonrpcendpoint.h index 7d6b0a1b8..ac2cfeb1e 100644 --- a/icinga/jsonrpcendpoint.h +++ b/icinga/jsonrpcendpoint.h @@ -7,6 +7,7 @@ namespace icinga class I2_ICINGA_API JsonRpcEndpoint : public Endpoint { private: + shared_ptr m_SSLContext; string m_Address; JsonRpcClient::Ptr m_Client; map m_PendingCalls; @@ -25,7 +26,8 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - void Connect(string host, unsigned short port); + void Connect(string host, unsigned short port, + shared_ptr sslContext); JsonRpcClient::Ptr GetClient(void); void SetClient(JsonRpcClient::Ptr client); diff --git a/jsonrpc/jsonrpcclient.cpp b/jsonrpc/jsonrpcclient.cpp index 10f232ada..8db0a1cb8 100644 --- a/jsonrpc/jsonrpcclient.cpp +++ b/jsonrpc/jsonrpcclient.cpp @@ -2,9 +2,12 @@ using namespace icinga; +JsonRpcClient::JsonRpcClient(TCPClientRole role, shared_ptr sslContext) + : TLSClient(role, sslContext) { } + void JsonRpcClient::Start(void) { - TCPClient::Start(); + TLSClient::Start(); OnDataAvailable += bind_weak(&JsonRpcClient::DataAvailableHandler, shared_from_this()); } @@ -40,3 +43,8 @@ int JsonRpcClient::DataAvailableHandler(const EventArgs& ea) return 0; } + +TCPClient::Ptr icinga::JsonRpcClientFactory(TCPClientRole role, shared_ptr sslContext) +{ + return make_shared(role, sslContext); +} diff --git a/jsonrpc/jsonrpcclient.h b/jsonrpc/jsonrpcclient.h index 2ad6f3431..8bf77dca9 100644 --- a/jsonrpc/jsonrpcclient.h +++ b/jsonrpc/jsonrpcclient.h @@ -12,7 +12,7 @@ struct I2_JSONRPC_API NewMessageEventArgs : public EventArgs icinga::Message Message; }; -class I2_JSONRPC_API JsonRpcClient : public TCPClient +class I2_JSONRPC_API JsonRpcClient : public TLSClient { private: int DataAvailableHandler(const EventArgs& ea); @@ -21,6 +21,8 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; + JsonRpcClient(TCPClientRole role, shared_ptr sslContext); + void SendMessage(const Message& message); virtual void Start(void); @@ -28,6 +30,8 @@ public: Event OnNewMessage; }; +TCPClient::Ptr JsonRpcClientFactory(TCPClientRole role, shared_ptr sslContext); + } #endif /* JSONRPCCLIENT_H */ diff --git a/jsonrpc/jsonrpcserver.cpp b/jsonrpc/jsonrpcserver.cpp index 3acde7f4c..59aecf842 100644 --- a/jsonrpc/jsonrpcserver.cpp +++ b/jsonrpc/jsonrpcserver.cpp @@ -2,7 +2,7 @@ using namespace icinga; -JsonRpcServer::JsonRpcServer(void) +JsonRpcServer::JsonRpcServer(shared_ptr sslContext) { - SetClientFactory(factory); + SetClientFactory(bind(&JsonRpcClientFactory, RoleInbound, sslContext)); } diff --git a/jsonrpc/jsonrpcserver.h b/jsonrpc/jsonrpcserver.h index b7feb4ea8..7614e9807 100644 --- a/jsonrpc/jsonrpcserver.h +++ b/jsonrpc/jsonrpcserver.h @@ -10,7 +10,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - JsonRpcServer(void); + JsonRpcServer(shared_ptr sslContext); }; }