#!/bin/sh -e
#
# Test if the LDAP server is working.
# $Id$

LC_ALL=C
export LC_ALL

. /usr/share/debian-edu-config/testsuite-lib.sh

success() { echo "success: $0: $*" ; }
error() { echo "error: $0: $*" ; RESULT=1; }

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|Roaming-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
    success "Dynamically located LDAP server '$ldap_server' is pingable."
else
    error "Dynamically located LDAP server '$ldap_server' is not pingable, continuing tests using DNS alias ldap."
    # Autodetection failed, use hardcoded DNS name for the rest of the tests
    ldap_server=ldap.intern
fi

for file in nslcd.conf ; do
    if [ -f /etc/$file ] ; then
	grep -v '^#' /etc/$file | grep -v '^$' | sort |
	    sed "s/^/info: $file: /"
    else
	error "/etc/$file is missing."
    fi
done

# Verify that NSS is properly configured for netgroups in LDAP.
if egrep -q '^netgroup: +files *.* +(ldap|sss)$' /etc/nsswitch.conf ; then
    success "NSS netgroup setting is correct in /etc/nsswitch.conf"
else
    error "NSS netgroup setting is wrong in /etc/nsswitch.conf"
fi

SERVICES="nslcd"

# Roaming workstations use sssd for caching, and not nscd
if echo "$PROFILE" | egrep -q 'Roaming-Workstation' ; then
    SERVICES="$SERVICES sssd"
else
    ls -l /var/cache/nscd/ | sed "s/^/info: nscd cache: /"
    nscd -g | sed "s/^/info: nscd statistics: /"
    SERVICES="$SERVICES nscd"
fi

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 egrep -q "^HOST (ldap|$ldap_server)" /etc/ldap/ldap.conf ; then
        :
    else
        error "ldap/ldap.conf misses definition of HOST ldap"
    fi
else
    error "/etc/ldap/ldap.conf is missing."
fi

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

if netgroup all-hosts | grep -q tjener ; then
    success "netgroup found 'tjener'"
else
    error "unable to find 'tjener' in 'all-hosts' using netgroup."
fi

if getent group students >/dev/null; then
    success "getent found file group 'students'."
else
    error "getent failed to find file group 'students'."
fi

if getent passwd |grep -z home0; then
    success "getent found LDAP user (with home0 home)."
else
    error "getent failed to find LDAP user (with home0 home)."
fi

for service in $SERVICES ; do
    if /etc/init.d/$service status > /dev/null 2>&1; then
	success "$service service is operational."
    else
	error "$service service is not operational."
    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 $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 / ; do
        if ! echo $LDAP_MOUNTS | grep -q $WANT_MOUNT ; then
            error "Missing $WANT_MOUNT mount point in ldap"
        fi
    done

    # Try a search using TLS too
    group=admins
    if ldapsearch -ZZ -LLL -h $ldap_server -b $namingContexts \
                  -x "(&(cn=$group)(objectclass=posixGroup))" >/dev/null 2>&1 ; then
        success "TLS search on $ldap_server for cn=$group returned OK exit code."
    elif ldapsearch -ZZ -LLL -h ldap.intern -b $namingContexts \
                  -x "(&(cn=$group)(objectclass=posixGroup))" >/dev/null 2>&1 ; then
        success "TLS search on ldap.intern for cn=$group returned OK exit code."
    else 
        error "TLS search for cn=$group failed."
    fi
else
    error "Missing /usr/bin/ldapsearch "
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
	    success "Saved LDAP certificate matches slapd certificate"
	else
	    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
	    success "Fetched LDAP certificate matches slapd certificate"
	else
	    error "Fetched LDAP certificate do not matches slapd certificate"
	fi
    fi
else
    error "Missing LDAP certificate $pubcert"
fi

if [ 1 -eq $(grep -v '^#' /etc/pam.d/common-auth | egrep 'pam_krb5.so|pam_ldap.so|pam_sss.so' | wc -l) ] ; then
    success "Only one PAM module of krb5, ldap and sss is enabled"
else
    error "Not only one PAM module of krb5, ldap and sss is enabled"
fi

# Make sure winbind isn't installed
if deb_installed winbind ; then
    error "winbind is installed"
else
    success "winbind is not installed"
fi

# Make sure winbind PAM module isn't active either
if grep -q pam_winbind.so /etc/pam.d/common-auth; then
    error "winbind PAM module is active"
else
    success "winbind PAM module is not active"
fi

if [ -r /etc/ldap/ldap.conf ]  ; then
    if grep -q '^TLS_REQCERT never' /etc/ldap/ldap.conf ; then
	error "LDAP cert checking turned off in /etc/ldap/ldap.conf"
    else
	success "LDAP cert checking not turned off in /etc/ldap/ldap.conf"
    fi
fi

if [ -r /etc/nslcd.conf ]  ; then
    if grep -q '^tls_reqcert never' /etc/nslcd.conf ; then
	error "LDAP cert checking turned off in /etc/nslcd.conf"
    else
	success "LDAP cert checking not turned off in /etc/nslcd.conf"
    fi
fi

if [ -r /etc/sssd/sssd.conf ]  ; then
    if grep -q '^ldap_tls_reqcert never' /etc/sssd/sssd.conf ; then
	error "LDAP cert checking turned off in /etc/sssd/sssd.conf"
    else
	success "LDAP cert checking not turned off in /etc/sssd/sssd.conf"
    fi
fi

if echo "$PROFILE" | egrep -q 'Thin-Client-Server' ; then
    check_file_perm \
	/opt/ltsp/i386/etc/ldap/ssl/ldap-server-pubkey.pem 644
fi

exit $RESULT
