<br>I didn't see many living examples of how to do this, so I thought<br>it might be useful to share.<br><br>In our system, we have an LDAP auth backend which can be broader<br>than the mailboxes on a system. We didn't have any luck with<br>
using pam_groupdn in pam_ldap.conf, so it is useful to use the PAM<br>module listfile. In pam.d/imap (same for pop or sieve) we would include:<br><br>auth required pam_listfile.so onerr=fail item=user sense=allow file=/cyrus/mailmgmt/mysystemlist<br>
<br>If you are not in this file list of users, but you have<br>authenticated against the backend OK, you won't get in.<br><br>Keeping that list of mailbox users updated is done by<br>a cron running the perl script following:<br>
<br><br>#!/usr/bin/perl -w<br><br># Maintain a list of valid mailboxes on mysystem for pam authentication purposes<br><br>use strict;<br>use Fcntl ':flock';<br><br># Global variables for filenames, etc.<br>my( $basedir );<br>
$basedir = "/cyrus/mailmgmt";<br><br>my( $PWD ) = $ENV{'PWD'};<br><br>chdir ( $basedir );<br><br># Other global variables<br>my( %mysystemboxes, $now);<br><br># Get the mailbox list from mysystem<br>%mysystemboxes = &get_mysystem_mailboxes( );<br>
<br>chdir( $PWD ) if ( $PWD );<br><br>exit 0;<br><br>#<br># It's all subroutines from here on out<br>#<br>#<br>#<br># Subroutine to get the mailbox list from mysystem.<br>#<br><br>sub get_mysystem_mailboxes( ) {<br> my( @mysystemboxes );<br>
# Get the list of mailboxes from <a href="http://mysystem.example.com">mysystem.example.com</a><br> @mysystemboxes = &get_mailbox_list( "localhost", "cyrusadm", "mypassword" );<br> if( grep { /^IMAP error:/ } @mysystemboxes ) {<br>
die "Error retrieving mailbox list from mysystem.\n@mysystemboxes\n";<br> }<br> # Dump the mailbox list to a file<br> open( SYSTEMBOXES, "> $basedir/mysystemlist " ) or die "Couldn't open file: $!\n";<br>
foreach( @mysystemboxes ) { print SYSTEMBOXES "$_\n"; }<br> print SYSTEMBOXES "cyrusadm\n";<br> close( SYSTEMBOXES ) or die "Couldn't close file: $!\n";<br> return %{ { map { $_ => 1 } @mysystemboxes } };<br>
}<br>#<br>#<br># Subroutine for an IMAP connection to get a mailbox list from a server<br>#<br>sub get_mailbox_list( $$$ ) {<br> use IMAP::Admin;<br><br> my( $server, $uid, $pwd ) = @_;<br> my( $client, $mailbox, @mailboxlist, @usernames, $username );<br>
<br> $client = IMAP::Admin->new( 'Server'=> "$server",<br> 'Login' => "$uid",<br> 'Password' => "$pwd",<br>
'CRAM' => 0<br> ) or<br> return "Couldn't create IMAP connection: $!\n";<br><br> @mailboxlist = $client->list( "user.*" ) or<br>
return "IMAP error: \n\t" . $client->error . "\n";<br><br> $client->close;<br> foreach $mailbox ( @mailboxlist ) {<br> push @usernames, ${ [ split( /\./, $mailbox ) ] }[1];<br> }<br>
<br> @usernames = keys %{ { map { $_ => 1 } @usernames } };<br><br> return( @usernames );<br>}<br><br><br>It would need some adjustment for different type of authentication or<br>separator.<br><br><br>