Don't perform TLS handshake in connectToUpstream

This defers TLS handshake until the first read or write operation. This
allows the upcoming identd server to register the connection before the
TLS handshake is complete, and is necessary because some IRC servers
send an ident request before that.
This commit is contained in:
Simon Ser 2020-07-06 17:37:52 +02:00
parent c1f8002428
commit 7c31c26d86
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
1 changed files with 15 additions and 10 deletions

View File

@ -98,13 +98,15 @@ func connectToUpstream(network *network) (*upstreamConn, error) {
switch u.Scheme { switch u.Scheme {
case "ircs": case "ircs":
addr := u.Host addr := u.Host
if _, _, err := net.SplitHostPort(addr); err != nil { host, _, err := net.SplitHostPort(u.Host)
addr = addr + ":6697" if err != nil {
host = u.Host
addr = u.Host + ":6697"
} }
logger.Printf("connecting to TLS server at address %q", addr) logger.Printf("connecting to TLS server at address %q", addr)
var tlsConfig *tls.Config tlsConfig := &tls.Config{ServerName: host}
if network.SASL.Mechanism == "EXTERNAL" { if network.SASL.Mechanism == "EXTERNAL" {
if network.SASL.External.CertBlob == nil { if network.SASL.External.CertBlob == nil {
return nil, fmt.Errorf("missing certificate for authentication") return nil, fmt.Errorf("missing certificate for authentication")
@ -116,21 +118,24 @@ func connectToUpstream(network *network) (*upstreamConn, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse private key: %v", err) return nil, fmt.Errorf("failed to parse private key: %v", err)
} }
tlsConfig = &tls.Config{ tlsConfig.Certificates = []tls.Certificate{
Certificates: []tls.Certificate{ {
{ Certificate: [][]byte{network.SASL.External.CertBlob},
Certificate: [][]byte{network.SASL.External.CertBlob}, PrivateKey: key.(crypto.PrivateKey),
PrivateKey: key.(crypto.PrivateKey),
},
}, },
} }
logger.Printf("using TLS client certificate %x", sha256.Sum256(network.SASL.External.CertBlob)) logger.Printf("using TLS client certificate %x", sha256.Sum256(network.SASL.External.CertBlob))
} }
netConn, err = tls.DialWithDialer(&dialer, "tcp", addr, tlsConfig) netConn, err = dialer.Dial("tcp", addr)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to dial %q: %v", addr, err) return nil, fmt.Errorf("failed to dial %q: %v", addr, err)
} }
// Don't do the TLS handshake immediately, because we need to register
// the new connection with identd ASAP. See:
// https://todo.sr.ht/~emersion/soju/69#event-41859
netConn = tls.Client(netConn, tlsConfig)
case "irc+insecure": case "irc+insecure":
addr := u.Host addr := u.Host
if _, _, err := net.SplitHostPort(addr); err != nil { if _, _, err := net.SplitHostPort(addr); err != nil {