Penguin

How I set up exim(8) SMTP Auth under Debian, in two parts: the server and the client.

Server Setup

First make sure exim is working correctly doing everything but relaying.

Then create a /etc/pam.d/exim with:

 auth            required       pam_unix.so
 account         required       pam_permit.so
 session         required       pam_permit.so

You can replace pam_unix.so with pam_permit.so for testing but make sure you put it back when you are done

Then you need to edit /etc/exim/exim.conf and look for the authentication configuration section and add these two stanzas:

 plain:
        driver = plaintext
        public_name = PLAIN
        server_condition = "${if pam {$2:$3}{yes}{no}}"
        server_set_id = $2

 login:
        driver = plaintext
        public_name = LOGIN
        server_prompts = "WLUG Username:: : WLUG Password::"
        server_condition = "${if pam {$1:$2}{yes}{no}}"
        server_set_id = $1

These are both plain text drivers, you may wish to investigate using other drivers. Note, this won't work if your login or password contain :'s

NOTE: the above example refers to $2 and $3 for PLAIN auth, and $1 and $2 for LOGIN auth. This is correct! It is the only way PLAIN auth will work. If you find PLAIN auth isn't working, check that you are using $2 and $3 for the user and secret tokens, and not $1 and $2

In Exim 3, you will also need to make sure you have

 host_auth_accept_relay = *

(which is the default in debian)

this is accomplished in Exim 4 with

 hostlist host_auth_accept_relay = *

in the main section of the config file, which is there by default in FreeBSD.

and you will need to add

 exim_user = root

since you can't check passwords unless you are root, so you need to run exim as root. Pity.

Note however that if you run exim as root, the default config may disallow remote SMTP delivery when running as root, which kills the whole show. If this is the case, then when you send a message using the MUA you will see no error, but in the log you will see "User 0 set for remote_smtp transport is on the never_users list" and the message will get dropped.

To get around this, set the group ownership of /etc/shadow to something like "shadow" or some other group used only for this purpose, make the file group readable, as in:

 # groupadd shadow
 # chgrp shadow /etc/shadow
 # chmod g+r /etc/shadow

then add these lines to exim.conf (and remove exim_user=root)

 exim_user = mail
 exim_group = shadow

Testing

Now restart exim and type

 exim -bh localhost

try the commands

 EHLO localhost

exim should produce at least one line saying

 250-AUTH LOGIN PLAIN

then type

 AUTH LOGIN

exim will give you a base 64 encoded prompt ("WLUG Username:" from above). You then type in your username base64 encoded, it will prompt you with a base64 encoded prompt for your password, you enter the base64 encoded version of your password and it should say "Autentication successful" yay! type

 QUIT

to quit.

to investigate:

  • using CRAM-MD5

EximSmtpAuth with an LDAP Backend:

I use an LDAP backend for my mail, which works ok - except for some reason exim's smtp auth feature dies when trying to use pam_ldap. I figured I may as well use a native ldap query anyway, so here's what I came up with:

Exim is basically set up as mentioned above, except I still run exim as 'mail', not as 'root'. In this first instance, all my user accounts are under 'ou=People,dc=wlug,dc=org,dc=nz'. I have 'BASEDN' defined within exim as being my base dn, eg:

 BASEDN=dc=wlug,dc=org,dc=nz

 login:
   driver = plaintext
   public_name = LOGIN
   server_prompts = "LDAP Username:: : LDAP Password::"
   server_condition = "${lookup ldap{user=uid=$1,ou=People,BASEDN pass=$2 \
     ldap://localhost/BASEDN?uid?sub?(uid=$1)}{yes}fail}"
   server_set_id = $1

This makes use of the ldap lookups ability to set the binddn and password via the 'user' and 'pass' directives, before the ldap url. This means that the ldap lookup binds as the connecting user - if this succeeds, then the user/pass is valid. If it fails, then its not.

I also have a more complicated setup which has virtual domains, and each domain is under o=$domain,ou=Domains,BASEDN. UIDs are stored in the form user@domain (ie, thats what they login with). Here's how i got smtp auth working with that:

 login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "LDAP Username:: : LDAP Password::"
  server_condition = "${lookup ldap{user=${lookup \
     ldapdn{ldap://localhost/ou=Domains,BASEDN?dn?sub?(uid=$1)}} pass=$2 \
     ldap://localhost/ou=Domains,BASEDN?uid?sub?(uid=$1)}{yes}fail}"
  server_set_id = $1

This one differs slightly, in that in order to find the binddn, i first had to do a query to find the dn of the uid relating to user@domain.co.nz. As this is stored in o=$domain,ou=Domains..., and the $domain wont work in this case (its only populated when it gets an incoming mail, not for an auth session), I either needed a regex to split $1 into $user and $domain, or else to do this extra query. It works out ok though :). Note that the internal query is of type 'ldapdn' - this returns the dn of the result, and assumes there is only one match for uid=$1.


another setup

something maybe simpler, that supports multiple virtual domains:

login:

  driver = plaintext
  public_name = LOGIN
  server_prompts = "LDAP Username:: : LDAP Password::"
  server_condition = ${if ldapauth { user="${lookup ldapdn{ ldap://LDAPSERVER/BASEDN?dn?sub?(mail=$1)}}" pass=${quote:$2} ldap://LDAPSERVER/}{yes}{no}}
  server_set_id = $1

the ldapdn lookup retrieves the full dn of user identified by is "mail" ( this attribute can of course be changed ) and attempt a bind to the ldapserver, with the given dn. if it succeeds, then smtp auth is considered successful


Client Setup

All mail generated at my house gets sent to exim which runs on the router connected to my DSL line, my ISPs smarthost sucks (for various reasons), and being on a dynamic IP delivering directly is not such a smart idea. The solution is to smarthost to another server somewhere that will accept my mail using SMTP AUTH. In this case exim is acting as an SMTP AUTH client rather than a server.

You need the following configuration snippets, unfortunately the notes in the config file seem to suggest that you can only be a client to one SMTP AUTH server (or all the servers you authenticate to need to use the same username and password).

The setup is very simple, add the following line to your remote_smtp transport

  authenticate_hosts = <your smarthost here>

Then you simply need to add the following stanza to the authentication section at the end of your config file.

 login:
   driver = plaintext
   public_name = LOGIN
   client_send = ": <your username> : <your password>"

You probably also want to be using STARTTLS to encrypt the connection, otherwise your password is sent in plaintext. Under debian you need to make sure you have the exim-tls package installed.

For exim4 on Debian 3.1: Some smarthosts don't support encrypted login's so you have to enable plaintext logins. Create a file /etc/exim4/passwd.client containing the following:

yourmailserver:yourlogin:yourpassword

then add the line following 2 lines somewhere near the top of exim4.conf.template

# allow plain text smtp login
AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS=1

Update the configuration files by running

update-exim4.conf

Your server will now login to the smarthost using plaintext username and password as specified in the passwd.client file

Server Prompts

Some clients respond poorly to server prompts that don't match what they consider "correct". This problem will manifest itself by some clients being able to auth, and others not. to be safe, set

 server_prompts="Username:: : Password::"

An alternative way of achieving a similar end (allowing hosts to relay through you for a set period of time) is to use POPbeforeSMTP See also SMTPBestPractises?

The following authors of this page have not agreed to the WlugWikiLicense. As such copyright to all content on this page is retained by the original authors. The following authors of this page have agreed to the WlugWikiLicense.

PHP Warning

lib/plugin/WlugLicense.php:99: Warning: Invalid argument supplied for foreach()

lib/plugin/WlugLicense.php:111: Warning: in_array() [<a href='function.in-array'>function.in-array</a>]: Wrong datatype for second argument

lib/plugin/WlugLicense.php:111: Warning: in_array() [<a href='function.in-array'>function.in-array</a>]: Wrong datatype for second argument