From 282d6b7f2c0f1fb51d911f75ef9989f62e389985 Mon Sep 17 00:00:00 2001 From: dteske Date: Tue, 18 Sep 2012 22:28:42 +0000 Subject: Move major includes into /usr/share/bsdconfig for easy external access. Reviewed by: adrian (co-mentor) Approved by: adrian (co-mentor) --- usr.sbin/bsdconfig/share/mustberoot.subr | 362 +++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 usr.sbin/bsdconfig/share/mustberoot.subr (limited to 'usr.sbin/bsdconfig/share/mustberoot.subr') 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 < /dev/null <