dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

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

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