11e88be94Sjsingpackage tls 21e88be94Sjsing 31e88be94Sjsingimport ( 40b17b726Sjsing "crypto/tls" 51e88be94Sjsing "encoding/pem" 61e88be94Sjsing "fmt" 71e88be94Sjsing "io/ioutil" 81e88be94Sjsing "net/http" 91e88be94Sjsing "net/http/httptest" 101e88be94Sjsing "net/url" 111e88be94Sjsing "os" 121e88be94Sjsing "strings" 131e88be94Sjsing "testing" 14c68aa4d5Sjsing "time" 15c68aa4d5Sjsing) 16c68aa4d5Sjsing 17c68aa4d5Sjsingconst ( 18c68aa4d5Sjsing httpContent = "Hello, TLS!" 19c68aa4d5Sjsing 2099fe86a4Sjsing certHash = "SHA256:1153aa0230ee0481b36bdd83ddb04b607340dbda35f3a4fff0615e4d9292d687" 21c68aa4d5Sjsing) 22c68aa4d5Sjsing 23c68aa4d5Sjsingvar ( 24c68aa4d5Sjsing certNotBefore = time.Unix(0, 0) 25c68aa4d5Sjsing certNotAfter = certNotBefore.Add(1000000 * time.Hour) 2699fe86a4Sjsing 2799fe86a4Sjsing // Generated with: 2899fe86a4Sjsing // go run crypto/tls/generate_cert.go --rsa-bits 2048 \ 2999fe86a4Sjsing // --host 127.0.0.1,::1,example.com --ca \ 3099fe86a4Sjsing // --start-date "Jan 1 00:00:00 1970" --duration=1000000h` 3199fe86a4Sjsing testServerCert = []byte(`-----BEGIN CERTIFICATE----- 3299fe86a4SjsingMIIDGTCCAgGgAwIBAgIRAJHZkrBTk/yTKT3L2Z+dgZcwDQYJKoZIhvcNAQELBQAw 3399fe86a4SjsingEjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 3499fe86a4SjsingMDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEP 3599fe86a4SjsingADCCAQoCggEBANxPCe2pafj2pWdA+hnN+Ne9Auh2YdoSPbQqIPQMVTT/3j6w9LlW 3699fe86a4SjsingJirXCLWNuoarOA2iCgVa4Y607O/f2FTN7cKY2lvhAkuftCUJzB/lJVH5bWZgSrks 3799fe86a4Sjsing3AaOBlBcyMKBajFoEOIgSMwHGAZO2XsWIvdbuQw3EKY50vfBvxQspjbMruhpZoKd 3899fe86a4Sjsing9tHx6XUBoYSf5t9X+FrG2UjihnfcfBcsKGq7lbujt3+3QvlU6w1ZGOX+f9b+3+yw 3999fe86a4SjsingRQkswxvkzKpfmgvr8GWWUm8w9wkImhAmA2UAhsM8OwnKVltvMih5mb9L2hw5+qBV 4099fe86a4SjsingW1V+CSR0tDI9D8eiL26B3dvOilpZjttp3fsCAwEAAaNoMGYwDgYDVR0PAQH/BAQD 4199fe86a4SjsingAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wLgYDVR0R 4299fe86a4SjsingBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZI 4399fe86a4SjsinghvcNAQELBQADggEBAA+tFyWOZLoUjN2SKcIXnN5zs4VZedybLFVZoJSDakgo8awS 4499fe86a4SjsingHPkD/1ReIOzT41Hmzjs/4CeVw6FSeKnYtEqTPOJoRVrXAIqyHGHJ2cEWpUXvg2b0 4599fe86a4Sjsingu7lkFfElRqcBjsDZYr+rJUxkjlCa11ylCbgdwoDMIbKNldcJoLB0iwQWUE7j19xe 4699fe86a4SjsingCF32aISt/nGxCYcO81tn+ionwzZyf5zh5k/SmAqrPy4O/qxn8oEaox4Z7BfoZlAS 4799fe86a4SjsinggmPA2gedTWORfthamJdT2irz3rdHjV7NWxwTsgOAx9y+P3fqmMCyMwxFJkmP118W 4899fe86a4SjsingyM5xDRR+ldYKoRts5qkPR6LVtCw9kn+dJKQm0Bc= 4999fe86a4Sjsing-----END CERTIFICATE-----`) 5099fe86a4Sjsing testServerKey = []byte(`-----BEGIN PRIVATE KEY----- 5199fe86a4SjsingMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcTwntqWn49qVn 5299fe86a4SjsingQPoZzfjXvQLodmHaEj20KiD0DFU0/94+sPS5ViYq1wi1jbqGqzgNogoFWuGOtOzv 5399fe86a4Sjsing39hUze3CmNpb4QJLn7QlCcwf5SVR+W1mYEq5LNwGjgZQXMjCgWoxaBDiIEjMBxgG 5499fe86a4SjsingTtl7FiL3W7kMNxCmOdL3wb8ULKY2zK7oaWaCnfbR8el1AaGEn+bfV/haxtlI4oZ3 5599fe86a4Sjsing3HwXLChqu5W7o7d/t0L5VOsNWRjl/n/W/t/ssEUJLMMb5MyqX5oL6/BlllJvMPcJ 5699fe86a4SjsingCJoQJgNlAIbDPDsJylZbbzIoeZm/S9ocOfqgVVtVfgkkdLQyPQ/Hoi9ugd3bzopa 5799fe86a4SjsingWY7bad37AgMBAAECggEAKSmnbD1sLHVBIFK2qB2g8gZBxddgnxMrbj802wR24ykv 5899fe86a4SjsingiD0d7IcZKIX2/Z0WjdTt6zYscyWw4S4S2xrS272CQAq5OdOHz0NusEDtX8Q7vd5B 5999fe86a4Sjsingv5AcRg8IqTzeFyPO6vCtO7/675UipORqa7tNzT6sl9UOdSbQuI4zSdFsd0OEZtZs 6099fe86a4SjsingoqKkv+jdvKaVJQ1vsoQSup23V0bvVCRydBNFZ2mQ3etZcRRYXyu1digJ7/oMyCHf 6199fe86a4Sjsing1F37lJmjPJ8WwsGJMk2ngJiUOQx21bbTZ22c/8sMMLJjhhC2qu984keVRanSsJwC 6299fe86a4SjsingZ80XcCxL/yoLF42A5ReMtutFs83rW7VX7VJGxoOaKQKBgQD91dCs9jGBVxHr4vxy 6399fe86a4SjsingNJC2n92R5/JpqXygXS3L6RDP+we6p/fmSd4/QllwIVeC9kepsFz4//ArmLOy9JHu 6499fe86a4SjsingrkXa7W9G+XbmYXSftmG78roLfAtvdudoytLQJg2bu8J3bzPVibRCUq0OORFyqOHR 6599fe86a4SjsingQGcQtvPxwFHctIkOjajbLpbL7QKBgQDeMAbvjzD8wU1gp2U8Bl5l5ohYgQpcs15R 6699fe86a4SjsingeBPS5DlRzICAeuQWi+BRjW5BPZVmTr3Ml3KiMWcalXMeH1TKoPON8RjmWgY2Fxvh 6799fe86a4SjsingnS7gV+rJm4H0T+bBEXNAraracwGYd6JgcH9BPD9znHRmyFR4pMPqkSa7o/OExH6W 6899fe86a4SjsingO32KqTMkhwKBgQCoX7wb/vK3qNnqbpal6thTS5fdwM276QESHrzSFbdhPlLSLbjy 6999fe86a4SjsinguO0DaS+KgZNa+6JtnN8PDDZztMb+XdyvRkpv/i9iFPgZuWtyxbfuxANEuvOa7HRz 7099fe86a4SjsingvpY4HAXK17EXKFxpuP4pQE4qsRAxznR8KQw0uib2pWunytlfHfhz62N7wQKBgQC+ 7199fe86a4Sjsing+TTc74zBkzx42SiwYSD+IRoMSE2pxBpLmBQh7jw+TLIevIITxwJ11kRwGwiwuPl2 7299fe86a4SjsingQq4rLp9aQB6EQ5XT3Ge7FwG57KLuFwrF7x59gdOymdEnNw414FPZwevae4Nhk2Kj 7399fe86a4Sjsing1c3rOmenbVC3j3TbhXNHyJ8sJQ2IjoPniRas+iWVPQKBgQDcZzKh6U+e9efYLAt0 7499fe86a4SjsingqdaKhm5MCAgzD9X/Tx2OvOqgWnSXt2Q2AhK2UsHnrGBn1SDNTNDGlniQy2OM2Ywn 7599fe86a4Sjsingn71nH1QUmgoiwBrFUh0gLxv878vwgUATqfFRTlirmK9XxHuTX9Jh6elmRebjYWyc 7699fe86a4SjsingOo0CJBeMABu71Y+VkCxURT1bzw== 7799fe86a4Sjsing-----END PRIVATE KEY-----`) 781e88be94Sjsing) 791e88be94Sjsing 800b17b726Sjsingtype handshakeError string 810b17b726Sjsing 820b17b726Sjsingfunc (he handshakeError) Error() string { 830b17b726Sjsing return string(he) 840b17b726Sjsing} 850b17b726Sjsing 861e88be94Sjsing// createCAFile writes a PEM encoded version of the certificate out to a 871e88be94Sjsing// temporary file, for use by libtls. 881e88be94Sjsingfunc createCAFile(cert []byte) (string, error) { 891e88be94Sjsing f, err := ioutil.TempFile("", "tls") 901e88be94Sjsing if err != nil { 911e88be94Sjsing return "", fmt.Errorf("failed to create file: %v", err) 921e88be94Sjsing } 931e88be94Sjsing defer f.Close() 941e88be94Sjsing block := &pem.Block{ 951e88be94Sjsing Type: "CERTIFICATE", 961e88be94Sjsing Bytes: cert, 971e88be94Sjsing } 981e88be94Sjsing if err := pem.Encode(f, block); err != nil { 991e88be94Sjsing return "", fmt.Errorf("failed to encode certificate: %v", err) 1001e88be94Sjsing } 1011e88be94Sjsing return f.Name(), nil 1021e88be94Sjsing} 1031e88be94Sjsing 1040b17b726Sjsingfunc newTestServer(tlsCfg *tls.Config) (*httptest.Server, *url.URL, string, error) { 1050b17b726Sjsing ts := httptest.NewUnstartedServer( 1061e88be94Sjsing http.HandlerFunc( 1071e88be94Sjsing func(w http.ResponseWriter, r *http.Request) { 1081e88be94Sjsing fmt.Fprintln(w, httpContent) 1091e88be94Sjsing }, 1101e88be94Sjsing ), 1111e88be94Sjsing ) 11299fe86a4Sjsing if tlsCfg == nil { 11399fe86a4Sjsing tlsCfg = &tls.Config{} 11499fe86a4Sjsing } 11599fe86a4Sjsing if len(tlsCfg.Certificates) == 0 { 11699fe86a4Sjsing cert, err := tls.X509KeyPair(testServerCert, testServerKey) 11799fe86a4Sjsing if err != nil { 11899fe86a4Sjsing return nil, nil, "", fmt.Errorf("failed to load key pair: %v", err) 11999fe86a4Sjsing } 12099fe86a4Sjsing tlsCfg.Certificates = []tls.Certificate{cert} 12199fe86a4Sjsing } 1220b17b726Sjsing ts.TLS = tlsCfg 1230b17b726Sjsing ts.StartTLS() 1241e88be94Sjsing 1251e88be94Sjsing u, err := url.Parse(ts.URL) 1261e88be94Sjsing if err != nil { 127c68aa4d5Sjsing return nil, nil, "", fmt.Errorf("failed to parse URL %q: %v", ts.URL, err) 1281e88be94Sjsing } 1291e88be94Sjsing 1301e88be94Sjsing caFile, err := createCAFile(ts.TLS.Certificates[0].Certificate[0]) 1311e88be94Sjsing if err != nil { 132c68aa4d5Sjsing return nil, nil, "", fmt.Errorf("failed to create CA file: %v", err) 133c68aa4d5Sjsing } 134c68aa4d5Sjsing 135c68aa4d5Sjsing return ts, u, caFile, nil 136c68aa4d5Sjsing} 137c68aa4d5Sjsing 1380b17b726Sjsingfunc handshakeVersionTest(tlsCfg *tls.Config) (ProtocolVersion, error) { 1390b17b726Sjsing ts, u, caFile, err := newTestServer(tlsCfg) 1400b17b726Sjsing if err != nil { 1410b17b726Sjsing return 0, fmt.Errorf("failed to start test server: %v", err) 1420b17b726Sjsing } 1430b17b726Sjsing defer os.Remove(caFile) 1440b17b726Sjsing defer ts.Close() 1450b17b726Sjsing 1460b17b726Sjsing if err := Init(); err != nil { 1470b17b726Sjsing return 0, err 1480b17b726Sjsing } 1490b17b726Sjsing 1500b17b726Sjsing cfg, err := NewConfig() 1510b17b726Sjsing if err != nil { 1520b17b726Sjsing return 0, err 1530b17b726Sjsing } 1540b17b726Sjsing defer cfg.Free() 1550b17b726Sjsing if err := cfg.SetCAFile(caFile); err != nil { 1560b17b726Sjsing return 0, err 1570b17b726Sjsing } 1580b17b726Sjsing if err := cfg.SetCiphers("compat"); err != nil { 1590b17b726Sjsing return 0, err 1600b17b726Sjsing } 1610b17b726Sjsing if err := cfg.SetProtocols(ProtocolsAll); err != nil { 1620b17b726Sjsing return 0, err 1630b17b726Sjsing } 1640b17b726Sjsing 1650b17b726Sjsing tls, err := NewClient(cfg) 1660b17b726Sjsing if err != nil { 1670b17b726Sjsing return 0, err 1680b17b726Sjsing } 1690b17b726Sjsing defer tls.Free() 1700b17b726Sjsing 1710b17b726Sjsing if err := tls.Connect(u.Host, ""); err != nil { 1720b17b726Sjsing return 0, err 1730b17b726Sjsing } 1740b17b726Sjsing if err := tls.Handshake(); err != nil { 1750b17b726Sjsing return 0, handshakeError(err.Error()) 1760b17b726Sjsing } 1770b17b726Sjsing version, err := tls.ConnVersion() 1780b17b726Sjsing if err != nil { 1790b17b726Sjsing return 0, err 1800b17b726Sjsing } 1810b17b726Sjsing if err := tls.Close(); err != nil { 1820b17b726Sjsing return 0, err 1830b17b726Sjsing } 1840b17b726Sjsing return version, nil 1850b17b726Sjsing} 1860b17b726Sjsing 187c68aa4d5Sjsingfunc TestTLSBasic(t *testing.T) { 1880b17b726Sjsing ts, u, caFile, err := newTestServer(nil) 189c68aa4d5Sjsing if err != nil { 190c68aa4d5Sjsing t.Fatalf("Failed to start test server: %v", err) 1911e88be94Sjsing } 1921e88be94Sjsing defer os.Remove(caFile) 193c68aa4d5Sjsing defer ts.Close() 1941e88be94Sjsing 1951e88be94Sjsing if err := Init(); err != nil { 1961e88be94Sjsing t.Fatal(err) 1971e88be94Sjsing } 1981e88be94Sjsing 1991e88be94Sjsing cfg, err := NewConfig() 2001e88be94Sjsing if err != nil { 2011e88be94Sjsing t.Fatal(err) 2021e88be94Sjsing } 2031e88be94Sjsing defer cfg.Free() 2046cbf0df4Sjsing if err := cfg.SetCAFile(caFile); err != nil { 2056cbf0df4Sjsing t.Fatal(err) 2066cbf0df4Sjsing } 2071e88be94Sjsing 2081e88be94Sjsing tls, err := NewClient(cfg) 2091e88be94Sjsing if err != nil { 2101e88be94Sjsing t.Fatal(err) 2111e88be94Sjsing } 2121e88be94Sjsing defer tls.Free() 2131e88be94Sjsing 2141e88be94Sjsing t.Logf("Connecting to %s", u.Host) 2151e88be94Sjsing 2161e88be94Sjsing if err := tls.Connect(u.Host, ""); err != nil { 2171e88be94Sjsing t.Fatal(err) 2181e88be94Sjsing } 2191e88be94Sjsing defer func() { 2201e88be94Sjsing if err := tls.Close(); err != nil { 22163818bffSjsing t.Fatalf("Close failed: %v", err) 2221e88be94Sjsing } 2231e88be94Sjsing }() 2241e88be94Sjsing 2251e88be94Sjsing n, err := tls.Write([]byte("GET / HTTP/1.0\n\n")) 2261e88be94Sjsing if err != nil { 2271e88be94Sjsing t.Fatal(err) 2281e88be94Sjsing } 2291e88be94Sjsing t.Logf("Wrote %d bytes...", n) 2301e88be94Sjsing 2311e88be94Sjsing buf := make([]byte, 1024) 2321e88be94Sjsing n, err = tls.Read(buf) 2331e88be94Sjsing if err != nil { 2341e88be94Sjsing t.Fatal(err) 2351e88be94Sjsing } 2361e88be94Sjsing t.Logf("Read %d bytes...", n) 2371e88be94Sjsing 2381e88be94Sjsing if !strings.Contains(string(buf), httpContent) { 2391e88be94Sjsing t.Errorf("Response does not contain %q", httpContent) 2401e88be94Sjsing } 2411e88be94Sjsing} 242c68aa4d5Sjsing 2430b17b726Sjsingfunc TestTLSVersions(t *testing.T) { 2440b17b726Sjsing tests := []struct { 2450b17b726Sjsing minVersion uint16 2460b17b726Sjsing maxVersion uint16 2470b17b726Sjsing wantVersion ProtocolVersion 2480b17b726Sjsing wantHandshakeErr bool 2490b17b726Sjsing }{ 2504f528881Sjsing {tls.VersionTLS10, tls.VersionTLS13, ProtocolTLSv13, false}, 2510b17b726Sjsing {tls.VersionSSL30, tls.VersionTLS12, ProtocolTLSv12, false}, 2520b17b726Sjsing {tls.VersionTLS10, tls.VersionTLS12, ProtocolTLSv12, false}, 2530b17b726Sjsing {tls.VersionTLS11, tls.VersionTLS12, ProtocolTLSv12, false}, 2545c389b79Sbeck {tls.VersionSSL30, tls.VersionTLS11, ProtocolTLSv11, true}, 2555c389b79Sbeck {tls.VersionSSL30, tls.VersionTLS10, ProtocolTLSv10, true}, 2560b17b726Sjsing {tls.VersionSSL30, tls.VersionSSL30, 0, true}, 2575c389b79Sbeck {tls.VersionTLS10, tls.VersionTLS10, ProtocolTLSv10, true}, 2585c389b79Sbeck {tls.VersionTLS11, tls.VersionTLS11, ProtocolTLSv11, true}, 2590b17b726Sjsing {tls.VersionTLS12, tls.VersionTLS12, ProtocolTLSv12, false}, 2600b17b726Sjsing } 2610b17b726Sjsing for i, test := range tests { 2620b17b726Sjsing t.Logf("Testing handshake with protocols %x:%x", test.minVersion, test.maxVersion) 2630b17b726Sjsing tlsCfg := &tls.Config{ 2640b17b726Sjsing MinVersion: test.minVersion, 2650b17b726Sjsing MaxVersion: test.maxVersion, 2660b17b726Sjsing } 2670b17b726Sjsing version, err := handshakeVersionTest(tlsCfg) 2680b17b726Sjsing switch { 2690b17b726Sjsing case test.wantHandshakeErr && err == nil: 2700b17b726Sjsing t.Errorf("Test %d - handshake %x:%x succeeded, want handshake error", 2710b17b726Sjsing i, test.minVersion, test.maxVersion) 2720b17b726Sjsing case test.wantHandshakeErr && err != nil: 2730b17b726Sjsing if _, ok := err.(handshakeError); !ok { 2740b17b726Sjsing t.Errorf("Test %d - handshake %x:%x; got unknown error, want handshake error: %v", 2750b17b726Sjsing i, test.minVersion, test.maxVersion, err) 2760b17b726Sjsing } 2770b17b726Sjsing case !test.wantHandshakeErr && err != nil: 2780b17b726Sjsing t.Errorf("Test %d - handshake %x:%x failed: %v", i, test.minVersion, test.maxVersion, err) 2790b17b726Sjsing case !test.wantHandshakeErr && err == nil: 2800b17b726Sjsing if got, want := version, test.wantVersion; got != want { 2810b17b726Sjsing t.Errorf("Test %d - handshake %x:%x; got protocol version %v, want %v", 2820b17b726Sjsing i, test.minVersion, test.maxVersion, got, want) 2830b17b726Sjsing } 2840b17b726Sjsing } 2850b17b726Sjsing } 2860b17b726Sjsing} 2870b17b726Sjsing 2887396c4efSjsingfunc TestTLSSingleByteReadWrite(t *testing.T) { 2890b17b726Sjsing ts, u, caFile, err := newTestServer(nil) 2907396c4efSjsing if err != nil { 2917396c4efSjsing t.Fatalf("Failed to start test server: %v", err) 2927396c4efSjsing } 2937396c4efSjsing defer os.Remove(caFile) 2947396c4efSjsing defer ts.Close() 2957396c4efSjsing 2967396c4efSjsing if err := Init(); err != nil { 2977396c4efSjsing t.Fatal(err) 2987396c4efSjsing } 2997396c4efSjsing 3007396c4efSjsing cfg, err := NewConfig() 3017396c4efSjsing if err != nil { 3027396c4efSjsing t.Fatal(err) 3037396c4efSjsing } 3047396c4efSjsing defer cfg.Free() 3056cbf0df4Sjsing if err := cfg.SetCAFile(caFile); err != nil { 3066cbf0df4Sjsing t.Fatal(err) 3076cbf0df4Sjsing } 3087396c4efSjsing 3097396c4efSjsing tls, err := NewClient(cfg) 3107396c4efSjsing if err != nil { 3117396c4efSjsing t.Fatal(err) 3127396c4efSjsing } 3137396c4efSjsing defer tls.Free() 3147396c4efSjsing 3157396c4efSjsing t.Logf("Connecting to %s", u.Host) 3167396c4efSjsing 3177396c4efSjsing if err := tls.Connect(u.Host, ""); err != nil { 3187396c4efSjsing t.Fatal(err) 3197396c4efSjsing } 3207396c4efSjsing defer func() { 3217396c4efSjsing if err := tls.Close(); err != nil { 3227396c4efSjsing t.Fatalf("Close failed: %v", err) 3237396c4efSjsing } 3247396c4efSjsing }() 3257396c4efSjsing 3267396c4efSjsing for _, b := range []byte("GET / HTTP/1.0\n\n") { 3277396c4efSjsing n, err := tls.Write([]byte{b}) 3287396c4efSjsing if err != nil { 3297396c4efSjsing t.Fatal(err) 3307396c4efSjsing } 3317396c4efSjsing if n != 1 { 3327396c4efSjsing t.Fatalf("Wrote byte %v, got length %d, want 1", b, n) 3337396c4efSjsing } 3347396c4efSjsing } 3357396c4efSjsing 3367396c4efSjsing var body []byte 3377396c4efSjsing for { 3387396c4efSjsing buf := make([]byte, 1) 3397396c4efSjsing n, err := tls.Read(buf) 3407396c4efSjsing if err != nil { 3417396c4efSjsing t.Fatal(err) 3427396c4efSjsing } 3437396c4efSjsing if n == 0 { 3447396c4efSjsing break 3457396c4efSjsing } 3467396c4efSjsing if n != 1 { 3477396c4efSjsing t.Fatalf("Read single byte, got length %d, want 1", n) 3487396c4efSjsing } 3497396c4efSjsing body = append(body, buf...) 3507396c4efSjsing } 3517396c4efSjsing 3527396c4efSjsing if !strings.Contains(string(body), httpContent) { 3537396c4efSjsing t.Errorf("Response does not contain %q", httpContent) 3547396c4efSjsing } 3557396c4efSjsing} 3567396c4efSjsing 357c68aa4d5Sjsingfunc TestTLSInfo(t *testing.T) { 3580b17b726Sjsing ts, u, caFile, err := newTestServer(nil) 359c68aa4d5Sjsing if err != nil { 360c68aa4d5Sjsing t.Fatalf("Failed to start test server: %v", err) 361c68aa4d5Sjsing } 362c68aa4d5Sjsing defer os.Remove(caFile) 363c68aa4d5Sjsing defer ts.Close() 364c68aa4d5Sjsing 365c68aa4d5Sjsing if err := Init(); err != nil { 366c68aa4d5Sjsing t.Fatal(err) 367c68aa4d5Sjsing } 368c68aa4d5Sjsing 369c68aa4d5Sjsing cfg, err := NewConfig() 370c68aa4d5Sjsing if err != nil { 371c68aa4d5Sjsing t.Fatal(err) 372c68aa4d5Sjsing } 373c68aa4d5Sjsing defer cfg.Free() 3746cbf0df4Sjsing if err := cfg.SetCAFile(caFile); err != nil { 3756cbf0df4Sjsing t.Fatal(err) 3766cbf0df4Sjsing } 377c68aa4d5Sjsing 378c68aa4d5Sjsing tls, err := NewClient(cfg) 379c68aa4d5Sjsing if err != nil { 380c68aa4d5Sjsing t.Fatal(err) 381c68aa4d5Sjsing } 382c68aa4d5Sjsing defer tls.Free() 383c68aa4d5Sjsing 384c68aa4d5Sjsing t.Logf("Connecting to %s", u.Host) 385c68aa4d5Sjsing 386c68aa4d5Sjsing if err := tls.Connect(u.Host, ""); err != nil { 387c68aa4d5Sjsing t.Fatal(err) 388c68aa4d5Sjsing } 389c68aa4d5Sjsing defer func() { 390c68aa4d5Sjsing if err := tls.Close(); err != nil { 391c68aa4d5Sjsing t.Fatalf("Close failed: %v", err) 392c68aa4d5Sjsing } 393c68aa4d5Sjsing }() 394c68aa4d5Sjsing 395c68aa4d5Sjsing // All of these should fail since the handshake has not completed. 396c68aa4d5Sjsing if _, err := tls.ConnVersion(); err == nil { 397c68aa4d5Sjsing t.Error("ConnVersion() return nil error, want error") 398c68aa4d5Sjsing } 399c68aa4d5Sjsing if _, err := tls.ConnCipher(); err == nil { 400c68aa4d5Sjsing t.Error("ConnCipher() return nil error, want error") 401c68aa4d5Sjsing } 402b97dc7d2Sjsing if _, err := tls.ConnCipherStrength(); err == nil { 403b97dc7d2Sjsing t.Error("ConnCipherStrength() return nil error, want error") 404b97dc7d2Sjsing } 405c68aa4d5Sjsing 406c68aa4d5Sjsing if got, want := tls.PeerCertProvided(), false; got != want { 407c68aa4d5Sjsing t.Errorf("PeerCertProvided() = %v, want %v", got, want) 408c68aa4d5Sjsing } 409c68aa4d5Sjsing for _, name := range []string{"127.0.0.1", "::1", "example.com"} { 410c68aa4d5Sjsing if got, want := tls.PeerCertContainsName(name), false; got != want { 411c68aa4d5Sjsing t.Errorf("PeerCertContainsName(%q) = %v, want %v", name, got, want) 412c68aa4d5Sjsing } 413c68aa4d5Sjsing } 414c68aa4d5Sjsing 415c68aa4d5Sjsing if _, err := tls.PeerCertIssuer(); err == nil { 416c68aa4d5Sjsing t.Error("PeerCertIssuer() returned nil error, want error") 417c68aa4d5Sjsing } 418c68aa4d5Sjsing if _, err := tls.PeerCertSubject(); err == nil { 419c68aa4d5Sjsing t.Error("PeerCertSubject() returned nil error, want error") 420c68aa4d5Sjsing } 421*7f9db3f5Stb if _, err := tls.PeerCertCommonName(); err == nil { 422*7f9db3f5Stb t.Error("PeerCertCommonName() returned nil error, want error") 423*7f9db3f5Stb } 424c68aa4d5Sjsing if _, err := tls.PeerCertHash(); err == nil { 425c68aa4d5Sjsing t.Error("PeerCertHash() returned nil error, want error") 426c68aa4d5Sjsing } 427c68aa4d5Sjsing if _, err := tls.PeerCertNotBefore(); err == nil { 428c68aa4d5Sjsing t.Error("PeerCertNotBefore() returned nil error, want error") 429c68aa4d5Sjsing } 430c68aa4d5Sjsing if _, err := tls.PeerCertNotAfter(); err == nil { 431c68aa4d5Sjsing t.Error("PeerCertNotAfter() returned nil error, want error") 432c68aa4d5Sjsing } 433c68aa4d5Sjsing 434c68aa4d5Sjsing // Complete the handshake... 435c68aa4d5Sjsing if err := tls.Handshake(); err != nil { 436c68aa4d5Sjsing t.Fatalf("Handshake failed: %v", err) 437c68aa4d5Sjsing } 438c68aa4d5Sjsing 439c68aa4d5Sjsing if version, err := tls.ConnVersion(); err != nil { 440b97dc7d2Sjsing t.Errorf("ConnVersion() returned error: %v", err) 441c68aa4d5Sjsing } else { 442c68aa4d5Sjsing t.Logf("Protocol version: %v", version) 443c68aa4d5Sjsing } 444c68aa4d5Sjsing if cipher, err := tls.ConnCipher(); err != nil { 445b97dc7d2Sjsing t.Errorf("ConnCipher() returned error: %v", err) 446c68aa4d5Sjsing } else { 447c68aa4d5Sjsing t.Logf("Cipher: %v", cipher) 448c68aa4d5Sjsing } 449b97dc7d2Sjsing if strength, err := tls.ConnCipherStrength(); err != nil { 450b97dc7d2Sjsing t.Errorf("ConnCipherStrength() return ederror: %v", err) 451b97dc7d2Sjsing } else { 452b97dc7d2Sjsing t.Logf("Cipher Strength: %v bits", strength) 453b97dc7d2Sjsing } 454c68aa4d5Sjsing 455c68aa4d5Sjsing if got, want := tls.PeerCertProvided(), true; got != want { 456c68aa4d5Sjsing t.Errorf("PeerCertProvided() = %v, want %v", got, want) 457c68aa4d5Sjsing } 458c68aa4d5Sjsing for _, name := range []string{"127.0.0.1", "::1", "example.com"} { 459c68aa4d5Sjsing if got, want := tls.PeerCertContainsName(name), true; got != want { 460c68aa4d5Sjsing t.Errorf("PeerCertContainsName(%q) = %v, want %v", name, got, want) 461c68aa4d5Sjsing } 462c68aa4d5Sjsing } 463c68aa4d5Sjsing 464c68aa4d5Sjsing if issuer, err := tls.PeerCertIssuer(); err != nil { 465c68aa4d5Sjsing t.Errorf("PeerCertIssuer() returned error: %v", err) 466c68aa4d5Sjsing } else { 467c68aa4d5Sjsing t.Logf("Issuer: %v", issuer) 468c68aa4d5Sjsing } 469c68aa4d5Sjsing if subject, err := tls.PeerCertSubject(); err != nil { 470c68aa4d5Sjsing t.Errorf("PeerCertSubject() returned error: %v", err) 471c68aa4d5Sjsing } else { 472c68aa4d5Sjsing t.Logf("Subject: %v", subject) 473c68aa4d5Sjsing } 474*7f9db3f5Stb if commonName, err := tls.PeerCertCommonName(); err != nil { 475*7f9db3f5Stb t.Errorf("PeerCertCommonName() returned error: %v", err) 476*7f9db3f5Stb } else { 477*7f9db3f5Stb t.Logf("Subject: %v", commonName) 478*7f9db3f5Stb } 479c68aa4d5Sjsing if hash, err := tls.PeerCertHash(); err != nil { 480c68aa4d5Sjsing t.Errorf("PeerCertHash() returned error: %v", err) 481c68aa4d5Sjsing } else if hash != certHash { 482c68aa4d5Sjsing t.Errorf("Got cert hash %q, want %q", hash, certHash) 483c68aa4d5Sjsing } else { 484c68aa4d5Sjsing t.Logf("Hash: %v", hash) 485c68aa4d5Sjsing } 486c68aa4d5Sjsing if notBefore, err := tls.PeerCertNotBefore(); err != nil { 487c68aa4d5Sjsing t.Errorf("PeerCertNotBefore() returned error: %v", err) 488c68aa4d5Sjsing } else if !certNotBefore.Equal(notBefore) { 489c68aa4d5Sjsing t.Errorf("Got cert notBefore %v, want %v", notBefore.UTC(), certNotBefore.UTC()) 490c68aa4d5Sjsing } else { 491c68aa4d5Sjsing t.Logf("NotBefore: %v", notBefore.UTC()) 492c68aa4d5Sjsing } 493c68aa4d5Sjsing if notAfter, err := tls.PeerCertNotAfter(); err != nil { 494c68aa4d5Sjsing t.Errorf("PeerCertNotAfter() returned error: %v", err) 495c68aa4d5Sjsing } else if !certNotAfter.Equal(notAfter) { 496c68aa4d5Sjsing t.Errorf("Got cert notAfter %v, want %v", notAfter.UTC(), certNotAfter.UTC()) 497c68aa4d5Sjsing } else { 498c68aa4d5Sjsing t.Logf("NotAfter: %v", notAfter.UTC()) 499c68aa4d5Sjsing } 500c68aa4d5Sjsing} 501