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

67 Commits

Author SHA1 Message Date
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
Alberto Bertogli
a5ea6c9ba0 aliases: Add files unconditionally, to allow for reloads
Today, if the aliases file does not exist when chasquid starts up, the entire
domain will be skipped from aliases resolution.

That's a bug, as it means we don't perform character and suffix replacements
for known domains, and is also an inconvenience as it forces us to reload the
daemon when adding a file for a known domain.

This patch fixes this by adding them unconditionally, even if the file does
not exist.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
469cbd5d76 test: Add a test for DSN and null address deliveries
This patch adds a test for delivery status notifications and null address
deliveries, that check that chasquid can both receive and send DSNs.

To do this, we extend the mail_diff utility to support wildcards in the
comparisons, to skip over variable parts of the messages (like dates).
2016-10-10 00:51:04 +01:00
Alberto Bertogli
1d3675a133 queue: Send delivery status notifications on failures
When we permanently failed to deliver to one or more recipients, send delivery
status notifications back to the sender.

To do this, we need to extend a couple of internal structures, to keep track
of the original destinations (so we can include them in the message, for
reference), and the hostname we're identifying ourselves as (this is arguable
but we're going with it for now, may change later).
2016-10-10 00:51:04 +01:00
Alberto Bertogli
927a74aa3c Improve handling of <> addresses
We can send and received with a <> "mail from", which is explicitly allowed.

Internally, we use "<>" to represent it. This requires special-casing in a
couple of places, but makes sure the handling is explicit, and we don't
accidentally confuse it with not having a source address.

This patch fixes some inconsistencies with this handling.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
0bf5d9b242 Distinguish between permanent and transient errors
This patch makes the queue and couriers distinguish between permanent and
transient errors when delivering mail to individual recipients.

Pipe delivery errors are always permanent.

Procmail delivery errors are almost always permanent, except if the command
exited with code 75, which is an indication of transient.

SMTP delivery errors are almost always transient, except if the DNS resolution
for the domain failed.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
0dc93d1ec6 chasquid: Remove overly verbose error about TLS config 2016-10-10 00:51:04 +01:00
Alberto Bertogli
711459b798 chasquid: Remove support for test keys
The test key flags have not been used in a while, so this patch removes
them, which simplifies the initialization code a little bit.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
3d06fb3a78 Turn chasquid-userdb into chasquid-util
This patch removes chasquid-userdb and adds a more generic and extensive
chasquid-util, that supports various operations on user databases as well as
aliases lookups.

The code is not very pretty but for now I took a more practical approach, the
tool is ancillary and can be tidied up later.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
859d4733f8 userdb: Add a method to remove users
This patch adds a method to userdb to remove users.
It will not be used by chasquid, but by the command-line tool.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
667358d72e courier: Tidy up the Procmail courier
This patch tidies up the Procmail courier:
 - Move the configuration options to the courier instance, instead of using
   global variables.
 - Implement more useful string replacement options.
 - Use exec.CommandContext for running the command with a timeout.

As a consequence of the first item, the queue now takes the couriers via its
constructor.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
d05b8ef189 chasquid: Add "Received" email headers
This patch makes chasquid add "Received" email headers, after DATA completes
and before queueing.

We only use this for debugging purposes.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
5f15b4e040 test: Skip exim test if the binary is not found
The exim test requires a bit more preparation than the rest, so skip it if the
binary is not found or not working properly.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
c34c073c1c chasquid: Load and resolve aliases
This patch integrates the aliases resolution into the daemon and queue.

The queue now will resolve aliases at Put time.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
bab8a8083c queue: Support sending to pipes
With the introduction of aliases, the queue may now be delivering mail to
pipes. This patch implements pipe delivery.

It uses a fixed 30s timeout for now, as these commands should really not take
much time, and we don't want to overly complicate the configuration for now.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
a531092f8b aliasesdb: Implement an aliases database resolver
aliases databases can be very useful, so this patch adds a package to parse
and resolve aliases.

It uses an existing, well known and widely used format for aliases, although
it doesn't necessarily match 100% any existing implementation at the moment.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
aacf8ffea7 queue: Implement persistency
This patch makes the queue read and write items to disk.

It uses protobuf for serialization. We serialize to text format to make
manual troubleshooting easier, as the performance difference is not very
relevant for us.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
9ed30a747b config: Add a "data_dir" option
This patch adds a "data_dir" option, that chasquid will use to store
persistent data. It defaults to "/var/lib/chasquid" (for now, at least).

Users will come in subsequent patches.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
e9d62e0467 chasquid: Do a Chdir into the configuration directory
In some cases, it's be useful to have references to directories relative
to the configuration itself.

So this patch makes chasquid do a Chdir into it, so we can assume it in
the rest of the code and config.
2016-10-10 00:51:04 +01:00
Alberto Bertogli
f375f276af safeio: Prefix temporary files with "."
To avoid user and automation confusion, prefix the temporary files with
a ".". That way, if something scans the directory for files, it's less
likely to encounter one of our temporary files.

This will become very relevant in subsequent patches.
2016-10-10 00:51:03 +01:00
Alberto Bertogli
394067bbd3 userdb: Use protocol buffers instead of our custom format
Protocol buffers are a more portable, practical and safe format for the user
database.
2016-10-10 00:51:03 +01:00
Alberto Bertogli
5c6fb934fe Re-generate protocol buffer code
This is just a run of "go generate ./..." which re-generates the protocol
buffers code.

There is no actual change in the logic or APIs, it's just a rebuild with a
newer proto compiler. While it's not strictly necessary, it will help make
subsequent patches cleaner.
2016-10-10 00:51:03 +01:00
Alberto Bertogli
960c348d42 protoio: I/O helpers for protobuf messages 2016-10-10 00:51:03 +01:00
Alberto Bertogli
e2fdcb3705 Add checks to prevent unauthorized relaying and impersonation
This patch adds checks that verify:

 - The envelope from must match the authenticated user. This prevents
   impersonation at the envelope level (while still allowing bounces, of
   course).
 - If the destination is remote, then the user must have completed
   authentication. This prevents unauthorized relaying.

The patch ends up adjusting quite a few tests, as they were not written
considering these restrictions so they have to be changed accordingly.
2016-10-10 00:50:56 +01:00
Alberto Bertogli
941eb9315c Distinguish between SMTP and submission ports
We want to be able to distinguish between connections for SMTP and connections
for submission, so we can make different policy decisions.

To do that, we first make the configuration aware of the different kinds of
addresses. This is done in this patch in a backwards-incompatible way, but at
this point in time it is ok to do so.

Then, we extend systemd's socket passing library to support socket naming, so
we can tell the different sockets apart. This is done via the
LISTEN_FDNAMES/FileDescriptorName mechanism.

And finally we make the server and connection types aware of the socket mode.
2016-10-10 00:50:24 +01:00
Alberto Bertogli
69222284e0 test: Rename test directories to use an explicit order
For convenience, rename the directories so the order is explicit in the name.
Make the simple test run first, to save time if it's not working.
2016-09-12 04:06:56 +01:00
Alberto Bertogli
2c90281c11 test: Add top-level README and run script 2016-09-12 04:06:56 +01:00
Alberto Bertogli
905161c537 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.
2016-09-12 04:06:56 +01:00
Alberto Bertogli
aac2d3c061 Minor style and simplification cleanups
This patch does various minor style and simplification cleanups, fixing things
detected by tools such as go vet, gofmt -s, and golint.

There are no functional changes, this change is purely cosmetic, but will
enable us to run those tools more regularly now that their output is clean.
2016-09-12 04:06:56 +01:00
Alberto Bertogli
92a88bd06f test: Add a new local end-to-end test
This patch introduces a new directory, test/, which contains a simple local
end-to-end test which runs a chasquid binary and uses msmtp to send an email,
which is delivered locally.

As it's the first one, it adds a bunch of common infrastructure to simplify
writing these kinds of tests.

More end-to-end tests will follow, and it's expected that the common
infrastructure will also change significantly to accomodate their needs.
2016-09-12 04:06:56 +01:00
Alberto Bertogli
92d16a0ca9 Add a new "chasquid-userdb" command line tool
This patch adds a "chasquid-userdb" command line tool to check and add users
to chasquid's userdb files.

It's not pretty or very friendly, as it's meant to be used for testing for
now.
2016-08-01 22:56:57 +01:00
Alberto Bertogli
7eba9bb4f7 chasquid: Flush logs periodically and before exiting
This patch makes chasquid flush logs periodically, and also before exiting,
even if it gets killed via the usual signals (including Ctrl-C).

Both things help troubleshooting when there is not much traffic, or we kill
the server manually (including during automated tests).
2016-08-01 22:56:57 +01:00
Alberto Bertogli
ae1c246bde chasquid: Make "MAIL FROM" ignore extra parameters
MAIL FROM commands usually come in the form of:

  MAIL FROM:<from@from> BODY=8BITMIME

Note that there's extra parameters after the address, which for now we want to
ignore.

The current parser doesn't ignore them, and relies on mail.ParseAddress doing
so (that is, on mail.ParseAddress("<from> BODY=8BITMIME") working).
However, in go 1.7, the parser will get more strict and start to fail these
cases.

To fix this, we change the way we parse the line to use fmt.Sprintf, which is
much nicer than splitting by hand, and is more readable as well.
2016-07-22 01:44:45 +01:00
Alberto Bertogli
9d172a6ea0 Make the queue aware of local and remote couriers
The routing courier is a nice idea in theory, but at least for now, we want
the queue to be aware of when a destination is local so we can implement
differentiated logic.

This may change in the future, though, but at the moment it's not clear that
the abstractions will be worth it.

So this patch removes it, and makes the queue do the routing. There is no
difference in how the two are handled yet, those will come in subsequent
patches.
2016-07-22 01:44:45 +01:00
Alberto Bertogli
362ef6f6d0 Introduce an "envelope" package
This patch introduces an "envelope" package which, for now, provides simple
utilities for getting the user and domain of an address.

It also changes the couriers to use it (but other implementations remain, will
be moved over in subsequent patches).
2016-07-22 01:44:45 +01:00
Alberto Bertogli
831ef13132 queue: Add a mutex to protect item's results
The item results get accessed in various places concurrently, so this patch
adds a mutex to protect it.
2016-07-22 01:44:45 +01:00
Alberto Bertogli
21e69aa42f Implement AUTH
This patch implements the AUTH SMTP command, using per-domain user databases.

Note that we don't really use or check the validation for anything, this is
just implementing the command itself.
2016-07-22 01:44:45 +01:00
Alberto Bertogli
ff103c18c3 courier: Let the users configure the mail delivery agent
This patch adds configuration options for the MDA binary and command line
arguments, and changes the (soon to be renamed) procmail courier to make use
of them.
2016-07-16 12:33:51 +01:00
Alberto Bertogli
bb08be4023 .gitignore: Exclude *.pem files 2016-07-16 12:33:50 +01:00
Alberto Bertogli
9015e97ae1 Implement a simple user database (internal/userdb)
This patch adds a package implementing a simple user database, called userdb.
It has a human readable space-separated extensible format, and uses scrypt for
password storage (but supports plain as well, for debugging and testing).

chasquid is not using it yet, that will come in later patches.
2016-07-16 12:33:50 +01:00
Alberto Bertogli
c12fa0eed7 Add a new internal/safeio package for safer I/O functions
This patch adds a new internal/safeio package, which is meant to implement
safer version of some I/O related functions.

For now, only an atomic version of ioutil.WriteFile is implemented. More may
be added later if there's a need for them.
2016-07-16 12:33:50 +01:00
Alberto Bertogli
7e7c8073c4 Implement VRFY and EXPN commands
We implement the VRFY and EXPN commands, but as no-ops. The RFC allows this,
and most implementations seem to do it this way too.

While at it, merge the tests for simple commands like these into one.
2016-07-16 12:33:50 +01:00
Alberto Bertogli
e32ba1ee86 courier: Make procmail's sanitize be more unicode friendly
Sanitize only lets some ascii characters go through, which is very unfriendly
to non-ascii usernames.

This patch changes it to be more inclusive, and filter out only selected
characters that may be problematic for the subprocesses, specially considering
UNIX shell environments. It's not meant to catch all possible problems, just
help prevent some common ones.
2016-07-16 12:33:34 +01:00
Alberto Bertogli
724d915e95 Implement a string set data type
We will need a few string sets in different places, create it as a separate
package for convenience.

For now, it only implements strings, but it may be extended to other data
types in the future.
2016-05-06 23:00:55 +01:00