123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- // Copyright 2014 go-dockerclient authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //
- // The content is borrowed from Docker's own source code to provide a simple
- // tls based dialer
- package docker
- import (
- "crypto/tls"
- "errors"
- "net"
- "strings"
- "time"
- )
- type tlsClientCon struct {
- *tls.Conn
- rawConn net.Conn
- }
- func (c *tlsClientCon) CloseWrite() error {
- // Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
- // on its underlying connection.
- if cwc, ok := c.rawConn.(interface {
- CloseWrite() error
- }); ok {
- return cwc.CloseWrite()
- }
- return nil
- }
- func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
- // We want the Timeout and Deadline values from dialer to cover the
- // whole process: TCP connection and TLS handshake. This means that we
- // also need to start our own timers now.
- timeout := dialer.Timeout
- if !dialer.Deadline.IsZero() {
- deadlineTimeout := dialer.Deadline.Sub(time.Now())
- if timeout == 0 || deadlineTimeout < timeout {
- timeout = deadlineTimeout
- }
- }
- var errChannel chan error
- if timeout != 0 {
- errChannel = make(chan error, 2)
- time.AfterFunc(timeout, func() {
- errChannel <- errors.New("")
- })
- }
- rawConn, err := dialer.Dial(network, addr)
- if err != nil {
- return nil, err
- }
- colonPos := strings.LastIndex(addr, ":")
- if colonPos == -1 {
- colonPos = len(addr)
- }
- hostname := addr[:colonPos]
- // If no ServerName is set, infer the ServerName
- // from the hostname we're connecting to.
- if config.ServerName == "" {
- // Make a copy to avoid polluting argument or default.
- config = copyTLSConfig(config)
- config.ServerName = hostname
- }
- conn := tls.Client(rawConn, config)
- if timeout == 0 {
- err = conn.Handshake()
- } else {
- go func() {
- errChannel <- conn.Handshake()
- }()
- err = <-errChannel
- }
- if err != nil {
- rawConn.Close()
- return nil, err
- }
- // This is Docker difference with standard's crypto/tls package: returned a
- // wrapper which holds both the TLS and raw connections.
- return &tlsClientCon{conn, rawConn}, nil
- }
- // this exists to silent an error message in go vet
- func copyTLSConfig(cfg *tls.Config) *tls.Config {
- return &tls.Config{
- Certificates: cfg.Certificates,
- CipherSuites: cfg.CipherSuites,
- ClientAuth: cfg.ClientAuth,
- ClientCAs: cfg.ClientCAs,
- ClientSessionCache: cfg.ClientSessionCache,
- CurvePreferences: cfg.CurvePreferences,
- InsecureSkipVerify: cfg.InsecureSkipVerify,
- MaxVersion: cfg.MaxVersion,
- MinVersion: cfg.MinVersion,
- NameToCertificate: cfg.NameToCertificate,
- NextProtos: cfg.NextProtos,
- PreferServerCipherSuites: cfg.PreferServerCipherSuites,
- Rand: cfg.Rand,
- RootCAs: cfg.RootCAs,
- ServerName: cfg.ServerName,
- SessionTicketKey: cfg.SessionTicketKey,
- SessionTicketsDisabled: cfg.SessionTicketsDisabled,
- }
- }
|