@@ -13,51 +13,50 @@ func setupTLSCommonName(config *tls.Config, pem []byte) error {
1313 // fix for https://github.com/denisenkom/go-mssqldb/issues/704
1414 // A SSL/TLS certificate Common Name (CN) containing the ":" character
1515 // (which is a non-standard character) will cause normal verification to fail.
16- // Since the VerifyConnection callback runs after normal certificate
17- // verification, confirm that SetupTLS() has been called
18- // with "insecureSkipVerify=false", then InsecureSkipVerify must be set to true
19- // for this VerifyConnection callback to accomplish certificate verification.
16+ // We use VerifyPeerCertificate to perform custom verification.
17+ // This is required because standard TLS verification in Go doesn't handle ":" in CN.
18+
19+ // Create a certificate pool with the provided certificate as the root CA
20+ roots := x509 .NewCertPool ()
21+ roots .AppendCertsFromPEM (pem )
22+
23+ // We must use InsecureSkipVerify=true for this specific edge case because
24+ // normal verification will fail for certificates with ":" in the CN.
25+ // The VerifyPeerCertificate callback performs proper certificate chain verification.
2026 config .InsecureSkipVerify = true
21- config .VerifyConnection = func (cs tls. ConnectionState ) error {
22- if len (cs . PeerCertificates ) == 0 {
27+ config .VerifyPeerCertificate = func (rawCerts [][] byte , verifiedChains [][] * x509. Certificate ) error {
28+ if len (rawCerts ) == 0 {
2329 return fmt .Errorf ("no peer certificates provided" )
2430 }
25- commonName := cs .PeerCertificates [0 ].Subject .CommonName
26- if commonName != cs .ServerName {
27- return fmt .Errorf ("invalid certificate name %q, expected %q" , commonName , cs .ServerName )
31+
32+ // Parse the peer certificate
33+ cert , err := x509 .ParseCertificate (rawCerts [0 ])
34+ if err != nil {
35+ return fmt .Errorf ("failed to parse certificate: %w" , err )
2836 }
29- // Create a certificate pool with the provided certificate as the root CA
30- roots := x509 .NewCertPool ()
31- roots .AppendCertsFromPEM (pem )
32-
37+
38+ // Check the common name matches the expected server name
39+ commonName := cert .Subject .CommonName
40+ if commonName != config .ServerName {
41+ return fmt .Errorf ("invalid certificate name %q, expected %q" , commonName , config .ServerName )
42+ }
43+
44+ // Verify the certificate chain against the provided root CA
3345 opts := x509.VerifyOptions {
3446 Roots : roots ,
3547 Intermediates : x509 .NewCertPool (),
3648 }
37- _ , err := cs . PeerCertificates [ 0 ] .Verify (opts )
49+ _ , err = cert .Verify (opts )
3850 return err
3951 }
4052 return nil
4153}
4254
4355// setupTLSCertificateOnly validates the certificate chain without checking the hostname
4456func setupTLSCertificateOnly (config * tls.Config , pem []byte ) error {
45- // Skip hostname validation but still verify the certificate chain
46- config .InsecureSkipVerify = true
47- config .VerifyConnection = func (cs tls.ConnectionState ) error {
48- if len (cs .PeerCertificates ) == 0 {
49- return fmt .Errorf ("no peer certificates provided" )
50- }
51- // Create a certificate pool with the provided certificate as the root CA
52- roots := x509 .NewCertPool ()
53- roots .AppendCertsFromPEM (pem )
54-
55- opts := x509.VerifyOptions {
56- Roots : roots ,
57- Intermediates : x509 .NewCertPool (),
58- }
59- _ , err := cs .PeerCertificates [0 ].Verify (opts )
60- return err
61- }
57+ // Skip hostname validation by setting ServerName to empty string
58+ // The certificate chain will still be verified against RootCAs (set later in SetupTLS)
59+ // This is the secure way to skip hostname validation without using InsecureSkipVerify
60+ config .ServerName = ""
6261 return nil
6362}
0 commit comments