Skip to content

Commit

Permalink
fix: DialTLSContext / Go 1.18+ CertificateVerify support
Browse files Browse the repository at this point in the history
This patch updates the GoVmomi SOAP client to use DialTLSContext
instead of DialTLS, as the latter has been deprecated for multiple,
major Go versions.

This patch also updates how the SOAP client handles TLS validation
with respect to thumbprints. Go 1.18+ adopted the host's certificate
verification framework, so it is necessary to alter a few things to
continue to support thumbprint verification.

* https://tip.golang.org/doc/go1.18 (search for "Certificate.Verify")
* square/certigo#264
  • Loading branch information
akutz committed Dec 12, 2022
1 parent 86f9d42 commit 05b0b08
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions vim25/soap/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,14 @@ func NewClient(u *url.URL, insecure bool) *Client {

c.hosts = make(map[string]string)
c.t.TLSClientConfig = &tls.Config{InsecureSkipVerify: c.k}
// Don't bother setting DialTLS if InsecureSkipVerify=true
if !c.k {
c.t.DialTLS = c.dialTLS
}

// Always set DialTLS and DialTLSContext, even if InsecureSkipVerify=true,
// because of how certificate verification has been delegated to the host's
// PKI framework in Go 1.18. Please see the following links for more info:
//
// * https://tip.golang.org/doc/go1.18 (search for "Certificate.Verify")
// * https://github.com/square/certigo/issues/264
c.t.DialTLSContext = c.dialTLSContext

c.Client.Transport = c.t
c.Client.Jar, _ = cookiejar.New(nil)
Expand Down Expand Up @@ -352,7 +356,10 @@ func ThumbprintSHA1(cert *x509.Certificate) string {
return strings.Join(hex, ":")
}

func (c *Client) dialTLS(network string, addr string) (net.Conn, error) {
func (c *Client) dialTLSContext(
ctx context.Context,
network, addr string) (net.Conn, error) {

// Would be nice if there was a tls.Config.Verify func,
// see tls.clientHandshakeState.doFullHandshake

Expand All @@ -366,7 +373,20 @@ func (c *Client) dialTLS(network string, addr string) (net.Conn, error) {
case x509.UnknownAuthorityError:
case x509.HostnameError:
default:
return nil, err
// Allow a thumbprint verification attempt if the error indicates
// the failure was due to lack of trust.
//
// Please note the err variable is not a special type of x509 or HTTP
// error that can be validated by a type assertion. The err variable is
// in fact an *errors.errorString.
switch {
case strings.HasSuffix(err.Error(), "certificate is not trusted"):
// darwin and linux
case strings.HasSuffix(err.Error(), "certificate signed by unknown authority"):
// windows
default:
return nil, err
}
}

thumbprint := c.Thumbprint(addr)
Expand All @@ -391,6 +411,10 @@ func (c *Client) dialTLS(network string, addr string) (net.Conn, error) {
return conn, nil
}

func (c *Client) dialTLS(network, addr string) (net.Conn, error) {
return c.dialTLSContext(context.Background(), network, addr)
}

// splitHostPort is similar to net.SplitHostPort,
// but rather than return error if there isn't a ':port',
// return an empty string for the port.
Expand Down

0 comments on commit 05b0b08

Please sign in to comment.