Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to allow non-standard Common Name (CN) in SSL certificate verification. #705

Merged
merged 2 commits into from
Dec 11, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 41 additions & 16 deletions msdsn/conn_str.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,52 @@ type Config struct {
}

func SetupTLS(certificate string, insecureSkipVerify bool, hostInCertificate string) (*tls.Config, error) {
var config tls.Config
if certificate != "" {
pem, err := ioutil.ReadFile(certificate)
if err != nil {
return nil, fmt.Errorf("cannot read certificate %q: %v", certificate, err)
config := tls.Config{
ServerName: hostInCertificate,

// fix for https://github.com/denisenkom/go-mssqldb/issues/166
// Go implementation of TLS payload size heuristic algorithm splits single TDS package to multiple TCP segments,
// while SQL Server seems to expect one TCP segment per encrypted TDS package.
// Setting DynamicRecordSizingDisabled to true disables that algorithm and uses 16384 bytes per TLS package
DynamicRecordSizingDisabled: true,
}
if len(certificate) == 0 {
return &config, nil
}
pem, err := ioutil.ReadFile(certificate)
if err != nil {
return nil, fmt.Errorf("cannot read certificate %q: %v", certificate, err)
}
if strings.Contains(config.ServerName, ":") && !insecureSkipVerify {
// fix for https://github.com/denisenkom/go-mssqldb/issues/704
// A SSL/TLS certificate Common Name (CN) containing the ":" character
// (which is a non-standard character) will cause normal verification to fail.
// Since the VerifyConnection callback runs after normal certificate
// verification, confirm that SetupTLS() has been called
// with "insecureSkipVerify=false", then InsecureSkipVerify must be set to true
// for this VerifyConnection callback to accomplish certificate verification.
config.InsecureSkipVerify = true
config.VerifyConnection = func(cs tls.ConnectionState) error {
commonName := cs.PeerCertificates[0].Subject.CommonName
if commonName != cs.ServerName {
return fmt.Errorf("invalid certificate name %q, expected %q", commonName, cs.ServerName)
}
opts := x509.VerifyOptions{
Roots: nil,
Intermediates: x509.NewCertPool(),
}
opts.Intermediates.AppendCertsFromPEM(pem)
_, err := cs.PeerCertificates[0].Verify(opts)
return err
}
certs := x509.NewCertPool()
certs.AppendCertsFromPEM(pem)
config.RootCAs = certs
return &config, nil
}
certs := x509.NewCertPool()
certs.AppendCertsFromPEM(pem)
config.RootCAs = certs
if insecureSkipVerify {
config.InsecureSkipVerify = true
}
config.ServerName = hostInCertificate

// fix for https://github.com/denisenkom/go-mssqldb/issues/166
// Go implementation of TLS payload size heuristic algorithm splits single TDS package to multiple TCP segments,
// while SQL Server seems to expect one TCP segment per encrypted TDS package.
// Setting DynamicRecordSizingDisabled to true disables that algorithm and uses 16384 bytes per TLS package
config.DynamicRecordSizingDisabled = true

return &config, nil
}

Expand Down