author | Alberto Bertogli
<albertito@blitiri.com.ar> 2021-10-15 10:16:46 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2021-10-25 11:41:24 UTC |
parent | ed38945fca3305544f3997cbbef81ee4450f8799 |
internal/smtpsrv/server_test.go | +1 | -76 |
internal/testlib/testlib.go | +80 | -0 |
internal/testlib/testlib_test.go | +22 | -0 |
diff --git a/internal/smtpsrv/server_test.go b/internal/smtpsrv/server_test.go index 891ee2e..9915973 100644 --- a/internal/smtpsrv/server_test.go +++ b/internal/smtpsrv/server_test.go @@ -1,16 +1,10 @@ package smtpsrv import ( - "crypto/rand" - "crypto/rsa" "crypto/tls" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" "flag" "fmt" "io/ioutil" - "math/big" "net" "net/smtp" "os" @@ -516,75 +510,6 @@ func BenchmarkManyEmailsParallel(b *testing.B) { // === Test environment === // -// generateCert generates a new, INSECURE self-signed certificate and writes -// it to a pair of (cert.pem, key.pem) files to the given path. -// Note the certificate is only useful for testing purposes. -func generateCert(path string) error { - tmpl := x509.Certificate{ - SerialNumber: big.NewInt(1234), - Subject: pkix.Name{ - Organization: []string{"chasquid_test.go"}, - }, - - DNSNames: []string{"localhost"}, - IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, - - NotBefore: time.Now(), - NotAfter: time.Now().Add(30 * time.Minute), - - KeyUsage: x509.KeyUsageKeyEncipherment | - x509.KeyUsageDigitalSignature | - x509.KeyUsageCertSign, - - BasicConstraintsValid: true, - IsCA: true, - } - - priv, err := rsa.GenerateKey(rand.Reader, 1024) - if err != nil { - return err - } - - derBytes, err := x509.CreateCertificate( - rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv) - if err != nil { - return err - } - - // Create a global config for convenience. - srvCert, err := x509.ParseCertificate(derBytes) - if err != nil { - return err - } - rootCAs := x509.NewCertPool() - rootCAs.AddCert(srvCert) - tlsConfig = &tls.Config{ - ServerName: "localhost", - RootCAs: rootCAs, - } - - certOut, err := os.Create(path + "/cert.pem") - if err != nil { - return err - } - defer certOut.Close() - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - - keyOut, err := os.OpenFile( - path+"/key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return err - } - defer keyOut.Close() - - block := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(priv), - } - pem.Encode(keyOut, block) - return nil -} - // waitForServer waits 5 seconds for the server to start, and returns an error // if it fails to do so. // It does this by repeatedly connecting to the address until it either @@ -650,7 +575,7 @@ func realMain(m *testing.M) int { } defer os.RemoveAll(tmpDir) - err = generateCert(tmpDir) + tlsConfig, err = testlib.GenerateCert(tmpDir) if err != nil { fmt.Printf("Failed to generate cert for testing: %v\n", err) return 1 diff --git a/internal/testlib/testlib.go b/internal/testlib/testlib.go index 162f4f8..461764d 100644 --- a/internal/testlib/testlib.go +++ b/internal/testlib/testlib.go @@ -2,7 +2,14 @@ package testlib import ( + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" "io/ioutil" + "math/big" "net" "os" "strings" @@ -129,3 +136,76 @@ func (c dumbCourier) Deliver(from string, to string, data []byte) (error, bool) // DumbCourier always succeeds delivery, and ignores everything. var DumbCourier = dumbCourier{} + +// generateCert generates a new, INSECURE self-signed certificate and writes +// it to a pair of (cert.pem, key.pem) files to the given path. +// Note the certificate is only useful for testing purposes. +func GenerateCert(path string) (*tls.Config, error) { + tmpl := x509.Certificate{ + SerialNumber: big.NewInt(1234), + Subject: pkix.Name{ + Organization: []string{"chasquid_test.go"}, + }, + + DNSNames: []string{"localhost"}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, + + NotBefore: time.Now(), + NotAfter: time.Now().Add(30 * time.Minute), + + KeyUsage: x509.KeyUsageKeyEncipherment | + x509.KeyUsageDigitalSignature | + x509.KeyUsageCertSign, + + BasicConstraintsValid: true, + IsCA: true, + } + + priv, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + return nil, err + } + + derBytes, err := x509.CreateCertificate( + rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv) + if err != nil { + return nil, err + } + + // Create a global config for convenience. + srvCert, err := x509.ParseCertificate(derBytes) + if err != nil { + return nil, err + } + rootCAs := x509.NewCertPool() + rootCAs.AddCert(srvCert) + tlsConfig := &tls.Config{ + ServerName: "localhost", + RootCAs: rootCAs, + } + + certOut, err := os.Create(path + "/cert.pem") + if err != nil { + return nil, err + } + defer certOut.Close() + err = pem.Encode(certOut, + &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + return nil, err + } + + keyOut, err := os.OpenFile( + path+"/key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return nil, err + } + defer keyOut.Close() + + block := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(priv), + } + err = pem.Encode(keyOut, block) + return tlsConfig, err +} diff --git a/internal/testlib/testlib_test.go b/internal/testlib/testlib_test.go index b2da661..f514dc4 100644 --- a/internal/testlib/testlib_test.go +++ b/internal/testlib/testlib_test.go @@ -96,3 +96,25 @@ func TestWaitFor(t *testing.T) { t.Errorf("WaitFor(false) worked") } } + +func TestGenerateCert(t *testing.T) { + dir := MustTempDir(t) + defer os.RemoveAll(dir) + conf, err := GenerateCert(dir) + if err != nil { + t.Errorf("GenerateCert returned error: %v", err) + } + if conf.ServerName != "localhost" { + t.Errorf("Config server name %q != localhost", conf.ServerName) + } + if conf.RootCAs == nil { + t.Errorf("Config had an empty RootCAs pool") + } +} + +func TestGenerateCertBadDir(t *testing.T) { + conf, err := GenerateCert("/doesnotexist/") + if err == nil || conf != nil { + t.Fatalf("GenerateCert returned non-error: %v / %v", conf, err) + } +}