diff --git a/examples/dkim-proxy/main.go b/examples/dkim-proxy/main.go index 5e33132..6d07eb0 100644 --- a/examples/dkim-proxy/main.go +++ b/examples/dkim-proxy/main.go @@ -3,40 +3,38 @@ package main import ( "bytes" + "crypto" + "crypto/x509" + "encoding/pem" "flag" "io/ioutil" "log" "net/smtp" "github.com/chrj/smtpd" - "github.com/eaigner/dkim" + "github.com/emersion/go-msgauth/dkim" ) var ( welcomeMsg = flag.String("welcome", "DKIM-proxy ESMTP ready.", "Welcome message for SMTP session") inAddr = flag.String("inaddr", "localhost:10025", "Address to listen for incoming SMTP on") outAddr = flag.String("outaddr", "localhost:25", "Address to deliver outgoing SMTP on") - privKeyFile = flag.String("key", "", "Private key file.") + privKeyFile = flag.String("key", "", "PEM encoded RSA private key file.") dkimS = flag.String("s", "default", "DKIM selector") dkimD = flag.String("d", "", "DKIM domain") - dkimConf dkim.Conf - privKey []byte + dkimOptions *dkim.SignOptions ) func handler(peer smtpd.Peer, env smtpd.Envelope) error { - d, err := dkim.New(dkimConf, privKey) - if err != nil { - log.Printf("DKIM error: %v", err) - return smtpd.Error{450, "Internal server error"} - } - + out := bytes.NewBuffer(nil) + in := bytes.NewBuffer(bytes.Replace(env.Data, []byte("\n"), []byte("\r\n"), -1)) // The dkim package expects \r\n newlines, so replace to that - data, err := d.Sign(bytes.Replace(env.Data, []byte("\n"), []byte("\r\n"), -1)) + err := dkim.Sign(out, in, dkimOptions) if err != nil { log.Printf("DKIM signing error: %v", err) - return smtpd.Error{450, "Internal server error"} + return smtpd.Error{Code: 450, Message: "Internal server error"} } return smtp.SendMail( @@ -44,30 +42,35 @@ func handler(peer smtpd.Peer, env smtpd.Envelope) error { nil, env.Sender, env.Recipients, - data, + out.Bytes(), ) } +func getSigner() crypto.Signer { + privKey, err := ioutil.ReadFile(*privKeyFile) + if err != nil { + log.Fatalf("Couldn't read private key: %v", err) + } + pemBlock, _ := pem.Decode(privKey) + if pemBlock == nil { + log.Fatalf("Couldn't decode private key: %v", err) + } + rsa, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) + if err != nil { + log.Fatalf("Couldn't parse as RSA private key: %v", err) + } + return rsa +} + func main() { flag.Parse() - var err error - - dkimConf, err = dkim.NewConf(*dkimD, *dkimS) - if err != nil { - log.Fatalf("DKIM configuration error: %v", err) - } - - privKey, err = ioutil.ReadFile(*privKeyFile) - if err != nil { - log.Fatalf("Couldn't read private key: %v", err) - } - - _, err = dkim.New(dkimConf, privKey) - if err != nil { - log.Fatalf("DKIM error: %v", err) + dkimOptions = &dkim.SignOptions{ + Domain: *dkimD, + Selector: *dkimS, + Signer: getSigner(), } server := &smtpd.Server{ diff --git a/go.mod b/go.mod index f5c2391..ff677bd 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/chrj/smtpd go 1.14 -require github.com/eaigner/dkim v0.0.0-20150301120808-6fe4a7ee9cfb +require ( + github.com/emersion/go-msgauth v0.6.5 + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect +) diff --git a/go.sum b/go.sum index 0d11b77..d21bbe3 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,31 @@ -github.com/eaigner/dkim v0.0.0-20150301120808-6fe4a7ee9cfb h1:17kQ+7S0aEyRhZd9KCAofvKlL1N1/w+zUZKaxpLFpM0= -github.com/eaigner/dkim v0.0.0-20150301120808-6fe4a7ee9cfb/go.mod h1:FSCIHbrqk7D01Mj8y/jW+NS1uoCerr+ad+IckTHTFf4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emersion/go-message v0.11.2/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY= +github.com/emersion/go-message v0.14.1/go.mod h1:N1JWdZQ2WRUalmdHAX308CWBq747VJ8oUorFI3VCBwU= +github.com/emersion/go-milter v0.3.2/go.mod h1:ablHK0pbLB83kMFBznp/Rj8aV+Kc3jw8cxzzmCNLIOY= +github.com/emersion/go-msgauth v0.6.5 h1:UaXBtrjYBM3SWw9BBODeSp0uYtScx3CuIF7/RQfkeWo= +github.com/emersion/go-msgauth v0.6.5/go.mod h1:/jbQISFJgtT12T8akRs20l+wI4HcyN/kWy7VRdHEAmA= +github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= +github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= +github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8= +github.com/martinlindhe/base36 v1.1.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5-0.20201125200606-c27b9fd57aec/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=