diff --git a/plinth/modules/email/__init__.py b/plinth/modules/email/__init__.py index b0049a89f..475e1ffb9 100644 --- a/plinth/modules/email/__init__.py +++ b/plinth/modules/email/__init__.py @@ -52,7 +52,7 @@ class EmailApp(plinth.app.App): app_id = 'email' - _version = 4 + _version = 5 def __init__(self) -> None: """Initialize the email app.""" @@ -116,6 +116,7 @@ class EmailApp(plinth.app.App): '/etc/rspamd/local.d/freedombox-logging.inc', '/etc/rspamd/local.d/freedombox-milter-headers.conf', '/etc/rspamd/local.d/freedombox-redis.conf', + '/etc/rspamd/local.d/freedombox-dkim-signing.conf' ]) self.add(dropin_configs) dropin_configs_sieve = DropinConfigs( @@ -219,6 +220,9 @@ class EmailApp(plinth.app.App): # Expose to public internet if old_version == 0: self.enable() + elif old_version < 5: + privileged.fix_incorrect_key_ownership() + service_privileged.try_restart('rspamd') def _get_first_admin(): diff --git a/plinth/modules/email/data/usr/share/freedombox/etc/rspamd/local.d/freedombox-dkim-signing.conf b/plinth/modules/email/data/usr/share/freedombox/etc/rspamd/local.d/freedombox-dkim-signing.conf new file mode 100644 index 000000000..509977540 --- /dev/null +++ b/plinth/modules/email/data/usr/share/freedombox/etc/rspamd/local.d/freedombox-dkim-signing.conf @@ -0,0 +1,11 @@ +# Do not edit this file. Manage your settings on FreedomBox or make your +# settings changes in a different configuration file. + +# Configure how DKIM signatures are made by rspamd on outgoing mail. + +# When sending an email with address that is an alias, the username used for +# authentication will not match the email address in 'From' field. rspamd +# refuses to add a DKIM signatures to such outgoing mail. Allow DKIM signatures +# to be made on outgoing mails where the 'From' does not match the authenticated +# user. +allow_username_mismatch = true; diff --git a/plinth/modules/email/privileged/__init__.py b/plinth/modules/email/privileged/__init__.py index cf5e8ea28..028c71157 100644 --- a/plinth/modules/email/privileged/__init__.py +++ b/plinth/modules/email/privileged/__init__.py @@ -2,13 +2,15 @@ """Provides privileged actions that run as root.""" from .aliases import setup_aliases -from .dkim import get_dkim_public_key, setup_dkim +from .dkim import (get_dkim_public_key, setup_dkim, + fix_incorrect_key_ownership) from .domain import set_domains from .home import setup_home from .postfix import setup_postfix from .spam import setup_spam __all__ = [ - 'setup_aliases', 'get_dkim_public_key', 'setup_dkim', 'set_domains', - 'setup_home', 'setup_postfix', 'setup_spam' + 'setup_aliases', 'get_dkim_public_key', 'setup_dkim', + 'fix_incorrect_key_ownership', 'set_domains', 'setup_home', + 'setup_postfix', 'setup_spam' ] diff --git a/plinth/modules/email/privileged/dkim.py b/plinth/modules/email/privileged/dkim.py index f57ba47fb..d3b9273c6 100644 --- a/plinth/modules/email/privileged/dkim.py +++ b/plinth/modules/email/privileged/dkim.py @@ -10,9 +10,12 @@ import shutil import subprocess from plinth.actions import privileged +from plinth.privileged import service as service_privileged _keys_dir = pathlib.Path('/var/lib/rspamd/dkim/') +rspamd_user = '_rspamd' + DOMAIN_PART_REGEX = r'^[a-zA-Z0-9]([-a-zA-Z0-9]{,61}[a-zA-Z0-9])?$' @@ -40,7 +43,7 @@ def setup_dkim(domain: str): _keys_dir.mkdir(exist_ok=True) _keys_dir.chmod(0o500) - shutil.chown(_keys_dir, '_rspamd', '_rspamd') + shutil.chown(_keys_dir, rspamd_user, rspamd_user) # Default path is /var/lib/dkim/$domain.$selector.key. Default selector is # "dkim". Use these to simplify key management until we have a need to @@ -55,4 +58,13 @@ def setup_dkim(domain: str): 'rspamadm', 'dkim_keygen', '-t', 'rsa', '-b', '2048', '-s', 'dkim', '-d', domain, '-k', (str(key_file)) ], check=True) + shutil.chown(key_file, rspamd_user, rspamd_user) key_file.chmod(0o400) + service_privileged.try_restart('rspamd') + + +@privileged +def fix_incorrect_key_ownership(): + """Set the ownership on DKIM private keys.""" + for key in _keys_dir.glob('*.dkim.key'): + shutil.chown(key, rspamd_user, rspamd_user) diff --git a/plinth/modules/email/privileged/spam.py b/plinth/modules/email/privileged/spam.py index 046a2b508..43451f9e3 100644 --- a/plinth/modules/email/privileged/spam.py +++ b/plinth/modules/email/privileged/spam.py @@ -4,6 +4,8 @@ Configures rspamd to handle incoming and outgoing spam. See: http://www.postfix.org/MILTER_README.html See: https://rspamd.com/doc/configuration/ucl.html + +For testing DKIM signatures: https://www.mail-tester.com/ """ import pathlib @@ -37,7 +39,8 @@ def _setup_rspamd(): """Adjust configuration to include FreedomBox configuration files.""" configs = [('milter_headers.conf', 'freedombox-milter-headers.conf'), ('redis.conf', 'freedombox-redis.conf'), - ('logging.inc', 'freedombox-logging.inc')] + ('logging.inc', 'freedombox-logging.inc'), + ('dkim_signing.conf', 'freedombox-dkim-signing.conf')] base_path = pathlib.Path('/etc/rspamd/local.d') for orig_path, include_path in configs: _setup_local_include(base_path / orig_path, base_path / include_path)