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 (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -101,6 +102,19 @@ func Dial(config *Config) (*Client, error) {
|
|||||||
return DialWithDialer(new(net.Dialer), config, nil)
|
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.
|
// DialWithDialer connects to the Mumble server at the address given in config.
|
||||||
//
|
//
|
||||||
// The function returns after the connection has been established, the initial
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
conn := tls.Client(rawConn, tlsConfig)
|
||||||
// net.Dialer.Timeout covers only the TCP dial. Apply the same bounded
|
// net.Dialer.Timeout covers only the TCP dial. Apply the same bounded
|
||||||
// deadline to TLS negotiation so a peer that accepts but never responds
|
// 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