Skip to content

Commit

Permalink
process certificate chains presented by the client
Browse files Browse the repository at this point in the history
Similar to Icinga#8859 this patch works
around Icinga#7719 by allowing the
intermediate certificate presented by the icinga2-agent.

To make this work the icinga2-master only holds to root-ca in its local
ca.crt, while the icinga2-agent has the intermediate-cert in its local
ca.crt (or the intermediate together with the root in the ca.crt / or
the intermediate in the cert.pem - doesn't matter).
  • Loading branch information
sircubbi authored and Al2Klimov committed Mar 8, 2024
1 parent d551eae commit ffdf278
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 4 deletions.
5 changes: 5 additions & 0 deletions lib/base/tlsstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ std::shared_ptr<X509> UnbufferedAsioTlsStream::GetPeerCertificate()
return std::shared_ptr<X509>(SSL_get_peer_certificate(native_handle()), X509_free);
}

STACK_OF(X509) *UnbufferedAsioTlsStream::GetPeerCertificateChain()
{
return SSL_get_peer_cert_chain(native_handle());
}

void UnbufferedAsioTlsStream::BeforeHandshake(handshake_type type)
{
namespace ssl = boost::asio::ssl;
Expand Down
1 change: 1 addition & 0 deletions lib/base/tlsstream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class UnbufferedAsioTlsStream : public AsioTcpTlsStream
bool IsVerifyOK() const;
String GetVerifyError() const;
std::shared_ptr<X509> GetPeerCertificate();
STACK_OF(X509) *GetPeerCertificateChain();

template<class... Args>
inline
Expand Down
4 changes: 2 additions & 2 deletions lib/base/tlsutility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ String BinaryToHex(const unsigned char* data, size_t length) {
return output;
}

bool VerifyCertificate(const std::shared_ptr<X509> &caCertificate, const std::shared_ptr<X509> &certificate, const String& crlFile)
bool VerifyCertificate(const std::shared_ptr<X509> &caCertificate, const std::shared_ptr<X509> &certificate, const String& crlFile, STACK_OF(X509) *chain)
{
X509_STORE *store = X509_STORE_new();

Expand All @@ -995,7 +995,7 @@ bool VerifyCertificate(const std::shared_ptr<X509> &caCertificate, const std::sh
}

X509_STORE_CTX *csc = X509_STORE_CTX_new();
X509_STORE_CTX_init(csc, store, certificate.get(), nullptr);
X509_STORE_CTX_init(csc, store, certificate.get(), chain);

int rc = X509_verify_cert(csc);

Expand Down
2 changes: 1 addition & 1 deletion lib/base/tlsutility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ String SHA256(const String& s);
String RandomString(int length);
String BinaryToHex(const unsigned char* data, size_t length);

bool VerifyCertificate(const std::shared_ptr<X509>& caCertificate, const std::shared_ptr<X509>& certificate, const String& crlFile);
bool VerifyCertificate(const std::shared_ptr<X509>& caCertificate, const std::shared_ptr<X509>& certificate, const String& crlFile, STACK_OF(X509) *chain = nullptr);
bool IsCa(const std::shared_ptr<X509>& cacert);
int GetCertificateVersion(const std::shared_ptr<X509>& cert);
String GetSignatureAlgorithm(const std::shared_ptr<X509>& cert);
Expand Down
5 changes: 4 additions & 1 deletion lib/remote/jsonrpcconnection-pki.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
String certText = params->Get("cert_request");

std::shared_ptr<X509> cert;
STACK_OF(X509) *chain;

Dictionary::Ptr result = new Dictionary();
auto& tlsConn (origin->FromClient->GetStream()->next_layer());

/* Use the presented client certificate if not provided. */
if (certText.IsEmpty()) {
cert = tlsConn.GetPeerCertificate();
chain = tlsConn.GetPeerCertificateChain();
} else {
cert = StringToCertificate(certText);
chain = nullptr;
}

if (!cert) {
Expand All @@ -62,7 +65,7 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
logmsg << "Received certificate request for CN '" << cn << "'";

try {
signedByCA = VerifyCertificate(cacert, cert, listener->GetCrlPath());
signedByCA = VerifyCertificate(cacert, cert, listener->GetCrlPath(), chain);
if (!signedByCA) {
logmsg << " not";
}
Expand Down

0 comments on commit ffdf278

Please sign in to comment.