1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-19 14:57:04 +00:00
Commit Graph

110 Commits

Author SHA1 Message Date
Alberto Bertogli
b8c0ac98f4 chasquid: Split Server and Conn
This patch moves chasquid's Server and Conn structures to their own
smtpsrv package, to make chasquid.go a bit more readable. It also helps
clarify the relation between Server and Conn.

There are no functional changes.

Note that git can still track the history across this commit (e.g. git
gui blame shows the right data).
2016-10-21 22:18:48 +01:00
Alberto Bertogli
c013c98283 domaininfo: New package to track domain (security) information
This patch introduces a new "domaininfo" package, which implements a
database with information about domains.  In particular, it tracks
incoming and outgoing security levels.

That information is used in incoming and outgoing SMTP to prevent
downgrades.
2016-10-21 22:15:09 +01:00
Alberto Bertogli
1d7a207e00 Minor code aesthetic improvements, based on vet+fmt+lint
This patch is the result of running go vet, go fmt -s and the linter,
and fixing some of the things they noted/suggested.

There shouldn't be any significant logic changes, it's mostly
readability improvements.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
a5e6e197a6 trace: Quote errors before logging them
Errors can contain newlines, in particular this is common in messages
returned by remote SMTP servers.

This patch quotes them before logging, they don't interfere with the
log. Note the tracer itself can handle this just fine.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
09d3c73f6c queue: Simplify sending loop
This patch simplifies the sending loop code:

 - Move the recipient sending function from a closure to a method.
 - Simplify the status update logic: we now update and write
   unconditionally (as we should have been doing).
 - Create a function for counting recipients in a given status.

It also adds a test for the removal of completed items from the queue,
which was not covered before and came up during development.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
c172894317 chasquid: Update the monitoring HTML index
Add some links to the monitoring HTML index, to reflect the new
additions.

Also reorder to make it more practical, and default to the expanded view
for the tracer links.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
dd35085a32 Remove obsolete TODOs 2016-10-21 22:13:39 +01:00
Alberto Bertogli
a7afa08e7c chasquid: Keep an AUTH event log
This patch adds an AUTH event log, to help troubleshoot issues with
authentication.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
6747f0785e chasquid: Add an expvar to count incoming TLS status 2016-10-21 22:13:39 +01:00
Alberto Bertogli
eadd0ffc89 chasquid: Track and enforce the HELO/EHLO address
HELO and EHLO both take a mandatory parameter, which also should be used
in the Received header.

This patch tracks and enforces that parameter, and also updates the
Received header generation to use it.

https://tools.ietf.org/html/rfc5321#section-4.4
2016-10-21 22:13:39 +01:00
Alberto Bertogli
008cd98e39 chasquid: Break connections after 10 errors
If a connection has accumulated 10 errors, it's very likely that
something has gone significantly wrong, or they're just probing/abusing
the service.

This patch makes chasquid break the connection after 10 errors.
The number is arbitrary, we may adjust it later.
2016-10-21 22:13:39 +01:00
Alberto Bertogli
aa0486b54e protoio: Add a generic protobuf store
This patch adds a generic protobuf store, where one can put and retreive
protobufs, indexed by a string.

This will be used in subsequent patches.
2016-10-10 01:32:55 +01:00
Alberto Bertogli
cf36003e3a trace: Add an EventLog
This patch adds an EventLog wrapper to the trace module, which will be
used in the future to track long-lived objects.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
112e492c3a Normalize domains
We should ignore the domains' case, and treat them uniformly, specially when it
comes to local domains.

This patch extends the existing normalization (IDNA, keeping domains as
UTF8 internally) to include case conversion and NFC form for
consistency.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
ad25706d72 Normalize local usernames using PRECIS
This patch implements local username normalization using PRECIS
(https://tools.ietf.org/html/rfc7564,
https://tools.ietf.org/html/rfc7613)

It makes chasquid accept local email and authentication regardless of
the case. It covers both userdb and aliases.

Note that non-local usernames remain untouched.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
220b5d20ff trace: Set max events to 30 by default
The default for max events is 10, which is a bit short for a normal SMTP
exchange. Expand it to 30 which should be large enough to keep most of
the traces.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
3eac221a7f chasquid: Make the "Received:" header RFC compliant
The Received header has some predefined structure and valid keywords,
this patch adjust how we create them to be compliant with that
structure.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
bc2b3b40a5 chasquid: Skip SPF if the connection has authenticated
Currently, we do SPF checks for all connections.

However, authenticated users will be sending email from different
locations, applying SPF to them will result in false positives.

So this patch makes chasquid skip SPF checking if the connection is
authenticated.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
5b0501e584 Tidy up MAIL FROM and RCPT TO address handling
This patch has small aesthetic changes to make the address handling in
MAIL FROM and RCPT TO a bit more readable.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
2b46f300ca trace: Include debug messages in the traces
We don't want to write debug messages to the log, but having them in
traces is always useful.

The traces are volatile and self-cleaning so the additional volume
should not cause any problems, and helps troubleshooting.

While at it, fix the depth constant when logging.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
3e55b0d742 courier/smtp: Reorder EHLO domain logic
The logic that picks the domain we use for EHLO does not need to live
within the TLS retry cycle, and makes it harder to understand.

This patch moves it out of the way, to improve readability.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
40153e352f chasquid: Detect email loops
This patch implements some measures against email loops, such as keeping
a limit on the lenght of an address, and rejecting email that has too
many Received headers.

It's not perfect (a server could be actively removing Received headers),
but it should cover the normal accidents and misconfigurations.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
c4e8b22fd0 Introduce expvar counters
This patch introduces expvar counters to chasquid and the queue
packages.

For now there's only a handful of counters, but they will be expanded in
future patches.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
641406cede queue: Fix race in tests
The test courier has a racy map access, and this started to manifest
after some recent changes. This patch fixes the race by implementing the
corresponding locks.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
08a5d19941 Add missing Close calls
The SMTP courier was not properly closing the connection, and chasquid's
closing of incoming connections was not ideal (it was closing the
underlying one, not necessarily the active one, like in the case of a jump
to TLS).

This patch fixes both by adding the missing calls to Close.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
dbe3843e12 chasquid: Redact AUTH parameters in debug logs 2016-10-10 00:51:05 +01:00
Alberto Bertogli
7403dbb8a3 chasquid: Minor fixes to MAIL FROM and RCPT TO handling
This patch tidies up the MAIL FROM and RCPT TO handling, in particular:

 - Preserve the case on received email. It could be outgoing and we
   should not change it.
 - Accept (but ignore) RCPT TO options, instead of failing.
 - Fix some error codes to make them follow the RFC.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
3e6dd12d06 Improve debugging and tracing information
This patch reviews various debug and informational messages, making more
uniform use of tracing, and extends the monitoring http server with
useful information like an index and a queue dump.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
2b801a84d1 chasquid: Add SPF checks
This patch makes chasquid perform SPF checks, and add the corresponding
Received-SPF header.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
3d3b771b80 internal/spf: Add an SPF package
This patch adds a package for evaluating SPF, as defined by RFC 7208
(https://tools.ietf.org/html/rfc7208).

It doesn't implement 100% of the RFC, but it coves enough to handle the
most common cases, and will fail open on the others.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
498bb29585 config: Set defaults for suffix_separators and drop_characters
This patch sets common and practical defaults for the suffix_separators ("+")
and drop_character options (".").
2016-10-10 00:51:05 +01:00
Alberto Bertogli
55b03c8cf0 queue: Use a local envelope-from when forwarding
If there's an alias to forward email to a non-local domain, using the original
From is problematic, as we may not be an authorized sender for it.

Some MTAs (like Exim) will do it anyway, others (like gmail) will construct a
special address based on the original address.

This patch implements the latter approach, which is safer and allows the
receiver to properly enforce SPF.

We construct a (hopefully) reasonable From based on the local user, and
embedding the original From (but transformed for IDNA, as the receiver may not
support SMTPUTF8).
2016-10-10 00:51:05 +01:00
Alberto Bertogli
afd79dfd8d courier: Always have a domain for EHLO/HELO
In the SMTP courier, we should always include a domain when saying hello, as
many MTAs will be pick about it.

An empty domain can happen if the envelope-from is <>. In that case, we fall
back to our hostname.
2016-10-10 00:51:05 +01:00
Alberto Bertogli
0e41821779 smtp: Distinguish permanent errors
This patch makes the SMTP courier distinguish permanent errors, so the queue
can decide whether to retry or not.

It's based on the SMTP replies: 5xy is considerent permanent, anything else is
transient (including errors other than protocol issues).
2016-10-10 00:51:04 +01:00
Alberto Bertogli
7cbe6a5076 courier: Support SMTPUTF8 in the SMTP courier
This patch adds SMTPUTF8 to the SMTP courier.

It introduces a new internal/smtp package that extends Go's net/smtp with
SMTPUTF8 (in a very narrow way, not for general use), and then makes the
courier use it.

Also use an IDNA-safe version when saying hello, otherwise servers could
complain if the hostname is not ASCII, and at that stage we don't know if they
support it or not.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
6dda2fff4b chasquid: Introduce support for SMTPUTF8
This patch adds initial support for SMTPUTF8, which for now consists of just
advertising it.

We support most of it, but sending emails over SMTP requires further work, as
the SMTP courier does not support this yet (it's not in Go's standard
library). That will come in subsequent patches, along with IDNA handling.

https://tools.ietf.org/html/rfc6531.html
2016-10-10 00:51:04 +01:00
Alberto Bertogli
f767b83fe0 Implement basic IDNA support
This patch implements the first steps of support for IDNA (Internationalized
Domain Names for Applications).

Internally, we maintain the byte-agnostic representation, including
configuration.

We support receiving IDNA mail over SMTP, which we convert to unicode for
internal handling.

Local deliveries are still kept agnostic.

For sending over SMTP, we use IDNA for DNS resolution, but there are some
corner cases pending in the SMTP courier that are tied with SMTPUTF8 and will
be fixed in subsequent patches.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
7fa40397c5 courier: SMTP falls back to A when MX does not exist
Make the SMTP courier fall back to the A record when MX does not exist, as per
standard behaviour.

This is not implemented nicely, because Go's API does not give a clear signal
if the answer was that there are no MX records or something else happens.
For now, we implement it with a heuristic that should work pretty reliably,
but it's definitely not very nice.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
fdaca0bedf courier: Fix small typo in smtp.go's trace 2016-10-10 00:51:04 +01:00
Alberto Bertogli
2f2d1f2dbd courier: Use the senders' domain when saying EHLO
Some servers, like postfix, will pay close attention to the domain we say as a
part of the EHLO.

By default, Go's smtp package will use "localhost", causing it to complain.

This patch fixes that by using the envelope-from's domain.
It's not clear if that's better than using what we are resolving to, but
that's much more involved so we're going to do this for now.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
280939c3ec chasquid: Don't enforce authentication at MAIL FROM
There are cases, like email bounces and forwarding, where a remote server may
use an address within our domain as "MAIL FROM".

The current test at MAIL FROM will block them, which can be quite an
inconvenience as those cases are not that rare.

It's a nice test but doesn't add much, as we don't really pass the validation
along, and we still do relay and user checks on RCPT TO.

So this patch removes that test.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
1e74e02506 smtp-check: Add a small utility to check SMTP setups
This patch adds a small utility called "smtp-check" that will perform basic
checks on the SMTP setup for the given domain.

Only basic things are implemented for now.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
d97a4047c1 chasquid: Use human-readable TLS constants in addReceivedHeader
Make the "Received" header a bit more human-friendly by using the newly
introduced tlsconst package.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
16d9d45e06 internal/tlsconst: Add a package with TLS constants
There are a couple of places where it's handy to print TLS constants in
human-readable form.

To do so, we need functions that take TLS constants (usually in uint16 form)
and give us friendly strings.

Go's crypto/tls package does not provide us with this, so this patch
introduces a new module with that purpose.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
e138f0dc05 chasquid: De-couple TLS certificates from domains
Having the certificates inside the domain directory may cause some confusion,
as it's possible they're not for the same name (they should be for the MX we
serve as, not the domain itself).

So it's not a problem if we have domains with no certificates (we could be
their MX with another name), and we could have more than one certificate per
"domain" (if we act as MXs with different names).

So this patch moves the certificates out of the domains into a new certs/
directory, where we do a one-level deep lookup for the files.

While at it, change the names of the files to "fullchain.pem" and
"privkey.pem", which match the names generated by the letsencrypt client, to
make it easier to set up.  There's no general convention for these names
anyway.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
04dd8b9534 Remove unreachable code, and don't leak contexts
This patch performs some minor cleanups for things detected by "go vet":

 - Remove one line of unreachable code.
 - Don't leak contexts until their deadline expires, cancel them.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
0995eac474 chasquid: Fail at RCPT TO time if a user does not exist
It's more convenient and in line with standard practice to fail RCPT TO if the
user does not exist.

This involves making the server and client aware of aliases, but it doesn't
end up being very convoluted, and simplifies other code.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
ce379dea3e chasquid-util: Add a print-config option
This patch adds a print-config option that will parse a config and print it
(in text protobuf format).

It can be used to validate configurations, and see what the effective
configuration is (that is, including the defaults).
2016-10-10 00:51:04 +01:00
Alberto Bertogli
935494429d test: Add RACE=1 variable to run with the race detector
It's often useful to run the tests with the race detector (-race) enabled.
Unfortunately, building with it is too slow to enable unconditionally.

So for now this patch adds an option, in the form of an environment variable,
to enable it manually.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
1433340ea6 chasquid: Periodically reload the user databases
This patch makes chasquid periodically reload the user databases, in line with
what we do for aliases.
2016-10-10 00:51:04 +01:00