1\ Copyright (c) 2006-2015 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 26marker task-check-password.4th 27 28include /boot/screen.4th 29 30vocabulary password-processing 31only forth also password-processing definitions 32 3313 constant enter_key \ The decimal ASCII value for Enter key 348 constant bs_key \ The decimal ASCII value for Backspace key 3521 constant ctrl_u \ The decimal ASCII value for Ctrl-U sequence 36255 constant readmax \ Maximum number of characters for the password 37 38variable read-tick \ Twiddle position (used by read) 39variable read-start \ Starting X offset (column)(used by read) 40 41create readval readmax allot \ input obtained (up to readmax characters) 42variable readlen \ input length 43 44\ This function blocks program flow (loops forever) until a key is pressed. 45\ The key that was pressed is added to the top of the stack in the form of its 46\ decimal ASCII representation. Note: the stack cannot be empty when this 47\ function starts or an underflow exception will occur. Simplest way to prevent 48\ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is 49\ called by the read function. You need not call it directly. NOTE: arrow keys 50\ show as 0 on the stack 51\ 52: sgetkey ( -- ) 53 54 begin \ Loop forever 55 key? if \ Was a key pressed? (see loader(8)) 56 drop \ Remove stack-cruft 57 key \ Get the key that was pressed 58 59 \ Check key pressed (see loader(8)) and input limit 60 dup 0<> if ( and ) readlen @ readmax < if 61 \ Spin the twiddle and then exit this function 62 read-tick @ dup 1+ 4 mod read-tick ! 63 2 spaces 64 dup 0 = if ( 1 ) ." /" else 65 dup 1 = if ( 2 ) ." -" else 66 dup 2 = if ( 3 ) ." \" else 67 dup 3 = if ( 4 ) ." |" else 68 1 spaces 69 then then then then drop 70 read-start @ 25 at-xy 71 exit 72 then then 73 74 \ Always allow Backspace, Enter, and Ctrl-U 75 dup bs_key = if exit then 76 dup enter_key = if exit then 77 dup ctrl_u = if exit then 78 then 79 50 ms \ Sleep for 50 milliseconds (see loader(8)) 80 again 81; 82 83: cfill ( c c-addr/u -- ) 84 begin dup 0> while 85 -rot 2dup c! 1+ rot 1- 86 repeat 2drop drop 87; 88 89: read-reset ( -- ) 90 0 readlen ! 91 0 readval readmax cfill 92; 93 94: read ( c-addr/u -- ) \ Expects string prompt as stack input 95 96 0 25 at-xy \ Move the cursor to the bottom-left 97 dup 1+ read-start ! \ Store X offset after the prompt 98 0 readlen ! \ Initialize the read length 99 type \ Print the prompt 100 101 begin \ Loop forever 102 103 0 sgetkey \ Block here, waiting for a key to be pressed 104 105 \ We are not going to echo the password to the screen (for 106 \ security reasons). If Enter is pressed, we process the 107 \ password, otherwise augment the key to a string. 108 109 dup enter_key = if 110 drop \ Clean up stack cruft 111 3 spaces \ Erase the twiddle 112 10 emit \ Echo new line 113 exit 114 else dup ctrl_u = if 115 3 spaces read-start @ 25 at-xy \ Erase the twiddle 116 0 readlen ! \ Reset input to NULL 117 else dup bs_key = if 118 readlen @ 1 - dup readlen ! \ Decrement input length 119 dup 0< if drop 0 dup readlen ! then \ Don't go negative 120 0= if 3 spaces read-start @ 25 at-xy then \ Twiddle 121 else dup \ Store the character 122 \ NB: sgetkey prevents overflow by way of blocking 123 \ at readmax except for Backspace or Enter 124 readlen @ 1+ dup readlen ! 1- readval + c! 125 then then then 126 127 drop \ last key pressed 128 again \ Enter was not pressed; repeat 129; 130 131only forth definitions also password-processing also support-functions 132 133: check-password ( -- ) 134 135 \ Do not allow the user to proceed beyond this point if a boot-lock 136 \ password has been set (preventing even boot from proceeding) 137 s" bootlock_password" getenv dup -1 <> if 138 dup readmax > if drop readmax then 139 begin 140 s" Boot Password: " read ( prompt -- ) 141 2dup readval readlen @ compare 0<> 142 while 143 3000 ms ." loader: incorrect password" 10 emit 144 repeat 145 2drop read-reset 146 else drop then 147 148 \ Prompt for GEOM ELI (geli(8)) passphrase if enabled 149 s" geom_eli_passphrase_prompt" getenv dup -1 <> if 150 s" YES" compare-insensitive 0= if 151 s" GELI Passphrase: " read ( prompt -- ) 152 readval readlen @ s" kern.geom.eli.passphrase" setenv 153 read-reset 154 then 155 else drop then 156 157 \ Exit if a password was not set 158 s" password" getenv -1 = if exit else drop then 159 160 \ We should prevent the user from visiting the menu or dropping to the 161 \ interactive loader(8) prompt, but still allow the machine to boot... 162 163 any_conf_read? if load_kernel load_modules then 164 0 autoboot 165 166 \ Only reached if autoboot fails for any reason (including if/when 167 \ the user aborts/escapes the countdown sequence leading to boot). 168 169 s" password" getenv dup readmax > if drop readmax then 170 begin 171 s" Password: " read ( prompt -- ) 172 2dup readval readlen @ compare 0= if \ Correct password? 173 2drop read-reset exit 174 then 175 3000 ms ." loader: incorrect password" 10 emit 176 again 177; 178 179only forth definitions 180