Courier Patch for automatic maildir creation

Carlo Contavalli <ccontavalli at commedia.it> Thu Jan 3 16:54:45 CET 2002

This file documents a patch I’ve made for courier to allow automatic maildir creation. This manual, the mentioned patch and all the provided files are copyright \begin{matrix}c \\ ◯ \end{matrix} Carlo Contavalli 2001,2002,2003,2004,2004. Please read the following sections for more details. Note that this is free software and authors hold no responsibility for any damage or loss, direct or indirect, caused by using this software. Use it only on your OWN risk and AFTER carefully reading this documentation. The latest version of this

document can be found at http://www.commedia.it/ccontavalli/ .

1 License, copyright and...

This document and the courier patch described here were written by Carlo Contavalli <ccontavalli at commedia.it> and are thus Copyright \begin{matrix}c \\ ◯ \end{matrix} Carlo Contavalli 2001-2002.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.

Any example of program code available in this document should be considered protected by the terms of the GNU General Public License.

This patch 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 2 of the License, or (at your option) any later version.

This patch 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Trademarks are owned by their respective owners.

2 About this document & this patch...

The purpose of this patch is to create users’ home directories when they first login either with a imap or pop3 client. It was developed in an afternoon and it is intended to be used in environments where the email accounts are managed using a database or some automatic process. It’s been used in production environments with mysql, but it hasn’t been deeply tested with ldap or any other authentication method (any feedback is welcome). This patch relies on some scripts that each administrator should write to adapt the whole system to his needs. Examples of those scripts are provided in the following sections of this manual.

This patch applies against:

• Courier 0.36.0

• Courier 0.36.1

• Courier 0.37.0

• Courier 0.37.2 • Courier 0.37.3

• Courier 0.38.0

• Courier 0.38.1

• Courier 0.39.0

• Courier 0.40.0

• Courier 0.40.1

• Courier 0.40.2

• Courier 0.41.0

• Courier 0.42.0

• Courier 0.43.1

• Courier 0.44.2

• Courier 0.45.5

It has been tested with Courier 0.36.0 and 0.37.2. However, this document may be out of date, so please refer to the specific documentation contained in the patch tarball (README_0.36.0, for example).

Since version 0.37.2 this patch also allows users in a virtual domain environment to use “%” or “:” as separator in usernames instead of the classical “@”. For example, once the patch is applied, a user could login on the imap or pop3 server either as:

• user@somedomain.com

• user%somedomain.com

• user:somedomain.com

This patch translates the username in something valid right when the user types his name. Thus, any authentication module would see the correct name, with the “%” or “:” replaced by an “@”.

You can find the latest version of this document and the mentioned software at http://www.commedia.it/ccontavalli/ . If you have troubles/suggestions/corrections feel free to mail me at <ccontavalli at commedia.it>.

The patch was not meant for maildrop or courier-mta, although little effort must be taken to adapt to add complete support. I personally use postfix, and I’m not very interested in courier-mta nor in maildrop. I’m now working to document the process of integration of courier imap with postfix and a web interface. If you are interested in it, I may send by email the latest “beta” version of such paper (it will be available on this site when complete). Actually, it may take me a while to complete the whole document (I haven’t had much time in the last few weeks).

Whatch out: a few version ago a bug in my patch that prevented courier from being compiled on many systems has been corrected thanks to Van Daele Bruno. If you had troubles using my patch, please try with the latest release available on my site. All the versions of the patch have been corrected.

Whatch out: if you had troubles getting the pop3 server to create the home directories go on to the section 4.1 (Configuration Parameters).

Watch out: I don’t have much spare time in my life anymore, and don’t have the time to actively upkeep my homepage and/or the courier patch. However, I’m quite happy about it, and will continue to release versions as soon as I realize a new version is availabile and somebody needs it (which may occur a couple months after the new release). So, do mail me if you need a recent version of my patch. I will be glad to provide it in a couple days and to upload it on my homepage.

3 Installation

Before starting, keep in mind that if you don’t want to patch your courier, you can use the authentication module courier-authmkhome on my home page to create users’ home directories. However, if you don’t patch courier, you need to do little tricks with the user home directory. Read the specific documentation.

3.1 From scratch

You’ll need: patch, make, tar, gzip, gunzip, gcc, and all the files needed to compile courier.

1. Get the source code of courier-imap and my patch from http://www.commedia.it/ccontavalli/ http://www.courier-mta.org/

2. Unpack the courier tarball somewhere (/usr/src is good - I assume the .tar.gz is in your home directory)

       $ cd /usr/src
       $ tar -xvzf ~/courier-imap.tar.gz

3. Unpack the patch somewhere in your hard drive (/usr/src is good - Same assumption)

       $ tar -xvzf ~/courier_patch.tar.gz

4. Apply the patch

(a) Get in the directory of the courier sources

           $ cd courier-0.x.x

(b) If provided, check the README for your specific courier version (README.courier_version). It should tell the exact diff file to use to patch your version of courier.

(c) Give the following command using instead of courier_0.x.x.diff the file found in the previous step:

           $ cat ../courier_patch/courier_0.x.x.diff | patch -p1

5. Compile courierYou should follow the steps indicated in courier documentation. It would be good to include support for authdaemon and for some kind of database :-).

3.2 With debian

1. Make sure to have all the needed tools to compile courier

       # apt-get install dpkg-dev
       # apt-get install gcc make patch g++

2. Get the source for courier with

       # apt-get source courier

3. Get the packages needed to build courier

       # apt-get build-dep courier

4. Apply the patch

     # cd courier_0.x.x.orig
     # cat ../courier_patch/courier_0.x.x | patch -p1

Remember to always apply the patch provided with debian before any other patch (in this case, apt-get source takes care of that).

5. Build a brand new debian package

     # dpkg-buildpackage

6. Install the needed packages

     # dpkg -i ./courier-imap_0.x.x.deb
     # dpkg -i ./courier-pop3_0.x.x.deb
     # dpkg -i ./courier-authdaemon_0.x.x.deb
     # dpkg -i ./courier-authmysql_0.x.x.deb

7. Watch out! the next time you’ll use apt-get update, this package will be overwritten! You may want to wait for the patch to be available as .deb on my own site or use the pin mechanism provided by apt-get (look at apt_preferences(5))... this is just a fast and easy method to compile courier without having to deal with configure scripts and stuff like that...

4 Usage

4.1 Configuration parameters

The patch you just applied adds support for three new configuration parameters you should add in the correct configuration file.

• IMAP_MAILDIR_CREATOR Specifies a script or a program to run when a maildir is not found by the imap daemon. The script is called with the missing maildir name as the first argument, and other parameters can be taken from the environment. This option should be put (in debian) in /etc/courier/imapd. In other distribution, the best place would be a configuration file, but if you can’t find one, just put the variable in the environment before running courier (look the manual page for env and at the scripts in init.d). Example:

                 IMAP_MAILDIR_CREATOR="/sbin/imapcreator"

• POP3_MAILDIR_CREATOR Specifies a script or a program to run when a maildir is not found by the pop3 daemon. The script is called with the missing maildir name as the first argument, and other parameters can be taken from the environment. This option should be put (in debian) in /etc/courier/pop3d. In other distribution, the best place would be a configuration file, but if you can’t find one, just put the variable in the environment before running courier (look the manual page for env and at the scripts in init.d). Example:

                 POP3_MAILDIR_CREATOR="/sbin/pop3creator"

Watch out: Courier passes configuration parameters throught the environment. If you look at the scripts in /etc/init.d/ you’ll see that while before loading the imap daemon all the parameters in the configuration file are loaded with export, sed and env, the pop3 initialization scripts export only a limited amount of parameters. You may find it usefull (It won’t work otherwise) to put something like this in your /etc/init.d/courier-pop3 script, or in /usr/sbin/pop3d (it’s a script):

                        /usr/bin/env - POP3_MAILDIR_CREATOR="$POP3_MAILDIR_CREATOR" PATH="...

and so on, instead of the usual (your is probably different):

                       /usr/bin/env - PATH="$PATH" SHELL="$SHELL" POP3AUTH="$POP3AUTH" \
                            $TCPD -pid=$PIDFILE -stderrlogger=${sbindir}/courierlogger \
                                                -maxprocs=$MAXDAEMONS -maxperip=$MAXPERIP \
                                                         $TCPDOPTS -address=$ADDRESS $PORT \
                        ${prefix}/lib/courier/courier/courierpop3login $AUTHMODULELIST \
                                        ${prefix}/lib/courier/courier/courierpop3d Maildir

• MOD_MAILDIR_CREATOR Specifies a script or a program to run when the home directory of the user is not found. For example, if you have an user called “foo”, if “/home/foo” does not exist MOD_MAILDIR_CREATOR is called. POP3 or IMAP MAILDIR_CREATOR are called when “/home/foo/Maildir” does not exist. Example:

                       MOD_MAILDIR_CREATOR="/sbin/modcreator"

Keep in mind that MOD_MAILDIR_CREATOR is the first one to be called when no homedir exists, while POP3/IMAP MAILDIR_CREATOR are called if the maildir in the user home directory does not exist, and the script are thus usually called in the following order:

• MOD_MAILDIR_CREATOR

• either one of POP3_MAILDIR_CREATOR or IMAP_MAILDIR_CREATOR

If the parameters are not defined or have a null value, no maildir is created. If the maildir creator is not found no error is produced, maildirs are simply not created.

4.2 Creating the necessary script(s)...

Beware! The scripts are called with a simple execve. Thus, they cannot be “inlined” bash scripts. Example:

     THIS IS BAD: IMAP_MAILDIR_CREATOR="mkdir $(echo 'SELECT * FROM ...'|cut -f);
     chmod..."

Ok, let’s review a little bit the process... When a user connects, its username and password are looked up in the selected database. Once all the necessary information have been found, the daemon drops its super-user privileges to become the user it has just authenticated. It then tries to change to the user home directory and, if not found, the maildir creator script is called. Once called, it tries again to chdir to the user home directory, and if an error verifies, the user is kicked out with an error message, otherwise the home directory has been successfully created and the session goes on.

There are few things to keep in mind when writing the mailcreator script:

• Unless you are using a suid script (with some kind of wraparound), the script will have the user’s privileges. Starting from this assumption, I would suggest you setup the home directories to be owned by the recipient and by a generic mailgroup. You can then create a /home/mail owned by root with privileges 0770 (rwxrwx— ) where every user owns his home directory and is part of the mailgroup, with his home directory having permissions 0700, leading to something like 4. Usage 6

drwxrwx--- root mailgrp /home/mail
drwx------ usr1 mailgrp /home/mail/usr1
drwx------ usr2 mailgrp /home/mail/usr2

Using this scheme, no user would be able to read somebody else mails, no user would be able to remove anybody else maildirs. However, using this scheme, any mailgrp user could be able to create any number of directories inside /home/mail without giving the right to courier to write in there leading to a denial of service. This method is thus suggested to those of you who don’t give shell accounts to their mail users.

• The maildir creator script can take a lot of information from the environment. However, the content of the environment may change from version to version of courier. Before you use those variables, I suggest you put some line like the following in your script, to make sure that the variable you want to use exist:

     set >> /tmp/state.log

Here is an incomplete list of variables available in courier-0.36.0 and their values (most of them are just crap from our point of view):

ADDRESS=0
AUTHADDR=ccontavalli@localhost  # Mail address of the logged in user
AUTHARGC=4                         # See man authlib
AUTHARGV0=/usr/lib/courier/courier/imaplogin
AUTHARGV1=/usr/lib/courier/authlib/authdaemon
AUTHARGV2=/usr/bin/imapd
AUTHARGV3=Maildir
AUTHENTICATED=ccontavalli@localhost # Username
AUTHEXPIRE=1009760251
AUTHFULLNAME='Carlo Contavalli' # Full name of the user (if provided by the db)
AUTHMODULES=authdaemon
AUTHMODULES_ORIG=authdaemon
AUTHUSER=/usr/lib/courier/courier/imaplogin
EUID=1051                          # Effective user id of the process
                                     # (provided by your system)
GROUPS=()                          # Additional groups (provided by your system)
HOSTNAME=caronte                  # Hostname (provided by your system)
IMAPDSTART=YES
IMAPLOGINTAG=001
IMAP_CAPABILITY='IMAP4rev1 CHILDREN NAMESPACE \
         THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT'
IMAP_CAPABILITY_ORIG='IMAP4rev1 CHILDREN NAMESPACE \
         THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT \
         AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE'
IMAP_CAPABILITY_TLS='IMAP4rev1 CHILDREN NAMESPACE \
         THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT AUTH=PLAIN'
IMAP_CAPABILITY_TLS_ORIG='IMAP4rev1 CHILDREN NAMESPACE \
         THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT AUTH=CRAM-MD5 \
         AUTH=CRAM-SHA1 IDLE AUTH=PLAIN'
IMAP_CHECK_ALL_FOLDERS=0
IMAP_DISABLETHREADSORT=0
IMAP_EMPTYTRASH=Trash:7
IMAP_IDLE_TIMEOUT=60
IMAP_MOVE_EXPUNGE_TO_TRASH=0
IMAP_OBSOLETE_CLIENT=0
IMAP_STARTTLS=NO
IMAP_ULIMITD=65536

          IMAP_USELOCKS=0
          MAILDIR=1051/
          MAXDAEMONS=40
          MAXPERIP=4
          OPTERR=1
          OPTIND=1
          PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
          PIDFILE=/var/run/courier/imapd.pid
          PIPESTATUS=([0]="0")
          PORT=143
          PPID=668
          TCPDOPTS='-nodnslookup -noidentlookup'
          TCPLOCALIP=::ffff:127.0.0.1
          TCPLOCALPORT=143
          TCPREMOTEIP=::ffff:127.0.0.1
          TCPREMOTEPORT=1030
          UID=1051

Finally, here is an example of maildir creator that uses the provided environment variables and the suggested scheme of ownerships and rights:

     #!/bin/bash
     maildir=$1
     maildirmake /home/mail/$maildir
     chown -R $UID:mailgrp /home/mail/$maildir
     logger -p auth.notice -t courier Automagically created homedir "$1"\
               for uid "$UID" aka "$AUTHADDR".

5 Tracking down problems

Since it’s sometimes kind of hard to track down problems with courier imap/pop3, I’ve modified some error messages outputted by the pop3 server and relate to my patch in order to ease the task of fixing problems.

Ok, once the courier pop3 server is up and running, try to

     $ telnet localhost 110

After you see

     +OK Hello there.

type (any line preceded by a + is output of the daemon, you don’t have to type it)

     USER validuser@domain
     +OK Password required.
     PASS userpassword

where validuser@domain is a valid username (already correctly configured in the database) and userpassword is its password.

If you have an error like:

• -ERR Maildir: non existent maildir and no POP3 environment variable You need to check:

– the init script for pop3d. You probably forgot to modify the environment as described in the previous sections.

– the POP3_MAILDIR_CREATOR environment variable didn’t reach the pop3 server. Check for typos.

• -ERR Maildir (exec): ... Courier executed (or tried to) the script but the maildir is still not existent, and the chdir failed with the error specified by the ... Whatever happened, the maildir was not created. You may want to check:

– the correctness of the path of the script to execute

– the ownership and rights of the script (maybe courier couldn’t execute it)

– if the script correctly creates the maildir when manually called

– if the maildir has the correct rights and is created in the correct place

Any other error is not related to my patch. You should check the whole configuration with the documentation provided with courier.

Once everything is working with pop3 it shouldn’t be hard to get everything working with imap, and no special messages are printed with imap.

Note that you should never see those messages in a running and configured server.