# LDAP Library  + PerLDAP stuff
# STTA Rev. 1.3 Copyright (c) 2001-2002 Jesús Pérez Lorenzo  --- license GNU GPL 

$conn = "";
$conncache = "";
$conncache2 = "";

use Mozilla::LDAP::Conn;                # Main "OO" layer for LDAP
use Mozilla::LDAP::Utils;               # LULU, utilities.

use strict;
no strict "vars";

sub connect
{
   if ( "$ldap_server" eq "1" ) {
         $conn = new Mozilla::LDAP::Conn ($config{ldap_server}, $config {ldap_port},
               $config{ldap_user}, $config{ldap_passwd});
         $line_conn=$config{ldap_server}.":".$config {ldap_port};
   } elsif ( "$ldap_server" eq "2" ) {
         $conn = new Mozilla::LDAP::Conn ($config{ldap2_server}, $config {ldap2_port},
               $config{ldap2_user}, $config{ldap2_passwd});
         $line_conn=$config{ldap2_server}.":".$config {ldap2_port};
   }
   #&error("Couldn't connect to LDAP server") unless $conn;
   if (! $conn) {
        $err=$text{ldap_conerr};
        &ldap_logerr("connect"); 
        &footHere; exit  
   }
}

sub connect_cache
{
   if ( "$ldapcache_server" eq "1" ) {
        $conncache = new Mozilla::LDAP::Conn ($config{ldapcache_server},
           $config {ldapcache_port},$config{ldapcache_user}, $config{ldapcache_passwd});
         $line_conn=$config{ldapcache_server}.":".$config {ldapcache_port};
   } elsif ( "$ldapcache_server" eq "2" ) {
        $conncache = new Mozilla::LDAP::Conn ($config{ldapcache2_server},
           $config {ldapcache2_port},$config{ldapcache2_user}, $config{ldapcache2_passwd});
         $line_conn=$config{ldapcache2_server}.":".$config {ldapcache2_port};
   }
   #&error("Couldn't connect to LDAP server") unless $conncache;
   if (! $conncache) {
        &ldapcache_logerr("connect"); 
        &footCacheHere; exit  
   }
}

# add_cache_ou ($tta3tier)
# following $tta3tier->{ObjType}[0] ( usr | ou | app | grpapps | host | grphosts | domain ) 
# add  obj  as OU 
# in ldapcache_base" as DN   
# returning $status_con as ( 0=OK, -1 = error, -2 = missing elements )
#
sub add_cache_ou
{
  	local (%obj) = @_;
	my ($status_con,$dn,$ouname,$entry);

	$status_con = 0;
    	if (!$obj->{target}) { return -2 };
        $objdescrip=&scan_objdescrip(0,\%$obj);
  	if ($objdescrip eq "" ) { $objdescrip= "organization"};
    	$dn = $obj->{target}.",".$config{ldapcache_base};
    	$entry = $conncache->newEntry ();
    	$entry->setDN ($dn);
        $entry->{objectclass} = ["top", "organizationalunit"];
    	$entry->{ou} = [$obj->{target}];
    	$entry->{description} = [$objdescrip];
    	$conncache->add ($entry);
 	if ($err = $conncache->getErrorCode ()) {
	    $status_con=-1;
    	}; 
        $dn_cache=$dn;
        &ldapcache_logerr("add ou"); 
        return $status_con;
}

# cache_obj($tta3tier)
# following $tta3tier->{action} ( add or mod ) 
# add or update  $tta3tier->{origin} 
# in $tta3tier->{target},"ldapcache_base" as DN for the OU  
# returning $status_con as ( 0=OK, -1 = error, -2 = missing elements )
#
sub cache_obj
{
  	my (%tta3tier) = @_;
  	local (%obj) = @_;
	my ($status_con,$objtype,$dn,$ou,$dn_t,$entry);
        my (@lista_targets) = ($tta3tier->{target},$tta3tier->{oudn});
        local (@dn_lin);
        my ($dntarget,$elem,$lnum,$dn_t);

	$status_con = 0;
    	if (!$tta3tier->{origin} ||  !$tta3tier->{target} ) { return -2 };

        if ( $tta3tier->{action} ne "add" && $tta3tier->{action} ne "mod" ) { return -2 };
    	if ( $tta3tier->{oudn} eq "default" ) {
    	     $dn_t = $tta3tier->{target};
        } else {
    	     $dn_t = $tta3tier->{oudn}.",".$tta3tier->{target};
        }
    	$dn = $tta3tier->{origin}.",".$dn_t.",".$config{ldapcache_base};
        $objtype=$tta3tier->{objetype};
        if ( $tta3tier->{action} eq "add" ) {
                # scanning for target .... and full_target
                $objtype=$tta3tier->{objetype};;
                $dn_t = $config{ldapcache_base};
                foreach $elem (@lista_targets) {
                   @dn_lin = split(/,/, $elem);
                   for ( $lnum= $#dn_lin ; $lnum >= 0 ; $lnum-- ) {
    	               if ( "$dn_lin[$lnum]" ne "default" ) {
    	                   $ou=$dn_lin[$lnum];
    	                   $dn_t = $ou.",".$dn_t;
	                   $dntarget=&sel_cache_obj($dn_t);
                           if (!$dntarget) { 
                                $objdescrip=&scan_objdescrip(2,
                                      $objtype,$dn_t,$tta3tier->{target});
                                if ($objdescrip eq "" ) { $objdescrip= "organization"};
                                $entry = $conncache->newEntry ();
                                $entry->setDN ($dn_t);
                                $entry->{objectclass} = ["top", "organizationalunit"];
                                $entry->{ou} = [$ou];
                                $entry->{description} = [$objdescrip];
                                $conncache->add ($entry);
                                if ($err = $conncache->getErrorCode()) {$status_con=-1;};
                                $dn_cache=$dn_t;
                                &ldapcache_logerr("add ou $dn_t"); 
                           };
                        };
                        if ($status_con ne 0 ) { return -2 };
                   }
                   if ($status_con ne 0 ) { return -2 };
                   $objtype="ou";
                }
                if ( $tta3tier->{login}.length gt 0 ) {                          
                     # Redy to go
                     $dn_cache=$dn;
	             $entry = $conncache->newEntry ();
    	             $entry->setDN ($dn);
       		     $entry->{objectclass} = ["ttacacheapp"];
                     $entry->{cn} = [$tta3tier->{origin}];
                }
        } elsif ( $tta3tier->{action} eq "mod" ) {
                $dn_cache=$dn;
                $entry = $conncache->browse ($dn); 
		if ($err = $conncache->getErrorCode ()) {
                    &ldapcache_logerr("browse obj");       
		    return -1;
    		}
                &ldapcache_logerr("browse obj");       
        }
        $entry->{tta3tierdomain} = [$tta3tier->{domain}];
	$entry->{tta3tierlogin} = [$tta3tier->{login}];
	$entry->{tta3tierpassword} = [$tta3tier->{password}];
	$entry->{tta3tierstringcmd} = [$tta3tier->{stringcmd}];
	$entry->{tta3tiertitle} = [$tta3tier->{title}];
	$entry->{tta3tieroudn} = [$tta3tier->{oudn}];
	$entry->{tta3tierappkey1} = [$tta3tier->{appkey1}];
	$entry->{tta3tierappkey2} = [$tta3tier->{appkey2}];
	$entry->{tta3tierappkey3} = [$tta3tier->{appkey3}];
	$entry->{tta3tierappkey4} = [$tta3tier->{appkey4}];
	$entry->{tta3tierappkey5} = [$tta3tier->{appkey5}];
	$entry->{tta3tierappkey6} = [$tta3tier->{appkey6}];
	$entry->{tta3tiermaxsess} = [$tta3tier->{maxsess}];
	$entry->{tta3tierticketstatus} = [$tta3tier->{ticketstatus}];
	$entry->{tta3tierticketcounter} = [$tta3tier->{ticketcounter}];
	$entry->{tta3tierendticket} = [$tta3tier->{endticket}];
	$entry->{tta3tierdoifendticket} = [$tta3tier->{doifendticket}];
        if ( $tta3tier->{action} eq "add" && $tta3tier->{login}.length gt 0 ) {
             $conncache->add ($entry); 
	     if ($err = $conncache->getErrorCode ()) { $status_con=-1; }; 
             &ldapcache_logerr("add obj"); 
        } elsif ( $tta3tier->{action} eq "mod" && $tta3tier->{login}.length gt 0 ) { 
             $conncache->update ($entry);
	     if ($err = $conncache->getErrorCode ()) { $status_con=-1; }; 
             &ldapcache_logerr("update obj"); 
        };
#  &print_tta3tier(\%$tta3tier);  # debugging trace 
        return $status_con;
}

sub del_cache_obj
{
    my ($dn) = @_;
    my ($status_con,$dn_cn);
 
    $status_con = 0;
    # scanning for subentries "cn" in $dn 
    $entry = $conncache->search ($dn, "subtree", "(cn=*)" );
    while ($entry) {
               $dn_cn = $entry->getDN ();
               $entry = $conncache->nextEntry ();
    	       $conncache->delete ($dn_cn);
    }  
    $dn_cache=$dn;
    $conncache->delete ($dn);
    if ($err = $conncache->getErrorCode ()) { $status_con=-1; };
    &ldapcache_logerr("delete tree obj"); 
    return $status_con;
}

sub del_cache_ou
{
    my ($dn) = @_;
    my ($status_con,$dn_cn);
 
    $status_con = 0;
    # scanning for subentries "cn" in $dn 
    $entry = $conncache->search ($dn, "subtree", "(cn=*)" );
    while ($entry) {
               $dn_cn = $entry->getDN ();
               $entry = $conncache->nextEntry ();
    	       $conncache->delete ($dn_cn);
    }
    # scanning for subentries "ou" in $dn 
    $entry = $conncache->search ($dn, "subtree", "(ou=*)" );
    while ($entry) {
               $dn_cn = $entry->getDN ();
               $entry = $conncache->nextEntry ();
    	       $conncache->delete ($dn_cn);
    }
    $entry = $conncache->browse ($dn);
    if ($entry)  {
        $conncache->delete ($dn);
        if ($err = $conncache->getErrorCode ()) { $status_con=-1;}
    };
    $dn_cache=$dn;
    &ldapcache_logerr("delete tree obj"); 
    return $status_con;
}

sub del_ldap_obj
{
    local ($status_ldap);
 
    $status_ldap=0;
    $ldapcache_server=1;
    &connect_cache ();
    if ( &del_cache_ou($dn) eq 0 ) {
         if ( $config{ldapcache2_server}.length gt 0 ) {
              $ldapcache_server=2;
              &connect_cache ();
              if (&del_cache_ou($dn) ne 0 ) {
                  &err_replication();
                  $status_ldap=1;
              }
         }
    } else {
      $status_ldap=1;
    }
  return $status_ldap;
}

sub del_obj
{
     my ($status_con);
     $status_con = 0;
   
     $dn_cache=$dn;
     $entry = $conncache->browse ($dn);
     if ($err = $conncache->getErrorCode ()) {
            if ( $debug gt 0 ) {
                 if ( !$DebugFile ) {
                       print "<hr>\n";
                       print "<b> del ($dn): $err:".$conncache->getErrorString ()."</b>\n";
                       print "<hr>\n";
                 } else {
                       print DebugFile "del ($dn): $err:".$conncache->getErrorString ()."\n";
                 }
            }
            $status_con=-1;
            &webmin_log("ldap-cache", "browse", $dn, $err);
            &ldapcache_logerr("browse obj"); 
     } else {
            $conncache->delete ($entry);
            if ($err = $conncache->getErrorCode ()) {
                $status_con=-1;
            }
            &ldapcache_logerr("delete obj"); 
     }
     return $status_con;
}


sub mod_obj
{
     my ($status_con);
     $status_con = 0;
 
     $dn_cache=$dn;
     $entry = $conncache->browse ($dn);
     if ($err = $conncache->getErrorCode ()) {
            $status_con=-1;
            &ldapcache_logerr("browse obj"); 
     } else {
            $entry->{tta3tierdomain} = [$in{tta3tier_domain}];
            $entry->{tta3tierlogin} = [$in{tta3tier_login}];
            $entry->{tta3tierpassword} = [$passwdcoded];
            $entry->{tta3tierstringcmd} = [$in{tta3tier_stringcmd}];
            $entry->{tta3tiertitle} = [$in{tta3tier_title}];
            $entry->{tta3tieroudn} = [$in{tta3tier_oudn}];
            $entry->{tta3tierappkey1} = [$in{tta3tier_appkey1}];
            $entry->{tta3tierappkey2} = [$in{tta3tier_appkey2}];
            $entry->{tta3tierappkey3} = [$in{tta3tier_appkey3}];
            $entry->{tta3tierappkey4} = [$in{tta3tier_appkey4}];
            $entry->{tta3tierappkey5} = [$in{tta3tier_appkey5}];
            $entry->{tta3tierappkey6} = [$in{tta3tier_appkey6}];
            $entry->{tta3tiermaxsess} = [$in{tta3tier_maxsess}];
            $entry->{tta3tierticketstatus} = [$in{tta3tier_ticketstatus}];
            $entry->{tta3tierticketcounter} = [$in{tta3tier_ticketcounter}];
            $entry->{tta3tierendticket} = [$in{tta3tier_endticket}];
            $entry->{tta3tierdoifendticket} = [$in{tta3tier_doifendticket}];
 
            $conncache->update ($entry);
            if ($err = $conncache->getErrorCode ()) { $status_con=-1; }
            &ldapcache_logerr("update obj"); 
     }
     return $status_con;
}

sub sel_cache_obj
{

    my ($dn) = @_;
 
    my ($entry);
 
    $entry = $conncache->browse ($dn);
    return $entry;
}

sub add_usr
{
    my ($status_con);
    $status_con = 0;

    $entry = $conn->newEntry ();
    $entry->setDN ($dn);
    if ( "$config{ldap_type}" eq "OpenLDAP" ) {
        $entry->{objectclass} =
             ["top", "person", "organizationalperson", "inetorgperson", "uidObject"];
    } else {
        $entry->{objectclass} =
             ["top", "person", "organizationalperson", "inetorgperson"];
    }
    $entry->{userpassword} = [$password];
    if ( "$config{ldap_type}" eq "OpenLDAP" ) {
         $entry->{description} = [$organizationname];
    } else {
         if ( "$where" ne "" ) { $entry->{displayname} = [$where]; }
         $entry->{departmentnumber} = [$organizationname];
    }
    if ( "$surname" ne "" ) { $entry->{sn} = [$surname]; }
    $entry->{cn} = [$username];
    $entry->{uid} = [$username];
    if ( "$email" ne "" ) { $entry->{mail} = [$email];}
    $conn->add ($entry);
    if ($err = $conn->getErrorCode ()) { $status_con=1; } 
    &ldap_logerr("add usr"); 
    return $status_con;
}

sub mod_usr
{
    my ($status_con);
    $status_con = 0;

    # assume the uid (or the DN) was not changed
    # no change for cn username --- password in other form
    $entry = $conn->browse ($dn);
    if ($err = $conn->getErrorCode ()) {
        $status_con=1;
        &ldap_logerr("browse usr"); 
    }
    else {
            $entry->{mail} = [$in{email}];
            $entry->{sn} = [$in{surname}];
            $entry->{displayname} = [$in{descrip}];
            $conn->update ($entry);
            if ($err = $conn->getErrorCode ()) { $status_con=1; } 
            &ldap_logerr("update usr"); 
    }
    return $status_con;
}

sub mod_usr_password
{
    my ($status_con);
    $status_con = 0;

    # assume the uid (or the DN) was not changed
    # no change for ou ouname ---
    $entry = $conn->browse ($dn);
    if ($err = $conn->getErrorCode ()) {
        $status_con=1;
        &ldap_logerr("browse usr"); 
    }
    else {
           $entry->{userpassword} = [$password];
           $surname=$entry->{sn};
           $conn->update ($entry);
           if ($err = $conn->getErrorCode ()) { $status_con=1; }
           &ldap_logerr("update passwd "); 
    }
    return $status_con;
}

sub del_usr
{
    my ($status_con);
    $status_con = 0;

    $conn->delete ($dn);
    if ( $err = $conn->getErrorCode () ) { $status_con=1; }
    &ldap_logerr("delete usr"); 
    return $status_con;
}

sub add_ou
{
    my ($status_con);
    $status_con = 0;

    $entry = $conn->newEntry ();
    $entry->setDN ($dn);
    $entry->{objectclass} = ["top", "organizationalunit"];
    $entry->{ou} = [$ouname];
    $conn->add ($entry);
    if ($err = $conn->getErrorCode ()) { $status_con=1; }
    &ldap_logerr("add ou"); 
    return $status_con;
}

sub mod_ou
{
    my ($status_con);
    $status_con = 0;

    # assume the uid (or the DN) was not changed
    # no change for ou ouname ---
    $entry = $conn->browse ($dn);
    if ($err = $conn->getErrorCode ()) {
        $status_con=1;
        &ldap_logerr("browse ou"); 
    } else {
            $entry->{description} = [$in{descrip}];
            $conn->update ($entry);
            if ($err = $conn->getErrorCode ()) { $status_con=1; }
            &ldap_logerr("update ou"); 
    }
    return $status_con;
}

sub del_ou
{
    my ($status_con);
    $status_con = 0;

    $conn->delete($dn);
    if ($err = $conn->getErrorCode()) { $status_con=1; }
    &ldap_logerr("delete ou"); 
    return $status_con;
}

# This function exist to allow other actions further than to print a messages
# just by example we can gently exit CGI by doing " &footHere; exit " 
# All replication return not 0 will cross this funcion.
sub err_replication
{
#   if ( $debug gt 0 ) {
        if ( !$DebugFile ) {
            print "<b> ($dn):".$text{'replica_err'} ."-->".$line_conn."</b>\n";
            print "<b> ".$text{'replica_msg'} ."</b>\n";
        } else {
            print DebugFile "($dn):".$text{'replica_err'} ."-->".$line_conn."\n";
            print DebugFile "$text{'replica_msg'}\n";
        }
#   }
}

sub ldapcache_logerr
{
    my ($msgstr) = @_;
    my ($msg_str)="";
    my ($msg_err)="";
    my ($line_conn);

  $msg_str="$text{task}=>'$msgstr'"; 
  if ( $search_cmd ) { $msg_str.="||$search_cmd"; };
  if ( "$ldapcache_server" eq "1" ) {
         $line_conn=$config{ldapcache_server}.":".$config {ldapcache_port};
  } elsif ( "$ldapcache_server" eq "2" ) {
         $line_conn=$config{ldapcache2_server}.":".$config {ldapcache2_port};
  }
  if ( $err ) {
       if (! $conncache) {
         $msg_err.="error=>'".$text{'ldapcache_admerr'}."'\nerror=>'".$text{'ldapcache_connerr'}."'";
       } else {
         $msg_err.="'$err=>".$conncache->getErrorString ()."'";
       }
       if ( $debug gt 0 ) {
            if ( !$DebugFile ) {
                  print "<hr>\n";
                  print "<i> $line_conn</i>\n";
                  print "<b> $msg_str $msg_err</b>\n";
                  print "<hr>\n";
            } else {
                  print DebugFile "$line_conn\n";
                  print DebugFile "$msg_str\n";
                  print DebugFile "$msg_err\n";
            }
       }
       $msg_err=~s/\\n/\|\|/g; 
       $msg_str.="||$msg_err";
       $line_conn.=" err=$err";
  }
  &webmin_log($line_conn,"ldapcache","ldap=>'$line_conn'||$msg_str||dn=>'$dn_cache'",$entry);
}

sub ldap_logerr
{
    my ($msgstr) = @_;
    my ($msg_str)="";
    my ($msg_err)="";
    my ($line_conn);

  $msg_str="$text{task}=>'$msgstr'"; 
  if ( $search_cmd ) { $msg_str.="||$search_cmd"; };
  if ( "$ldap_server" eq "1" ) {
         $line_conn=$config{ldap_server}.":".$config {ldap_port};
  } elsif ( "$ldap_server" eq "2" ) {
         $line_conn=$config{ldap2_server}.":".$config {ldap2_port};
  }
  $line_conn.=" $msgstr";
  if ( $err ) {
       if (! $conn) {
         $msg_err.="error=>'".$text{'ldap_admerr'}."'\nerror=>'".$text{'ldap_connerr'}."'";
       } else {
         $msg_err.="'$err=>".$conn->getErrorString ()."'";
       }
       if ( $debug gt 0 ) {
            if ( !$DebugFile ) { 
                  print "<hr>\n";
                  print "<i> $line_conn</i>\n";
                  print "<b> $msg_err</b>\n";
                  print "<hr>\n";
            } else {
                  print DebugFile "$line_conn\n";
                  print DebugFile "$msg_str\n";
                  print DebugFile "$msg_err\n";
            }
       }
       $msg_err=~s/\\n/\|\|/g; 
       $msg_str.="||$msg_err";
       $line_conn.=" err=$err";
  }
  &webmin_log($line_conn,"ldap","ldap=>'$line_conn'||$msg_str||dn=>'$dn'",$entry);
}
