Skip to content

Fix | Perform ServerCertificate pin validation to verify with server provided cert - #4445

Merged
cheenamalhotra merged 5 commits into
mainfrom
dev/cheena/server-cert-fix
Aug 24, 2026
Merged

cheenamalhotra merged 5 commits into
mainfrom
dev/cheena/server-cert-fix

Conversation

@cheenamalhotra

@cheenamalhotra cheenamalhotra commented Jul 14, 2026

Copy link
Copy Markdown
Member

Description

Refines the managed SNI certificate-validation helper so that the ServerCertificate connection-string keyword behaves consistently with its documented "exact match" semantic.

Address internal item AB#46371

Two small refinements in SniCommon.ValidateSslServerCertificate. The existing design is unchanged: an exact ServerCertificate match still satisfies certificate validation.

  1. Short-circuit narrowed to the pin-less path. The early-return on policyErrors == SslPolicyErrors.None now also requires validationCertFileName to be null/empty. When the caller has supplied a ServerCertificate, the helper always compares it against the presented server certificate — previously it was skipped entirely whenever the platform reported no policy errors. The no-pin fast path is unchanged.
  2. Load failure fails closed. If the file can't be loaded/parsed, the helper now throws SSLCertificateAuthenticationException naming the configured path, instead of silently discarding the option and falling back to host-name validation — matching the caller's explicit intent.

Additionally, two defects surfaced in review:

  • The loaded X509Certificate is now disposed via a narrow using scope (it owns unmanaged resources).
  • A null server certificate now throws AuthenticationException rather than a NullReferenceException from the raw-bytes comparison.

The TrustServerCertificate=true short-circuit on the transport handles is unchanged — when validation is disabled at that layer, ServerCertificate remains unconsulted, matching the existing semantic.

Backwards compatibility

  • No ServerCertificate supplied → identical behavior.
  • ServerCertificate supplied, well-formed, and matches → identical behavior, including when the presented certificate would otherwise fail chain validation (for example a self-signed or private-CA certificate). This scenario deliberately continues to work.
  • ServerCertificate supplied and the file is missing/unreadable, or it doesn't match the server cert → now throws SSLCertificateAuthenticationException at handshake, aligning runtime with the documented "exact match" contract. Both cases previously risked accepting a connection the caller intended to restrict.

Testing

Added SniCommonValidateSslServerCertificateTest, which exercises SniCommon.ValidateSslServerCertificate directly. Both the TCP and Named Pipes transports call into this same helper, so no transport-specific parameterization is needed.

Scenario Expected
No cert configured + PolicyErrors.None returns true
Match + PolicyErrors.None returns true
Match + PolicyErrors.RemoteCertificateChainErrors returns true (exact match satisfies validation)
Mismatch + PolicyErrors.None throws AuthenticationException
Mismatch + PolicyErrors.RemoteCertificateChainErrors throws AuthenticationException
Configured + null server cert + PolicyErrors.RemoteCertificateNotAvailable throws AuthenticationException
Configured + null server cert + PolicyErrors.None throws AuthenticationException
Unreadable file + PolicyErrors.None throws AuthenticationException

Local run on net9.0: 8 passed / 0 failed.

Guidelines

Reviewed:

@cheenamalhotra
cheenamalhotra requested a review from a team as a code owner July 14, 2026 00:43
Copilot AI lite review requested due to automatic review settings July 14, 2026 00:43
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Jul 14, 2026
@cheenamalhotra cheenamalhotra added Hotfix 7.0.3 PRs targeting main that should be backported to release/7.0 branch for next release. Hotfix 6.1.7 PRs targeting main that should be backported to release/6.1 branch for future hotfix labels Jul 14, 2026
@cheenamalhotra cheenamalhotra added this to the 7.1.0-preview3 milestone Jul 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 refines Managed SNI’s TLS server-certificate validation so the ServerCertificate connection-string keyword behaves as an explicit certificate pin (and updates docs/tests to reflect the intended semantics).

Changes:

  • Tightens the “policyErrors == None” fast path so it only applies when no ServerCertificate pin is provided.
  • Changes pin-load failures to fail closed by throwing an authentication exception.
  • Adds unit tests for pin vs. no-pin behavior and updates documentation to clarify “additive” pinning semantics.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ManagedSni/SniCommon.netcore.cs Adjusts certificate-validation control flow for pin handling and fail-closed behavior.
src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/ManagedSni/SniCommonValidateSslServerCertificateTest.cs Adds unit coverage for SniCommon.ValidateSslServerCertificate pin/no-pin scenarios.
doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml Documents ServerCertificate as an additive check (pin + standard validation).
doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml Expands connection-string keyword docs to clarify additive pinning and fail-closed behavior.

@cheenamalhotra
cheenamalhotra force-pushed the dev/cheena/server-cert-fix branch from 3a048c7 to 59524a6 Compare July 14, 2026 00:58
Copilot AI review requested due to automatic review settings July 14, 2026 01:04
@cheenamalhotra
cheenamalhotra force-pushed the dev/cheena/server-cert-fix branch from 59524a6 to e5a2542 Compare July 14, 2026 01:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs: Generated file

Comment thread doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml Outdated
Comment thread doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml Outdated
@github-project-automation github-project-automation Bot moved this from To triage to Waiting for customer in SqlClient Board Jul 14, 2026
@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale due to inactivity for more than 30 days.

If you would like to keep this pull request open, please provide an update or respond to any comments. Otherwise, it will be closed automatically in 7 days.

@github-actions github-actions Bot added the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Aug 14, 2026
@cheenamalhotra cheenamalhotra removed the Stale The Issue or PR has become stale and will be automatically closed shortly if no activity occurs. label Aug 14, 2026
- Perform ServerCertificate pin validation after chain/name policy error
  handling, making the additive semantics explicit in control flow.
- Extract ValidateCertificatePin/LoadValidationCertificate helpers so the
  loaded pin certificate lives in a narrow 'using' scope (no try/finally).
- Guard against a null server certificate in the pin path.
- Clarify method docs on the policyErrors relationship and reword the
  no-pin fast-path trace message.
- Replace ambiguous 'platform trust' wording in docs with chain-and-name
  validation, and note that pinning does not itself confer trust.
- Add TempCertFile disposable test helper and a null-server-cert regression
  test for the policyErrors == None case.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 14, 2026 05:45
This was referenced Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Hotfix 6.1.7 PRs targeting main that should be backported to release/6.1 branch for future hotfix Hotfix 7.0.3 PRs targeting main that should be backported to release/7.0 branch for next release.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants