Allow TLS connections with unverified certificates

refs #7244
This commit is contained in:
Gunnar Beutner 2014-10-16 09:01:18 +02:00
parent 408939c9fb
commit 311cce5d41
6 changed files with 45 additions and 11 deletions

View 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.
*

View 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);
};

View 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;

View 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;

View 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) {

View 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;