2016-02-11 15:06:05 +08:00
|
|
|
package https
|
2015-05-19 03:38:21 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
2016-02-11 15:06:05 +08:00
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"os"
|
2015-05-19 03:38:21 +08:00
|
|
|
"testing"
|
2016-02-11 15:06:05 +08:00
|
|
|
|
|
|
|
"github.com/mholt/caddy/caddy/setup"
|
2015-05-19 03:38:21 +08:00
|
|
|
)
|
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
// Write test certificates to disk before tests, and clean up
|
|
|
|
// when we're done.
|
|
|
|
err := ioutil.WriteFile(certFile, testCert, 0644)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(keyFile, testKey, 0644)
|
|
|
|
if err != nil {
|
|
|
|
os.Remove(certFile)
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
result := m.Run()
|
2015-05-21 14:06:53 +08:00
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
os.Remove(certFile)
|
|
|
|
os.Remove(keyFile)
|
|
|
|
os.Exit(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetupParseBasic(t *testing.T) {
|
|
|
|
c := setup.NewTestController(`tls ` + certFile + ` ` + keyFile + ``)
|
|
|
|
|
|
|
|
_, err := Setup(c)
|
2015-05-21 14:06:53 +08:00
|
|
|
if err != nil {
|
2015-05-22 00:37:39 +08:00
|
|
|
t.Errorf("Expected no errors, got: %v", err)
|
2015-05-21 14:06:53 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
// Basic checks
|
2016-02-11 15:06:05 +08:00
|
|
|
if !c.TLS.Manual {
|
|
|
|
t.Error("Expected TLS Manual=true, but was false")
|
2015-05-21 14:06:53 +08:00
|
|
|
}
|
|
|
|
if !c.TLS.Enabled {
|
|
|
|
t.Error("Expected TLS Enabled=true, but was false")
|
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
// Security defaults
|
|
|
|
if c.TLS.ProtocolMinVersion != tls.VersionTLS10 {
|
|
|
|
t.Errorf("Expected 'tls1.0 (0x0301)' as ProtocolMinVersion, got %#v", c.TLS.ProtocolMinVersion)
|
|
|
|
}
|
|
|
|
if c.TLS.ProtocolMaxVersion != tls.VersionTLS12 {
|
|
|
|
t.Errorf("Expected 'tls1.2 (0x0303)' as ProtocolMaxVersion, got %v", c.TLS.ProtocolMaxVersion)
|
|
|
|
}
|
2015-05-19 03:38:21 +08:00
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
// Cipher checks
|
|
|
|
expectedCiphers := []uint16{
|
2016-01-14 00:24:03 +08:00
|
|
|
tls.TLS_FALLBACK_SCSV,
|
2015-05-22 00:37:39 +08:00
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
// Ensure count is correct (plus one for TLS_FALLBACK_SCSV)
|
2015-12-19 19:37:38 +08:00
|
|
|
if len(c.TLS.Ciphers) != len(expectedCiphers) {
|
2015-05-22 00:37:39 +08:00
|
|
|
t.Errorf("Expected %v Ciphers (including TLS_FALLBACK_SCSV), got %v",
|
2015-12-19 19:37:38 +08:00
|
|
|
len(expectedCiphers), len(c.TLS.Ciphers))
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
// Ensure ordering is correct
|
|
|
|
for i, actual := range c.TLS.Ciphers {
|
|
|
|
if actual != expectedCiphers[i] {
|
|
|
|
t.Errorf("Expected cipher in position %d to be %0x, got %0x", i, expectedCiphers[i], actual)
|
|
|
|
}
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
if !c.TLS.PreferServerCipherSuites {
|
|
|
|
t.Error("Expected PreferServerCipherSuites = true, but was false")
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestSetupParseIncompleteParams(t *testing.T) {
|
2016-01-12 23:55:01 +08:00
|
|
|
// Using tls without args is an error because it's unnecessary.
|
2016-02-11 15:06:05 +08:00
|
|
|
c := setup.NewTestController(`tls`)
|
|
|
|
_, err := Setup(c)
|
2016-01-12 23:55:01 +08:00
|
|
|
if err == nil {
|
|
|
|
t.Error("Expected an error, but didn't get one")
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestSetupParseWithOptionalParams(t *testing.T) {
|
|
|
|
params := `tls ` + certFile + ` ` + keyFile + ` {
|
2015-05-19 05:15:41 +08:00
|
|
|
protocols ssl3.0 tls1.2
|
2015-05-19 03:38:21 +08:00
|
|
|
ciphers RSA-3DES-EDE-CBC-SHA RSA-AES256-CBC-SHA ECDHE-RSA-AES128-GCM-SHA256
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c := setup.NewTestController(params)
|
2015-05-19 03:38:21 +08:00
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
_, err := Setup(c)
|
2015-05-19 03:38:21 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Expected no errors, got: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.TLS.ProtocolMinVersion != tls.VersionSSL30 {
|
2015-05-19 05:15:41 +08:00
|
|
|
t.Errorf("Expected 'ssl3.0 (0x0300)' as ProtocolMinVersion, got %#v", c.TLS.ProtocolMinVersion)
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if c.TLS.ProtocolMaxVersion != tls.VersionTLS12 {
|
2015-05-19 05:15:41 +08:00
|
|
|
t.Errorf("Expected 'tls1.2 (0x0302)' as ProtocolMaxVersion, got %#v", c.TLS.ProtocolMaxVersion)
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:37:39 +08:00
|
|
|
if len(c.TLS.Ciphers)-1 != 3 {
|
2016-01-04 07:44:30 +08:00
|
|
|
t.Errorf("Expected 3 Ciphers (not including TLS_FALLBACK_SCSV), got %v", len(c.TLS.Ciphers)-1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestSetupDefaultWithOptionalParams(t *testing.T) {
|
2016-01-04 07:44:30 +08:00
|
|
|
params := `tls {
|
|
|
|
ciphers RSA-3DES-EDE-CBC-SHA
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c := setup.NewTestController(params)
|
2016-01-04 07:44:30 +08:00
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
_, err := Setup(c)
|
2016-01-04 07:44:30 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Expected no errors, got: %v", err)
|
|
|
|
}
|
|
|
|
if len(c.TLS.Ciphers)-1 != 1 {
|
|
|
|
t.Errorf("Expected 1 ciphers (not including TLS_FALLBACK_SCSV), got %v", len(c.TLS.Ciphers)-1)
|
2015-05-19 03:38:21 +08:00
|
|
|
}
|
|
|
|
}
|
2015-05-19 10:27:35 +08:00
|
|
|
|
2016-01-04 07:44:30 +08:00
|
|
|
// TODO: If we allow this... but probably not a good idea.
|
2016-02-11 15:06:05 +08:00
|
|
|
// func TestSetupDisableHTTPRedirect(t *testing.T) {
|
2016-01-04 07:44:30 +08:00
|
|
|
// c := NewTestController(`tls {
|
|
|
|
// allow_http
|
|
|
|
// }`)
|
|
|
|
// _, err := TLS(c)
|
|
|
|
// if err != nil {
|
|
|
|
// t.Errorf("Expected no error, but got %v", err)
|
|
|
|
// }
|
|
|
|
// if !c.TLS.DisableHTTPRedir {
|
|
|
|
// t.Error("Expected HTTP redirect to be disabled, but it wasn't")
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestSetupParseWithWrongOptionalParams(t *testing.T) {
|
2015-05-19 10:27:35 +08:00
|
|
|
// Test protocols wrong params
|
2016-02-11 15:06:05 +08:00
|
|
|
params := `tls ` + certFile + ` ` + keyFile + ` {
|
2015-05-19 10:27:35 +08:00
|
|
|
protocols ssl tls
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c := setup.NewTestController(params)
|
|
|
|
_, err := Setup(c)
|
2015-05-19 10:27:35 +08:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("Expected errors, but no error returned")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test ciphers wrong params
|
2016-02-11 15:06:05 +08:00
|
|
|
params = `tls ` + certFile + ` ` + keyFile + ` {
|
2015-05-19 10:27:35 +08:00
|
|
|
ciphers not-valid-cipher
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c = setup.NewTestController(params)
|
|
|
|
_, err = Setup(c)
|
2015-05-19 10:27:35 +08:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("Expected errors, but no error returned")
|
|
|
|
}
|
|
|
|
}
|
2015-06-02 13:22:11 +08:00
|
|
|
|
2016-02-11 15:06:05 +08:00
|
|
|
func TestSetupParseWithClientAuth(t *testing.T) {
|
|
|
|
params := `tls ` + certFile + ` ` + keyFile + ` {
|
2015-06-02 13:22:11 +08:00
|
|
|
clients client_ca.crt client2_ca.crt
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c := setup.NewTestController(params)
|
|
|
|
_, err := Setup(c)
|
2015-06-02 13:22:11 +08:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Expected no errors, got: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if count := len(c.TLS.ClientCerts); count != 2 {
|
|
|
|
t.Fatalf("Expected two client certs, had %d", count)
|
|
|
|
}
|
|
|
|
if actual := c.TLS.ClientCerts[0]; actual != "client_ca.crt" {
|
|
|
|
t.Errorf("Expected first client cert file to be '%s', but was '%s'", "client_ca.crt", actual)
|
|
|
|
}
|
|
|
|
if actual := c.TLS.ClientCerts[1]; actual != "client2_ca.crt" {
|
|
|
|
t.Errorf("Expected second client cert file to be '%s', but was '%s'", "client2_ca.crt", actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test missing client cert file
|
2016-02-11 15:06:05 +08:00
|
|
|
params = `tls ` + certFile + ` ` + keyFile + ` {
|
2015-06-02 13:22:11 +08:00
|
|
|
clients
|
|
|
|
}`
|
2016-02-11 15:06:05 +08:00
|
|
|
c = setup.NewTestController(params)
|
|
|
|
_, err = Setup(c)
|
2015-06-02 13:22:11 +08:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("Expected an error, but no error returned")
|
|
|
|
}
|
|
|
|
}
|
2016-02-11 15:06:05 +08:00
|
|
|
|
|
|
|
const (
|
|
|
|
certFile = "test_cert.pem"
|
|
|
|
keyFile = "test_key.pem"
|
|
|
|
)
|
|
|
|
|
|
|
|
var testCert = []byte(`-----BEGIN CERTIFICATE-----
|
|
|
|
MIIBkjCCATmgAwIBAgIJANfFCBcABL6LMAkGByqGSM49BAEwFDESMBAGA1UEAxMJ
|
|
|
|
bG9jYWxob3N0MB4XDTE2MDIxMDIyMjAyNFoXDTE4MDIwOTIyMjAyNFowFDESMBAG
|
|
|
|
A1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEs22MtnG7
|
|
|
|
9K1mvIyjEO9GLx7BFD0tBbGnwQ0VPsuCxC6IeVuXbQDLSiVQvFZ6lUszTlczNxVk
|
|
|
|
pEfqrM6xAupB7qN1MHMwHQYDVR0OBBYEFHxYDvAxUwL4XrjPev6qZ/BiLDs5MEQG
|
|
|
|
A1UdIwQ9MDuAFHxYDvAxUwL4XrjPev6qZ/BiLDs5oRikFjAUMRIwEAYDVQQDEwls
|
|
|
|
b2NhbGhvc3SCCQDXxQgXAAS+izAMBgNVHRMEBTADAQH/MAkGByqGSM49BAEDSAAw
|
|
|
|
RQIgRvBqbyJM2JCJqhA1FmcoZjeMocmhxQHTt1c+1N2wFUgCIQDtvrivbBPA688N
|
|
|
|
Qh3sMeAKNKPsx5NxYdoWuu9KWcKz9A==
|
|
|
|
-----END CERTIFICATE-----
|
|
|
|
`)
|
|
|
|
|
|
|
|
var testKey = []byte(`-----BEGIN EC PARAMETERS-----
|
|
|
|
BggqhkjOPQMBBw==
|
|
|
|
-----END EC PARAMETERS-----
|
|
|
|
-----BEGIN EC PRIVATE KEY-----
|
|
|
|
MHcCAQEEIGLtRmwzYVcrH3J0BnzYbGPdWVF10i9p6mxkA4+b2fURoAoGCCqGSM49
|
|
|
|
AwEHoUQDQgAEs22MtnG79K1mvIyjEO9GLx7BFD0tBbGnwQ0VPsuCxC6IeVuXbQDL
|
|
|
|
SiVQvFZ6lUszTlczNxVkpEfqrM6xAupB7g==
|
|
|
|
-----END EC PRIVATE KEY-----
|
|
|
|
`)
|