Blame SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch

ecb9bb
From bde7036b706857aff32a025e82da5bc32473e439 Mon Sep 17 00:00:00 2001
ecb9bb
From: Robert Marshall <rmarshall@redhat.com>
ecb9bb
Date: Thu, 25 Jun 2015 11:13:11 -0400
27a4da
Subject: [PATCH 178/260] Add friendly grub2 password config tool (#985962)
ecb9bb
ecb9bb
Provided a tool for users to reset the grub2 root user password
ecb9bb
without having to alter the grub.cfg. The hashed password now
ecb9bb
lives in a root-only-readable configuration file.
ecb9bb
ecb9bb
Resolves: rhbz#985962
ecb9bb
---
ecb9bb
 .gitignore               |  12 ++---
ecb9bb
 Makefile.util.def        |  13 +++++
ecb9bb
 configure.ac             |   1 +
ecb9bb
 util/grub-mkconfig.in    |   2 +
ecb9bb
 util/grub-setpassword.8  |  28 +++++++++++
ecb9bb
 util/grub-setpassword.in | 123 +++++++++++++++++++++++++++++++++++++++++++++++
ecb9bb
 util/grub.d/01_users.in  |  11 +++++
ecb9bb
 7 files changed, 182 insertions(+), 8 deletions(-)
ecb9bb
 create mode 100644 util/grub-setpassword.8
ecb9bb
 create mode 100755 util/grub-setpassword.in
ecb9bb
 create mode 100644 util/grub.d/01_users.in
ecb9bb
ecb9bb
diff --git a/.gitignore b/.gitignore
27a4da
index b6c45776a..e49f76b11 100644
ecb9bb
--- a/.gitignore
ecb9bb
+++ b/.gitignore
ecb9bb
@@ -1,11 +1,7 @@
ecb9bb
-00_header
ecb9bb
-10_*
ecb9bb
-20_linux_xen
ecb9bb
-30_os-prober
ecb9bb
-40_custom
ecb9bb
-41_custom
ecb9bb
-*.1
ecb9bb
-*.8
ecb9bb
+[[:digit:]][[:digit:]]_*
ecb9bb
+!util/[[:digit:]][[:digit:]]_*.in
ecb9bb
+*.[[:digit:]]
ecb9bb
+!util/*.[[:digit:]]
ecb9bb
 aclocal.m4
ecb9bb
 ahci_test
ecb9bb
 ascii.bitmaps
ecb9bb
diff --git a/Makefile.util.def b/Makefile.util.def
27a4da
index 3ac757204..e2821a2f3 100644
ecb9bb
--- a/Makefile.util.def
ecb9bb
+++ b/Makefile.util.def
ecb9bb
@@ -438,6 +438,12 @@ script = {
ecb9bb
 };
ecb9bb
 
ecb9bb
 script = {
ecb9bb
+  name = '01_users';
ecb9bb
+  common = util/grub.d/01_users.in;
ecb9bb
+  installdir = grubconf;
ecb9bb
+};
ecb9bb
+
ecb9bb
+script = {
ecb9bb
   name = '10_windows';
ecb9bb
   common = util/grub.d/10_windows.in;
ecb9bb
   installdir = grubconf;
ecb9bb
@@ -713,6 +719,13 @@ script = {
ecb9bb
 };
ecb9bb
 
ecb9bb
 script = {
ecb9bb
+  name = grub-setpassword;
ecb9bb
+  common = util/grub-setpassword.in;
ecb9bb
+  mansection = 8;
ecb9bb
+  installdir = sbin;
ecb9bb
+};
ecb9bb
+
ecb9bb
+script = {
ecb9bb
   name = grub-mkconfig_lib;
ecb9bb
   common = util/grub-mkconfig_lib.in;
ecb9bb
   installdir = noinst;
ecb9bb
diff --git a/configure.ac b/configure.ac
27a4da
index de17e65c4..273da6cb9 100644
ecb9bb
--- a/configure.ac
ecb9bb
+++ b/configure.ac
ecb9bb
@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath])
ecb9bb
 grub_TRANSFORM([grub-mkrescue])
ecb9bb
 grub_TRANSFORM([grub-probe])
ecb9bb
 grub_TRANSFORM([grub-reboot])
ecb9bb
+grub_TRANSFORM([grub-setpassword])
ecb9bb
 grub_TRANSFORM([grub-rpm-sort])
ecb9bb
 grub_TRANSFORM([grub-script-check])
ecb9bb
 grub_TRANSFORM([grub-set-default])
ecb9bb
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
27a4da
index bc26e7c10..e029d0d5e 100644
ecb9bb
--- a/util/grub-mkconfig.in
ecb9bb
+++ b/util/grub-mkconfig.in
ecb9bb
@@ -260,6 +260,8 @@ for i in "${grub_mkconfig_dir}"/* ; do
ecb9bb
     *~) ;;
ecb9bb
     # emacsen autosave files. FIXME: support other editors
ecb9bb
     */\#*\#) ;;
ecb9bb
+    # rpm config files of yore.
ecb9bb
+    *.rpmsave|*.rpmnew|*.rpmorig) ;;
ecb9bb
     *)
ecb9bb
       if grub_file_is_not_garbage "$i" && test -x "$i" ; then
ecb9bb
         echo
ecb9bb
diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8
ecb9bb
new file mode 100644
27a4da
index 000000000..5973abef4
ecb9bb
--- /dev/null
ecb9bb
+++ b/util/grub-setpassword.8
ecb9bb
@@ -0,0 +1,28 @@
ecb9bb
+.TH GRUB-SETPASSWORD 3 "Thu Jun 25 2015"
ecb9bb
+.SH NAME
ecb9bb
+\fBgrub-setpassword\fR \(em Generate the user.cfg file containing the hashed grub bootloader password.
ecb9bb
+
ecb9bb
+.SH SYNOPSIS
ecb9bb
+\fBgrub-setpassword\fR [OPTION]
ecb9bb
+
ecb9bb
+.SH DESCRIPTION
ecb9bb
+\fBgrub-setpassword\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.
ecb9bb
+
ecb9bb
+The file has the format:
ecb9bb
+GRUB_2PASSWORD=<\fIhashed password\fR>.
ecb9bb
+
ecb9bb
+.SH OPTIONS
ecb9bb
+.TP
ecb9bb
+-h, --help
ecb9bb
+Display program usage and exit.
ecb9bb
+.TP
ecb9bb
+-v, --version
ecb9bb
+Display the current version.
ecb9bb
+.TP
ecb9bb
+-o, --output[=\fIDIRECTORY PATH\fR]
ecb9bb
+Choose the file path to which user.cfg will be written.
ecb9bb
+
ecb9bb
+.SH SEE ALSO
ecb9bb
+.BR "info grub"
ecb9bb
+
ecb9bb
+.BR "info grub2-mkpasswd-pbkdf2"
ecb9bb
diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
ecb9bb
new file mode 100755
27a4da
index 000000000..dd76f00fc
ecb9bb
--- /dev/null
ecb9bb
+++ b/util/grub-setpassword.in
ecb9bb
@@ -0,0 +1,123 @@
ecb9bb
+#!/bin/sh -e
ecb9bb
+
ecb9bb
+if [ -d /sys/firmware/efi/efivars/ ]; then
ecb9bb
+    grubdir=`echo "/@bootdirname@/efi/EFI/redhat/" | sed 's,//*,/,g'`
ecb9bb
+else
ecb9bb
+    grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
ecb9bb
+fi
ecb9bb
+
ecb9bb
+PACKAGE_VERSION="@PACKAGE_VERSION@"
ecb9bb
+PACKAGE_NAME="@PACKAGE_NAME@"
ecb9bb
+self=`basename $0`
ecb9bb
+bindir="@bindir@"
ecb9bb
+grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@"
ecb9bb
+
ecb9bb
+# Usage: usage
ecb9bb
+# Print the usage.
ecb9bb
+usage () {
ecb9bb
+    cat <
ecb9bb
+Usage: $0 [OPTION] [SOURCE]
ecb9bb
+Run GRUB script in a Qemu instance.
ecb9bb
+
ecb9bb
+  -h, --help              print this message and exit
ecb9bb
+  -v, --version           print the version information and exit
ecb9bb
+  -o, --output_path       choose a custom output path for user.cfg
ecb9bb
+
ecb9bb
+$0 prompts the user to set a password on the grub bootloader. The password
ecb9bb
+is written to a file named user.cfg.
ecb9bb
+
ecb9bb
+Report bugs at https://bugzilla.redhat.com.
ecb9bb
+EOF
ecb9bb
+}
ecb9bb
+
ecb9bb
+argument () {
ecb9bb
+    opt=$1
ecb9bb
+    shift
ecb9bb
+
ecb9bb
+    if test $# -eq 0; then
ecb9bb
+        gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
ecb9bb
+        exit 1
ecb9bb
+    fi
ecb9bb
+    echo $1
ecb9bb
+}
ecb9bb
+
ecb9bb
+# Ensure that it's the root user running this script
ecb9bb
+if [ "${EUID}" -ne 0 ]; then
ecb9bb
+    echo "The grub bootloader password may only be set by root."
ecb9bb
+    usage
ecb9bb
+    exit 2
ecb9bb
+fi
ecb9bb
+
ecb9bb
+# Check the arguments.
ecb9bb
+while test $# -gt 0
ecb9bb
+do
ecb9bb
+    option=$1
ecb9bb
+    shift
ecb9bb
+
ecb9bb
+    case "$option" in
ecb9bb
+    -h | --help)
ecb9bb
+	usage
ecb9bb
+	exit 0 ;;
ecb9bb
+    -v | --version)
ecb9bb
+	echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
ecb9bb
+	exit 0 ;;
ecb9bb
+    -o | --output)
ecb9bb
+        OUTPUT_PATH=`argument $option "$@"`; shift ;;
ecb9bb
+    --output=*)
ecb9bb
+        OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;;
ecb9bb
+    -o=*)
ecb9bb
+        OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;;
ecb9bb
+    esac
ecb9bb
+done
ecb9bb
+
ecb9bb
+# set user input or default path for user.cfg file
ecb9bb
+if [ -z "${OUTPUT_PATH}" ]; then
ecb9bb
+    OUTPUT_PATH="${grubdir}"
ecb9bb
+fi
ecb9bb
+
ecb9bb
+if [ ! -d "${OUTPUT_PATH}" ]; then
ecb9bb
+    echo "${OUTPUT_PATH} does not exist."
ecb9bb
+    usage
ecb9bb
+    exit 2;
ecb9bb
+fi
ecb9bb
+
ecb9bb
+ttyopt=$(stty -g)
ecb9bb
+fixtty() {
ecb9bb
+      stty ${ttyopt}
ecb9bb
+}
ecb9bb
+
ecb9bb
+trap fixtty EXIT
ecb9bb
+stty -echo
ecb9bb
+
ecb9bb
+# prompt & confirm new grub2 root user password
ecb9bb
+echo -n "Enter password: "
ecb9bb
+read PASSWORD
ecb9bb
+echo
ecb9bb
+echo -n "Confirm password: "
ecb9bb
+read PASSWORD_CONFIRM
ecb9bb
+echo
ecb9bb
+stty ${ttyopt}
ecb9bb
+
ecb9bb
+getpass() {
ecb9bb
+    local P0
ecb9bb
+    local P1
ecb9bb
+    P0="$1" && shift
ecb9bb
+    P1="$1" && shift
ecb9bb
+
ecb9bb
+    ( echo ${P0} ; echo ${P1} ) | \
ecb9bb
+        ${grub_mkpasswd} | \
ecb9bb
+        grep -v '[eE]nter password:' | \
ecb9bb
+        sed -e "s/PBKDF2 hash of your password is //"
ecb9bb
+}
ecb9bb
+
ecb9bb
+MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")"
ecb9bb
+if [ -z "${MYPASS}" ]; then
ecb9bb
+      echo "${self}: error: empty password" 1>&2
ecb9bb
+      exit 1
ecb9bb
+fi
ecb9bb
+
ecb9bb
+# on the ESP, these will fail to set the permissions, but it's okay because
ecb9bb
+# the directory is protected.
ecb9bb
+install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || :
ecb9bb
+chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
ecb9bb
+echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
ecb9bb
diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in
ecb9bb
new file mode 100644
27a4da
index 000000000..facd409e7
ecb9bb
--- /dev/null
ecb9bb
+++ b/util/grub.d/01_users.in
ecb9bb
@@ -0,0 +1,11 @@
ecb9bb
+#!/bin/sh -e
ecb9bb
+cat << EOF
ecb9bb
+if [ -f \${prefix}/user.cfg ]; then
ecb9bb
+  source \${prefix}/user.cfg
ecb9bb
+  if [ -n \${GRUB2_PASSWORD} ]; then
ecb9bb
+    set superusers="root"
ecb9bb
+    export superusers
ecb9bb
+    password_pbkdf2 root \${GRUB2_PASSWORD}
ecb9bb
+  fi
ecb9bb
+fi
ecb9bb
+EOF
ecb9bb
-- 
27a4da
2.13.0
ecb9bb