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
|