#!/usr/bin/perl
##################################################
# Wilmer Jaramillo M. <wilmer@fedoraproject.org>
# Exporta las entradas desde MS Active Directory
# hacia un Fedora Directory Server.
# ads2fds.pl
##################################################

use Net::LDAP;
use Net::LDAP::Control::Paged;
use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED );

#############################################
### Información del Servidor Active Directory
#############################################
my $adserver = 'ms-ads.vzla.gob.ve';
# Usuario/Contraseña, cuenta con privilegios administrativos.
my $aduser = 'cn=Administrator,cn=Users,dc=vzla,dc=gob,dc=ve';
my $adpass ='redhat';
####################################################
### Información del Servidor Fedora Directory Server
####################################################
my $fdserver = 'dei-ds1';
# Usuario/Contraseña, cuenta con privilegios administrativos.
my $fduser = 'uid=<ADMIN>,ou=Administrators,ou=TopologyManagement,o=NetscapeRoot';
my $fdpass ='<PASS>';
###################################################

my $posixShell = "/bin/bash";
## baseDN
my $base = 'dc=vzla,dc=gob,dc=ve';
#my $filter = "(objCategory=group)(|(givenName=*)(sAMAccountName=*)";
#my $filter = '(|(objectClass=user)(objectCategory=*)(objectClass=group))'; # Server Oficina
my $filter = '(&(objectCategory=person)(objectClass=user))';
my $page = Net::LDAP::Control::Paged->new( size => 400 );
# Atributos requeridos
my $attrs = [ 'company', 'comment', 'description', 'displayName', 'givename', 'homePhone', 'initials', 'mail', 'mailNickname', 'member', 'memberOf', 'mobile', 'name', 'sn', 'st', 'title', 'physicalDeliveryOfficeName', 'postalCode', 'userPrincipalName', 'initials', 'member', 'memberOf', 'mail', 'homePhone', 'telephonenumber', 'mobile', 'pager', 'givenName', 'physicalDeliveryOfficeName', 'postalCode', 'company', 'comment', 'name', 'mailNickname', 'displayName', 'userPrincipalName', 'sAMAccountName', 'accountExpires' ];
my $entry = '';
my $blank = '';

#### Conectando con el Servidor MS Active Directory 
print "[+] Conectando con el servidor $adserver ...\n";sleep 1;
$ldap = Net::LDAP->new($adserver, version=>3) or die $@;
my $ads = $ldap -> bind($aduser, password => $adpass);
$ads -> code && die $mesg -> error;

print "==> Recibiendo datos del servidor $adserver ...";
# Búsqueda de atributos necesarios
my @args = (	base => $base,
		filter => $filter,
		scope  => 'sub',
		attrs =>  $attrs,
		timelimit => 60,
	 	control  => [ $page ]);

$ads = $ldap -> search(@args);
print " Hecho.\n";sleep 1;

#### Conectando con el Fedora Directory Server
print "[+] Conectando con el servidor $fdserver ...\n";sleep 1 ;
$ldap = Net::LDAP->new($fdserver, version=>3) or die $@;
my $fds = $ldap -> bind($fduser, password => $fdpass);
$fds -> code && die $fds -> error;

# Crea Objetos OU en FDS.
print "==> Preparando Objetos OU ..\n"; sleep 1;

# Tomando datos de fecha y hora para los timestamp de las entradas
($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = gmtime(time);
$year = 1900 + $yearOffset;
$timestamp = "$year$month$dayOfMonth$hour$minute$second". "Z";

open (DATOS,"ouSearch.txt") || die "[-] No pudo leer el archivo: $!";
while (my $ous = <DATOS>) {
chomp $ous;
$result = $ldap->add( "$ous",
                 attr => [
                "createtimestamp"   => ["$timestamp"],
                "modifiersname"   => "$fduser",
                "modifytimestamp" => "$timestamp",
                "objectclass" => ["top", "organizationalunit" ],
		]
                            );
       $result->code && warn "Error al añadir la entrada, ", $result->error ;
   }
close DATOS;
print "==> Moviendo entradas a $fdserver ...\n";
my $count = $ads->count;
my $posixNumber = 1000;
for (my $i=0; $i<$count; $i++) {
     $entry = $ads->entry($i);
	my $dn = $entry->dn; $dn =~ s/^CN/uid/;	
        my $cn = $entry->get_value('cn');
        my $memberOf = $entry->get_value('memberOf');
        my $member = $entry->get_value('member');
        my $displayName = $entry->get_value('displayName');
        my $userPrincipalName = $entry->get_value('userPrincipalName');
        my $name = $entry->get_value('name');
        my $sn = $entry->get_value('sn');
        my $title = $entry->get_value('title');
        my $mail = $entry->get_value('mail');
        my $mailNickname = $entry->get_value('mailNickname');
        my $physicalDeliveryOfficeName = $entry->get_value('physicalDeliveryOfficeName');
        my $st = $entry->get_value('st');
        my $userPrincipalName = $entry->get_value('userPrincipalName');
        my $postalCode = $entry->get_value('postalCode');
        my $description = $entry->get_value('description');
        my $company = $entry->get_value('company');
        my $department = $entry->get_value('department');
        my $givenName = $entry->get_value('givenName');
        my $homePhone = $entry->get_value('homePhone');
        my $telephonenumber = $entry->get_value('telephonenumber');
        my $comment = $entry->get_value('comment');
        my $description = $entry->get_value('description');
        my $initials = $entry->get_value('initials');
        my $homePhone = $entry->get_value('homePhone');
        my $mobile = $entry->get_value('mobile');
        my $pager = $entry->get_value('pager');
	# Usuarios NT
        my $sAMAccountName = $entry->get_value('sAMAccountName');
	my $accountExpires = $entry->get_value('accountExpires');
	open(sAMA, ">>ListaUsuarios.txt")||die("[-] No se pudo escribir el archivo");
	print sAMA ("$mailNickname $mail\n");
	close sAMA;

# Agregamos en FDS los atributos recolectados desde MS-AD.
#print "\n==> Ingresando entrada en el servidor $fdserver ...\n";
$result = $ldap->add( "$dn",
                 attr => [
                "cn"   => ["$displayName", ""],
                "sn"   => "$sn",
                "mail" => "$mail",
                "uid" => "$sAMAccountName",
                "uidNumber" => "$posixNumber", ## Usuario Posix
		"gidNumber" => "$posixNumber",
		"homedirectory" => "/home/$sAMAccountName",
		"loginshell" => "$posixShell",
		"ntUserDomainId" => "$sAMAccountName", ## Usuario NT
		"ntUserAcctExpires" => "$accountExpires",
		"ntuserDeleteAccount" => "true",
		"modifiersname" => "$fdsadmin",
		"modifytimestamp" => "20070727194529Z",
                "objectclass" => ["top", "person",
                "organizationalPerson", "inetOrgPerson",
	        "posixAccount", "ntUser"],
#		"posixGroup"
#                "sambaSamAccount", "shadowAccount" ],
                      ]
                            );
$posixNumber++;

$result->code && warn "Error al añadir la entrada, ", $result->error ;
}
# Desconectado del MS Active Directory.
my $ads = $ldap->unbind;
# Desconectado del Fedora Directory Server
my $fds = $ldap->unbind;

# Cantidad de Entradas/Objetos
print "--\nCantidad de Objetos procesados: $count\n";
