#!/usr/bin/perl -w

use strict;
use Net::LDAP;
use Net::LDAP::Entry;
use Unicode::Map8;
use Unicode::String qw(utf16);

sub randomString;

#AD credentials
our ($adHost, $adAdmin, $adPass);
require "/etc/ldap/adcreds.inc";

die "\n\ninsufficient data given!\n\nRun with: $0 login firstname lastname [password]\nrandom password if not provided\n\n" unless ($ARGV[2]);

my $login = $ARGV[0];
my $firstName = $ARGV[1];
my $lastName = $ARGV[2];
my $password = $ARGV[3] || randomString(11);

#convert password to UTF16
my $charmap = Unicode::Map8-> new('latin1') or die $!;
my $UTFpassword = $charmap-> tou('"'.$password.'"')-> byteswap()-> utf16();

#bind to Active Directory
my $adURI = "ldaps://$adHost";
my $basedn = "dc=ad,dc=phys,dc=ethz,dc=ch";
my $ldaps = Net::LDAP-> new($adURI) or die "$@";
my $mesg = $ldaps-> bind($adAdmin, password =>$adPass);
$mesg->code && die "failed to bind to AD: ", $mesg->error ;

#create inactive account first...
$mesg = $ldaps->add (
	dn   => "cn=$login,OU=Users,OU=D-PHYS,DC=ad,DC=phys,DC=ethz,DC=ch",
	attr => [ 'cn'    => "$login",
		'sn' => $lastName,
		'givenName' => $firstName,
		'displayName' => "$firstName $lastName",
		'distinguishedName' => "CN=$login,OU=Users,OU=D-PHYS,DC=ad,DC=phys,DC=ethz,DC=ch",
		'name' => "$firstName $lastName",
		'profilePath' => "\\\\winprofile\\profiles\\$login\\profile",
		'samAccountName' => $login,
		'userPrincipalName' => "$login\@ad.phys.ethz.ch",
		'UserAccountControl' => "8389154",
		'objectclass' => ['top', 'person',
			'organizationalPerson',
			'user'
		],
	]
);

$mesg->code && die "failed to create account: ", $mesg->error ;


#now search for account and change password
my $userdn;
my @attrs = qw(cn sn givenname samAccountName uid mail unicodePwd);
my $query = "(samAccountName=$login)";

$mesg = $ldaps->search (
 base => $basedn,
 scope => 'sub',
 filter => $query,
 attrs => \@attrs
 );

while (my $entry = $mesg->shift_entry()) {
    $userdn = $entry->dn;
    $entry->replace('unicodePwd' => $UTFpassword);
    $entry->replace('UserAccountControl' => "66048");
    $entry->update($ldaps);
}
$mesg->code && die "failed to change password: ", $mesg->error ;

# set Terminal Server ProfilePath in userParameters binary blob
system("./UPedit.pl \"$login\" s 1") == 0 or exit 1;

# add user to the G_TS_Access group
# disabled, only works for the first some 270 users, stalls afterwards
#@attrs = qw(cn memberUid gidNumber member);
#$query = "(cn=G_TS_Access)";

#$mesg = $ldaps->search (
# base => $basedn,
# scope => 'sub',
# filter => $query,
# attrs => \@attrs
#);

#my $tsGroup = $mesg->shift_entry();
#my $groupdn = $tsGroup->dn;
#my @currentUsers = $tsGroup->get_value('member');
#push @currentUsers, "$userdn";
#$tsGroup->replace('member' => \@currentUsers);
#$tsGroup->update($ldaps);



#we're done!
$ldaps-> unbind;

exit $mesg->code;

#################################################################
sub randomString {
	my $length_of_randomstring=shift;# the length of # the random string to generate

	my @chars=('a'..'z','A'..'Z','0'..'9','_');
	my $random_string;
	foreach (1..$length_of_randomstring) 
	{
		# rand @chars will generate a random 
		# number between 0 and scalar @chars
		$random_string.=$chars[rand @chars];
	}
	return $random_string;
}


##### requirements for LDAPS:
my $foo = "<<EOF
in /etc/ssl/certs/dphys-ca.crt:
-----BEGIN CERTIFICATE-----
MIIDvzCCAqegAwIBAgIQGxurr3mGS4FHTCO6ODn6ITANBgkqhkiG9w0BAQUFADBm
MRIwEAYKCZImiZPyLGQBGRYCY2gxFDASBgoJkiaJk/IsZAEZFgRldGh6MRQwEgYK
CZImiZPyLGQBGRYEcGh5czESMBAGCgmSJomT8ixkARkWAmFkMRAwDgYDVQQDEwdw
aGQtYWQxMB4XDTA4MDUzMDEzMzI1NloXDTE4MDUzMDEzNDI1NVowZjESMBAGCgmS
JomT8ixkARkWAmNoMRQwEgYKCZImiZPyLGQBGRYEZXRoejEUMBIGCgmSJomT8ixk
ARkWBHBoeXMxEjAQBgoJkiaJk/IsZAEZFgJhZDEQMA4GA1UEAxMHcGhkLWFkMTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdLZZFBDlA9bvVZTbiQijzg
GVk7dow3SKKu0elDzi1G3OkFTCy8IYhxRBV9zyUZfCEg/ISsx/9yrEQXeT+dl7t4
8rKrGKFjd6NKvk3SGeGnD4y+L0RuMUTkHC9Hm4BoT8q8fnpJqgDIMN6WLuPnbxE1
N6ieCUnX7b59pc/mo9rkTlZqDn9REQrdpGvmMsQq8dUY2/cRApBFk/XcdmKxvXxz
vozDZ+XkSR85Y/Ylfgyzj33phsEzZ59PBaS1fxIvxd29hVIA7RFlwKta263SbPZA
0pvmQU/WoJCwbW+e97XmoAm196bKmLZPVppSIw1PLNB667yKLtoiqa+kwBXXX7MC
AwEAAaNpMGcwEwYJKwYBBAGCNxQCBAYeBABDAEEwDgYDVR0PAQH/BAQDAgGGMA8G
A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHLNwrJXtL+f5rIXA7jGfDuw2q8jMBAG
CSsGAQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQALGwKTAc3KmOu66cXC
TC3kP30dBOfdu525E41J6UCX/rmz7dXatgL1ZBuy+4FoJ/bbF9tQsJKVYN0OJsZ4
I+3qD6t8DRc923z0UtQAwC2eAeJpFW7ycsTj3JCleKge5jMgGcKEXRJf8WtlVZL+
USRhNjLPUs2k8Vv2rPXVGbf1WOTC9Up5gVzm4dzvPGVDl+NB2U8fh8KLo9vqSNfp
liKe/TZAgQPk2JFh+FayahuY3wXnpvZIT5fiReAUdNsGki6Ewpy4dbDrcwad1cZM
t83Wm+CBNRUaafzgJGqiZRdNhTX102HdpjiRLaTHhsdxTfKl1gA5VQb8aQRuLNbc
/qkK
-----END CERTIFICATE-----

in /etc/ldap/ldap.conf:
TLS_REQCERT allow
EOF";
