Browse code

vendor: github.com/docker/go-connections v0.6.0

- deprecate sockets.GetProxyEnv, sockets.DialerFromEnvironment
- add support for unix sockets on Windows
- remove legacy CBC cipher suites from client config
- align client and server defaults to be the same.
- remove support for encrypted TLS private keys.
- nat: optimize ParsePortSpec

full diff: https://github.com/docker/go-connections/compare/v0.5.0...v0.6.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/06/02 21:35:28
Showing 19 changed files
... ...
@@ -3,7 +3,7 @@ module github.com/moby/moby/api
3 3
 go 1.23.0
4 4
 
5 5
 require (
6
-	github.com/docker/go-connections v0.5.0
6
+	github.com/docker/go-connections v0.6.0
7 7
 	github.com/docker/go-units v0.5.0
8 8
 	github.com/google/go-cmp v0.5.9
9 9
 	github.com/moby/docker-image-spec v1.3.1
... ...
@@ -1,5 +1,5 @@
1
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
2
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
1
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
2
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
3 3
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
4 4
 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
5 5
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
... ...
@@ -7,7 +7,7 @@ require (
7 7
 	github.com/containerd/errdefs v1.0.0
8 8
 	github.com/containerd/errdefs/pkg v0.3.0
9 9
 	github.com/distribution/reference v0.6.0
10
-	github.com/docker/go-connections v0.5.0
10
+	github.com/docker/go-connections v0.6.0
11 11
 	github.com/docker/go-units v0.5.0
12 12
 	github.com/moby/moby/api v1.52.0-alpha.1
13 13
 	github.com/moby/term v0.5.2
... ...
@@ -12,8 +12,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
12 12
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13 13
 github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
14 14
 github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
15
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
16
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
15
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
16
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
17 17
 github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
18 18
 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
19 19
 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
... ...
@@ -40,7 +40,7 @@ require (
40 40
 	github.com/deckarep/golang-set/v2 v2.3.0
41 41
 	github.com/distribution/reference v0.6.0
42 42
 	github.com/docker/distribution v2.8.3+incompatible
43
-	github.com/docker/go-connections v0.5.0
43
+	github.com/docker/go-connections v0.6.0
44 44
 	github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32
45 45
 	github.com/docker/go-metrics v0.0.1
46 46
 	github.com/docker/go-units v0.5.0
... ...
@@ -183,8 +183,8 @@ github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjY
183 183
 github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
184 184
 github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
185 185
 github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
186
-github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
187
-github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
186
+github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
187
+github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
188 188
 github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk=
189 189
 github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
190 190
 github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
... ...
@@ -2,6 +2,7 @@
2 2
 package nat
3 3
 
4 4
 import (
5
+	"errors"
5 6
 	"fmt"
6 7
 	"net"
7 8
 	"strconv"
... ...
@@ -43,19 +44,19 @@ func NewPort(proto, port string) (Port, error) {
43 43
 
44 44
 // ParsePort parses the port number string and returns an int
45 45
 func ParsePort(rawPort string) (int, error) {
46
-	if len(rawPort) == 0 {
46
+	if rawPort == "" {
47 47
 		return 0, nil
48 48
 	}
49 49
 	port, err := strconv.ParseUint(rawPort, 10, 16)
50 50
 	if err != nil {
51
-		return 0, err
51
+		return 0, fmt.Errorf("invalid port '%s': %w", rawPort, errors.Unwrap(err))
52 52
 	}
53 53
 	return int(port), nil
54 54
 }
55 55
 
56 56
 // ParsePortRangeToInt parses the port range string and returns start/end ints
57 57
 func ParsePortRangeToInt(rawPort string) (int, int, error) {
58
-	if len(rawPort) == 0 {
58
+	if rawPort == "" {
59 59
 		return 0, 0, nil
60 60
 	}
61 61
 	start, end, err := ParsePortRange(rawPort)
... ...
@@ -91,29 +92,31 @@ func (p Port) Range() (int, int, error) {
91 91
 	return ParsePortRangeToInt(p.Port())
92 92
 }
93 93
 
94
-// SplitProtoPort splits a port in the format of proto/port
95
-func SplitProtoPort(rawPort string) (string, string) {
96
-	parts := strings.Split(rawPort, "/")
97
-	l := len(parts)
98
-	if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 {
94
+// SplitProtoPort splits a port(range) and protocol, formatted as "<portnum>/[<proto>]"
95
+// "<startport-endport>/[<proto>]". It returns an empty string for both if
96
+// no port(range) is provided. If a port(range) is provided, but no protocol,
97
+// the default ("tcp") protocol is returned.
98
+//
99
+// SplitProtoPort does not validate or normalize the returned values.
100
+func SplitProtoPort(rawPort string) (proto string, port string) {
101
+	port, proto, _ = strings.Cut(rawPort, "/")
102
+	if port == "" {
99 103
 		return "", ""
100 104
 	}
101
-	if l == 1 {
102
-		return "tcp", rawPort
105
+	if proto == "" {
106
+		proto = "tcp"
103 107
 	}
104
-	if len(parts[1]) == 0 {
105
-		return "tcp", parts[0]
106
-	}
107
-	return parts[1], parts[0]
108
+	return proto, port
108 109
 }
109 110
 
110
-func validateProto(proto string) bool {
111
-	for _, availableProto := range []string{"tcp", "udp", "sctp"} {
112
-		if availableProto == proto {
113
-			return true
114
-		}
111
+func validateProto(proto string) error {
112
+	switch proto {
113
+	case "tcp", "udp", "sctp":
114
+		// All good
115
+		return nil
116
+	default:
117
+		return errors.New("invalid proto: " + proto)
115 118
 	}
116
-	return false
117 119
 }
118 120
 
119 121
 // ParsePortSpecs receives port specs in the format of ip:public:private/proto and parses
... ...
@@ -123,22 +126,18 @@ func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding,
123 123
 		exposedPorts = make(map[Port]struct{}, len(ports))
124 124
 		bindings     = make(map[Port][]PortBinding)
125 125
 	)
126
-	for _, rawPort := range ports {
127
-		portMappings, err := ParsePortSpec(rawPort)
126
+	for _, p := range ports {
127
+		portMappings, err := ParsePortSpec(p)
128 128
 		if err != nil {
129 129
 			return nil, nil, err
130 130
 		}
131 131
 
132
-		for _, portMapping := range portMappings {
133
-			port := portMapping.Port
134
-			if _, exists := exposedPorts[port]; !exists {
132
+		for _, pm := range portMappings {
133
+			port := pm.Port
134
+			if _, ok := exposedPorts[port]; !ok {
135 135
 				exposedPorts[port] = struct{}{}
136 136
 			}
137
-			bslice, exists := bindings[port]
138
-			if !exists {
139
-				bslice = []PortBinding{}
140
-			}
141
-			bindings[port] = append(bslice, portMapping.Binding)
137
+			bindings[port] = append(bindings[port], pm.Binding)
142 138
 		}
143 139
 	}
144 140
 	return exposedPorts, bindings, nil
... ...
@@ -150,28 +149,34 @@ type PortMapping struct {
150 150
 	Binding PortBinding
151 151
 }
152 152
 
153
-func splitParts(rawport string) (string, string, string) {
153
+func (p *PortMapping) String() string {
154
+	return net.JoinHostPort(p.Binding.HostIP, p.Binding.HostPort+":"+string(p.Port))
155
+}
156
+
157
+func splitParts(rawport string) (hostIP, hostPort, containerPort string) {
154 158
 	parts := strings.Split(rawport, ":")
155
-	n := len(parts)
156
-	containerPort := parts[n-1]
157 159
 
158
-	switch n {
160
+	switch len(parts) {
159 161
 	case 1:
160
-		return "", "", containerPort
162
+		return "", "", parts[0]
161 163
 	case 2:
162
-		return "", parts[0], containerPort
164
+		return "", parts[0], parts[1]
163 165
 	case 3:
164
-		return parts[0], parts[1], containerPort
166
+		return parts[0], parts[1], parts[2]
165 167
 	default:
166
-		return strings.Join(parts[:n-2], ":"), parts[n-2], containerPort
168
+		n := len(parts)
169
+		return strings.Join(parts[:n-2], ":"), parts[n-2], parts[n-1]
167 170
 	}
168 171
 }
169 172
 
170 173
 // ParsePortSpec parses a port specification string into a slice of PortMappings
171 174
 func ParsePortSpec(rawPort string) ([]PortMapping, error) {
172
-	var proto string
173 175
 	ip, hostPort, containerPort := splitParts(rawPort)
174
-	proto, containerPort = SplitProtoPort(containerPort)
176
+	proto, containerPort := SplitProtoPort(containerPort)
177
+	proto = strings.ToLower(proto)
178
+	if err := validateProto(proto); err != nil {
179
+		return nil, err
180
+	}
175 181
 
176 182
 	if ip != "" && ip[0] == '[' {
177 183
 		// Strip [] from IPV6 addresses
... ...
@@ -182,7 +187,7 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
182 182
 		ip = rawIP
183 183
 	}
184 184
 	if ip != "" && net.ParseIP(ip) == nil {
185
-		return nil, fmt.Errorf("invalid IP address: %s", ip)
185
+		return nil, errors.New("invalid IP address: " + ip)
186 186
 	}
187 187
 	if containerPort == "" {
188 188
 		return nil, fmt.Errorf("no port specified: %s<empty>", rawPort)
... ...
@@ -190,51 +195,43 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
190 190
 
191 191
 	startPort, endPort, err := ParsePortRange(containerPort)
192 192
 	if err != nil {
193
-		return nil, fmt.Errorf("invalid containerPort: %s", containerPort)
193
+		return nil, errors.New("invalid containerPort: " + containerPort)
194 194
 	}
195 195
 
196
-	var startHostPort, endHostPort uint64 = 0, 0
197
-	if len(hostPort) > 0 {
196
+	var startHostPort, endHostPort uint64
197
+	if hostPort != "" {
198 198
 		startHostPort, endHostPort, err = ParsePortRange(hostPort)
199 199
 		if err != nil {
200
-			return nil, fmt.Errorf("invalid hostPort: %s", hostPort)
200
+			return nil, errors.New("invalid hostPort: " + hostPort)
201 201
 		}
202
-	}
203
-
204
-	if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
205
-		// Allow host port range iff containerPort is not a range.
206
-		// In this case, use the host port range as the dynamic
207
-		// host port range to allocate into.
208
-		if endPort != startPort {
209
-			return nil, fmt.Errorf("invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
202
+		if (endPort - startPort) != (endHostPort - startHostPort) {
203
+			// Allow host port range iff containerPort is not a range.
204
+			// In this case, use the host port range as the dynamic
205
+			// host port range to allocate into.
206
+			if endPort != startPort {
207
+				return nil, fmt.Errorf("invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
208
+			}
210 209
 		}
211 210
 	}
212 211
 
213
-	if !validateProto(strings.ToLower(proto)) {
214
-		return nil, fmt.Errorf("invalid proto: %s", proto)
215
-	}
216
-
217
-	ports := []PortMapping{}
218
-	for i := uint64(0); i <= (endPort - startPort); i++ {
219
-		containerPort = strconv.FormatUint(startPort+i, 10)
220
-		if len(hostPort) > 0 {
221
-			hostPort = strconv.FormatUint(startHostPort+i, 10)
222
-		}
223
-		// Set hostPort to a range only if there is a single container port
224
-		// and a dynamic host port.
225
-		if startPort == endPort && startHostPort != endHostPort {
226
-			hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
227
-		}
228
-		port, err := NewPort(strings.ToLower(proto), containerPort)
229
-		if err != nil {
230
-			return nil, err
231
-		}
212
+	count := endPort - startPort + 1
213
+	ports := make([]PortMapping, 0, count)
232 214
 
233
-		binding := PortBinding{
234
-			HostIP:   ip,
235
-			HostPort: hostPort,
215
+	for i := uint64(0); i < count; i++ {
216
+		cPort := Port(strconv.FormatUint(startPort+i, 10) + "/" + proto)
217
+		hPort := ""
218
+		if hostPort != "" {
219
+			hPort = strconv.FormatUint(startHostPort+i, 10)
220
+			// Set hostPort to a range only if there is a single container port
221
+			// and a dynamic host port.
222
+			if count == 1 && startHostPort != endHostPort {
223
+				hPort += "-" + strconv.FormatUint(endHostPort, 10)
224
+			}
236 225
 		}
237
-		ports = append(ports, PortMapping{Port: port, Binding: binding})
226
+		ports = append(ports, PortMapping{
227
+			Port:    cPort,
228
+			Binding: PortBinding{HostIP: ip, HostPort: hPort},
229
+		})
238 230
 	}
239 231
 	return ports, nil
240 232
 }
... ...
@@ -1,7 +1,7 @@
1 1
 package nat
2 2
 
3 3
 import (
4
-	"fmt"
4
+	"errors"
5 5
 	"strconv"
6 6
 	"strings"
7 7
 )
... ...
@@ -9,7 +9,7 @@ import (
9 9
 // ParsePortRange parses and validates the specified string as a port-range (8000-9000)
10 10
 func ParsePortRange(ports string) (uint64, uint64, error) {
11 11
 	if ports == "" {
12
-		return 0, 0, fmt.Errorf("empty string specified for ports")
12
+		return 0, 0, errors.New("empty string specified for ports")
13 13
 	}
14 14
 	if !strings.Contains(ports, "-") {
15 15
 		start, err := strconv.ParseUint(ports, 10, 16)
... ...
@@ -27,7 +27,7 @@ func ParsePortRange(ports string) (uint64, uint64, error) {
27 27
 		return 0, 0, err
28 28
 	}
29 29
 	if end < start {
30
-		return 0, 0, fmt.Errorf("invalid range specified for port: %s", ports)
30
+		return 0, 0, errors.New("invalid range specified for port: " + ports)
31 31
 	}
32 32
 	return start, end, nil
33 33
 }
34 34
deleted file mode 100644
... ...
@@ -9,6 +9,8 @@ import (
9 9
 // GetProxyEnv allows access to the uppercase and the lowercase forms of
10 10
 // proxy-related variables.  See the Go specification for details on these
11 11
 // variables. https://golang.org/pkg/net/http/
12
+//
13
+// Deprecated: this function was used as helper for [DialerFromEnvironment] and is no longer used. It will be removed in the next release.
12 14
 func GetProxyEnv(key string) string {
13 15
 	proxyValue := os.Getenv(strings.ToUpper(key))
14 16
 	if proxyValue == "" {
... ...
@@ -19,10 +21,11 @@ func GetProxyEnv(key string) string {
19 19
 
20 20
 // DialerFromEnvironment was previously used to configure a net.Dialer to route
21 21
 // connections through a SOCKS proxy.
22
-// DEPRECATED: SOCKS proxies are now supported by configuring only
22
+//
23
+// Deprecated: SOCKS proxies are now supported by configuring only
23 24
 // http.Transport.Proxy, and no longer require changing http.Transport.Dial.
24
-// Therefore, only sockets.ConfigureTransport() needs to be called, and any
25
-// sockets.DialerFromEnvironment() calls can be dropped.
25
+// Therefore, only [sockets.ConfigureTransport] needs to be called, and any
26
+// [sockets.DialerFromEnvironment] calls can be dropped.
26 27
 func DialerFromEnvironment(direct *net.Dialer) (*net.Dialer, error) {
27 28
 	return direct, nil
28 29
 }
... ...
@@ -2,13 +2,19 @@
2 2
 package sockets
3 3
 
4 4
 import (
5
+	"context"
5 6
 	"errors"
7
+	"fmt"
6 8
 	"net"
7 9
 	"net/http"
10
+	"syscall"
8 11
 	"time"
9 12
 )
10 13
 
11
-const defaultTimeout = 10 * time.Second
14
+const (
15
+	defaultTimeout        = 10 * time.Second
16
+	maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
17
+)
12 18
 
13 19
 // ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system.
14 20
 var ErrProtocolNotAvailable = errors.New("protocol not available")
... ...
@@ -35,3 +41,26 @@ func ConfigureTransport(tr *http.Transport, proto, addr string) error {
35 35
 	}
36 36
 	return nil
37 37
 }
38
+
39
+// DialPipe connects to a Windows named pipe. It is not supported on
40
+// non-Windows platforms.
41
+//
42
+// Deprecated: use [github.com/Microsoft/go-winio.DialPipe] or [github.com/Microsoft/go-winio.DialPipeContext].
43
+func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
44
+	return dialPipe(addr, timeout)
45
+}
46
+
47
+func configureUnixTransport(tr *http.Transport, proto, addr string) error {
48
+	if len(addr) > maxUnixSocketPathSize {
49
+		return fmt.Errorf("unix socket path %q is too long", addr)
50
+	}
51
+	// No need for compression in local communications.
52
+	tr.DisableCompression = true
53
+	dialer := &net.Dialer{
54
+		Timeout: defaultTimeout,
55
+	}
56
+	tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
57
+		return dialer.DialContext(ctx, proto, addr)
58
+	}
59
+	return nil
60
+}
... ...
@@ -3,37 +3,16 @@
3 3
 package sockets
4 4
 
5 5
 import (
6
-	"context"
7
-	"fmt"
8 6
 	"net"
9 7
 	"net/http"
10 8
 	"syscall"
11 9
 	"time"
12 10
 )
13 11
 
14
-const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
15
-
16
-func configureUnixTransport(tr *http.Transport, proto, addr string) error {
17
-	if len(addr) > maxUnixSocketPathSize {
18
-		return fmt.Errorf("unix socket path %q is too long", addr)
19
-	}
20
-	// No need for compression in local communications.
21
-	tr.DisableCompression = true
22
-	dialer := &net.Dialer{
23
-		Timeout: defaultTimeout,
24
-	}
25
-	tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
26
-		return dialer.DialContext(ctx, proto, addr)
27
-	}
28
-	return nil
29
-}
30
-
31 12
 func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
32 13
 	return ErrProtocolNotAvailable
33 14
 }
34 15
 
35
-// DialPipe connects to a Windows named pipe.
36
-// This is not supported on other OSes.
37
-func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
16
+func dialPipe(_ string, _ time.Duration) (net.Conn, error) {
38 17
 	return nil, syscall.EAFNOSUPPORT
39 18
 }
... ...
@@ -9,10 +9,6 @@ import (
9 9
 	"github.com/Microsoft/go-winio"
10 10
 )
11 11
 
12
-func configureUnixTransport(tr *http.Transport, proto, addr string) error {
13
-	return ErrProtocolNotAvailable
14
-}
15
-
16 12
 func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
17 13
 	// No need for compression in local communications.
18 14
 	tr.DisableCompression = true
... ...
@@ -22,7 +18,6 @@ func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
22 22
 	return nil
23 23
 }
24 24
 
25
-// DialPipe connects to a Windows named pipe.
26
-func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
25
+func dialPipe(addr string, timeout time.Duration) (net.Conn, error) {
27 26
 	return winio.DialPipe(addr, &timeout)
28 27
 }
... ...
@@ -1,5 +1,3 @@
1
-//go:build !windows
2
-
3 1
 /*
4 2
 Package sockets is a simple unix domain socket wrapper.
5 3
 
... ...
@@ -57,26 +55,6 @@ import (
57 57
 // SockOption sets up socket file's creating option
58 58
 type SockOption func(string) error
59 59
 
60
-// WithChown modifies the socket file's uid and gid
61
-func WithChown(uid, gid int) SockOption {
62
-	return func(path string) error {
63
-		if err := os.Chown(path, uid, gid); err != nil {
64
-			return err
65
-		}
66
-		return nil
67
-	}
68
-}
69
-
70
-// WithChmod modifies socket file's access mode.
71
-func WithChmod(mask os.FileMode) SockOption {
72
-	return func(path string) error {
73
-		if err := os.Chmod(path, mask); err != nil {
74
-			return err
75
-		}
76
-		return nil
77
-	}
78
-}
79
-
80 60
 // NewUnixSocketWithOpts creates a unix socket with the specified options.
81 61
 // By default, socket permissions are 0000 (i.e.: no access for anyone); pass
82 62
 // WithChmod() and WithChown() to set the desired ownership and permissions.
... ...
@@ -90,22 +68,7 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
90 90
 		return nil, err
91 91
 	}
92 92
 
93
-	// net.Listen does not allow for permissions to be set. As a result, when
94
-	// specifying custom permissions ("WithChmod()"), there is a short time
95
-	// between creating the socket and applying the permissions, during which
96
-	// the socket permissions are Less restrictive than desired.
97
-	//
98
-	// To work around this limitation of net.Listen(), we temporarily set the
99
-	// umask to 0777, which forces the socket to be created with 000 permissions
100
-	// (i.e.: no access for anyone). After that, WithChmod() must be used to set
101
-	// the desired permissions.
102
-	//
103
-	// We don't use "defer" here, to reset the umask to its original value as soon
104
-	// as possible. Ideally we'd be able to detect if WithChmod() was passed as
105
-	// an option, and skip changing umask if default permissions are used.
106
-	origUmask := syscall.Umask(0o777)
107
-	l, err := net.Listen("unix", path)
108
-	syscall.Umask(origUmask)
93
+	l, err := listenUnix(path)
109 94
 	if err != nil {
110 95
 		return nil, err
111 96
 	}
... ...
@@ -119,8 +82,3 @@ func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error
119 119
 
120 120
 	return l, nil
121 121
 }
122
-
123
-// NewUnixSocket creates a unix socket with the specified path and group.
124
-func NewUnixSocket(path string, gid int) (net.Listener, error) {
125
-	return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0o660))
126
-}
127 122
new file mode 100644
... ...
@@ -0,0 +1,54 @@
0
+//go:build !windows
1
+
2
+package sockets
3
+
4
+import (
5
+	"net"
6
+	"os"
7
+	"syscall"
8
+)
9
+
10
+// WithChown modifies the socket file's uid and gid
11
+func WithChown(uid, gid int) SockOption {
12
+	return func(path string) error {
13
+		if err := os.Chown(path, uid, gid); err != nil {
14
+			return err
15
+		}
16
+		return nil
17
+	}
18
+}
19
+
20
+// WithChmod modifies socket file's access mode.
21
+func WithChmod(mask os.FileMode) SockOption {
22
+	return func(path string) error {
23
+		if err := os.Chmod(path, mask); err != nil {
24
+			return err
25
+		}
26
+		return nil
27
+	}
28
+}
29
+
30
+// NewUnixSocket creates a unix socket with the specified path and group.
31
+func NewUnixSocket(path string, gid int) (net.Listener, error) {
32
+	return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0o660))
33
+}
34
+
35
+func listenUnix(path string) (net.Listener, error) {
36
+	// net.Listen does not allow for permissions to be set. As a result, when
37
+	// specifying custom permissions ("WithChmod()"), there is a short time
38
+	// between creating the socket and applying the permissions, during which
39
+	// the socket permissions are Less restrictive than desired.
40
+	//
41
+	// To work around this limitation of net.Listen(), we temporarily set the
42
+	// umask to 0777, which forces the socket to be created with 000 permissions
43
+	// (i.e.: no access for anyone). After that, WithChmod() must be used to set
44
+	// the desired permissions.
45
+	//
46
+	// We don't use "defer" here, to reset the umask to its original value as soon
47
+	// as possible. Ideally we'd be able to detect if WithChmod() was passed as
48
+	// an option, and skip changing umask if default permissions are used.
49
+	origUmask := syscall.Umask(0o777)
50
+	l, err := net.Listen("unix", path)
51
+	syscall.Umask(origUmask)
52
+	return l, err
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+package sockets
1
+
2
+import "net"
3
+
4
+func listenUnix(path string) (net.Listener, error) {
5
+	return net.Listen("unix", path)
6
+}
... ...
@@ -34,51 +34,37 @@ type Options struct {
34 34
 	// the system pool will be used.
35 35
 	ExclusiveRootPools bool
36 36
 	MinVersion         uint16
37
-	// If Passphrase is set, it will be used to decrypt a TLS private key
38
-	// if the key is encrypted.
39
-	//
40
-	// Deprecated: Use of encrypted TLS private keys has been deprecated, and
41
-	// will be removed in a future release. Golang has deprecated support for
42
-	// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
43
-	// design (see https://go-review.googlesource.com/c/go/+/264159).
44
-	Passphrase string
45
-}
46
-
47
-// Extra (server-side) accepted CBC cipher suites - will phase out in the future
48
-var acceptedCBCCiphers = []uint16{
49
-	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
50
-	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
51
-	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
52
-	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
53 37
 }
54 38
 
55 39
 // DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
56 40
 // options struct but wants to use a commonly accepted set of TLS cipher suites, with
57 41
 // known weak algorithms removed.
58
-var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
42
+var DefaultServerAcceptedCiphers = defaultCipherSuites
43
+
44
+// defaultCipherSuites is shared by both client and server as the default set.
45
+var defaultCipherSuites = []uint16{
46
+	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
47
+	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
48
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
49
+	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
50
+}
59 51
 
60 52
 // ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
61 53
 func ServerDefault(ops ...func(*tls.Config)) *tls.Config {
62
-	tlsConfig := &tls.Config{
63
-		// Avoid fallback by default to SSL protocols < TLS1.2
64
-		MinVersion:               tls.VersionTLS12,
65
-		PreferServerCipherSuites: true,
66
-		CipherSuites:             DefaultServerAcceptedCiphers,
67
-	}
68
-
69
-	for _, op := range ops {
70
-		op(tlsConfig)
71
-	}
72
-
73
-	return tlsConfig
54
+	return defaultConfig(ops...)
74 55
 }
75 56
 
76 57
 // ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
77 58
 func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
59
+	return defaultConfig(ops...)
60
+}
61
+
62
+// defaultConfig is the default config used by both client and server TLS configuration.
63
+func defaultConfig(ops ...func(*tls.Config)) *tls.Config {
78 64
 	tlsConfig := &tls.Config{
79
-		// Prefer TLS1.2 as the client minimum
65
+		// Avoid fallback by default to SSL protocols < TLS1.2
80 66
 		MinVersion:   tls.VersionTLS12,
81
-		CipherSuites: clientCipherSuites,
67
+		CipherSuites: defaultCipherSuites,
82 68
 	}
83 69
 
84 70
 	for _, op := range ops {
... ...
@@ -92,13 +78,13 @@ func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
92 92
 func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
93 93
 	// If we should verify the server, we need to load a trusted ca
94 94
 	var (
95
-		certPool *x509.CertPool
96
-		err      error
95
+		pool *x509.CertPool
96
+		err  error
97 97
 	)
98 98
 	if exclusivePool {
99
-		certPool = x509.NewCertPool()
99
+		pool = x509.NewCertPool()
100 100
 	} else {
101
-		certPool, err = SystemCertPool()
101
+		pool, err = SystemCertPool()
102 102
 		if err != nil {
103 103
 			return nil, fmt.Errorf("failed to read system certificates: %v", err)
104 104
 		}
... ...
@@ -107,10 +93,10 @@ func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
107 107
 	if err != nil {
108 108
 		return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
109 109
 	}
110
-	if !certPool.AppendCertsFromPEM(pemData) {
110
+	if !pool.AppendCertsFromPEM(pemData) {
111 111
 		return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
112 112
 	}
113
-	return certPool, nil
113
+	return pool, nil
114 114
 }
115 115
 
116 116
 // allTLSVersions lists all the TLS versions and is used by the code that validates
... ...
@@ -144,34 +130,32 @@ func adjustMinVersion(options Options, config *tls.Config) error {
144 144
 	return nil
145 145
 }
146 146
 
147
-// IsErrEncryptedKey returns true if the 'err' is an error of incorrect
148
-// password when trying to decrypt a TLS private key.
147
+// errEncryptedKeyDeprecated is produced when we encounter an encrypted
148
+// (password-protected) key. From https://go-review.googlesource.com/c/go/+/264159;
149 149
 //
150
-// Deprecated: Use of encrypted TLS private keys has been deprecated, and
151
-// will be removed in a future release. Golang has deprecated support for
152
-// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
153
-// design (see https://go-review.googlesource.com/c/go/+/264159).
154
-func IsErrEncryptedKey(err error) bool {
155
-	return errors.Is(err, x509.IncorrectPasswordError)
156
-}
150
+// > Legacy PEM encryption as specified in RFC 1423 is insecure by design. Since
151
+// > it does not authenticate the ciphertext, it is vulnerable to padding oracle
152
+// > attacks that can let an attacker recover the plaintext
153
+// >
154
+// > It's unfortunate that we don't implement PKCS#8 encryption so we can't
155
+// > recommend an alternative but PEM encryption is so broken that it's worth
156
+// > deprecating outright.
157
+//
158
+// Also see https://docs.docker.com/go/deprecated/
159
+var errEncryptedKeyDeprecated = errors.New("private key is encrypted; encrypted private keys are obsolete, and not supported")
157 160
 
158 161
 // getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format.
159
-// If the private key is encrypted, 'passphrase' is used to decrypted the
160
-// private key.
161
-func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) {
162
+// It returns an error if the file could not be decoded or was protected by
163
+// a passphrase.
164
+func getPrivateKey(keyBytes []byte) ([]byte, error) {
162 165
 	// this section makes some small changes to code from notary/tuf/utils/x509.go
163 166
 	pemBlock, _ := pem.Decode(keyBytes)
164 167
 	if pemBlock == nil {
165 168
 		return nil, fmt.Errorf("no valid private key found")
166 169
 	}
167 170
 
168
-	var err error
169 171
 	if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // Ignore SA1019 (IsEncryptedPEMBlock is deprecated)
170
-		keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) //nolint:staticcheck // Ignore SA1019 (DecryptPEMBlock is deprecated)
171
-		if err != nil {
172
-			return nil, fmt.Errorf("private key is encrypted, but could not decrypt it: %w", err)
173
-		}
174
-		keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes})
172
+		return nil, errEncryptedKeyDeprecated
175 173
 	}
176 174
 
177 175
 	return keyBytes, nil
... ...
@@ -195,7 +179,7 @@ func getCert(options Options) ([]tls.Certificate, error) {
195 195
 		return nil, err
196 196
 	}
197 197
 
198
-	prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase)
198
+	prKeyBytes, err = getPrivateKey(prKeyBytes)
199 199
 	if err != nil {
200 200
 		return nil, err
201 201
 	}
... ...
@@ -210,7 +194,7 @@ func getCert(options Options) ([]tls.Certificate, error) {
210 210
 
211 211
 // Client returns a TLS configuration meant to be used by a client.
212 212
 func Client(options Options) (*tls.Config, error) {
213
-	tlsConfig := ClientDefault()
213
+	tlsConfig := defaultConfig()
214 214
 	tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
215 215
 	if !options.InsecureSkipVerify && options.CAFile != "" {
216 216
 		CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
... ...
@@ -235,7 +219,7 @@ func Client(options Options) (*tls.Config, error) {
235 235
 
236 236
 // Server returns a TLS configuration meant to be used by a server.
237 237
 func Server(options Options) (*tls.Config, error) {
238
-	tlsConfig := ServerDefault()
238
+	tlsConfig := defaultConfig()
239 239
 	tlsConfig.ClientAuth = options.ClientAuth
240 240
 	tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
241 241
 	if err != nil {
242 242
deleted file mode 100644
... ...
@@ -1,14 +0,0 @@
1
-// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
2
-package tlsconfig
3
-
4
-import (
5
-	"crypto/tls"
6
-)
7
-
8
-// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
9
-var clientCipherSuites = []uint16{
10
-	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
11
-	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
12
-	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
13
-	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
14
-}
... ...
@@ -511,7 +511,7 @@ github.com/docker/distribution/registry/storage/cache/memory
511 511
 github.com/docker/docker/libnetwork/internal/resolvconf
512 512
 github.com/docker/docker/libnetwork/resolvconf
513 513
 github.com/docker/docker/profiles/seccomp
514
-# github.com/docker/go-connections v0.5.0
514
+# github.com/docker/go-connections v0.6.0
515 515
 ## explicit; go 1.18
516 516
 github.com/docker/go-connections/nat
517 517
 github.com/docker/go-connections/sockets