#!/usr/bin/perl -w

# LDAP create user for samba-tng and unix
# originally by Mirko Manea <mami@arena.sci.univr.it>
# 01/12/2001	mami@arena.sci.univr.it
#		handle command line options
# 01/25/2001	mami@arena.sci.univr.it
#		added gecos field
# 01/26/2001	mami@arena.sci.univr.it
#		bugfix: password now works
# 02/28/2001	mami@arena.sci.univr.it
#		handle home directory creation (it uses /etc/skel)
# 05/07/2001	mami@arena.sci.univr.it
#		
# TODO: implement all options

# BEGIN CONFIG PART

$UID_START = 1000;
$GID_START = 1000;

$basedn = "ou=Students,dc=sci,dc=univr,dc=it";
$binddn = "uid=root,dc=sci,dc=univr,dc=it";
$domainUsers = "cn=Domain Users,dc=sci,dc=univr,dc=it";
$scope = "sub";

$_userLoginShell = q(/bin/bash);
$_userHomePrefix = q(/home/);
$_userGecos = q(DST Student);

$_userSmbHome = q(\\\\arena\homes);
$_userProfile = q(\\\\arena\profiles\default.man);
$_userHomeDrive = q(H:);
$_userScript = q(scripts\startup.bat); # make sure script file is edited under dos

# END CONFIG PART 

use Getopt::Std;
my %Options;

$ok = getopts('nmlu:g:d:s:c:?', \%Options);

if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
	print "Usage: $0 [-nmugdsc?] username\n";
	print "  -n	shows what would be done, but doesn't actually add user\n";
	print "  -u	uid\n";
	print "  -g	gid\n";
	print "  -d	home\n";
	print "  -s	shell\n";
	print "  -c	gecos\n";
	print "  -m	creates home directory and copies /etc/skel\n";
	print "  -l	adds user to Domain Users group\n";
	print "  -?	show this help message\n";
	exit (-1);
}

# Read options
$_userUidNumber = $Options{'u'}; 
if (!defined($_userUidNumber)) { 
	# find first unused uid starting from $UID_START
	while (defined(getpwuid($UID_START))) {
		$UID_START++;
	}
	$_userUidNumber = $UID_START;
} elsif (getpwuid($_userUidNumber)) { die "Uid already exists.\n"; }

# as rid we use hex value of uid
$_userRid = sprintf("%x", $_userUidNumber);

$_userGidNumber = $Options{'g'}; 
if (!defined($_userGidNumber)) { 
	# find first unused gid starting from $GID_START
	while (defined(getgrgid($GID_START))) {
		$GID_START++;
	}
	$_userGidNumber = $GID_START;
} elsif (getgrgid($_userGidNumber)) { die "Gid already exists.\n"; }

# as grouprid we use hex value of gid
$_userGroupRid = sprintf("%x", $_userGidNumber);

# Read only first @ARGV
$_userName = $ARGV[0];

if (!defined($_userHomeDirectory = $Options{'d'})) { $_userHomeDirectory = $_userHomePrefix.$_userName; }
if (defined($tmp = $Options{'s'})) { $_userLoginShell = $tmp; }
if (defined($tmp = $Options{'c'})) { $_userGecos = $tmp; }

print "About creating $_userName:\n";

print "uidnumber = $_userUidNumber\n";
print "rid = 0x$_userRid\n";
print "gidnumber = $_userGidNumber\n";
print "grouprid = $_userGroupRid\n";
print "name = $_userName\n";
print "gecos = $_userGecos\n";
print "homedirectory = $_userHomeDirectory";
if (defined($tmp = $Options{'m'})) { print " [CREATED]\n"; } else { print " [NOT CREATED]\n"; }
print "userloginshell = $_userLoginShell\n";
print "usersmbhome = $_userSmbHome\n";
print "userprofile = $_userProfile\n";
print "userhomedrive = $_userHomeDrive\n";
print "userscript = $_userScript\n";

system "stty -echo";
print "New password for user $_userName: ";
chomp($pass=<STDIN>);
print "\n";
system "stty echo";

system "stty -echo";
print "Retype new password for user $_userName: ";
chomp($pass2=<STDIN>);
print "\n";
system "stty echo";

if ($pass ne $pass2) {
        die "Wrong password!\n";
} else {
# MD5 password
$random = join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64];
$bsalt = "\$1\$"; $esalt = "\$";
$modsalt = $bsalt.$random.$esalt;
$_userUserPassword = crypt($pass, $modsalt);

# LanManager and NT clear text passwords
$ntpwd = `/usr/local/sbin/mkntpwd '$pass'`;
chomp($_userLmPassword = substr($ntpwd, 0, index($ntpwd, ':')));
chomp($_userNtPassword = substr($ntpwd, index($ntpwd, ':')+1));
}

if (defined($tmp = $Options{'n'})) { $options = '-nv'; } else { $options = ''; }

$FILE="|/usr/bin/ldapadd $options -D '$binddn' -W";

open FILE or die;

print FILE <<EOF;
dn: uid=$_userName,$basedn
objectclass: account
objectclass: posixAccount
objectclass: top
objectclass: shadowAccount
objectclass: sambaAccount
acctflags: [U          ]
userpassword: {crypt}$_userUserPassword
ntpassword: $_userNtPassword
lmpassword: $_userLmPassword
uid: $_userName
gecos: $_userGecos
uidnumber: $_userUidNumber
gidnumber: $_userGidNumber
cn: $_userName
ntuid: $_userName
rid: $_userRid
grouprid: $_userGroupRid
loginshell: $_userLoginShell
smbhome: $_userSmbHome
profile: $_userProfile
homedrive: $_userHomeDrive
script: $_userScript
homedirectory: $_userHomeDirectory
logontime: 00000000
logofftime: 00000000
kickofftime: 00000000
pwdlastset: 3A561FEC
pwdcanchange: 00000000
pwdmustchange: FFFFFFFF
shadowmax: 99999
shadowwarning: 7
shadowlastchange: 11270

EOF
close FILE;

if (defined($tmp = $Options{'l'})) {
	print "Adding to Domain Users group...\n";

	$FILE="|/usr/bin/ldapadd $options -D '$binddn' -W";

	open FILE or die;

	print FILE <<EOF;
dn: $domainUsers
changetype: modify
add: sambaMember
sambaMember: $_userName,$_userRid,1
-

EOF
	close FILE;
}

# If user was created successfully then we should create his/her home dir
if (defined($tmp = $Options{'m'})) {
	print "Creating home directory...";
	if (!defined($tmp = $Options{'n'})) { 
		chomp($dn=`ldapsearch -b '$basedn' -s '$scope' '(uid=$_userName)'|head -1`);
		if ($dn eq '') {
			exit (-1);
		} else {
			if ( !(-e $_userHomeDirectory) ) {
				system "mkdir $_userHomeDirectory";
				system "cp -a /etc/skel/.[a-z,A-Z]* /etc/skel/* $_userHomeDirectory";
				system "chown -R $_userUidNumber:$_userGidNumber $_userHomeDirectory"
			}
		}
		print "done!\n";
	} else {
		print "simulated!\n";
	}
}

exit 0;

