2021-09-13 00:28:12 +02:00
2021-09-13 00:28:12 +02:00
2021-09-13 00:28:12 +02:00
2021-08-20 01:25:15 +02:00
2021-08-22 02:17:11 +02:00

exim-encrypt-dlfunc

This library injects functions for string encryption and decryption into exim4. It is basically glue code that exports certain parts of the libsodium library to exim at runtime.

[[TOC]]

Installation

These instructions are currently only tested on Debian and Ubuntu.

  1. Install development tools and libsodium development files:
apt-get install -y build-essential exim4-dev libsodium-dev meson pkg-config openssl exim4-daemon-heavy

exim-encrypt-dlfunc uses meson (and ninja) as build system. To ensure all features are present (which are lacking in the version packages in older distributions) it is advised to install from pypi via pip:

apt-get install -y python3-pip
pip3 install meson ninja

You may alternatively use your distribution packages:

apt-get install -y meson
  1. Clone this repository:
git clone https://git.scc.kit.edu/mail/exim-encrypt-dlfunc.git
cd exim-encrypt-dlfunc
  1. Build and test everything:
meson build # run only once
meson compile -C build
meson test -C build

The ci_container directory contains a script (and a short README) which creates the images used in continous integration for this project.

  1. Copy to final destination (feel free to pick another place than /usr/lib/x86_64-linux-gnu/):
meson install -C build
  1. Ensure you have the correct exim build:

    Not every build of exim is able to load libraries at runtime. Please refer to the documentation of the ${dlfunc{…}} function for details. The Debian package exim4-daemon-heavy meets these requirements.

Try

exim4 --version | egrep -i --color 'Expand_dlfunc|Content_Scanning'

for a preliminary test.

Usage

There are currently two pairs of complementary functions:

Symmetric encryption that derives a 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.

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 proper 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. 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.

$ 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 discarded):

$ 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

This example's use case 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 the test scripts for usage examples.

$ 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).
$ 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.
Description
No description provided
Readme 325 KiB
Languages
C 71%
Shell 22.3%
Meson 3.3%
Dockerfile 2.6%
Python 0.8%