github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/tcp_utils.go (about)

     1  package ravendb
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"encoding/base64"
     7  	"fmt"
     8  	"net"
     9  	"net/url"
    10  )
    11  
    12  func newTLSConfig(certificate *tls.Certificate, trustStore *x509.Certificate) (*tls.Config, error) {
    13  	if certificate != nil && trustStore == nil {
    14  		return nil, newIllegalArgumentError("certificates and trustStoreASN1 can't be both empty")
    15  	}
    16  
    17  	config := &tls.Config{}
    18  
    19  	if trustStore != nil {
    20  		roots := x509.NewCertPool()
    21  		roots.AddCert(trustStore)
    22  		config.RootCAs = roots
    23  	}
    24  	// TODO: not sure if this should always (ever?) be set
    25  	// see setSSLHostnameVerifier and loadTrustMaterial in java code
    26  	config.InsecureSkipVerify = true
    27  
    28  	config.Certificates = []tls.Certificate{*certificate}
    29  	return config, nil
    30  }
    31  
    32  func tcpConnect(uri string, serverCertificateBase64 []byte, clientCertificate *tls.Certificate) (net.Conn, error) {
    33  	//  uri is in the format: tcp://127.0.0.1:14206
    34  	parsed, err := url.Parse(uri)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	if parsed.Scheme != "tcp" {
    39  		return nil, fmt.Errorf("bad url: '%s', expected scheme to be 'ftp', is '%s'", uri, parsed.Scheme)
    40  	}
    41  
    42  	if len(serverCertificateBase64) > 0 || clientCertificate != nil {
    43  		// serverCertificateBase64 is base64-encoded ASN1-encoded certificate
    44  		// This is a root signing certificate needed for tls.Dial to recognize
    45  		// data Send by the server (?) as properly signed.
    46  		// If we didn't have this we could set tls.Config.InsecureSkipVerify to true
    47  		var trustStore *x509.Certificate
    48  		if len(serverCertificateBase64) > 0 {
    49  			serverCertificate, err := base64.StdEncoding.DecodeString(string(serverCertificateBase64))
    50  			if err != nil {
    51  				return nil, err
    52  			}
    53  			trustStore, err = x509.ParseCertificate(serverCertificate)
    54  			if err != nil {
    55  				return nil, err
    56  			}
    57  		}
    58  
    59  		config, err := newTLSConfig(clientCertificate, trustStore)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		// forcing TLS 1.2 as Java code seems to be doing
    64  		config.MinVersion = tls.VersionTLS12
    65  		config.MaxVersion = tls.VersionTLS12
    66  
    67  		conn, err := tls.Dial("tcp", parsed.Host, config)
    68  		return conn, err
    69  	}
    70  
    71  	// parsed.Host is in the form "127.0.0.1:14206"
    72  	return net.Dial("tcp", parsed.Host)
    73  }