Ca certificate reload#3568
Open
afreof wants to merge 6 commits intoeclipse-mosquitto:masterfrom
Open
Conversation
added 6 commits
April 15, 2026 21:43
OpenSSL 3.x on some distributions (e.g. Fedora 42) does not ship engine.h as part of openssl-devel because the ENGINE API is deprecated. When the header is absent, the OpenSSL configuration header defines OPENSSL_NO_ENGINE to signal that the ENGINE API is unavailable. Three files in lib/ included <openssl/engine.h> unconditionally inside #ifdef WITH_TLS blocks, causing a fatal build error on those systems: lib/tls_mosq.h lib/net_mosq.c lib/options.c src/net.c already guarded its engine usage correctly with Apply the same OPENSSL_NO_ENGINE guard to the three lib/ files. In options.c, where no other OpenSSL header was included before the engine.h line, add <openssl/opensslconf.h> first so that the macro is defined before it is tested. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
listeners__reload_all_certificates() called only net__load_certificates() on the existing SSL_CTX without calling net__tls_load_verify(). As a result, any rotation of the CA bundle (cafile/capath) had no effect until a full broker restart: clients whose certificate was signed by the new CA were rejected, and clients whose certificate was signed by a revoked CA continued to be accepted. Fix by recreating the SSL_CTX from scratch: net__tls_server_ctx() frees and reallocates a fresh context, then net__tls_load_verify() loads CA certs and CRLs into it. As a secondary benefit this also stops a resource leak: net__load_crl_file() calls X509_STORE_add_lookup() on every reload, which appends a new X509_LOOKUP_file() entry to the store's internal lookup-methods stack. There is no public API to remove entries, so each SIGHUP grew the stack by one. (CRL objects themselves are not duplicated because X509_STORE_add_crl() deduplicates by issuer name.) Existing TLS connections are unaffected: SSL objects hold a reference to their parent SSL_CTX, so the old context is kept alive until the last connection derived from it is closed. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Without the SSL_CTX recreation fix, swapping the cafile symlink and sending SIGHUP leaves the broker using the old CA store.Clients whose certificate is signed by the old CA continue to connect successfully even though the cafile now points at an entirely unrelated root CA. The test atomically replaces a cafile symlink with one pointing at test-fake-root-ca.crt (a self-signed root with no relation to the test PKI used to issue client.crt) and then confirms that a subsequent TLS handshake with client.crt is rejected. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Add 08-ssl-hup-reload.py to cover the two scenarios that had no dedicated test: 1. After SIGHUP, new TLS connections with a valid client certificate are still accepted. The existing 08-ssl-hup-disconnect.py only verifies that an already-established connection is not dropped; it does not exercise a fresh TLS handshake against the reloaded SSL_CTX. 2. After SIGHUP, revoked certificates (crlfile) are still rejected. The existing CRL tests (08-ssl-connect-cert-auth-crl.py, 08-ssl-connect-cert-auth-revoked.py) never send a SIGHUP, so they do not verify that the CRL store survives the reload. The test repeats the SIGHUP cycle three times to act as a regression test against any accumulation behaviour that could degrade or break subsequent reloads. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
…eloads Configure a certfile containing both the leaf (server.crt) and the intermediate signing CA (test-signing-ca.crt). After each SIGHUP the test uses openssl s_client -showcerts to extract every certificate sent by the broker and compares their SHA-256 fingerprints against the expected values: - chain[0] must be server.crt (correct leaf, not stale or wrong cert) - chain[1] must be test-signing-ca.crt (correct intermediate) - no further certificates (no accumulation of duplicate intermediates) Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Before the SSL_CTX recreation fix, only certfile and keyfile were effectively reloaded on SIGHUP. The mosquitto.conf(5) man page reflected this: cafile, capath, and crlfile had no reload note, while certfile mentioned only itself. Now that net__tls_load_verify() is called on every reload, all four options take effect on SIGHUP. Update the man page accordingly: - cafile, capath, crlfile: add 'Reloaded when Mosquitto receives a SIGHUP signal.' - certfile: broaden the existing note to mention keyfile, cafile, and crlfile alongside certfile. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix stale CA store and CRL not reloaded on SIGHUP certificate reload
listeners__reload_all_certificates() called only net__load_certificates()
on the existing SSL_CTX, without calling net__tls_load_verify(). This meant
that cafile/capath and crlfile were silently ignored on SIGHUP: CA cert
rotations required a full broker restart to take effect, and each reload
leaked an X509_LOOKUP instance into the store's internal lookup-methods stack.
The fix recreates the SSL_CTX from scratch (net__tls_server_ctx() followed by
net__tls_load_verify()) so that all four TLS options — certfile, keyfile,
cafile/capath, and crlfile — are fully reloaded on every SIGHUP. Existing
connections are unaffected because SSL objects hold their own reference to
the old SSL_CTX until they close.
The man page is updated to document that cafile, capath, and crlfile are now
reloaded on SIGHUP (only certfile had this note before).
Tests added:
symlink swap and verifies that client.crt is rejected after SIGHUP.
are still rejected across 3 SIGHUP cycles (CRL survives SSL_CTX recreation).
(correct leaf + intermediate fingerprints) across SIGHUP reloads.
Then please check the following list of things we ask for in your pull request:
make testwith your changes locally?