Deleted Added
full compact
mustberoot.subr (251242) mustberoot.subr (251264)
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 251242 2013-06-02 05:45:25Z dteske $
27# $FreeBSD: head/usr.sbin/bsdconfig/share/mustberoot.subr 251264 2013-06-02 20:02:50Z 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{
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
80 local prompt hline height width rows msg
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
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 prompt=$( printf "$msg_you_are_not_root_but" bsdconfig )
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
94 msg=$( printf "$msg_always_try_sudo_when_run_as" "$USER" )
95 local menu_list="
96 'X' '$msg_cancel_exit'
97 '1' '$msg'
98 '2' '$msg_try_sudo_only_this_once'
99 " # END-QUOTE
99 msg=$( printf "$msg_you_are_not_root_but" bsdconfig )
100 hline="$hline_arrows_tab_enter"
100 hline="$hline_arrows_tab_enter"
101
101 eval f_dialog_menu_size height width rows \
102 \"\$DIALOG_TITLE\" \
103 \"\$DIALOG_BACKTITLE\" \
102 eval f_dialog_menu_size height width rows \
103 \"\$DIALOG_TITLE\" \
104 \"\$DIALOG_BACKTITLE\" \
104 \"\$msg\" \
105 \"\$prompt\" \
105 \"\$hline\" \
106 $menu_list
107
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\" \
106 \"\$hline\" \
107 $menu_list
108
109 local mtag
110 mtag=$( eval $DIALOG \
111 --title \"\$DIALOG_TITLE\" \
112 --backtitle \"\$DIALOG_BACKTITLE\" \
113 --hline \"\$hline\" \
114 --ok-label \"\$msg_ok\" \
115 --cancel-label \"\$msg_cancel\" \
115 --menu \"\$msg\" \
116 --menu \"\$prompt\" \
116 $height $width $rows \
117 $menu_list \
118 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
119 ) || f_die
120 f_dialog_data_sanitize mtag
121
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 #
117 $height $width $rows \
118 $menu_list \
119 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
120 ) || f_die
121 f_dialog_data_sanitize mtag
122
123 case "$mtag" in
124 X) # Cancel/Exit
125 f_die ;;
126 1) # Always try sudo(8) when run as $user
127 local err
128 if ! err=$( touch "$checkpath" 2>&1 ); then
129 f_dialog_msgbox "$err"
130 else
131 f_show_msg "$msg_created_path" "$checkpath"
132 fi
133 esac
134 else
135 #
136 # This user has created the path signing-off on sudo(8)-use
137 # but let's still give them a short/quick/unobtrusive reminder
138 #
139 f_dialog_info "$msg_becoming_root_via_sudo"
140 [ "$USE_XDIALOG" ] || sleep 0.6
141 fi
142
143 #
144 # Check sudo(8) access before prompting for password.
145 #
146 :| sudo -S -v 2> /dev/null
147 if [ $? -ne $SUCCESS ]; then
148 #
149 # sudo(8) access denied. Prompt for their password.
150 #
150 msg="$msg_please_enter_password"
151 prompt="$msg_please_enter_password"
151 hline="$hline_alnum_punc_tab_enter"
152 f_dialog_inputbox_size height width \
153 "$DIALOG_TITLE" \
154 "$DIALOG_BACKTITLE" \
152 hline="$hline_alnum_punc_tab_enter"
153 f_dialog_inputbox_size height width \
154 "$DIALOG_TITLE" \
155 "$DIALOG_BACKTITLE" \
155 "$msg" \
156 "$prompt" \
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" \
157 "$hline"
158
159 #
160 # Continue prompting until they either Cancel, succeed
161 # or exceed the number of allowed failures.
162 #
163 local password nfailures=0 retval
164 while [ $nfailures -lt $PASSWD_TRIES ]; do
165 if [ "$USE_XDIALOG" ]; then
166 password=$( $DIALOG \
167 --title "$DIALOG_TITLE" \
168 --backtitle "$DIALOG_BACKTITLE" \
169 --hline "$hline" \
170 --ok-label "$msg_ok" \
171 --cancel-label "$msg_cancel" \
171 --password --inputbox "$msg" \
172 --password --inputbox "$prompt" \
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 password=$( $DIALOG \
181 --title "$DIALOG_TITLE" \
182 --backtitle "$DIALOG_BACKTITLE" \
183 --hline "$hline" \
184 --ok-label "$msg_ok" \
185 --cancel-label "$msg_cancel" \
186 --insecure \
173 $height $width \
174 2>&1 > /dev/null )
175 retval=$?
176
177 # Catch X11-related errors
178 [ $retval -eq 255 ] &&
179 f_die $retval "$password"
180 else
181 password=$( $DIALOG \
182 --title "$DIALOG_TITLE" \
183 --backtitle "$DIALOG_BACKTITLE" \
184 --hline "$hline" \
185 --ok-label "$msg_ok" \
186 --cancel-label "$msg_cancel" \
187 --insecure \
187 --passwordbox "$msg" \
188 --passwordbox "$prompt" \
188 $height $width \
189 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
190 ) || exit $?
191 fi
192 debug= f_dialog_line_sanitize password
193
194 #
195 # Validate sudo(8) credentials
196 #
197 sudo -S -v 2> /dev/null <<-EOF
198 $password
199 EOF
200 retval=$?
201 unset password # scrub memory
202 if [ $retval -eq $SUCCESS ]; then
203 # Access granted...
204 break
205 else
206 # Access denied...
207 nfailures=$(( $nfailures + 1 ))
208
209 # introduce a short delay
210 if [ $nfailures -lt $PASSWD_TRIES ]; then
211 f_dialog_info "$msg_sorry_try_again"
212 sleep 1
213 fi
214 fi
215 done
216
217 #
218 # If user exhausted number of allowed password tries, log
219 # the security event and exit immediately.
220 #
221 if [ $nfailures -ge $PASSWD_TRIES ]; then
222 msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
223 logger -p auth.notice -t sudo " " \
224 "$USER : $msg" \
225 "; TTY=$(tty)" \
226 "; PWD=$PWD" \
227 "; USER=root" \
228 "; COMMAND=$0"
229 f_die 1 "sudo: $msg"
230 fi
231 fi
232
233 # Use xauth(1) to grant root the ability to use this X11/SSH session
234 if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then
235 f_have xauth || f_die 1 \
236 "$msg_no_such_file_or_directory" "$pgm" "xauth"
237 local HOSTNAME displaynum
238 HOSTNAME=$(hostname)
239 displaynum="${DISPLAY#*:}"
240 xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \
241 $HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \
242 ~root/.Xauthority merge - > /dev/null 2>&1'
243 fi
244
245 # Re-execute ourselves with sudo(8)
246 f_dprintf "%s: Becoming root via sudo(8)..." mustberoot.subr
247 if [ $ARGC -gt 0 ]; then
248 exec sudo "$0" $ARGV
249 else
250 exec sudo "$0"
251 fi
252 exit $? # Never reached unless error
253}
254
255# f_authenticate_some_user
256#
257# Only used if running as root and requires X11 (see USE_XDIALOG below).
258# Prompts the user to enter a username and password to be authenticated via
259# sudo(8) to proceed.
260#
261# The following environment variables effect functionality:
262#
263# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate
264# that Xdialog(1) should be used instead of dialog(1).
265#
266f_authenticate_some_user()
267{
268 local msg hline height width
269
270 f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
271
272 #
273 # Secure-mode has been requested.
274 #
275
276 [ "$USE_XDIALOG" ] || f_die 1 "$msg_secure_mode_requires_x11"
277 [ "$(id -u)" = "0" ] || f_die 1 "$msg_secure_mode_requires_root"
278
279 #
280 # Prompt for sudo(8) credentials.
281 #
282
283 msg="$msg_please_enter_username_password"
284 hline="$hline_alnum_punc_tab_enter"
285 f_xdialog_2inputsbox_size height width \
286 "$DIALOG_TITLE" \
287 "$DIALOG_BACKTITLE" \
288 "$msg" \
289 "$field_username" "" \
290 "$field_password" ""
291 height=$(( $height + 2 )) # Add height for --password
292
293 #
294 # Continue prompting until they either Cancel, succeed or exceed the
295 # number of allowed failures.
296 #
297 local user_pass nfailures=0 retval
298 while [ $nfailures -lt $PASSWD_TRIES ]; do
299 user_pass=$( $DIALOG \
300 --title "$DIALOG_TITLE" \
301 --backtitle "$DIALOG_BACKTITLE" \
302 --hline "$hline" \
303 --ok-label "$msg_ok" \
304 --cancel-label "$msg_cancel" \
305 --password --2inputsbox "$msg" \
306 $height $width \
307 "$field_username" "" \
308 "$field_password" "" \
309 2>&1 > /dev/null )
310 retval=$?
311
312 # Catch X11-related errors
313 [ $retval -eq 255 ] && f_die $retval "$user_pass"
314
315 # Exit if the user cancelled.
316 [ $retval -eq $SUCCESS ] || exit $retval
317
318 #
319 # Make sure the user exists and is non-root
320 #
321 local user password
322 user="${user_pass%%/*}"
323 password="${user_pass#*/}"
324 unset user_pass # scrub memory
325 if [ ! "$user" ]; then
326 nfailures=$(( $nfailures + 1 ))
327 f_dialog_msgbox "$msg_no_username"
328 continue
329 fi
330 if [ ! "$SECURE_ALLOW_ROOT" ]; then
331 case "$user" in
332 root|toor)
333 nfailures=$(( $nfailures + 1 ))
334 f_show_msg "$msg_user_disallowed" "$user"
335 continue
336 esac
337 fi
338 if ! f_quietly id "$user"; then
339 nfailures=$(( $nfailures + 1 ))
340 if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
341 f_show_msg "$msg_unknown_user" "$user"
342 elif [ $nfailures -lt $PASSWD_TRIES ]; then
343 f_dialog_info "$msg_sorry_try_again"
344 sleep 1
345 fi
346 continue
347 fi
348
349 #
350 # Validate sudo(8) credentials for given user
351 #
352 su -m "$user" <<-EOF
353 sh <<EOS
354 sudo -k
355 sudo -S -v 2> /dev/null <<EOP
356 $password
357 EOP
358 EOS
359 EOF
360 retval=$?
361 unset user
362 unset password # scrub memory
363
364 if [ $retval -eq $SUCCESS ]; then
365 # Access granted...
366 break
367 else
368 # Access denied...
369 nfailures=$(( $nfailures + 1 ))
370
371 # introduce a short delay
372 if [ $nfailures -lt $PASSWD_TRIES ]; then
373 f_dialog_info "$msg_sorry_try_again"
374 sleep 1
375 fi
376 fi
377 done
378
379 #
380 # If user exhausted number of allowed password tries, log
381 # the security event and exit immediately.
382 #
383 if [ $nfailures -ge $PASSWD_TRIES ]; then
384 msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
385 logger -p auth.notice -t sudo " " \
386 "${SUDO_USER:-$USER} : $msg" \
387 "; TTY=$(tty)" \
388 "; PWD=$PWD" \
389 "; USER=root" \
390 "; COMMAND=$0"
391 f_die 1 "sudo: $message"
392 fi
393}
394
395# f_mustberoot_init
396#
397# If not already root, make the switch to root by re-executing ourselves via
398# sudo(8) using user-supplied credentials.
399#
400# The following environment variables effect functionality:
401#
402# SECURE Either NULL or Non-NULL. If given a value will indicate
403# that (while running as root) sudo(8) authentication is
404# required to proceed.
405#
406f_mustberoot_init()
407{
408 if [ "$(id -u)" != "0" -a ! "$SECURE" ]; then
409 f_become_root_via_sudo
410 elif [ "$SECURE" ]; then
411 f_authenticate_some_user
412 fi
413}
414
415############################################################ MAIN
416
417f_dprintf "%s: Successfully loaded." mustberoot.subr
418
419fi # ! $_MUSTBEROOT_SUBR
189 $height $width \
190 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
191 ) || exit $?
192 fi
193 debug= f_dialog_line_sanitize password
194
195 #
196 # Validate sudo(8) credentials
197 #
198 sudo -S -v 2> /dev/null <<-EOF
199 $password
200 EOF
201 retval=$?
202 unset password # scrub memory
203 if [ $retval -eq $SUCCESS ]; then
204 # Access granted...
205 break
206 else
207 # Access denied...
208 nfailures=$(( $nfailures + 1 ))
209
210 # introduce a short delay
211 if [ $nfailures -lt $PASSWD_TRIES ]; then
212 f_dialog_info "$msg_sorry_try_again"
213 sleep 1
214 fi
215 fi
216 done
217
218 #
219 # If user exhausted number of allowed password tries, log
220 # the security event and exit immediately.
221 #
222 if [ $nfailures -ge $PASSWD_TRIES ]; then
223 msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
224 logger -p auth.notice -t sudo " " \
225 "$USER : $msg" \
226 "; TTY=$(tty)" \
227 "; PWD=$PWD" \
228 "; USER=root" \
229 "; COMMAND=$0"
230 f_die 1 "sudo: $msg"
231 fi
232 fi
233
234 # Use xauth(1) to grant root the ability to use this X11/SSH session
235 if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then
236 f_have xauth || f_die 1 \
237 "$msg_no_such_file_or_directory" "$pgm" "xauth"
238 local HOSTNAME displaynum
239 HOSTNAME=$(hostname)
240 displaynum="${DISPLAY#*:}"
241 xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \
242 $HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \
243 ~root/.Xauthority merge - > /dev/null 2>&1'
244 fi
245
246 # Re-execute ourselves with sudo(8)
247 f_dprintf "%s: Becoming root via sudo(8)..." mustberoot.subr
248 if [ $ARGC -gt 0 ]; then
249 exec sudo "$0" $ARGV
250 else
251 exec sudo "$0"
252 fi
253 exit $? # Never reached unless error
254}
255
256# f_authenticate_some_user
257#
258# Only used if running as root and requires X11 (see USE_XDIALOG below).
259# Prompts the user to enter a username and password to be authenticated via
260# sudo(8) to proceed.
261#
262# The following environment variables effect functionality:
263#
264# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate
265# that Xdialog(1) should be used instead of dialog(1).
266#
267f_authenticate_some_user()
268{
269 local msg hline height width
270
271 f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
272
273 #
274 # Secure-mode has been requested.
275 #
276
277 [ "$USE_XDIALOG" ] || f_die 1 "$msg_secure_mode_requires_x11"
278 [ "$(id -u)" = "0" ] || f_die 1 "$msg_secure_mode_requires_root"
279
280 #
281 # Prompt for sudo(8) credentials.
282 #
283
284 msg="$msg_please_enter_username_password"
285 hline="$hline_alnum_punc_tab_enter"
286 f_xdialog_2inputsbox_size height width \
287 "$DIALOG_TITLE" \
288 "$DIALOG_BACKTITLE" \
289 "$msg" \
290 "$field_username" "" \
291 "$field_password" ""
292 height=$(( $height + 2 )) # Add height for --password
293
294 #
295 # Continue prompting until they either Cancel, succeed or exceed the
296 # number of allowed failures.
297 #
298 local user_pass nfailures=0 retval
299 while [ $nfailures -lt $PASSWD_TRIES ]; do
300 user_pass=$( $DIALOG \
301 --title "$DIALOG_TITLE" \
302 --backtitle "$DIALOG_BACKTITLE" \
303 --hline "$hline" \
304 --ok-label "$msg_ok" \
305 --cancel-label "$msg_cancel" \
306 --password --2inputsbox "$msg" \
307 $height $width \
308 "$field_username" "" \
309 "$field_password" "" \
310 2>&1 > /dev/null )
311 retval=$?
312
313 # Catch X11-related errors
314 [ $retval -eq 255 ] && f_die $retval "$user_pass"
315
316 # Exit if the user cancelled.
317 [ $retval -eq $SUCCESS ] || exit $retval
318
319 #
320 # Make sure the user exists and is non-root
321 #
322 local user password
323 user="${user_pass%%/*}"
324 password="${user_pass#*/}"
325 unset user_pass # scrub memory
326 if [ ! "$user" ]; then
327 nfailures=$(( $nfailures + 1 ))
328 f_dialog_msgbox "$msg_no_username"
329 continue
330 fi
331 if [ ! "$SECURE_ALLOW_ROOT" ]; then
332 case "$user" in
333 root|toor)
334 nfailures=$(( $nfailures + 1 ))
335 f_show_msg "$msg_user_disallowed" "$user"
336 continue
337 esac
338 fi
339 if ! f_quietly id "$user"; then
340 nfailures=$(( $nfailures + 1 ))
341 if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
342 f_show_msg "$msg_unknown_user" "$user"
343 elif [ $nfailures -lt $PASSWD_TRIES ]; then
344 f_dialog_info "$msg_sorry_try_again"
345 sleep 1
346 fi
347 continue
348 fi
349
350 #
351 # Validate sudo(8) credentials for given user
352 #
353 su -m "$user" <<-EOF
354 sh <<EOS
355 sudo -k
356 sudo -S -v 2> /dev/null <<EOP
357 $password
358 EOP
359 EOS
360 EOF
361 retval=$?
362 unset user
363 unset password # scrub memory
364
365 if [ $retval -eq $SUCCESS ]; then
366 # Access granted...
367 break
368 else
369 # Access denied...
370 nfailures=$(( $nfailures + 1 ))
371
372 # introduce a short delay
373 if [ $nfailures -lt $PASSWD_TRIES ]; then
374 f_dialog_info "$msg_sorry_try_again"
375 sleep 1
376 fi
377 fi
378 done
379
380 #
381 # If user exhausted number of allowed password tries, log
382 # the security event and exit immediately.
383 #
384 if [ $nfailures -ge $PASSWD_TRIES ]; then
385 msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
386 logger -p auth.notice -t sudo " " \
387 "${SUDO_USER:-$USER} : $msg" \
388 "; TTY=$(tty)" \
389 "; PWD=$PWD" \
390 "; USER=root" \
391 "; COMMAND=$0"
392 f_die 1 "sudo: $message"
393 fi
394}
395
396# f_mustberoot_init
397#
398# If not already root, make the switch to root by re-executing ourselves via
399# sudo(8) using user-supplied credentials.
400#
401# The following environment variables effect functionality:
402#
403# SECURE Either NULL or Non-NULL. If given a value will indicate
404# that (while running as root) sudo(8) authentication is
405# required to proceed.
406#
407f_mustberoot_init()
408{
409 if [ "$(id -u)" != "0" -a ! "$SECURE" ]; then
410 f_become_root_via_sudo
411 elif [ "$SECURE" ]; then
412 f_authenticate_some_user
413 fi
414}
415
416############################################################ MAIN
417
418f_dprintf "%s: Successfully loaded." mustberoot.subr
419
420fi # ! $_MUSTBEROOT_SUBR