]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/fsouza/go-dockerclient/tls.go
bb5790b5f0bf88308c64b7351d30bdc5dc802fb1
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / fsouza / go-dockerclient / tls.go
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
8 package docker
9
10 import (
11 "crypto/tls"
12 "errors"
13 "net"
14 "strings"
15 "time"
16 )
17
18 type tlsClientCon struct {
19 *tls.Conn
20 rawConn net.Conn
21 }
22
23 func (c *tlsClientCon) CloseWrite() error {
24 // Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
25 // on its underlying connection.
26 if cwc, ok := c.rawConn.(interface {
27 CloseWrite() error
28 }); ok {
29 return cwc.CloseWrite()
30 }
31 return nil
32 }
33
34 func 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.
38 timeout := dialer.Timeout
39
40 if !dialer.Deadline.IsZero() {
41 deadlineTimeout := dialer.Deadline.Sub(time.Now())
42 if timeout == 0 || deadlineTimeout < timeout {
43 timeout = deadlineTimeout
44 }
45 }
46
47 var errChannel chan error
48
49 if timeout != 0 {
50 errChannel = make(chan error, 2)
51 time.AfterFunc(timeout, func() {
52 errChannel <- errors.New("")
53 })
54 }
55
56 rawConn, err := dialer.Dial(network, addr)
57 if err != nil {
58 return nil, err
59 }
60
61 colonPos := strings.LastIndex(addr, ":")
62 if colonPos == -1 {
63 colonPos = len(addr)
64 }
65 hostname := addr[:colonPos]
66
67 // If no ServerName is set, infer the ServerName
68 // from the hostname we're connecting to.
69 if config.ServerName == "" {
70 // Make a copy to avoid polluting argument or default.
71 config = copyTLSConfig(config)
72 config.ServerName = hostname
73 }
74
75 conn := tls.Client(rawConn, config)
76
77 if timeout == 0 {
78 err = conn.Handshake()
79 } else {
80 go func() {
81 errChannel <- conn.Handshake()
82 }()
83
84 err = <-errChannel
85 }
86
87 if err != nil {
88 rawConn.Close()
89 return 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.
94 return &tlsClientCon{conn, rawConn}, nil
95 }
96
97 // this exists to silent an error message in go vet
98 func copyTLSConfig(cfg *tls.Config) *tls.Config {
99 return &tls.Config{
100 Certificates: cfg.Certificates,
101 CipherSuites: cfg.CipherSuites,
102 ClientAuth: cfg.ClientAuth,
103 ClientCAs: cfg.ClientCAs,
104 ClientSessionCache: cfg.ClientSessionCache,
105 CurvePreferences: cfg.CurvePreferences,
106 InsecureSkipVerify: cfg.InsecureSkipVerify,
107 MaxVersion: cfg.MaxVersion,
108 MinVersion: cfg.MinVersion,
109 NameToCertificate: cfg.NameToCertificate,
110 NextProtos: cfg.NextProtos,
111 PreferServerCipherSuites: cfg.PreferServerCipherSuites,
112 Rand: cfg.Rand,
113 RootCAs: cfg.RootCAs,
114 ServerName: cfg.ServerName,
115 SessionTicketKey: cfg.SessionTicketKey,
116 SessionTicketsDisabled: cfg.SessionTicketsDisabled,
117 }
118 }