#!/bin/bash

# das_getFreeIdNumber - display first free uidNumber or gidNumber
# (C) 2009, 2010 Dennis Leeuw
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# The GNU General Public License is available from:
# <http://www.gnu.org/licenses/>.

# Version 0.9 first release
# Version 1.0 added using highest ID first, until we wrap
MY_VERSION="1.0"

# Modify for your local environment
OLDAP_USERS="ou=People"
OLDAP_GROUPS="ou=Group"
UID_START=600
UID_END=900000
GID_START=500
GID_END=900000

function print_syntax() {
	echo "Syntax: $0 [-g|-u|-v]"
	echo "	-u outputs the uidNumber"
	echo "	-g outputs the gidNumber"
	echo "	-v outputs the version number"
}

function print_version() {
	echo "das_getFreeIdNumber version $MY_VERSION"
	exit 0
}

# Get LDAP host or uri from /etc/ldap.conf
LDAPHOST=`grep ^'host ' /etc/ldap.conf 2>/dev/null | cut -d' ' -f2`
if [ "x${LDAPHOST}" != "x" ]; then
	SSLCHECK=`grep ^'ssl ' /etc/ldap.conf 2>/dev/null`
	if [ "x${SSLCHECK}" != "x" ]; then
		LDAPURI="ldap://${LDAPHOST}/"
	else
		LDAPURI="ldaps://${LDAPHOST}/"
	fi
else
	LDAPURI=`grep ^'uri ' /etc/ldap.conf 2>/dev/null | cut -d' ' -f2`
fi

if [ "x${LDAPURI}" != "x" ]; then
	LDAPBASE=`grep ^'base ' /etc/ldap.conf 2>/dev/null | cut -d' ' -f2`
else
	echo "No valid LDAP entry found in /etc/ldap.conf"
	exit 1
fi

# What are the options?
while getopts "ugv" flag
do
  case "$flag" in
        u) START=${UID_START}
	   END=${UID_END}
           FIND=uidNumber
	   bind="${OLDAP_USERS},${LDAPBASE}"
	  ;;
        g) START=${GID_START}
	   END=${GID_END}
	   FIND=gidNumber
	   bind="${OLDAP_GROUPS},${LDAPBASE}"
	  ;;
	v) print_version
	  ;;
	*) print_syntax
	   exit 1
	  ;;
  esac
done

# No known options given
if [ "x$START" = "x" ]; then
	print_syntax
	exit 1
fi

# Make uid array
id_array=(`ldapsearch -x -H ${LDAPURI} -b "${bind}" -LLL ${FIND} | grep ^${FIND} |cut -d' ' -f2|sort -g`)

# Assume (are there fucked up mothers?) that if the array is empty
# that the LDAP tree is empty... oh boy...
if [ "x${id_array[*]}" = "x" ]; then
	echo $START
fi

# First take highest id
HIGHEST_ID=${id_array[$((${#id_array[*]}-1))]}
NEXT_ID=$((${HIGHEST_ID}+1))

# If NEXT_ID is less the the set maximum echo the NEXT_ID
if [ ${NEXT_ID} -lt ${END} ]; then
	echo ${NEXT_ID}
	exit 0
fi

# Apparently all ID's have been used so we have to find old
# unused ID's

# Find first free ID
for ((I=0; $I < ${#id_array[*]}; I=$(($I+1)) )); do
	# Compare and if START is smaller then our
	# array element. It means we previously started
	# with smaller ID's so let's continue silently.
	#
	# If we are equal add one to START, until we
	# find the first free element
	#
	# All other cases we have found our free ID.
	if [ ${START} -gt ${id_array[$I]} ]; then
		echo -n
	elif [ ${START} -eq ${id_array[$I]} ]; then
		START=$(($START+1))
	else
		echo $START
		exit 0
	fi
done

# Hope it never gets to this, but give some clues
echo "All IDs are taken. Your LDAP tree is full."
echo "You might want to change the START and END ranges of your IDs"
exit 1

# END
