From 905161c537123b49532f8b1b7ee726a56b8e055f Mon Sep 17 00:00:00 2001 From: Alberto Bertogli Date: Thu, 21 Jul 2016 22:21:48 +0100 Subject: [PATCH] test: Add a test for Exim interactions This patch adds a new test which makes chasquid send and receive email to/from Exim. To make it work we need to add two testing flags to the SMTP courier, which is not ideal but doesn't muddle the code much. The test is not very portable, and assumes an exim binary is available, but does not have to be installed in the system. It includes a helper script to fetch one from the Debian archives. --- internal/courier/smtp.go | 14 ++++- internal/courier/smtp_test.go | 4 +- test/t-exim/.gitignore | 3 + test/t-exim/config/chasquid.conf | 5 ++ test/t-exim/config/domains/srv-chasquid/users | 2 + test/t-exim/config/exim4.in | 62 +++++++++++++++++++ test/t-exim/content | 4 ++ test/t-exim/get-exim4-debian.sh | 27 ++++++++ test/t-exim/hosts | 2 + test/t-exim/msmtprc | 14 +++++ test/t-exim/run.sh | 57 +++++++++++++++++ 11 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 test/t-exim/.gitignore create mode 100644 test/t-exim/config/chasquid.conf create mode 100644 test/t-exim/config/domains/srv-chasquid/users create mode 100644 test/t-exim/config/exim4.in create mode 100644 test/t-exim/content create mode 100755 test/t-exim/get-exim4-debian.sh create mode 100644 test/t-exim/hosts create mode 100644 test/t-exim/msmtprc create mode 100755 test/t-exim/run.sh diff --git a/internal/courier/smtp.go b/internal/courier/smtp.go index 423cb50..cf2e199 100644 --- a/internal/courier/smtp.go +++ b/internal/courier/smtp.go @@ -2,6 +2,7 @@ package courier import ( "crypto/tls" + "flag" "net" "net/smtp" "time" @@ -19,7 +20,12 @@ var ( // Port for outgoing SMTP. // Tests can override this. - smtpPort = "25" + smtpPort = flag.String("testing__outgoing_smtp_port", "25", + "port to use for outgoing SMTP connections, ONLY FOR TESTING") + + // Bypass the MX lookup, for testing purposes. + bypassMX = flag.Bool("testing__bypass_mx_lookup", false, + "bypass MX lookup, ONLY FOR TESTING") // Fake MX records, used for testing only. fakeMX = map[string]string{} @@ -45,7 +51,7 @@ func (s *SMTP) Deliver(from string, to string, data []byte) error { insecure := false retry: - conn, err := net.DialTimeout("tcp", mx+":"+smtpPort, smtpDialTimeout) + conn, err := net.DialTimeout("tcp", mx+":"+*smtpPort, smtpDialTimeout) if err != nil { return tr.Errorf("Could not dial: %v", err) } @@ -117,6 +123,10 @@ func lookupMX(domain string) (string, error) { return v, nil } + if *bypassMX { + return domain, nil + } + mxs, err := net.LookupMX(domain) if err != nil { return "", err diff --git a/internal/courier/smtp_test.go b/internal/courier/smtp_test.go index 46e21c9..b90a7ba 100644 --- a/internal/courier/smtp_test.go +++ b/internal/courier/smtp_test.go @@ -70,7 +70,7 @@ func TestSMTP(t *testing.T) { host, port, _ := net.SplitHostPort(addr) fakeMX["to"] = host - smtpPort = port + *smtpPort = port s := &SMTP{} err := s.Deliver("me@me", "to@to", []byte("data")) @@ -130,7 +130,7 @@ func TestSMTPErrors(t *testing.T) { host, port, _ := net.SplitHostPort(addr) fakeMX["to"] = host - smtpPort = port + *smtpPort = port s := &SMTP{} err := s.Deliver("me@me", "to@to", []byte("data")) diff --git a/test/t-exim/.gitignore b/test/t-exim/.gitignore new file mode 100644 index 0000000..88be49f --- /dev/null +++ b/test/t-exim/.gitignore @@ -0,0 +1,3 @@ + +# Packages, so fetches via get-exim4-* don't add cruft. +*.deb diff --git a/test/t-exim/config/chasquid.conf b/test/t-exim/config/chasquid.conf new file mode 100644 index 0000000..1302399 --- /dev/null +++ b/test/t-exim/config/chasquid.conf @@ -0,0 +1,5 @@ +address: ":1025" +monitoring_address: ":1099" + +mail_delivery_agent_bin: "test-mda" +mail_delivery_agent_args: "%user%@%domain%" diff --git a/test/t-exim/config/domains/srv-chasquid/users b/test/t-exim/config/domains/srv-chasquid/users new file mode 100644 index 0000000..bd031fe --- /dev/null +++ b/test/t-exim/config/domains/srv-chasquid/users @@ -0,0 +1,2 @@ +#chasquid-userdb-v1 +user SCRYPT@n:14,r:8,p:1,l:32,r00XqNmRkV505R2X6KT8+Q== aAiBBIVNNzmDXwxLLdJezFuxGtc2/wcHsy3FiOMAH4c= diff --git a/test/t-exim/config/exim4.in b/test/t-exim/config/exim4.in new file mode 100644 index 0000000..7623b43 --- /dev/null +++ b/test/t-exim/config/exim4.in @@ -0,0 +1,62 @@ +CONFDIR = ${EXIMDIR} + +spool_directory = CONFDIR/spool +exim_path = CONFDIR/exim4 + +# No need to keep anything on the environment. +# This is the default, but exim emits a warning if it's not set +# (https://www.exim.org/static/doc/CVE-2016-1531.txt). +keep_environment = + +# Disable TLS for now. +tls_advertise_hosts = + +# Run as the current user. +# TODO: obviously do not hard-code it! +exim_group = ${USER} +exim_user = ${USER} + +# Listen on a non-privileged port. +daemon_smtp_port = 2025 + +# ACLs to let anyone send mail (for testing, obviously). +acl_smtp_rcpt = acl_check_rcpt +acl_smtp_data = acl_check_data + +begin acl +acl_check_rcpt: + accept + +acl_check_data: + accept + + +# Forward all incoming email to chasquid (running on :1025 in this test). +begin routers + +rewritedst: + driver = redirect + data = someone@srv-chasquid + +forwardall: + driver = accept + transport = tochasquid + +begin transports + +tochasquid: + driver = smtp + + # exim4 will by default detect and special-case deliveries to localhost; + # this avoids that behaviour and tells it to go ahead anyway. + allow_localhost + hosts_override + + # chasquid will be listening on localhost:1025 + hosts = localhost + port = 1025 + + # Add headers to help debug failures. + delivery_date_add + envelope_to_add + return_path_add diff --git a/test/t-exim/content b/test/t-exim/content new file mode 100644 index 0000000..76a8b16 --- /dev/null +++ b/test/t-exim/content @@ -0,0 +1,4 @@ +Subject: Prueba desde el test + +Crece desde el test el futuro +Crece desde el test diff --git a/test/t-exim/get-exim4-debian.sh b/test/t-exim/get-exim4-debian.sh new file mode 100755 index 0000000..c5cbcb2 --- /dev/null +++ b/test/t-exim/get-exim4-debian.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +# This script downloads the exim4 binary from Debian's package. +# It assumes "apt" is functional, which means it's not very portable, but +# given the nature of these tests that's acceptable for now. + +set -e +. $(dirname ${0})/../util/lib.sh + +init + +# Download and extract the package in .exim-bin +apt download exim4-daemon-light +dpkg -x exim4-daemon-light_*.deb $PWD/.exim-bin/ + +# Create a symlink to .exim4, which is the directory we will use to store +# configuration, spool, etc. +# The configuration template will look for it here. +mkdir -p .exim4 +ln -sf $PWD/.exim-bin/usr/sbin/exim4 .exim4/ + +# Remove the setuid bit, if there is one - we don't need it and may cause +# confusion and/or security troubles. +chmod -s .exim-bin/usr/sbin/exim4 + +success + diff --git a/test/t-exim/hosts b/test/t-exim/hosts new file mode 100644 index 0000000..a338cd2 --- /dev/null +++ b/test/t-exim/hosts @@ -0,0 +1,2 @@ +srv-chasquid localhost +srv-exim localhost diff --git a/test/t-exim/msmtprc b/test/t-exim/msmtprc new file mode 100644 index 0000000..d5e75c1 --- /dev/null +++ b/test/t-exim/msmtprc @@ -0,0 +1,14 @@ +account default + +host srv-chasquid +port 1025 + +tls on +tls_trust_file config/domains/srv-chasquid/cert.pem + +from user@srv-chasquid + +auth on +user user@srv-chasquid +password secretpassword + diff --git a/test/t-exim/run.sh b/test/t-exim/run.sh new file mode 100755 index 0000000..a9803dc --- /dev/null +++ b/test/t-exim/run.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# +# This test checks that we can send and receive mail to/from exim4. +# +# Setup: +# - chasquid listening on :1025. +# - exim listening on :2025. +# - hosts "srv-chasquid" and "srv-exim" pointing back to localhost. +# - exim configured to accept all email and forward it to +# someone@srv-chasquid. +# +# Test: +# msmtp --> chasquid --> exim --> chasquid --> local delivery +# +# msmtp will auth as user@srv-chasquid to chasquid, and send an email with +# recipient someone@srv-exim. +# +# chasquid will deliver the mail to exim. +# +# exim will deliver the mail back to chasquid (after changing the +# destination to someone@chasquid). +# +# chasquid will receive the email from exim, and deliver it locally. + +set -e +. $(dirname ${0})/../util/lib.sh + +init + +# Create a temporary directory for exim4 to use, and generate the exim4 +# config based on the template. +mkdir -p .exim4 +EXIMDIR="$PWD/.exim4" envsubst < config/exim4.in > .exim4/config + +generate_certs_for srv-chasquid + +# Launch chasquid at port 1025 (in config). +# Use outgoing port 2025 which is where exim will be at. +# Bypass MX lookup, so it can find srv-exim (via our host alias). +chasquid -v=2 --log_dir=.logs --config_dir=config \ + --testing__outgoing_smtp_port=2025 \ + --testing__bypass_mx_lookup & + +wait_until_ready 1025 + +# Launch exim at port 2025 +.exim4/exim4 -bd -d -C "$PWD/.exim4/config" > .exim4/log 2>&1 & +wait_until_ready 2025 + +# msmtp will use chasquid to send an email to someone@srv-exim. +run_msmtp someone@srv-exim < content + +wait_for_file .mail/someone@srv-chasquid + +mail_diff content .mail/someone@srv-chasquid + +success