The Cyrus-Imapd Chapter

The article describes the installation and configuration of a secured cyrus-imapd server on Debian Squeeze. Its goal is to describe the steps to get a running IMAP server, with SSL and LDAP support.

It does not include the configuration of Postfix and OpenLDAP. Those onces are described in other articles of this wiki.

As shown in the architecture diagram below, Cyrus-Imap will be using many others component of the system, such as OpenLDAP for account information storage, postfix for everything related to SMTP and LMTP, and so on…

Cyrus Imapd's job is mainly to store emails, apply rules to them (via sieve and ACLs), and provide network access (via imap). And we will stick to this.

The basis

I assume you are familiar with the Imap theory. So let's get started directly with, as always…

# aptitude install cyrus-imapd-2.2

Life should always be that simple !

So we now have to major files : /etc/cyrus.conf and /etc/imapd.conf. The first one declares the services to start, and the second one contains the configuration parameters.

Selecting Cyrus Imapd services in cyrus.conf

Cyrus-imapd starts a bunch of services by default:

samchiel:~# netstat -taupen|grep cyrmaster                                                                                
tcp        0      0 0.0.0.0:110             0.0.0.0:*         LISTEN      0          35730       26003/cyrmaster  
tcp        0      0 0.0.0.0:143             0.0.0.0:*         LISTEN      0          35723       26003/cyrmaster  
tcp        0      0 0.0.0.0:119             0.0.0.0:*         LISTEN      0          35737       26003/cyrmaster  
tcp        0      0 127.0.0.1:4190          0.0.0.0:*         LISTEN      0          35750       26003/cyrmaster  
tcp6       0      0 :::110                  :::*              LISTEN      0          35732       26003/cyrmaster  
tcp6       0      0 :::143                  :::*              LISTEN      0          35725       26003/cyrmaster  
tcp6       0      0 :::119                  :::*              LISTEN      0          35739       26003/cyrmaster  
tcp6       0      0 ::1:4190                :::*              LISTEN      0          35748       26003/cyrmaster  
  • 110 is pop3 (deprecated)
  • 143 is imap (but we will prefer imapS)
  • 119 is nntp (USENET News Transfer Protocol)
  • 4190 is sieve (the email filtering daemon)

What I want is the following:

  • imaps open to the world, with a SSL certificate I will generate locally
  • imap open on localhost only (I intend to put a webmail on this host, no need to overload the server with useless local SSL connections)
  • sieve open on localhost only (sieve rules will be managed through the webmail)

The rest, I can get rid of. So my /etc/cyrus.conf file will look as follow (once the commented lines removed):

START {
        recover         cmd="/usr/sbin/ctl_cyrusdb -r"
        delprune        cmd="/usr/sbin/cyr_expire -E 3"
        tlsprune        cmd="/usr/sbin/tls_prune"
}
SERVICES {
        imap            cmd="imapd -U 30" listen="localhost:imap" prefork=0 maxchild=10
        imaps           cmd="imapd -s -U 30" listen="imaps" prefork=0 maxchild=10
        lmtp            cmd="lmtpd" listen="localhost:lmtp" prefork=0 maxchild=3
        sieve           cmd="timsieved" listen="localhost:sieve" prefork=0 maxchild=10
}
EVENTS {
        checkpoint      cmd="/usr/sbin/ctl_cyrusdb -c" period=30
        delprune        cmd="/usr/sbin/cyr_expire -E 3" at=0401
        tlsprune        cmd="/usr/sbin/tls_prune" at=0401
}

OK, 3 different sections with 3 different types of entries. The man page of cyrus.conf gives us some more information on thoses:

   START
       This section lists the processes to run before any 
       SERVICES are spawned.  This section is  typically  used  to
       initialize databases and start long running daemons.
   SERVICES
       This  section is the heart of the /etc/cyrus.conf file.
       It lists the processes that should be spawned to handle 
       client connections made on certain Internet/UNIX sockets.
   EVENTS
       This section lists processes that should be run at 
       specific intervals, similar to cron jobs.  This section is
       typically used to perform scheduled cleanup/maintenance.

So, with our new config file, we can restart cyrus and check the open port. It should look like this:

# /etc/init.d/cyrus2.2 restart
Stopping Cyrus IMAPd: cyrmaster.
Waiting for complete shutdown...
Starting Cyrus IMAPd: cyrmaster.

# netstat -taupen |grep cyrmaster                                                                               
tcp        0      0 0.0.0.0:993             0.0.0.0:*     LISTEN      0    50401       27013/cyrmaster  
tcp        0      0 127.0.0.1:143           0.0.0.0:*     LISTEN      0    50396       27013/cyrmaster  
tcp        0      0 127.0.0.1:4190          0.0.0.0:*     LISTEN      0    50411       27013/cyrmaster  
tcp6       0      0 :::993                  :::*          LISTEN      0    50403       27013/cyrmaster  
tcp6       0      0 ::1:143                 :::*          LISTEN      0    50394       27013/cyrmaster  
tcp6       0      0 ::1:4190                :::*          LISTEN      0    50409       27013/cyrmaster  

Good to go…

Configuring Cyrus Imapd in imapd.conf

/etc/imapd.conf contains all the configuration parameters. The Debian version of this file is very well commented, but it doesn't explain the underlying logic of cyrus-imapd.

Imapd is not only an imap server, as we saw before, it supports nntp, sieve, pop3, notifyd and so on… All of those services are email related, and the main one is imap v4. The goal of cyrus-imapd is to provide an implementation of those protocol and thus serve email stored on a local storage to a network client through a network protocol. cyrus-imapd needs to rely an other softwares to perform mail delivery and authentication. For mail delivery, feel free to take a look at the articles on Postfix on this wiki. For the authentication, the cyrus team provides another software: cyrus-sasl. SASL stands for Simple Authentication and Security Layer. Typically, cyrus-imapd will receive and authentication requests through an imap command, and will pass it along to cyrus-sasl to verify this authentication. Will see SASL in detail later. For now, we need to configure the imap service itself.

Configuration of /etc/imapd.conf:

# grep -v "^#" /etc/imapd.conf |grep -v "^$"

configdirectory: /var/lib/cyrus
defaultpartition: default
partition-default: /var/spool/cyrus/mail
altnamespace: no
unixhierarchysep: no
reject8bit: no
munge8bit: yes
lmtp_downcase_rcpt: yes
admins: cyrus
allowanonymouslogin: no
popminpoll: 1
autocreatequota: 0
umask: 077
sieveusehomedir: false
sievedir: /var/spool/sieve
hashimapspool: true
allowplaintext: yes
sasl_pwcheck_method: auxprop
sasl_auxprop_plugin: ldapdb
sasl_auto_transition: no
sasl_ldapdb_uri: ldap://localhost
sasl_ldapdb_id: cyrus
sasl_ldapdb_pw: highsecuritypassword
sasl_ldapdb_mech: DIGEST-MD5
tls_cert_file: /etc/ssl/certs/imap/imap.certificate.pem
tls_key_file: /etc/ssl/certs/imap/imap.privatekey.key
tls_ca_file: /etc/ssl/certs/imap/rootca-certificate.crt
tls_session_timeout: 1440
tls_cipher_list: TLSv1+HIGH:!aNULL:@STRENGTH
lmtpsocket: /var/run/cyrus/socket/lmtp
idlemethod: poll
idlesocket: /var/run/cyrus/socket/idle
notifysocket: /var/run/cyrus/socket/notify
syslog_prefix: cyrus

Let's take a closer look at this file.

configdirectory

This contains internal databases and files related to imapd internal work. You will find there copies of databases, user 'seen' files (the seen/not seen emails), and so on…

This is what I have on another server.

|-- annotations.db
|-- db
|   |-- __db.001
|   |-- __db.002
|   |-- __db.003
|   |-- __db.004
|   |-- __db.005
|   |-- log.0000000011
|   `-- skipstamp
|-- db.backup1
|   |-- annotations.db
|   |-- log.0000000011
|   `-- mailboxes.db
|-- db.backup2
|   |-- annotations.db
|   |-- log.0000000011
|   `-- mailboxes.db
|-- deliver.db
|-- log
|-- mailboxes.db
|-- msg
|-- proc
|   |-- 10012
[...]

defaultpartition and partition-default

A partition is the location of the file storage, typically a path on your server (with some space available). Both values work together, the first one declares the name of the default partition (defaultpartition: <name>) and the second one is the expected value (partition-<name>).

So, here, we store all the files in the default partition which is in /var/spool/cyrus/mail. (feel free to change that).

admins

The name(s) of the administrator(s). We will see later that we need to create this guy in the SASL database.

hashimapspool

Define the hashing for the email partition. This is the option that will decide on your folder hierarchy. If this is on, you will have a partition that looks like this:

.
|-- a
|-- b
|   `-- user
|       `-- bogdana
|           |-- Draft
|           |-- INBOX
|           |   `-- Trash
|           |-- Sent
|           |-- Spam
|           |-- Trash
|-- c
|-- d
|-- e
|-- f
|   `-- user
|       `-- franck
|           |-- Drafts
|           |-- Junk
|           |-- Sent
|           `-- Trash
|-- g
|-- h
|-- i
|-- j
|   `-- user
|       |-- jeannot
|       |-- jerome
|       |   |-- Brouillons
|       |   |-- Corbeille
|       |   |-- Exemple
|       |   |-- Trash
|       |   `-- sent
|       `-- julien
|           |-- BugTraq
|           |-- Drafts
|           |-- Golf
|           |-- La Sauce
|           |-- Linuxwall
|           |-- Lists
|           |   |-- Full Disclosure
|           |   |-- Metasploit
|           |   |-- Netfilter
|           |   |   `-- devel
|           |   |-- OpenCA
|           |   |-- OpenSSL
|           |   |-- OpenVPN
|           |   |-- cyrus
|           |   |-- debian
|           |-- Rapports_Systemes
|           |-- SQT Group
|           |-- Spam
|           |-- Trash
|           |-- UMD
|           |-- drafts
|           |-- jobs
|           `-- sent-mail
|-- k
|-- l
|-- m
|-- n
|   `-- user
|       `-- njm
|           |-- Drafts
|           |-- Junk
|           |-- Sent
|           `-- Trash
|-- o
|-- p
|-- q
|-- r
|-- s
|-- t
|-- u
|-- v
|-- w
|-- x
|-- y
`-- z

sieveusehomedir and sievedir

We will be using the sieve server. Sieve is a service that allow a user to set up filter on his incoming emails. This is very useful to sort your emails in folder (like the mailing list) when they reach the server. And since it's done by cyrus-imapd directly, it doesn't overload your email client.

Sieve needs to store your filtering rules somewhere, and this in what sievedir defines. It will contain scripts and bytecodes. The scripts are just text files that look like this:

# rule:[postfix]
elsif anyof (header :contains "To" "postfix-users",
        header :contains "Cc" "postfix-users")
{
        fileinto "INBOX.Lists.postfix";
}

If you want to read more about sieve, take a look here: Filter your emails with sieve

sasl_*

The mechanism used by the server to verify plaintext passwords. Possible values include “auxprop”, “saslauthd”, and “pwcheck”. Here, we want to use auxprop. Auxprop will call an external SASL plugin to connect to the authentication backend. Since the authentication backend we will use is a ldap directory, the corresponding auxprop module will be ldapdb. For now, we focus on imapd and we will configure the authentication later.

tls_*

The tls_* parameters are used to configure the imaps access. You need a certificate and a private key to configure this. If you do not know what a certificate and a private key are, do not configure this. (And read some litterature on openssl, pki and X.509 certificates before)

TLS session can be costly to renegociate, therefore, the parameter tls_session_timeout is particularly interesting because it allows cyrus-imapd to reuse a previously negociated TLS session during half an hour without renegociating the master key.

Once TLS sessions are negociated, there is very little difference between symetrics algorithms. Using a 128 bit key or a 256 bit key in AES won't make a huge difference. Thus, I leave the default parameter for tls_cipher_list that impose high security algorithm. Or, more precisely:

# openssl ciphers 'TLSv1+HIGH:!aNULL'

DHE-RSA-AES256-SHA
DHE-DSS-AES256-SHA
AES256-SHA
DHE-RSA-AES128-SHA
DHE-DSS-AES128-SHA
AES128-SHA
EDH-RSA-DES-CBC3-SHA
EDH-DSS-DES-CBC3-SHA
DES-CBC3-SHA                                                                                        

and the rest

There is still a bunch of configuration parameters I didn't describe here. For them, the default values are alright. The comments inside the file are clear enough, and if not a little man imapd.conf should satisfy your curiosity.

Restart and check

We have imap open on localhost, and imaps globally. Let's try to connect to the second one using the openssl client:

# openssl s_client -connect localhost:993

CONNECTED(00000003)
---
Certificate chain
 0 s:/C=FR/ST=France/O=testdomain/CN=imap.testdomain.info  
i:/C=FR/ST=France/L=Paris/O=testdomain/CN=testdomain Root Certificate/emailAddress=root@testdomain.info 
 1 s:/C=FR/ST=France/L=Paris/O=testdomain/CN=testdomain oot Certificate/emailAddress=root@testdomain.info 
i:/C=FR/ST=France/L=Paris/O=testdomain/CN=testdomain Root Certificate/emailAddress=root@testdomain.info 
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFBjCCA+6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBoTELMAkGA1UEBhMCRlIx  
[...]
MmTjsl7DE8AFpWru49udHC5AiQBD51Z3aNL9z849Wd0hcwM1QIulAMH5 
-----END CERTIFICATE-----  
subject=/C=FR/ST=France/O=testdomain/CN=imap.testdomain.info  
issuer=/C=FR/ST=France/L=Paris/O=testdomain/CN=testdomain Root Certificate/emailAddress=root@testdomain.info  
---
No client certificate CA names sent 
---
SSL handshake has read 2419 bytes and written 444 bytes  
---
New, TLSv1/SSLv3, Cipher is AES256-SHA 
Server public key is 2048 bit 
Compression: NONE 
Expansion: NONE
SSL-Session:
 Protocol  : TLSv1
 Cipher : AES256-SHA 
 Session-ID: F067E10CA08531374E7D0BF379A571F234A196B94C187CE1182E93259BFB022D 
 Session-ID-ctx:  
 Master-Key: B496E9DE5A5BF9B872AEFE1836B3B923DA2412A554EE08FE67091AFEDCF983F3F859B73D2F3F7FC61662BF3761A18577  
 Key-Arg: None 
 Start Time: 1266508567 
 Timeout: 300 (sec)  
 Verify return code: 19 (self signed certificate in certificate chain)  
---


* OK samchiel Cyrus IMAP4 v2.2.13-Debian-2.2.13-19 server ready

This trace confirms our configuration. Only the very last line is from the IMAP protocol. All the rest is SSL junk. And we confirm that the cipher algorithm is AES256-SHA, which is pretty high security.

So we now have a working IMAP server, but without any account. We then need to configure SASL and also OpenLDAP.

Cyrus SASL and OpenLDAP

There are many ways to store users's credentials. One of them is to have everything regarding our users into a LDAP directory and tell Cyrus-Imapd to query that directory. However, setting up LDAP querying in Cyrus-Imapd is not that straightforward.

Imapd relies on Cyrus-SASL for everything that concerns authentication.

SASL is the Simple Authentication and Security Layer, a method for adding authentication support to connection-based protocols. To use SASL, a protocol includes a command for identifying and authenticating a user to a server and for optionally negotiating protection of subsequent protocol interactions. If its use is negotiated, a security layer is inserted between the protocol and the connection. source

To connect to a LDAP directory, Cyrus-Imapd will need several things:

  1. A SASL library with the ldapdb plugin activated
  2. A proxy user to log into the directory
  3. A proxy authorization rule in the directory

The items 2 and 3 are described in The OpenLDAP Chapter (section SASL). We will detail item 1 below.

Configuring ldapdb

We will need some additionnal components for this: The SASL binaries, and the LDAP library module for SASL.

As always:

# aptitude install sasl2-bin libsasl2-modules-ldap

The package sasl2-bin installs also the saslauthd daemon. But we will not use this last one. However, we need this package for the saslpluginviewer binary, that will list the available authentication plugins activated on the system:

# saslpluginviewer
Installed SASL (server side) mechanisms are:
LOGIN ANONYMOUS PLAIN DIGEST-MD5 NTLM CRAM-MD5 EXTERNAL
       
[ .... ]

The description is pretty long. The information we need is the list of auxprop modules:

Installed auxprop mechanisms are:
sasldb
List of auxprop plugins follows
 
Plugin "sasldb" ,       API version: 4
        supports store: yes

OK, so we miss ldapdb. To activate it, we have to add a file into /usr/lib/sasl2/ that contains the location of the LDAP directory:

# echo "ldapdb_uri: ldap://localhost" > /usr/lib/sasl2/pluginviewer.conf

# cat /usr/lib/sasl2/pluginviewer.conf
ldapdb_uri: ldap://localhost

Now, check saslpluginviewer again. ldapdb should be available in the auxprop plugins.

# saslpluginviewer

[ ... ]

Installed auxprop mechanisms are:
ldapdb sasldb
List of auxprop plugins follows
Plugin "ldapdb" ,       API version: 4
        supports store: yes

[ ... ]

Back to imapd.conf

The ldapdb plugin is now available. Now, we need to tell imapd to connect to the LDAP directory using the ldapdb plugin. It also needs a username and a password. Make sure that the user you chose has the Proxy Authorization capability (as seen in the OpenLDAP chapter). In clear, user 'cyrus' must have an attribute like authzTo: ldap:///dc=example,dc=net??sub?(objectclass=inetOrgPerson).

Then, in imapd.conf, the following parameters will do the job:

# grep -E "sasl|ldap" /etc/imapd.conf |grep -v "^#"
sasl_pwcheck_method: auxprop
sasl_auxprop_plugin: ldapdb
sasl_auto_transition: no
sasl_ldapdb_uri: ldap://localhost
sasl_ldapdb_id: cyrus
sasl_ldapdb_pw: highsecuritypassword
sasl_ldapdb_mech: DIGEST-MD5

We connect from cyrus-imapd to ldap://localhost using user cyrus and SASL mechanism DIGEST-MD5.

Now restart cyrus with these parameters and try to login as user 'toto'.

# openssl s_client -connect localhost:993

* OK samchiel Cyrus IMAP4 v2.2.13-Debian-2.2.13-19 server ready
. login toto highsecuritypassword
. OK User logged in
. list "" "*"
. OK Completed (0.000 secs 1 calls)

That's a success ! Some more imap command here if you want to play around: Accessing IMAP email accounts using telnet

In /var/log/mail.info, you see the following:

May 10 13:11:28 samchiel cyrus/imap[4891]: login: localhost [127.0.0.1] toto plaintext User logged in

In /var/log/auth.log:

May 10 13:11:28 samchiel cyrus/imap[4891]: DIGEST-MD5 client step 2
May 10 13:11:28 samchiel cyrus/imap[4891]: DIGEST-MD5 client step 2
May 10 13:11:28 samchiel cyrus/imap[4891]: DIGEST-MD5 client step 3

And in /var/log/slapd.log:

May 10 13:11:28 samchiel slapd[2482]: conn=40 fd=16 ACCEPT from IP=[::1]:58180 (IP=[::]:389)
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=0 BIND dn="" method=163
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=0 RESULT tag=97 err=14 text=SASL(0): successful result:
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=1 BIND dn="" method=163
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=1 BIND authcid="cyrus" authzid="cyrus"
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=1 BIND dn="cn=cyrus administrator,ou=people,dc=example,dc=net" mech=DIGEST-MD5
 sasl_ssf=128 ssf=128
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=1 RESULT tag=97 err=0 text=
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=2 PROXYAUTHZ dn="cn=toto tata,ou=people,dc=example,dc=net"
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=2 EXT oid=1.3.6.1.4.1.4203.1.11.3
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=2 WHOAMI
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=2 RESULT oid= err=0 text=
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=3 PROXYAUTHZ dn="cn=toto tata,ou=people,dc=example,dc=net"
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=3 SRCH base="cn=toto tata,ou=people,dc=example,dc=net" scope=0 deref=0 fil
ter="(objectClass=*)"
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=3 SRCH attr=userPassword cmusaslsecretPLAIN
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=3 SEARCH RESULT tag=101 err=0 nentries=1 text=
May 10 13:11:28 samchiel slapd[2482]: conn=40 op=4 UNBIND
May 10 13:11:28 samchiel slapd[2482]: conn=40 fd=16 closed

As explained in the OpenLDAP chapter, your passwords must be stored in cleartext in the LDAP directory. This is necessary for DIGEST-MD5 to work.

Create the mailboxes

Now that we have a working authentication backend, to create the mailboxes, we need to use the Cyrus Administration tools.

# apt-get install cyrus-admin-2.2

This will install the 'cyradm' tool, which is in fact a Perl module.

cyradm - Cyrus administration shell, alter ego of Cyrus::IMAP::Shell                                                    
en/ressources/dossiers/cyrus/imapd.txt · Last modified: 2011/05/18 01:53 (external edit)
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0