diff --git a/lib/remote/jsonrpcconnection-pki.cpp b/lib/remote/jsonrpcconnection-pki.cpp index d2b727b674f..d7f89ec3d3e 100644 --- a/lib/remote/jsonrpcconnection-pki.cpp +++ b/lib/remote/jsonrpcconnection-pki.cpp @@ -31,11 +31,11 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona std::shared_ptr cert; Dictionary::Ptr result = new Dictionary(); + auto& tlsConn (origin->FromClient->GetStream()->next_layer()); /* Use the presented client certificate if not provided. */ if (certText.IsEmpty()) { - auto stream (origin->FromClient->GetStream()); - cert = stream->next_layer().GetPeerCertificate(); + cert = tlsConn.GetPeerCertificate(); } else { cert = StringToCertificate(certText); } @@ -78,12 +78,38 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona } if (signedByCA) { - if (IsCertUptodate(cert)) { + bool uptodate = IsCertUptodate(cert); + if (uptodate) { + // Even if the leaf is up-to-date, the root may expire soon. + // In a regular setup where Icinga manages the PKI, there is only one CA. + // Icinga includes it in handshakes, let's see whether the peer needs a fresh one... + + auto chain (SSL_get_peer_cert_chain(tlsConn.native_handle())); + + if (chain) { + X509* root = nullptr; + auto len (sk_X509_num(chain)); + + for (int i = 0; i < len; ++i) { + auto link (sk_X509_value(chain, i)); + + if (!X509_NAME_cmp(X509_get_subject_name(link), X509_get_issuer_name(link))) { + root = link; + } + } + + if (root) { + uptodate = IsCertUptodate(root); + } + } + } + + if (uptodate) { Log(LogInformation, "JsonRpcConnection") - << "The certificate for CN '" << cn << "' is valid and uptodate. Skipping automated renewal."; + << "The certificates for CN '" << cn << "' and its root CA are valid and uptodate. Skipping automated renewal."; result->Set("status_code", 1); - result->Set("error", "The certificate for CN '" + cn + "' is valid and uptodate. Skipping automated renewal."); + result->Set("error", "The certificates for CN '" + cn + "' and its root CA are valid and uptodate. Skipping automated renewal."); return result; } }