Пример #1
1
func performHandshakeAndValidation(conn *tls.Conn, uri *url.URL) error {
	if err := conn.Handshake(); err != nil {
		return err
	}

	cs := conn.ConnectionState()
	if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != protocol.ProtocolName {
		return fmt.Errorf("protocol negotiation error")
	}

	q := uri.Query()
	relayIDs := q.Get("id")
	if relayIDs != "" {
		relayID, err := syncthingprotocol.DeviceIDFromString(relayIDs)
		if err != nil {
			return fmt.Errorf("relay address contains invalid verification id: %s", err)
		}

		certs := cs.PeerCertificates
		if cl := len(certs); cl != 1 {
			return fmt.Errorf("unexpected certificate count: %d", cl)
		}

		remoteID := syncthingprotocol.NewDeviceID(certs[0].Raw)
		if remoteID != relayID {
			return fmt.Errorf("relay id does not match. Expected %v got %v", relayID, remoteID)
		}
	}

	return nil
}
Пример #2
0
// checkErr logs if an error occurs and closes the tlsConn.
func checkErr(err error, tlsConn *tls.Conn) {
	if err != nil {
		tlsConn.Close()
		log.Fatalf("GBNetworkTools: %s\n", err.Error())

	}
}
Пример #3
0
func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (IntermediateConnection, error) {
	inv, err := client.GetInvitationFromRelay(uri, id, d.tlsCfg.Certificates, 10*time.Second)
	if err != nil {
		return IntermediateConnection{}, err
	}

	conn, err := client.JoinSession(inv)
	if err != nil {
		return IntermediateConnection{}, err
	}

	err = dialer.SetTCPOptions(conn)
	if err != nil {
		conn.Close()
		return IntermediateConnection{}, err
	}

	var tc *tls.Conn
	if inv.ServerSocket {
		tc = tls.Server(conn, d.tlsCfg)
	} else {
		tc = tls.Client(conn, d.tlsCfg)
	}

	err = tc.Handshake()
	if err != nil {
		tc.Close()
		return IntermediateConnection{}, err
	}

	return IntermediateConnection{tc, "Relay (Client)", relayPriority}, nil
}
Пример #4
0
func (c *connection) startTls() (err error) {
	if c.authOptions == nil {
		return nil
	}
	if c.authOptions.TlsConfig == nil {
		return ErrAuthMissingConfig
	}
	c.state = connTlsStarting
	startTlsCmd := &StartTlsCommand{}
	if err = c.execute(startTlsCmd); err != nil {
		return
	}
	var tlsConn *tls.Conn
	if tlsConn = tls.Client(c.conn, c.authOptions.TlsConfig); tlsConn == nil {
		err = ErrAuthTLSUpgradeFailed
		return
	}
	if err = tlsConn.Handshake(); err != nil {
		return
	}
	c.conn = tlsConn
	authCmd := &AuthCommand{
		User:     c.authOptions.User,
		Password: c.authOptions.Password,
	}
	err = c.execute(authCmd)
	return
}
Пример #5
0
func NewConnectingPeer(logger *util.Logger, server *TLSServer, connection *tls.Conn) *Peer {
	inst := NewPeer(logger, server, connection.RemoteAddr().String())
	inst.Connection = connection
	inst.State = PeerStateHandshake
	inst.Incoming = true
	return inst
}
Пример #6
0
// getChain returns chain of certificates retrieved from TLS session
// established at given addr (host:port) for hostname provided. If addr is
// empty, then hostname:443 is used.
func getChain(hostname, addr string) ([]*x509.Certificate, error) {
	if hostname == "" {
		return nil, errors.New("empty hostname")
	}
	var (
		conn *tls.Conn
		err  error
	)
	type tempErr interface {
		Temporary() bool
	}
	conf := &tls.Config{ServerName: hostname}
	if addr == "" {
		addr = hostname + ":443"
	}
	dialer := &net.Dialer{
		Timeout: 30 * time.Second,
	}
	for i := 0; i < 3; i++ {
		if i > 0 {
			time.Sleep(time.Duration(i) * time.Second)
		}
		conn, err = tls.DialWithDialer(dialer, "tcp", addr, conf)
		if e, ok := err.(tempErr); ok && e.Temporary() {
			continue
		}
		if err != nil {
			return nil, err
		}
		defer conn.Close()
		return conn.ConnectionState().PeerCertificates, nil
	}
	return nil, err
}
Пример #7
0
// SessionResumeScan tests that host is able to resume sessions across all addresses.
func sessionResumeScan(addr, hostname string) (grade Grade, output Output, err error) {
	config := defaultTLSConfig(hostname)
	config.ClientSessionCache = tls.NewLRUClientSessionCache(1)

	conn, err := tls.DialWithDialer(Dialer, Network, addr, config)
	if err != nil {
		return
	}
	if err = conn.Close(); err != nil {
		return
	}

	return multiscan(addr, func(addrport string) (g Grade, o Output, e error) {
		var conn *tls.Conn
		if conn, e = tls.DialWithDialer(Dialer, Network, addrport, config); e != nil {
			return
		}
		conn.Close()

		if o = conn.ConnectionState().DidResume; o.(bool) {
			g = Good
		}
		return
	})
}
Пример #8
0
// HandleStartTLS is the companion to StartTLS, and will do the connection upgrade.  It assumes
// that the TLS command byte has already been read.  Like StartTLS it returns the peer name, or
// an error
func (p *Protocol) HandleStartTLS(identity *security.Identity, caCertificate *security.Certificate) (string, error) {
	var (
		err     error
		tlsConn *tls.Conn
	)

	// Build the config
	config := new(tls.Config)
	config.ClientAuth = tls.RequireAndVerifyClientCert

	// Setup the tls connection
	if err := p.tlsSetup(config, identity, caCertificate); err != nil {
		return "", err
	}

	// Upgrade the connection to TLS
	// TODO: Add a deadline here?
	tlsConn = tls.Server(p.conn, config)
	if err = tlsConn.Handshake(); err != nil {
		return "", err
	}

	// Capture the connection state
	cs := tlsConn.ConnectionState()

	// And replace the original connection
	p.conn = net.Conn(tlsConn)
	p.setupBuffers()

	// Send an Ack
	p.Ack()

	return cs.PeerCertificates[0].Subject.CommonName, nil
}
Пример #9
0
func read(client *Client, conn *tls.Conn) {
	buffer := make([]byte, ERR_RESPONSE_LEN)

	if _, err := conn.Read(buffer); err != nil {
		log.Printf("read err %v, %v, %p\n", err, err == io.EOF, client)
		client.chConnectionErr <- conn
		return
	}

	errRsp := &errResponse{
		Command: uint8(buffer[0]),
		Status:  uint8(buffer[1]),
	}

	if err := binary.Read(bytes.NewBuffer(buffer[2:]), binary.BigEndian, &errRsp.Identifier); err != nil {
		log.Println("read identifier err", err)
		return
	}

	if errRsp.Command != ERR_RESPONSE_CMD {
		log.Println("unknown err response", buffer)
		return
	}

	errMsg, ok := ApplePushResponses[errRsp.Status]
	if !ok {
		log.Println("unknown err status", buffer)
		return
	}

	log.Printf("get err response : %##v, %s\n", errRsp, errMsg)

	client.chErrResponse <- errRsp
}
Пример #10
0
func HandleUserTimeout(UserCollection *mgo.Collection, username, RSA_Public_Key string, conn *tls.Conn, timeout_sec int) {
	log.Printf("Timeout:\tUser '%s' at %s\n", username, conn.RemoteAddr())
	err := GBServerDatabase.UpdateLastAccessedTime(UserCollection, username, string(RSA_Public_Key), 5)
	checkErr(err)
	err = GBServerDatabase.UpdateCurrentlyBeingUsed(UserCollection, username, string(RSA_Public_Key), false)
	checkErr(err)
}
Пример #11
0
func (c *connection) startTls() error {
	if c.authOptions == nil {
		return nil
	}
	if c.authOptions.TlsConfig == nil {
		return ErrAuthMissingConfig
	}
	c.setState(connTlsStarting)
	startTlsCmd := &startTlsCommand{}
	if err := c.execute(startTlsCmd); err != nil {
		return err
	}
	var tlsConn *tls.Conn
	if tlsConn = tls.Client(c.conn, c.authOptions.TlsConfig); tlsConn == nil {
		return ErrAuthTLSUpgradeFailed
	}
	if err := tlsConn.Handshake(); err != nil {
		return err
	}
	c.conn = tlsConn
	authCmd := &authCommand{
		user:     c.authOptions.User,
		password: c.authOptions.Password,
	}
	return c.execute(authCmd)
}
Пример #12
0
func connect(app string, keyFile string, certFile string, sandbox bool) {
	defer CapturePanic(fmt.Sprintf("connection to apns server error %s", app))
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		log.Printf("server : loadKeys: %s", err)
	}
	config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
	endPoint := APNS_ENDPOINT
	if sandbox {
		endPoint = APNS_SANDBOX_ENDPOINT
	}
	var conn *tls.Conn
	for {
		conn, err = tls.Dial("tcp", endPoint, &config)
		if err != nil {
			log.Println("连接服务器有误, 2秒后将重连", err)
			time.Sleep(time.Second * 2)
		} else {
			break
		}
	}

	log.Println("client is connect to ", conn.RemoteAddr())
	state := conn.ConnectionState()

	log.Println("client: hand shake ", state.HandshakeComplete)
	log.Println("client: mutual", state.NegotiatedProtocolIsMutual)
	if sandbox {
		app = app + DEVELOP_SUBFIX
	}
	info := &ConnectInfo{Connection: conn, App: app, Sandbox: sandbox, lastActivity: time.Now().Unix()}
	socketCN <- info
}
Пример #13
0
func (t *TCP) startTLS() (el element.Element, err error) {
	var tlsConn *tls.Conn
	if t.mode == stream.Initiating {
		err = t.WriteElement(element.StartTLS)
		if err != nil {
			return
		}
		el, err = t.Next()
		if err != nil || el.Tag != element.TLSProceed.Tag {
			return
		}
		tlsConn = tls.Client(t.Conn, t.conf)
	} else {
		err = t.WriteElement(element.TLSProceed)
		if err != nil {
			return
		}
		tlsConn = tls.Server(t.Conn, t.conf)
	}

	err = tlsConn.Handshake()
	if err != nil {
		return
	}
	conn := net.Conn(tlsConn)
	t.Conn = conn
	t.Decoder = xml.NewDecoder(conn)
	el = element.Element{}
	err = stream.ErrRequireRestart
	t.secure = true
	log.Println("Done upgrading connection")
	return
}
Пример #14
0
func getPublicKey(tlsConn *tls.Conn) ([]byte, error) {
	state := tlsConn.ConnectionState()
	for _, v := range state.PeerCertificates {
		return x509.MarshalPKIXPublicKey(v.PublicKey)
	}
	return []byte{}, nil
}
Пример #15
0
// Start the simple voice app on the encrypted channel.
func startVoiceApp(tlsconn *tls.Conn, remoteCN string) {
	// start the speaker part and connect it to our socket
	spr := exec.Command("/usr/bin/aplay")
	spr.Stdin = tlsconn
	err := spr.Start() // start asynchronously
	check(err)

	// start the microphone too
	// defaults: 1 channel 8000 Hz sample rate, WAVE format
	mic := exec.Command("/usr/bin/arecord")
	mic.Stdout = tlsconn
	err = mic.Start() // start asynchronously
	check(err)

	// TODO: write a ping to signal connection
	// mess := text_to_speech("Connected to %s, chat away!\n", remoteCN)
	// spr.Write([]byte(mess))

	// wait for it to finish
	// TODO: find a way to hang up the connection, short of killall arecord/aplay
	err = mic.Wait()
	check(err)
	err = spr.Wait()
	check(err)

	tlsconn.Close()
}
Пример #16
0
func postVerifyTLSConnection(conn *tls.Conn, config *TLSConfig) error {
	st := conn.ConnectionState()

	if !st.HandshakeComplete {
		return errors.New("incomplete handshake")
	}

	// no more checks if no extra configs available
	if config == nil {
		return nil
	}

	versions := config.Versions
	if versions == nil {
		versions = tlsDefaultVersions
	}
	versionOK := false
	for _, version := range versions {
		versionOK = versionOK || st.Version == uint16(version)
	}
	if !versionOK {
		return fmt.Errorf("tls version %v not configured", TLSVersion(st.Version))
	}

	return nil
}
Пример #17
0
// StartTLS takes an identity and an authority certificate and upgrades the net.Conn on the protocol to TLS
// It returns the CommonName from the peer certitifcate, or an error
func (p *Protocol) StartTLS(identity *security.Identity, caCertificate *security.Certificate) (string, error) {
	var (
		err     error
		tlsConn *tls.Conn
	)

	if err = p.WriteBytesWithDeadline([]byte{TLS}); err != nil {
		return "", err
	}

	// Build the config
	config := new(tls.Config)
	config.ServerName = p.serverName

	// Setup the tls connection
	if err = p.tlsSetup(config, identity, caCertificate); err != nil {
		return "", err
	}

	// Upgrade the connection to TLS
	// TODO: Add a deadline here?
	tlsConn = tls.Client(p.conn, config)
	if err = tlsConn.Handshake(); err != nil {
		return "", err
	}

	// Capture the connection state
	cs := tlsConn.ConnectionState()

	// And replace the original connection
	p.conn = net.Conn(tlsConn)
	p.setupBuffers()

	return cs.PeerCertificates[0].Subject.CommonName, nil
}
Пример #18
0
func closeAndCountFDs(t *testing.T, conn *tls.Conn, err error, fdStart int) {
	if err == nil {
		conn.Close()
	}
	fdEnd := countTCPFiles()
	assert.Equal(t, fdStart, fdEnd, "Number of open TCP files should be the same after test as before")
}
Пример #19
0
func Connect(cert_filename string, key_filename string, server string) (*Apn, error) {
	rchan := make(chan NotificationError)

	cert, cert_err := tls.LoadX509KeyPair(cert_filename, key_filename)
	if cert_err != nil {
		return nil, cert_err
	}

	conn, err := net.Dial("tcp", server)
	if err != nil {
		return nil, err
	}

	certificate := []tls.Certificate{cert}
	conf := tls.Config{
		Certificates: certificate,
	}

	var client_conn *tls.Conn = tls.Client(conn, &conf)
	err = client_conn.Handshake()
	if err != nil {
		return nil, err
	}

	go readError(client_conn, rchan)

	return &Apn{cert, server, client_conn, rchan}, nil
}
Пример #20
0
// Start the simple chat app on the encrypted channel.
func startChatApp(tlsconn *tls.Conn, remoteCN string) {
	// Create listener socket for the simple chat
	socket, err := net.Listen("tcp", "[::1]:0")
	check(err)
	port := getPort(socket.Addr().String())

	// start the chat app and point it to our socket
	cmd := exec.Command("uxterm", "-e", "nc", "-6", "::1", port)

	err = cmd.Start() // start asynchronously
	check(err)

	// wait for it to connect
	app, err := socket.Accept()
	check(err)

	// show a welcome message
	mess := fmt.Sprintf("Connected to %s, chat away!\n", remoteCN)
	app.Write([]byte(mess))
	app.Write([]byte(fmt.Sprintf("%s\n", strings.Repeat("-", len(mess)-1))))

	// copy the TLS-connection to the chat app and back
	go io.Copy(app, tlsconn)
	go io.Copy(tlsconn, app)

	// wait for it to finish
	err = cmd.Wait()
	check(err)

	// Close all, including the socket and the TLS channel.
	// We run this only once.
	app.Close()
	socket.Close()
	tlsconn.Close()
}
Пример #21
0
func (options *ScanOptions) SSLMatchHosts(conn *tls.Conn) []string {
	hosts := make([]string, 0)
	options.hostsMutex.Lock()
	for _, host := range options.inputHosts {
		testhost := host.Host
		if strings.Contains(testhost, ".appspot.com") {
			testhost = "appengine.google.com"
		} else if strings.Contains(testhost, "ggpht.com") {
			testhost = "googleusercontent.com"
		} else if strings.Contains(testhost, ".books.google.com") {
			testhost = "books.google.com"
		} else if strings.Contains(testhost, ".googleusercontent.com") {
			testhost = "googleusercontent.com"
		}
		if conn.VerifyHostname(testhost) == nil {
			hosts = append(hosts, host.Host)
		}
	}
	options.hostsMutex.Unlock()
	dest := make([]string, len(hosts))
	perm := rand.Perm(len(hosts))
	for i, v := range perm {
		dest[v] = hosts[i]
	}
	hosts = dest
	return hosts
}
Пример #22
0
func test_conn(conn *tls.Conn, options *ScanOptions, record *ScanRecord) bool {
	//check SSL certificate
	success := false
	for _, cert := range conn.ConnectionState().PeerCertificates {
		for _, verifyHost := range options.Config.ScanGoogleIP.SSLCertVerifyHosts {
			if cert.VerifyHostname(verifyHost) != nil {
				return false
			} else {
				success = true
			}
		}
		if success {
			break
		}
	}
	for _, verifyHost := range options.Config.ScanGoogleIP.HTTPVerifyHosts {
		conn.SetReadDeadline(time.Now().Add(record.httpVerifyTimeout))
		req, _ := http.NewRequest("HEAD", "https://"+verifyHost, nil)
		res, err := httputil.NewClientConn(conn, nil).Do(req)
		if nil != err || res.StatusCode >= 400 {
			return false
		}
	}
	return true
}
Пример #23
0
func (r *invitationReceiver) Serve() {
	for {
		select {
		case inv := <-r.invitations:
			l.Debugln("Received relay invitation", inv)
			conn, err := client.JoinSession(inv)
			if err != nil {
				l.Debugf("Failed to join relay session %s: %v", inv, err)
				continue
			}

			var tc *tls.Conn

			if inv.ServerSocket {
				tc = tls.Server(conn, r.tlsCfg)
			} else {
				tc = tls.Client(conn, r.tlsCfg)
			}
			err = tc.Handshake()
			if err != nil {
				l.Infof("TLS handshake (BEP/relay %s): %v", inv, err)
				tc.Close()
				continue
			}
			r.conns <- tc

		case <-r.stop:
			return
		}
	}
}
Пример #24
0
func find_match_hosts(conn *tls.Conn, options *ScanOptions, record *ScanRecord) bool {
	if nil == record.MatchHosts || len(record.MatchHosts) == 0 {
		record.MatchHosts = options.SSLMatchHosts(conn)
	}

	newhosts := make([]string, 0)
	for _, host := range record.MatchHosts {
		if options.HaveHostInRecords(host) {
			continue
		}
		newhosts = append(newhosts, host)
		valid := true
		for _, pattern := range options.Config.ScanGoogleHosts.HTTPVerifyHosts {
			if matchHostnames(pattern, host) {
				conn.SetReadDeadline(time.Now().Add(record.httpVerifyTimeout))
				req, _ := http.NewRequest("HEAD", "https://"+host, nil)
				res, err := httputil.NewClientConn(conn, nil).Do(req)
				if nil != err || res.StatusCode >= 400 {
					valid = false
				}
				break
			}
		}
		if valid {
			newhosts = append(newhosts, host)
		}
	}
	record.MatchHosts = newhosts
	return len(record.MatchHosts) > 0
}
Пример #25
0
// dial dials the host specified by req, using TLS if appropriate.
func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) {
	dialAddr := netutil.CanonicalAddr(req.URL)

	if req.URL.Scheme == "http" {
		if s.Dialer == nil {
			return net.Dial("tcp", dialAddr)
		} else {
			return s.Dialer.Dial("tcp", dialAddr)
		}
	}

	// TODO validate the TLSClientConfig is set up?
	var conn *tls.Conn
	var err error
	if s.Dialer == nil {
		conn, err = tls.Dial("tcp", dialAddr, s.tlsConfig)
	} else {
		conn, err = tls.DialWithDialer(s.Dialer, "tcp", dialAddr, s.tlsConfig)
	}
	if err != nil {
		return nil, err
	}

	host, _, err := net.SplitHostPort(dialAddr)
	if err != nil {
		return nil, err
	}
	err = conn.VerifyHostname(host)
	if err != nil {
		return nil, err
	}

	return conn, nil
}
Пример #26
0
Файл: client.go Проект: pyr/warp
func WritePacket(logger *log.Logger, conn *tls.Conn, p *Packet) error {

	jsbuf, err := json.Marshal(&p)
	if err != nil {
		return err
	}

	plen := len(jsbuf)
	pilen := uint32(plen)

	outlen := new(bytes.Buffer)
	binary.Write(outlen, binary.BigEndian, &pilen)

	jsbuf = append(outlen.Bytes(), jsbuf...)

	bw := 0
	for {
		if bw >= (plen + 4) {
			break
		}
		w, err := conn.Write(jsbuf)
		if err != nil {
			return err
		}
		bw = bw + w
	}
	return nil
}
Пример #27
0
func handle_tlsconn(conn *tls.Conn, context *Context) bool {
	conn.SetDeadline(time.Now().Add(config.TimeoutTLS))
	err := conn.Handshake()
	if err != nil {
		util.Log(0, "ERROR! [SECURITY] TLS Handshake: %v", err)
		return false
	}

	var no_deadline time.Time
	conn.SetDeadline(no_deadline)

	state := conn.ConnectionState()
	if len(state.PeerCertificates) == 0 {
		util.Log(0, "ERROR! [SECURITY] TLS peer has no certificate")
		return false
	}
	cert := state.PeerCertificates[0] // docs are unclear about this but I think leaf certificate is the first entry because that's as it is in tls.Certificate

	if util.LogLevel >= 2 { // because creating the dump is expensive
		util.Log(2, "DEBUG! [SECURITY] Peer certificate presented by %v:\n%v", conn.RemoteAddr(), CertificateInfo(cert))
	}

	for _, cacert := range config.CACert {
		err = cert.CheckSignatureFrom(cacert)
		if err == nil {
			if string(cacert.RawSubject) != string(cert.RawIssuer) {
				err = fmt.Errorf("Certificate was issued by wrong CA: \"%v\" instead of \"%v\"", cacert.Subject, cert.Issuer)
			} else {
				break // stop checking if we found a match for a CA. err == nil here!
			}
		}
	}

	if err != nil {
		util.Log(0, "ERROR! [SECURITY] TLS peer presented certificate not signed by trusted CA: %v", err)
		return false
	}

	for _, e := range cert.Extensions {
		if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 && e.Id[3] == 17 {
			parseSANExtension(e.Value, context)
		} else if len(e.Id) == 9 && e.Id[0] == 1 && e.Id[1] == 3 && e.Id[2] == 6 && e.Id[3] == 1 && e.Id[4] == 4 && e.Id[5] == 1 && e.Id[6] == 45753 && e.Id[7] == 1 {
			switch e.Id[8] {
			case 5:
				err = parseConnectionLimits(e.Value, context)
				if err != nil {
					util.Log(0, "ERROR! [SECURITY] GosaConnectionLimits: %v", err)
				}
			case 6: //err = parseAccessControl(e.Value, context)
				//if err != nil { util.Log(0, "ERROR! [SECURITY] GosaAccessControl: %v", err) }
			}

		}
	}

	context.TLS = true

	return true
}
Пример #28
0
func closeAndCountFDs(t *testing.T, conn *tls.Conn, err error, fdc *fdcount.Counter) {
	if err == nil {
		if err := conn.Close(); err != nil {
			t.Fatalf("Unable to close connection: %v", err)
		}
	}
	assert.NoError(t, fdc.AssertDelta(0), "Number of open TCP files should be the same after test as before")
}
Пример #29
0
// Default TLS peer name function - returns the CN of the certificate
func defaultTlsPeerName(tlsConn *tls.Conn) (tlsPeer string, ok bool) {
	state := tlsConn.ConnectionState()
	if len(state.PeerCertificates) <= 0 {
		return "", false
	}
	cn := state.PeerCertificates[0].Subject.CommonName
	return cn, true
}
Пример #30
0
// DialTLSFunc returns the adequate dial function, when using SSL, depending on
// whether we're using insecure TLS (certificate verification is disabled), or we
// have some trusted certs, or we're on android.1
// If the client's config has some trusted certs, the server's certificate will
// be checked against those in the config after the TLS handshake.
func (c *Client) DialTLSFunc() func(network, addr string) (net.Conn, error) {
	if !c.useTLS() {
		return nil
	}
	trustedCerts := c.getTrustedCerts()
	var stdTLS bool
	if !c.insecureAnyTLSCert && len(trustedCerts) == 0 {
		// TLS with normal/full verification.
		stdTLS = true
		if !android.IsChild() {
			// Not android, so let the stdlib deal with it
			return nil
		}
	}

	return func(network, addr string) (net.Conn, error) {
		var conn *tls.Conn
		var err error
		if android.IsChild() {
			ac, err := android.Dial(network, addr)
			if err != nil {
				return nil, err
			}
			var tlsConfig *tls.Config
			if stdTLS {
				tlsConfig, err = android.TLSConfig()
				if err != nil {
					return nil, err
				}
			} else {
				tlsConfig = &tls.Config{InsecureSkipVerify: true}
			}
			conn = tls.Client(ac, tlsConfig)
			if err := conn.Handshake(); err != nil {
				return nil, err
			}
		} else {
			conn, err = tls.Dial(network, addr, &tls.Config{InsecureSkipVerify: true})
			if err != nil {
				return nil, err
			}
		}
		if c.insecureAnyTLSCert {
			return conn, nil
		}
		certs := conn.ConnectionState().PeerCertificates
		if len(certs) < 1 {
			return nil, fmt.Errorf("no TLS peer certificates from %s", addr)
		}
		sig := hashutil.SHA256Prefix(certs[0].Raw)
		for _, v := range trustedCerts {
			if v == sig {
				return conn, nil
			}
		}
		return nil, fmt.Errorf("TLS server at %v presented untrusted certificate (signature %q)", addr, sig)
	}
}