mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 21:55:03 +02:00
Use new I/O engine in PkiUtility::FetchCert() and PkiUtility::RequestCertificate()
This commit is contained in:
parent
6e7932f157
commit
00d859234e
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
#include "remote/pkiutility.hpp"
|
#include "remote/pkiutility.hpp"
|
||||||
#include "remote/apilistener.hpp"
|
#include "remote/apilistener.hpp"
|
||||||
|
#include "base/defer.hpp"
|
||||||
|
#include "base/io-engine.hpp"
|
||||||
#include "base/logger.hpp"
|
#include "base/logger.hpp"
|
||||||
#include "base/application.hpp"
|
#include "base/application.hpp"
|
||||||
|
#include "base/tcpsocket.hpp"
|
||||||
#include "base/tlsutility.hpp"
|
#include "base/tlsutility.hpp"
|
||||||
#include "base/console.hpp"
|
#include "base/console.hpp"
|
||||||
#include "base/tlsstream.hpp"
|
#include "base/tlsstream.hpp"
|
||||||
@ -14,6 +17,7 @@
|
|||||||
#include "remote/jsonrpc.hpp"
|
#include "remote/jsonrpc.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <boost/asio/ssl/context.hpp>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
@ -76,22 +80,10 @@ int PkiUtility::SignCsr(const String& csrfile, const String& certfile)
|
|||||||
|
|
||||||
std::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String& port)
|
std::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String& port)
|
||||||
{
|
{
|
||||||
TcpSocket::Ptr client = new TcpSocket();
|
std::shared_ptr<boost::asio::ssl::context> sslContext;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client->Connect(host, port);
|
sslContext = MakeAsioSslContext();
|
||||||
} catch (const std::exception& ex) {
|
|
||||||
Log(LogCritical, "pki")
|
|
||||||
<< "Cannot connect to host '" << host << "' on port '" << port << "'";
|
|
||||||
Log(LogDebug, "pki")
|
|
||||||
<< "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
|
|
||||||
return std::shared_ptr<X509>();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<SSL_CTX> sslContext;
|
|
||||||
|
|
||||||
try {
|
|
||||||
sslContext = MakeSSLContext();
|
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Log(LogCritical, "pki")
|
Log(LogCritical, "pki")
|
||||||
<< "Cannot make SSL context.";
|
<< "Cannot make SSL context.";
|
||||||
@ -100,17 +92,31 @@ std::shared_ptr<X509> PkiUtility::FetchCert(const String& host, const String& po
|
|||||||
return std::shared_ptr<X509>();
|
return std::shared_ptr<X509>();
|
||||||
}
|
}
|
||||||
|
|
||||||
TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext);
|
auto stream (std::make_shared<AsioTlsStream>(IoEngine::Get().GetIoService(), *sslContext, host));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream->Handshake();
|
Connect(stream->lowest_layer(), host, port);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "pki")
|
||||||
|
<< "Cannot connect to host '" << host << "' on port '" << port << "'";
|
||||||
|
Log(LogDebug, "pki")
|
||||||
|
<< "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
|
||||||
|
return std::shared_ptr<X509>();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& sslConn (stream->next_layer());
|
||||||
|
|
||||||
|
try {
|
||||||
|
sslConn.handshake(sslConn.client);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Log(LogCritical, "pki")
|
Log(LogCritical, "pki")
|
||||||
<< "Client TLS handshake failed. (" << ex.what() << ")";
|
<< "Client TLS handshake failed. (" << ex.what() << ")";
|
||||||
return std::shared_ptr<X509>();
|
return std::shared_ptr<X509>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream->GetPeerCertificate();
|
Defer shutdown ([&sslConn]() { sslConn.shutdown(); });
|
||||||
|
|
||||||
|
return sslConn.GetPeerCertificate();
|
||||||
}
|
}
|
||||||
|
|
||||||
int PkiUtility::WriteCert(const std::shared_ptr<X509>& cert, const String& trustedfile)
|
int PkiUtility::WriteCert(const std::shared_ptr<X509>& cert, const String& trustedfile)
|
||||||
@ -142,22 +148,10 @@ int PkiUtility::GenTicket(const String& cn, const String& salt, std::ostream& ti
|
|||||||
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile,
|
int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile,
|
||||||
const String& certfile, const String& cafile, const std::shared_ptr<X509>& trustedCert, const String& ticket)
|
const String& certfile, const String& cafile, const std::shared_ptr<X509>& trustedCert, const String& ticket)
|
||||||
{
|
{
|
||||||
TcpSocket::Ptr client = new TcpSocket();
|
std::shared_ptr<boost::asio::ssl::context> sslContext;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client->Connect(host, port);
|
sslContext = MakeAsioSslContext(certfile, keyfile);
|
||||||
} catch (const std::exception& ex) {
|
|
||||||
Log(LogCritical, "cli")
|
|
||||||
<< "Cannot connect to host '" << host << "' on port '" << port << "'";
|
|
||||||
Log(LogDebug, "cli")
|
|
||||||
<< "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<SSL_CTX> sslContext;
|
|
||||||
|
|
||||||
try {
|
|
||||||
sslContext = MakeSSLContext(certfile, keyfile);
|
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Log(LogCritical, "cli")
|
Log(LogCritical, "cli")
|
||||||
<< "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'.";
|
<< "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'.";
|
||||||
@ -166,17 +160,31 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TlsStream::Ptr stream = new TlsStream(client, host, RoleClient, sslContext);
|
auto stream (std::make_shared<AsioTlsStream>(IoEngine::Get().GetIoService(), *sslContext, host));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream->Handshake();
|
Connect(stream->lowest_layer(), host, port);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogCritical, "cli")
|
||||||
|
<< "Cannot connect to host '" << host << "' on port '" << port << "'";
|
||||||
|
Log(LogDebug, "cli")
|
||||||
|
<< "Cannot connect to host '" << host << "' on port '" << port << "':\n" << DiagnosticInformation(ex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& sslConn (stream->next_layer());
|
||||||
|
|
||||||
|
try {
|
||||||
|
sslConn.handshake(sslConn.client);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Log(LogCritical, "cli")
|
Log(LogCritical, "cli")
|
||||||
<< "Client TLS handshake failed: " << DiagnosticInformation(ex, false);
|
<< "Client TLS handshake failed: " << DiagnosticInformation(ex, false);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<X509> peerCert = stream->GetPeerCertificate();
|
Defer shutdown ([&sslConn]() { sslConn.shutdown(); });
|
||||||
|
|
||||||
|
auto peerCert (sslConn.GetPeerCertificate());
|
||||||
|
|
||||||
if (X509_cmp(peerCert.get(), trustedCert.get())) {
|
if (X509_cmp(peerCert.get(), trustedCert.get())) {
|
||||||
Log(LogCritical, "cli", "Peer certificate does not match trusted certificate.");
|
Log(LogCritical, "cli", "Peer certificate does not match trusted certificate.");
|
||||||
@ -196,36 +204,32 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
|
|||||||
{ "params", params }
|
{ "params", params }
|
||||||
});
|
});
|
||||||
|
|
||||||
JsonRpc::SendMessage(stream, request);
|
|
||||||
|
|
||||||
String jsonString;
|
|
||||||
Dictionary::Ptr response;
|
Dictionary::Ptr response;
|
||||||
StreamReadContext src;
|
|
||||||
|
|
||||||
for (;;) {
|
try {
|
||||||
StreamReadStatus srs = JsonRpc::ReadMessage(stream, &jsonString, src);
|
JsonRpc::SendMessage(stream, request);
|
||||||
|
stream->flush();
|
||||||
|
|
||||||
if (srs == StatusEof)
|
for (;;) {
|
||||||
break;
|
response = JsonRpc::DecodeMessage(JsonRpc::ReadMessage(stream));
|
||||||
|
|
||||||
if (srs != StatusNewItem)
|
if (response && response->Contains("error")) {
|
||||||
continue;
|
Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log (notice or debug).");
|
||||||
|
|
||||||
response = JsonRpc::DecodeMessage(jsonString);
|
|
||||||
|
|
||||||
if (response && response->Contains("error")) {
|
|
||||||
Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log (notice or debug).");
|
|
||||||
#ifdef I2_DEBUG
|
#ifdef I2_DEBUG
|
||||||
/* we shouldn't expose master errors to the user in production environments */
|
/* we shouldn't expose master errors to the user in production environments */
|
||||||
Log(LogCritical, "cli", response->Get("error"));
|
Log(LogCritical, "cli", response->Get("error"));
|
||||||
#endif /* I2_DEBUG */
|
#endif /* I2_DEBUG */
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response && (response->Get("id") != msgid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
} catch (...) {
|
||||||
if (response && (response->Get("id") != msgid))
|
Log(LogCritical, "cli", "Could not fetch valid response. Please check the master log.");
|
||||||
continue;
|
return 1;
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user