Skip to content

Commit

Permalink
pki::RequestCertificate handler: renew cert if it's not suitable for …
Browse files Browse the repository at this point in the history
…handshake
  • Loading branch information
Al2Klimov committed Jan 27, 2025
1 parent b501410 commit 8dcddc8
Showing 1 changed file with 37 additions and 0 deletions.
37 changes: 37 additions & 0 deletions lib/remote/jsonrpcconnection-pki.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <openssl/asn1.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <time.h>

using namespace icinga;

Expand Down Expand Up @@ -80,6 +82,8 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona

std::shared_ptr<X509> parsedRequestorCA;
X509* requestorCA = nullptr;
constexpr long handshakeVerifyErrorUnset = X509_V_OK;
long handshakeVerifyError = handshakeVerifyErrorUnset;

if (signedByCA) {
bool uptodate = IsCertUptodate(cert);
Expand Down Expand Up @@ -121,6 +125,35 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
}
}

if (uptodate) {
// There's a bug causing malformed certificates to be issued sometimes.
// The handshake chain verification fails with X509_V_ERR_CERT_SIGNATURE_FAILURE, but (luckily)
// the certificate sent via pki::RequestCertificate gets properly recognized by VerifyCertificate().
// The latter allows to self-heal the cluster by issuing a new certificate,
// despite the old one being "valid and uptodate".

if (cn == origin->FromClient->GetIdentity()) {
handshakeVerifyError = tlsConn.GetVerifyErrorCode();
} else {
Value hve;

if (params->Get("handshake_verify_error", &hve) && hve.IsNumber()) {
handshakeVerifyError = hve;
}
}

if (handshakeVerifyError == X509_V_ERR_CERT_SIGNATURE_FAILURE) {
// In the hypothetic case of a permanent failure to issue sane certificates,
// don't issue a new one on every re-connect:

time_t threshold = time(nullptr) - 10 * 60;

if (X509_cmp_time(X509_get_notBefore(cert.get()), &threshold) < 0) {
uptodate = false;
}
}
}

if (uptodate) {
Log(LogInformation, "JsonRpcConnection")
<< "The certificates for CN '" << cn << "' and its root CA are valid and uptodate. Skipping automated renewal.";
Expand Down Expand Up @@ -276,6 +309,10 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
request->Set("requestor_ca", CertificateToString(requestorCA));
}

if (handshakeVerifyError != handshakeVerifyErrorUnset) {
request->Set("handshake_verify_error", handshakeVerifyError);
}

Utility::SaveJsonFile(requestPath, 0600, request);

JsonRpcConnection::SendCertificateRequest(nullptr, origin, requestPath);
Expand Down

0 comments on commit 8dcddc8

Please sign in to comment.