void TlsStream::Start(void)
{
- m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
-
- m_SSLContext.reset();
-
- if (!m_SSL) {
- BOOST_THROW_EXCEPTION(openssl_error()
- << boost::errinfo_api_function("SSL_new")
- << errinfo_openssl_error(ERR_get_error()));
- }
+ {
+ boost::mutex::scoped_lock lock(m_SSLMutex);
- if (!m_SSL)
- BOOST_THROW_EXCEPTION(std::logic_error("No X509 client certificate was specified."));
+ m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
- if (!m_SSLIndexInitialized) {
- m_SSLIndex = SSL_get_ex_new_index(0, const_cast<char *>("TlsStream"), NULL, NULL, NULL);
- m_SSLIndexInitialized = true;
- }
+ m_SSLContext.reset();
- SSL_set_ex_data(m_SSL.get(), m_SSLIndex, this);
+ if (!m_SSL) {
+ BOOST_THROW_EXCEPTION(openssl_error()
+ << boost::errinfo_api_function("SSL_new")
+ << errinfo_openssl_error(ERR_get_error()));
+ }
- SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ if (!m_SSLIndexInitialized) {
+ m_SSLIndex = SSL_get_ex_new_index(0, const_cast<char *>("TlsStream"), NULL, NULL, NULL);
+ m_SSLIndexInitialized = true;
+ }
- m_BIO = BIO_new_I2Stream(m_InnerStream);
- SSL_set_bio(m_SSL.get(), m_BIO, m_BIO);
+ SSL_set_ex_data(m_SSL.get(), m_SSLIndex, this);
- if (m_Role == TlsRoleServer)
- SSL_set_accept_state(m_SSL.get());
- else
- SSL_set_connect_state(m_SSL.get());
+ SSL_set_verify(m_SSL.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
- /*int rc = SSL_do_handshake(m_SSL.get());
+ m_BIO = BIO_new_I2Stream(m_InnerStream);
+ SSL_set_bio(m_SSL.get(), m_BIO, m_BIO);
- if (rc == 1) {
- SetConnected(true);
- OnConnected(GetSelf());
- }*/
+ if (m_Role == TlsRoleServer)
+ SSL_set_accept_state(m_SSL.get());
+ else
+ SSL_set_connect_state(m_SSL.get());
+ }
Stream::Start();
*/
shared_ptr<X509> TlsStream::GetClientCertificate(void) const
{
- ObjectLock olock(this);
+ boost::mutex::scoped_lock lock(m_SSLMutex);
return shared_ptr<X509>(SSL_get_certificate(m_SSL.get()), &Utility::NullDeleter);
}
*/
shared_ptr<X509> TlsStream::GetPeerCertificate(void) const
{
- ObjectLock olock(this);
+ boost::mutex::scoped_lock lock(m_SSLMutex);
return shared_ptr<X509>(SSL_get_peer_certificate(m_SSL.get()), X509_free);
}
void TlsStream::HandleIO(void)
{
ASSERT(!OwnsLock());
- ObjectLock olock(this);
char data[16 * 1024];
int rc;
if (!IsConnected()) {
+ boost::mutex::scoped_lock lock(m_SSLMutex);
+
rc = SSL_do_handshake(m_SSL.get());
if (rc == 1) {
+ lock.unlock();
+
SetConnected(true);
} else {
switch (SSL_get_error(m_SSL.get(), rc)) {
bool new_data = false, read_ok = true;
while (read_ok) {
+ boost::mutex::scoped_lock lock(m_SSLMutex);
+
rc = SSL_read(m_SSL.get(), data, sizeof(data));
if (rc > 0) {
+ lock.unlock();
+
+ ObjectLock olock(this);
m_RecvQueue->Write(data, rc);
new_data = true;
} else {
}
}
- if (new_data) {
- olock.Unlock();
+ if (new_data)
OnDataAvailable(GetSelf());
- olock.Lock();
- }
+
+ ObjectLock olock(this);
while (m_SendQueue->GetAvailableBytes() > 0) {
size_t count = m_SendQueue->GetAvailableBytes();
m_SendQueue->Peek(data, count);
+ olock.Unlock();
+
+ boost::mutex::scoped_lock lock(m_SSLMutex);
+
rc = SSL_write(m_SSL.get(), (const char *)data, count);
if (rc > 0) {
+ lock.unlock();
+
+ olock.Lock();
m_SendQueue->Read(NULL, rc);
} else {
switch (SSL_get_error(m_SSL.get(), rc)) {
*/
void TlsStream::Close(void)
{
- ObjectLock olock(this);
+ {
+ boost::mutex::scoped_lock lock(m_SSLMutex);
+
+ if (m_SSL)
+ SSL_shutdown(m_SSL.get());
+ }
- if (m_SSL)
- SSL_shutdown(m_SSL.get());
+ {
+ ObjectLock olock(this);
- m_SendQueue->Close();
- m_RecvQueue->Close();
+ m_SendQueue->Close();
+ m_RecvQueue->Close();
+ }
Stream::Close();
}
*/
void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
{
- ObjectLock olock(this);
-
- String peerAddress = client->GetPeerAddress();
TlsStream::Ptr tlsStream = boost::make_shared<TlsStream>(client, role, m_SSLContext);
- tlsStream->Start();
m_PendingClients.insert(tlsStream);
- tlsStream->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1, peerAddress));
+ tlsStream->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1));
tlsStream->OnClosed.connect(boost::bind(&EndpointManager::ClientClosedHandler, this, _1));
client->Start();
+ tlsStream->Start();
}
-void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress)
+void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client)
{
- ObjectLock olock(this);
-
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
JsonRpcConnection::Ptr jclient = boost::make_shared<JsonRpcConnection>(tlsStream);
- m_PendingClients.erase(tlsStream);
+ {
+ ObjectLock olock(this);
+ m_PendingClients.erase(tlsStream);
+ }
shared_ptr<X509> cert = tlsStream->GetPeerCertificate();
String identity = GetCertificateCN(cert);
- Log(LogInformation, "icinga", "New client connection at " + peerAddress + " for identity '" + identity + "'");
+ Log(LogInformation, "icinga", "New client connection for identity '" + identity + "'");
Endpoint::Ptr endpoint = Endpoint::GetByName(identity);
void EndpointManager::ClientClosedHandler(const Stream::Ptr& client)
{
- ObjectLock olock(this);
-
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
- m_PendingClients.erase(tlsStream);
+
+ {
+ ObjectLock olock(this);
+ m_PendingClients.erase(tlsStream);
+ }
}
/**
subscriptions->Seal();
- if (m_Endpoint)
+ if (m_Endpoint) {
+ ObjectLock olock(m_Endpoint);
m_Endpoint->SetSubscriptions(subscriptions);
+ }
}
void EndpointManager::ReconnectTimerHandler(void)