#!/bin/bash

###########################################################################
#
# MODULE:       Commands
# COPYRIGHT:    (C) 2009-2025 by CacheGuard Technologies Ltd (UK)
# COPYRIGHT:    (C) 2026-2026 by CacheGuard Technologies SAS (FR)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################

source functions

exit-cb()
{
    stty echo
    exit 0
}

check-password-type()
{
    test -n "${1}" || return 1
    
    case "${1}" in
	ad|console|email|file|ldap|login|pppoe|snmp|wadmin)
	    return 0
	    ;;
	*)
	    return 1
	    ;;
    esac
}

set-password()
{
    test -n "${1}" || return 1
    test -n "${2}" || return 2
    password_type=${1}
    password=${2}

    local sha1_file sha1 level
    local passwd_file=${HOME}/.passwd
    local user_mask=$(umask)

    case ${password_type} in
	console)
	    sha1_file=${HOME}/.passwd.sha1
	    umask -S  u=rw,g=,o= > /dev/null 2>&1
	    echo ${USER}:${password} > ${passwd_file}

	    if test ${USER} == ${ADMIN_NAME} ; then
		level=$(get-usage-level)
		echo ${SUPERADMIN_NAME}:${password} >> ${passwd_file}
		echo root:${password}${level} >> ${passwd_file}
	    fi

	    umask ${user_mask}
	    ;;
	wadmin)
	    sha1_file=${HOME}/.htpasswd.sha1
	    htpasswd -Bb ${HARD_DIR}/.htpasswd ${USER} "${password}" 2> /dev/null || return 11
	    ;;
	*)
	    return 255
	    ;;
    esac

    sha1=$(echo ${password} | openssl dgst -sha1 2> /dev/null)
    umask -S  u=rw,g=,o= > /dev/null 2>&1
    echo ${sha1} > ${sha1_file} || return 13
    umask ${user_mask}
}

check-old-password()
{
    test -n "${1}" || return 1
    password_type=${1}
    password=${2}

    local sha1_file sha11 sha12

    case ${password_type} in
	console)
	    sha1_file=${HOME}/.passwd.sha1
	    ;;
	wadmin)
	    sha1_file=${HOME}/.htpasswd.sha1
	    ;;
	login)
	    if test ${TERM} == ${WADMIN_TERM} ; then
		sha1_file=${HOME}/.htpasswd.sha1
	    else
		sha1_file=${HOME}/.passwd.sha1
	    fi
	    ;;
	*)
	    return 255
	    ;;
    esac

    test -f ${sha1_file} || return 3

    sha11=$(echo ${password} | openssl dgst -sha1 2> /dev/null)
    sha12=$(cat ${sha1_file} 2> /dev/null)

    test "${sha11}" == "${sha12}"
}

read-password()
{
    test ${TERM} != ${WADMIN_TERM} || return 0
    test "${__BATCH_MODE}" != yes || error 111
    test -z "${TRANSACTION}" || return 106
    
    test -n "${1}" || return 1
    password_type=${1}

    local asked_password_type password password1 password2

    case ${password_type} in
	console|wadmin)
	    asked_password_type=${password_type}
	    ;;
	login)
	    if test ${TERM} == ${WADMIN_TERM} ; then
		asked_password_type=wadmin
	    else
		asked_password_type=console
	    fi
	    ;;
	*)
	    return 255
	    ;;
    esac

    if ! is-first-login ${USER} ; then

	echo -n "Please enter your current ${asked_password_type} password: "
	stty -echo
	read password
	stty echo
	echo

	check-old-password ${password_type} "${password}" || return 146
    fi

    echo -n "Please enter your new password: "
    stty -echo
    read password1
    stty echo
    echo

    check-password "${password1}" || return 86

    echo -n "Please reenter your new password: "
    stty -echo
    read password2
    stty echo
    echo
    
    if test "${password1}" == "${password2}" ; then
	export PASSWORD=${password1}
	return 0
    else
	unset PASSWORD
	return 146
    fi
}

run()
{
    local old_password password ret

    if test -z "${ARGS[1]}" ; then
	local pwt=login
    else
	local pwt=${ARGS[1]}
	check-password-type ${pwt} || return 1
    fi

    trap exit-cb INT QUIT TERM

    case ${pwt} in
	console|wadmin|login)
	    case "${pwt}" in
		console)
		    is-in-top-level-context || return 231
		    test ${TERM} != ${WADMIN_TERM} || return 1
		    read-password ${pwt} ; ret=${?}
		    test ${ret} -eq 0 || return ${ret}
		    password=${PASSWORD}
		    set-password ${pwt} "${password}" || return 104
		    ;;

		wadmin|login)
		    is-in-top-level-context || return 231

		    if test ${TERM} == ${WADMIN_TERM} ; then
			old_password=${ARGS[2]}
			is-first-login ${USER} || check-old-password ${pwt} "${old_password}" || return 146
			password=${ARGS[3]}
			check-password "${password}" || return 86
		    else
			if test -z "${ARGS[2]}" ; then
			    read-password ${pwt} ; ret=${?}
			    test ${ret} -eq 0 || return ${ret}
			    password=${PASSWORD}
			else
			    old_password=${ARGS[2]}
			    is-first-login ${USER} || check-old-password ${pwt} "${old_password}" || return 146
			    test -n "${ARGS[3]}" || return 1
			    password=${ARGS[3]}
			    check-password "${password}" || return 86
			fi
		    fi

		    case "${pwt}" in
			wadmin)
			    set-password ${pwt} "${password}" || return 104
			    ;;
			login)
			    set-password wadmin "${password}" || return 104
			    set-password console "${password}" || return 104
			    ;;
			*)
			    return 255
			    ;;
		    esac
		    ;;
		*)
		    return 255
		    ;;
	    esac
	    supervisor-action "password-${pwt}" || return 104
	    ;;
	file)
	    if test -z "${ARGS[2]}" ; then show-file-password ; return 0 ; fi
	    local act=${ARGS[2]}
	    case ${act} in
		add|add:encrypted|del)

		    test -n "${ARGS[3]}" || return 1
		    local pt=${ARGS[3]}
		    check-file-password-protocol ${pt} || return 59

		    test -n "${ARGS[4]}" || return 1
		    local ip=${ARGS[4]}
		    check-ip-name ${ip} || return 113

		    case ${act} in
			add|add:encrypted)
			    test -n "${ARGS[5]}" || return 1
			    local lg=${ARGS[5]}
			    check-ftp-login-name ${lg} || return 162

			    if test ${act} == add ; then
				if test -n "${ARGS[6]}" ; then
				    password="${ARGS[6]}"
				else
				    test ${TERM} != ${WADMIN_TERM} || return 0
				    test "${__BATCH_MODE}" != yes || error 111
				    test -z "${TRANSACTION}" || return 106

				    echo -n "Please enter the password: "
				    stty -echo
				    read password
				    stty echo
				    echo
				    test -n "${password}" || return 51
				    password="${password}"
				fi
				check-file-password "${password}" || return 163
			    else
				test -n "${ARGS[6]}" || return 0
				password=$(decrypt-password "encrypted:${ARGS[6]}" "${FILE_PASSWD}")
			    fi
			    add-file-password ${pt} ${ip} ${lg} "${password}"
			    SAVENV=1
			    ;;
			del)
			    del-file-password ${pt} ${ip}
			    SAVENV=1
			    ;;
			*)
			    error 255
			    ;;
		    esac
		    ;;
		raz)
		    raz-file-password
		    SAVENV=1
		    ;;
		*)
		    return 1
		    ;;
	    esac
	    ;;

	email|ad|ldap)
	    if test -n "${ARGS[2]}" ; then
		password=${ARGS[2]}
		test "${pwt}" != ad || check-password "${password}" || return 86
	    else
		case ${pwt} in
		    ad)
			if test ${TERM} == ${WADMIN_TERM} ; then
			    unset AD_WEBGATEWAY_PASSWORD
			    SAVENV=1
			    return 0
			fi
			;;
		    *)
			test ${TERM} != ${WADMIN_TERM} || return 0
			;;
		esac

		test "${__BATCH_MODE}" != yes || error 111
		test -z "${TRANSACTION}" || return 106

		echo -n "Please enter the password: "
		stty -echo
		read password
		stty echo
		echo

		if test "${pwt}" == ad ; then
		    test -z "${password}" || check-password "${password}" || return 86

		    local retype_password
		    echo -n "Please retype the password: "
		    stty -echo
		    read retype_password
		    stty echo
		    echo

		    test "${retype_password}" == "${password}" || return 146
		fi
	    fi

	    if test "${pwt}" != ad ; then
		if ! check-external-password-length "${password}" ; then
		    INDIRECT_ERROR_CODE=531
		    return 254
		fi
	    fi

	    case ${pwt} in
		email)
		    export EMAIL_ACCOUNT_PASSWORD=${password}
		    ;;
		ad)
		    export AD_WEBGATEWAY_PASSWORD=${password}
		    ;;
		ldap)
		    export LDAP_BIND_PASSWORD=${password}
		    ;;
		*)
		    return 255
		    ;;
	    esac
	    SAVENV=1
	    ;;

	snmp)
	    local key=${ARGS[2]}
	    case "${key}" in
		community|privacy)
		    if test -n "${ARGS[3]}" ; then
			password="${ARGS[3]}"
		    else
			test ${TERM} != ${WADMIN_TERM} || return 0
			test "${__BATCH_MODE}" != yes || error 111
			test -z "${TRANSACTION}" || return 106

			echo -n "Please enter the ${key} passphrase: "
			stty -echo
			read password
			stty echo
			echo
		    fi
		    ;;
		*)
		    return 1
		    ;;
	    esac

	    check-snmp-password-length "${password}" || return 34
	    check-snmp-password "${password}" || return 22

	    case "${key}" in
		community)
		    export SNMP_COMMUNITY="${password}"
		    ;;
		privacy)
		    export SNMP_PRIVACY="${password}"
		    ;;
		*)
		    return 1
		    ;;
	    esac
	    SAVENV=1
	    ;;
	pppoe)
	    if test -n "${ARGS[2]}" ; then
		password="${ARGS[2]}"
	    else
		if test ${TERM} != ${WADMIN_TERM} ; then
		    test "${__BATCH_MODE}" != yes || error 111
		    test -z "${TRANSACTION}" || return 106

		    echo -n "Please enter the PPPoE password: "
		    stty -echo
		    read password
		    stty echo
		    echo
		fi
	    fi

	    if ! check-pppoe-password "${password}" ; then
		INDIRECT_ERROR_CODE=543
		return 254
	    fi

	    export IP_EXTRNAL_PPPOE_PASSWORD=${password}
	    SAVENV=1
	    ;;
	*)
	    error 255
	    ;;
    esac
}

main "${@}"
