freebsd-dev/sys/boot/forth/check-password.4th
Devin Teske 9d93dba489 Fix a regression caused by SVN r222417.
Prior to r222417, setting `password' in loader.conf(5) did not prevent boot
but instead only prevented changes to boot options by prompting for password
if autoboot failed or the user interrupted the countdown sequence.
After r222417 the same machine with `password' set in loader.conf(5) would no
longer boot without _always_ entering the password.

This patch restores the old (8.x and older) functionality for password in
loader.conf(5) while adding a new bootlock_password feature to replace the
edge-case should anybody desire the regressed functionality (HINT: great for
PXE servers and/or private distributions).

loader.conf(5) was updated to be more clear with-respect to password setting
(previous text was misleading).

Documentation (loader.conf(5) and check-password.4th(8)) has been updated to
include notes on the new bootlock_password setting.

Special thanks to Alex Verbod for bringing this to my attention and helping to
refine the loader.conf(5) text.

PR:		conf/170110
Submitted by:	Vitaly Zakharov <ded3axap@gmail.com>
Reviewed by:	Alexander Verbod <alexander.verbod@gmail.com>
2012-12-12 17:49:01 +00:00

171 lines
5.5 KiB
Forth

\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
\ modification, are permitted provided that the following conditions
\ are met:
\ 1. Redistributions of source code must retain the above copyright
\ notice, this list of conditions and the following disclaimer.
\ 2. Redistributions in binary form must reproduce the above copyright
\ notice, this list of conditions and the following disclaimer in the
\ documentation and/or other materials provided with the distribution.
\
\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
\ $FreeBSD$
marker task-check-password.4th
include /boot/screen.4th
13 constant enter_key \ The decimal ASCII value for Enter key
8 constant bs_key \ The decimal ASCII value for Backspace key
16 constant readmax \ Maximum number of characters for the password
variable readX \ Current X offset (column)(used by read)
variable read-start \ Starting X offset (column)(used by read)
create readval 16 allot \ input obtained (maximum 16 characters)
variable readlen \ input length
\ This function blocks program flow (loops forever) until a key is pressed.
\ The key that was pressed is added to the top of the stack in the form of its
\ decimal ASCII representation. Note: the stack cannot be empty when this
\ function starts or an underflow exception will occur. Simplest way to prevent
\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is
\ called by the read function. You need not call it directly. NOTE: arrow keys
\ show as 0 on the stack
\
: sgetkey ( -- )
begin \ Loop forever
key? if \ Was a key pressed? (see loader(8))
drop \ Remove stack-cruft
key \ Get the key that was pressed
\ Check key pressed (see loader(8)) and input limit
dup 0<> if ( and ) readlen @ readmax < if
\ Echo an asterisk (unless Backspace/Enter)
dup bs_key <> if ( and ) dup enter_key <> if
." *" \ Echo an asterisk
then then
exit \ Exit from the function
then then
\ Always allow Backspace and Enter
dup bs_key = if exit then
dup enter_key = if exit then
then
50 ms \ Sleep for 50 milliseconds (see loader(8))
again
;
: read ( String prompt -- )
0 25 at-xy \ Move the cursor to the bottom-left
dup 1+ read-start ! \ Store X offset after the prompt
read-start @ readX ! \ copy value to the current X offset
0 readlen ! \ Initialize the read length
type \ Print the prompt
begin \ Loop forever
0 sgetkey \ Block here, waiting for a key to be pressed
\ We are not going to echo the password to the screen (for
\ security reasons). If Enter is pressed, we process the
\ password, otherwise augment the key to a string.
\ If the key that was entered was not Enter, advance
dup enter_key <> if
readX @ 1+ readX ! \ Advance the column
readlen @ 1+ readlen ! \ Increment input length
then
\ Handle backspacing
dup bs_key = if
readX @ 2 - readX ! \ Set new cursor position
readlen @ 2 - readlen ! \ Decrement input length
\ Don't move behind starting position
readX @ read-start @ < if
read-start @ readX !
then
readlen @ 0< if
0 readlen !
then
\ Reposition cursor and erase character
readX @ 25 at-xy 1 spaces readX @ 25 at-xy
then
dup enter_key = if
drop \ Clean up stack cruft
10 emit \ Echo new line
exit
then
\ If not Backspace or Enter, store the character
dup bs_key <> if ( and ) dup enter_key <> if
\ store the character in our buffer
dup readval readlen @ 1- + c!
then then
drop \ drop the last key that was entered
again \ Enter was not pressed; repeat
;
: check-password ( -- )
\ Do not allow the user to proceed beyond this point if a boot-lock
\ password has been set (preventing even boot from proceeding)
s" bootlock_password" getenv dup -1 <> if
begin
s" Boot Password: " read ( prompt -- )
2dup readval readlen @ compare 0<>
while
3000 ms ." loader: incorrect password" 10 emit
repeat
2drop ( c-addr/u )
else
drop ( -1 ) \ getenv cruft
then
\ Exit if a password was not set
s" password" getenv -1 = if exit else drop then
\ We should prevent the user from visiting the menu or dropping to the
\ interactive loader(8) prompt, but still allow the machine to boot...
0 autoboot
\ Only reached if autoboot fails for any reason (including if/when
\ the user aborts/escapes the countdown sequence leading to boot).
s" password" getenv
begin
s" Password: " read ( prompt -- )
2dup readval readlen @ compare 0= if
2drop exit \ Correct password
then
3000 ms ." loader: incorrect password" 10 emit
again
;