1244158Sdteske\ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
2222417Sjulian\ All rights reserved.
3222417Sjulian\ 
4222417Sjulian\ Redistribution and use in source and binary forms, with or without
5222417Sjulian\ modification, are permitted provided that the following conditions
6222417Sjulian\ are met:
7222417Sjulian\ 1. Redistributions of source code must retain the above copyright
8222417Sjulian\    notice, this list of conditions and the following disclaimer.
9222417Sjulian\ 2. Redistributions in binary form must reproduce the above copyright
10222417Sjulian\    notice, this list of conditions and the following disclaimer in the
11222417Sjulian\    documentation and/or other materials provided with the distribution.
12222417Sjulian\ 
13222417Sjulian\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14222417Sjulian\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15222417Sjulian\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16222417Sjulian\ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17222417Sjulian\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18222417Sjulian\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19222417Sjulian\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20222417Sjulian\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21222417Sjulian\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22222417Sjulian\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23222417Sjulian\ SUCH DAMAGE.
24222417Sjulian\ 
25222417Sjulian\ $FreeBSD$
26222417Sjulian
27222417Sjulianmarker task-check-password.4th
28222417Sjulian
29222417Sjulianinclude /boot/screen.4th
30222417Sjulian
31222417Sjulian13 constant enter_key   \ The decimal ASCII value for Enter key
32222417Sjulian8  constant bs_key      \ The decimal ASCII value for Backspace key
33222417Sjulian16 constant readmax     \ Maximum number of characters for the password
34222417Sjulian
35222417Sjulianvariable readX          \ Current X offset (column)(used by read)
36222417Sjulianvariable read-start     \ Starting X offset (column)(used by read)
37222417Sjulian
38222417Sjuliancreate readval 16 allot \ input obtained (maximum 16 characters)
39222417Sjulianvariable readlen        \ input length
40222417Sjulian
41222417Sjulian\ This function blocks program flow (loops forever) until a key is pressed.
42222417Sjulian\ The key that was pressed is added to the top of the stack in the form of its
43222417Sjulian\ decimal ASCII representation. Note: the stack cannot be empty when this
44222417Sjulian\ function starts or an underflow exception will occur. Simplest way to prevent
45222417Sjulian\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is
46222417Sjulian\ called by the read function. You need not call it directly. NOTE: arrow keys
47222417Sjulian\ show as 0 on the stack
48222417Sjulian\ 
49222417Sjulian: sgetkey ( -- )
50222417Sjulian
51222417Sjulian   begin \ Loop forever
52222417Sjulian      key? if \ Was a key pressed? (see loader(8))
53222417Sjulian
54222417Sjulian         drop \ Remove stack-cruft
55222417Sjulian         key  \ Get the key that was pressed
56222417Sjulian
57222417Sjulian         \ Check key pressed (see loader(8)) and input limit
58222417Sjulian         dup 0<> if ( and ) readlen @ readmax < if
59222417Sjulian
60222417Sjulian            \ Echo an asterisk (unless Backspace/Enter)
61222417Sjulian            dup bs_key <> if ( and ) dup enter_key <> if
62222417Sjulian                  ." *" \ Echo an asterisk
63222417Sjulian            then then
64222417Sjulian
65222417Sjulian            exit \ Exit from the function
66222417Sjulian         then then
67222417Sjulian
68222417Sjulian         \ Always allow Backspace and Enter
69222417Sjulian         dup bs_key = if exit then
70222417Sjulian         dup enter_key = if exit then
71222417Sjulian
72222417Sjulian      then
73222417Sjulian      50 ms \ Sleep for 50 milliseconds (see loader(8))
74222417Sjulian   again
75222417Sjulian;
76222417Sjulian
77244158Sdteske: read ( String prompt -- )
78222417Sjulian
79222417Sjulian	0 25 at-xy           \ Move the cursor to the bottom-left
80222417Sjulian	dup 1+ read-start !  \ Store X offset after the prompt
81222417Sjulian	read-start @ readX ! \ copy value to the current X offset
82222417Sjulian	0 readlen !          \ Initialize the read length
83222417Sjulian	type                 \ Print the prompt
84222417Sjulian
85222417Sjulian	begin \ Loop forever
86222417Sjulian
87222417Sjulian		0 sgetkey \ Block here, waiting for a key to be pressed
88222417Sjulian
89222417Sjulian		\ We are not going to echo the password to the screen (for
90222417Sjulian		\ security reasons). If Enter is pressed, we process the
91222417Sjulian		\ password, otherwise augment the key to a string.
92222417Sjulian
93222417Sjulian		\ If the key that was entered was not Enter, advance
94222417Sjulian		dup enter_key <> if
95222417Sjulian			readX @ 1+ readX !     \ Advance the column
96222417Sjulian			readlen @ 1+ readlen ! \ Increment input length
97222417Sjulian		then
98222417Sjulian
99222417Sjulian		\ Handle backspacing
100222417Sjulian		dup bs_key = if
101222417Sjulian			readX @ 2 - readX !     \ Set new cursor position
102222417Sjulian			readlen @ 2 - readlen ! \ Decrement input length
103222417Sjulian
104222417Sjulian			\ Don't move behind starting position
105222417Sjulian			readX @ read-start @ < if
106222417Sjulian				read-start @ readX !
107222417Sjulian			then
108222417Sjulian			readlen @ 0< if
109222417Sjulian				0 readlen !
110222417Sjulian			then
111222417Sjulian
112222417Sjulian			\ Reposition cursor and erase character
113222417Sjulian			readX @ 25 at-xy 1 spaces readX @ 25 at-xy
114222417Sjulian		then
115222417Sjulian
116222417Sjulian		dup enter_key = if
117222417Sjulian			drop    \ Clean up stack cruft
118222417Sjulian			10 emit \ Echo new line
119222417Sjulian			exit
120222417Sjulian		then
121222417Sjulian
122222417Sjulian		\ If not Backspace or Enter, store the character
123222417Sjulian		dup bs_key <> if ( and ) dup enter_key <> if
124222417Sjulian
125222417Sjulian			\ store the character in our buffer
126222417Sjulian			dup readval readlen @ 1- + c!
127222417Sjulian
128222417Sjulian		then then
129222417Sjulian
130222417Sjulian		drop \ drop the last key that was entered
131222417Sjulian
132222417Sjulian	again \ Enter was not pressed; repeat
133222417Sjulian;
134222417Sjulian
135222417Sjulian: check-password ( -- )
136222417Sjulian
137244158Sdteske	\ Do not allow the user to proceed beyond this point if a boot-lock
138244158Sdteske	\ password has been set (preventing even boot from proceeding)
139244158Sdteske	s" bootlock_password" getenv dup -1 <> if
140244158Sdteske		begin
141244158Sdteske			s" Boot Password: " read ( prompt -- )
142244158Sdteske			2dup readval readlen @ compare 0<>
143244158Sdteske		while
144244158Sdteske			3000 ms ." loader: incorrect password" 10 emit
145244158Sdteske		repeat
146244158Sdteske		2drop ( c-addr/u )
147244158Sdteske	else
148244158Sdteske		drop ( -1 ) \ getenv cruft
149222417Sjulian	then
150222417Sjulian
151244158Sdteske	\ Exit if a password was not set
152244158Sdteske	s" password" getenv -1 = if exit else drop then
153222417Sjulian
154244158Sdteske	\ We should prevent the user from visiting the menu or dropping to the
155244158Sdteske	\ interactive loader(8) prompt, but still allow the machine to boot...
156222417Sjulian
157244158Sdteske	0 autoboot
158244158Sdteske
159244158Sdteske	\ Only reached if autoboot fails for any reason (including if/when
160244158Sdteske	\ the user aborts/escapes the countdown sequence leading to boot).
161244158Sdteske
162244158Sdteske	s" password" getenv
163244158Sdteske	begin
164244158Sdteske		s" Password: " read ( prompt -- )
165222417Sjulian		2dup readval readlen @ compare 0= if
166222417Sjulian			2drop exit \ Correct password
167222417Sjulian		then
168244158Sdteske		3000 ms ." loader: incorrect password" 10 emit
169244158Sdteske	again
170222417Sjulian;
171