summaryrefslogtreecommitdiffstats
path: root/stand/forth/check-password.4th
blob: d41777c8bd2a67636bb054202a9c849598a63767 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
\ Copyright (c) 2006-2015 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

vocabulary password-processing
only forth also password-processing definitions

13  constant enter_key       \ The decimal ASCII value for Enter key
8   constant bs_key          \ The decimal ASCII value for Backspace key
21  constant ctrl_u          \ The decimal ASCII value for Ctrl-U sequence
255 constant readmax         \ Maximum number of characters for the password

variable read-tick           \ Twiddle position (used by read)
variable read-start          \ Starting X offset (column)(used by read)

create readval readmax allot \ input obtained (up to readmax 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
				\ Spin the twiddle and then exit this function
				read-tick @ dup 1+ 4 mod read-tick !
				2 spaces
				dup 0 = if ( 1 ) ." /" else
				dup 1 = if ( 2 ) ." -" else
				dup 2 = if ( 3 ) ." \" else
				dup 3 = if ( 4 ) ." |" else
					1 spaces
				then then then then drop
				read-start @ 25 at-xy
				exit
			then then

			\ Always allow Backspace, Enter, and Ctrl-U
			dup bs_key = if exit then
			dup enter_key = if exit then
			dup ctrl_u = if exit then
		then
		50 ms \ Sleep for 50 milliseconds (see loader(8))
	again
;

: cfill ( c c-addr/u -- )
	begin dup 0> while
		-rot 2dup c! 1+ rot 1-
	repeat 2drop drop
;

: read-reset ( -- )
	0 readlen !
	0 readval readmax cfill
;

: read ( c-addr/u -- ) \ Expects string prompt as stack input

	0 25 at-xy           \ Move the cursor to the bottom-left
	dup 1+ read-start !  \ Store X offset after the prompt
	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.

		dup enter_key = if
			drop     \ Clean up stack cruft
			3 spaces \ Erase the twiddle
			10 emit  \ Echo new line
			exit
		else dup ctrl_u = if
			3 spaces read-start @ 25 at-xy \ Erase the twiddle
			0 readlen ! \ Reset input to NULL
		else dup bs_key = if
			readlen @ 1 - dup readlen ! \ Decrement input length
			dup 0< if drop 0 dup readlen ! then \ Don't go negative
			0= if 3 spaces read-start @ 25 at-xy then \ Twiddle
		else dup \ Store the character
			\ NB: sgetkey prevents overflow by way of blocking
			\     at readmax except for Backspace or Enter
			readlen @ 1+ dup readlen ! 1- readval + c!
		then then then

		drop \ last key pressed
	again \ Enter was not pressed; repeat
;

only forth definitions also password-processing

: 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
		dup readmax > if drop readmax then
		begin
			s" Boot Password: " read ( prompt -- )
			2dup readval readlen @ compare 0<>
		while
			3000 ms ." loader: incorrect password" 10 emit
		repeat
		2drop read-reset
	else drop then

	\ Prompt for GEOM ELI (geli(8)) passphrase if enabled
	s" geom_eli_passphrase_prompt" getenv dup -1 <> if
		s" YES" compare-insensitive 0= if
			s" GELI Passphrase: " read ( prompt -- )
			readval readlen @ s" kern.geom.eli.passphrase" setenv
			read-reset
		then
	else drop 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 dup readmax > if drop readmax then
	begin
		s" Password: " read ( prompt -- )
		2dup readval readlen @ compare 0= if \ Correct password?
			2drop read-reset exit
		then
		3000 ms ." loader: incorrect password" 10 emit
	again
;

only forth definitions
OpenPOWER on IntegriCloud