You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tls-rustls: sslrootcert / ssl-ca is added to the built-in roots instead of replacing them (no way to pin a private CA) #4492
sqlx-core 0.9.0, src/net/tls/tls_rustls.rs: the client's root store always starts from a built-in set, and sslrootcert / ssl-ca is added to it:
letmut cert_store = import_root_certs();// webpki-roots or rustls-native-certsifletSome(ca) = tls_config.root_cert_path{
...cert_store.add(cert)?;// added, not replacing}
Every rustls feature selects one of those sets (sqlx-core/Cargo.toml: _tls-rustls-aws-lc-rs and _tls-rustls-ring-webpki enable webpki-roots; _tls-rustls-ring-native-roots enables rustls-native-certs). The empty store exists but is unreachable: "Not currently used but allows for a "tls-rustls-no-roots" feature." (tls_rustls.rs:233).
Effect: with sslmode=verify-full&sslrootcert=private-ca.pem (Postgres) or ssl-mode=VERIFY_IDENTITY&ssl-ca=… (MySQL), a server certificate issued by any public CA for the dialled name is also accepted. A user who sets a private CA expects it to be the only trust anchor; libpq's sslrootcert behaves that way (it replaces the defaults). There is also no API to supply a custom rustls::ClientConfig or to inspect the peer certificate, so an application cannot enforce the pin itself.
Suggestion (any of):
when a root certificate file is given, start from RootCertStore::empty() (libpq parity), or
ship the tls-rustls-no-roots feature the comment anticipates, or
accept a caller-supplied rustls::ClientConfig / verifier.
Found while hardening our own service. Related: #4491.
Activity