Example #1
0
// getConn dials and creates a new persistConn to the target as
// specified in the connectMethod.  This includes doing a proxy CONNECT
// and/or setting up TLS.  If this doesn't return an error, the persistConn
// is ready to write requests to.
func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
	if pc := t.getIdleConn(cm); pc != nil {
		return pc, nil
	}

	conn, err := t.dial("tcp", cm.addr())
	if err != nil {
		if cm.proxyURL != nil {
			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
		}
		return nil, err
	}

	pa := cm.proxyAuth()

	pconn := &persistConn{
		t:        t,
		cacheKey: cm.String(),
		conn:     conn,
		reqch:    make(chan requestAndChan, 50),
	}

	switch {
	case cm.proxyURL == nil:
		// Do nothing.
	case cm.targetScheme == "http":
		pconn.isProxy = true
		if pa != "" {
			pconn.mutateHeaderFunc = func(h Header) {
				h.Set("Proxy-Authorization", pa)
			}
		}
	case cm.targetScheme == "https":
		connectReq := &Request{
			Method:  "CONNECT",
			URL:     &url.URL{Opaque: cm.targetAddr},
			Host:    cm.targetAddr,
			Headers: make(Header),
		}
		if pa != "" {
			connectReq.Headers.Set("Proxy-Authorization", pa)
		}
		connectReq.Write(conn)

		// Read response.
		// Okay to use and discard buffered reader here, because
		// TLS server will not speak until spoken to.
		br := bufio.NewReader(conn)
		resp, err := ReadResponse(br, connectReq)
		if err != nil {
			conn.Close()
			return nil, err
		}
		if resp.StatusCode != 200 {
			f := strings.SplitN(resp.Status, " ", 2)
			conn.Close()
			return nil, errors.New(f[1])
		}
	}

	if cm.targetScheme == "https" {
		// Initiate TLS and check remote host name against certificate.
		conn = ztls.Client(conn, t.TLSClientConfig)
		if err = conn.(*ztls.Conn).Handshake(); err != nil {
			return nil, err
		}

		if t.TLSClientConfig == nil || !t.TLSClientConfig.InsecureSkipVerify {
			if err = conn.(*ztls.Conn).VerifyHostname(cm.tlsHost()); err != nil {
				return nil, err
			}
		}
		pconn.conn = conn
	}

	pconn.br = bufio.NewReader(pconn.conn)
	pconn.bw = bufio.NewWriter(pconn.conn)
	go pconn.readLoop()
	return pconn, nil
}
Example #2
0
// Extra method - Do a TLS Handshake and record progress
func (c *Conn) TLSHandshake() error {
	if c.isTls {
		return fmt.Errorf(
			"Attempted repeat handshake with remote host %s",
			c.RemoteAddr().String())
	}
	tlsConfig := new(ztls.Config)
	tlsConfig.InsecureSkipVerify = true
	tlsConfig.MinVersion = ztls.VersionSSL30
	tlsConfig.MaxVersion = c.maxTlsVersion
	tlsConfig.RootCAs = c.caPool
	tlsConfig.HeartbeatEnabled = true
	tlsConfig.ClientDSAEnabled = true
	if !c.noSNI && c.domain != "" {
		tlsConfig.ServerName = c.domain
	}
	if c.onlyDHE {
		tlsConfig.CipherSuites = ztls.DHECiphers
	}
	if c.onlyExports {
		tlsConfig.CipherSuites = ztls.RSA512ExportCiphers
	}
	if c.onlyExportsDH {
		tlsConfig.CipherSuites = ztls.DHEExportCiphers
	}
	if c.chromeCiphers {
		tlsConfig.CipherSuites = ztls.ChromeCiphers
	}
	if c.chromeNoDHE {
		tlsConfig.CipherSuites = ztls.ChromeNoDHECiphers
	}
	if c.firefoxCiphers {
		tlsConfig.CipherSuites = ztls.FirefoxCiphers
	}
	if c.firefoxNoDHECiphers {
		tlsConfig.CipherSuites = ztls.FirefoxNoDHECiphers
	}

	if c.safariCiphers {
		tlsConfig.CipherSuites = ztls.SafariCiphers
		tlsConfig.ForceSuites = true
	}
	if c.safariNoDHECiphers {
		tlsConfig.CipherSuites = ztls.SafariNoDHECiphers
		tlsConfig.ForceSuites = true
	}
	if c.extendedRandom {
		tlsConfig.ExtendedRandom = true
	}
	if c.gatherSessionTicket {
		tlsConfig.ForceSessionTicketExt = true
	}
	if c.offerExtendedMasterSecret {
		tlsConfig.ExtendedMasterSecret = true
	}

	c.tlsConn = ztls.Client(c.conn, tlsConfig)
	c.tlsConn.SetReadDeadline(c.readDeadline)
	c.tlsConn.SetWriteDeadline(c.writeDeadline)
	c.isTls = true
	err := c.tlsConn.Handshake()
	if tlsConfig.ForceSuites && err == ztls.ErrUnimplementedCipher {
		err = nil
	}
	hl := c.tlsConn.GetHandshakeLog()

	if !c.tlsVerbose {
		hl.KeyMaterial = nil
		hl.ClientHello = nil
		hl.ClientFinished = nil
		hl.ClientKeyExchange = nil
	}

	c.grabData.TLSHandshake = hl
	return err
}