Skip to content

[SSL] Report OpenSSL error when certificate chain can't be read (#5556) - #5561

Open
Ankith L (Ankith-Confluent) wants to merge 1 commit into
masterfrom
dev_ssl_cert_pem_error_reporting
Open

[SSL] Report OpenSSL error when certificate chain can't be read (#5556)#5561
Ankith L (Ankith-Confluent) wants to merge 1 commit into
masterfrom
dev_ssl_cert_pem_error_reporting

Conversation

@Ankith-Confluent

@Ankith-Confluent Ankith L (Ankith-Confluent) commented Aug 7, 2026

Copy link
Copy Markdown
Member

Fixes #5556

A PEM in ssl.certificate.pem whose leaf certificate parses but whose
trailing block does not is rejected with an error that names neither the
reason nor the part that failed:

ssl.certificate.pem failed: not in PEM format?: kafka: No further error information available

Both halves of that message are unhelpful. The leaf was in PEM format —
it parsed fine — and the OpenSSL reason is reported as unavailable even
though OpenSSL did produce one.

Root cause

rd_kafka_ssl_read_cert_chain_from_BIO() called ERR_clear_error()
unconditionally, including on the failure path. By the time the caller
reached rd_kafka_ssl_error() the queue was empty, so the three ASN.1
errors describing the failure had already been discarded.

The not in PEM format? text was used for both a leaf failure and a chain
failure, so it pointed at the wrong part of the input.

The same applied to a PEM public key passed to
rd_kafka_conf_set_ssl_cert(), which reads the chain through the same
function and reported an empty reason.

Changes

  • Clear the OpenSSL error queue only on success, so a real parse error
    survives for the caller to report.
  • Distinguish a leaf failure from a chain failure so the message names the
    part that actually failed.
  • Clear the error queue at rd_kafka_cert_new()'s failure label. That path
    only peeks at the queue, so preserving errors would otherwise leave them
    behind to be reported again by a later, unrelated failure.

The error now reads:

ssl.certificate.pem failed: error reading certificate chain: error:0488000D:PEM routines::ASN1 lib

Not changed

Rejecting the certificate is intentional and stays. Since 2.8.0 the client
certificate chain is sent to the broker, so a chain that cannot be parsed
cannot be silently truncated — the leaf alone would produce an incomplete
chain and move the failure to the TLS handshake.

This also keeps the in-memory path consistent with the file-based one:
SSL_CTX_use_certificate_chain_file(), used by ssl.certificate.location,
rejects the same input with the same ASN.1 errors.

Testing

New sub-test in 0097_ssl_verify_local (no broker required) covering a
valid certificate, a malformed trailing block via ssl.certificate.pem,
and the same input via set_ssl_cert(). It fails on master with the exact
message from the issue and passes with this change.

@Ankith-Confluent
Ankith L (Ankith-Confluent) requested a review from a team as a code owner August 7, 2026 12:46
Copilot AI lite review requested due to automatic review settings August 7, 2026 12:46
@confluent-cla-assistant

Copy link
Copy Markdown

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves SSL configuration error reporting when parsing PEM-encoded client certificates/chains, ensuring OpenSSL’s underlying parse errors remain available to be surfaced to the user, and adds regression coverage to prevent the error-queue from being inadvertently cleared on failure paths.

Changes:

  • Preserve OpenSSL error-queue contents on certificate-chain parse failures (only clear on success / intentional EOF condition).
  • Differentiate leaf-certificate vs trailing-chain parse failures so the reported message identifies the failing part.
  • Add a focused regression sub-test covering valid cert PEM, malformed trailing chain block via ssl.certificate.pem, and the same input via set_ssl_cert().

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/0097-ssl_verify.cpp Adds a new local sub-test to validate improved error reporting for malformed PEM certificate chains and setter API behavior.
src/rdkafka_ssl.c Adjusts cert-chain parsing to preserve OpenSSL errors on failure and improves failure-context messaging (leaf vs chain).
src/rdkafka_cert.c Clears the OpenSSL error queue on rd_kafka_cert_new() failure after copying the reason into errstr to avoid stale error reuse.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rdkafka_ssl.c
Comment on lines 846 to 850
if (!x509) {
*reasonp = "not in PEM format?";
BIO_free(bio);
return NULL;
}
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.

Backward compatibility regression in ssl.certificate.pem parsing introduced by #4894

2 participants