#!/bin/sh -f

. alterator-openldap-functions

# find_dn dc=my,dc=domain,dc=com
# => /etc/openldap/slapd-my.domain.com.conf
# or
# find_dn
# => /etc/openldap/slapd-my1.domain.com.conf
# => /etc/openldap/slapd-my2.domain.com.conf
# => /etc/openldap/slapd-my1....
find_dn()
{
    local dn=
    [ $# -ge 1 ] && dn="$1" && shift

    for conf in $(read_slapd_conf include|egrep -i "slapd-[.a-z0-9_-]+\.conf[[:blank:]]*$"); do
	if [ -z "$dn" ]; then
	    local suffix="$(read_config "$conf" suffix)"
	    [ -z "$suffix" ] || echo "$suffix $conf"
	else
	    read_config "$conf" suffix|egrep -qw "^$dn$" && { echo "$conf"; break; }
	fi
    done
}

# to_realm my.domain.ru
# => MY.DOMAIN.RU
to_realm()
{
    echo "$1"|tr '[[:lower:]]' '[[:upper:]]'
}

check_dn_name()
{
    # please fix regexp
    echo "$1"|egrep -qi "^dc=[a-z][a-z0-9_-]*(,dc=[a-z][a-z0-9_-]*)*$" ||
    fatal "$0: check_dn_name: invalid suffix dn '$name'"

    [ -n "$(find_dn "$1")" ] && fatal "check_dn_name: basedn '$1' already exists"
}

create_dn()
{
    local dn="$1"
    local domain=$(dn_2_host "$dn")
    local realm="$(to_realm "$domain")"
    local basedir=${SLAPD_CONF%/*}
    local template="$basedir/slapd-mdb-template.conf"
    local new_dn_conf="$basedir/slapd-$domain.conf"
    local passwd=$(pwgen -n 16 -1)

    #autodetect database backend type
    if [ $hdb_backend -ne 0 -o "$(read_sysconfig SLAPD_BACKEND)" = "hdb" ]; then
	template="$basedir/slapd-hdb-template.conf"
    fi

    #copy template into slapd-domain.conf
    cp "$template" "$new_dn_conf"
    chmod 640 "$new_dn_conf"
    chown root:ldap "$new_dn_conf"

    #fix dc=. base, password
    sed -i -e "s/dc=template/$dn/g" $new_dn_conf
    sed -i -e "s/template/$domain/g" $new_dn_conf
    sed -i -e "s/REALM/$realm/g" $new_dn_conf
    sed -i -e "s/secret/$passwd/g" $new_dn_conf

    echo "include $new_dn_conf" >> "$SLAPD_CONF"

    export DN_CONF="$new_dn_conf"
    base_rootdn_rootpw
    ldap-init

    service slapd restart >/dev/null
}

delete_dn()
{
    local dn="$1"
    local domain=$(dn_2_host "$dn")
    local basedir="${SLAPD_CONF%/*}"
    local dn_conf="$(find_dn "$dn")"
    [ -f "$dn_conf" ] || fatal "delete_dn: no such file '$dn_conf'"
    local dn_base_file="$(read_config "$dn_conf" directory)"

    rm -f -- "$dn_conf"
    rm -rf -- "$dn_base_file"
    dn_conf="$(quote_sed_regexp $dn_conf)"
    sed -r -i -e "/^include[[:blank:]]+$dn_conf[[:blank:]]*$/ d" "$SLAPD_CONF"

    service slapd restart >/dev/null 2>&1
}

rename_dn()
{
    local old="$1"; shift
    local new="$1"; shift
    local oldhost="$(dn_2_host "$old")"
    local newhost="$(dn_2_host "$new")"
    local databasedir=""
    local oldname=""
    local newname=""

    TMPFILE="$(mktemp -t "$oldhost.XXXXXXXXXX")" || fatal "can't create tempfile"

    #slapcating old database
    service slapd stop && slapcat -b "$old" -l "$TMPFILE"

    #substitution dc=old to dc=new
    sed -r -i -e "s/$(quote_sed_regexp $old)/$(quote_sed_regexp $new)/g" "$TMPFILE"

    # changing 'dc: '
    oldname="$(quote_sed_regexp "$(echo "$oldhost"|cut -f1 -d'.')")"
    newname="$(quote_sed_regexp "$(echo "$newhost"|cut -f1 -d'.')")"
    sed -r -i -e "s/dc:[[:space:]]$oldname/dc: $newname/" "$TMPFILE"

    #substitution cn=OLDDOMAIN to cn=NEWDOMAIN (KDC)
    oldname="$(to_realm $oldhost)"
    newname="$(to_realm $newhost)"
    sed -r -i -e "s/cn=$oldname/cn=$newname/g" "$TMPFILE"

    #substitution @OLDDOMAIN to @NEWDOMAIN (KDC)
    sed -r -i -e "s/@$oldname/@$newname/g" "$TMPFILE"

    #substitution olddomain to newdomain
    sed -r -i -e "s/$oldhost/$newhost/g" "$TMPFILE"

    #fixing main slapd conf
    sed -r -i -e "s/^include[[:space:]]+$(quote_sed_regexp "/etc/openldap/slapd-$oldhost.conf")$/include $(quote_sed_regexp "/etc/openldap/slapd-$newhost.conf")/" "$MAIN_SLAPD_CONF"

    #moving old to new
    mv "/etc/openldap/slapd-$oldhost.conf" "/etc/openldap/slapd-$newhost.conf"

    #changing dc=old to dc=new
    sed -r -i -e "s/$(quote_sed_regexp $old)/$(quote_sed_regexp $new)/g" "/etc/openldap/slapd-$newhost.conf"

    #database dir with OLD directory value
    databasedir="$(read_config "/etc/openldap/slapd-$newhost.conf" directory)"

    #removing old database dir with database
    rm -rf "$databasedir" || fatal "can't remove old database dir"

    #changing directory value
    sed -r -i -e "s/^directory[[:space:]].+/directory $(quote_sed_regexp "/var/lib/ldap/bases/$newhost")/" "/etc/openldap/slapd-$newhost.conf"

    #database dir with NEW directory value
    databasedir="$(read_config "/etc/openldap/slapd-$newhost.conf" directory)"

    #adding changed ldif
    mkdir -p "$databasedir"
    chmod 700 "$databasedir"
    slapadd -c -b "$new" -l "$TMPFILE"
    chown -R ldap:ldap "$databasedir"

    service slapd start
    rm -f "$TMPFILE" >&2
}


# Parse arguments
#
new=
action="$1"
object="$2"
old="$object"
hdb_backend=0
[ $# -ne 3 ] || new="$3"
#
case "$action" in
    create)
	[ -z "$object" ] && fatal "basedn not set"
	[ "$new" != "--hdb" ] || hdb_backend=1
	check_dn_name "$object"
	create_dn "$object"
	;;
    delete)
	[ -z "$object" ] && fatal "object not set"
	delete_dn "$object"
	;;
    find)
	[ -z "$object" ] && fatal "object not set"
	find_dn "$object"
	;;
    list)
	find_dn
	;;
    master)
	master_conf="/etc/alterator/openldap/master.conf"
	if [ -n "$object" ]; then
	    cfile="$(find_dn "$object")"
	    [ -z "$cfile" ] || ln -sf "$cfile" "$master_conf"
	else
	    if [ -h "$master_conf" ]; then
		cfile=$(readlink "$master_conf")
		[ -s "$cfile" ] && echo "$(read_config "$cfile" suffix) $cfile"
	    fi
	fi
	;;
#   rename)
#	[ -z "$old" -o -z "$new" ] && fatal "old domain or new domain not set"
#	rename_dn "$old" "$new"
#	;;
    --version)
	get_ldap_version
	;;
    -h|--help|*)
	cat <<EOF
Usage:

    $0 <command> [<domain_dn>]

Available commands:

    list        show all locally configured domains
    create      create domain
    delete      delete domain
    find        show configuration file for domain
    master      set domain as master domain
    -h, --help  show this help
    --version   show version

EOF
#	echo "or"
#	echo "$0 rename dc=myold,dc=domain,dc=ru dc=mynew,dc=domain,dc=ru"
	;;
esac

