#!/bin/sh set -e CONFFILE="/etc/nslcd.conf" OCONFFILE="/etc/nss-ldapd.conf" # fall back to old configfile if new one isn't present but old one is [ ! -f "$CONFFILE" ] && [ -f "$OCONFFILE" ] && CONFFILE="$OCONFFILE" # source debconf library. . /usr/share/debconf/confmodule db_version 2.0 db_capb backup # # This is the fist part of the script. In this part an attempt # is made to get or guess the current configuration. This information # is used later on to prompt the user and to provide a sensible # default. # # read a configuration value from the specified file # (it takes care in not overwriting a previously written debconf value) read_config() { debconf_param="$1" cfg_param="$2" # overwrite debconf value if different from config file db_get "$debconf_param" debconf_value="$RET" cfgfile_value=`sed -n 's/^'"$cfg_param"'[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*$/\1/ip' "$cfgfile" | head -n 1` [ -n "$cfgfile_value" ] && [ "$debconf_value" != "$cfgfile_value" ] && db_set "$debconf_param" "$cfgfile_value" # we're done return 0 } # figure out the system's domain name get_domain() { domain=`hostname --domain` || true [ -z "$domain" ] && domain=`hostname --nis | grep '\.'` || true [ -z "$domain" ] && domain=`hostname --fqdn | sed -n 's/^[^.]*\.//p'` || true [ -z "$domain" ] && domain=`sed -n 's/^[[:space:]]*\(domain\|search\)[[:space:]]*\([^[:space:]]*\)[[:space:]]*$/\2/p' /etc/resolv.conf | tail -n 1` || true echo "$domain" } # find a LDAP server URI by trying DNS and normal hostname lookups guess_ldap_uri() { # see if ldap server exists on localhost and is listening on ldapi:// if [ -e /var/run/slapd/ldapi ] then echo "ldapi:///" return fi # try to lookup _ldap._tcp SRV records if [ -n "$domain" ] then server=`host -N 2 -t SRV _ldap._tcp.$domain 2> /dev/null | grep -v NXDOMAIN | awk '{print $NF}' | head -n 1 | sed 's/\.$//'` || true if [ -n "$server" ] then echo "ldap://$server/" return fi fi # fall back to name lookups if [ -z "$ldap_uri" ] then # try unqualified hostname lookup server=`getent hosts ldap` || true [ -z "$server" ] && server=`getent hosts dirhost` || true # try qualified hostname if [ -n "$domain" ] && [ -z "$server" ] then server=`getent hosts ldap."$domain"` || true [ -z "$server" ] && server=`getent hosts dirhost."$domain"` || true fi # turn into URI with IP address if [ -n "$server" ] then # extract IP address from host entry and quote IPv6 address ip=`echo $server | sed 's/[[:space:]].*//;s/^\(.*:.*\)$/[\1]/'` echo "ldap://$ip/" fi fi } # guess the LDAP search base by performing LDAP searches on the # found server query_search_base() { ldap_uri="$1" # first try the default naming context context=`ldapsearch -LLL -H "$ldap_uri" -x -b '' -s base defaultNamingContext 2>/dev/null | sed -n 's/^defaultNamingContext: //pi'` || true if [ -n "$context" ] then echo "$context" return fi # go over naming contexts, pick the first one with posixAccount or # posixGroup objects in it for context in `ldapsearch -LLL -H "$ldap_uri" -x -b '' -s base namingContexts 2>/dev/null | sed -n 's/^namingContexts: //pi'` do # search the context found=`ldapsearch -LLL -H "$ldap_uri" -x -b "$context" -s sub -z 1 '(|(objectClass=posixAccount)(objectclass=posixGroup))' dn 2>/dev/null` || true if [ -n "$found" ] then echo $context return fi done } # check the system (non-LDAP configuration files) for some # reasonable defaults parsesys() { # guess domain based on system information domain=`get_domain` # guess ldap server URI db_get nslcd/ldap-uris if [ -z "$RET" ] then ldap_uri=`guess_ldap_uri "$domain"` [ -n "$ldap_uri" ] && db_set nslcd/ldap-uris "$ldap_uri" else # only get first URI from any stored (preseeded) value ldap_uri=`echo "$RET" | sed -n 's/[[:space:]].*//'` fi # guess search base db_get nslcd/ldap-base if [ -z "$RET" ] then # try to find the search base from the found URI [ -n "$ldap_uri" ] && search_base=`query_search_base "$ldap_uri"` # try to use the domain name to build the default base if [ -z "$search_base" ] && [ -n "$domain" ] then search_base=`echo "$domain" | sed 's/^/dc=/;s/\./,dc=/g'` fi [ -n "$search_base" ] && db_set nslcd/ldap-base "$search_base" fi # we're done return 0 } # parse a LDAP-like configuration file parsecfg() { cfgfile="$1" # check existance [ -f "$cfgfile" ] || return 0 # find uri/host/port combo db_get nslcd/ldap-uris if [ -z "$RET" ] then uris=`sed -n 's/^uri[[:space:]]*//ip' "$cfgfile" | tr '\n' ' '` if [ -z "$uris" ] then hosts=`sed -n 's/^host[[:space:]]*//ip' "$cfgfile"` port=`sed -n 's/^port[[:space:]]*//ip' "$cfgfile" | head -n 1` for host in $hosts do if [ -z "$port" ] || (echo "$host" | grep -q ':' ) then uris="$uris ldap://$host/" else uris="$uris ldap://$host:$port/" fi done fi [ -n "$uris" ] && db_set nslcd/ldap-uris "$uris" fi # read simple options read_config nslcd/ldap-base base read_config nslcd/ldap-binddn binddn read_config nslcd/ldap-bindpw bindpw read_config nslcd/ldap-sasl-mech sasl_mech read_config nslcd/ldap-sasl-realm sasl_realm read_config nslcd/ldap-sasl-authcid sasl_authcid read_config nslcd/ldap-sasl-authzid sasl_authzid read_config nslcd/ldap-sasl-secprops sasl_secprops read_config nslcd/ldap-sasl-krb5-ccname krb5_ccname # check ssl option db_get nslcd/ldap-starttls if [ -z "$RET" ] then if grep -qi '^ssl[[:space:]]*start_*tls' "$cfgfile" then db_set nslcd/ldap-starttls "true" elif grep -qi '^ssl[[:space:]]' "$cfgfile" then db_set nslcd/ldap-starttls "false" fi fi # check reqcert option db_get nslcd/ldap-reqcert if [ -z "$RET" ] then reqcert=`sed -n 's/^tls_\(reqcert\|checkpeer\)[[:space:]]*\([^[:space:]]*\)[[:space:]]*$/\2/ip' "$cfgfile" | head -n 1` # normalise value reqcert=`echo "$reqcert" | tr 'A-Z' 'a-z' | sed 's/^no$/never/;s/^yes$/demand/;s/^hard$/demand/'` [ -n "$reqcert" ] && db_set nslcd/ldap-reqcert "$reqcert" fi # we're done return 0 } # fill our defaults with the current configuration if available # and fall back to guessing the config from some other system files if [ -f "$CONFFILE" ] then # parse current configuration parsecfg "$CONFFILE" else # first match wins parsecfg /etc/libnss-ldap.conf parsecfg /etc/pam_ldap.conf parsecfg /etc/ldap/ldap.conf parsecfg /etc/ldap.conf parsesys # fallback default values db_get nslcd/ldap-uris [ -z "$RET" ] && db_set nslcd/ldap-uris "ldap://127.0.0.1/" db_get nslcd/ldap-base [ -z "$RET" ] && db_set nslcd/ldap-base "dc=example,dc=net" fi # fallback for starttls option db_get nslcd/ldap-starttls [ -z "$RET" ] && db_set nslcd/ldap-starttls "false" # deduce auth-type from available information db_get nslcd/ldap-auth-type if [ -z "$RET" ] then db_get nslcd/ldap-sasl-mech sasl_mech="$RET" db_get nslcd/ldap-binddn binddn="$RET" if [ -n "$sasl_mech" ] then db_set nslcd/ldap-auth-type "SASL" elif [ -n "$binddn" ] then db_set nslcd/ldap-auth-type "simple" else db_set nslcd/ldap-auth-type "none" fi fi # # This is the second part of the script. In this part the configurable # settings will be presented to the user for approval. The postinst # will finaly perform the actual modifications. # state="server" while [ "$state" != "done" ] do case "$state" in server) # ask about server configuration db_input high nslcd/ldap-uris || true db_input high nslcd/ldap-base || true # ask the questions, go to the next question or exit state="authtype" db_go || exit 1 # TODO: add error checking on options ;; authtype) # ask for authentication type db_input medium nslcd/ldap-auth-type || true # ask the question, go to the next question or back state="authentication" db_go || state="server" ;; authentication) # check which questions to ask, depending on the authentication type db_get nslcd/ldap-auth-type case "$RET" in none) # anonymous bind, nothing to ask (clear password) db_set nslcd/ldap-bindpw "" state="starttls" ;; simple) # ask for binddn and bindpw db_input medium nslcd/ldap-binddn || true db_input medium nslcd/ldap-bindpw || true state="starttls" ;; SASL) # ask about SASL mechanism (other SASL questions depend on this) db_input medium nslcd/ldap-sasl-mech || true state="sasloptions" ;; *) exit 1 ;; esac db_go || state="authtype" ;; sasloptions) # get SASL mech db_get nslcd/ldap-sasl-mech sasl_mech="$RET" # ask SASL questions db_input medium nslcd/ldap-sasl-realm || true if [ "$sasl_mech" != "GSSAPI" ] then db_input medium nslcd/ldap-sasl-authcid || true db_input medium nslcd/ldap-bindpw || true fi db_input medium nslcd/ldap-sasl-authzid || true db_input medium nslcd/ldap-sasl-secprops || true if [ "$sasl_mech" = "GSSAPI" ] then # have a default for ldap-sasl-krb5-ccname db_get nslcd/ldap-sasl-krb5-ccname [ -z "$RET" ] && db_set nslcd/ldap-sasl-krb5-ccname "/var/run/nslcd/nslcd.tkt" db_input low nslcd/ldap-sasl-krb5-ccname || true fi # ask the question, go to the next question or back state="starttls" db_go || state="authentication" ;; starttls) # check if ldaps:// URL's are used db_get nslcd/ldap-uris uris="$RET" if (echo "$uris" | grep -q 'ldaps://') then # ldaps: URI defined, don't ask about StartTLS db_set nslcd/ldap-starttls "false" else # ask whether to use StartTLS db_input medium nslcd/ldap-starttls || true fi # ask the question, go to the next question or back # (we go back to authtype because the previous questions were optional) state="reqcert" db_go || state="authtype" ;; reqcert) # check if ldaps:// URL's are used db_get nslcd/ldap-uris uris="$RET" # check if StartTLS is used db_get nslcd/ldap-starttls starttls="$RET" if (echo "$uris" | grep -q 'ldaps://') || [ "$starttls" = "true" ] then # ask whether to do certificate validation db_input high nslcd/ldap-reqcert || true else db_set nslcd/ldap-reqcert "" fi # ask the question, go to the next question or back # (we go back to authtype because the previous questions were optional) state="done" db_go || state="authtype" ;; esac done exit 0