#!/bin/sh exec > /tmp/checkpassword 2>&1; printenv; set -x CKPASSREPLY=$1 # TMP file creation and cleanup dnresult=$(mktemp -t $(basename $0)); authresult=$(mktemp -t $(basename $0)) cleanup () { rm -f "$dnresult" "$authresult"; exit; } trap 'cleanup' 0 1 2 3 4 6 7 8 10 11 12 14 15 24 25 cfgvalue() { echo $(cut -d= -f2-) } ldapvalue() { awk '{FS=": "; print $2}' } # Dovecot-style LDAP configuration, containing a single "hosts", a "base", "dn" and "dnpass" cfg=/usr/local/etc/dovecot/on2it-ldap-users.cfg srv=$(grep "^hosts[[:space:]]*=[[:space:]]*" "$cfg" | cfgvalue) base=$(grep "^base[[:space:]]*=[[:space:]]*" "$cfg" | cfgvalue) dn=$(grep "^dn[[:space:]]*=[[:space:]]*" "$cfg" | cfgvalue) dnpass=$(grep "^dnpass[[:space:]]*=[[:space:]]*" "$cfg" | cfgvalue) LDAPSEARCH="/usr/local/bin/ldapsearch -o ldif-wrap=no -x -LLL -E pr=200/noprompt -H ldap://$srv -b $base -s sub" # Read username and pass, null-separated on fd 3 input=$(tr "\0" "\1" 0<&3) username=$(echo $input | awk '{FS = "\1" ; print $1}') userpass=$(echo $input | awk '{FS = "\1" ; print $2}') # Obtain DN using authenticated bind if ${LDAPSEARCH} -D "$dn" -w "$dnpass" "(&(ObjectClass=person)(sAMAccountName=$username))" DN > "$dnresult" ; then logger -t checkpassword -p mail.info "successful authenticated bind and DN($username) lookup" else logger -t checkpassword -p mail.err "internal error looking up DN($username)" exit 111 fi DN=$(grep -i '^DN:' "$dnresult" | ldapvalue) if [ "${DN}" ] ; then logger -t checkpassword -p mail.info "DN($username) is $DN" else logger -t checkpassword -p mail.warning "DN($username) not found" exit 3 fi if ${LDAPSEARCH} -D "$DN" -w "$userpass" sAMAccountName=$username sAMAccountName > "$authresult" ; then logger -t checkpassword -p mail.info "$username authenticated" else logger -t checkpassword -p mail.warning "$username authentication failed" exit 1 fi HOME=$(grep -i '^sAMAccountName:' "$authresult" | ldapvalue) USER=${HOME} AUTHORIZED=2 userdb_uid=1000 userdb_gid=1000 EXTRA="userdb_uid userdb_gid" exec ${CKPASSREPLY}