xref: /freebsd/usr.sbin/bsdconfig/share/mustberoot.subr (revision 74036c4de983981ee2b23f91e285363293aa7c3c)
1ab2043b8SDevin Teskeif [ ! "$_MUSTBEROOT_SUBR" ]; then _MUSTBEROOT_SUBR=1
2ab2043b8SDevin Teske#
3e14ddd1fSDevin Teske# Copyright (c) 2006-2013 Devin Teske
4ab2043b8SDevin Teske# All Rights Reserved.
5ab2043b8SDevin Teske#
6ab2043b8SDevin Teske# Redistribution and use in source and binary forms, with or without
7ab2043b8SDevin Teske# modification, are permitted provided that the following conditions
8ab2043b8SDevin Teske# are met:
9ab2043b8SDevin Teske# 1. Redistributions of source code must retain the above copyright
10ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer.
11ab2043b8SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
12ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer in the
13ab2043b8SDevin Teske#    documentation and/or other materials provided with the distribution.
14ab2043b8SDevin Teske#
15ab2043b8SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16ab2043b8SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17ab2043b8SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ab2043b8SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ab2043b8SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20ab2043b8SDevin Teske# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21ab2043b8SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ab2043b8SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ab2043b8SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ab2043b8SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ab2043b8SDevin Teske# SUCH DAMAGE.
26ab2043b8SDevin Teske#
27ab2043b8SDevin Teske# $FreeBSD$
28ab2043b8SDevin Teske#
29ab2043b8SDevin Teske############################################################ INCLUDES
30ab2043b8SDevin Teske
31ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
32ab2043b8SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3356961fd7SDevin Teskef_dprintf "%s: loading includes..." mustberoot.subr
34ab2043b8SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
35ab2043b8SDevin Teske
36ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig"
37ab2043b8SDevin Teskef_include_lang $BSDCFG_LIBE/include/messages.subr
38ab2043b8SDevin Teske
39ab2043b8SDevin Teske############################################################ CONFIGURATION
40ab2043b8SDevin Teske# NOTE: These are not able to be overridden/inherited for security purposes.
41ab2043b8SDevin Teske
42ab2043b8SDevin Teske#
43ab2043b8SDevin Teske# Number of tries a user gets to enter his/her password before we log the
44ab2043b8SDevin Teske# sudo(8) failure and exit.
45ab2043b8SDevin Teske#
46ab2043b8SDevin TeskePASSWD_TRIES=3
47ab2043b8SDevin Teske
48ab2043b8SDevin Teske#
49ab2043b8SDevin Teske# While in SECURE mode, should authentication as `root' be allowed? Set to
50ab2043b8SDevin Teske# non-NULL to enable authentication as `root', otherwise disabled.
51ab2043b8SDevin Teske#
52ab2043b8SDevin Teske# WARNING:
53ab2043b8SDevin Teske# Unless using a custom sudo(8) configuration, user `root' should not be
54ab2043b8SDevin Teske# allowed because no password is required to become `root' when already `root'
55ab2043b8SDevin Teske# and therefore, any value entered as password will work.
56ab2043b8SDevin Teske#
57ab2043b8SDevin TeskeSECURE_ALLOW_ROOT=
58ab2043b8SDevin Teske
59ab2043b8SDevin Teske#
60ab2043b8SDevin Teske# While in SECURE mode, should we divulge (through error message) when the
61ab2043b8SDevin Teske# requested authentication user does not exist? Set to non-NULL to enable,
62ab2043b8SDevin Teske# otherwise a non-existent user is treated like an invalid password.
63ab2043b8SDevin Teske#
64ab2043b8SDevin TeskeSECURE_DIVULGE_UNKNOWN_USER=
65ab2043b8SDevin Teske
66ab2043b8SDevin Teske############################################################ FUNCTIONS
67ab2043b8SDevin Teske
68ab2043b8SDevin Teske# f_become_root_via_sudo
69ab2043b8SDevin Teske#
70ab2043b8SDevin Teske# If not running as root, prompt for sudo(8) credentials to become root.
71ab2043b8SDevin Teske# Re-execution of the current program via sudo is automatically handled.
72ab2043b8SDevin Teske#
73ab2043b8SDevin Teske# The following environment variables effect functionality:
74ab2043b8SDevin Teske#
75ab2043b8SDevin Teske# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
76ab2043b8SDevin Teske# 	              that Xdialog(1) should be used instead of dialog(1).
77ab2043b8SDevin Teske#
78ab2043b8SDevin Teskef_become_root_via_sudo()
79ab2043b8SDevin Teske{
80*74036c4dSDevin Teske	local msg hline height width rows
81ab2043b8SDevin Teske
82ab2043b8SDevin Teske	[ "$( id -u )" = "0" ] && return $SUCCESS
83ab2043b8SDevin Teske
84ab2043b8SDevin Teske	f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
85ab2043b8SDevin Teske
86ab2043b8SDevin Teske	#
879da4528eSDevin Teske	# Ask the user if it's OK to become root via sudo(8) and give them
889da4528eSDevin Teske	# the option to save this preference (by touch(1)ing a file in the
899da4528eSDevin Teske	# user's $HOME directory).
909da4528eSDevin Teske	#
919da4528eSDevin Teske	local checkpath="${HOME%/}/.bsdconfig_uses_sudo"
929da4528eSDevin Teske	if [ ! -e "$checkpath" ]; then
939da4528eSDevin Teske		msg=$( printf "$msg_always_try_sudo_when_run_as" "$USER" )
949da4528eSDevin Teske		local menu_list="
959da4528eSDevin Teske			'X' '$msg_cancel_exit'
969da4528eSDevin Teske			'1' '$msg'
979da4528eSDevin Teske			'2' '$msg_try_sudo_only_this_once'
989da4528eSDevin Teske		" # END-QUOTE
999da4528eSDevin Teske		msg=$( printf "$msg_you_are_not_root_but" bsdconfig )
1009da4528eSDevin Teske		hline="$hline_arrows_tab_enter"
101*74036c4dSDevin Teske		eval f_dialog_menu_size height width rows \
1029da4528eSDevin Teske		                        \"\$DIALOG_TITLE\"     \
1039da4528eSDevin Teske		                        \"\$DIALOG_BACKTITLE\" \
1049da4528eSDevin Teske		                        \"\$msg\"              \
1059da4528eSDevin Teske		                        \"\$hline\"            \
106*74036c4dSDevin Teske		                        $menu_list
1079da4528eSDevin Teske
1089da4528eSDevin Teske		local dialog_menu mtag retval
1099da4528eSDevin Teske		dialog_menu=$( eval $DIALOG \
1109da4528eSDevin Teske			--title \"\$DIALOG_TITLE\"         \
1119da4528eSDevin Teske			--backtitle \"\$DIALOG_BACKTITLE\" \
1129da4528eSDevin Teske			--hline \"\$hline\"                \
1139da4528eSDevin Teske			--ok-label \"\$msg_ok\"            \
1149da4528eSDevin Teske			--cancel-label \"\$msg_cancel\"    \
115*74036c4dSDevin Teske			--menu \"\$msg\"                   \
116*74036c4dSDevin Teske			$height $width $rows               \
1179da4528eSDevin Teske			$menu_list                         \
1189da4528eSDevin Teske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
1199da4528eSDevin Teske		)
1209da4528eSDevin Teske		retval=$?
1219da4528eSDevin Teske		setvar DIALOG_MENU_$$ "$dialog_menu"
1229da4528eSDevin Teske		mtag=$( f_dialog_menutag )
1239da4528eSDevin Teske
1249da4528eSDevin Teske		[ $retval -eq 0 ] || f_die
1259da4528eSDevin Teske
1269da4528eSDevin Teske		case "$mtag" in
1279da4528eSDevin Teske		X) # Cancel/Exit
1289da4528eSDevin Teske		   f_die ;;
1299da4528eSDevin Teske		1) # Always try sudo(8) when run as $user
1309da4528eSDevin Teske			local err
1319da4528eSDevin Teske			if ! err=$( touch "$checkpath" 2>&1 ); then
132db7b0ba7SDevin Teske				f_dialog_msgbox "$err"
1339da4528eSDevin Teske			else
1349da4528eSDevin Teske				f_show_msg "$msg_created_path" "$checkpath"
1359da4528eSDevin Teske			fi
1369da4528eSDevin Teske		esac
1379da4528eSDevin Teske	else
1389da4528eSDevin Teske		#
1399da4528eSDevin Teske		# This user has created the path signing-off on sudo(8)-use
1409da4528eSDevin Teske		# but let's still give them a short/quick/unobtrusive reminder
1419da4528eSDevin Teske		#
1429da4528eSDevin Teske		f_dialog_info "$msg_becoming_root_via_sudo"
1439da4528eSDevin Teske		[ "$USE_XDIALOG" ] || sleep 0.6
1449da4528eSDevin Teske	fi
1459da4528eSDevin Teske
1469da4528eSDevin Teske	#
147ab2043b8SDevin Teske	# Check sudo(8) access before prompting for password.
148ab2043b8SDevin Teske	#
149fb7d723eSDevin Teske	:| sudo -S -v 2> /dev/null
150ab2043b8SDevin Teske	if [ $? -ne $SUCCESS ]; then
151ab2043b8SDevin Teske		#
152ab2043b8SDevin Teske		# sudo(8) access denied. Prompt for their password.
153ab2043b8SDevin Teske		#
154ab2043b8SDevin Teske		msg="$msg_please_enter_password"
155ab2043b8SDevin Teske		hline="$hline_alnum_punc_tab_enter"
156*74036c4dSDevin Teske		f_dialog_inputbox_size height width \
157ab2043b8SDevin Teske		                       "$DIALOG_TITLE"     \
158ab2043b8SDevin Teske		                       "$DIALOG_BACKTITLE" \
159ab2043b8SDevin Teske		                       "$msg"              \
160*74036c4dSDevin Teske		                       "$hline"
161ab2043b8SDevin Teske
162ab2043b8SDevin Teske		#
163ab2043b8SDevin Teske		# Continue prompting until they either Cancel, succeed
164ab2043b8SDevin Teske		# or exceed the number of allowed failures.
165ab2043b8SDevin Teske		#
166ab2043b8SDevin Teske		local password nfailures=0 retval
167ab2043b8SDevin Teske		while [ $nfailures -lt $PASSWD_TRIES ]; do
168ab2043b8SDevin Teske			if [ "$USE_XDIALOG" ]; then
169ab2043b8SDevin Teske				password=$( $DIALOG \
170ab2043b8SDevin Teske					--title "$DIALOG_TITLE"         \
171ab2043b8SDevin Teske					--backtitle "$DIALOG_BACKTITLE" \
172ab2043b8SDevin Teske					--hline "$hline"                \
173ab2043b8SDevin Teske					--ok-label "$msg_ok"            \
174ab2043b8SDevin Teske					--cancel-label "$msg_cancel"    \
175*74036c4dSDevin Teske					--password --inputbox "$msg"    \
176*74036c4dSDevin Teske					$height $width                  \
177fb7d723eSDevin Teske					2>&1 > /dev/null )
178ab2043b8SDevin Teske				retval=$?
179ab2043b8SDevin Teske
180ab2043b8SDevin Teske				# Catch X11-related errors
181ab2043b8SDevin Teske				[ $retval -eq 255 ] &&
182ab2043b8SDevin Teske					f_die $retval "$password"
183ab2043b8SDevin Teske			else
18489498fdfSDevin Teske				local dialog_inputbox
18589498fdfSDevin Teske				dialog_inputbox=$( $DIALOG \
186ab2043b8SDevin Teske					--title "$DIALOG_TITLE"         \
187ab2043b8SDevin Teske					--backtitle "$DIALOG_BACKTITLE" \
188ab2043b8SDevin Teske					--hline "$hline"                \
189ab2043b8SDevin Teske					--ok-label "$msg_ok"            \
190ab2043b8SDevin Teske					--cancel-label "$msg_cancel"    \
191ab2043b8SDevin Teske					--insecure                      \
192*74036c4dSDevin Teske					--passwordbox "$msg"            \
193*74036c4dSDevin Teske					$height $width                  \
19489498fdfSDevin Teske					2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
19589498fdfSDevin Teske				)
196ab2043b8SDevin Teske				retval=$?
19789498fdfSDevin Teske				setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
198ab2043b8SDevin Teske				password=$( f_dialog_inputstr )
199ab2043b8SDevin Teske			fi
200ab2043b8SDevin Teske
201ab2043b8SDevin Teske			# Exit if the user cancelled.
202ab2043b8SDevin Teske			[ $retval -eq $SUCCESS ] || exit $retval
203ab2043b8SDevin Teske
204ab2043b8SDevin Teske			#
205ab2043b8SDevin Teske			# Validate sudo(8) credentials
206ab2043b8SDevin Teske			#
207fb7d723eSDevin Teske			sudo -S -v 2> /dev/null <<-EOF
208ab2043b8SDevin Teske			$password
209ab2043b8SDevin Teske			EOF
210ab2043b8SDevin Teske			retval=$?
211ab2043b8SDevin Teske			unset password # scrub memory
212ab2043b8SDevin Teske			if [ $retval -eq $SUCCESS ]; then
213ab2043b8SDevin Teske				# Access granted...
214ab2043b8SDevin Teske				break
215ab2043b8SDevin Teske			else
216ab2043b8SDevin Teske				# Access denied...
217ab2043b8SDevin Teske				nfailures=$(( $nfailures + 1 ))
218ab2043b8SDevin Teske
219ab2043b8SDevin Teske				# introduce a short delay
220ab2043b8SDevin Teske				if [ $nfailures -lt $PASSWD_TRIES ]; then
221ab2043b8SDevin Teske					f_dialog_info "$msg_sorry_try_again"
222ab2043b8SDevin Teske					sleep 1
223ab2043b8SDevin Teske				fi
224ab2043b8SDevin Teske			fi
225ab2043b8SDevin Teske		done
226ab2043b8SDevin Teske
227ab2043b8SDevin Teske		#
228ab2043b8SDevin Teske		# If user exhausted number of allowed password tries, log
229ab2043b8SDevin Teske		# the security event and exit immediately.
230ab2043b8SDevin Teske		#
231ab2043b8SDevin Teske		if [ $nfailures -ge $PASSWD_TRIES ]; then
232ab2043b8SDevin Teske			msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
233ab2043b8SDevin Teske			logger -p auth.notice -t sudo " " \
234ab2043b8SDevin Teske				"$USER : $msg" \
235ab2043b8SDevin Teske				"; TTY=$(tty)" \
236ab2043b8SDevin Teske				"; PWD=$PWD"   \
237ab2043b8SDevin Teske				"; USER=root"  \
238ab2043b8SDevin Teske				"; COMMAND=$0"
239ab2043b8SDevin Teske			f_die 1 "sudo: $msg"
240ab2043b8SDevin Teske		fi
241ab2043b8SDevin Teske	fi
242ab2043b8SDevin Teske
243ab2043b8SDevin Teske	# Use xauth(1) to grant root the ability to use this X11/SSH session
244ab2043b8SDevin Teske	if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then
245ab2043b8SDevin Teske		f_have xauth || f_die 1 \
246ab2043b8SDevin Teske			"$msg_no_such_file_or_directory" "$pgm" "xauth"
247ab2043b8SDevin Teske		local HOSTNAME displaynum
248ab2043b8SDevin Teske		HOSTNAME=$(hostname)
249ab2043b8SDevin Teske		displaynum="${DISPLAY#*:}"
250ab2043b8SDevin Teske		xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \
251ab2043b8SDevin Teske			$HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \
252fb7d723eSDevin Teske			~root/.Xauthority merge - > /dev/null 2>&1'
253ab2043b8SDevin Teske	fi
254ab2043b8SDevin Teske
255ab2043b8SDevin Teske	# Re-execute ourselves with sudo(8)
256e14ddd1fSDevin Teske	f_dprintf "%s: Becoming root via sudo(8)..." mustberoot.subr
257ab2043b8SDevin Teske	if [ $ARGC -gt 0 ]; then
258ab2043b8SDevin Teske		exec sudo "$0" $ARGV
259ab2043b8SDevin Teske	else
260ab2043b8SDevin Teske		exec sudo "$0"
261ab2043b8SDevin Teske	fi
262ab2043b8SDevin Teske	exit $? # Never reached unless error
263ab2043b8SDevin Teske}
264ab2043b8SDevin Teske
265ab2043b8SDevin Teske# f_authenticate_some_user
266ab2043b8SDevin Teske#
267ab2043b8SDevin Teske# Only used if running as root and requires X11 (see USE_XDIALOG below).
268ab2043b8SDevin Teske# Prompts the user to enter a username and password to be authenticated via
269ab2043b8SDevin Teske# sudo(8) to proceed.
270ab2043b8SDevin Teske#
271ab2043b8SDevin Teske# The following environment variables effect functionality:
272ab2043b8SDevin Teske#
273ab2043b8SDevin Teske# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
274ab2043b8SDevin Teske# 	              that Xdialog(1) should be used instead of dialog(1).
275ab2043b8SDevin Teske#
276ab2043b8SDevin Teskef_authenticate_some_user()
277ab2043b8SDevin Teske{
278*74036c4dSDevin Teske	local msg hline height width
279ab2043b8SDevin Teske
280ab2043b8SDevin Teske	f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
281ab2043b8SDevin Teske
282ab2043b8SDevin Teske	#
283ab2043b8SDevin Teske	# Secure-mode has been requested.
284ab2043b8SDevin Teske	#
285ab2043b8SDevin Teske
286ab2043b8SDevin Teske	[ "$USE_XDIALOG" ] || f_die 1 "$msg_secure_mode_requires_x11"
287ab2043b8SDevin Teske	[ "$(id -u)" = "0" ] || f_die 1 "$msg_secure_mode_requires_root"
288ab2043b8SDevin Teske
289ab2043b8SDevin Teske	#
290ab2043b8SDevin Teske	# Prompt for sudo(8) credentials.
291ab2043b8SDevin Teske	#
292ab2043b8SDevin Teske
293ab2043b8SDevin Teske	msg="$msg_please_enter_username_password"
294ab2043b8SDevin Teske	hline="$hline_alnum_punc_tab_enter"
295*74036c4dSDevin Teske	f_xdialog_2inputsbox_size height width \
296ab2043b8SDevin Teske	                          "$DIALOG_TITLE"      \
297ab2043b8SDevin Teske	                          "$DIALOG_BACKTITLE"  \
298ab2043b8SDevin Teske	                          "$msg"               \
299ab2043b8SDevin Teske	                          "$field_username" "" \
300*74036c4dSDevin Teske	                          "$field_password" ""
301ab2043b8SDevin Teske	height=$(( $height + 2 )) # Add height for --password
302ab2043b8SDevin Teske
303ab2043b8SDevin Teske	#
304ab2043b8SDevin Teske	# Continue prompting until they either Cancel, succeed or exceed the
305ab2043b8SDevin Teske	# number of allowed failures.
306ab2043b8SDevin Teske	#
307ab2043b8SDevin Teske	local user_pass nfailures=0 retval
308ab2043b8SDevin Teske	while [ $nfailures -lt $PASSWD_TRIES ]; do
309ab2043b8SDevin Teske		user_pass=$( $DIALOG \
310ab2043b8SDevin Teske			--title "$DIALOG_TITLE"         \
311ab2043b8SDevin Teske			--backtitle "$DIALOG_BACKTITLE" \
312ab2043b8SDevin Teske			--hline "$hline"                \
313ab2043b8SDevin Teske			--ok-label "$msg_ok"            \
314ab2043b8SDevin Teske			--cancel-label "$msg_cancel"    \
315ab2043b8SDevin Teske			--password --2inputsbox "$msg"  \
316ab2043b8SDevin Teske			$height $width                  \
317ab2043b8SDevin Teske			"$field_username" ""            \
318ab2043b8SDevin Teske			"$field_password" ""            \
319fb7d723eSDevin Teske			2>&1 > /dev/null )
320ab2043b8SDevin Teske		retval=$?
321ab2043b8SDevin Teske
322ab2043b8SDevin Teske		# Catch X11-related errors
323ab2043b8SDevin Teske		[ $retval -eq 255 ] && f_die $retval "$user_pass"
324ab2043b8SDevin Teske
325ab2043b8SDevin Teske		# Exit if the user cancelled.
326ab2043b8SDevin Teske		[ $retval -eq $SUCCESS ] || exit $retval
327ab2043b8SDevin Teske
328ab2043b8SDevin Teske		#
329ab2043b8SDevin Teske		# Make sure the user exists and is non-root
330ab2043b8SDevin Teske		#
331ab2043b8SDevin Teske		local user password
332ab2043b8SDevin Teske		user="${user_pass%%/*}"
333ab2043b8SDevin Teske		password="${user_pass#*/}"
334ab2043b8SDevin Teske		unset user_pass # scrub memory
335ab2043b8SDevin Teske		if [ ! "$user" ]; then
336ab2043b8SDevin Teske			nfailures=$(( $nfailures + 1 ))
337ab2043b8SDevin Teske			f_dialog_msgbox "$msg_no_username"
338ab2043b8SDevin Teske			continue
339ab2043b8SDevin Teske		fi
340ab2043b8SDevin Teske		if [ ! "$SECURE_ALLOW_ROOT" ]; then
341ab2043b8SDevin Teske			case "$user" in
342ab2043b8SDevin Teske			root|toor)
343ab2043b8SDevin Teske				nfailures=$(( $nfailures + 1 ))
344fa2e39c8SDevin Teske				f_show_msg "$msg_user_disallowed" "$user"
345ab2043b8SDevin Teske				continue
346ab2043b8SDevin Teske			esac
347ab2043b8SDevin Teske		fi
348ab2043b8SDevin Teske		if ! f_quietly id "$user"; then
349ab2043b8SDevin Teske			nfailures=$(( $nfailures + 1 ))
350ab2043b8SDevin Teske			if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
351fa2e39c8SDevin Teske				f_show_msg "$msg_unknown_user" "$user"
352ab2043b8SDevin Teske			elif [ $nfailures -lt $PASSWD_TRIES ]; then
353ab2043b8SDevin Teske				f_dialog_info "$msg_sorry_try_again"
354ab2043b8SDevin Teske				sleep 1
355ab2043b8SDevin Teske			fi
356ab2043b8SDevin Teske			continue
357ab2043b8SDevin Teske		fi
358ab2043b8SDevin Teske
359ab2043b8SDevin Teske		#
360ab2043b8SDevin Teske		# Validate sudo(8) credentials for given user
361ab2043b8SDevin Teske		#
362ab2043b8SDevin Teske		su -m "$user" <<-EOF
363ab2043b8SDevin Teske			sh <<EOS
364ab2043b8SDevin Teske				sudo -k
365fb7d723eSDevin Teske				sudo -S -v 2> /dev/null <<EOP
366ab2043b8SDevin Teske				$password
367ab2043b8SDevin Teske				EOP
368ab2043b8SDevin Teske			EOS
369ab2043b8SDevin Teske		EOF
370ab2043b8SDevin Teske		retval=$?
371ab2043b8SDevin Teske		unset user
372ab2043b8SDevin Teske		unset password # scrub memory
373ab2043b8SDevin Teske
374ab2043b8SDevin Teske		if [ $retval -eq $SUCCESS ]; then
375ab2043b8SDevin Teske			# Access granted...
376ab2043b8SDevin Teske			break
377ab2043b8SDevin Teske		else
378ab2043b8SDevin Teske			# Access denied...
379ab2043b8SDevin Teske			nfailures=$(( $nfailures + 1 ))
380ab2043b8SDevin Teske
381ab2043b8SDevin Teske			# introduce a short delay
382ab2043b8SDevin Teske			if [ $nfailures -lt $PASSWD_TRIES ]; then
383ab2043b8SDevin Teske				f_dialog_info "$msg_sorry_try_again"
384ab2043b8SDevin Teske				sleep 1
385ab2043b8SDevin Teske			fi
386ab2043b8SDevin Teske		fi
387ab2043b8SDevin Teske	done
388ab2043b8SDevin Teske
389ab2043b8SDevin Teske	#
390ab2043b8SDevin Teske	# If user exhausted number of allowed password tries, log
391ab2043b8SDevin Teske	# the security event and exit immediately.
392ab2043b8SDevin Teske	#
393ab2043b8SDevin Teske	if [ $nfailures -ge $PASSWD_TRIES ]; then
394ab2043b8SDevin Teske		msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
395ab2043b8SDevin Teske		logger -p auth.notice -t sudo " " \
396ab2043b8SDevin Teske			"${SUDO_USER:-$USER} : $msg" \
397ab2043b8SDevin Teske			"; TTY=$(tty)"               \
398ab2043b8SDevin Teske			"; PWD=$PWD"                 \
399ab2043b8SDevin Teske			"; USER=root"                \
400ab2043b8SDevin Teske			"; COMMAND=$0"
401ab2043b8SDevin Teske		f_die 1 "sudo: $message"
402ab2043b8SDevin Teske	fi
403ab2043b8SDevin Teske}
404ab2043b8SDevin Teske
405ab2043b8SDevin Teske# f_mustberoot_init
406ab2043b8SDevin Teske#
407ab2043b8SDevin Teske# If not already root, make the switch to root by re-executing ourselves via
408ab2043b8SDevin Teske# sudo(8) using user-supplied credentials.
409ab2043b8SDevin Teske#
410ab2043b8SDevin Teske# The following environment variables effect functionality:
411ab2043b8SDevin Teske#
412ab2043b8SDevin Teske# 	SECURE        Either NULL or Non-NULL. If given a value will indicate
413ab2043b8SDevin Teske# 	              that (while running as root) sudo(8) authentication is
414ab2043b8SDevin Teske# 	              required to proceed.
415ab2043b8SDevin Teske#
416ab2043b8SDevin Teskef_mustberoot_init()
417ab2043b8SDevin Teske{
418ab2043b8SDevin Teske	if [ "$(id -u)" != "0" -a ! "$SECURE" ]; then
419ab2043b8SDevin Teske		f_become_root_via_sudo
420ab2043b8SDevin Teske	elif [ "$SECURE" ]; then
421ab2043b8SDevin Teske		f_authenticate_some_user
422ab2043b8SDevin Teske	fi
423ab2043b8SDevin Teske}
424ab2043b8SDevin Teske
42556961fd7SDevin Teske############################################################ MAIN
42656961fd7SDevin Teske
42756961fd7SDevin Teskef_dprintf "%s: Successfully loaded." mustberoot.subr
42856961fd7SDevin Teske
429ab2043b8SDevin Teskefi # ! $_MUSTBEROOT_SUBR
430