#!/bin/sh
#
# Create user in LDAP and add a password using Kerberos.  This script
# is for testing purposes only, and will fail if several systems add
# users at the same time to LDAP, as the uid and gid values will
# conflict.

# The samba related attributes are described in
# <URL: http://download.gna.org/smbldap-tools/docs/samba-ldap-howto/#htoc43 >

set -e

USERNAME="$1"
# posixAccount only accept ASCII in the gecos attribute.  Make sure
# any non-ascii characters are converted apprpropriately.
GECOS="$(echo $2 | iconv -t ASCII//TRANSLIT)"

if [ -z "$USERNAME" -o -z "$GECOS" ] ; then 
    echo "Usage: $0 <username> <gecos>"
    echo
    echo "  Create a user with a personal group and configure its kerberos"
    echo "  principal."
    exit 1
fi

# Put users in first gosaDepartment
BASE=$(ldapsearch -x "(objectClass=gosaDepartment)" 2>/dev/null | perl -p0e 's/\n //g' | awk '/^dn: / {print $2}' | sort | head -1)

if [ -z "$BASE" ] ; then
    BASE="$(debian-edu-ldapserver -b)"
fi

GROUPBASE="ou=group,$BASE"
USERBASE="ou=people,$BASE"

ADMINUSER="admin";

# Locate the LDAP admin DN
admindn=$(ldapsearch -x "(&(cn=$ADMINUSER)(objectClass=simpleSecurityObject))" 2>/dev/null | perl -p0e 's/\n //g' | awk '/^dn: / {print $2}')

HOMEDIR=/skole/tjener/home0/$USERNAME
SMBHOMEPATH="\\\\tjener.intern\\$USERNAME"
KRB5DOMAIN=INTERN
SAMBADOMAIN=SKOLELINUX
PWLASTCHANGE=$(( $(date +%s) / (60 * 60 * 24) ))

# Find last UID/GID
SAMBASID=`net getlocalsid $HOSTNAME 2>/dev/null | awk '{ print $6; }'`

if [ -z "$SAMBASID" ] ; then
    echo "error: unable to fetch Samba SID"
    exit 1
fi

SAMBADOMAINDN=$(ldapsearch -x -s sub \
    "(&(objectclass=sambaDomain)(sambaDomainName=$SAMBADOMAIN))" \
    dn 2>/dev/null | perl -p0e 's/\n //g' | \
    awk '/^dn: / { print $2}')

if [ -z "$SAMBADOMAINDN" ] ; then
    echo "error: unable to find sambaDomain LDAP object"
    exit 1
fi

SAMBARID=$(ldapsearch -s base -b "$SAMBADOMAINDN" -x \
    sambaNextRid 2>/dev/null | perl -p0e 's/\n //g' | \
    awk '/^sambaNextRid: / { print $2}')

if [ -z "$SAMBARID" ] ; then
    echo "error: unable to find sambaNextRid LDAP attribute in $SAMBADOMAINDN"
    exit 1
fi

NEXTRID=$(( $SAMBARID + 1 ))

LASTID=$(ldapsearch -s sub -x \
    '(|(objectclass=posixaccount)(objectclass=posixgroup))' \
    uidnumber gidnumber 2>/dev/null | perl -p0e 's/\n //g' | \
    awk '/^[ug]idNumber: / {if (max < $2) { max = $2; } } END { print max}')

# If no ID was found, use LASTID=1000-1 to get uid/gid=1000
if [ -z "$LASTID" ] ; then
    LASTID=999
fi

NEWUID=$(( $LASTID + 1 ))

# Look up group DN
NEWGID=$(ldapsearch -x "(&(cn=$USERNAME)(objectClass=posixGroup))" 2>/dev/null | perl -p0e 's/\n //g' | awk '/^gidNumber: / {print $2}')
if [ -z "$NEWGID" ] ; then
    NEWGID=$NEWUID
    ldif="$ldif

dn: cn=$USERNAME,$GROUPBASE
objectClass: posixGroup
cn: $USERNAME
description: Private group of user $USERNAME
gidNumber: $NEWGID
"
fi

ldif="$ldif

dn: uid=$USERNAME,$USERBASE
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: krbPrincipalAux
objectClass: sambaSamAccount
sn: $GECOS
givenName: $GECOS
uid: $USERNAME
cn: $GECOS
userPassword: {SSHA}N0T$3T4N0W
homeDirectory: $HOMEDIR
loginShell: /bin/bash
uidNumber: $NEWUID
gidNumber: $NEWGID
gecos: $GECOS
shadowLastChange: $PWLASTCHANGE
shadowMin: 0
shadowMax: 99999
shadowWarning: 7
sambaSID: $SAMBASID-$SAMBARID
sambaAcctFlags: [U]
sambaHomePath: SMBHOMEPATH
krbPrincipalName: $USERNAME@$KRB5DOMAIN
"

# Update samba RIN
ldif="$ldif
dn: $SAMBADOMAINDN
changetype: modify
replace: sambaNextRid
sambaNextRid: $NEXTRID
"

echo "$ldif"

if echo "$ldif" | ldapadd -ZZ -D "$admindn" -W -v -x ; then

    # Set the kerberos password
    kadmin.local -q "change_password $USERNAME@$KRB5DOMAIN"

    # Create home directory
    if [ ! -d $HOMEDIR ] ; then
	cp -r /etc/skel $HOMEDIR
	chown -R $NEWUID:$NEWGID $HOMEDIR
    fi
fi
