LMTP Post login script for acl_groups

lists at mlserv.org
Wed, 28 Aug 2019 15:13:30 -0000

Further information below.

> Am 28.08.2019 um 14:52 schrieb R.N.S. via dovecot <dovecot at
dovecot.org>:
>
> Hi,
>
> I use a post login script for imap, to fetch acl groups from LDAP. Because
Dovecot can only deal with a single value, which must be a comma seperated list
of groups, I decided to use a post login script do deal with multi values in
LDAP:
>
> This looks like this in LDAP:
>
> rnsMSACLGroup: admin
> rnsMSACLGroup: automx
> rnsMSACLGroup: amavis
> rnsMSACLGroup: postfix
> rnsMSACLGroup: dovecot
> rnsMSACLGroup: rspamd
> rnsMSACLGroup: powerdns
> rnsMSACLGroup: sogo
> rnsMSACLGroup: zabbix
> rnsMSACLGroup: dane-users
> rnsMSACLGroup: gentoo
> rnsMSACLGroup: openbsd
>
> My post login script looks like this:
>
> ---------------------------------------------------------
> #!/bin/sh
>
> BINDDN='cn=dovecot-postlogin,ou=people,ou=it,dc=roessner-net,dc=de'
> BINDPWFILE='/etc/dovecot/ldap-postlogin.secret'
> BASE='ou=people,ou=it,dc=roessner-net,dc=de'
>
> LDAPSEARCH="/usr/bin/ldapsearch"
> AWK="/usr/bin/awk"
>
> test -x ${LDAPSEARCH} || exec "$@"
> test -x ${AWK} || exec "$@"
>
> ACL_GROUPS=$(
>       ${LDAPSEARCH} -LLL -ZZ -y ${BINDPWFILE} -xD ${BINDDN} -b ${BASE}
"(rnsMSDovecotUser=${USER})" rnsMSACLGroup | \
>       grep rnsMSACLGroup | \
>       ${AWK} -vORS=, '{ print $2 }' | \
>       sed 's/,$/\n/'
> )
> export ACL_GROUPS
> export USERDB_KEYS="${USERDB_KEYS} acl_groups"
>
> exec "$@"
> ---------------------------------------------------------
>
> This script is included in imap-postlogin executables and works for logged
in users.
>
> But it does not work for LMTP. LMTP itself seems not to have any
permissions to access the folders associated with these groups. I thought, I
simply could add the imap-postlogin block to lmtp-postlogin and that would work,
but it doesn't.
>
> So here is the question:
>
> What am I missing in Dovecot that LMTP can also have ACL_GROUPS like the
imap service?
>
> Here is my config (non-defaults):
>
> ---------------------------------------------------------
> doveconf -n
> # 2.3.7.1 (0152c8b10): /etc/dovecot/dovecot.conf
> # Pigeonhole version 0.5.7.1 (db5c74be)
> # OS: Linux 4.19.44-gentoo x86_64 Gentoo Base System release 2.6
> # Hostname: mx.roessner-net.de
> auth_cache_size = 64 M
> auth_master_user_separator = *
> auth_mechanisms = plain login
> auth_ssl_username_from_cert = yes
> auth_verbose = yes
> default_client_limit = 5000
> default_process_limit = 500
> default_vsz_limit = 512 M
> disable_plaintext_auth = no
> hostname = mail.roessner-net.de
> imap_client_workarounds = tb-extra-mailbox-sep tb-lsub-flags
> imap_max_line_length = 4 M
> lda_mailbox_autocreate = yes
> lda_mailbox_autosubscribe = yes
> lmtp_rcpt_check_quota = yes
> login_log_format_elements = user=<%u> method=%m rip=%r lip=%l mpid=%e
%c %k
> mail_access_groups = vmail
> mail_attachment_dir = /var/mail/virtual/copymail/attachments
> mail_gid = vmail
> mail_location = sdbox:~/sdbox
> mail_max_keyword_length = 4096
> mail_plugins = quota acl fts fts_lucene zlib mail_log notify
> mail_privileged_group = mail
> mail_save_crlf = yes
> mail_uid = vmail
> managesieve_notify_capability = mailto
> managesieve_sieve_capability = fileinto reject envelope encoded-character
vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy
include variables body enotify environment mailbox date index ihave duplicate
mime foreverypart extracttext vacation-seconds imapsieve vnd.dovecot.imapsieve
> mdbox_preallocate_space = yes
> mdbox_rotate_size = 128 M
> namespace {
> list = children
> location = sdbox:%%h/sdbox
> prefix = Shared/%%u/
> separator = /
> subscriptions = no
> type = shared
> }
> namespace {
> hidden = no
> list = children
> location = maildir:/var/mail/virtual/public:INDEXPVT=~/Maildir/public
> prefix = Public/
> separator = /
> subscriptions = no
> type = public
> }
> namespace inbox {
> inbox = yes
> location > mailbox Archive {
>   auto = subscribe
>   special_use = \Archive
> }
> mailbox "Deleted Messages" {
>   special_use = \Trash
> }
> mailbox Drafts {
>   auto = subscribe
>   special_use = \Drafts
> }
> mailbox Junk-E-Mail {
>   special_use = \Junk
> }
> mailbox Junk {
>   auto = subscribe
>   special_use = \Junk
> }
> mailbox Sent {
>   auto = subscribe
>   special_use = \Sent
> }
> mailbox "Sent Messages" {
>   special_use = \Sent
> }
> mailbox Trash {
>   auto = subscribe
>   special_use = \Trash
> }
> prefix > separator = /
> type = private
> }
> passdb {
> args = /etc/dovecot/master-users
> driver = passwd-file
> master = yes
> pass = yes
> }
> passdb {
> args = /etc/dovecot/dovecot-ldap.conf.ext
> driver = ldap
> }
> plugin {
> acl = vfile:/etc/dovecot/dovecot-acl:cache_secs=300
> acl_shared_dict = file:/var/mail/virtual/shared-mailboxes.db
> fts = lucene
> fts_autoindex = yes
> fts_lucene = whitespace_chars=@.
> imapsieve_mailbox1_before =
file:/etc/dovecot/sieve/rspamd.d/report-spam.sieve
> imapsieve_mailbox1_causes = COPY FLAG
> imapsieve_mailbox1_name = Junk
> imapsieve_mailbox2_before =
file:/etc/dovecot/sieve/rspamd.d/report-ham.sieve
> imapsieve_mailbox2_causes = COPY
> imapsieve_mailbox2_from = Junk
> imapsieve_mailbox2_name = *
> mail_log_events = delete undelete expunge copy save mailbox_create
mailbox_delete mailbox_rename
> mail_log_fields = box msgid
> quota = count:User quota
> quota_grace = 10%%
> quota_rule = *:storage=300M:messages=20000
> quota_rule2 = Trash:storage=+500M
> quota_rule3 = Sent:storage=+2G
> quota_rule4 = Archive:storage=+2G
> quota_status_nouser = DUNNO
> quota_status_overquota = 552 5.2.2 Mailbox is full
> quota_status_success = DUNNO
> quota_vsizes = yes
> quota_warning = storage=95%% quota-warning 95 %u
> quota_warning2 = storage=80%% quota-warning 80 %u
> quota_warning3 = -storage=100%% quota-warning below %u
> sieve = file:~/sieve;active=~/.dovecot.sieve
> sieve_after = /etc/dovecot/sieve/after
> sieve_before = /etc/dovecot/sieve/before
> sieve_extensions = +vacation-seconds
> sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
+vnd.dovecot.debug
> sieve_pipe_bin_dir = /usr/bin
> sieve_plugins = sieve_imapsieve sieve_extprograms
> sieve_vacation_default_period = 10d
> sieve_vacation_max_period = 30d
> sieve_vacation_min_period = 1h
> zlib_save = gz
> zlib_save_level = 6
> }
> protocols = imap pop3 lmtp submission sieve
> service auth-worker {
> extra_groups = ssl-cert
> unix_listener auth-worker {
>   mode = 0600
>   user = vmail
> }
> user = vmail
> }
> service auth {
> extra_groups = ssl-cert
> unix_listener /var/spool/postfix-submission/private/auth {
>   group = postfix
>   mode = 0666
>   user = postfix
> }
> unix_listener auth-userdb {
>   mode = 0600
>   user = vmail
> }
> user = vmail
> }
> service config {
> unix_listener config {
>   mode = 0600
>   user = vmail
> }
> }
> service dict {
> unix_listener dict {
>   mode = 0600
>   user = vmail
> }
> }
> service imap-login {
> inet_listener imap {
>   address = 127.0.0.1 134.255.226.248 ::1 2a05:bec0:28:1:134:255:226:248
> }
> inet_listener imaps {
>   port = 0
> }
> }
> service imap-postlogin {
> executable = script-login /usr/local/bin/dovecot-masteruser.sh
/usr/local/bin/dovecot-lastlogin.sh /usr/local/bin/dovecot-aclgroups.sh
> user = vmail
> }
> service imap {
> executable = imap imap-postlogin
> }
> service lmtp-postlogin {
> executable = script-login /usr/local/bin/dovecot-aclgroups.sh
> user = vmail
> }
> service lmtp {
> executable = lmtp lmtp-postlogin
> inet_listener lmtp {
>   address = 127.0.0.1
>   port = 24
> }
> unix_listener /var/spool/postfix/private/lmtp-dovecot {
>   group = postfix
>   mode = 0660
>   user = postfix
> }
> }
> service managesieve-login {
> inet_listener sieve {
>   address = 127.0.0.1 134.255.226.248 ::1 2a05:bec0:28:1:134:255:226:248
> }
> }
> service pop3-login {
> inet_listener pop3 {
>   address = 127.0.0.1 134.255.226.248 ::1 2a05:bec0:28:1:134:255:226:248
> }
> inet_listener pop3s {
>   port = 0
> }
> }
> service quota-status {
> client_limit = 1
> executable = quota-status -p postfix
> inet_listener {
>   address = 127.0.0.1
>   port = 12340
> }
> }
> service quota-warning {
> executable = script /usr/local/bin/quota-warning.sh
> extra_groups = mail
> unix_listener quota-warning {
>   group = vmail
>   mode = 0600
>   user = vmail
> }
> user = vmail
> }
> ssl_cert = </etc/ssl/mail.roessner-net.de/cert/fullchain.pem
> ssl_cipher_list =
ALL:!DH:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW
at STRENGTH
> ssl_client_cert = </etc/ssl/mail.roessner-net.de/cert/fullchain.pem
> ssl_client_key = # hidden, use -P to show it
> ssl_dh = # hidden, use -P to show it
> ssl_key = # hidden, use -P to show it
> ssl_min_protocol = TLSv1.2
> ssl_prefer_server_ciphers = yes
> submission_client_workarounds = whitespace-before-path
> submission_relay_host = mail.roessner-net.de
> submission_relay_port = 5870
> submission_relay_ssl = starttls
> submission_relay_trusted = yes
> userdb {
> args = /etc/dovecot/dovecot-ldap-userdb.conf.ext
> driver = ldap
> }
> verbose_proctitle = yes
> protocol lmtp {
> mail_plugins = quota acl fts fts_lucene zlib mail_log notify sieve
> }
> protocol lda {
> mail_plugins = quota acl fts fts_lucene zlib mail_log notify sieve
> }
> protocol imap {
> mail_max_userip_connections = 50
> mail_plugins = quota acl fts fts_lucene zlib mail_log notify imap_quota
imap_acl imap_zlib imap_sieve
> }
> protocol submission {
> login_greeting = ESMTP
> }
> ---------------------------------------------------------
>
> Thanks for any help in advance
>
> Christian

Here are some logs that show my problem:

Aug 28 14:42:42 mx dovecot: lmtp(lists at
srvint.net)<11222><O6twLsJ2Zl3WKwAAm3ipfw>: Error: sieve:
msgid=unspecified: failed to
 store into mailbox 'Public/Mailinglisten/Dovecot': Mailbox doesn't
exist: Public/Mailinglisten/Dovecot

LMTP can not put the message with sieve in the given mailbox.

That is alos seen with this:

---------------------------------------------------------
doveadm -Dv acl debug -u lists at srvint.net Public/Mailinglisten/Dovecot
2>&1
Debug: Loading modules from directory: /usr/lib64/dovecot
Debug: Module loaded: /usr/lib64/dovecot/lib01_acl_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib10_quota_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib15_notify_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib20_fts_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib20_mail_log_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib20_zlib_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/lib21_fts_lucene_plugin.so
Debug: Loading modules from directory: /usr/lib64/dovecot/doveadm
Debug: Module loaded: /usr/lib64/dovecot/doveadm/lib10_doveadm_acl_plugin.so
Debug: Skipping module doveadm_expire_plugin, because dlopen() failed:
/usr/lib64/dovecot/doveadm/lib10_doveadm_expire_plugin.so: undefined symbol:
expire_set_deinit (this is usually intentional, so just ignore this message)
Debug: Module loaded: /usr/lib64/dovecot/doveadm/lib10_doveadm_quota_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/doveadm/lib10_doveadm_sieve_plugin.so
Debug: Module loaded:
/usr/lib64/dovecot/doveadm/lib20_doveadm_fts_lucene_plugin.so
Debug: Module loaded: /usr/lib64/dovecot/doveadm/lib20_doveadm_fts_plugin.so
Debug: Skipping module doveadm_mail_crypt_plugin, because dlopen() failed:
/usr/lib64/dovecot/doveadm/libdoveadm_mail_crypt_plugin.so: undefined symbol:
mail_crypt_box_get_pvt_digests (this is usually intentional, so just ignore this
message)
doveadm(lists at srvint.net)<32375><>: Debug: auth-master: userdb
lookup(lists at srvint.net): Started userdb lookup
doveadm(lists at srvint.net)<32375><>: Debug: auth-master: conn
unix:/run/dovecot/auth-userdb: Connecting
doveadm(lists at srvint.net)<32375><>: Debug: auth-master: conn
unix:/run/dovecot/auth-userdb: Client connected (fd=10)
doveadm(lists at srvint.net)<32375><>: Debug: auth-master: userdb
lookup(lists at srvint.net): auth USER input: lists at srvint.net
quota_rule=*:storage=5242880 home=/var/mail/virtual/lists
mail_location=sdbox:~/sdbox
doveadm(lists at srvint.net)<32375><>: Debug: auth-master: userdb
lookup(lists at srvint.net): Finished userdb lookup (username=lists at
srvint.net quota_rule=*:storage=5242880 home=/var/mail/virtual/lists
mail_location=sdbox:~/sdbox)
doveadm(lists at srvint.net)<32375><>: Debug: Added userdb setting:
mail_location=sdbox:~/sdbox
doveadm(lists at srvint.net)<32375><>: Debug: Added userdb setting:
plugin/quota_rule=*:storage=5242880
doveadm(lists at srvint.net): Debug: Effective uid=5000, gid=5000,
home=/var/mail/virtual/lists
doveadm(lists at srvint.net): Debug: Quota root: name=User quota backend=count
argsdoveadm(lists at srvint.net): Debug: Quota rule: root=User quota mailbox=*
bytes=5368709120 messages=0
doveadm(lists at srvint.net): Debug: Quota rule: root=User quota mailbox=Trash
bytes=+524288000 messages=0
doveadm(lists at srvint.net): Debug: Quota rule: root=User quota mailbox=Sent
bytes=+2147483648 messages=0
doveadm(lists at srvint.net): Debug: Quota rule: root=User quota mailbox=Archive
bytes=+2147483648 messages=0
doveadm(lists at srvint.net): Debug: Quota warning: bytes=5100273664 (95%)
messages=0 reverse=no command=quota-warning 95 lists at srvint.net
doveadm(lists at srvint.net): Debug: Quota warning: bytes=4294967296 (80%)
messages=0 reverse=no command=quota-warning 80 lists at srvint.net
doveadm(lists at srvint.net): Debug: Quota warning: bytes=5368709120 (100%)
messages=0 reverse=yes command=quota-warning below lists at srvint.net
doveadm(lists at srvint.net): Debug: Quota grace: root=User quota
bytes=536870912 (10%)
doveadm(lists at srvint.net): Debug: Namespace inbox: type=private, prefix=,
sep=/, inbox=yes, hidden=no, list=yes, subscriptions=yes location=sdbox:~/sdbox
doveadm(lists at srvint.net): Debug: fs: root=/var/mail/virtual/lists/sdbox,
index=, indexpvt=, control=, inbox=, altdoveadm(lists at srvint.net): Debug:
acl: initializing backend with data:
vfile:/etc/dovecot/dovecot-acl:cache_secs=300
doveadm(lists at srvint.net): Debug: acl: acl username = lists at srvint.net
doveadm(lists at srvint.net): Debug: acl: owner = 1
doveadm(lists at srvint.net): Debug: acl vfile: Global ACL file:
/etc/dovecot/dovecot-acl
doveadm(lists at srvint.net): Debug: Namespace : type=shared, prefix=Shared/%u/,
sep=/, inbox=no, hidden=no, list=children, subscriptions=no
location=sdbox:%h/sdbox
doveadm(lists at srvint.net): Debug: shared: root=/run/dovecot, index=,
indexpvt=, control=, inbox=, altdoveadm(lists at srvint.net): Debug: fts:
Indexes disabled for namespace 'Shared/%u/'
doveadm(lists at srvint.net): Debug: acl: initializing backend with data:
vfile:/etc/dovecot/dovecot-acl:cache_secs=300
doveadm(lists at srvint.net): Debug: acl: acl username = lists at srvint.net
doveadm(lists at srvint.net): Debug: acl: owner = 0
doveadm(lists at srvint.net): Debug: acl vfile: Global ACL file:
/etc/dovecot/dovecot-acl
doveadm(lists at srvint.net): Debug: Namespace : type=public, prefix=Public/,
sep=/, inbox=no, hidden=no, list=children, subscriptions=no
location=maildir:/var/mail/virtual/public:INDEXPVT=~/Maildir/public
doveadm(lists at srvint.net): Debug: maildir++: root=/var/mail/virtual/public,
index=, indexpvt=/var/mail/virtual/lists/Maildir/public, control=, inbox=,
altdoveadm(lists at srvint.net): Debug: acl: initializing backend with data:
vfile:/etc/dovecot/dovecot-acl:cache_secs=300
doveadm(lists at srvint.net): Debug: acl: acl username = lists at srvint.net
doveadm(lists at srvint.net): Debug: acl: owner = 0
doveadm(lists at srvint.net): Debug: acl vfile: Global ACL file:
/etc/dovecot/dovecot-acl
doveadm(lists at srvint.net): Debug: quota: quota_over_flag check:
quota_over_script unset - skipping
doveadm(lists at srvint.net): Info: Mailbox 'Mailinglisten.Dovecot' is
in namespace 'Public/'
doveadm(lists at srvint.net): Info: Mailbox path:
/var/mail/virtual/public/.Mailinglisten.Dovecot
doveadm(lists at srvint.net): Info: Per-user private flags in mailbox: \Seen
doveadm(lists at srvint.net): Debug: acl vfile: reading file
/var/mail/virtual/public/.Mailinglisten.Dovecot/dovecot-acl
doveadm(lists at srvint.net): Info: User lists at srvint.net has no rights for
mailbox
doveadm(lists at srvint.net): Error: User lists at srvint.net is missing
'lookup' right
doveadm(lists at srvint.net): Info: Mailbox Public/Mailinglisten/Dovecot is NOT
visible in LIST
doveadm(lists at srvint.net): Debug: auth-master: conn
unix:/run/dovecot/auth-userdb: Disconnected: Connection closed (fd=10)
---------------------------------------------------------

But if I use telnet, I can see this:

---------------------------------------------------------
telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+
STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
a login someuser "***secret***"
a OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT
SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND
URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED
I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH
LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY LITERAL+ NOTIFY SPECIAL-USE
COMPRESS=DEFLATE QUOTA ACL RIGHTS=texk] Logged in
a LIST "" "*"
* LIST (\HasNoChildren \UnMarked \Junk) "/" Junk
* LIST (\HasNoChildren \UnMarked \Trash) "/" Trash
* LIST (\HasNoChildren \UnMarked \Sent) "/" Sent
* LIST (\HasNoChildren \UnMarked \Drafts) "/" Drafts
* LIST (\HasNoChildren \UnMarked \Archive) "/" Archive
* LIST (\Noselect \HasChildren) "/" Public
* LIST (\HasNoChildren) "/" Public/Mailinglisten/DANE-Users
* LIST (\HasNoChildren \UnMarked) "/" Public/Mailinglisten/Zabbix
* LIST (\HasNoChildren) "/" Public/Mailinglisten/SOGo
* LIST (\HasNoChildren) "/" Public/Mailinglisten/Rspamd
* LIST (\HasNoChildren) "/" Public/Mailinglisten/PowerDNS
* LIST (\HasNoChildren) "/" Public/Mailinglisten/Postfix
* LIST (\HasNoChildren) "/" Public/Mailinglisten/Dovecot
* LIST (\HasNoChildren \UnMarked) "/" Public/Mailinglisten/Automx
* LIST (\HasNoChildren) "/" Public/Mailinglisten/Amavis
* LIST (\HasChildren \UnMarked) "/" Public/Mailinglisten/Gentoo
* LIST (\HasNoChildren \UnMarked) "/" Public/Mailinglisten/Gentoo/user
* LIST (\HasNoChildren \UnMarked) "/"
Public/Mailinglisten/Gentoo/bugzilla
* LIST (\HasNoChildren) "/" Public/Mailinglisten/Gentoo/announce
* LIST (\HasChildren \UnMarked) "/" Public/Mailinglisten/OpenBSD
* LIST (\HasNoChildren) "/" Public/Mailinglisten/OpenBSD/misc
* LIST (\HasNoChildren \UnMarked) "/"
Public/Mailinglisten/OpenBSD/announce
* LIST (\HasNoChildren) "/" Public/Postfix-Meldungen
* LIST (\HasNoChildren) "/" INBOX
a OK List completed (0.137 + 0.000 + 0.137 secs).
a SELECT "Public/Mailinglisten/Dovecot"
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft $NotJunk)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $NotJunk \*)]
Flags permitted.
* 236 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1549006882] UIDs valid
* OK [UIDNEXT 2280] Predicted next UID
* OK [HIGHESTMODSEQ 2522] Highest
a OK [READ-WRITE] Select completed (0.013 + 0.000 + 0.012 secs).
a LOGOUT
* BYE Logging out
a OK Logout completed (0.001 + 0.000 secs).
Connection closed by foreign host.
---------------------------------------------------------

That tells me that the post login script works. At least for IMAP. But it seems
it is not working, if mail comes form Postfix->LMTP->Dovecot.

So what can I do?

Thanks

Christian