Skip to content

Fix spurious "CRL: cannot read CRL from file" warning on CRL reload - #1104

Open
linuxkd wants to merge 1 commit into
OpenVPN:masterfrom
linuxkd:crl-reload-error-queue
Open

linuxkd wants to merge 1 commit into
OpenVPN:masterfrom
linuxkd:crl-reload-error-queue

Conversation

@linuxkd

@linuxkd linuxkd commented Sep 10, 2026

Copy link
Copy Markdown

Fixes #1103.

backend_tls_ctx_reload_crl() tests for end of file with ERR_peek_error(), which returns the oldest error on the thread's OpenSSL error queue, and never clears the queue first. Any error left queued earlier in the handshake makes a clean EOF after the last CRL look like a read failure: the M_WARN "CRL: cannot read CRL from file" fires with the unrelated queued errors printed under it, and the CRLs already parsed are installed anyway ("loaded 1 CRLs"). Seen on every first handshake after the CRL file changes, with OpenSSL 3.5.5 leaving an EVP "unsupported" error queued.

This change clears the queue before the read loop, tests ERR_peek_last_error(), and clears the queue on the EOF path instead of popping one entry.

Validated on aarch64 / OpenSSL 3.5.5 / DCO with two builds of master 28ec0f90 run as a server with crl-verify <file>, the file atomically replaced three times with a client re-handshake after each, then once with a file containing no CRL:

build spurious warning on reload file with no CRL
unpatched 3 of 3, stale EVP error printed with it warns, loaded 0 CRLs, VERIFY ERROR: CRL not loaded
patched 0 of 3 warns, loaded 0 CRLs, VERIFY ERROR: CRL not loaded, prints only the PEM error

Opened for review per CONTRIBUTING; the patch will go to openvpn-devel once ACKed. clang-format --dry-run -Werror is clean on the file.

backend_tls_ctx_reload_crl() decides whether PEM_read_bio_X509_CRL()
hit end of file by looking at ERR_peek_error(), which returns the
OLDEST error on the thread's OpenSSL error queue, and it never clears
the queue before reading. If anything earlier in the handshake left an
error queued (seen with OpenSSL 3.5: an EVP "unsupported" error from
the same handshake), a clean EOF after the last CRL is misclassified:
the M_WARN "cannot read CRL from file" fires, crypto_msg() prints the
unrelated queued errors as if they came from the CRL file, and the
CRLs that were already parsed are installed anyway ("loaded 1 CRLs").

Observed on every first handshake after the CRL file changed (mtime or
size), never at daemon start where the queue is empty. The verdict is
unaffected; the warning is a false positive that operators alerting on
that string for a fail-closed crl-verify deployment will page on.

Clear the error queue before the read loop so only errors raised by
PEM_read_bio_X509_CRL() are visible, test the last error rather than
the first, and clear the queue on the EOF path instead of popping one
entry.

Signed-off-by: Drew Blokzyl <drew@linuxkids.com>
@linuxkd

linuxkd commented Sep 10, 2026

Copy link
Copy Markdown
Author

Patch sent to openvpn-devel on 2026-09-10 as [PATCH] Fix spurious "CRL: cannot read CRL from file" warning on CRL reload (same commit as this branch, validation notes under the --- line).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spurious "CRL: cannot read CRL from file" on every CRL reload when the OpenSSL error queue is not empty

1 participant