#!/bin/sh -e
#
# Test if the LDAP server is working.
# $Id: ldap-client 60603 2010-01-02 22:19:54Z pere $

LC_ALL=C
export LC_ALL

if test -r /etc/debian-edu/config ; then
    . /etc/debian-edu/config
fi

# Only networked profiles use LDAP
if echo "$PROFILE" | egrep -q 'Main-Server|Workstation|Thin-Client-Server|Minimal' ; then
    :
else
    exit 0
fi

RESULT=0

# Locate LDAP server dynamically, by looking up SRV records.  The -N 2
# argument is tested and found to work with the debian package
# bind9-host, and not with the host package.
ldap_servers=$(host -N 2 -t srv _ldap._tcp | rev | awk '/VRS/ {print $1}' | cut -d. -f2- | rev)
# Cut the list to one server as we do not handle redundant servers at
# the moment.
ldap_server=$(echo $ldap_servers | awk '{print $1}')

# Test if LDAP server is reachable
if ping -c1 $ldap_server > /dev/null 2>&1 ; then
    echo "success: $0: Dynamically located LDAP server '$ldap_server' is pingable."
else
    echo "error: $0: Dynamically located LDAP server '$ldap_server' is not pingable, continuing tests using DNS alias ldap."
    RESULT=1
    # Autodetection failed, use hardcoded DNS name for the rest of the tests
    ldap_server=ldap
fi

for file in nss-ldapd.conf pam_ldap.conf ; do
    if [ -f /etc/$file ] ; then
	grep -v '^#' /etc/$file | grep -v '^$' | sort |
	    sed "s/^/info: $file: /"
    else
	RESULT=1
	echo "error: $0: /etc/$file is missing."
    fi
done

ls -l /var/cache/nscd/ | sed "s/^/info: nscd cache: /"
nscd -g | sed "s/^/info: nscd statistics: /"

host -a -t srv _ldap._tcp | sed "s/^/info: SRV record from DNS: /"
host -a "$ldap_server" | sed "s/^/info: LDAP server from DNS: /"

if [ -f /etc/ldap/ldap.conf ] ; then
    if grep -q "^HOST ldap" /etc/ldap/ldap.conf ; then
        :
    else
        echo "error: $0: ldap/ldap.conf misses definition of HOST ldap"
        RESULT=1
    fi
else
    RESULT=1
    echo "error: $0: /etc/ldap/ldap.conf is missing."
fi

# test netgroups
if ldap2netgroup $ldap_server | grep -q tjener ; then
    echo "success: $0: ldap2netgroup found 'tjener'"
else
    echo "error: $0: unable to find 'tjener' in 'all-hosts' using ldap2netgroup."
    RESULT=1
fi

if netgroup all-hosts | grep -q tjener ; then
    echo "success: $0: netgroup found 'tjener'"
else
    echo "error: $0: unable to find 'tjener' in 'all-hosts' using netgroup."
    RESULT=1
fi

if getent group students >/dev/null; then
    echo "success: $0: getent found file group 'students'."
else
    echo "error: $0: getent failed to find file group 'students'."
    RESULT=1
fi

for service in nscd nslcd ; do
    if /etc/init.d/$service status > /dev/null 2>&1; then
	echo "success: $0: $service service is operational."
    else
	echo "error: $0: $service service is not operational."
	RESULT=1
    fi
done

if [ -x /usr/bin/ldapsearch ] ; then
    namingContexts="$(
        ldapsearch -s base -h $ldap_server -b '' -x '*' '+' | \
            awk '/^namingContexts:/ {print $2}' | head -1
        )"
    echo info: $0: LDAP rootDSE namingContext: $namingContexts

    LDAP_MOUNTS="$(
        ldapsearch -LLL -h $ldap_server -b ou=Automount,$namingContexts \
                   -x '(objectClass=automount)' |\
            grep "^cn:" | while read attr val; do
                echo "$val"
          done
        )"
    echo info: $0: Mountpoints found in ldap: $LDAP_MOUNTS
    for WANT_MOUNT in /skole tjener home0 ; do
        if ! echo $LDAP_MOUNTS | grep -q $WANT_MOUNT ; then
            echo "error: $0: Missing $WANT_MOUNT mount point in ldap"
            RESULT=1
        fi
    done

    # Try a search using TLS too
    if ldapsearch -ZZ -LLL -h ldap -b ou=Group,$namingContexts \
                  -x '(cn=machines)' >/dev/null 2>&1 ; then
        echo "success: TLS search for machines returned OK exit code."
    else
        echo "error: TLS search for machines failed."
    fi
else
    echo "error: $0:Missing /usr/bin/ldapsearch "
    RESULT=1
fi

pubcert=/etc/ldap/ssl/ldap-server-pubkey.pem
privcert=/etc/ldap/ssl/slapd.pem
sedextract='/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p'
if [ -s $pubcert ] ; then
    if [ -f $privcert ] ; then
	# Only compare the public part
	if sed -n "$sedextract" < $privcert | \
	    diff - $pubcert ; then
	    echo "success: Saved LDAP certificate matches slapd certificate"
	else
	    echo "error: Saved LDAP certificate do not matches slapd certificate"
	fi
    else
	if echo | openssl s_client -connect $ldap_server:ldaps 2>/dev/null | \
	    sed -n "$sedextract" | diff - $pubcert ; then
	    echo "success: Fetched LDAP certificate matches slapd certificate"
	else
	    echo "error: Fetched LDAP certificate do not matches slapd certificate"
	fi
    fi
else
    echo "error: Missing LDAP certificate $pubcert"
fi

exit $RESULT
