#!/bin/bash

set -e
set -o pipefail

realm="EXAMPLE.FAKE"
myhostname="sshd-gssapi.${realm,,}"
testuser="ubuntu"
password="secret"
user_principal="${testuser}@${realm}"
service_principal="host/${myhostname}"
ticket_file="/tmp/krb5cc_test"

source debian/tests/util

cleanup() {
    if [ $? -ne 0 ]; then
        echo "## Something failed"
    else
        echo "## ALL TESTS PASSED"
    fi
    echo "## Cleaning up"
    rm -f /etc/krb5.keytab "${ticket_file}"
    rm -f /etc/ssh/sshd_config.d/gssapi.conf
    rm -f /etc/ssh/ssh_config.d/gssapi.conf
    rm -f /etc/ssh/ssh_config.d/dep8.conf
}

trap cleanup EXIT

setup() {
    echo "## Setting up test environment"
    adjust_hostname "${myhostname}"
    echo "## Creating Kerberos realm ${realm}"
    create_realm "${realm}" "${myhostname}"
    echo "## Creating principals"
    kadmin.local -q "addprinc -pw ${password} ${user_principal}"
    kadmin.local -q "addprinc -randkey ${service_principal}"
    echo "## Extracting service principal ${service_principal}"
    kadmin.local -q "ktadd -k /etc/krb5.keytab ${service_principal}"
    echo "## Configuring sshd for gssapi authentication and credentials delegation"
    cat > /etc/ssh/sshd_config.d/gssapi.conf <<EOF
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
PubkeyAuthentication no
EOF
    cat > /etc/ssh/ssh_config.d/gssapi.conf <<EOF
Host *
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials yes
    PubkeyAuthentication no
EOF
    cat > /etc/ssh/ssh_config.d/dep8.conf <<EOF
Host *
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
EOF
    echo "## Restarting ssh"
    systemctl restart ssh.service
    echo
}

test_ignore_default_ccache() {
    echo "## Disabling unique ccache"
    cat > /etc/ssh/sshd_config.d/ccache.conf <<EOF
# default value is no
KerberosUniqueCCache yes
EOF
    echo "## Restarting ssh"
    systemctl restart ssh.service

    cat > /etc/krb5.conf <<EOF
[libdefaults]
    default_realm = ${realm}
    default_ccache_name = KEYRING:persistent:%{uid}
    rdns = false
    forwardable = true

[realms]
    ${realm} = {
        kdc = ${myhostname}
        admin_server = ${myhostname}
    }
EOF
    kdestroy 2>/dev/null || :
    # we will force a FILE type ccache, kinit into it, then ssh to the server
    # and verify that the KEYRING type is NOT used, and instead we have another
    # FILE type cache, this time with a random suffix
    echo "## Exporting KRB5CCNAME=FILE:${ticket_file}"
    export KRB5CCNAME="FILE:${ticket_file}"
    echo "## Obtaining TGT"
    echo "${password}" | timeout --verbose 30 kinit "${user_principal}"
    klist
    echo
    echo "## ssh'ing into server and obtaining remote ccache data"
    output=$(timeout --verbose 30 ssh "${testuser}@${myhostname}" "klist; eval echo KRB5CCNAME=\$KRB5CCNAME")
    echo "${output}"
    echo
    echo "## Remote ccache must be of the form FILE:/tmp/krb5cc_<uid>_<random>, and match KRB5CCNAME"
    remote_ccache=$(echo "${output}" | grep -E "^Ticket cache: " | cut -d " " -f 3)
    env_var=$(echo "${output}" | grep -E "^KRB5CCNAME=" | cut -d = -f 2)
    echo "## Found remote ccache: ${remote_ccache}"
    echo "## Found remote env_var: ${env_var}"
    if echo "${remote_ccache}" | grep -qE "^FILE:/tmp/krb5cc_[0-9]+_[a-zA-Z0-9]+"; then
        if [ "${env_var}" = "${remote_ccache}" ]; then
            return 0
        fi
    fi
    return 1
}

test_default_ccache() {
    echo "## Enabling unique ccache"
    cat > /etc/ssh/sshd_config.d/ccache.conf <<EOF
# default value is no
KerberosUniqueCCache no
EOF
    echo "## Restarting ssh"
    systemctl restart ssh.service
    cat > /etc/krb5.conf <<EOF
[libdefaults]
    default_realm = ${realm}
    default_ccache_name = KEYRING:persistent:%{uid}
    rdns = false
    forwardable = true

[realms]
    ${realm} = {
        kdc = ${myhostname}
        admin_server = ${myhostname}
    }
EOF
    kdestroy 2>/dev/null || :
    # we will force a FILE type ccache, kinit into it, then ssh to the server
    # and verify that the KEYRING type IS used
    echo "## Exporting KRB5CCNAME=FILE:${ticket_file}"
    export KRB5CCNAME="FILE:${ticket_file}"
    echo "## Obtaining TGT"
    echo "${password}" | timeout --verbose 30 kinit "${user_principal}"
    klist
    echo
    echo "## ssh'ing into server and obtaining remote ccache data"
    output=$(timeout --verbose 30 ssh "${testuser}@${myhostname}" "klist; eval echo KRB5CCNAME=\$KRB5CCNAME")
    echo "${output}"
    echo
    echo "## Remote ccache must be of the form KEYRING:persistend:<uid>:krb_ccache_<random>, and KRB5CCNAME must NOT be set"
    remote_ccache=$(echo "${output}" | grep -E "^Ticket cache: " | cut -d " " -f 3)
    env_var=$(echo "${output}" | grep -E "^KRB5CCNAME=" | cut -d = -f 2)
    echo "## Found remote ccache: ${remote_ccache}"
    echo "## Found remote env_var: ${env_var}"
    if echo "${remote_ccache}" | grep -qE "^KEYRING:persistent:[0-9]+:krb_ccache_[a-zA-Z0-9]+"; then
        if [ -z "${env_var}" ]; then
            return 0
        fi
    fi
    return 1
    echo
}

setup
echo "## TESTS"
echo
run_test test_ignore_default_ccache
run_test test_default_ccache
