podman
115 строк · 2.9 Кб
1// Copyright 2014 go-dockerclient authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4//
5// The content is borrowed from Docker's own source code to provide a simple
6// tls based dialer
7
8package docker
9
10import (
11"crypto/tls"
12"errors"
13"net"
14"strings"
15"time"
16)
17
18type tlsClientCon struct {
19*tls.Conn
20rawConn net.Conn
21}
22
23func (c *tlsClientCon) CloseWrite() error {
24// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
25// on its underlying connection.
26if cwc, ok := c.rawConn.(interface {
27CloseWrite() error
28}); ok {
29return cwc.CloseWrite()
30}
31return nil
32}
33
34func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
35// We want the Timeout and Deadline values from dialer to cover the
36// whole process: TCP connection and TLS handshake. This means that we
37// also need to start our own timers now.
38timeout := dialer.Timeout
39
40if !dialer.Deadline.IsZero() {
41deadlineTimeout := time.Until(dialer.Deadline)
42if timeout == 0 || deadlineTimeout < timeout {
43timeout = deadlineTimeout
44}
45}
46
47var errChannel chan error
48
49if timeout != 0 {
50errChannel = make(chan error, 2)
51time.AfterFunc(timeout, func() {
52errChannel <- errors.New("")
53})
54}
55
56rawConn, err := dialer.Dial(network, addr)
57if err != nil {
58return nil, err
59}
60
61colonPos := strings.LastIndex(addr, ":")
62if colonPos == -1 {
63colonPos = len(addr)
64}
65hostname := addr[:colonPos]
66
67// If no ServerName is set, infer the ServerName
68// from the hostname we're connecting to.
69if config.ServerName == "" {
70// Make a copy to avoid polluting argument or default.
71config = copyTLSConfig(config)
72config.ServerName = hostname
73}
74
75conn := tls.Client(rawConn, config)
76
77if timeout == 0 {
78err = conn.Handshake()
79} else {
80go func() {
81errChannel <- conn.Handshake()
82}()
83
84err = <-errChannel
85}
86
87if err != nil {
88rawConn.Close()
89return nil, err
90}
91
92// This is Docker difference with standard's crypto/tls package: returned a
93// wrapper which holds both the TLS and raw connections.
94return &tlsClientCon{conn, rawConn}, nil
95}
96
97// this exists to silent an error message in go vet
98func copyTLSConfig(cfg *tls.Config) *tls.Config {
99return &tls.Config{
100Certificates: cfg.Certificates,
101CipherSuites: cfg.CipherSuites,
102ClientAuth: cfg.ClientAuth,
103ClientCAs: cfg.ClientCAs,
104ClientSessionCache: cfg.ClientSessionCache,
105CurvePreferences: cfg.CurvePreferences,
106InsecureSkipVerify: cfg.InsecureSkipVerify,
107MaxVersion: cfg.MaxVersion,
108MinVersion: cfg.MinVersion,
109NextProtos: cfg.NextProtos,
110Rand: cfg.Rand,
111RootCAs: cfg.RootCAs,
112ServerName: cfg.ServerName,
113SessionTicketsDisabled: cfg.SessionTicketsDisabled,
114}
115}
116