Using PAM to allow access

Over the years PAM (Pluggable Authentication Modules) has become the standard on Solaris and Linux, and others like AIX and the known BSD’s are following. But by default all services that use PAM are allowing all users to use it unless the service itself takes action. So why not bring the authorization part to PAM and make the decision to allow access directly in PAM?

In this example we want to allow only access to Dovecot for users who are member of POSIX-group ac_mail. For this we use a module called pam_succeed_if which can verify if an user is in a certain group or not. Based on the standard PAM-file for a service we create a new file for Dovecot and added required line to do the authentication.

#%PAM-1.0
 
@include common-auth
auth required pam_succeed_if.so quiet user ingroup ac_mail
@include common-account
@include common-session

Also changing the Dovecot configuration to tell it to use the dovecot PAM-file.

passdb pam {
  args = session=yes dovecot
}

Now only users who are member of the ac_mail group can logon. This allows a system administrator to use LDAP for example so all machines have the same group information and all machines with the modified PAM configuration to use it. This way of allowing users to logon can also be used for other services that depend on PAM like Proftpd, OpenSSH or PostgreSQL for example.

Dovecot en verlopen berichten

Vroeger moest je met Courier en oudere versies van Dovecot nog handmatig mail verwijderen die was verlopen. Dit mede om oa Trash en Spam-folders te legen na een x-aantal dagen, maar zodra de mailstore begint te groeien begint dit steeds meer tijd te korten. Daarbij is niet elke implementatie van find even goed waardoor je alleen per 24 uur kan schonen. Maar met oa de komst van Dovecot 1.2 is de expire-plugin op orde en kan met een database backend wordt gekeken welke folders moeten worden geschoond.

De eerste aanpassing is om de configuratie file van Dovecot aan te passen met het volgende en Dovecot te herstarten.

protocol lda {
mail_plugins = expire ...
}
protocol imap {
mail_plugins = expire ...
}
dict {
expire = pgsql:/etc/dovecot/dovecot-dict-expire.conf
}
plugin {
expire = Trash 8 Trash/* 8 Junk 30
expire_dict = proxy::expire
}

Nu Dovecot weet wat de expire policy is voor oa de Junk-folder en de Trash-folder kan in een database wordt bijgehouden wanneer het volgende moment is dat er moet worden opgeruimd. Dit wordt gedaan wanneer er wijzigingen zijn aan de mailbox via de delivery agent of de imap-server. Als je lang genoeg wacht komt je vanzelf in de situatie dat de onderstaande test-commando’s aangeven en er daadwerkelijk kan worden opgeruimd.

$ sudo /usr/sbin/dovecot --exec-mail ext /usr/lib/dovecot/expire-tool.sh --test
Info: user1/Trash: stop, expire time in future: Tue Jan 26 17:15:48 2010
...
sleep
...
$ sudo /usr/sbin/dovecot --exec-mail ext /usr/lib/dovecot/expire-tool.sh --test
Info: user1/Trash: seq=1 uid=35624: Expunge
Info: user1/Trash: seq=2 uid=35625: Expunge
...
Info: user1/Trash: seq=89 uid=35721: Expunge
Info: user1/Trash: timestamp 1263658548 (Tue Jan 26 17:15:48 2010) ->; 1263671263 (Tue Jan 26 20:47:43 2010)
Info: user2/Trash: stop, expire time in future: Tue Jan 26 23:04:22 2010

Als je nu dit commando draait zonder de optie –test dan zullen de verlopen berichten daadwerkelijk worden verwijdert. Nu blijft de vraag hoe vaak je dit moet draaien en dit hangt af van belasting, maar ook hoeveel je kan bezuinigen aan schijfruimte of hoeveel zin het heeft om dit meer dan eens per dag te draaien.

IMAP migreren naar IMAP, deel 2

In september ging een posting over het migreren van IMAP en afgelopen weekend was het zover. Dovecot 1.0.15 werd upgrade naar 1.2.9 waardoor oa een bug in de delivery agent werd geholpen en bewust werd van namespace prefixen. Maar ook werd Sieve-ondersteuning verbetert en redelijk veel performance verbeteringen.

Een van de belangrijkste reden van de migratie was niet om Dovecot te upgraden, maar om mailbox-layout op een dermate manier te wijzigen dat Dovecot zoveel mogelijk out-of-the-box gebruikt kon worden. De INBOX-prefix moest dus verdwijnen en na veel testen met oa Evolution, Roundcube, Thunderbird en Microsoft Outlook 2007 kwam de volgende layout eruit rollen.

Trash
Drafts
INBOX.Test
Junk
Sent
INBOX

Een van de keuzes was om dubbele algemene mappen aan te maken, maar gezien het feit hoe makkelijk vele clients de nieuwe layout oppakte zijn de algemene mappen op het hoogste niveau geplaatst. Elke client lijkt hier redelijk goed mee om te gaan. Alleen Evolution behoefte in sommige speciale gevallen een opschoning van de lokale cache, maar in veel gevallen is het niet eens nodig. De keuze gaf ook de mogelijkheid om Dovecot zo in te stellen dat de algemene mappen altijd beschikbaar zijn en door de gebruiker eigenlijk niet weg te gooien zijn. De mappen worden bij het eerst volgende bericht weer automatisch aangemaakt en beschikbaar gesteld.

protocol lda {
mail_plugins = autocreate ...
}
plugin {
autocreate = Trash
autocreate2 = Junk
autocreate3 = Drafts
autosubscribe = Trash
autosubscribe2 = Junk
autosubscribe3 = Drafts
}

Door de vaste locatie en het automatisch beschikbaar stellen van mappen is het vooraf wegfilteren van Spam wel een optie geworden. En hoewel dit natuurlijk wel een heikel punt is, want de gebruiker heeft ineens geen invloed meer of spam opzij wordt gezet. Dit is misschien het belangrijkste punt wat van XS4ALL te leren is en dat is om niet te veel keuzes te geven, maar een veilige oplossing aan te bieden.

protocol lda {
mail_plugins = sieve ...
}
plugin {
sieve_before = /etc/dovecot/sieve/discard-junk.sieve
}

Door tegen de Sieve-plugin te vertellen dat hij voor elke lokale delivery van een mailbericht het discard-junk.sieve script moet afwerken. Nu zijn er vele voorbeelden in omloop met wildcard en dat men de wildcards telt, maar waarom niet gewoon de beslissing in bijvoorbeeld Amavisd-new laten maken en zoeken naar de juiste header.

require ["fileinto"];
# rule:[spamfilter]
if anyof (header :contains "X-Spam-Flag" "YES")
{
fileinto "Junk";
}

Wat nu eigenlijk nog overblijft is om het Sieve-script met de hand te compileren.

$ sudo sievec /etc/dovecot/sieve/discard-junk.sieve

Er zijn nog veel meer wijzigingen geweest, maar die komen binnenkort vanzelf aan de orde.

Sieve heeft ook zijn eigen poort

Sieve is een gestandaardiseerde filtertaal voor mailservers en clients. Oa Dovecot heeft een implementatie van hiervan waardoor mail op de server al kan worden gefilterd ipv op de client. Om eerlijk zijn ook de enige juiste plek IMHO, maar dat zijn details. Een andere bekende implementatie is binnen de Cyrus mailsuite en waar het precies fout is gegaan laat ik even in het midden. Heel lang is er een discussie geweest of Sieve wel de oplossing was, omdat er vele wegen waren of juist ontbraken om de regels op de mailserver te krijgen.

Gelukkig is er na lang gesteggel een redelijk veilige oplossing gekomen, maar iemand had poort 2000 uitgekozen om deze dienst op te laten draaien. Helaas was deze poort door IANA al vergeven aan Cisco SCCP om hun eigen XMMP/VoIP-oplossing op te laten luisteren. Uiteindelijk is poort 4190 uit IANA komen rollen als gereserveerde poort voor het Sieve-protocol. De migratie naar deze poort is nu begonnen en zal met Debian 6.0 waarheid worden voor veel Debian-gebruikers cq installaties. Bug 560094 heeft meer informatie.

IMAP migreren naar IMAP, deel 1

Vroeger was Courier redelijk de standaard voor diensten zoals POP3 en IMAP, maar er waren te veel beperkinge en de developers te moeilijk in de omgang. En totdat Dovecot aan de releasecandidates begon van 1.0 serie was er ook niet echt een alternatief. Een zeer goed bruikbaar alternatief welke nog hard in ontwikkeling is met mailboxen in verschillende namespaces zoals public en private, maar ook fatsoenlijk Sieve-ondersteuning.

Met de komst van Roundcube 0.3 als webmailclient zijn er nieuwe mogelijkheden beschikbaar gekomen welke nu langzaam benut kunnen worden. Ondersteuning voor Sieve is daar eentje van en met de belofte van de developers om ook ondersteuning in Evolution te bouwen komt serverside mailfitering voor oa de Linux-wereld en de normale gebruikers redelijk dichtbij. Geen geknutsel meer met .procmailrc of .maildrop files uploaden en hopen dat het werkt.

Helaas kwam er direct een probleem aan het licht bij het testen. Een probleem in de private namespace van de mailbox en eentje die eigenlijk voorkomt uit de migratie van Courier naar Dovecot. Om het gedrag van Courier te imiteren beschikt Dovecot over de mogelijkheid om standaard een prefix voor subfolders te zetten. Een actie om zo gebruikers transparante kunnen migreren, maar welke wel zorgt dat alle subfolders onderdeel zijn van de Inbox.

Om cache fouten in mailclients uit te sluiten is het gebruiken van een simpele client aan te raden. Simpeler dan de Perl-code hieronder bestaat bijna niet, maar doet precies wat het moet doen.

#!/usr/bin/env perl
use Net::IMAP::Client;
my $imap = Net::IMAP::Client->new(
server => 'mailhost',
user => 'username',
pass => 'password',
ssl => 1,
port => 993
) or die "Could not connect to IMAP server";
$imap->login or die('Login failed: '.$imap->last_error);
foreach ($imap->folders) { print $_."\n"; }

Bij de eerste run komt de output zoals die nu wordt aangeboden aan de mailclient.

INBOX.Trash
INBOX.Drafts
INBOX.Test
INBOX.Junk
INBOX.Sent
INBOX

Bij het uitschakelen van alleen de prefix-optie in Dovecot komt gelijk naar voren wat er gaat veranderen.

Trash
Drafts
Test
Junk
Sent
INBOX

Bij het controleren met verschillende mailclients komt direct naar voren dat hier wat slims gedaan moet gaan worden. Want de mailclients zien subfolders die ineens niet meer onderdeel zijn van de Inbox. Technisch gezien zijn ze nu ook geen onderdeel van de Inbox. Voor de standaard folders zoals Trash, Drafts, Junk en Sent zal dit niet echt een probleem gaan vormen, maar wel voor bv de folder Test.