#!/bin/sh
[ ! "$KERNEL_PACKAGE_SCRIPT_TRACE" ] || set -x

op=${0##*-}

ca_check=""
certs=""

while true ; do
    case $1 in
	--ca-check)
	    ca_check="$2"
	    shift
	    ;;
	--certs)
	    certs="$2"
	    shift
	    ;;
	*) break
	    ;;
    esac
    shift
done

is_efi () {
    # All shells supported as /bin/sh under SUSE support "local"
    # shellcheck disable=SC3043
    local msg rc=0

# The below statement fails if mokutil isn't installed or UEFI is unsupported.
# It doesn't fail if UEFI is available but secure boot is off.
    msg="$(mokutil --sb-state 2>&1)" || rc=$?

    [ -z "$KERNEL_PACKAGE_SCRIPT_DEBUG" ] || echo "$msg"

    return $rc
}

if ! is_efi; then
    [ -z "$KERNEL_PACKAGE_SCRIPT_DEBUG" ] || \
	echo "$0: system doesn't support UEFI, skipping certificate handling" >&2
    exit 0
fi
if [ ! -w /sys/firmware/efi/efivars ]; then
    mkdir -p /run/suse-kernel-rpm-scriptlets
    if [ -n "$KERNEL_PACKAGE_SCRIPT_DEBUG" ] || \
	   [ ! -e /run/suse-kernel-rpm-scriptlets/cert-warning ]; then
	echo "$0: efivarfs is not writable, skipping certificate handling" >&2
    fi
    touch /run/suse-kernel-rpm-scriptlets/cert-warning
    exit 0
fi

run_mokutil () {
    [ -z "$KERNEL_PACKAGE_SCRIPT_DEBUG" ] || echo mokutil "$@" >&2
    mokutil "$@"
}

[ -z "$KERNEL_PACKAGE_SCRIPT_DEBUG" ] || echo "cert $op" ca-check: "$ca_check" certs: "$certs" -- "$@" >&2

script_rc=0
case $op in
    pre)
	;;
    post)
	MOK_ARGS=""
	# Only apply CA check on the kernel package certs (bsc#1173115)
	if [ -n "$ca_check" ] && mokutil -h | grep -q "ca-check"; then
	    MOK_ARGS="${MOK_ARGS} --ca-check"
	fi
	# Kernel key needs to be enrolled even if it's in the kernel keyring (bsc#1191480)
	if [ -n "$ca_check" ] && mokutil -h | grep -q "ignore-keyring"; then
	    MOK_ARGS="${MOK_ARGS} --ignore-keyring"
	fi
	# XXX: Only call mokutil if UEFI and shim are used
	for cert in $certs; do
	    cert="/etc/uefi/certs/${cert}.crt"
	    # Word splitting is intended here
	    # shellcheck disable=SC2086
	    run_mokutil --import "$cert" --root-pw ${MOK_ARGS}
	    rc=$?
	    if [ $rc != 0 ] ; then
		script_rc=$rc
		echo "Failed to import $cert" >&2
	    fi
	done
	;;
    preun)
	for cert in $certs; do
	    cert="/etc/uefi/certs/${cert}.crt"
	    # Here we queue the certificate for de-enrollment. If by postun
	    # the certificate does not exist last kernel using it was
	    # removed and we can queue it for de-enrollment with mokutil.
	    # The .delete file must exist after package is removed so we cannot
	    # add it to the rpm filelist to be removed by rpm. And if script is
	    # interrupted it may remain. Do not fail when it exists (bsc#1191804).
	    ln -f "$cert" "$cert.delete" ||:
	done
	;;
    postun)
	for cert in $certs; do
	    cert="/etc/uefi/certs/${cert}.crt"
	    # If the certificate is now gone there are no users left
	    # queue -> de-enrollment
	    if ! test -e "$cert"; then
		run_mokutil --delete "$cert.delete" --root-pw
		rc=$?
		if [ $rc != 0 ] ; then
		    script_rc=$rc
		    echo "Failed to delete $cert" >&2
		fi
	    fi
	    rm "$cert.delete" || script_rc=$?
	done
	;;
    posttrans)
	;;
    *)
	echo Unknown scriptlet "$op" >&2
	script_rc=255
	;;
esac

exit $script_rc

# vim: set sts=4 sw=4 ts=8 noet:
