Set TLS server name from Mumble address
This commit is contained in:
committed by
Brandon McGinty
parent
883f7250f5
commit
05dc6e4e0e
@@ -3,6 +3,7 @@ package gumble
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"runtime"
|
||||
@@ -101,6 +102,19 @@ func Dial(config *Config) (*Client, error) {
|
||||
return DialWithDialer(new(net.Dialer), config, nil)
|
||||
}
|
||||
|
||||
// tlsServerName returns the hostname portion of a Mumble server address for
|
||||
// TLS certificate verification and SNI.
|
||||
func tlsServerName(address string) (string, error) {
|
||||
host, _, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("gumble: derive TLS server name from %q: %w", address, err)
|
||||
}
|
||||
if host == "" {
|
||||
return "", fmt.Errorf("gumble: derive TLS server name from %q: empty host", address)
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// DialWithDialer connects to the Mumble server at the address given in config.
|
||||
//
|
||||
// The function returns after the connection has been established, the initial
|
||||
@@ -120,6 +134,23 @@ func DialWithDialer(dialer *net.Dialer, config *Config, tlsConfig *tls.Config) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// tls.Client cannot infer a server name from an already-open connection.
|
||||
// Clone the caller's configuration before deriving it so reconnects and
|
||||
// concurrent clients do not mutate a shared configuration.
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{}
|
||||
} else {
|
||||
tlsConfig = tlsConfig.Clone()
|
||||
}
|
||||
if tlsConfig.ServerName == "" {
|
||||
serverName, err := tlsServerName(config.Address)
|
||||
if err != nil {
|
||||
rawConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
tlsConfig.ServerName = serverName
|
||||
}
|
||||
conn := tls.Client(rawConn, tlsConfig)
|
||||
// net.Dialer.Timeout covers only the TCP dial. Apply the same bounded
|
||||
// deadline to TLS negotiation so a peer that accepts but never responds
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package gumble
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTLSServerNameUsesAddressHost(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
address string
|
||||
want string
|
||||
}{
|
||||
{"mumble.example:64738", "mumble.example"},
|
||||
{"[2001:db8::1]:64738", "2001:db8::1"},
|
||||
} {
|
||||
got, err := tlsServerName(test.address)
|
||||
if err != nil {
|
||||
t.Errorf("tlsServerName(%q): %v", test.address, err)
|
||||
continue
|
||||
}
|
||||
if got != test.want {
|
||||
t.Errorf("tlsServerName(%q) = %q, want %q", test.address, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSServerNameRejectsAddressWithoutHost(t *testing.T) {
|
||||
if _, err := tlsServerName(":64738"); err == nil {
|
||||
t.Fatal("tlsServerName accepted an empty host")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user