300 lines
7.4 KiB
Bash
Executable File
300 lines
7.4 KiB
Bash
Executable File
#!/bin/sh
|
|
set -e
|
|
|
|
if test $# = 0 \
|
|
&& test x"$SHIM_NOTRIGGER" = x \
|
|
&& test x"$DPKG_MAINTSCRIPT_PACKAGE" != x \
|
|
&& dpkg-trigger --check-supported 2>/dev/null
|
|
then
|
|
if dpkg-trigger --no-await shim-secureboot-policy; then
|
|
if test x"$SHIM_TRIGGER_DEBUG" != x; then
|
|
echo "shim: wrapper deferring policy update (trigger activated)"
|
|
fi
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "$0: Permission denied"
|
|
exit 1
|
|
fi
|
|
|
|
do_enroll=0
|
|
do_toggle=0
|
|
|
|
efivars=/sys/firmware/efi/efivars
|
|
secureboot_var=SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c
|
|
moksbstatert_var=MokSBStateRT-605dab50-e046-4300-abb6-3dd810dd8b23
|
|
|
|
SB_KEY="/var/lib/shim-signed/mok/MOK.der"
|
|
SB_PRIV="/var/lib/shim-signed/mok/MOK.priv"
|
|
|
|
OLD_DKMS_LIST="/var/lib/shim-signed/dkms-list"
|
|
NEW_DKMS_LIST="${OLD_DKMS_LIST}.new"
|
|
|
|
touch $OLD_DKMS_LIST
|
|
|
|
dkms_list=$(find /var/lib/dkms -maxdepth 1 -type d -print 2>/dev/null \
|
|
| LC_ALL=C sort)
|
|
dkms_modules=$(echo "$dkms_list" | wc -l)
|
|
|
|
. /usr/share/debconf/confmodule
|
|
|
|
update_dkms_list()
|
|
{
|
|
echo "$dkms_list" > $NEW_DKMS_LIST
|
|
}
|
|
|
|
save_dkms_list()
|
|
{
|
|
mv "$NEW_DKMS_LIST" "$OLD_DKMS_LIST"
|
|
}
|
|
|
|
clear_new_dkms_list()
|
|
{
|
|
rm "$NEW_DKMS_LIST"
|
|
}
|
|
|
|
new_dkms_module()
|
|
{
|
|
# handle nvidia module specially because it changed path
|
|
if ! grep -q "/var/lib/dkms/nvidia" "$OLD_DKMS_LIST" && grep -q "/var/lib/dkms/nvidia" "$NEW_DKMS_LIST" ; then
|
|
# nvidia module is newly added
|
|
return 0
|
|
fi
|
|
|
|
# return 0 if there is any other new module
|
|
env LC_ALL=C comm -1 -3 $OLD_DKMS_LIST $NEW_DKMS_LIST | grep -q -v "/var/lib/dkms/nvidia"
|
|
}
|
|
|
|
show_dkms_list_changes()
|
|
{
|
|
diff -u $OLD_DKMS_LIST $NEW_DKMS_LIST >&2
|
|
}
|
|
|
|
validate_password()
|
|
{
|
|
db_capb
|
|
if [ "$key" != "$again" ]; then
|
|
db_fset shim/error/secureboot_key_mismatch seen false
|
|
db_input critical shim/error/secureboot_key_mismatch || true
|
|
STATE=$(($STATE - 2))
|
|
else
|
|
length=$((`echo "$key" | wc -c` - 1))
|
|
if [ $length -lt 8 ] || [ $length -gt 16 ]; then
|
|
db_fset shim/error/bad_secureboot_key seen false
|
|
db_input critical shim/error/bad_secureboot_key || true
|
|
STATE=$(($STATE - 2))
|
|
elif [ $length -ne 0 ]; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
clear_passwords()
|
|
{
|
|
# Always clear secureboot key.
|
|
db_set shim/secureboot_key ''
|
|
db_fset shim/secureboot_key seen false
|
|
db_set shim/secureboot_key_again ''
|
|
db_fset shim/secureboot_key_again seen false
|
|
}
|
|
|
|
toggle_validation()
|
|
{
|
|
local key="$1"
|
|
local again="$2"
|
|
|
|
echo "Enabling shim validation."
|
|
printf '%s\n%s\n' "$key" "$again" | mokutil --enable-validation >/dev/null || true
|
|
mokutil --timeout -1 >/dev/null || true
|
|
}
|
|
|
|
enroll_mok()
|
|
{
|
|
local key="$1"
|
|
local again="$2"
|
|
|
|
echo "Adding '$SB_KEY' to shim:"
|
|
printf '%s\n%s\n' "$key" "$again" | mokutil --import "$SB_KEY" >/dev/null || true
|
|
mokutil --timeout -1 >/dev/null || true
|
|
}
|
|
|
|
do_it()
|
|
{
|
|
STATE=1
|
|
db_settitle shim/title/secureboot
|
|
while true; do
|
|
case "$STATE" in
|
|
1)
|
|
db_capb
|
|
db_fset shim/secureboot_explanation seen false
|
|
db_input critical shim/secureboot_explanation || true
|
|
;;
|
|
2)
|
|
if [ "$do_toggle" -eq 1 ]; then
|
|
# Force no backtracking here; otherwise the GNOME backend
|
|
# might allow it due to displaying the explanation just before.
|
|
# Fixes LP: #1767091
|
|
db_capb
|
|
# Allow the user to skip toggling Secure Boot.
|
|
db_fset shim/enable_secureboot seen false
|
|
db_input critical shim/enable_secureboot || true
|
|
db_go
|
|
|
|
db_get shim/enable_secureboot
|
|
if [ "$RET" = "false" ]; then
|
|
break
|
|
fi
|
|
fi
|
|
;;
|
|
3)
|
|
|
|
db_input critical shim/secureboot_key || true
|
|
seen_key=$RET
|
|
db_input critical shim/secureboot_key_again || true
|
|
;;
|
|
4)
|
|
db_get shim/secureboot_key
|
|
key="$RET"
|
|
db_get shim/secureboot_key_again
|
|
again="$RET"
|
|
|
|
if [ -z "$key$again" ] && echo "$seen_key" | grep -q ^30; then
|
|
echo "Running in non-interactive mode, doing nothing." >&2
|
|
|
|
if new_dkms_module; then
|
|
show_dkms_list_changes
|
|
clear_new_dkms_list
|
|
exit 1
|
|
else
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
if validate_password; then
|
|
if [ $do_toggle -eq 1 ]; then
|
|
toggle_validation "$key" "$again"
|
|
fi
|
|
if [ $do_enroll -eq 1 ]; then
|
|
enroll_mok "$key" "$again"
|
|
fi
|
|
save_dkms_list
|
|
fi
|
|
|
|
clear_passwords
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
|
|
if db_go; then
|
|
STATE=$(($STATE + 1))
|
|
else
|
|
STATE=$(($STATE - 1))
|
|
fi
|
|
db_capb backup
|
|
done
|
|
db_capb
|
|
}
|
|
|
|
validate_actions() {
|
|
# Validate any queued actions before we go try to do them.
|
|
local moksbstatert=0
|
|
|
|
if ! [ -d $efivars ]; then
|
|
echo "$efivars not found, aborting." >&2
|
|
exit 0
|
|
fi
|
|
|
|
if ! [ -f $efivars/$secureboot_var ] \
|
|
|| [ "$(od -An -t u1 $efivars/$secureboot_var | awk '{ print $NF }')" -ne 1 ]
|
|
then
|
|
echo "Secure Boot not enabled on this system." >&2
|
|
exit 0
|
|
fi
|
|
|
|
if [ $dkms_modules -lt 2 ]; then
|
|
echo "No DKMS modules installed." >&2
|
|
exit 0
|
|
fi
|
|
|
|
if [ -f /proc/sys/kernel/moksbstate_disabled ]; then
|
|
moksbstatert=$(cat /proc/sys/kernel/moksbstate_disabled 2>/dev/null || echo 0)
|
|
elif [ -f $efivars/$moksbstatert_var ]; then
|
|
# MokSBStateRT set to 1 means validation is disabled
|
|
moksbstatert=$(od -An -t u1 $efivars/$moksbstatert_var | \
|
|
awk '{ print $NF; }')
|
|
fi
|
|
|
|
# We were asked to enroll a key. This only makes sense if validation
|
|
# is enabled.
|
|
if [ $do_enroll -eq 1 ] && [ $moksbstatert -eq 1 ]; then
|
|
do_toggle=1
|
|
fi
|
|
}
|
|
|
|
create_mok()
|
|
{
|
|
if [ -e "$SB_KEY" ]; then
|
|
return
|
|
fi
|
|
|
|
echo "Generating a new Secure Boot signing key:"
|
|
openssl req -config /usr/lib/shim/mok/openssl.cnf \
|
|
-subj "/CN=`hostname -s | cut -b1-31` Secure Boot Module Signature key" \
|
|
-new -x509 -newkey rsa:2048 \
|
|
-nodes -days 36500 -outform DER \
|
|
-keyout "$SB_PRIV" \
|
|
-out "$SB_KEY"
|
|
}
|
|
|
|
update_dkms_list
|
|
|
|
case "$1" in
|
|
'--enable'|'--disable')
|
|
echo "Please run mokutil directly to change shim validation behavior."
|
|
exit 0
|
|
;;
|
|
|
|
'--new-key')
|
|
create_mok
|
|
exit 0
|
|
;;
|
|
|
|
'--enroll-key')
|
|
if [ -e "$SB_KEY" ]; then
|
|
if mokutil --test-key "$SB_KEY" | \
|
|
grep -qc 'is not'; then
|
|
do_enroll=1
|
|
fi
|
|
else
|
|
echo "No MOK found."
|
|
exit 1
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
echo "update-secureboot-policy: toggle UEFI Secure Boot in shim"
|
|
echo
|
|
echo "\t--new-key\tCreate a new MOK."
|
|
echo "\t--enroll-key\tEnroll the new MOK for this system in shim."
|
|
echo "\t--help\t\tThis help text."
|
|
exit 0
|
|
|
|
esac
|
|
|
|
validate_actions
|
|
|
|
if [ $(($do_toggle + $do_enroll)) -lt 1 ]; then
|
|
echo "Nothing to do."
|
|
exit 0
|
|
fi
|
|
|
|
do_it
|
|
|
|
exit 0
|