From b4173c3374dd5ac45652453bebd0406c7d551f33 Mon Sep 17 00:00:00 2001 From: Shumon Huque Date: Wed, 27 May 2020 15:14:29 -0400 Subject: [PATCH] ConnectByName() function. --- byname.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ byname_test.go | 31 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 byname.go create mode 100644 byname_test.go diff --git a/byname.go b/byname.go new file mode 100644 index 0000000..35327c2 --- /dev/null +++ b/byname.go @@ -0,0 +1,56 @@ +package dane + +import ( + "crypto/tls" + "fmt" +) + +// +// ConnectByName takes a hostname and port, resolves the addresses for +// the hostname (IPv6 followed by IPv4), and then attempts to connect to +// them and establish TLS. It returns a TLS connection and dane config for +// the first address that succeeds. +// +// Uses a default DANE configuration. For a custom DANE configuration, +// use the DialTLS or DialStartTLS functions instead. +// +func ConnectByName(hostname string, port int) (*tls.Conn, *Config, error) { + + var conn *tls.Conn + + resolver, err := GetResolver("") + if err != nil { + return nil, nil, fmt.Errorf("Error obtaining resolver address: %s", err.Error()) + } + + tlsa, err := GetTLSA(resolver, hostname, port) + if err != nil { + return nil, nil, fmt.Errorf("GetTLSA: %s", err.Error()) + } + + needSecure := (tlsa != nil) + iplist, err := GetAddresses(resolver, hostname, needSecure) + if err != nil { + return nil, nil, fmt.Errorf("GetAddresses: %s", err.Error()) + } + + if len(iplist) == 0 { + return nil, nil, fmt.Errorf("No addresses found") + } + + for _, ip := range iplist { + + server := NewServer(hostname, ip, port) + config := NewConfig() + config.SetServer(server) + config.SetTLSA(tlsa) + conn, err = DialTLS(config) + if err != nil { + fmt.Printf("Connection failed to %s: %s\n", server.Address(), err.Error()) + continue + } + return conn, config, err + } + + return conn, nil, fmt.Errorf("Failed to connect to any server address") +} diff --git a/byname_test.go b/byname_test.go new file mode 100644 index 0000000..b5c61f7 --- /dev/null +++ b/byname_test.go @@ -0,0 +1,31 @@ +package dane + +/* + * Note: these test routines may not work unless you adapt this file + * to use validating DNS resolvers and appropriately configured DANE TLS + * servers you have access to. + */ + +import ( + "fmt" + "testing" +) + +func TestConnectByName(t *testing.T) { + + var hostname = "www.example.com" + var port = 443 + + conn, config, err := ConnectByName(hostname, port) + if err != nil { + t.Fatalf("%s\n", err.Error()) + } + fmt.Printf("ConnectByName: Success connecting to %s %d\n", hostname, port) + if config.Okdane { + fmt.Printf("DANE OK\n") + } else if config.Okpkix { + fmt.Printf("PKIX OK\n") + } + fmt.Printf("\n") + conn.Close() +}