Howdy folks,
we're using Dovecot 2.3.19 in combination with vmailmgr as the virtual user
management backend (please don't judge, there are plans to move away from it
for various reasons, but as of today it's there), using the wrapper from
https://wiki.dovecot.org/HowTo/VMailMgr - and we're facing an interesting
problem with colons in home directories. I think this problem is not specific
to vmailmgr but happens in any scenario that includes ":" in directory names.
tl;dr:
- The checkvpw-dovecot-wrapper from the Dovecot wiki converts ":" in directory
names to "::" which works fine with general IMAP use, but at least the
autoexpunge plugin and ManageSieve don't handle this escaping and thus break on
those users.
- When patching the ":"->"::" conversion out of the checkvpw-dovecot-wrapper,
Dovecot itself bails on it, interpreting it as a sub-setting.
- The latter is quite surprising because a HOME/mail_home directory is supposed
to be exactly one directory (AFAIK), with no sub-settings like e.g.
mail_location, so I did not expect it to be "interpreted" in any way.
Short story long:
When you set up a user with a name containing dots, vmailmgr converts them to
colons, pretty much like qmail does (qmail maps the username "xy.z" to a file
named ".qmail-xy:z"; vmailmgr creates the directory "./users/xy:z" for that
username). The wrapper from the dovecot wiki escapes ":" into "::" before
exporting the user's directory as the HOME environment variable:
/* escape possible ':' characters before finally exporting */
escape_colon(buffer, MAXLEN);
setenv("HOME", buffer, 1);
The result looks like that:
[root@stardust ~]# doveadm auth login [email protected] supersecret
passdb: [email protected] auth succeeded
extra fields:
[email protected]
userdb extra fields:
[email protected]
home=/home/coltest/./users/xy::z <---------- notice the double colon here
uid=1009
gid=1010
auth_mech=PLAIN
So far, so good: Working with IMAP generally works fine, but there's a catch:
Not every module seems prepared for this "::" syntax. The first notable
exception is the autoexpunge plugin which simply bails on it:
Error: autoexpunge: Couldn't create dovecot.autoexpunge.lock lock:
file_create_locked(/home/coltest/./users/xy::z/dovecot.autoexpunge.lock)
failed: safe_mkstemp(/home/coltest/./users/xy::z/dovecot.autoexpunge.lock)
failed: No such file or directory
The second notable exception is ManageSieve which takes the escaped directory
name "as is", leading to a situation where the Maildir is in "xy:z" while the
Sieve stuff is being put in "xy::z" where it effectively is never picked up
during delivery (as the stuff is in the wrong location and the .dovecot.sieve
symlink is - silently - not created):
[coltest@stardust ~]$ ls -la users/*
users/xy:z:
total 28
drwx------. 9 coltest coltest 4096 Jun 16 11:39 .
drwxr-xr-x. 4 coltest coltest 31 Jun 16 11:40 ..
drwxr-xr-x. 2 coltest coltest 6 Jun 16 11:39 cur
-rw-------. 1 coltest coltest 376 Jun 16 11:40 dovecot.index.log
-rw-------. 1 coltest coltest 2676 Jun 16 11:39 dovecot.list.index.log
-rw-------. 1 coltest coltest 96 Jun 16 11:39 dovecot.mailbox.log
-rw-------. 1 coltest coltest 51 Jun 16 11:39 dovecot-uidlist
-rw-------. 1 coltest coltest 8 Jun 16 11:39 dovecot-uidvalidity
-r--r--r--. 1 coltest coltest 0 Jun 16 11:39 dovecot-uidvalidity.62aafa70
drwx------. 5 coltest coltest 108 Jun 16 11:39 .Drafts
drwxr-xr-x. 2 coltest coltest 6 Jun 16 11:39 new
drwx------. 5 coltest coltest 108 Jun 16 11:39 .Sent
drwx------. 5 coltest coltest 108 Jun 16 11:39 .Spam
-rw-------. 1 coltest coltest 28 Jun 16 11:39 subscriptions
drwxr-xr-x. 2 coltest coltest 6 Jun 16 11:39 tmp
drwx------. 5 coltest coltest 108 Jun 16 11:39 .Trash
users/xy::z:
total 0
drwx------. 3 coltest coltest 19 Jun 16 11:40 .
drwxr-xr-x. 4 coltest coltest 31 Jun 16 11:40 ..
drwx------. 3 coltest coltest 33 Jun 16 11:40 sieve
So my initial thought was: Why is the ":" even escaped to a "::" in the first
place? It shouldn't be necessary according to this clean workaround that I
found in a posting from 2009 with Timo advising for this type of handling:
> Hmm. Although now that I looked at your code, you seem to be using only
> HOME. And using ~/ in mail_location should work around any ":" issues.
> So what exactly is the problem you're seeing?
https://www.dovecot.org/list/dovecot/2009-June/040590.html
(In the same thread, Timo _also_ introduced the "::" handling in Dovecot.)
This is exactly what we're doing at delivery time: Setting mail_home to the
real pathname including a _single_ colon (not an escaped double colon) and then
pointing mail_location to "~/":
/usr/libexec/dovecot/dovecot-lda -a '$RECIPIENT' -f '$SENDER' -o
mail_home='$MAILDIR' -o mail_location='maildir:~/'
This works well.
So my assumption was: If the checkvpw-dovecot-wrapper returns the HOME
directory of a virtual user; where's even the need to escape a single colon to
a double colon? So I gave it a try and removed that one line of escaping and
recompiled the wrapper. Result:
[root@stardust ~]# doveadm auth login [email protected] supersecret
passdb: [email protected] auth succeeded
extra fields:
[email protected]
userdb extra fields:
[email protected]
home=/home/coltest/./users/xy:z <---------- single colon here now
uid=1009
gid=1010
auth_mech=PLAIN
Using a real IMAP login, though, this lead to the "interesting" situation that
the login itself worked correctly, but _then_ immediately an "Internal error
occurred":
[root@stardust ~]# nc localhost 143
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SPECIAL-USE
LITERAL+ STARTTLS AUTH=PLAIN] Dovecot ready.
0 LOGIN [email protected] supersecret
0 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 PREVIEW STATUS=SIZE
SAVEDATE SPECIAL-USE LITERAL+ NOTIFY SPECIAL-USE] Logged in
* BYE Internal error occurred. Refer to server log for more information.
This is the according log:
Jun 16 10:04:37 stardust.uberspace.de dovecot[15268]: Jun 16 10:04:37
imap-login: Info: Login: user=<[email protected]>, method=PLAIN, rip=::1,
lip=::1, mpid=22889, secured
Jun 16 10:04:37 stardust.uberspace.de dovecot[15268]: Jun 16 10:04:37
imap([email protected])<22889><utbow43hgJoAAAAAAAAAAAAAAAAAAAAB>: Error:
Namespace '': Unknown setting: z
Jun 16 10:04:37 stardust.uberspace.de dovecot[15268]: Jun 16 10:04:37
imap([email protected])<22889><utbow43hgJoAAAAAAAAAAAAAAAAAAAAB>: Info:
Disconnected: Namespace '': Unknown setting: z in=0 out=428 deleted=0
expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
So it looks like Dovecot tries to do some interpretation on the HOME value,
splitting it at the ":" and interpret the "z" as some kind of sub-setting -
which a HOME variable (in contrast to, e.g. mail_location) is not supposed to
have.
Here I'm a bit stuck. My idea is to work around this by eliminating the ":"
from directory names altogether by passing an explicit directory name to
vadduser:
[coltest@stardust ~]$ echo supersecret | vadduser --directory=./users/ab.c ab.c
vadduser: user 'ab.c' successfully added
[coltest@stardust ~]$ ls -l users
total 0
drwx------. 5 coltest coltest 39 Jun 16 10:26 ab.c
drwx------. 5 coltest coltest 39 Jun 16 09:31 xy:z
But still, it would be nicer if Dovecot cleanly supported the ":" in directory
names, as it seems to _want_ to support it (by introducing the "::" escaping)
but then only does it halfway.
Could this be fixed in whatever direction, or is there any other advice how we
should handle this?
All the best,
Jonas