#!/usr/bin/perl

use Net::LDAP;
use Net::LDAP::Search;
use Getopt::Std;
use POSIX;

$vers="1.1.00.beta";

sub ldap_err
{
	my $sub=$_[0];
	my $rval=$_[1];
	my $token=$_[2];
	printf("%s: %s:\n\t%s: %s\n\t%s: %s (%s)\n\t%s: %s\n\t%s:\n\n%s\n",
		$arg0, $sub, "value", $token, 
		"mesg",$rval->error_name,$rval->code,
		"m id",$rval->mesg_id,
		"text",$rval->error_text)
}

sub get_current_user
{
	my $sub=(caller(0))[3];
	$clogin=getlogin();

	#$template = "s i A32 A6 A32 A256 b55";
    	#my ($type, $tpid, $line, $itabid, $name, $host, $time) = unpack $template, $buf;
}

sub read_ldap_conf
{
	open(LDAPCONF,"<","/etc/ldap.conf");
	%ldapconf=map {/([^\s+ ]*?)\s+/,[split(/\s+/)]} <LDAPCONF>;
	close(LDAPCONF);

	$host=$ldapconf{'uri'}[1];
	$base=$ldapconf{'base'}[1];
	$rootbinddn=$ldapconf{'rootbinddn'}[1];
	$binddn=$ldapconf{'binddn'}[1];
	$bindpw=$ldapconf{'bindpw'}[1];
}

sub show_conf
{
	print("$arg0: conf: uri $host\n");
	print("$arg0: conf: ldap base: $base\n");
	print("$arg0: conf: binddn: $binddn\n");
	print("$arg0: conf: ldap proxy pw: $bindpw\n");
}


sub save_password_old
{
	my $passwd=$_[0];
	my $ldap_entry=$_[1];

	$home_d=$ldap_entry->get_value("homeDirectory");
	if (!$home_d)
	{
		$home_d=$ldap_entry->get_value("unixHomeDirectory");
	}
	if (!$home_d)
	{
		printf("%s: %s: error: cannot detemine home - password cannot be saved\n",$arg0,$login); # if ($opt_d);
		return(1);
	}
	$p4pass_f="$home_d/.p4-$arg0";
	$rval=open(P4PASS,">",$p4pass_f);
	if (!$rval)
	{
		printf("%s: error: cannot open password file: %s: %s\n",$arg0,$p4pass_f,$!); # if ($opt_d);
		return(1);
	}
	chmod(S_IRUSR|S_IWUSR,$p4pass_f);
	printf(P4PASS "%s",$passwd);
	print("$arg0: password for $login written to $p4pass_f\n") if ($opt_d);
	close(P4PASS);
}

$arg0=$0;
$arg0=~(s%.*/%%);

$cfe_vars_f='/etc/bch/conf/vars.pli';
my $sub=(caller(0))[3];
$sub="main" if (!$sub);

my ($os_type,$hostname,$os_ver,$kern_info,$arch_type) = POSIX::uname();

getopts('du:p:r:s');
if ($?)
{
	die "FATAL: options: $!\n";
}

if (-r $cfe_vars_f)
{
	do $cfe_vars_f;
}

&read_ldap_conf;
&show_conf if ($opt_d);

$login=$opt_u if ($opt_u);
$password=$opt_p if ($opt_p);
$p4root=$opt_r if ($opt_r);

if (!$password)
{
	$password = <STDIN>;
	$password =~ s/\n//;
}

if (!$login)
{
	$login=$ARGV[0];
}

if (!$login)
{
	printf(STDERR "%s: error: FATAL: no login specified\n",$arg0);
	exit(1);
}

if (!$password)
{
	printf(STDERR "%s: error: FATAL: no password specified\n",$arg0);
	exit(1);
}

$p4root="/data/perforce-main" if (!$p4root);

if (!$host)
{
	printf(STDERR "%s: error: FATAL: no LDAP host found/specified\n",$arg0);
	exit(1);
}

if (!$base)
{
	printf(STDERR "%s: error: FATAL: no LDAP base found/specified\n",$arg0);
	exit(1);
}

if (!$binddn)
{
	printf(STDERR "%s: error: FATAL: no LDAP bind DN found/specified\n",$arg0);
	exit(1);
}

if (!$bindpw)
{
	printf(STDERR "%s: error: FATAL: no LDAP bind password found/specified\n",$arg0);
	exit(1);
}

$ldap = Net::LDAP->new ( $host );

$mesg=$ldap->bind("$binddn",password => "$bindpw",version => 3);
if ($mesg->code)
{
	ldap_err($sub,$mesg,"bind") if ($opt_d);
	exit(1);
}
$search = $ldap->search (
	base => "$base",
	scope => "sub",
	filter => "( &(objectClass=user) (|(uid=$login)(sAMAccountName=$login))  )",
	attrs => [ 'uid', 'uidNumber', 'sAMAccountName', 'homeDirectory', 'unixHomeDirectory' ]
);
if ($search->count == 0)
{
	printf("%s: %s: error: FATAL: no such user\n",$arg0,$login);
	exit(1);
}
elsif ($search->count > 1)
{
	printf("%s: error: FATAL: %s: more than one entry found\n",$arg0,$login);
	exit(1);
}

my $entry = $search->entry ( 0 );
$dn=$entry->dn();
print("$arg0: dn found: $dn\n") if ($opt_d);
$mesg=$ldap->bind("$dn",password => "$password",version => 3);
if ($mesg->code)
{
	#ldap_err($sub,$mesg,"bind") if ($opt_d);
	printf("%s: authentication failed for %s: %s\n",$arg0,$login,$mesg->error_text);
	exit(1);
}
else
{
	print("$arg0: authentication for $login: success\n") if ($opt_d);
}

save_password($password,$entry) if ($opt_s);

$mesg=$ldap->unbind;
if ($mesg->code)
{
	ldap_err($sub,$mesg,"unbind") if ($opt_d);
}
exit(0);