#!/usr/bin/perl -w
#  
#  authPAM.pl.  Version 1.0.
#
#  A simple external authentication program for CommuniGate Pro   
#  that uses PAM (Pluggable Authentication Modules) library.
#
#  Warning: On some systems this program will work properly only if
#  you are running as 'root'.
#
#  Please mail your comments to <support@stalker.com>
#
#  References:
#  [1] CGPro External Authentication
#        <http://www.stalker.com/CommuniGatePro/Security.html#External>
#  [2] The Linux-PAM System Administrators' Guide
#        <http://linux.ssc.nsu.ru/pam/html/pam.html>
#  [3] The Linux-PAM Application Developers' Guide
#        <http://linux.ssc.nsu.ru/pam/html/pam_appl.html>
#  [4] Perl interface for PAM.
#        <http://search.cpan.org/search?module=Authen::PAM>
#

use Authen::PAM;
$| = 1; #force STDOUT autoflush after each write

my ($seq,$vrfy,$mode,$user,$passw);

sub pam_conv_func {
  my @res;
  while ( @_ ) {
    my $msg_type = shift;
    my $msg = shift;
    #print $msg;
    push @res, 0;
    push @res, $passw;
  }
  push @res, PAM_SUCCESS;
  return @res;
}

while(<STDIN>) {

  ($seq,$vrfy,$mode,$user,$passw) = split(/ /);

  unless($mode =~ /^\(.*\)$/) {
    $passw=$user; $user=$mode;  
  }
  
  unless($seq && $vrfy && $user && $passw) {
    print "$seq ERROR Wrong arguments\n";
  } elsif($vrfy ne 'VRFY') {
    print "$seq ERROR Only clear text passwords supported\n";
  } else {
    my ($res,$pamh);
    chomp($passw);
    if($user =~/(.+)\@.+/) {$user=$1;}  #strip the domain name if necessary
    if(($res=pam_start("login", $user, \&pam_conv_func, $pamh))!=PAM_SUCCESS ||
       ($res=pam_authenticate($pamh, 0))!=PAM_SUCCESS ||
       ($res=pam_end($pamh, 0))!=PAM_SUCCESS) {
      print "$seq ERROR ".pam_strerror($pamh,$res)."\n";
    } else {
      print "$seq OK \n";
    }   
  }

}
