#/bin/sh
. /etc/functions.sh

TRUE=0
FALSE=1
LDAP_LOG=/tmp/ldap.log
DEF_FROM=user_mnt		# user_mnt, PPTP, L2TP
username=$1
passwd=$2
auth_from="${3:-$DEF_FROM}"
remote_ip=$4
DEF_PROFILE=profile
profiles=""
matched_LDAP_group=""
final_auth_result="fail"
max_usage_time=1
UNLIMIT_TIME=-1

append_DN() {
	local value=$(echo $1)
	if [ -n "$args" ]; then
		args="$args,$value"
	else
		args="$value"
	fi
}
config_load ldap

case "$auth_from" in 
	user_mnt)
	profiles=$(uci -q get general_conf.base.ldap_profile)
	;;
	PPTP|pptp)
	profiles=$(uci -q get pptpd_config.pptpd.ldap_profile)
	;;
	L2TP|l2tp)
	profiles=$(uci -q get l2tpd_config.l2tpd.ldap_profile)
	;;
	PPPOE|pppoe)
	profiles=$(uci -q get pppoe_server.general.ldap_profile)
	;;
	*)
	profiles=$(uci -q get general_conf.base.ldap_profile)
	;;
esac

profiles="${profiles:-$DEF_PROFILE}"
is_unlimit=n

for ldap_profile in $profiles; do

	ldap_profile="${ldap_profile:-$DEF_PROFILE}"

	status=$(uci get ldap.$ldap_profile.status)

	if [ -z "$status" -o "$status" = "disable" ];then
		#echo "Incorrect"
		#exit 1
		continue
	fi 

	#basedn=$(uci get ldap.$ldap_profile.base_dn | sed 's/^ *//;s/ *$//' | tr -s " " | sed 's/ /,/g')
	args=""
	config_list_foreach "$ldap_profile" "base_dn" append_DN
	basedn="$args"
	#groupdn=$(uci get ldap.$ldap_profile.group_dn | sed 's/^ *//;s/ *$//' | tr -s " " | sed 's/ /,/g')
	args=""
	config_list_foreach "$ldap_profile" "group_dn" append_DN
	groupdn="$args"
	
	port=$(uci get ldap.$ldap_profile.port)
	cid=$(uci -q get ldap.$ldap_profile.cid || echo 'cn')
	bind_type=$(uci -q get ldap.$ldap_profile.bind_type || echo 0)
	usage_time=$(uci -q get ldap.$ldap_profile.usage_time || echo 480)

	if [ "$bind_type" == "2" ]; then	# regular mode
		#regulardn=$(uci -q get ldap.$ldap_profile.regular_dn | sed 's/^ *//;s/ *$//' | tr -s " " | sed 's/ /,/g')
		args=""
		config_list_foreach "$ldap_profile" "regular_dn" append_DN
		regulardn="$args"
		regular_pwd=$(uci -q get ldap.$ldap_profile.regular_pwd)
	fi

	serverip=$(uci get ldap.$ldap_profile.serverip)


	if [ "$basedn" = "" ];then
		#echo "Incorrect"
		#exit 1
		continue
	fi 

	if [ "$serverip" = "" ];then
		#echo "Incorrect"
		#exit 1
		continue
	fi


	IsLDAP_OK ()
	{
	result=$(cat $1 | grep ldap_bind)
	result2=$(cat $1 | grep "Can't contact LDAP server")

	if [ "$result" = "" ] && [ "$result2" = "" ];then
		return $TRUE   
	else
		return $FALSE   
	fi
	}

	if [ "$bind_type" == "0" ]; then # simple mode
		# bind and auth 
		dn=`ldapsearch -h ${serverip} -p ${port} -x -b "${cid}=${username},${basedn}" dn -D "${cid}=${username},${basedn}" -w "$passwd" -LLL 2>$LDAP_LOG`
	else
		#search base to get full dn
		if [ "$cid" = "cn" ]; then
			dn=`ldapsearch -h ${serverip} -p ${port} -x -b "${basedn}" "(|(cn=${username}) (uid=${username}) (sAMAccountName=${username}))" dn ${regulardn:+-D "$regulardn" -w "$regular_pwd"} -LLL 2>$LDAP_LOG`
		else
			dn=`ldapsearch -h ${serverip} -p ${port} -x -b "${basedn}" ${cid}=${username} dn ${regulardn:+-D "$regulardn" -w "$regular_pwd"} -LLL 2>$LDAP_LOG`
		fi
	fi

	IsLDAP_OK $LDAP_LOG
	if [ $? -eq "$FALSE" ]; then
	  #echo "Incorrect"
	  #return $FALSE
	  continue
	fi

	if [ "$bind_type" == "0" -a -z "$groupdn" ]; then # simple mode and no group dn
		[ -n "$remote_ip" ] && ipset -A ldap_$ldap_profile $remote_ip 2>/dev/null
		matched_LDAP_group="${ldap_profile} ${matched_LDAP_group}"
		if [ "$is_unlimit" = "n" ] ;then
			if [ $usage_time -eq $UNLIMIT_TIME ] ;then
				max_usage_time=$UNLIMIT_TIME
				is_unlimit=y
			else
				[ $max_usage_time -lt $usage_time ] && max_usage_time=$usage_time
			fi
		fi
		final_auth_result=ok
	fi

	# authentication and group check
	if [ "$(echo $dn | head -c 4)" == "dn::" ]; then
		fdn=`echo "$dn" | cut -d ' ' -f 2 | openssl base64 -d`
	else
		fdn="${dn##dn: }"
		if [ `echo "$fdn" | wc -l` -gt 1 ]; then
			fdn=`echo "$fdn" | sed ':a;N;$!ba;s/\n //g`
		fi
	fi
	#echo $fdn
	gdn=`ldapsearch -h ${serverip} -p ${port} -x -b "${groupdn:-$fdn}" ${groupdn:+"(|(memberuid=$username) (member=$fdn))" dn} -D "${fdn}" -w "${passwd}" -LLL 2>$LDAP_LOG`

	#echo $gdn
	IsLDAP_OK $LDAP_LOG
	if [ $? -eq "$FALSE" -o -z "$gdn" ]; then
	  #echo "Incorrect"
	  #return $FALSE
	  continue
	else
		[ -n "$remote_ip" ] && ipset -A ldap_$ldap_profile $remote_ip 2>/dev/null
		matched_LDAP_group="${ldap_profile} ${matched_LDAP_group}"
		if [ "$is_unlimit" = "n" ] ;then
			if [ $usage_time -eq $UNLIMIT_TIME ] ;then
				max_usage_time=$UNLIMIT_TIME
				is_unlimit=y
			else
				[ $max_usage_time -lt $usage_time ] && max_usage_time=$usage_time
			fi
		fi
		final_auth_result=ok
	fi
done

if [ "$final_auth_result" == "ok" ] ;then
	#Notice: ',' in json value will be replace to blank ' ' !!
	matched_LDAP_group=`echo $matched_LDAP_group |sed 's/ /;/g'`
	####Fix Bug: a case that 2 hosts with the same username but different password,
	#they should be treated as 2 different hosts, so we can not only use "username" to be the section key
	#Resovle: use the name of format: $username_$remote_ip, remote_ip must replace '.' to ';'
	tmp_ip=`echo $remote_ip |tr '.' '-'`
	json set ldap_user.${username}_${tmp_ip} group="${matched_LDAP_group}"
	
	####(Known Issue):username with special characters may result in setup failure
	#Todo: Enable /sbin/get_ldap_user_id script: maintain a (key_id vs. real_name) table
	
	echo "ok $max_usage_time"
	return $TRUE
else
	echo "Incorrect"
	return $FALSE
fi
