#!/bin/sh

# Run an ntpd-rs NTS server and client against each other on loopback and verify
# the client obtains NTS cookies and the server receives NTS-protected NTP
# packets.
#
# ntpd-rs rejects self-signed certificates, so a throwaway private CA signs the
# server certificate.

set -e

. debian/tests/helper-functions

workdir="${AUTOPKGTEST_TMP:-$(mktemp -d)}"
server_log="${workdir}/server.log"
client_log="${workdir}/client.log"
server_pid=""
client_pid=""

cleanup() {
    result=$?
    set +e
    [ -n "${server_pid}" ] && kill "${server_pid}" 2>/dev/null
    [ -n "${client_pid}" ] && kill "${client_pid}" 2>/dev/null
    if [ ${result} -ne 0 ]; then
        echo "## server log:"; cat "${server_log}" 2>/dev/null
        echo "## client log:"; cat "${client_log}" 2>/dev/null
    fi
}
trap cleanup EXIT

systemctl --quiet stop "${NTPD_RS_SERVICE}" 2>/dev/null || :

printf "Generating a throwaway CA and server certificate: "
{
    openssl genrsa -out "${workdir}/testca.key" 2048
    openssl req -x509 -new -nodes -key "${workdir}/testca.key" -sha256 -days 2 \
        -subj "/CN=ntpd-rs-test-ca" -out "${workdir}/testca.pem"
    openssl genrsa -out "${workdir}/server.key" 2048
    openssl req -new -key "${workdir}/server.key" -subj "/CN=localhost" \
        -out "${workdir}/server.csr"
    cat > "${workdir}/server.ext" <<EOF
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = DNS:localhost
EOF
    openssl x509 -req -in "${workdir}/server.csr" -CA "${workdir}/testca.pem" \
        -CAkey "${workdir}/testca.key" -CAcreateserial -out "${workdir}/server.pem" \
        -days 2 -sha256 -extfile "${workdir}/server.ext"
    cat "${workdir}/server.pem" "${workdir}/testca.pem" > "${workdir}/server.fullchain.pem"
} >/dev/null 2>&1 && __test_ok || __test_skip "unable to generate certificates"

cat > "${workdir}/server.toml" <<EOF
[observability]
log-level = "info"
observation-path = "${workdir}/server-observe"

[[server]]
listen = "127.0.0.1:123"

[[nts-ke-server]]
listen = "127.0.0.1:4460"
certificate-chain-path = "${workdir}/server.fullchain.pem"
private-key-path = "${workdir}/server.key"
key-exchange-timeout-ms = 1000
EOF

cat > "${workdir}/client.toml" <<EOF
[observability]
log-level = "info"
observation-path = "${workdir}/client-observe"

# Poll quickly so an NTS-protected NTP exchange happens within a few seconds.
[source-defaults]
poll-interval-limits = { min = 1, max = 4 }
initial-poll-interval = 1

[[source]]
mode = "nts"
address = "localhost:4460"
certificate-authority = "${workdir}/testca.pem"

[synchronization]
minimum-agreeing-sources = 1
EOF

printf "Validating generated server and client configurations: "
ntp-ctl validate -c "${workdir}/server.toml" >/dev/null 2>&1 \
    && ntp-ctl validate -c "${workdir}/client.toml" >/dev/null 2>&1 \
    && __test_ok || __test_fail

printf "Starting the NTS server: "
ntp-daemon -c "${workdir}/server.toml" > "${server_log}" 2>&1 &
server_pid=$!
sleep 3
kill -0 "${server_pid}" 2>/dev/null && __test_ok || __test_fail

printf "Starting the NTS client: "
ntp-daemon -c "${workdir}/client.toml" > "${client_log}" 2>&1 &
client_pid=$!
sleep 3
kill -0 "${client_pid}" 2>/dev/null && __test_ok || __test_fail

printf "Waiting for the client to obtain NTS cookies from the server: "
__wait_for_positive_metric "${workdir}/client.toml" \
    '^ntp_source_nts_cookies_available' 30 2 && __test_ok || __test_fail

printf "Waiting for the server to receive NTS-protected NTP packets: "
__wait_for_positive_metric "${workdir}/server.toml" \
    '^ntp_server_nts_received_packets_total' 30 2 && __test_ok || __test_fail

exit 0
