#!/usr/bin/perl

#  Sample External Authenticaton program for CommuniGate Pro 
#  that employs LDAP "bind". 
#
#  See for more info:
#  <http://communigatepro.ru/CommuniGatePro/Security.html#External>


#  You may need to install the following modules:
#  ASN1 from <http://www.cpan.org/modules/by-module/Convert/>
#  LDAP from <http://www.cpan.org/modules/by-module/Net/>
 
use Net::LDAP;
use Text::ParseWords;

my $LDAPServerAddress =  '127.0.0.1';   # You should define this value


$| = 1;     #force STDOUT autoflush after each write

   
while(<STDIN>) {
  chomp;    # remove \n from the end of line
  my ($prefix,$method,$mode,$name,$password) = parse_line('\s+', 0, $_);

  unless($mode =~ /^\(.*\)$/) {
    $password=$name; $name=$mode;  
  }

  unless($prefix && $method && $name && $password) {  
    print "$prefix ERROR Expected: nnn VRFY user\@domain password\n";
    
  } elsif($method ne 'VRFY') {
    print "$prefix ERROR Only plain text passwords supported\n";    

  } else {
    my $errorMsg=checkPassword($name,$password);   
    if(defined $errorMsg) {
      print "$prefix ERROR $errorMsg\n";
    } else {
      print "$prefix OK\n";
    }  

  }  
}


sub checkPassword() {
  my ($user,$password)=@_;


  my $name,$domain=""; 
  if($user =~ /(.+)\@(.+)/) {  
    $name=$1;
    $domain=$2;
  } else {
    return "Full account name with \@ and domain part expected";
  }

  my $ldap = Net::LDAP->new($LDAPServerAddress,port=>389,timeout=>20)
    || return "Can't connect to $LDAPServerAddress via LDAP";

  my $result=$ldap->bind("uid=$name,cn=$domain",password=>$password)
    || return "Can't bind";

  $ldap->unbind();                        # unbind & disconnect

  $result->code && return $result->error; # return error message if failed
  return undef;                           # return "undef" on success
} 
