Skip to content

Commit b1647fd

Browse files
Copilotshueybubbles
andcommitted
Consolidate setupTLSCertificateOnly into conn_str.go
Moved setupTLSCertificateOnly from build-tag-specific files to conn_str.go since the implementation is identical for all Go versions. This reduces code duplication and makes the codebase easier to maintain. Co-authored-by: shueybubbles <[email protected]>
1 parent 768525c commit b1647fd

File tree

3 files changed

+39
-74
lines changed

3 files changed

+39
-74
lines changed

msdsn/conn_str.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package msdsn
22

33
import (
4+
"bytes"
45
"crypto/tls"
56
"crypto/x509"
67
"encoding/pem"
@@ -241,6 +242,44 @@ func SetupTLS(certificate string, insecureSkipVerify bool, hostInCertificate str
241242
return &config, nil
242243
}
243244

245+
// setupTLSCertificateOnly validates that the server certificate matches the provided certificate
246+
func setupTLSCertificateOnly(config *tls.Config, pemData []byte) error {
247+
// To match the behavior of Microsoft.Data.SqlClient, we simply compare the raw bytes
248+
// of the server's certificate with the provided certificate file. This approach:
249+
// - Does not validate certificate chain, expiry, or subject
250+
// - Only checks that the server's certificate exactly matches the provided certificate
251+
// - Skips hostname validation (which is the intended behavior)
252+
//
253+
// We use InsecureSkipVerify=true with VerifyPeerCertificate callback because
254+
// VerifyConnection runs AFTER standard verification (including hostname check).
255+
256+
// Parse the expected certificate from the PEM data
257+
block, _ := pem.Decode(pemData)
258+
if block == nil {
259+
return fmt.Errorf("failed to decode PEM certificate")
260+
}
261+
// Store the raw certificate bytes (DER format) for comparison
262+
expectedCertBytes := block.Bytes
263+
264+
config.InsecureSkipVerify = true
265+
config.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
266+
if len(rawCerts) == 0 {
267+
return fmt.Errorf("no peer certificates provided")
268+
}
269+
270+
// Compare the server's certificate bytes with the expected certificate bytes
271+
// This matches the Microsoft.Data.SqlClient behavior: just compare raw bytes
272+
serverCertBytes := rawCerts[0]
273+
274+
if !bytes.Equal(serverCertBytes, expectedCertBytes) {
275+
return fmt.Errorf("server certificate doesn't match the provided certificate")
276+
}
277+
278+
return nil
279+
}
280+
return nil
281+
}
282+
244283
// Parse and handle encryption parameters. If encryption is desired, it returns the corresponding tls.Config object.
245284
func parseTLS(params map[string]string, host string) (Encryption, *tls.Config, error) {
246285
trustServerCert := false

msdsn/conn_str_go115.go

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
package msdsn
55

66
import (
7-
"bytes"
87
"crypto/tls"
98
"crypto/x509"
10-
"encoding/pem"
119
"fmt"
1210
)
1311

@@ -71,41 +69,3 @@ func setupTLSCommonName(config *tls.Config, pem []byte) error {
7169
}
7270
return nil
7371
}
74-
75-
// setupTLSCertificateOnly validates that the server certificate matches the provided certificate
76-
func setupTLSCertificateOnly(config *tls.Config, pemData []byte) error {
77-
// To match the behavior of Microsoft.Data.SqlClient, we simply compare the raw bytes
78-
// of the server's certificate with the provided certificate file. This approach:
79-
// - Does not validate certificate chain, expiry, or subject
80-
// - Only checks that the server's certificate exactly matches the provided certificate
81-
// - Skips hostname validation (which is the intended behavior)
82-
//
83-
// We use InsecureSkipVerify=true with VerifyPeerCertificate callback because
84-
// VerifyConnection runs AFTER standard verification (including hostname check).
85-
86-
// Parse the expected certificate from the PEM data
87-
block, _ := pem.Decode(pemData)
88-
if block == nil {
89-
return fmt.Errorf("failed to decode PEM certificate")
90-
}
91-
// Store the raw certificate bytes (DER format) for comparison
92-
expectedCertBytes := block.Bytes
93-
94-
config.InsecureSkipVerify = true
95-
config.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
96-
if len(rawCerts) == 0 {
97-
return fmt.Errorf("no peer certificates provided")
98-
}
99-
100-
// Compare the server's certificate bytes with the expected certificate bytes
101-
// This matches the Microsoft.Data.SqlClient behavior: just compare raw bytes
102-
serverCertBytes := rawCerts[0]
103-
104-
if !bytes.Equal(serverCertBytes, expectedCertBytes) {
105-
return fmt.Errorf("server certificate doesn't match the provided certificate")
106-
}
107-
108-
return nil
109-
}
110-
return nil
111-
}

msdsn/conn_str_go115pre.go

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,11 @@
44
package msdsn
55

66
import (
7-
"bytes"
87
"crypto/tls"
9-
"encoding/pem"
10-
"fmt"
118
)
129

1310
func setupTLSCommonName(config *tls.Config, pemData []byte) error {
1411
// Prior to Go 1.15, the TLS allowed ":" when checking the hostname.
1512
// See https://golang.org/issue/40748 for details.
1613
return skipSetup
1714
}
18-
19-
// setupTLSCertificateOnly validates that the server certificate matches the provided certificate
20-
func setupTLSCertificateOnly(config *tls.Config, pemData []byte) error {
21-
// To match the behavior of Microsoft.Data.SqlClient, we simply compare the raw bytes
22-
// of the server's certificate with the provided certificate file.
23-
24-
// Parse the expected certificate from the PEM data
25-
block, _ := pem.Decode(pemData)
26-
if block == nil {
27-
return fmt.Errorf("failed to decode PEM certificate")
28-
}
29-
// Store the raw certificate bytes (DER format) for comparison
30-
expectedCertBytes := block.Bytes
31-
32-
config.InsecureSkipVerify = true
33-
config.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
34-
if len(rawCerts) == 0 {
35-
return fmt.Errorf("no peer certificates provided")
36-
}
37-
38-
// Compare the server's certificate bytes with the expected certificate bytes
39-
serverCertBytes := rawCerts[0]
40-
41-
if !bytes.Equal(serverCertBytes, expectedCertBytes) {
42-
return fmt.Errorf("server certificate doesn't match the provided certificate")
43-
}
44-
45-
return nil
46-
}
47-
return nil
48-
}

0 commit comments

Comments
 (0)