mirror of
https://gitlab.kit.edu/kit/scc/sys/mail/exim-encrypt-dlfunc.git
synced 2025-12-06 09:23:57 +01:00
199 lines
7.7 KiB
Markdown
199 lines
7.7 KiB
Markdown
# exim-encrypt-dlfunc
|
|
|
|
This library injects functions for string encryption and decryption into [exim4](https://www.exim.org/). It is basically
|
|
glue code that exports certain parts of the [libsodium library](https://github.com/jedisct1/libsodium) to exim at runtime.
|
|
|
|
[[_TOC_]]
|
|
|
|
## Installation
|
|
|
|
These instructions are currently only tested on [Debian](https://www.debian.org) and
|
|
[Ubuntu](https://ubuntu.com).
|
|
|
|
1. Install development tools and libsodium development files:
|
|
|
|
```shell
|
|
apt-get install -y build-essential exim4-dev libsodium-dev meson pkg-config openssl exim4-daemon-heavy
|
|
```
|
|
|
|
This project uses [meson](https://mesonbuild.com/) (and [ninja](https://ninja-build.org/)) as build system. To ensure
|
|
all features are present (which are lacking in the packaged versions of older distributions)
|
|
you are strongly advised to install from [pypi](https://pypi.org/) via [pip](https://pypi.org/project/pip/):
|
|
|
|
```shell
|
|
apt-get install -y python3-pip
|
|
pip3 install -U meson ninja
|
|
```
|
|
|
|
You may alternatively try to use your distribution packages:
|
|
|
|
```shell
|
|
apt-get install -y meson
|
|
```
|
|
|
|
2. Clone this repository:
|
|
|
|
```shell
|
|
git clone https://git.scc.kit.edu/mail/exim-encrypt-dlfunc.git
|
|
cd exim-encrypt-dlfunc
|
|
```
|
|
|
|
3. Build and test everything:
|
|
|
|
```shell
|
|
meson build # run only once
|
|
meson compile -C build
|
|
meson test -C build
|
|
```
|
|
|
|
The `ci_container` directory contains a [script](ci_container/build.sh) (and a [short README](ci_container/README.md))
|
|
which creates the container images used in continuous integration for this project.
|
|
|
|
5. Install library and tools (defaults to `/usr/local/bin` and `/usr/local/lib/x86_64-linux-gnu`):
|
|
|
|
```shell
|
|
meson install -C build
|
|
```
|
|
|
|
6. Ensure you have the correct exim build:
|
|
|
|
Not every build of exim is able to load libraries at runtime. Please refer to the
|
|
[documentation](https://www.exim.org/exim-html-current/doc/html/spec_html/ch-string_expansions.html)
|
|
of the `${dlfunc{…}}` function for details. The Debian
|
|
package [`exim4-daemon-heavy`](https://packages.debian.org/exim4-daemon-heavy)
|
|
meets these requirements.
|
|
|
|
Try
|
|
|
|
```shell
|
|
exim4 --version | egrep -i --color 'Expand_dlfunc|Content_Scanning'
|
|
```
|
|
|
|
for a preliminary test.
|
|
|
|
7. Configure exim to use the new functionality
|
|
|
|
This highly depends on your use case. See [the example below](#xoip-example) and
|
|
[`src/test_libexim-encrypt-dlfunc.sh`](src/test_libexim-encrypt-dlfunc.sh).
|
|
|
|
## Usage
|
|
|
|
There are currently two sets of complementary function pairs:
|
|
|
|
### Symmetric encryption that derives the key from an ASCII string (aka a “password”)
|
|
|
|
* `sodium_crypto_secretbox_encrypt_password(password, cleartext) → ciphertext`
|
|
* `sodium_crypto_secretbox_decrypt_password(password, ciphertext) → cleartext`
|
|
|
|
The generated key is only as strong as the provided password. Use `openssl rand --base64 48 | tr -d =`
|
|
to get a passable password.
|
|
|
|
### Public key encryption that uses a key pair which needs to be created beforehand
|
|
|
|
* `sodium_crypto_box_seal(public key, cleartext) → ciphertext`
|
|
* `sodium_crypto_box_seal_open(private key, public key, ciphertext) → cleartext`
|
|
|
|
The second pair needs a matching key pair in the correct format. This is what the
|
|
`libexim-encrypt-dlfunc-genkeys` utility is for. Simply run it once to generate a pair in the current directory. Be
|
|
aware that every invocation will overwrite the previous key pair file without confirmation! Make sure to store your
|
|
production keys in a safe place!
|
|
|
|
```shell
|
|
$ libexim-encrypt-dlfunc-genkeys
|
|
=== Creating cryptobox key pair ===
|
|
Wrote »cryptobox_recipient_pk_exim.conf«
|
|
Wrote »cryptobox_recipient_pk.raw«
|
|
Wrote »cryptobox_recipient_sk_exim.conf«
|
|
Wrote »cryptobox_recipient_sk.raw
|
|
```
|
|
|
|
The `*_exim.conf` files contain the keys in a format that can simply be used in
|
|
`exim.conf` (the first line contains the key as a C code comment and can usually be ignored or discarded):
|
|
|
|
```shell
|
|
$ cat cryptobox_recipient_pk_exim.conf
|
|
# const unsigned char cryptobox_recipient_pk[32] = { 0xda, 0x46, 0xc8, 0x75, 0x2b, 0x31, 0xd9, 0x0c, 0x83, 0x54, 0x2d,
|
|
# 0x18, 0xda, 0xdc, 0xe5, 0x2d, 0x0e, 0x10, 0xe8, 0x0c, 0x39, 0xde, 0xaf, 0x30, 0x7e, 0xab, 0xca, 0x4d, 0xed, 0x26,
|
|
# 0x4d, 0x6e }; const unsigned int cryptobox_recipient_pk_length = 32;
|
|
CRYPTOBOX_RECIPIENT_PK=2kbIdSsx2QyDVC0Y2tzlLQ4Q6Aw53q8wfqvKTe0mTW4=
|
|
```
|
|
|
|
The `*.raw` files contain the same key without any formatting; these files are not needed for usage with exim but are
|
|
generated as convenience when writing your own tools.
|
|
|
|
### Example: remove `X-Originating-IP:` header
|
|
|
|
<a name="xoip-example"></a>
|
|
This task was the initial reason to develop this library: remove the X-Originating-IP header to preserve our user's
|
|
privacy but also keep the information in the final e-mail to enable response to complaints and abuse (the original
|
|
header is usually provided in these cases). Add this snippet to your DATA ACL section in exim:
|
|
|
|
```
|
|
warn log_message = Removing X-Originating-IP: header
|
|
condition = ${if def:h_X-originating-IP: {1}{0}}
|
|
add_header = X-Orig-IP-PKK: ${dlfunc{/usr/lib/x86_64-linux-gnu/libexim-encrypt-dlfunc.so} \
|
|
{sodium_crypto_box_seal} \
|
|
{ktp1OEEItrgvSfpVTtu+ybyNjzuuN8OzCdfrGAJt4j8=} \
|
|
{$h_X-originating-IP:}}
|
|
add_header = X-Orig-IP-Pass: ${dlfunc{/usr/lib/x86_64-linux-gnu/libexim-encrypt-dlfunc.so} \
|
|
{sodium_crypto_secretbox_encrypt_password} \
|
|
{Insert your password here} \
|
|
{$h_X-originating-IP:}}
|
|
remove_header = X-Originating-IP
|
|
|
|
```
|
|
|
|
Pick one of the `add_header` lines depending on which kind of encryption you want.
|
|
|
|
### Decryption Tools
|
|
|
|
Two additional programs are included:
|
|
|
|
* `libexim-encrypt-dlfunc-decrypt-secretbox`
|
|
* `libexim-encrypt-dlfunc-decrypt-sealedbox`
|
|
|
|
They can decrypt strings that were encrypted by the two respective functions. Please refer to their `--help` message
|
|
(reproduced below) for usage information and to both [test](src/test_libexim-encrypt-dlfunc-decrypt-secretbox.sh)
|
|
[scripts](src/test_libexim-encrypt-dlfunc-decrypt-sealedbox.sh) for usage examples.
|
|
|
|
```shell
|
|
$ libexim-encrypt-dlfunc-decrypt-secretbox -h
|
|
Usage: libexim-encrypt-dlfunc-decrypt-secretbox [OPTIONS] [CIPHERTEXT]
|
|
|
|
Password:
|
|
-p, --password PASSWORD Decrypt using PASSWORD
|
|
|
|
If the environment variable LIBEXIM_PASSWORD is set the password is read from there.
|
|
Setting a password with -p/--password overwrites this mechanism.
|
|
|
|
Select input:
|
|
-f, --infile FILE Decrypt contents of the first line of file FILE (use - for stdin)
|
|
|
|
Output:
|
|
-n, --no-newline Do not append a newline to the output
|
|
|
|
Password and ciphertext are expected to be base64-encoded (as produced by the library).
|
|
```
|
|
|
|
```shell
|
|
$ libexim-encrypt-dlfunc-decrypt-sealedbox -h
|
|
Usage: libexim-encrypt-dlfunc-decrypt-sealedbox [OPTIONS] [CIPHERTEXT]
|
|
|
|
Secret and public key:
|
|
-s, --secret-key SECRETKEY Secret key (base64-encoded)
|
|
-p, --public-key PUBLICKEY Public key (base64-encoded)
|
|
-S, --secret-key-file FILE Read secret key (raw) from file FILE (use - for stdin)
|
|
-P, --public-key-file FILE Read public key (raw) from file FILE (use - for stdin)
|
|
|
|
The environment variables LIBEXIM_SECRETKEY and LIBEXIM_PUBLICKEY may contain base64-encoded secret/public keys.
|
|
|
|
Select input:
|
|
-f, --infile FILE Decrypt contents of the first line of file FILE (use - for stdin)
|
|
|
|
Output:
|
|
-n, --no-newline Do not append a newline to the output
|
|
|
|
Keys in arguments and environment variables are expected to be base64 encoded (as produced by the library).
|
|
Keys in files need to be raw bytes with no encoding, ciphertext should always be base64-encoded.
|
|
```
|