Skip to content

Honour certificate verification mode when custom trust roots are set (TransportServices) - #185

Merged
glbrntt merged 1 commit into
grpc:mainfrom
dmonagle:fix/custom-trust-roots-verification
Jul 20, 2026
Merged

Honour certificate verification mode when custom trust roots are set (TransportServices)#185
glbrntt merged 1 commit into
grpc:mainfrom
dmonagle:fix/custom-trust-roots-verification

Conversation

@dmonagle

@dmonagle dmonagle commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Fixes #184.

Motivation

With trustRoots: .certificates(...), the TransportServices transports install a verify block that anchors the custom roots and then calls SecTrustEvaluateAsyncWithError on the trust exactly as Network.framework configured it — with the default SSL policy, which includes hostname matching. The configured CertificateVerification mode is never consulted there:

  • .noHostnameVerification behaves like full verification: any certificate whose SANs don't cover the dialled endpoint is rejected (errSSLBadCert), even though the chain validates against the custom roots. This breaks private-CA deployments whose certs deliberately carry no DNS/IP SANs, and peers dialled by IP address. The identical configuration works with the Posix transport, where the mode maps to NIOSSL's certificateVerification = .noHostnameVerification.
  • .noVerification still installs the evaluating block and can fail the handshake despite verification being explicitly disabled.

Modifications

The verify block now receives the verification mode and whether it is evaluating server or client certificates:

  • .noHostnameVerification: the trust is re-policied with SecPolicyCreateSSL(<role>, nil) before evaluation — chain validation against the custom anchors is unchanged, hostname matching is skipped.
  • .noVerification: no verify block is installed (the callers already set sec_protocol_options_set_peer_authentication_required(false) for this mode), matching NIOSSL semantics.
  • .fullVerification: behaviour unchanged.

Result

.noHostnameVerification + custom trust roots connects when the chain is valid but the hostname doesn't match, on both client and server TransportServices transports, matching the Posix transport.

New regression test (testClientNoHostnameVerificationIgnoresHostname) covers all client/server transport combinations; without the source change the two TransportServices-client cases fail with NWError.tls(-9808). Existing TLS suites pass (HTTP2TransportTLSEnabledTests, TLSConfigurationTests).

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jul 20, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: dmonagle / name: David Monagle (9001353)

…rtServices)

With custom trustRoots, the TransportServices transports installed a
verify block that anchored the custom roots and then evaluated the
SecTrust exactly as Network.framework configured it — with the default
SSL policy, including hostname matching. The configured
CertificateVerification mode was never consulted, so
.noHostnameVerification behaved like full verification (rejecting any
certificate whose SANs don't cover the endpoint, e.g. private-CA
deployments or IP-dialled peers), and .noVerification still evaluated
and could fail the handshake.

The verify block now honours the mode: .noHostnameVerification
re-policies the trust for SSL use with no hostname before evaluating
(chain validation against the custom roots is unchanged), and
.noVerification installs no verify block at all, matching the Posix
transport's NIOSSL semantics for both modes.
@dmonagle
dmonagle force-pushed the fix/custom-trust-roots-verification branch from d6f372d to 9001353 Compare July 20, 2026 08:36
@glbrntt glbrntt added the 🔨 semver/patch No public API change. label Jul 20, 2026

@glbrntt glbrntt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you!

@glbrntt
glbrntt enabled auto-merge (squash) July 20, 2026 10:45
@dmonagle

Copy link
Copy Markdown
Contributor Author

The two failing jobs (Linux nightly-main / nightly-next) reproduce on main — the nightly toolchain's SwiftPM now errors on the Documentation.docc directories ("found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target") for four targets. Unrelated to this change; all release-toolchain jobs pass.

@glbrntt
glbrntt merged commit 39b8e90 into grpc:main Jul 20, 2026
39 of 41 checks passed
dongjoon-hyun added a commit to apache/spark-connect-swift that referenced this pull request Aug 4, 2026
### What changes were proposed in this pull request?

This PR upgrades the `grpc-swift-nio-transport` dependency to `2.9.1`.

### Why are the changes needed?

To adopt the latest `grpc-swift-nio-transport` release (`2.9.1`, 2026-08-03).
- https://github.com/grpc/grpc-swift-nio-transport/releases/tag/2.9.1
  - grpc/grpc-swift-nio-transport#185
  - grpc/grpc-swift-nio-transport#187

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Pass the CIs.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Fable 5

Closes #476 from dongjoon-hyun/SPARK-58542.

Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TransportServices client TLS: serverCertificateVerification is ignored when custom trustRoots are set

2 participants