This was previously an unconditional screen clear, regardless of whether or not we would be prompting for any passwords. This is pointless, given that the screen clear is only there to put our screen into a consistent state before we draw the prompts and do cursor manipulation. This is also the only screen clear besides that to draw the menu. One can now see early pre-loader and loader output with the menu disabled, which may be useful for diagnostics. Reported by: ian MFC after: 3 days
139 lines
3.9 KiB
Lua
139 lines
3.9 KiB
Lua
--
|
|
-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
--
|
|
-- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
|
|
-- Copyright (C) 2018 Kyle Evans <kevans@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$
|
|
--
|
|
|
|
local core = require("core")
|
|
local screen = require("screen")
|
|
|
|
local password = {}
|
|
|
|
local INCORRECT_PASSWORD = "loader: incorrect password"
|
|
-- Asterisks as a password mask
|
|
local show_password_mask = false
|
|
local twiddle_chars = {"/", "-", "\\", "|"}
|
|
local screen_setup = false
|
|
|
|
-- Module exports
|
|
function password.read(prompt_length)
|
|
local str = ""
|
|
local twiddle_pos = 1
|
|
|
|
local function draw_twiddle()
|
|
printc(twiddle_chars[twiddle_pos])
|
|
-- Reset cursor to just after the password prompt
|
|
screen.setcursor(prompt_length + 2, screen.default_y)
|
|
twiddle_pos = (twiddle_pos % #twiddle_chars) + 1
|
|
end
|
|
|
|
-- Space between the prompt and any on-screen feedback
|
|
printc(" ")
|
|
while true do
|
|
local ch = io.getchar()
|
|
if ch == core.KEY_ENTER then
|
|
break
|
|
end
|
|
if ch == core.KEY_BACKSPACE or ch == core.KEY_DELETE then
|
|
if #str > 0 then
|
|
if show_password_mask then
|
|
printc("\008 \008")
|
|
else
|
|
draw_twiddle()
|
|
end
|
|
str = str:sub(1, #str - 1)
|
|
end
|
|
else
|
|
if show_password_mask then
|
|
printc("*")
|
|
else
|
|
draw_twiddle()
|
|
end
|
|
str = str .. string.char(ch)
|
|
end
|
|
end
|
|
return str
|
|
end
|
|
|
|
function password.check()
|
|
-- pwd is optionally supplied if we want to check it
|
|
local function doPrompt(prompt, pwd)
|
|
local attempts = 1
|
|
|
|
local function clear_incorrect_text_prompt()
|
|
printc("\r" .. string.rep(" ", #INCORRECT_PASSWORD))
|
|
end
|
|
|
|
if not screen_setup then
|
|
screen.clear()
|
|
screen.defcursor()
|
|
screen_setup = true
|
|
end
|
|
|
|
while true do
|
|
if attempts > 1 then
|
|
clear_incorrect_text_prompt()
|
|
end
|
|
screen.defcursor()
|
|
printc(prompt)
|
|
local read_pwd = password.read(#prompt)
|
|
if pwd == nil or pwd == read_pwd then
|
|
-- Clear the prompt + twiddle
|
|
printc(string.rep(" ", #prompt + 5))
|
|
return read_pwd
|
|
end
|
|
printc("\n" .. INCORRECT_PASSWORD)
|
|
attempts = attempts + 1
|
|
loader.delay(3*1000*1000)
|
|
end
|
|
end
|
|
local function compare(prompt, pwd)
|
|
if pwd == nil then
|
|
return
|
|
end
|
|
doPrompt(prompt, pwd)
|
|
end
|
|
|
|
local boot_pwd = loader.getenv("bootlock_password")
|
|
compare("Bootlock password:", boot_pwd)
|
|
|
|
local geli_prompt = loader.getenv("geom_eli_passphrase_prompt")
|
|
if geli_prompt ~= nil and geli_prompt:lower() == "yes" then
|
|
local passphrase = doPrompt("GELI Passphrase:")
|
|
loader.setenv("kern.geom.eli.passphrase", passphrase)
|
|
end
|
|
|
|
local pwd = loader.getenv("password")
|
|
if pwd ~= nil then
|
|
core.autoboot()
|
|
end
|
|
compare("Loader password:", pwd)
|
|
end
|
|
|
|
return password
|