m_SSLContext = sslContext;
}
-X509 *TLSClient::GetClientCertificate(void) const
+void TLSClient::NullCertificateDeleter(X509 *certificate)
{
- return SSL_get_certificate(m_SSL.get());
+ /* Nothing to do here. */
}
-X509 *TLSClient::GetPeerCertificate(void) const
+shared_ptr<X509> TLSClient::GetClientCertificate(void) const
{
- return SSL_get_peer_certificate(m_SSL.get());
+ return shared_ptr<X509>(SSL_get_certificate(m_SSL.get()), &TLSClient::NullCertificateDeleter);
+}
+
+shared_ptr<X509> TLSClient::GetPeerCertificate(void) const
+{
+ return shared_ptr<X509>(SSL_get_peer_certificate(m_SSL.get()), X509_free);
}
void TLSClient::Start(void)
m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
if (!m_SSL)
- ; /* TODO: deal with error */
+ throw OpenSSLException("SSL_new failed", ERR_get_error());
if (!GetClientCertificate())
throw InvalidArgumentException("No X509 client certificate was specified.");
vcea.Source = client->shared_from_this();
vcea.ValidCertificate = (ok != 0);
vcea.Context = x509Context;
+ vcea.Certificate = shared_ptr<X509>(x509Context->cert, &TLSClient::NullCertificateDeleter);
client->OnVerifyCertificate(vcea);
return (int)vcea.ValidCertificate;
{
bool ValidCertificate;
X509_STORE_CTX *Context;
+ shared_ptr<X509> Certificate;
};
class I2_BASE_API TLSClient : public TCPClient
virtual void CloseInternal(bool from_dtor);
+ static void NullCertificateDeleter(X509 *certificate);
+
static int SSLVerifyCertificate(int ok, X509_STORE_CTX *x509Context);
protected:
public:
TLSClient(TCPClientRole role, shared_ptr<SSL_CTX> sslContext);
- X509 *GetClientCertificate(void) const;
- X509 *GetPeerCertificate(void) const;
+ shared_ptr<X509> GetClientCertificate(void) const;
+ shared_ptr<X509> GetPeerCertificate(void) const;
virtual void Start(void);
return sslContext;
}
+
+string Utility::GetCertificateCN(const shared_ptr<X509>& certificate)
+{
+ char buffer[256];
+
+ int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()), NID_commonName, buffer, sizeof(buffer));
+
+ if (rc == -1)
+ throw InvalidArgumentException("X509 certificate has no CN attribute.");
+
+ return buffer;
+}
static void Daemonize(void);
static shared_ptr<SSL_CTX> MakeSSLContext(string pubkey, string privkey, string cakey);
+ static string GetCertificateCN(const shared_ptr<X509>& certificate);
};
}
long configSource;
if (GetConfig()->GetPropertyInteger("configSource", &configSource) && configSource != 0) {
- m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects", bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this()));
+ m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects",
+ bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this()));
configHive->OnObjectCreated += bind_weak(&ConfigRpcComponent::LocalObjectCreatedHandler, shared_from_this());
configHive->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this());
m_ConfigRpcEndpoint->RegisterMethodSource("config::PropertyChanged");
}
- m_ConfigRpcEndpoint->RegisterMethodHandler("auth::Welcome", bind_weak(&ConfigRpcComponent::WelcomeMessageHandler, shared_from_this()));
-
- m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCreated", bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
- m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved", bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this()));
- m_ConfigRpcEndpoint->RegisterMethodHandler("config::PropertyChanged", bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
+ m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCreated",
+ bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
+ m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved",
+ bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this()));
+ m_ConfigRpcEndpoint->RegisterMethodHandler("config::PropertyChanged",
+ bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint);
int ConfigRpcComponent::NewEndpointHandler(const NewEndpointEventArgs& ea)
{
- if (ea.Endpoint->HasIdentity()) {
- JsonRpcRequest request;
- request.SetMethod("config::FetchObjects");
-
- GetEndpointManager()->SendUnicastRequest(m_ConfigRpcEndpoint, ea.Endpoint, request);
- }
+ ea.Endpoint->OnSessionEstablished += bind_weak(&ConfigRpcComponent::SessionEstablishedHandler, shared_from_this());
return 0;
}
-int ConfigRpcComponent::WelcomeMessageHandler(const NewRequestEventArgs& ea)
+int ConfigRpcComponent::SessionEstablishedHandler(const EventArgs& ea)
{
- NewEndpointEventArgs neea;
- neea.Source = shared_from_this();
- neea.Endpoint = ea.Sender;
- NewEndpointHandler(neea);
+ JsonRpcRequest request;
+ request.SetMethod("config::FetchObjects");
+
+ Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(ea.Source);
+ GetEndpointManager()->SendUnicastRequest(m_ConfigRpcEndpoint, endpoint, request);
return 0;
}
VirtualEndpoint::Ptr m_ConfigRpcEndpoint;
int NewEndpointHandler(const NewEndpointEventArgs& ea);
- int WelcomeMessageHandler(const NewRequestEventArgs& ea);
+ int SessionEstablishedHandler(const EventArgs& ea);
int LocalObjectCreatedHandler(const EventArgs& ea);
int LocalObjectRemovedHandler(const EventArgs& ea);
+++ /dev/null
-#include "i2-icinga.h"
-
-using namespace icinga;
-
-string AuthenticationComponent::GetName(void) const
-{
- return "authenticationcomponent";
-}
-
-void AuthenticationComponent::Start(void)
-{
- m_AuthenticationEndpoint = make_shared<VirtualEndpoint>();
- m_AuthenticationEndpoint->RegisterMethodHandler("auth::SetIdentity", bind_weak(&AuthenticationComponent::IdentityMessageHandler, shared_from_this()));
- m_AuthenticationEndpoint->RegisterMethodSource("auth::Welcome");
-
- EndpointManager::Ptr mgr = GetEndpointManager();
- mgr->OnNewEndpoint += bind_weak(&AuthenticationComponent::NewEndpointHandler, shared_from_this());
- mgr->ForeachEndpoint(bind(&AuthenticationComponent::NewEndpointHandler, this, _1));
- mgr->RegisterEndpoint(m_AuthenticationEndpoint);
-}
-
-void AuthenticationComponent::Stop(void)
-{
- EndpointManager::Ptr mgr = GetEndpointManager();
-
- if (mgr)
- mgr->UnregisterEndpoint(m_AuthenticationEndpoint);
-}
-
-int AuthenticationComponent::NewEndpointHandler(const NewEndpointEventArgs& neea)
-{
- if (neea.Endpoint->IsLocal() || neea.Endpoint->HasIdentity())
- return 0;
-
- neea.Endpoint->AddAllowedMethodSinkPrefix("auth::");
- neea.Endpoint->AddAllowedMethodSourcePrefix("auth::");
-
- neea.Endpoint->RegisterMethodSink("auth::SetIdentity");
-
- JsonRpcRequest request;
- request.SetMethod("auth::SetIdentity");
-
- IdentityMessage params;
- params.SetIdentity("keks");
- request.SetParams(params);
-
- GetEndpointManager()->SendUnicastRequest(m_AuthenticationEndpoint, neea.Endpoint, request);
-
- return 0;
-}
-
-int AuthenticationComponent::IdentityMessageHandler(const NewRequestEventArgs& nrea)
-{
- Message params;
- if (!nrea.Request.GetParams(¶ms))
- return 0;
-
- IdentityMessage identityMessage = params;
-
- string identity;
- if (!identityMessage.GetIdentity(&identity))
- return 0;
-
- nrea.Sender->SetIdentity(identity);
-
- /* there's no authentication for now, just tell them it's ok to send messages */
- JsonRpcRequest request;
- request.SetMethod("auth::Welcome");
-
- GetEndpointManager()->SendUnicastRequest(m_AuthenticationEndpoint, nrea.Sender, request);
-
- return 0;
-}
+++ /dev/null
-#ifndef AUTHENTICATIONCOMPONENT_H
-#define AUTHENTICATIONCOMPONENT_H
-
-namespace icinga
-{
-
-class AuthenticationComponent : public IcingaComponent
-{
-private:
- VirtualEndpoint::Ptr m_AuthenticationEndpoint;
-
- int NewEndpointHandler(const NewEndpointEventArgs& neea);
- int IdentityMessageHandler(const NewRequestEventArgs& nrea);
-
-public:
- virtual string GetName(void) const;
- virtual void Start(void);
- virtual void Stop(void);
-};
-
-}
-
-#endif /* AUTHENTICATIONCOMPONENT_H */
{
m_DiscoveryEndpoint = make_shared<VirtualEndpoint>();
m_DiscoveryEndpoint->RegisterMethodSource("discovery::PeerAvailable");
- m_DiscoveryEndpoint->RegisterMethodHandler("auth::Welcome",
- bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this()));
m_DiscoveryEndpoint->RegisterMethodHandler("discovery::GetPeers",
bind_weak(&DiscoveryComponent::GetPeersMessageHandler, shared_from_this()));
int DiscoveryComponent::NewEndpointHandler(const NewEndpointEventArgs& neea)
{
- neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::IdentityChangedHandler, shared_from_this());
+ neea.Endpoint->OnSessionEstablished += bind_weak(&DiscoveryComponent::SessionEstablishedHandler, shared_from_this());
/* TODO: register handler for new sink/source */
return 0;
}
-int DiscoveryComponent::IdentityChangedHandler(const EventArgs& neea)
-{
- /* TODO: send information about this client to all other clients */
-
- return 0;
-}
-
-int DiscoveryComponent::WelcomeMessageHandler(const NewRequestEventArgs& nrea)
+int DiscoveryComponent::SessionEstablishedHandler(const EventArgs& neea)
{
JsonRpcRequest request;
request.SetMethod("discovery::GetPeers");
- GetEndpointManager()->SendUnicastRequest(m_DiscoveryEndpoint, nrea.Sender, request);
+ Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(neea.Source);
+ GetEndpointManager()->SendUnicastRequest(m_DiscoveryEndpoint, endpoint, request);
+
+ /* TODO: send information about this client to all other clients */
return 0;
}
IcingaApplication::Ptr GetIcingaApplication(void) const;
int NewEndpointHandler(const NewEndpointEventArgs& neea);
- int IdentityChangedHandler(const EventArgs& neea);
- int WelcomeMessageHandler(const NewRequestEventArgs& nrea);
+ int SessionEstablishedHandler(const EventArgs& neea);
int GetPeersMessageHandler(const NewRequestEventArgs& nrea);
public:
EventArgs ea;
ea.Source = shared_from_this();
OnIdentityChanged(ea);
+
+ OnSessionEstablished(ea);
}
bool Endpoint::HasIdentity(void) const
int CountMethodSources(void) const;
Event<EventArgs> OnIdentityChanged;
+ Event<EventArgs> OnSessionEstablished;
};
}
#include "icingacomponent.h"
#include "subscriptioncomponent.h"
#include "subscriptionmessage.h"
-#include "authenticationcomponent.h"
#include "identitymessage.h"
#include "discoverycomponent.h"
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="authenticationcomponent.cpp" />
<ClCompile Include="discoverycomponent.cpp" />
<ClCompile Include="endpoint.cpp" />
<ClCompile Include="endpointmanager.cpp" />
<ClCompile Include="virtualendpoint.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="authenticationcomponent.h" />
<ClInclude Include="discoverycomponent.h" />
<ClInclude Include="endpoint.h" />
<ClInclude Include="endpointmanager.h" />
connectionCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedRpcConnectionHandler, shared_from_this());
- AuthenticationComponent::Ptr authenticationComponent = make_shared<AuthenticationComponent>();
- RegisterComponent(authenticationComponent);
-
SubscriptionComponent::Ptr subscriptionComponent = make_shared<SubscriptionComponent>();
RegisterComponent(subscriptionComponent);
client->OnNewMessage += bind_weak(&JsonRpcEndpoint::NewMessageHandler, shared_from_this());
client->OnClosed += bind_weak(&JsonRpcEndpoint::ClientClosedHandler, shared_from_this());
client->OnError += bind_weak(&JsonRpcEndpoint::ClientErrorHandler, shared_from_this());
+ client->OnVerifyCertificate += bind_weak(&JsonRpcEndpoint::VerifyCertificateHandler, shared_from_this());
}
bool JsonRpcEndpoint::IsLocal(void) const
return 0;
}
+
+int JsonRpcEndpoint::VerifyCertificateHandler(const VerifyCertificateEventArgs& ea)
+{
+ if (ea.Certificate && ea.ValidCertificate)
+ SetIdentity(Utility::GetCertificateCN(ea.Certificate));
+
+ return 0;
+}
int ClientClosedHandler(const EventArgs& ea);
int ClientErrorHandler(const SocketErrorEventArgs& ea);
int ClientReconnectHandler(const TimerEventArgs& ea);
+ int VerifyCertificateHandler(const VerifyCertificateEventArgs& ea);
public:
typedef shared_ptr<JsonRpcEndpoint> Ptr;