nginx pop imap and ldap
Øyvind Kolbu
oyvind.kolbu at usit.uio.no
Mon Aug 4 11:18:28 MSD 2008
On 2008-07-24 at 00:37, Leveau Stanislas wrote:
> Maybe that someone has already done it? ;)) a script for ldap??
Hi
Sorry for the late answer, but I've attached the perl auth daemon we use.
You probably want to change IMAPserver to mailHost, and look up the port as
well, but the changes should be quite straight forward.
In the mail section, add "auth_http localhost:9000/cgi-bin/auth;"
--
Øyvind Kolbu
Postmaster
Universitetet i Oslo
-------------- next part --------------
#!/local/bin/perl -w
# $Header: /usit/cvs/cvsroot/gt/postmaster/mail_config/proxy/site/bin/proxy_auth,v 1.9 2008/02/24 13:02:15 kolbu Exp $
use strict;
use Socket;
use POSIX;
use Getopt::Long;
use Net::LDAP;
use Net::hostent;
use Data::Dumper;
my $hostname = `hostname`;
chomp $hostname;
my $ldap_server = "ldap.uio.no";
my $target_dir = "/var/log/proxy_auth";
my $port = 9000;
my $uid = "nobody";
my $daemon = 1;
GetOptions("hostname=s" => \$hostname,
"port=s" => \$port,
"uid=s" => \$uid,
"targetdir=s" => \$target_dir,
"ldap=s" => \$ldap_server,
"daemon!" => \$daemon);
if( $port !~ /^\d+/ ) { $port = getservbyname($port,"tcp"); }
if( $uid !~ /^\d+/ ) { $uid = getpwnam($uid); }
$| = 1;
socket(SERVER, PF_INET, SOCK_STREAM,getprotobyname('tcp')) or
die "socket failed $!,";
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l",1)) or
die "setsockopt $!,";
bind(SERVER,sockaddr_in($port,INADDR_ANY)) or
die "bind $!,";
listen(SERVER,SOMAXCONN) or
die "listen $!,";
chdir $target_dir or die "chdir $target_dir failed,";
$> = $uid;
warn "UID $uid != $>," if $uid != $>;
if($daemon) {
my $pid = fork();
if($pid) {
exit(0);
}
close(STDIN);
close(STDOUT);
close(STDERR);
}
while(my $paddr = accept(CLIENT,SERVER)) {
my $pid = fork();
die "fork," unless defined($pid);
if($pid == 0) {
close(SERVER);
autoflush(*CLIENT);
my ($port,$iaddr) = sockaddr_in($paddr);
my $remote = sprintf("%s:%d",inet_ntoa($iaddr),$port);
my $messageid;
my %request = ();
while(<CLIENT>) {
s/\r//g;
last if /^\s*$/;
if(my ($key,$value) = /(\S+):\s(.+)/) {
$request{$key} = $value;
if ($key eq "Auth-Pass") {
$request{'Auth-Pass'} =~ s/\%([A-Fa-f0-9]{2})/pack("C",hex($1))/seg;
next;
}
}
}
my $imapserver;
my $remote_port;
my $user;
if($request{'Auth-User'} =~ /^[\w_-]+$/) {
my $uid = $request{'Auth-User'};
my $pwd = $request{'Auth-Pass'};
my @ret = ldap( base => "cn=targets,cn=mail,dc=uio,dc=no",
filter => "(&(target=$uid)(targetType=user))" );
for my $i (@ret) {
my ($k,$v) = @$i;
#print "$k: $v\n";
if($k eq "IMAPserver") {
$imapserver = inet_ntoa(gethost($v)->addr);
} elsif($k eq "dn") {
$user = auth($v,$pwd);
}
}
}
if($request{'Auth-Protocol'} eq "imap") {
$remote_port = 143;
}
if($request{'Auth-Protocol'} eq "pop3") {
$remote_port = 110;
}
if($imapserver and $remote_port and $user) {
l("main","ok",$request{'Auth-User'},$request{'Auth-Protocol'});
print CLIENT <<EOF
HTTP/1.0 200 OK
Auth-Status: OK
Auth-Server: $imapserver
Auth-Port: $remote_port
EOF
;
} elsif($imapserver and $remote_port) {
l("main","invalid password",
$request{'Auth-User'},$request{'Auth-Protocol'});
print CLIENT <<EOF
HTTP/1.0 200 OK
Auth-Status: Invalid password.
Auth-Wait: 3
EOF
;
} else {
l("main","invalid login",
$request{'Auth-User'},$request{'Auth-Protocol'});
print CLIENT <<EOF
HTTP/1.0 200 OK
Auth-Status: Invalid login.
Auth-Wait: 5
EOF
;
}
exit(0);
}
close(CLIENT);
1 while waitpid(-1,POSIX::WNOHANG) > 0;
}
sub autoflush {
my $fh = shift;
my $old = select($fh);
$| = 1;
select($old);
}
sub auth {
my $dn = shift;
my $password = shift;
my $uio = Net::LDAP->new($ldap_server)
or die "LDAP failed,";
$uio->start_tls();
my $m = $uio->bind( $dn,
password => $password );
return $m && ! $m->code();
}
sub ldap {
no strict 'vars';
no warnings 'once';
my %params = @_;
*uio = *LDAP::ldap;
*m = *LDAP::message;
my $errors = 0;
do {
eval {
if(not $uio) {
$uio = Net::LDAP->new ($ldap_server)
or die "LDAP->new $!,";
$m = $uio->bind() or die "bind,$!,";
}
$m = $uio->search (%params) or die "search $!,";
if($m->code) {
die "Search error: " . $m->code . ",";
}
};
if($@) {
$uio = undef;
&l("error","LDAP",%params,"error: $@");
select(undef,undef,undef,0.25);
if($errors++ > 10) {
die "This is not working. $@,";
}
}
} while($@);
return () unless ( defined( $m->entry));
my @ret = ( [ "dn", $m->entry->dn() ] );
for my $entry ($m->entries) {
for my $attr ( $entry->attributes ) {
for my $value (@{$entry->get_value($attr, asref => 1)}) {
push(@ret,[ $attr , $value]);
}
}
}
return @ret;
}
sub l {
my $pre = shift;
my @args = @_;
my $now = localtime();
my $timestr = POSIX::strftime("%F", localtime() );
open O,">>","$pre.log.$timestr" or die "Cannot open log '$pre.$timestr',";
if(not @args) {
carp("\@args not defined,");
} else {
chomp @args;
}
local $" = "] [";
print O "$now: [@args]\n";
close(O);
}
-------------- next part --------------
#!/bin/bash
# $Header: /usit/cvs/cvsroot/gt/postmaster/mail_config/proxy/etc/rc.d/init.d/proxy_auth,v 1.2 2007/12/20 13:01:43 kolbu Exp $
# proxy_auth This shell script takes care of starting and stopping proxy_auth
#
# chkconfig: 2345 70 30
# description: proxy_auth nginx authentication helper.
# processname: proxy_auth
# config:
# pidfile: /var/run/proxy_auth.pid
# Source function library.
. /etc/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -f /site/bin/proxy_auth ] || exit 0
start() {
echo -n $"Starting proxy_auth: "
mkdir -p /var/log/proxy_auth
chown nobody.nobody /var/log/proxy_auth
cd /var/log/proxy_auth || exit
daemon /site/bin/proxy_auth
RETVAL1=$?
echo
[ $RETVAL1 = 0 ] && touch /var/lock/subsys/proxy_auth
}
stop() {
# Stop daemons.
echo -n $"Shutting down proxy_auth: "
killproc proxy_auth
RETVAL1=$?
echo
[ $RETVAL1 = 0 ] && rm -f /var/lock/subsys/proxy_auth
}
restart() {
stop
start
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status proxy_auth
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit $RETVAL
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://nginx.org/pipermail/nginx/attachments/20080804/b00c2c1a/attachment.pgp>
More information about the nginx
mailing list