Skip to content

fix(ssl): sslmode=verify-ca and verify-full fail with UnknownIssuer when server does not send full chain #712

@NikolayS

Description

@NikolayS

Problem

sslmode=verify-ca and sslmode=verify-full fail with:

rpg: SSL error: certificate verification failed: invalid peer certificate: UnknownIssuer

even when the correct CA cert is provided via sslrootcert, if the Postgres server does not include intermediate/CA certificates in its TLS handshake.

psql (via OpenSSL) handles this correctly: OpenSSL can validate a chain using only the root cert and the leaf cert. rustls (used by rpg) requires the full intermediate chain to be present in the TLS handshake.

Reproduction

# Server configured with: ssl_cert_file = server.crt (leaf only, CA-signed)
# CA cert available locally at /path/to/ca.crt
rpg -h host -p 5432 -U postgres sslmode=verify-ca sslrootcert=/path/to/ca.crt -c "SELECT 1"
# => SSL error: certificate verification failed: invalid peer certificate: UnknownIssuer

psql with the same flags succeeds.

Root cause

rustls's WebPkiServerVerifier requires the full certificate chain in the TLS handshake. Postgres by default only sends the leaf cert. OpenSSL can complete the chain from the local trust store; rustls cannot.

Possible fixes

  1. Configure Postgres to send the full chain via ssl_cert_file containing concatenated leaf + CA certs (workaround, not a fix in rpg)
  2. Implement AIA (Authority Information Access) fetching to retrieve intermediates — complex
  3. Use a different chain-building strategy: try matching intermediates from the local root store when they are not sent by the server

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions