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