Browse code

Merge pull request #31705 from cyli/bump-go-connections

Use either a system pool or custom CA pool when connecting from client->daemon (+go-connections version bump)

Victor Vieux authored on 2017/03/22 02:36:41
Showing 3 changed files
... ...
@@ -250,8 +250,9 @@ func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, er
250 250
 		// let the api client configure the default transport.
251 251
 		return nil, nil
252 252
 	}
253
-
254
-	config, err := tlsconfig.Client(*tlsOptions)
253
+	opts := *tlsOptions
254
+	opts.ExclusiveRootPools = true
255
+	config, err := tlsconfig.Client(opts)
255 256
 	if err != nil {
256 257
 		return nil, err
257 258
 	}
... ...
@@ -17,7 +17,7 @@ github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
17 17
 golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674
18 18
 golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
19 19
 github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1
20
-github.com/docker/go-connections 7da10c8c50cad14494ec818dcdfb6506265c0086
20
+github.com/docker/go-connections a2afab9802043837035592f1c24827fb70766de9
21 21
 golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756
22 22
 
23 23
 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5
... ...
@@ -29,6 +29,11 @@ type Options struct {
29 29
 	InsecureSkipVerify bool
30 30
 	// server-only option
31 31
 	ClientAuth tls.ClientAuthType
32
+	// If ExclusiveRootPools is set, then if a CA file is provided, the root pool used for TLS
33
+	// creds will include exclusively the roots in that CA file.  If no CA file is provided,
34
+	// the system pool will be used.
35
+	ExclusiveRootPools bool
36
+	MinVersion         uint16
32 37
 }
33 38
 
34 39
 // Extra (server-side) accepted CBC cipher suites - will phase out in the future
... ...
@@ -46,6 +51,15 @@ var acceptedCBCCiphers = []uint16{
46 46
 // known weak algorithms removed.
47 47
 var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
48 48
 
49
+// allTLSVersions lists all the TLS versions and is used by the code that validates
50
+// a uint16 value as a TLS version.
51
+var allTLSVersions = map[uint16]struct{}{
52
+	tls.VersionSSL30: {},
53
+	tls.VersionTLS10: {},
54
+	tls.VersionTLS11: {},
55
+	tls.VersionTLS12: {},
56
+}
57
+
49 58
 // ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
50 59
 func ServerDefault() *tls.Config {
51 60
 	return &tls.Config{
... ...
@@ -66,11 +80,19 @@ func ClientDefault() *tls.Config {
66 66
 }
67 67
 
68 68
 // certPool returns an X.509 certificate pool from `caFile`, the certificate file.
69
-func certPool(caFile string) (*x509.CertPool, error) {
69
+func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
70 70
 	// If we should verify the server, we need to load a trusted ca
71
-	certPool, err := SystemCertPool()
72
-	if err != nil {
73
-		return nil, fmt.Errorf("failed to read system certificates: %v", err)
71
+	var (
72
+		certPool *x509.CertPool
73
+		err      error
74
+	)
75
+	if exclusivePool {
76
+		certPool = x509.NewCertPool()
77
+	} else {
78
+		certPool, err = SystemCertPool()
79
+		if err != nil {
80
+			return nil, fmt.Errorf("failed to read system certificates: %v", err)
81
+		}
74 82
 	}
75 83
 	pem, err := ioutil.ReadFile(caFile)
76 84
 	if err != nil {
... ...
@@ -83,12 +105,34 @@ func certPool(caFile string) (*x509.CertPool, error) {
83 83
 	return certPool, nil
84 84
 }
85 85
 
86
+// isValidMinVersion checks that the input value is a valid tls minimum version
87
+func isValidMinVersion(version uint16) bool {
88
+	_, ok := allTLSVersions[version]
89
+	return ok
90
+}
91
+
92
+// adjustMinVersion sets the MinVersion on `config`, the input configuration.
93
+// It assumes the current MinVersion on the `config` is the lowest allowed.
94
+func adjustMinVersion(options Options, config *tls.Config) error {
95
+	if options.MinVersion > 0 {
96
+		if !isValidMinVersion(options.MinVersion) {
97
+			return fmt.Errorf("Invalid minimum TLS version: %x", options.MinVersion)
98
+		}
99
+		if options.MinVersion < config.MinVersion {
100
+			return fmt.Errorf("Requested minimum TLS version is too low. Should be at-least: %x", config.MinVersion)
101
+		}
102
+		config.MinVersion = options.MinVersion
103
+	}
104
+
105
+	return nil
106
+}
107
+
86 108
 // Client returns a TLS configuration meant to be used by a client.
87 109
 func Client(options Options) (*tls.Config, error) {
88 110
 	tlsConfig := ClientDefault()
89 111
 	tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
90 112
 	if !options.InsecureSkipVerify && options.CAFile != "" {
91
-		CAs, err := certPool(options.CAFile)
113
+		CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
92 114
 		if err != nil {
93 115
 			return nil, err
94 116
 		}
... ...
@@ -103,6 +147,10 @@ func Client(options Options) (*tls.Config, error) {
103 103
 		tlsConfig.Certificates = []tls.Certificate{tlsCert}
104 104
 	}
105 105
 
106
+	if err := adjustMinVersion(options, tlsConfig); err != nil {
107
+		return nil, err
108
+	}
109
+
106 110
 	return tlsConfig, nil
107 111
 }
108 112
 
... ...
@@ -119,11 +167,16 @@ func Server(options Options) (*tls.Config, error) {
119 119
 	}
120 120
 	tlsConfig.Certificates = []tls.Certificate{tlsCert}
121 121
 	if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" {
122
-		CAs, err := certPool(options.CAFile)
122
+		CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
123 123
 		if err != nil {
124 124
 			return nil, err
125 125
 		}
126 126
 		tlsConfig.ClientCAs = CAs
127 127
 	}
128
+
129
+	if err := adjustMinVersion(options, tlsConfig); err != nil {
130
+		return nil, err
131
+	}
132
+
128 133
 	return tlsConfig, nil
129 134
 }