mirror of https://github.com/Icinga/icinga2.git
Add timeout for TLS handshakes
This commit is contained in:
parent
aa1ccd7ada
commit
70c81734c5
|
@ -60,7 +60,7 @@ void Stream::SignalDataAvailable(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stream::WaitForData(int timeout)
|
bool Stream::WaitForData()
|
||||||
{
|
{
|
||||||
if (!SupportsWaiting())
|
if (!SupportsWaiting())
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Stream does not support waiting."));
|
BOOST_THROW_EXCEPTION(std::runtime_error("Stream does not support waiting."));
|
||||||
|
@ -68,10 +68,25 @@ bool Stream::WaitForData(int timeout)
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
while (!IsDataAvailable() && !IsEof())
|
while (!IsDataAvailable() && !IsEof())
|
||||||
if (timeout < 0)
|
m_CV.wait(lock);
|
||||||
m_CV.wait(lock);
|
|
||||||
else
|
return IsDataAvailable() || IsEof();
|
||||||
m_CV.timed_wait(lock, boost::posix_time::milliseconds(timeout * 1000));
|
}
|
||||||
|
|
||||||
|
bool Stream::WaitForData(int timeout)
|
||||||
|
{
|
||||||
|
if (!SupportsWaiting())
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error("Stream does not support waiting."));
|
||||||
|
|
||||||
|
if (timeout < 0)
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error("Timeout can't be negative"));
|
||||||
|
|
||||||
|
boost::system_time const point_of_timeout = boost::get_system_time() + boost::posix_time::seconds(timeout);
|
||||||
|
|
||||||
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
|
while (!IsDataAvailable() && !IsEof() && point_of_timeout > boost::get_system_time())
|
||||||
|
m_CV.timed_wait(lock, point_of_timeout);
|
||||||
|
|
||||||
return IsDataAvailable() || IsEof();
|
return IsDataAvailable() || IsEof();
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,8 +124,10 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits until data can be read from the stream.
|
* Waits until data can be read from the stream.
|
||||||
|
* Optionally with a timeout.
|
||||||
*/
|
*/
|
||||||
bool WaitForData(int timeout = -1);
|
bool WaitForData();
|
||||||
|
bool WaitForData(int timeout);
|
||||||
|
|
||||||
virtual bool SupportsWaiting(void) const;
|
virtual bool SupportsWaiting(void) const;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
#define TLS_TIMEOUT_SECONDS 10
|
||||||
|
#define TLS_TIMEOUT_STEP_SECONDS 1
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
int I2_EXPORT TlsStream::m_SSLIndex;
|
int I2_EXPORT TlsStream::m_SSLIndex;
|
||||||
|
@ -286,8 +289,14 @@ void TlsStream::Handshake(void)
|
||||||
m_CurrentAction = TlsActionHandshake;
|
m_CurrentAction = TlsActionHandshake;
|
||||||
ChangeEvents(POLLOUT);
|
ChangeEvents(POLLOUT);
|
||||||
|
|
||||||
while (!m_HandshakeOK && !m_ErrorOccurred && !m_Eof)
|
boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(TLS_TIMEOUT_SECONDS);
|
||||||
m_CV.wait(lock);
|
|
||||||
|
while (!m_HandshakeOK && !m_ErrorOccurred && !m_Eof && timeout > boost::get_system_time())
|
||||||
|
m_CV.timed_wait(lock, timeout);
|
||||||
|
|
||||||
|
// We should _NOT_ (underline, bold, itallic and wordart) throw an exception for a timeout.
|
||||||
|
if (timeout < boost::get_system_time())
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error("Timeout during handshake."));
|
||||||
|
|
||||||
if (m_Eof)
|
if (m_Eof)
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Socket was closed during TLS handshake."));
|
BOOST_THROW_EXCEPTION(std::runtime_error("Socket was closed during TLS handshake."));
|
||||||
|
|
|
@ -511,11 +511,17 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
|
||||||
JsonRpc::SendMessage(tlsStream, message);
|
JsonRpc::SendMessage(tlsStream, message);
|
||||||
ctype = ClientJsonRpc;
|
ctype = ClientJsonRpc;
|
||||||
} else {
|
} else {
|
||||||
tlsStream->WaitForData(5);
|
tlsStream->WaitForData(10);
|
||||||
|
|
||||||
if (!tlsStream->IsDataAvailable()) {
|
if (!tlsStream->IsDataAvailable()) {
|
||||||
Log(LogWarning, "ApiListener")
|
if (identity.IsEmpty())
|
||||||
<< "No data received on new API connection for identity '" << identity << "'. Ensure that the remote endpoints are properly configured in a cluster setup.";
|
Log(LogInformation, "ApiListener")
|
||||||
|
<< "No data received on new API connection. "
|
||||||
|
<< "Ensure that the remote endpoints are properly configured in a cluster setup.";
|
||||||
|
else
|
||||||
|
Log(LogWarning, "ApiListener")
|
||||||
|
<< "No data received on new API connection for identity '" << identity << "'. "
|
||||||
|
<< "Ensure that the remote endpoints are properly configured in a cluster setup.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ void HttpServerConnection::StaticInitialize(void)
|
||||||
{
|
{
|
||||||
l_HttpServerConnectionTimeoutTimer = new Timer();
|
l_HttpServerConnectionTimeoutTimer = new Timer();
|
||||||
l_HttpServerConnectionTimeoutTimer->OnTimerExpired.connect(boost::bind(&HttpServerConnection::TimeoutTimerHandler));
|
l_HttpServerConnectionTimeoutTimer->OnTimerExpired.connect(boost::bind(&HttpServerConnection::TimeoutTimerHandler));
|
||||||
l_HttpServerConnectionTimeoutTimer->SetInterval(15);
|
l_HttpServerConnectionTimeoutTimer->SetInterval(5);
|
||||||
l_HttpServerConnectionTimeoutTimer->Start();
|
l_HttpServerConnectionTimeoutTimer->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,12 @@ TlsStream::Ptr HttpServerConnection::GetStream(void) const
|
||||||
|
|
||||||
void HttpServerConnection::Disconnect(void)
|
void HttpServerConnection::Disconnect(void)
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_try_lock lock(m_DataHandlerMutex);
|
||||||
|
if (!lock.owns_lock()) {
|
||||||
|
Log(LogInformation, "HttpServerConnection", "Unable to disconnect Http client, I/O thread busy");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log(LogDebug, "HttpServerConnection", "Http client disconnected");
|
Log(LogDebug, "HttpServerConnection", "Http client disconnected");
|
||||||
|
|
||||||
ApiListener::Ptr listener = ApiListener::GetInstance();
|
ApiListener::Ptr listener = ApiListener::GetInstance();
|
||||||
|
|
|
@ -121,8 +121,10 @@ boost::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String&
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream->Handshake();
|
stream->Handshake();
|
||||||
} catch (...) {
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "pki")
|
||||||
|
<< "Client TLS handshake failed. (" << ex.what() << ")";
|
||||||
|
return std::shared_ptr<X509>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream->GetPeerCertificate();
|
return stream->GetPeerCertificate();
|
||||||
|
|
Loading…
Reference in New Issue