1\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
2\ All rights reserved.
3\ 
4\ Redistribution and use in source and binary forms, with or without
5\ modification, are permitted provided that the following conditions
6\ are met:
7\ 1. Redistributions of source code must retain the above copyright
8\    notice, this list of conditions and the following disclaimer.
9\ 2. Redistributions in binary form must reproduce the above copyright
10\    notice, this list of conditions and the following disclaimer in the
11\    documentation and/or other materials provided with the distribution.
12\ 
13\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16\ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23\ SUCH DAMAGE.
24\ 
25\ $FreeBSD$
26
27marker task-check-password.4th
28
29include /boot/screen.4th
30
3113 constant enter_key   \ The decimal ASCII value for Enter key
328  constant bs_key      \ The decimal ASCII value for Backspace key
3316 constant readmax     \ Maximum number of characters for the password
34
35variable readX          \ Current X offset (column)(used by read)
36variable read-start     \ Starting X offset (column)(used by read)
37
38create readval 16 allot \ input obtained (maximum 16 characters)
39variable readlen        \ input length
40
41\ This function blocks program flow (loops forever) until a key is pressed.
42\ The key that was pressed is added to the top of the stack in the form of its
43\ decimal ASCII representation. Note: the stack cannot be empty when this
44\ function starts or an underflow exception will occur. Simplest way to prevent
45\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is
46\ called by the read function. You need not call it directly. NOTE: arrow keys
47\ show as 0 on the stack
48\ 
49: sgetkey ( -- )
50
51   begin \ Loop forever
52      key? if \ Was a key pressed? (see loader(8))
53
54         drop \ Remove stack-cruft
55         key  \ Get the key that was pressed
56
57         \ Check key pressed (see loader(8)) and input limit
58         dup 0<> if ( and ) readlen @ readmax < if
59
60            \ Echo an asterisk (unless Backspace/Enter)
61            dup bs_key <> if ( and ) dup enter_key <> if
62                  ." *" \ Echo an asterisk
63            then then
64
65            exit \ Exit from the function
66         then then
67
68         \ Always allow Backspace and Enter
69         dup bs_key = if exit then
70         dup enter_key = if exit then
71
72      then
73      50 ms \ Sleep for 50 milliseconds (see loader(8))
74   again
75;
76
77: read ( String prompt -- )
78
79	0 25 at-xy           \ Move the cursor to the bottom-left
80	dup 1+ read-start !  \ Store X offset after the prompt
81	read-start @ readX ! \ copy value to the current X offset
82	0 readlen !          \ Initialize the read length
83	type                 \ Print the prompt
84
85	begin \ Loop forever
86
87		0 sgetkey \ Block here, waiting for a key to be pressed
88
89		\ We are not going to echo the password to the screen (for
90		\ security reasons). If Enter is pressed, we process the
91		\ password, otherwise augment the key to a string.
92
93		\ If the key that was entered was not Enter, advance
94		dup enter_key <> if
95			readX @ 1+ readX !     \ Advance the column
96			readlen @ 1+ readlen ! \ Increment input length
97		then
98
99		\ Handle backspacing
100		dup bs_key = if
101			readX @ 2 - readX !     \ Set new cursor position
102			readlen @ 2 - readlen ! \ Decrement input length
103
104			\ Don't move behind starting position
105			readX @ read-start @ < if
106				read-start @ readX !
107			then
108			readlen @ 0< if
109				0 readlen !
110			then
111
112			\ Reposition cursor and erase character
113			readX @ 25 at-xy 1 spaces readX @ 25 at-xy
114		then
115
116		dup enter_key = if
117			drop    \ Clean up stack cruft
118			10 emit \ Echo new line
119			exit
120		then
121
122		\ If not Backspace or Enter, store the character
123		dup bs_key <> if ( and ) dup enter_key <> if
124
125			\ store the character in our buffer
126			dup readval readlen @ 1- + c!
127
128		then then
129
130		drop \ drop the last key that was entered
131
132	again \ Enter was not pressed; repeat
133;
134
135: check-password ( -- )
136
137	\ Do not allow the user to proceed beyond this point if a boot-lock
138	\ password has been set (preventing even boot from proceeding)
139	s" bootlock_password" getenv dup -1 <> if
140		begin
141			s" Boot Password: " read ( prompt -- )
142			2dup readval readlen @ compare 0<>
143		while
144			3000 ms ." loader: incorrect password" 10 emit
145		repeat
146		2drop ( c-addr/u )
147	else
148		drop ( -1 ) \ getenv cruft
149	then
150
151	\ Exit if a password was not set
152	s" password" getenv -1 = if exit else drop then
153
154	\ We should prevent the user from visiting the menu or dropping to the
155	\ interactive loader(8) prompt, but still allow the machine to boot...
156
157	0 autoboot
158
159	\ Only reached if autoboot fails for any reason (including if/when
160	\ the user aborts/escapes the countdown sequence leading to boot).
161
162	s" password" getenv
163	begin
164		s" Password: " read ( prompt -- )
165		2dup readval readlen @ compare 0= if
166			2drop exit \ Correct password
167		then
168		3000 ms ." loader: incorrect password" 10 emit
169	again
170;
171