#!/bin/sh

po_domain="alterator-ahttpd"
alterator_api_version=1

l10n_dir=/etc/alterator/l10n

. alterator-sh-functions

LOGIN_TIMESTAMPS_DIR=/var/lib/alterator/login-timestamps
LOG_FILE=/var/log/ahttpd/login.log
MAX_TRIES=3
BLOCK_TIME=30

_log_message()
{
	local ipstr=

	[ -z "$in_ip" ] || ipstr="$in_ip  "
	printf "%s\t%s%s: %s\n" \
		"$(date)" \
		"$ipstr" \
		"$in_login" \
		"$1" \
		>>"$LOG_FILE"
}

list_locale()
{
    [ ! -d "$l10n_dir" ] ||
	find "$l10n_dir" -type f|
	sort|
	while read f; do
	    local name="${f##*/}"
	    name="${name##??-}"
	    write_enum_item "$name" "$(cat "$f")"
	done
}

authenticate()
{
	local tries= blocked=

	if [ -n "$in_ip" -a -s "$LOGIN_TIMESTAMPS_DIR/$in_ip" ]; then
		read tries <"$LOGIN_TIMESTAMPS_DIR/$in_ip"
		if [ -n "$tries" -a $tries -le 0 ]; then
			local t="$(date +%s)"
			local ft="$(stat --printf='%Y' "$LOGIN_TIMESTAMPS_DIR/$in_ip")"
			local interval="$(($t - $ft))"
			if [ $interval -le $BLOCK_TIME ]; then
				_log_message "IP address blocked ($(($BLOCK_TIME - $interval))s left)"
				# We will check password even if IP address is blocked:
				# There must not be a visible distinction between blocked and
				# non-blocked login attempts.
				blocked=1
				# Clear password to avoid timing attacks.
				in_password=
			else
				tries="$MAX_TRIES"
			fi
		fi
	fi

	if printf "%s\0%s\0" "$in_login" "$in_password" |
			/usr/sbin/alterator-chkpwd &&
			[ -z "$blocked" ]; then
		[ -z "$in_ip" ] || rm -f -- "$LOGIN_TIMESTAMPS_DIR/$in_ip"
		_log_message "Successfully logged in"
	else
		if [ -z "$blocked" ]; then
			if [ -n "$in_ip" ]; then
				[ -n "$tries" ] || tries="$MAX_TRIES"
				tries="$(($tries - 1))"
				mkdir -p "$LOGIN_TIMESTAMPS_DIR"
				echo "$tries" >"$LOGIN_TIMESTAMPS_DIR/$in_ip"
				_log_message "Authentication failed, $tries attempts left"
			else
				_log_message "Authentication failed"
			fi
		fi

		write_error "`_ "Authentication failed"`"
	fi
}

alterator_export_proc list_locale
alterator_export_proc authenticate

message_loop
