nginx pop imap and ldap
Øyvind Kolbu
oyvind.kolbu at usit.uio.no
Wed Mar 17 23:44:37 MSK 2010
On 2010-03-17 at 10:06, Anh tuan Truong wrote:
> Sorry, but I can not see the attachment.
> I know this article has been posted for a long time but the topic is so
> interesting for me.
>
> Could you please check and share me the configuration details.
OK, they are attached again.
--
Øyvind Kolbu
-------------- 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
More information about the nginx
mailing list