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