From 71d43f95cb0a79ebfb9b3aa795c411dd99e53bb9 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Mon, 3 Sep 2018 01:03:59 -0400 Subject: [PATCH] Add a SMTP test for STARTTLS. --- smtp/conn_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++ testtls/domain.crt | 23 ++++++++++++++++++++ testtls/domain.key | 27 +++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 testtls/domain.crt create mode 100644 testtls/domain.key diff --git a/smtp/conn_test.go b/smtp/conn_test.go index 4a93101..85dcb45 100644 --- a/smtp/conn_test.go +++ b/smtp/conn_test.go @@ -1,6 +1,7 @@ package smtp import ( + "crypto/tls" "fmt" "net" "net/mail" @@ -58,12 +59,17 @@ func runServer(t *testing.T, server Server) net.Listener { type testServer struct { EmptyServerCallbacks blockList []string + tlsConfig *tls.Config } func (s *testServer) Name() string { return "Test-Server" } +func (s *testServer) TLSConfig() *tls.Config { + return s.tlsConfig +} + func (s *testServer) VerifyAddress(addr mail.Address) ReplyLine { for _, block := range s.blockList { if strings.ToLower(block) == addr.Address { @@ -275,3 +281,50 @@ func TestGetReceivedInfo(t *testing.T) { } } + +func getTLSConfig(t *testing.T) *tls.Config { + cert, err := tls.LoadX509KeyPair("../testtls/domain.crt", "../testtls/domain.key") + if err != nil { + t.Fatal(err) + return nil + } + return &tls.Config{ + ServerName: "localhost", + Certificates: []tls.Certificate{cert}, + InsecureSkipVerify: true, + } +} + +func TestTLS(t *testing.T) { + l := runServer(t, &testServer{tlsConfig: getTLSConfig(t)}) + defer l.Close() + + nc, err := net.Dial(l.Addr().Network(), l.Addr().String()) + ok(t, err) + + conn := textproto.NewConn(nc) + readCodeLine(t, conn, 220) + + ok(t, conn.PrintfLine("EHLO test-tls")) + _, resp, err := conn.ReadResponse(250) + ok(t, err) + if !strings.Contains(resp, "STARTTLS\n") { + t.Errorf("STARTTLS not advertised") + } + + ok(t, conn.PrintfLine("STARTTLS")) + readCodeLine(t, conn, 220) + + tc := tls.Client(nc, getTLSConfig(t)) + err = tc.Handshake() + ok(t, err) + + conn = textproto.NewConn(tc) + + ok(t, conn.PrintfLine("EHLO test-tls-started")) + _, resp, err = conn.ReadResponse(250) + ok(t, err) + if strings.Contains(resp, "STARTTLS\n") { + t.Errorf("STARTTLS advertised when already started") + } +} diff --git a/testtls/domain.crt b/testtls/domain.crt new file mode 100644 index 0000000..e0d10bb --- /dev/null +++ b/testtls/domain.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID0DCCArigAwIBAgIJAKKsGKE6sUkAMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNV +BAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEYMBYGA1UEChMPVEVTVCBNQUlMUE9Q +Qk9YMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTgwOTA2MDAzOTQxWhcNMTgxMDA2 +MDAzOTQxWjBOMQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxGDAWBgNV +BAoTD1RFU1QgTUFJTFBPUEJPWDESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqRckvnfo5MdbIWZHLP+g1wDrBLC3LS3M +9JFumGXXe19Ooy9a+WvBK3tnFfEhpMIKJ3iphgPlf3fU8W96kuE3o6rPRUzpv6FU +z+w1FTBiOd1FfUmKwULdjmMFFdl2nYzjp4le9yfaUDNdu8bj9Wk2tL6sBaO6gkHr +thJiPPtCv19YxGPG5FZIDnlDwLkwuaUxQCTgZ7BZ0qM036gmXJ6gYd1Scgz5iSHC +Pfj9v1dEOPowA9MRrDa9sQdjrFCq2vgdsdsVdVfoWhHeQfd6PCFUTy06xDHfGnor +/+wAklbnIVCnVbyQeQHpPkQjlzcVMZkHnxwfG4CJ/WgF+inzQ0hNTQIDAQABo4Gw +MIGtMB0GA1UdDgQWBBSqQHNqsbIav6Q0SYwla379Q19YsjB+BgNVHSMEdzB1gBSq +QHNqsbIav6Q0SYwla379Q19YsqFSpFAwTjELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CE5ldyBZb3JrMRgwFgYDVQQKEw9URVNUIE1BSUxQT1BCT1gxEjAQBgNVBAMTCWxv +Y2FsaG9zdIIJAKKsGKE6sUkAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBAJeT2v5N+i15zlEeOVSsuvV/aGe068K5e+FE1qOnkmBsvqN2/BmWT5oeJuNc +AT0ZyKI1vR5/Enq1Fta5xSNWLVeFQwm4DYEFxJ21SGWnY6+hl213nr7x0pmLG3tT +YFq9/A+4iG5LQuDroQOC2TAqZFMTpdgLQgFZYKJvI4rk6/QrcI2pdMdwpAIJgMgd +USV/MHoj30ll17cAukHnaZGKxkkZu0BKhadOEkB7p4zSZsVFWJfGsi5Pf3+LFmyE +dkxewA5SVD7KwVkZ+wSkxEBuaIYAArbuxc9aT2u4H3+fxVrd2UnuDeq0nv0lMZN/ +eAHjIwvvWme+6AxRhIA5z5eTpcA= +-----END CERTIFICATE----- diff --git a/testtls/domain.key b/testtls/domain.key new file mode 100644 index 0000000..dc43434 --- /dev/null +++ b/testtls/domain.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAqRckvnfo5MdbIWZHLP+g1wDrBLC3LS3M9JFumGXXe19Ooy9a ++WvBK3tnFfEhpMIKJ3iphgPlf3fU8W96kuE3o6rPRUzpv6FUz+w1FTBiOd1FfUmK +wULdjmMFFdl2nYzjp4le9yfaUDNdu8bj9Wk2tL6sBaO6gkHrthJiPPtCv19YxGPG +5FZIDnlDwLkwuaUxQCTgZ7BZ0qM036gmXJ6gYd1Scgz5iSHCPfj9v1dEOPowA9MR +rDa9sQdjrFCq2vgdsdsVdVfoWhHeQfd6PCFUTy06xDHfGnor/+wAklbnIVCnVbyQ +eQHpPkQjlzcVMZkHnxwfG4CJ/WgF+inzQ0hNTQIDAQABAoIBAGmTocWraScvsp7w +FZDrK6oTUKrlC/qRll8+TyeorxrBL4CEmPETbtGPg5YXsUIGRgDPPkoHNMyaLcNy +L752ER+ID1Ld6zVTrnkEq0BHrY0js7e+q3xwG5ZEDXDPD1jgF2UMSNdZct6Qs/4C ++WLKBvZj91SuHk4mit5sLBqXZ93EzvmK6mb2OSwrtla2500Pf1CsY9VAT75z0kBi +cLV+WYrA1Q84eNqFm4gW1wjfz9xs8+u+jRTgtI0X4HkXpDBzliIecxR8RmjPG0ET +xykW4gfnVZoTPI1iRnCdaXhzP2oyx96/i1BUWoNQmQjki0TzOY56XgiLRpWnrD5b +XaoHrqECgYEA0s6STz8qe5Cz96J3B4nm4yZcvsfTPm9R/L5k9dg9bPed8KcqPuT8 +KSA/1JWk8Z4XcHdO3DilvHVYgENEBBNEPKfjL5Dz9r62EEn4Xjt2pHjgSkDAEKtr +BRKXhdTWCoT0fpx8I6yCPzCDV6IA4yfT2J7RZeuoK5hYXVaE5I1oGUcCgYEAzVcZ +9qhR/DkStQ41wtyepZXHmkgzwqi2drb6tj+EsQfi/jHm1SX7uCkrbYgLwWMARmBO +zS2cqEKP7Fzv1yBw0ooDxvGOqtsi7HKFsHeYWXXZCrrxiinMg1lpVjfLFchW10jY +deiUBDGeYsu8gCe1ekOVRJrXbFpC8mxxe2ICrssCgYEAjHC8fnkZh1qe2vJslCQm +Itxy21LrA+RL3bLGNhbKzWal3Saw+Ve6OnfWrnzHd4SYHwANFJ/UopoWzNSDYqen +RTWgIBdUwOTLDE0LX1QENYyl+DHtAu4AjU+WjL1/n2B2NkdwWJ/b4dcjGWW/a5Yk +B2O/I0R9NBX5gK1cOZuPZ48CgYAoVJs83wJ7T5plBU154GsoiqqRmuzPpuNvnbDQ +atldC/eBhbuY0cUG/s8QzE/Cw/ch23iew/6o7anm+roAvtZqA8GKKZej5zaMylGH +v3Wk3IismtsmD9+jTMRrsrmopZio4B3jyrKHwFcjgHCdmy8BvJRszRzSo0fS5YnE +ehOc0QKBgQCGhYKMbhGNobsXnjxKQDRlrKxvWXSHtx6wgcyAPdb1iqaFe+jIEgvx +6Vd63Jin2/kruSr8m9VSltkdXmcbLKRNff55J8dyH322Z09R8WrVkCtw8nWIWvgJ +EVR2rG4y0S2YhzhO8bOlybZS0egg93RSye0Xd3pPyLFgAXmixgqmgw== +-----END RSA PRIVATE KEY----- -- 2.22.5