#!/bin/bash

# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

set -e
set -o pipefail

source /usr/share/debconf/confmodule

nvcrypt_passwd_script="/usr/lib/nvidia/crypt-passwd/nvcrypt-passwd.sh"
log_path="/var/log/crypt-passwd.log"

db_capb "backup"

unset_db() {
    db_set cryptpasswd/device ""
    db_set cryptpasswd/crypt-password ""
    db_set cryptpasswd/crypt-password-again ""
}

check_crypt_password() {
    s="${1}"

    if [ ${#s} -lt 8 ] || [ ${#s} -gt 32 ]; then
        return 1
    else
        return 0
    fi
}

db_settitle cryptpasswd/title

db_set cryptpasswd/device ""
db_set cryptpasswd/crypt-password ""
db_set cryptpasswd/crypt-password-again ""
db_fset cryptpasswd/crypt-password seen false
db_fset cryptpasswd/crypt-password-again seen false

# Bail out here if there is no crypt
phys_crypt="$("${nvcrypt_passwd_script}" -f)"
if [ -z "${phys_crypt}" ]; then
    echo "can't find the crypt part" > "${log_path}"
    unset_db
    exit 0
else
    db_set cryptpasswd/device "${phys_crypt}"
fi

default_key_exists="$("${nvcrypt_passwd_script}" -d "${phys_crypt}")"
if [[ ${default_key_exists} != "true" ]]; then
    echo "Default password doesn't exist" > "${log_path}"
    unset_db
    exit 0
fi

# Main loop starts here. Use a state machine to allow jumping back to
# previous questions.
state=0
while :; do
    case "${state}" in
        0)
            # below three steps are fundamental to work with debconf
            #
            # 1. prepare question
            db_input critical cryptpasswd/crypt-password || true
            # 2. Tell db to prompt a question for the user
            db_go || true
            # 3. collect the input from user
            db_get cryptpasswd/crypt-password

            USER_PW="${RET}"
            if [ "${USER_PW}" ] && check_crypt_password "${USER_PW}"; then
                db_input critical cryptpasswd/crypt-password-again || true
                db_go || true
                db_get cryptpasswd/crypt-password-again
                if [ "${USER_PW}" != "${RET}" ]; then
                    db_set cryptpasswd/crypt-password ""
                    db_set cryptpasswd/crypt-password-again ""
                    db_fset cryptpasswd/crypt-password-mismatch seen false
                    db_input critical cryptpasswd/crypt-password-mismatch
                    db_fset cryptpasswd/crypt-password seen false
                    db_fset cryptpasswd/crypt-password-again seen false
                    state=0
                    continue
                fi
            else
                db_set cryptpasswd/crypt-password ""
                db_input critical cryptpasswd/crypt-password-criteria
                db_fset cryptpasswd/crypt-password seen false
                state=0
                continue
            fi
            ;;
        *)
            break
            ;;
    esac

    if db_go; then
        state=$((${state} + 1))
    else
        state=$((${state} - 1))
    fi
done

if [ "${state}" = -1 ]; then
    exit 1
fi

# Add usr passwd
result="$("${nvcrypt_passwd_script}" -a "${phys_crypt}" "${USER_PW}")"
if [[ ${result} != "true" ]]; then
    echo "Can't add user passwd" > "${log_path}"
    exit 1
fi

# Remove default key
result="$("${nvcrypt_passwd_script}" -r "${phys_crypt}")"
if [[ ${result} != "true" ]]; then
    echo "Can't remove default key" > "${log_path}"
    exit 1
fi

exit 0
