diff options
Diffstat (limited to 'roles/IMAP')
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/10-logging.conf | 85 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/10-mail.conf | 45 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf | 33 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/15-lda.conf | 2 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/20-imap.conf | 29 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/conf.d/90-plugin.conf | 5 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/dovecot-dict-auth.conf.ext | 2 | ||||
-rw-r--r-- | roles/IMAP/files/etc/dovecot/dovecot-ldap.conf.ext | 11 | ||||
-rw-r--r-- | roles/IMAP/files/etc/systemd/system/dovecot-auth-proxy.service | 10 | ||||
-rwxr-xr-x | roles/IMAP/files/usr/local/bin/dovecot-auth-proxy.pl | 104 | ||||
-rwxr-xr-x | roles/IMAP/files/usr/local/bin/list-users.pl | 45 | ||||
-rw-r--r-- | roles/IMAP/tasks/imap.yml | 17 | ||||
-rw-r--r-- | roles/IMAP/tasks/mda.yml | 2 | ||||
-rw-r--r-- | roles/IMAP/tasks/spam.yml | 4 | ||||
-rw-r--r-- | roles/IMAP/templates/etc/dovecot/conf.d/10-master.conf.j2 | 30 | ||||
-rw-r--r-- | roles/IMAP/templates/etc/dovecot/conf.d/15-lda.conf | 0 | ||||
-rw-r--r-- | roles/IMAP/templates/etc/postfix/main.cf.j2 | 2 |
17 files changed, 218 insertions, 208 deletions
diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-logging.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-logging.conf deleted file mode 100644 index 848fe69..0000000 --- a/roles/IMAP/files/etc/dovecot/conf.d/10-logging.conf +++ /dev/null @@ -1,85 +0,0 @@ -## -## Log destination. -## - -# Log file to use for error messages. "syslog" logs to syslog, -# /dev/stderr logs to stderr. -#log_path = syslog - -# Log file to use for informational messages. Defaults to log_path. -#info_log_path = -# Log file to use for debug messages. Defaults to info_log_path. -#debug_log_path = - -# Syslog facility to use if you're logging to syslog. Usually if you don't -# want to use "mail", you'll use local0..local7. Also other standard -# facilities are supported. -#syslog_facility = mail - -## -## Logging verbosity and debugging. -## - -# Log unsuccessful authentication attempts and the reasons why they failed. -#auth_verbose = no - -# In case of password mismatches, log the attempted password. Valid values are -# no, plain and sha1. sha1 can be useful for detecting brute force password -# attempts vs. user simply trying the same password over and over again. -# You can also truncate the value to n chars by appending ":n" (e.g. sha1:6). -#auth_verbose_passwords = no - -# Even more verbose logging for debugging purposes. Shows for example SQL -# queries. -#auth_debug = no - -# In case of password mismatches, log the passwords and used scheme so the -# problem can be debugged. Enabling this also enables auth_debug. -#auth_debug_passwords = no - -# Enable mail process debugging. This can help you figure out why Dovecot -# isn't finding your mails. -#mail_debug = no - -# Show protocol level SSL errors. -#verbose_ssl = no - -# mail_log plugin provides more event logging for mail processes. -plugin { - # Events to log. Also available: flag_change append - #mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename - # Available fields: uid, box, msgid, from, subject, size, vsize, flags - # size and vsize are available only for expunge and copy events. - #mail_log_fields = uid box msgid size -} - -## -## Log formatting. -## - -# Prefix for each line written to log file. % codes are in strftime(3) -# format. -log_timestamp = "%Y-%m-%d %H:%M:%S " - -# Space-separated list of elements we want to log. The elements which have -# a non-empty variable value are joined together to form a comma-separated -# string. -#login_log_format_elements = user=<%u> method=%m rip=%r lip=%l mpid=%e %c - -# Login log format. %s contains login_log_format_elements string, %$ contains -# the data we want to log. -#login_log_format = %$: %s - -# Log prefix for mail processes. See doc/wiki/Variables.txt for list of -# possible variables you can use. -#mail_log_prefix = "%s(%u): " - -# Format to use for logging mail deliveries. See doc/wiki/Variables.txt for -# list of all variables you can use. Some of the common ones include: -# %$ - Delivery status message (e.g. "saved to INBOX") -# %m - Message-ID -# %s - Subject -# %f - From address -# %p - Physical size -# %w - Virtual size -#deliver_log_format = msgid=%m: %$ diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-mail.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-mail.conf index a781402..d74b026 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/10-mail.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/10-mail.conf @@ -118,7 +118,7 @@ mail_gid = vmail # Group to enable temporarily for privileged operations. Currently this is # used only with INBOX when either its initial creation or dotlocking fails. # Typically this is set to "mail" to give access to /var/mail. -#mail_privileged_group = +mail_privileged_group = # Grant access to these supplementary groups for mail processes. Typically # these are used to set up access to shared mailboxes. Note that it may be @@ -172,7 +172,10 @@ mail_server_admin = mailto:postmaster@fripost.org # methods. NFS users: flock doesn't work, remember to change mmap_disable. #lock_method = fcntl -# Directory in which LDA/LMTP temporarily stores incoming mails >128 kB. +# Directory where mails can be temporarily stored. Usually it's used only for +# mails larger than >= 128 kB. It's used by various parts of Dovecot, for +# example LDA/LMTP while delivering large mails or zlib plugin for keeping +# uncompressed mails. #mail_temp_dir = /tmp # Valid UID range for users, defaults to 500 and above. This is mostly @@ -219,7 +222,7 @@ first_valid_uid = 1 # Space separated list of plugins to load for all services. Plugins specific to # IMAP, LDA, etc. are added to this list in their own .conf files. -mail_plugins = quota stats virtual zlib +mail_plugins = quota virtual zlib ## ## Mailbox handling optimizations @@ -227,7 +230,16 @@ mail_plugins = quota stats virtual zlib # Mailbox list indexes can be used to optimize IMAP STATUS commands. They are # also required for IMAP NOTIFY extension to be enabled. -mailbox_list_index = yes +#mailbox_list_index = yes + +# Trust mailbox list index to be up-to-date. This reduces disk I/O at the cost +# of potentially returning out-of-date results after e.g. server crashes. +# The results will be automatically fixed once the folders are opened. +#mailbox_list_index_very_dirty_syncs = yes + +# Should INBOX be kept up-to-date in the mailbox list index? By default it's +# not, because most of the mailbox accesses will open INBOX anyway. +#mailbox_list_index_include_inbox = no # The minimum number of mails in a mailbox before updates are done to cache # file. This allows optimizing Dovecot's behavior to do less disk writes at @@ -255,6 +267,19 @@ mailbox_list_index = yes # These should exist only after Dovecot dies in the middle of saving mails. #mail_temp_scan_interval = 1w +# How many slow mail accesses sorting can perform before it returns failure. +# With IMAP the reply is: NO [LIMIT] Requested sort would have taken too long. +# The untagged SORT reply is still returned, but it's likely not correct. +#mail_sort_max_read_count = 0 + +protocol !indexer-worker { + # If folder vsize calculation requires opening more than this many mails from + # disk (i.e. mail sizes aren't in cache already), return failure and finish + # the calculation via indexer process. Disabled by default. This setting must + # be 0 for indexer-worker processes. + #mail_vsize_bg_after_count = 0 +} + ## ## Maildir-specific settings ## @@ -354,7 +379,7 @@ mailbox_list_index = yes ## # Maximum dbox file size until it's rotated. -#mdbox_rotate_size = 2M +#mdbox_rotate_size = 10M # Maximum dbox file age until it's rotated. Typically in days. Day begins # from midnight, so 1d = today, 2d = yesterday, etc. 0 = check disabled. @@ -390,3 +415,13 @@ mail_attachment_fs = sis-queue /home/mail/attachments/queue:posix # variables: %{md4}, %{md5}, %{sha1}, %{sha256}, %{sha512}, %{size}. # Variables can be truncated, e.g. %{sha256:80} returns only first 80 bits mail_attachment_hash = %{sha256} + +# Settings to control adding $HasAttachment or $HasNoAttachment keywords. +# By default, all MIME parts with Content-Disposition=attachment, or inlines +# with filename parameter are consired attachments. +# add-flags-on-save - Add the keywords when saving new mails. +# content-type=type or !type - Include/exclude content type. Excluding will +# never consider the matched MIME part as attachment. Including will only +# negate an exclusion (e.g. content-type=!foo/* content-type=foo/bar). +# exclude-inlined - Exclude any Content-Disposition=inline MIME part. +#mail_attachment_detection_options = diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf index 250eec5..adeb879 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf @@ -27,10 +27,11 @@ ssl_key = </etc/dovecot/ssl/imap.fripost.org.key #ssl_require_crl = yes # Directory and/or file for trusted SSL CA certificates. These are used only -# when Dovecot needs to act as an SSL client (e.g. imapc backend). The -# directory is usually /etc/ssl/certs in Debian-based systems and the file is -# /etc/pki/tls/cert.pem in RedHat-based systems. -#ssl_client_ca_dir = +# when Dovecot needs to act as an SSL client (e.g. imapc backend or +# submission service). The directory is usually /etc/ssl/certs in +# Debian-based systems and the file is /etc/pki/tls/cert.pem in +# RedHat-based systems. +ssl_client_ca_dir = /etc/ssl/certs #ssl_client_ca_file = # Request client to send a certificate. If you also want to require it, set @@ -42,14 +43,23 @@ ssl_key = </etc/dovecot/ssl/imap.fripost.org.key # auth_ssl_username_from_cert=yes. #ssl_cert_username_field = commonName -# DH parameters length to use. -ssl_dh_parameters_length = 2048 +# SSL DH parameters +# Generate new params with `openssl dhparam -out /etc/dovecot/dh.pem 4096` +# Or migrate from old ssl-parameters.dat file with the command dovecot +# gives on startup when ssl_dh is unset. +ssl_dh = </etc/ssl/dhparams.pem -# SSL protocols to use -#ssl_protocols = !SSLv3 +# Minimum SSL protocol version to use. Potentially recognized values are SSLv3, +# TLSv1, TLSv1.1, and TLSv1.2, depending on the OpenSSL version used. +ssl_min_protocol = TLSv1.2 # SSL ciphers to use -ssl_cipher_list = HIGH:!aNULL:!eNULL:!3DES:!MD5:@STRENGTH +ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 + +# Colon separated list of elliptic curves to use. Empty value (the default) +# means use the defaults from the SSL library. P-521:P-384:P-256 would be an +# example of a valid value. +#ssl_curve_list = # Prefer the server's order of ciphers over client's. #ssl_prefer_server_ciphers = no @@ -58,5 +68,6 @@ ssl_cipher_list = HIGH:!aNULL:!eNULL:!3DES:!MD5:@STRENGTH #ssl_crypto_device = # SSL extra options. Currently supported options are: -# no_compression - Disable compression. -ssl_options = no_compression +# compression - Enable compression. +# no_ticket - Disable SSL session tickets. +#ssl_options = diff --git a/roles/IMAP/files/etc/dovecot/conf.d/15-lda.conf b/roles/IMAP/files/etc/dovecot/conf.d/15-lda.conf index 2a7bd27..4bfd8a5 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/15-lda.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/15-lda.conf @@ -3,7 +3,7 @@ ## # Address to use when sending rejection mails. -# Default is postmaster@<your domain>. %d expands to recipient domain. +# Default is postmaster@%d. %d expands to recipient domain. #postmaster_address = # Hostname to use in various parts of sent mails (e.g. in Message-Id) and diff --git a/roles/IMAP/files/etc/dovecot/conf.d/20-imap.conf b/roles/IMAP/files/etc/dovecot/conf.d/20-imap.conf index 3ddedce..de1fbbb 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/20-imap.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/20-imap.conf @@ -21,10 +21,17 @@ imap_hibernate_timeout = 15s # %{fetch_body_count} - Number of mails with mail body data sent to client # %{fetch_body_bytes} - Number of bytes with mail body data sent to client # %{deleted} - Number of mails where client added \Deleted flag -# %{expunged} - Number of mails that client expunged +# %{expunged} - Number of mails that client expunged, which does not +# include automatically expunged mails +# %{autoexpunged} - Number of mails that were automatically expunged after +# client disconnected # %{trashed} - Number of mails that client copied/moved to the # special_use=\Trash mailbox. -#imap_logout_format = in=%i out=%o +# %{appended} - Number of mails saved during the session +#imap_logout_format = in=%i out=%o deleted=%{deleted} expunged=%{expunged} \ +# trashed=%{trashed} hdr_count=%{fetch_hdr_count} \ +# hdr_bytes=%{fetch_hdr_bytes} body_count=%{fetch_body_count} \ +# body_bytes=%{fetch_body_bytes} # Override the IMAP CAPABILITY response. If the value begins with '+', # add the given capabilities on top of the defaults (e.g. +XFOO XBAR). @@ -65,9 +72,25 @@ imap_hibernate_timeout = 15s # Host allowed in URLAUTH URLs sent by client. "*" allows all. #imap_urlauth_host = +# Enable IMAP LITERAL- extension (replaces LITERAL+) +#imap_literal_minus = no + +# What happens when FETCH fails due to some internal error: +# disconnect-immediately: +# The FETCH is aborted immediately and the IMAP client is disconnected. +# disconnect-after: +# The FETCH runs for all the requested mails returning as much data as +# possible. The client is finally disconnected without a tagged reply. +# no-after: +# Same as disconnect-after, but tagged NO reply is sent instead of +# disconnecting the client. If the client attempts to FETCH the same failed +# mail more than once, the client is disconnected. This is to avoid clients +# from going into infinite loops trying to FETCH a broken mail. +#imap_fetch_failure = disconnect-immediately + protocol imap { # Space separated list of plugins to load (default is global mail_plugins). - mail_plugins = $mail_plugins imap_stats imap_zlib + mail_plugins = $mail_plugins imap_zlib # Maximum number of IMAP connections allowed for a user from each IP address. # NOTE: The username is compared case-sensitively. diff --git a/roles/IMAP/files/etc/dovecot/conf.d/90-plugin.conf b/roles/IMAP/files/etc/dovecot/conf.d/90-plugin.conf index 9583b6d..52a81ca 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/90-plugin.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/90-plugin.conf @@ -23,11 +23,6 @@ plugin { quota = count:User quota quota_vsizes = yes - # how often to session statistics - stats_refresh = 30 secs - # track per-IMAP command statistics - stats_track_cmds = yes - zlib_save = gz zlib_save_level = 6 } diff --git a/roles/IMAP/files/etc/dovecot/dovecot-dict-auth.conf.ext b/roles/IMAP/files/etc/dovecot/dovecot-dict-auth.conf.ext index ecd7134..a054ffe 100644 --- a/roles/IMAP/files/etc/dovecot/dovecot-dict-auth.conf.ext +++ b/roles/IMAP/files/etc/dovecot/dovecot-dict-auth.conf.ext @@ -2,7 +2,7 @@ # conf.d/auth-dict.conf.ext # Dictionary URI -uri = proxy:/var/run/dovecot/auth-proxy: +uri = proxy:/run/dovecot/auth-proxy: # Username iteration prefix. Keys under this are assumed to contain usernames. iterate_prefix = userdb/ diff --git a/roles/IMAP/files/etc/dovecot/dovecot-ldap.conf.ext b/roles/IMAP/files/etc/dovecot/dovecot-ldap.conf.ext index 1b97a0e..a455616 100644 --- a/roles/IMAP/files/etc/dovecot/dovecot-ldap.conf.ext +++ b/roles/IMAP/files/etc/dovecot/dovecot-ldap.conf.ext @@ -130,7 +130,7 @@ pass_attrs = #pass_attrs = uid=user,userPassword=password,\ # homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid -# Filter for password lookups (ignored for auth binds) +# Filter for password lookups pass_filter = (&(objectClass=FripostVirtualUser)(fvl=%n)(fripostIsStatusActive=TRUE)) # Attributes and filter to get a list of all users @@ -140,3 +140,12 @@ pass_filter = (&(objectClass=FripostVirtualUser)(fvl=%n)(fripostIsStatusActive=T # Default password scheme. "{scheme}" before password overrides this. # List of supported schemes is in: http://wiki2.dovecot.org/Authentication #default_pass_scheme = CRYPT + +# By default all LDAP lookups are performed by the auth master process. +# If blocking=yes, auth worker processes are used to perform the lookups. +# Each auth worker process creates its own LDAP connection so this can +# increase parallelism. With blocking=no the auth master process can +# keep 8 requests pipelined for the LDAP connection, while with blocking=yes +# each connection has a maximum of 1 request running. For small systems the +# blocking=no is sufficient and uses less resources. +#blocking = no diff --git a/roles/IMAP/files/etc/systemd/system/dovecot-auth-proxy.service b/roles/IMAP/files/etc/systemd/system/dovecot-auth-proxy.service index d20f9c2..3ac0b31 100644 --- a/roles/IMAP/files/etc/systemd/system/dovecot-auth-proxy.service +++ b/roles/IMAP/files/etc/systemd/system/dovecot-auth-proxy.service @@ -4,8 +4,7 @@ After=dovecot.target Requires=dovecot-auth-proxy.socket [Service] -User=vmail -Group=vmail +User=_dovecot-auth-proxy StandardInput=null SyslogFacility=mail ExecStart=/usr/local/bin/dovecot-auth-proxy.pl @@ -13,14 +12,13 @@ ExecStart=/usr/local/bin/dovecot-auth-proxy.pl # Hardening NoNewPrivileges=yes PrivateDevices=yes -ProtectSystem=strict -ProtectHome=read-only -PrivateDevices=yes PrivateNetwork=yes +ProtectHome=yes +ProtectSystem=strict ProtectControlGroups=yes ProtectKernelModules=yes ProtectKernelTunables=yes -RestrictAddressFamilies= +RestrictAddressFamilies=AF_UNIX [Install] WantedBy=multi-user.target diff --git a/roles/IMAP/files/usr/local/bin/dovecot-auth-proxy.pl b/roles/IMAP/files/usr/local/bin/dovecot-auth-proxy.pl index 5b2c74e..39d3762 100755 --- a/roles/IMAP/files/usr/local/bin/dovecot-auth-proxy.pl +++ b/roles/IMAP/files/usr/local/bin/dovecot-auth-proxy.pl @@ -1,8 +1,8 @@ -#!/usr/bin/perl +#!/usr/bin/perl -T #---------------------------------------------------------------------- # Dovecot userdb lookup proxy table for user iteration -# Copyright © 2017 Guilhem Moulin <guilhem@fripost.org> +# Copyright © 2017,2020 Guilhem Moulin <guilhem@fripost.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,14 +21,22 @@ use warnings; use strict; -use Errno 'EINTR'; +use Errno qw/EINTR/; +use Net::LDAPI; +use Net::LDAP::Constant qw/LDAP_CONTROL_PAGED LDAP_SUCCESS/; +use Net::LDAP::Control::Paged (); +use Net::LDAP::Util qw/ldap_explode_dn/; +use Authen::SASL; + +my $BASE = "ou=virtual,dc=fripost,dc=org"; # clean up PATH $ENV{PATH} = join ':', qw{/usr/bin /bin}; delete @ENV{qw/IFS CDPATH ENV BASH_ENV/}; -# number of pre-forked servers +# number of pre-forked servers and maximum requests per worker my $nProc = 1; +my $maxRequests = 1; sub server(); # fdopen(3) the file descriptor FD @@ -37,12 +45,6 @@ die "This service must be socket-activated.\n" and defined $ENV{LISTEN_FDS} and $ENV{LISTEN_FDS} == 1; open my $S, '+<&=', 3 or die "fdopen: $!"; -do { - my $dir = (getpwnam('vmail'))[7] // die "No such user: vmail"; - $dir .= '/virtual'; - chdir($dir) or die "chdir($dir): $!"; -}; - my @CHILDREN; for (my $i = 0; $i < $nProc-1; $i++) { my $pid = fork() // die "fork: $!"; @@ -61,7 +63,7 @@ exit $?; ############################################################################# sub server() { - for (my $n = 0; $n < 1; $n++) { + for (my $n = 0; $n < $maxRequests; $n++) { accept(my $conn, $S) or do { next if $! == EINTR; die "accept: $!"; @@ -74,7 +76,7 @@ sub server() { next; } # <major-version> <minor-version> <value type> - unless ($1 == 2 and $2 == 1 and $3 == 0) { + unless ($1 == 2 and $2 == 2 and $3 == 0) { warn "Unsupported protocol version $1.$2 (or value type $3)\n"; close $conn or warn "Can't close: $!"; next; @@ -94,10 +96,20 @@ sub server() { sub fail($;$) { my ($fh, $msg) = @_; $fh->printflush("F\n"); - warn "$msg\n" if defined $msg; + print STDERR $msg, "\n" if defined $msg; } -# list all users, even the inactive ones +sub dn2user($) { + my $dn = shift; + $dn = ldap_explode_dn($dn, casefold => "lower"); + if (defined $dn and $#$dn == 4 + and defined (my $l = $dn->[0]->{fvl}) + and defined (my $d = $dn->[1]->{fvd})) { + return $l ."@". $d; + } +} + +# list all users (even the inactive ones) sub iterate($$$$) { my ($fh, $flags, $max_rows, $prefix) = @_; unless ($flags == 0) { @@ -105,27 +117,55 @@ sub iterate($$$$) { return; } - opendir my $dh, '.' or do { - fail($fh => "opendir: $!"); - return; - }; - my $count = 0; - while (defined (my $d = readdir $dh)) { - next if $d eq '.' or $d eq '..'; - opendir my $dh, $d or do { - fail($fh => "opendir: $!"); - return; - }; - while (defined (my $l = readdir $dh) and ($max_rows <= 0 or $count < $max_rows)) { - next if $l eq '.' or $l eq '..'; - my $user = $l.'@'.$d; - next unless $user =~ /\A[a-zA-Z0-9\.\-_@]+\z/; # skip invalid user names + my $ldap = Net::LDAPI::->new(); + $ldap->bind( undef, sasl => Authen::SASL::->new(mechanism => "EXTERNAL") ) + or do { fail($fh => "Error: Couldn't bind"); return; }; + my $page = Net::LDAP::Control::Paged::->new(size => 100); + + my $callback = sub($$) { + my ($mesg, $entry) = @_; + return unless defined $entry; + + my $dn = $entry->dn(); + if (defined (my $user = dn2user($dn))) { $fh->printf("O%s%s\t\n", $prefix, $user); - $count++; + } else { + print STDERR "Couldn't extract username from dn: ", $dn, "\n"; } - closedir $dh or warn "closedir: $!"; + $mesg->pop_entry; + }; + + my @search_args = ( + base => $BASE, + , scope => "children" + , deref => "never" + , filter => "(objectClass=FripostVirtualUser)" + , sizelimit => $max_rows + , control => [$page] + , callback => $callback + , attrs => ["1.1"] + ); + + my $cookie; + while (1) { + my $mesg = $ldap->search(@search_args); + last unless $mesg->code == LDAP_SUCCESS; + + my ($resp) = $mesg->control(LDAP_CONTROL_PAGED) or last; + $cookie = $resp->cookie(); + goto SEARCH_DONE unless defined $cookie and length($cookie) > 0; + + $page->cookie($cookie); + } + + if (defined $cookie and length($cookie) > 0) { + fail($fh => "Abnormal exit from LDAP search, aborting"); + $page->cookie($cookie); + $page->size(0); + $ldap->search(@search_args); } - closedir $dh or warn "closedir: $!"; + SEARCH_DONE: + $ldap->unbind(); $fh->printflush("\n"); } diff --git a/roles/IMAP/files/usr/local/bin/list-users.pl b/roles/IMAP/files/usr/local/bin/list-users.pl deleted file mode 100755 index 1bcab35..0000000 --- a/roles/IMAP/files/usr/local/bin/list-users.pl +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/perl - -# Copyright © 2017 Guilhem Moulin <guilhem@fripost.org> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -use warnings; -use strict; -use Net::LDAPI; -use Net::LDAP::Util qw/ldap_explode_dn escape_dn_value/; -use Authen::SASL; - -my $BASE = 'ou=virtual,dc=fripost,dc=org'; - -my $LDAP = Net::LDAPI::->new(); -$LDAP->bind( undef, sasl => Authen::SASL::->new(mechanism => 'EXTERNAL') ) - or die "Error: Couldn't bind"; - -my $mesg = $LDAP->search( base => $BASE, scope => 'children', deref => 'never' - , filter => '(objectClass=FripostVirtualUser)' - , attrs => ['1.1'] - ); -die $mesg->error if $mesg->code; - -while (defined (my $entry = $mesg->pop_entry())) { - my $dn = $entry->dn() // next; - $dn = ldap_explode_dn($dn, casefold => 'lower'); - next unless defined $dn and $#$dn == 4; - my $l = $dn->[0]->{fvl} // next; - my $d = $dn->[1]->{fvd} // next; - printf "%s@%s\n", $l, $d; -} - -$LDAP->unbind; diff --git a/roles/IMAP/tasks/imap.yml b/roles/IMAP/tasks/imap.yml index 231c759..4a157af 100644 --- a/roles/IMAP/tasks/imap.yml +++ b/roles/IMAP/tasks/imap.yml @@ -18,6 +18,13 @@ password=! state=present +- name: Install Net::LDAP and Authen::SASL + apt: pkg={{ packages }} + vars: + packages: + - libnet-ldap-perl + - libauthen-sasl-perl + - name: Copy dovecot auth proxy copy: src=usr/local/bin/dovecot-auth-proxy.pl dest=/usr/local/bin/dovecot-auth-proxy.pl @@ -30,6 +37,15 @@ tags: - sysctl +- name: Create '_dovecot-auth-proxy' user + user: name=_dovecot-auth-proxy system=yes + group=nogroup + createhome=no + home=/nonexistent + shell=/usr/sbin/nologin + password=! + state=present + - name: Copy dovecot auth proxy systemd unit files copy: src=etc/systemd/system/{{ item }} dest=/etc/systemd/system/{{ item }} @@ -123,7 +139,6 @@ register: r1 with_items: - conf.d/10-auth.conf - - conf.d/10-logging.conf - conf.d/10-mail.conf - conf.d/10-ssl.conf - conf.d/15-mailboxes.conf diff --git a/roles/IMAP/tasks/mda.yml b/roles/IMAP/tasks/mda.yml index f705fe7..0e8690d 100644 --- a/roles/IMAP/tasks/mda.yml +++ b/roles/IMAP/tasks/mda.yml @@ -3,7 +3,7 @@ vars: packages: - postfix - - postfix-ldap + - postfix-lmdb - name: Configure Postfix template: src=etc/postfix/{{ item }}.j2 diff --git a/roles/IMAP/tasks/spam.yml b/roles/IMAP/tasks/spam.yml index c275b55..d70ccc9 100644 --- a/roles/IMAP/tasks/spam.yml +++ b/roles/IMAP/tasks/spam.yml @@ -63,8 +63,8 @@ - name: Create a 'amavis' SQL user # This *must* be the user we run spamd as # See https://svn.apache.org/repos/asf/spamassassin/trunk/sql/README.bayes - mysql_user2: > - name=amavis password= auth_plugin=auth_socket + mysql_user: > + name=amavis password= plugin=auth_socket priv="spamassassin.awl: SELECT,INSERT,UPDATE,DELETE /spamassassin.bayes_seen: SELECT,INSERT, DELETE /spamassassin.bayes_token: SELECT,INSERT,UPDATE,DELETE diff --git a/roles/IMAP/templates/etc/dovecot/conf.d/10-master.conf.j2 b/roles/IMAP/templates/etc/dovecot/conf.d/10-master.conf.j2 index 8eef8a1..d61c11b 100644 --- a/roles/IMAP/templates/etc/dovecot/conf.d/10-master.conf.j2 +++ b/roles/IMAP/templates/etc/dovecot/conf.d/10-master.conf.j2 @@ -4,7 +4,7 @@ # Default VSZ (virtual memory size) limit for service processes. This is mainly # intended to catch and kill processes that leak memory before they eat up # everything. -default_vsz_limit = 512M +default_vsz_limit = 1024M # Login user is internally used by login processes. This is the most untrusted # user in Dovecot system. It shouldn't have access to anything at all. @@ -53,6 +53,19 @@ service pop3-login { } } +service stats { + unix_listener stats-writer { + user = vmail + mode = 0600 + } +} + +service submission-login { + inet_listener submission { + port = 0 + } +} + service lmtp { user = vmail @@ -88,6 +101,8 @@ service imap { service imap-hibernate { unix_listener imap-hibernate { + # Match user running imap processes, cf. + # https://dovecot.org/pipermail/dovecot/2015-August/101783.html user = vmail mode = 0600 } @@ -98,6 +113,11 @@ service pop3 { #process_limit = 1024 } +service submission { + # Max. number of SMTP Submission processes (connections) + #process_limit = 1024 +} + service auth { # auth_socket_path points to this userdb socket by default. It's typically # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have @@ -120,6 +140,7 @@ service auth { # Postfix smtp-auth unix_listener /var/spool/postfix-{{ postfix_instance.MSA.name }}/private/dovecot-auth { user = postfix + group = postfix mode = 0600 } @@ -143,10 +164,3 @@ service dict { #group = } } - -service stats { - fifo_listener stats-mail { - user = vmail - mode = 0600 - } -} diff --git a/roles/IMAP/templates/etc/dovecot/conf.d/15-lda.conf b/roles/IMAP/templates/etc/dovecot/conf.d/15-lda.conf deleted file mode 100644 index e69de29..0000000 --- a/roles/IMAP/templates/etc/dovecot/conf.d/15-lda.conf +++ /dev/null diff --git a/roles/IMAP/templates/etc/postfix/main.cf.j2 b/roles/IMAP/templates/etc/postfix/main.cf.j2 index 2105d29..64a2a40 100644 --- a/roles/IMAP/templates/etc/postfix/main.cf.j2 +++ b/roles/IMAP/templates/etc/postfix/main.cf.j2 @@ -21,7 +21,7 @@ append_dot_mydomain = no mynetworks = 127.0.0.0/8, [::1]/128 {%- if groups.all | length > 1 -%} {%- for mx in groups.MX | sort -%} - , {{ ipsec[ hostvars[mx].inventory_hostname_short ] | ipaddr }} + , {{ ipsec[ hostvars[mx].inventory_hostname_short ] | ansible.utils.ipaddr }} {%- endfor %} {% endif %} |