mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 21:55:03 +02:00
ApiListener: perform TLS handshake
This commit is contained in:
parent
2615967e7f
commit
720c53ab77
@ -23,9 +23,13 @@
|
|||||||
#include <boost/asio/ip/v6_only.hpp>
|
#include <boost/asio/ip/v6_only.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/asio/ssl/context.hpp>
|
#include <boost/asio/ssl/context.hpp>
|
||||||
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
|
#include <boost/asio/ssl/verify_mode.hpp>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <openssl/tls1.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
@ -373,15 +377,36 @@ bool ApiListener::AddListener(const String& node, const String& service)
|
|||||||
Log(LogInformation, "ApiListener")
|
Log(LogInformation, "ApiListener")
|
||||||
<< "Started new listener on '[" << localEndpoint.address() << "]:" << localEndpoint.port() << "'";
|
<< "Started new listener on '[" << localEndpoint.address() << "]:" << localEndpoint.port() << "'";
|
||||||
|
|
||||||
asio::spawn(io, [acceptor](asio::yield_context yc) {
|
asio::spawn(io, [this, acceptor, sslContext](asio::yield_context yc) { ListenerCoroutineProc(yc, acceptor, sslContext); });
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
UpdateStatusFile(localEndpoint);
|
UpdateStatusFile(localEndpoint);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiListener::ListenerCoroutineProc(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ip::tcp::acceptor>& server, const std::shared_ptr<boost::asio::ssl::context>& sslContext)
|
||||||
|
{
|
||||||
|
namespace asio = boost::asio;
|
||||||
|
namespace ssl = asio::ssl;
|
||||||
|
using asio::ip::tcp;
|
||||||
|
|
||||||
|
auto& io (server->get_io_service());
|
||||||
|
auto sslConn (std::make_shared<ssl::stream<tcp::socket>>(io, *sslContext));
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
try {
|
||||||
|
server->async_accept(sslConn->lowest_layer(), yc);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "ApiListener") << "Cannot accept new connection: " << DiagnosticInformation(ex, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
asio::spawn(io, [this, sslConn](asio::yield_context yc) { NewClientHandler(yc, sslConn, String(), RoleServer); });
|
||||||
|
|
||||||
|
sslConn = std::make_shared<ssl::stream<tcp::socket>>(io, *sslContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new JSON-RPC client and connects to the specified endpoint.
|
* Creates a new JSON-RPC client and connects to the specified endpoint.
|
||||||
*
|
*
|
||||||
@ -601,6 +626,70 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiListener::NewClientHandler(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>& client, const String& hostname, ConnectionRole role)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
NewClientHandlerInternal(yc, client, hostname, role);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "ApiListener")
|
||||||
|
<< "Exception while handling new API client connection: " << DiagnosticInformation(ex, false);
|
||||||
|
|
||||||
|
Log(LogDebug, "ApiListener")
|
||||||
|
<< "Exception while handling new API client connection: " << DiagnosticInformation(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a new client connection.
|
||||||
|
*
|
||||||
|
* @param client The new client.
|
||||||
|
*/
|
||||||
|
void ApiListener::NewClientHandlerInternal(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>& client, const String& hostname, ConnectionRole role)
|
||||||
|
{
|
||||||
|
namespace ssl = boost::asio::ssl;
|
||||||
|
|
||||||
|
String conninfo;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream conninfo_;
|
||||||
|
|
||||||
|
if (role == RoleClient) {
|
||||||
|
conninfo_ << "to";
|
||||||
|
} else {
|
||||||
|
conninfo_ << "from";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto endpoint (client->lowest_layer().remote_endpoint());
|
||||||
|
|
||||||
|
conninfo_ << " [" << endpoint.address() << "]:" << endpoint.port();
|
||||||
|
|
||||||
|
conninfo = conninfo_.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
client->set_verify_mode(ssl::verify_peer | ssl::verify_client_once);
|
||||||
|
|
||||||
|
if (role == RoleClient) {
|
||||||
|
String environmentName = Application::GetAppEnvironment();
|
||||||
|
String serverName = hostname;
|
||||||
|
|
||||||
|
if (!environmentName.IsEmpty())
|
||||||
|
serverName += ":" + environmentName;
|
||||||
|
|
||||||
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
|
if (!hostname.IsEmpty()) {
|
||||||
|
SSL_set_tlsext_host_name(client->native_handle(), serverName.CStr());
|
||||||
|
}
|
||||||
|
#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
client->async_handshake(role == RoleClient ? client->client : client->server, yc);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "ApiListener")
|
||||||
|
<< "Client TLS handshake failed (" << conninfo << "): " << DiagnosticInformation(ex, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoint::Ptr& endpoint, bool needSync)
|
void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoint::Ptr& endpoint, bool needSync)
|
||||||
{
|
{
|
||||||
Zone::Ptr eZone = endpoint->GetZone();
|
Zone::Ptr eZone = endpoint->GetZone();
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
#include "base/tlsstream.hpp"
|
#include "base/tlsstream.hpp"
|
||||||
#include "base/threadpool.hpp"
|
#include "base/threadpool.hpp"
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/asio/ssl/context.hpp>
|
#include <boost/asio/ssl/context.hpp>
|
||||||
|
#include <boost/asio/ssl/stream.hpp>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
@ -132,6 +134,10 @@ private:
|
|||||||
void NewClientHandler(const Socket::Ptr& client, const String& hostname, ConnectionRole role);
|
void NewClientHandler(const Socket::Ptr& client, const String& hostname, ConnectionRole role);
|
||||||
void NewClientHandlerInternal(const Socket::Ptr& client, const String& hostname, ConnectionRole role);
|
void NewClientHandlerInternal(const Socket::Ptr& client, const String& hostname, ConnectionRole role);
|
||||||
|
|
||||||
|
void NewClientHandler(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>& client, const String& hostname, ConnectionRole role);
|
||||||
|
void NewClientHandlerInternal(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>& client, const String& hostname, ConnectionRole role);
|
||||||
|
void ListenerCoroutineProc(boost::asio::yield_context yc, const std::shared_ptr<boost::asio::ip::tcp::acceptor>& server, const std::shared_ptr<boost::asio::ssl::context>& sslContext);
|
||||||
|
|
||||||
static ThreadPool& GetTP();
|
static ThreadPool& GetTP();
|
||||||
static void EnqueueAsyncCallback(const std::function<void ()>& callback, SchedulerPolicy policy = DefaultScheduler);
|
static void EnqueueAsyncCallback(const std::function<void ()>& callback, SchedulerPolicy policy = DefaultScheduler);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user