"sieve: failed to store into mailbox 'Junk': Read-only mbox" over root_squashed NFS, lmtp : euid/egid set and access() don't mix together for me
Hi,
I try to migrate an old fashioned mailsystem to Debian 9.7 / dovecot 2.2.7. I "have" to cope with mbox for now. I try to get rid of Sun OS 5.9 sendmail before mbox to mdbox migration (I'm fine if you laugh loudly ^^). Intended setup : 2 VM with exim (smtp in, smtp out roughly), 3 VM with dovecot (mbox, maildir, testbed), 1 VM with IMAP proxy and LMTP proxy.
doveconf -n is at end of this mail. My test case is :
root@wagram:~# swaks --to tstifi04 --server imap --protocol lmtp --header-X-Spam-Status yes root@wagram:~# (imap VM LMTP proxies to telegraphe5 VM in this test)
mbox folders are in users homedir, no generic "vmail" unix account. Real posixAccounts in LDAP, NFS root_squashed.
sieve "fileinto "Junk" call goes wrong :
Feb 6 17:56:03 telegraphe5 dovecot: lmtp(tstifi04): Error: PytSHqIRW1x2dgAA+Fldtw: sieve: msgid=unspecified: failed to store into mailbox 'Junk': Read-only mbox straced : https://pastebin.com/A53hDYnS
I may miss some configuration options... but I get stuck. I get to IRC and it seems that there is no simple things to circumvent. I tried to read some code path too.
https://wiki.dovecot.org/LMTP states :
Security
Unfortunately LMTP process currently needs to run as root, and only temporarily drop privileges to users. Otherwise it couldn't handle mail deliveries to more than a single user with different UID. If you're using only a single global UID/GID, you can improve security by running lmtp processes as that user: service lmtp { user = vmail }
lmtp run as root, drop temporarily privileges. The point, IHMO, is lmtp calls sieve code paths, that call some mbox saving function, that calls libc/syscall access(). And this explicitly not consider effective uid/gid.
From strace (more in pastebin) :
[pid 30326] geteuid() = 0 [pid 30326] setresuid(-1, 20609, -1) = 0 [pid 30326] geteuid() = 20609 [pid 30326] access("/home/tstifi04/mail-imap/Junk", R_OK|W_OK) = -1 EACCES (Permission denied)
From man access
The check is done using the calling process's real UID and GID, rather than the effective IDs as is done when actually attempting an operation (e.g., open(2)) on the file. Similarly, for the root user, the check uses the set of permitted capabilities rather than the set of effective capabilities; and for non-root users, the check uses an empty set of capa- bilities. I think that the process has effectively sufficient permissions to write into the root_squashed file, and infortunately access() check another thing.
In dovecot sources, src/lib/eacces-error.c is aware of those "problems" with access(), but I think that mbox and maybe other storage backends don't use this for main codepath (like save a mail), but "only" for smart log messages in some cases.
I may gone wrong while seeking about it. Do you see a configuration that can use root squashed mboxes and LMTP ?
Should test_access() variant could be used as access() replacement ? There is eaccess() and euidaccess() too but may be not portable enough (_GNU_SOURCE only).
Regards, Ludovic
telegraphe5:/dev/shm# mount | grep tstifi04 cifs1:/homeeleves/tstifi/tstifi04 on /home/tstifi04 type nfs (rw,nosuid,nodev,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=172.16.2.29,mountvers=3,mountport=635,mountproto=udp,local_lock=none,addr=172.16.2.29)
telegraphe5:/dev/shm# dovecot -n # 2.2.27 (c0f36b0): /etc/dovecot/dovecot.conf # Pigeonhole version 0.4.16 (fed8554) # OS: Linux 4.9.0-8-amd64 x86_64 Debian 9.7 auth_debug = yes auth_verbose = yes default_client_limit = 10240 default_process_limit = 2048 lda_mailbox_autocreate = yes lda_mailbox_autosubscribe = yes mail_debug = yes mail_fsync = always mail_location = mbox:~/mail-imap:INBOX=/var/mail/mailbox/%u:INDEX=/var/dovecot-indexes/%u mail_nfs_storage = yes mail_plugins = quota 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 mbox_write_locks = fcntl mmap_disable = yes namespace inbox { inbox = yes location = mailbox Drafts { special_use = \Drafts } mailbox Junk { special_use = \Junk } mailbox Sent { special_use = \Sent } mailbox "Sent Messages" { special_use = \Sent } mailbox Trash { special_use = \Trash } prefix = } passdb { args = /etc/dovecot/dovecot-ldap.conf.ext driver = ldap } plugin { mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename mail_log_fields = uid box msgid size quota = count:Quota mail global quota_rule = *:storage=100M quota_rule2 = Trash:storage=+100M quota_vsizes = yes quota_warning = storage=95%% quota-warning 95 %u quota_warning2 = storage=80%% quota-warning 80 %u sieve = file:/var/mail/mailconf/%1u/%u/sieve;active=/var/mail/mailconf/%1u/%u/.dovecot.sieve sieve_after = /var/mail/mailconf/global/sieve/after.d/ sieve_before = /var/mail/mailconf/global/sieve/before.d/ sieve_global = /var/mail/mailconf/global/sieve sieve_vacation_dont_check_recipient = yes } protocols = " imap lmtp sieve sieve" service anvil { unix_listener anvil-auth-penalty { mode = 00 } } service imap-login { inet_listener imap { port = 0 } } service lmtp { inet_listener lmtp { port = 24 } } service managesieve { process_limit = 16 } service quota-warning { executable = script /usr/local/bin/quota-warning.sh unix_listener quota-warning { mode = 0666 } user = root } ssl = required ssl_cert = </etc/ssl/local_certs/telegraphe5_cert.pem ssl_key = # hidden, use -P to show it syslog_facility = local0 userdb { args = /etc/dovecot/dovecot-ldap.conf.ext driver = ldap } verbose_proctitle = yes protocol lmtp { mail_plugins = quota sieve } protocol imap { mail_max_userip_connections = 20 mail_plugins = quota imap_quota }
telegraphe5:/dev/shm# grep -vE '^(#|$)' /etc/dovecot/dovecot-ldap.conf.ext
uris = ldaps://ldap-test.mines-albi.fr
tls_require_cert = hard
auth_bind = yes
base = ou=People,dc=enstimac,dc=fr
user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid,
dcMailQuota=quota_rule=*:bytes=%{ldap:dcMailQuota}M
user_filter = (&(objectClass=posixAccount)(|(uid=%n)(mail=%n@mines-albi.fr)))
iterate_attrs = uid=user
iterate_filter = (objectClass=posixAccount)
telegraphe5:/dev/shm# ls -l /var/mail/mailconf/global/sieve/before.d/ total 0
telegraphe5:/dev/shm# ls -al /var/mail/mailconf/t/tstifi04/ total 44 drwx------ 3 tstifi04 ifie2012 4096 févr. 5 10:46 . drwxrwxrwt 169 root root 16384 janv. 5 18:48 .. lrwxrwxrwx 1 tstifi04 ifie2012 25 janv. 31 17:50 .dovecot.sieve -> sieve/rainloop.user.sieve -rw------- 1 tstifi04 ifie2012 1520 févr. 5 13:22 .dovecot.sieve.log -rw------- 1 tstifi04 ifie2012 10336 févr. 5 10:46 .dovecot.sieve.log.0 -rw------- 1 tstifi04 ifie2012 172 janv. 31 17:56 .dovecot.svbin drwx------ 3 tstifi04 ifie2012 4096 janv. 31 17:50 sieve telegraphe5:/dev/shm# ls -al /var/mail/mailconf/t/tstifi04/sieve/rainloop.user.sieve -rw------- 1 tstifi04 ifie2012 102 janv. 31 17:50 /var/mail/mailconf/t/tstifi04/sieve/rainloop.user.sieve telegraphe5:/dev/shm# cat /var/mail/mailconf/t/tstifi04/sieve/rainloop.user.sieve
# This is RainLoop Webmail sieve script. # Please don't change anything here. # RAINLOOP:SIEVE
telegraphe5:/dev/shm#
telegraphe5:/dev/shm# cat /var/mail/mailconf/global/sieve/after.d/spam-into-junk.sieve require ["fileinto"];
if header :is "X-Spam-Status" "Yes" { fileinto "Junk"; stop; }
participants (1)
-
Ludovic POUZENC