From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Robert Marshall Date: Thu, 25 Jun 2015 11:13:11 -0400 Subject: [PATCH] Add friendly grub2 password config tool (#985962) Provided a tool for users to reset the grub2 root user password without having to alter the grub.cfg. The hashed password now lives in a root-only-readable configuration file. Resolves: rhbz#985962 Signed-off-by: Robert Marshall [pjones: fix the efidir in grub-setpassword and rename tool] Signed-off-by: Peter Jones [luto: fix grub-setpassword -o's output path] Andy Lutomirski --- configure.ac | 1 + Makefile.util.def | 13 +++++ .gitignore | 2 + util/grub-mkconfig.in | 2 + util/grub-set-password.8 | 28 ++++++++++ util/grub-set-password.in | 128 ++++++++++++++++++++++++++++++++++++++++++++++ util/grub.d/01_users.in | 11 ++++ 7 files changed, 185 insertions(+) create mode 100644 util/grub-set-password.8 create mode 100644 util/grub-set-password.in create mode 100644 util/grub.d/01_users.in diff --git a/configure.ac b/configure.ac index 00f1db29b1a..1cb6a9615db 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath]) grub_TRANSFORM([grub-mkrescue]) grub_TRANSFORM([grub-probe]) grub_TRANSFORM([grub-reboot]) +grub_TRANSFORM([grub-set-password]) grub_TRANSFORM([grub-rpm-sort]) grub_TRANSFORM([grub-script-check]) grub_TRANSFORM([grub-set-default]) diff --git a/Makefile.util.def b/Makefile.util.def index bb21c87c8ed..7729e65c607 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -442,6 +442,12 @@ script = { installdir = grubconf; }; +script = { + name = '01_users'; + common = util/grub.d/01_users.in; + installdir = grubconf; +}; + script = { name = '10_windows'; common = util/grub.d/10_windows.in; @@ -724,6 +730,13 @@ script = { installdir = sbin; }; +script = { + name = grub-set-password; + common = util/grub-set-password.in; + mansection = 8; + installdir = sbin; +}; + script = { name = grub-mkconfig_lib; common = util/grub-mkconfig_lib.in; diff --git a/.gitignore b/.gitignore index fa2e5b609b1..141684867d1 100644 --- a/.gitignore +++ b/.gitignore @@ -111,6 +111,8 @@ grub-*.tar.* /grub*-script-check.1 /grub*-set-default /grub*-set-default.8 +/grub*-set-password +/grub*-set-password.8 /grub*-shell /grub*-shell-tester /grub*-sparc64-setup diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index f68d4925ee6..bdb9982aefb 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -282,6 +282,8 @@ for i in "${grub_mkconfig_dir}"/* ; do *~) ;; # emacsen autosave files. FIXME: support other editors */\#*\#) ;; + # rpm config files of yore. + *.rpmsave|*.rpmnew|*.rpmorig) ;; *) if grub_file_is_not_garbage "$i" && test -x "$i" ; then echo diff --git a/util/grub-set-password.8 b/util/grub-set-password.8 new file mode 100644 index 00000000000..9646546e43d --- /dev/null +++ b/util/grub-set-password.8 @@ -0,0 +1,28 @@ +.TH GRUB-SET-PASSWORD 3 "Thu Jun 25 2015" +.SH NAME +\fBgrub-set-password\fR \(em Generate the user.cfg file containing the hashed grub bootloader password. + +.SH SYNOPSIS +\fBgrub-set-password\fR [OPTION] + +.SH DESCRIPTION +\fBgrub-set-password\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user. + +The file has the format: +GRUB2_PASSWORD=<\fIhashed password\fR>. + +.SH OPTIONS +.TP +-h, --help +Display program usage and exit. +.TP +-v, --version +Display the current version. +.TP +-o, --output=<\fIDIRECTORY\fR> +Choose the file path to which user.cfg will be written. + +.SH SEE ALSO +.BR "info grub" + +.BR "info grub2-mkpasswd-pbkdf2" diff --git a/util/grub-set-password.in b/util/grub-set-password.in new file mode 100644 index 00000000000..5ebf50576d6 --- /dev/null +++ b/util/grub-set-password.in @@ -0,0 +1,128 @@ +#!/bin/sh -e + +EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/') +if [ -d /sys/firmware/efi/efivars/ ]; then + grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'` +else + grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` +fi + +PACKAGE_VERSION="@PACKAGE_VERSION@" +PACKAGE_NAME="@PACKAGE_NAME@" +self=`basename $0` +bindir="@bindir@" +grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@" + +# Usage: usage +# Print the usage. +usage () { + cat < put user.cfg in a user-selected directory + +Report bugs at https://bugzilla.redhat.com. +EOF +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2 + exit 1 + fi + echo $1 +} + +# Ensure that it's the root user running this script +if [ "${EUID}" -ne 0 ]; then + echo "The grub bootloader password may only be set by root." + usage + exit 2 +fi + +# Check the arguments. +while test $# -gt 0 +do + option=$1 + shift + + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + -o | --output) + OUTPUT_PATH=`argument $option "$@"`; shift ;; + --output=*) + OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;; + -o=*) + OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;; + esac +done + +# set user input or default path for user.cfg file +if [ -z "${OUTPUT_PATH}" ]; then + OUTPUT_PATH="${grubdir}" +fi + +if [ ! -d "${OUTPUT_PATH}" ]; then + echo "${OUTPUT_PATH} does not exist." + usage + exit 2; +fi + +ttyopt=$(stty -g) +fixtty() { + stty ${ttyopt} +} + +trap fixtty EXIT +stty -echo + +# prompt & confirm new grub2 root user password +echo -n "Enter password: " +read PASSWORD +echo +echo -n "Confirm password: " +read PASSWORD_CONFIRM +echo +stty ${ttyopt} + +getpass() { + local P0 + local P1 + P0="$1" && shift + P1="$1" && shift + + ( echo ${P0} ; echo ${P1} ) | \ + LC_ALL=C ${grub_mkpasswd} | \ + grep -v '[eE]nter password:' | \ + sed -e "s/PBKDF2 hash of your password is //" +} + +MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")" +if [ -z "${MYPASS}" ]; then + echo "${self}: error: empty password" 1>&2 + exit 1 +fi + +# on the ESP, these will fail to set the permissions, but it's okay because +# the directory is protected. +install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : +chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || : +echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg" + +if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then + echo "WARNING: The current configuration lacks password support!" + echo "Update your configuration with @grub_mkconfig@ to support this feature." +fi diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in new file mode 100644 index 00000000000..db2f44bfb78 --- /dev/null +++ b/util/grub.d/01_users.in @@ -0,0 +1,11 @@ +#!/bin/sh -e +cat << EOF +if [ -f \${prefix}/user.cfg ]; then + source \${prefix}/user.cfg + if [ -n "\${GRUB2_PASSWORD}" ]; then + set superusers="root" + export superusers + password_pbkdf2 root \${GRUB2_PASSWORD} + fi +fi +EOF