summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bsdconfig/share/mustberoot.subr
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2012-09-18 22:28:42 +0000
committerdteske <dteske@FreeBSD.org>2012-09-18 22:28:42 +0000
commit282d6b7f2c0f1fb51d911f75ef9989f62e389985 (patch)
tree3ef909c692976c6a6b0854f8d722182e78ff8915 /usr.sbin/bsdconfig/share/mustberoot.subr
parent969b25f00f504248a5c234274661472d753475ad (diff)
downloadFreeBSD-src-282d6b7f2c0f1fb51d911f75ef9989f62e389985.zip
FreeBSD-src-282d6b7f2c0f1fb51d911f75ef9989f62e389985.tar.gz
Move major includes into /usr/share/bsdconfig for easy external access.
Reviewed by: adrian (co-mentor) Approved by: adrian (co-mentor)
Diffstat (limited to 'usr.sbin/bsdconfig/share/mustberoot.subr')
-rw-r--r--usr.sbin/bsdconfig/share/mustberoot.subr362
1 files changed, 362 insertions, 0 deletions
diff --git a/usr.sbin/bsdconfig/share/mustberoot.subr b/usr.sbin/bsdconfig/share/mustberoot.subr
new file mode 100644
index 0000000..ec3e16a
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/mustberoot.subr
@@ -0,0 +1,362 @@
+if [ ! "$_MUSTBEROOT_SUBR" ]; then _MUSTBEROOT_SUBR=1
+#
+# Copyright (c) 2006-2012 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_include $BSDCFG_SHARE/dialog.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+# NOTE: These are not able to be overridden/inherited for security purposes.
+
+#
+# Number of tries a user gets to enter his/her password before we log the
+# sudo(8) failure and exit.
+#
+PASSWD_TRIES=3
+
+#
+# While in SECURE mode, should authentication as `root' be allowed? Set to
+# non-NULL to enable authentication as `root', otherwise disabled.
+#
+# WARNING:
+# Unless using a custom sudo(8) configuration, user `root' should not be
+# allowed because no password is required to become `root' when already `root'
+# and therefore, any value entered as password will work.
+#
+SECURE_ALLOW_ROOT=
+
+#
+# While in SECURE mode, should we divulge (through error message) when the
+# requested authentication user does not exist? Set to non-NULL to enable,
+# otherwise a non-existent user is treated like an invalid password.
+#
+SECURE_DIVULGE_UNKNOWN_USER=
+
+############################################################ FUNCTIONS
+
+# f_become_root_via_sudo
+#
+# If not running as root, prompt for sudo(8) credentials to become root.
+# Re-execution of the current program via sudo is automatically handled.
+#
+# The following environment variables effect functionality:
+#
+# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate
+# that Xdialog(1) should be used instead of dialog(1).
+#
+f_become_root_via_sudo()
+{
+ local msg hline size
+
+ [ "$( id -u )" = "0" ] && return $SUCCESS
+
+ f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
+
+ #
+ # Check sudo(8) access before prompting for password.
+ #
+ :| sudo -S -v 2> /dev/null
+ if [ $? -ne $SUCCESS ]; then
+ #
+ # sudo(8) access denied. Prompt for their password.
+ #
+ msg="$msg_please_enter_password"
+ hline="$hline_alnum_punc_tab_enter"
+ size=$( f_dialog_inputbox_size \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$msg" \
+ "$hline" )
+
+ #
+ # Continue prompting until they either Cancel, succeed
+ # or exceed the number of allowed failures.
+ #
+ local password nfailures=0 retval
+ while [ $nfailures -lt $PASSWD_TRIES ]; do
+ if [ "$USE_XDIALOG" ]; then
+ password=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --password --inputbox "$msg" $size \
+ 2>&1 > /dev/null )
+ retval=$?
+
+ # Catch X11-related errors
+ [ $retval -eq 255 ] &&
+ f_die $retval "$password"
+ else
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$msg" $size \
+ 2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+ retval=$?
+ password=$( f_dialog_inputstr )
+ fi
+
+ # Exit if the user cancelled.
+ [ $retval -eq $SUCCESS ] || exit $retval
+
+ #
+ # Validate sudo(8) credentials
+ #
+ sudo -S -v 2> /dev/null <<-EOF
+ $password
+ EOF
+ retval=$?
+ unset password # scrub memory
+ if [ $retval -eq $SUCCESS ]; then
+ # Access granted...
+ break
+ else
+ # Access denied...
+ nfailures=$(( $nfailures + 1 ))
+
+ # introduce a short delay
+ if [ $nfailures -lt $PASSWD_TRIES ]; then
+ f_dialog_info "$msg_sorry_try_again"
+ sleep 1
+ fi
+ fi
+ done
+
+ #
+ # If user exhausted number of allowed password tries, log
+ # the security event and exit immediately.
+ #
+ if [ $nfailures -ge $PASSWD_TRIES ]; then
+ msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+ logger -p auth.notice -t sudo " " \
+ "$USER : $msg" \
+ "; TTY=$(tty)" \
+ "; PWD=$PWD" \
+ "; USER=root" \
+ "; COMMAND=$0"
+ f_die 1 "sudo: $msg"
+ fi
+ fi
+
+ # Use xauth(1) to grant root the ability to use this X11/SSH session
+ if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then
+ f_have xauth || f_die 1 \
+ "$msg_no_such_file_or_directory" "$pgm" "xauth"
+ local HOSTNAME displaynum
+ HOSTNAME=$(hostname)
+ displaynum="${DISPLAY#*:}"
+ xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \
+ $HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \
+ ~root/.Xauthority merge - > /dev/null 2>&1'
+ fi
+
+ # Re-execute ourselves with sudo(8)
+ if [ $ARGC -gt 0 ]; then
+ exec sudo "$0" $ARGV
+ else
+ exec sudo "$0"
+ fi
+ exit $? # Never reached unless error
+}
+
+# f_authenticate_some_user
+#
+# Only used if running as root and requires X11 (see USE_XDIALOG below).
+# Prompts the user to enter a username and password to be authenticated via
+# sudo(8) to proceed.
+#
+# The following environment variables effect functionality:
+#
+# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate
+# that Xdialog(1) should be used instead of dialog(1).
+#
+f_authenticate_some_user()
+{
+ local msg hline size width height
+
+ f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
+
+ #
+ # Secure-mode has been requested.
+ #
+
+ [ "$USE_XDIALOG" ] || f_die 1 "$msg_secure_mode_requires_x11"
+ [ "$(id -u)" = "0" ] || f_die 1 "$msg_secure_mode_requires_root"
+
+ #
+ # Prompt for sudo(8) credentials.
+ #
+
+ msg="$msg_please_enter_username_password"
+ hline="$hline_alnum_punc_tab_enter"
+ size=$( f_xdialog_2inputsbox_size \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$msg" \
+ "$field_username" "" \
+ "$field_password" "" )
+ width="${size##*[$IFS]}"
+ height="${size%%[$IFS]*}"
+ height=$(( $height + 2 )) # Add height for --password
+
+ #
+ # Continue prompting until they either Cancel, succeed or exceed the
+ # number of allowed failures.
+ #
+ local user_pass nfailures=0 retval
+ while [ $nfailures -lt $PASSWD_TRIES ]; do
+ user_pass=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --password --2inputsbox "$msg" \
+ $height $width \
+ "$field_username" "" \
+ "$field_password" "" \
+ 2>&1 > /dev/null )
+ retval=$?
+
+ # Catch X11-related errors
+ [ $retval -eq 255 ] && f_die $retval "$user_pass"
+
+ # Exit if the user cancelled.
+ [ $retval -eq $SUCCESS ] || exit $retval
+
+ #
+ # Make sure the user exists and is non-root
+ #
+ local user password
+ user="${user_pass%%/*}"
+ password="${user_pass#*/}"
+ unset user_pass # scrub memory
+ if [ ! "$user" ]; then
+ nfailures=$(( $nfailures + 1 ))
+ f_dialog_msgbox "$msg_no_username"
+ continue
+ fi
+ if [ ! "$SECURE_ALLOW_ROOT" ]; then
+ case "$user" in
+ root|toor)
+ nfailures=$(( $nfailures + 1 ))
+ f_dialog_msgbox "$( printf \
+ "$msg_user_disallowed" "$user" )"
+ continue
+ esac
+ fi
+ if ! f_quietly id "$user"; then
+ nfailures=$(( $nfailures + 1 ))
+ if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
+ f_dialog_msgbox "$( printf \
+ "$msg_unknown_user" "$user" )"
+ elif [ $nfailures -lt $PASSWD_TRIES ]; then
+ f_dialog_info "$msg_sorry_try_again"
+ sleep 1
+ fi
+ continue
+ fi
+
+ #
+ # Validate sudo(8) credentials for given user
+ #
+ su -m "$user" <<-EOF
+ sh <<EOS
+ sudo -k
+ sudo -S -v 2> /dev/null <<EOP
+ $password
+ EOP
+ EOS
+ EOF
+ retval=$?
+ unset user
+ unset password # scrub memory
+
+ if [ $retval -eq $SUCCESS ]; then
+ # Access granted...
+ break
+ else
+ # Access denied...
+ nfailures=$(( $nfailures + 1 ))
+
+ # introduce a short delay
+ if [ $nfailures -lt $PASSWD_TRIES ]; then
+ f_dialog_info "$msg_sorry_try_again"
+ sleep 1
+ fi
+ fi
+ done
+
+ #
+ # If user exhausted number of allowed password tries, log
+ # the security event and exit immediately.
+ #
+ if [ $nfailures -ge $PASSWD_TRIES ]; then
+ msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+ logger -p auth.notice -t sudo " " \
+ "${SUDO_USER:-$USER} : $msg" \
+ "; TTY=$(tty)" \
+ "; PWD=$PWD" \
+ "; USER=root" \
+ "; COMMAND=$0"
+ f_die 1 "sudo: $message"
+ fi
+}
+
+# f_mustberoot_init
+#
+# If not already root, make the switch to root by re-executing ourselves via
+# sudo(8) using user-supplied credentials.
+#
+# The following environment variables effect functionality:
+#
+# SECURE Either NULL or Non-NULL. If given a value will indicate
+# that (while running as root) sudo(8) authentication is
+# required to proceed.
+#
+f_mustberoot_init()
+{
+ if [ "$(id -u)" != "0" -a ! "$SECURE" ]; then
+ f_become_root_via_sudo
+ elif [ "$SECURE" ]; then
+ f_authenticate_some_user
+ fi
+}
+
+fi # ! $_MUSTBEROOT_SUBR
OpenPOWER on IntegriCloud