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