1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-17 14:37:02 +00:00

testlib: Add GenerateCert function

This patch moves the GenerateCert function from the smtpsrv tests to the
common testlib, so it can be used by other tests in the future.
This commit is contained in:
Alberto Bertogli
2021-10-15 11:16:46 +01:00
parent ed38945fca
commit 90d385556f
3 changed files with 103 additions and 76 deletions

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)
}
}