  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 pro-
  vided files are copyright  Carlo Contavalli 2001-2002. Please read
  the following sections for more details. [1mNote that this is free soft-[0m
  [1mware and authors hold no responsibility for any damage or loss, direct[0m
  [1mor indirect, caused by using this software.  Use it only on your OWN[0m
  [1mrisk and AFTER carefully reading this documentation.  [22mThe latest ver-
  sion of this document can be found at  <http://www.commedia.it/ccon-
  tavalli/>.

  [1m1.  License, copyright and...[0m

  This document and the courier patch described here were written by
  Carlo Contavalli <ccontavalli at commedia.it> and are thus Copyright 
  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.



  [1m2.  About this document & this patch...[0m

  The purpose of this patch is to create users' home directoryes 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:

    [1mCourier 0.36.0[0m

    [1mCourier 0.36.1[0m

    [1mCourier 0.37.0[0m

    [1mCourier 0.37.2[0m

    [1mCourier 0.37.3[0m

    [1mCourier 0.38.0[0m

    [1mCourier 0.38.1[0m

    [1mCourier 0.39.0[0m

    [1mCourier 0.40.0[0m

    [1mCourier 0.40.1[0m

    [1mCourier 0.40.2[0m

    [1mCourier 0.41.0[0m

     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 [1mhttp://www.commedia.it/ccontavalli/[22m.  If you have
  troubles/suggestions/corrections feel free to mail me at [1m<ccontavalli[0m
  [1mat commedia.it>[22m.

  The patch was not meant for maildrop or courier-mta, althrought 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).

  [1mWhatch out: [22ma 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.
  [1mWhatch out: [22mif you had troubles getting the pop3 server to create the
  home directories go on to the section ``Configuration Parameters''.


  [1m3.  Installation[0m

  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.


  [1m3.1.  From scratch[0m


  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 courier

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


  [1m3.2.  With debian[0m


  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 couirer


       # 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. [1mWatch out! [22mthe 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...


  [1m4.  Usage[0m


  [1m4.1.  Configuration parameters[0m

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

    [1mIMAP_MAILDIR_CREATOR[0m

     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"



    [1mPOP3_MAILDIR_CREATOR[0m

     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"



  [1mWatch out: [22mCourier passes configuration parameters throught the envi-
  ronment. 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 config-
  uration file are loaded with export, sed and env, the pop3 initializa-
  tion scripts export only a limited amount of parameters. You may find
  it usefull ([1mIt won't work otherwise[22m) 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



    [1mMOD_MAILDIR_CREATOR[0m

     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.



  [1m4.2.  Creating the necessary script(s)...[0m

  [1mBeware! [22mThe scripts are  called with a simple execve. Thus, they
  cannot be ``inlined'' bash scripts.  Example:
       [1mTHIS IS BAD: [22mIMAP_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

     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".
  ______________________________________________________________________



  [1m5.  Tracking down problems[0m

  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 preceeded 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 config-
  ured in the database) and userpassword is its password.

  If you have an error like:

    [1m-ERR Maildir: non existent maildir and no POP3 environment variable[0m


     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.


    [1m-ERR Maildir (exec): ...[0m


     Courier executed (or tryed to) the script but the maildir is still
     not existant, 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 shuld 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.



