[lxc-devel] [lxd/master] candid: Fix client when using https candid server

stgraber on Github lxc-bot at linuxcontainers.org
Wed Oct 3 21:46:01 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20181003/fb9e233f/attachment.bin>
-------------- next part --------------
From 018ec48c3d92415ed02aadf3ca393ec542cb99e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 3 Oct 2018 17:45:33 -0400
Subject: [PATCH] candid: Fix client when using https candid server
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 client/connection.go | 28 +++++++++++++++++++++-------
 client/util.go       | 15 ++++++++++++++-
 shared/network.go    |  5 ++++-
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/client/connection.go b/client/connection.go
index b300cae198..f5d0e218ac 100644
--- a/client/connection.go
+++ b/client/connection.go
@@ -129,7 +129,7 @@ func ConnectPublicLXD(url string, args *ConnectionArgs) (ImageServer, error) {
 // ConnectSimpleStreams lets you connect to a remote SimpleStreams image server over HTTPs.
 //
 // Unless the remote server is trusted by the system CA, the remote certificate must be provided (TLSServerCert).
-func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error) {
+func ConnectSimpleStreams(uri string, args *ConnectionArgs) (ImageServer, error) {
 	logger.Debugf("Connecting to a remote simplestreams server")
 
 	// Use empty args if not specified
@@ -139,27 +139,34 @@ func ConnectSimpleStreams(url string, args *ConnectionArgs) (ImageServer, error)
 
 	// Initialize the client struct
 	server := ProtocolSimpleStreams{
-		httpHost:        url,
+		httpHost:        uri,
 		httpUserAgent:   args.UserAgent,
 		httpCertificate: args.TLSServerCert,
 	}
 
+	// Parse the URL
+	u, err := url.Parse(uri)
+	if err != nil {
+		return nil, err
+	}
+	tlsServerHost := u.Host
+
 	// Setup the HTTP client
-	httpClient, err := tlsHTTPClient(args.HTTPClient, args.TLSClientCert, args.TLSClientKey, args.TLSCA, args.TLSServerCert, args.InsecureSkipVerify, args.Proxy)
+	httpClient, err := tlsHTTPClient(args.HTTPClient, args.TLSClientCert, args.TLSClientKey, args.TLSCA, tlsServerHost, args.TLSServerCert, args.InsecureSkipVerify, args.Proxy)
 	if err != nil {
 		return nil, err
 	}
 	server.http = httpClient
 
 	// Get simplestreams client
-	ssClient := simplestreams.NewClient(url, *httpClient, args.UserAgent)
+	ssClient := simplestreams.NewClient(uri, *httpClient, args.UserAgent)
 	server.ssClient = ssClient
 
 	return &server, nil
 }
 
 // Internal function called by ConnectLXD and ConnectPublicLXD
-func httpsLXD(url string, args *ConnectionArgs) (ContainerServer, error) {
+func httpsLXD(uri string, args *ConnectionArgs) (ContainerServer, error) {
 	// Use empty args if not specified
 	if args == nil {
 		args = &ConnectionArgs{}
@@ -168,7 +175,7 @@ func httpsLXD(url string, args *ConnectionArgs) (ContainerServer, error) {
 	// Initialize the client struct
 	server := ProtocolLXD{
 		httpCertificate:  args.TLSServerCert,
-		httpHost:         url,
+		httpHost:         uri,
 		httpProtocol:     "https",
 		httpUserAgent:    args.UserAgent,
 		bakeryInteractor: args.AuthInteractor,
@@ -177,8 +184,15 @@ func httpsLXD(url string, args *ConnectionArgs) (ContainerServer, error) {
 		server.RequireAuthenticated(true)
 	}
 
+	// Parse the URL
+	u, err := url.Parse(uri)
+	if err != nil {
+		return nil, err
+	}
+	tlsServerHost := u.Host
+
 	// Setup the HTTP client
-	httpClient, err := tlsHTTPClient(args.HTTPClient, args.TLSClientCert, args.TLSClientKey, args.TLSCA, args.TLSServerCert, args.InsecureSkipVerify, args.Proxy)
+	httpClient, err := tlsHTTPClient(args.HTTPClient, args.TLSClientCert, args.TLSClientKey, args.TLSCA, tlsServerHost, args.TLSServerCert, args.InsecureSkipVerify, args.Proxy)
 	if err != nil {
 		return nil, err
 	}
diff --git a/client/util.go b/client/util.go
index 3826c138e1..0a5704a83d 100644
--- a/client/util.go
+++ b/client/util.go
@@ -1,6 +1,7 @@
 package lxd
 
 import (
+	"crypto/tls"
 	"fmt"
 	"io"
 	"net"
@@ -11,7 +12,7 @@ import (
 	"github.com/lxc/lxd/shared"
 )
 
-func tlsHTTPClient(client *http.Client, tlsClientCert string, tlsClientKey string, tlsCA string, tlsServerCert string, insecureSkipVerify bool, proxy func(req *http.Request) (*url.URL, error)) (*http.Client, error) {
+func tlsHTTPClient(client *http.Client, tlsClientCert string, tlsClientKey string, tlsCA string, tlsServerHost string, tlsServerCert string, insecureSkipVerify bool, proxy func(req *http.Request) (*url.URL, error)) (*http.Client, error) {
 	// Get the TLS configuration
 	tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, tlsCA, tlsServerCert, insecureSkipVerify)
 	if err != nil {
@@ -31,6 +32,18 @@ func tlsHTTPClient(client *http.Client, tlsClientCert string, tlsClientKey strin
 		transport.Proxy = proxy
 	}
 
+	// Special TLS handling
+	transport.DialTLS = func(network string, addr string) (net.Conn, error) {
+		config := transport.TLSClientConfig.Clone()
+
+		// If forwarded to another host, clear ServerName
+		if addr != tlsServerHost {
+			config.ServerName = ""
+		}
+
+		return tls.Dial(network, addr, config)
+	}
+
 	// Define the http client
 	if client == nil {
 		client = &http.Client{}
diff --git a/shared/network.go b/shared/network.go
index 1a82c7bca9..78da2966b7 100644
--- a/shared/network.go
+++ b/shared/network.go
@@ -69,7 +69,10 @@ func finalizeTLSConfig(tlsConfig *tls.Config, tlsRemoteCert *x509.Certificate) {
 	if tlsRemoteCert != nil {
 		caCertPool := tlsConfig.RootCAs
 		if caCertPool == nil {
-			caCertPool = x509.NewCertPool()
+			caCertPool, _ = x509.SystemCertPool()
+			if caCertPool == nil {
+				caCertPool = x509.NewCertPool()
+			}
 		}
 
 		// Make it a valid RootCA


More information about the lxc-devel mailing list