#!/opt/perl-5.6.1/bin/perl

BEGIN {unshift (@INC,"/home/lab/bin/adtool/")};

use lib '/opt/perl/5.8.7/lib/5.8.7/sun4-solaris';
use lib '/opt/perl/5.8.7/lib/5.8.7';
use lib '/opt/perl/5.8.7/lib/site_perl/5.8.7/sun4-solaris';
use lib '/opt/perl/5.8.7/lib/site_perl/5.8.7';
use lib '/opt/perl/5.8.7/lib/site_perl';

use strict;
#use debug;
use BER;
use Net::LDAP;
use Net::LDAPS;
use Net::LDAP::LDIF;

#----------------------------------------------#
# Some standard settings...
#----------------------------------------------#

# Unix connection parameters
my $UNIX_COMP = 'lich';
my $LDAP_PASS = "";
my $LDAP_MANAGER = "";
my $LDAP_SERVER = "";

# AD connection parameters
my $WIN_DC     = 'nemeton.ics.uci.edu';

my $WINCAFILE = "/home/lab/bin/adtool/uciics.pem";
my $CAFILE = "/home/lab/bin/adtool/CA.crt";

# search parameters
my $BASE = "dc=ics,dc=uci,dc=edu";
my $SCOPE = "subtree";
my $ATTRS = ['uid', 'accounttype', 'fullname', 'surname', 'systemType', 'uciidnumber'];

#Common Windows account settings
my $NETWORK_DRV = 'H:';

#----------------------------------------------#
# Main
# Connects to unix ldap and queries for uid based on ID number
# Prints out user info, verifies it is correct, and changes password
#----------------------------------------------#

if ($#ARGV + 1 != 4)
{
	print "No workie!\n";
	exit(0);
}
else
{
	my $bindname = $ARGV[0];
	my $unix_username = "uid="."$bindname".",ou=people,dc=ics,dc=uci,dc=edu";
	my $win_username = "$bindname"."\@ics.uci.edu";

	my $unix_pass = $ARGV[1];
	my $option = $ARGV[2];


	if ($option eq "f")
	{
		my $idnumber = $ARGV[3];
		option_f($unix_pass,$unix_username,$idnumber);
	}
	exit(0);
}


#---------------------------------------#
# Finds a username based on the ID number
# Input: $unix_pass, $unix_username, $filter (which is the ID number)
# Output: prints out username if found, returns nothing
#---------------------------------------#
sub option_f
{
  my ($unix_pass,$unix_username,$idnumber) = @_;
  my $unix_ldap = open_LDAPS($unix_pass, $unix_username, $UNIX_COMP);

  my $filter = "(&(uciidnumber=$idnumber)(objectClass=icsAccount))";
  my $search = search_ldap($unix_ldap,$BASE,$SCOPE,$filter,$ATTRS);
  my @entries = $search->entries;

  if ($search->count != 1)
  {
    if ($search->count == 0)
    {
      print "Username not found.\n";
      print "Please try again or see system administrator.\n";
    }
    else
    {
      print "More than one username found for this user.\n";
      print "Please see system administrator.\n";
    }
    close_LDAP($unix_ldap);
    return 0;
  }

  foreach my $entry (@entries)
  {
    my $uid = $entry->get_value('uid');
    my @systemtype = $entry->get_value('systemType');
    my $fullname = $entry->get_value('fullname');
  
    print "Fullname:  $fullname\n";

    foreach my $system (@systemtype)
    {
      if ($system eq 'Windows' && $uid )
      {
        print "Windows username:  $uid\n";
      }
      elsif ($system eq 'UNIX' && $uid )
      {
        print "Unix username:  $uid\n";
      }
    }
  }

  close_LDAP($unix_ldap);
}

#--------------------------------------------------------------#
# Convert the zulu time to a large integer to set the expiration
# date for the user.
# Input:  windowsAccountExpireDate entry in LDAP
# Output: $sec,$min,$hours,$mday,$mon,$year of expiration
#--------------------------------------------------------------#
sub modify_zulu
{
  my ($zulu) = @_;
  my @time = split(//,$zulu);
  my $expire_time = "";

  if ($time[0] eq "2")
  {
    my $year = "$time[0]$time[1]$time[2]$time[3]";
    my $month = "$time[4]$time[5]";
    my $day = "$time[6]$time[7]";
    my $hours = "$time[8]$time[9]";
    my $min = "$time[10]$time[11]";
    my $sec = "$time[12]$time[13]";

    $expire_time = "$month/$day/$year";
  }
  elsif ($time[0] eq "0")
  {
    $expire_time = "Account never expires";
  }
  else
  {
    $expire_time = "Unknown.  Please email support.";
  }

  return $expire_time;
}



#----------------------------------------------------------
# Got code from Jeff Edgington at
# http://www.xray.mpe.mpg.de/mailing-lists/perl-ldap/2002-07/msg00003.html
# The password needs to be converted to Unicode before being BER encoded.
# Description: simple ascii to unicode/2bytechar conversion
# Syntax: $unicode = $ads->MakeUnicode($string);
#----------------------------------------------------------

sub MakeUnicode
{
  my ($string, $plainstring, $chr);

#$string is assigned arg[0] that is passed into the function
  $string = shift;

  $plainstring = "\"$string\"";

  #simple string=>unicode conversion
  my @tmp = ();
  foreach $chr ( split('', $plainstring) )
  {
     push(@tmp, $chr);
     push(@tmp, chr(0));
  }
  my $unistring = join("",@tmp);

  return $unistring;
}

#---------------------------------------------#
# Open an SSL connection LDAP server
# Input: Password, Username, Server
# Output: $LDAPS bound object
#---------------------------------------------#
sub open_ssl_ldap
{
  my ($bindpass,$bindname,$server) = @_;
  my $ldap = Net::LDAPS->new($server, port => '636', verify => 'require', cafile
 => $WINCAFILE) or die "$@";

  my $mesg = $ldap->bind( dn => $bindname, password =>$bindpass );

  if ($mesg->code)
  {
    print LOGFILE "OpenLDAP:  ".$mesg->error."\n";
    return $mesg;
  }
  return $ldap;
}

####################################################################
#
# Open a new connection to the ldap database via ssl
#
#  input:  bindpassword and optinaly bindname and ldap server
#  returns: ldap object.
#
####################################################################

sub open_LDAPS
{

  my ($bindpass,$bindname,$server) = @_;
  $bindpass = $LDAP_PASS if (!$bindpass);
  $bindname = $LDAP_MANAGER if (!$bindname);
  $server = $LDAP_SERVER if (!$server);
  #my $ldap = Net::LDAPS->new($server) or die "$@";
  #print "cafile $CAFILE\n";
  #print "server $server\n";
  my $ldaps = Net::LDAPS->new($server,
                         port => '636',
                         verify => 'require',
                         cafile => $CAFILE) or die "$@";

  my $mesg = $ldaps->bind( dn => $bindname, password =>$bindpass );
 
  if ($mesg->code)
  {
    print LOGFILE "OpenLDAP:  ".$mesg->error."\n";
    return 0;
  }
  return $ldaps;
 
}

####################################################################
#
#  closes the LDAP connection
#
#    input: nothing
#    returns:  nothing
#
####################################################################

sub close_LDAP
{

        return @_[0]->unbind;
}

#---------------------------------------#
# Search directory and dump all entries
# Input: bound $LDAP variable, BASE, FILTER, ATTRS
# Output: Return $search (object with all search results)
#---------------------------------------#
sub search_ldap
{
  my ($ldap,$base,$scope,$filter,$attrs) = @_;
  my $search = $ldap->search (
                         base   => $base,
                         scope  => $scope,
                         filter => $filter,
                         attrs => $attrs
                    );
# Rather than die, I have it return $search and any scripts using this
# function should use the if statement below and either die or print out an
# error message.
#  if (($search->code) && ($search->code != 9))
#  {die $search->error;}

#  foreach my $entry ($search->entries) {
#     $entry->dump;
#  }
  return $search;
}