Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 01a0073e78 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -817,7 +817,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "init"
|
name = "init"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"dkl",
|
"dkl",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "init"
|
name = "init"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
pub mod bootstrap;
|
pub mod bootstrap;
|
||||||
pub mod connect_boot;
|
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod init_input;
|
pub mod init_input;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
@ -33,6 +33,7 @@ pub async fn bootstrap(cfg: Config) {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare system
|
||||||
let boot_version = utils::param("version").unwrap_or("current");
|
let boot_version = utils::param("version").unwrap_or("current");
|
||||||
let base_dir = &format!("/bootstrap/{boot_version}");
|
let base_dir = &format!("/bootstrap/{boot_version}");
|
||||||
|
|
||||||
|
|||||||
@ -56,27 +56,72 @@ pub async fn setup(devs: &[CryptDev]) {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PREV_PW: Mutex<String> = Mutex::const_new(String::new());
|
struct PrevPw {
|
||||||
|
pw: String,
|
||||||
async fn crypt_open(crypt_dev: &str, dev_path: &str) -> Result<()> {
|
reuse: bool,
|
||||||
'open_loop: loop {
|
|
||||||
let mut prev_pw = PREV_PW.lock().await;
|
|
||||||
let prompt = if prev_pw.is_empty() {
|
|
||||||
format!("crypt password for {crypt_dev}? ")
|
|
||||||
} else {
|
|
||||||
format!("crypt password for {crypt_dev} (enter = reuse previous)? ")
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pw = input::read_password(prompt).await;
|
|
||||||
if pw.is_empty() {
|
|
||||||
pw = prev_pw.clone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrevPw {
|
||||||
|
fn is_set(&self) -> bool {
|
||||||
|
!self.pw.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_reuse(&self) -> bool {
|
||||||
|
self.reuse && self.is_set()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate(&mut self) {
|
||||||
|
self.pw = String::new();
|
||||||
|
self.reuse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn input(&mut self, prompt: impl std::fmt::Display) -> String {
|
||||||
|
if self.can_reuse() {
|
||||||
|
info!("reusing password");
|
||||||
|
self.pw.clone()
|
||||||
|
} else if self.is_set() {
|
||||||
|
let pw =
|
||||||
|
input::read_password(format!("{prompt} (\"\" reuse, \"*\" auto-reuse)? ")).await;
|
||||||
|
|
||||||
|
match pw.as_str() {
|
||||||
|
"" => self.pw.clone(),
|
||||||
|
"*" => {
|
||||||
|
self.reuse = true;
|
||||||
|
self.pw.clone()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.pw = pw.clone();
|
||||||
|
pw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let pw = loop {
|
||||||
|
let pw = input::read_password(format!("{prompt}? ")).await;
|
||||||
if pw.is_empty() {
|
if pw.is_empty() {
|
||||||
error!("empty password provided!");
|
error!("empty password provided!");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
break pw;
|
||||||
|
};
|
||||||
|
|
||||||
*prev_pw = pw.clone();
|
self.pw = pw.clone();
|
||||||
|
pw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PREV_PW: Mutex<PrevPw> = Mutex::const_new(PrevPw {
|
||||||
|
pw: String::new(),
|
||||||
|
reuse: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
async fn crypt_open(crypt_dev: &str, dev_path: &str) -> Result<()> {
|
||||||
|
'open_loop: loop {
|
||||||
|
let mut prev_pw = PREV_PW.lock().await;
|
||||||
|
|
||||||
|
let pw = prev_pw
|
||||||
|
.input(format!("crypt password for {crypt_dev}"))
|
||||||
|
.await;
|
||||||
|
|
||||||
if cryptsetup(&pw, ["open", dev_path, crypt_dev]).await? {
|
if cryptsetup(&pw, ["open", dev_path, crypt_dev]).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -107,10 +152,13 @@ async fn crypt_open(crypt_dev: &str, dev_path: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
// device looks initialized, don't allow format
|
// device looks initialized, don't allow format
|
||||||
warn!("{dev_path} looks initialized, formatting not allowed from init");
|
warn!("{dev_path} looks initialized, formatting not allowed from init");
|
||||||
|
|
||||||
|
prev_pw.invalidate();
|
||||||
|
|
||||||
match input::read_choice(["[r]etry", "[i]gnore"]).await {
|
match input::read_choice(["[r]etry", "[i]gnore"]).await {
|
||||||
'r' => continue 'open_loop,
|
'r' => continue 'open_loop,
|
||||||
'i' => return Ok(()),
|
'i' => return Ok(()),
|
||||||
@ -118,7 +166,6 @@ async fn crypt_open(crypt_dev: &str, dev_path: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async fn cryptsetup<const N: usize>(pw: &str, args: [&str; N]) -> Result<bool> {
|
async fn cryptsetup<const N: usize>(pw: &str, args: [&str; N]) -> Result<bool> {
|
||||||
let mut child = Command::new("cryptsetup")
|
let mut child = Command::new("cryptsetup")
|
||||||
|
|||||||
@ -2,6 +2,10 @@ use crate::input;
|
|||||||
|
|
||||||
pub async fn run() {
|
pub async fn run() {
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
|
// give a bit of time for stdout
|
||||||
|
use tokio::time::{sleep, Duration};
|
||||||
|
sleep(Duration::from_millis(200)).await;
|
||||||
|
|
||||||
if let Err(e) = input::forward_requests_from_socket().await {
|
if let Err(e) = input::forward_requests_from_socket().await {
|
||||||
eprintln!("failed to forwards requests from socket: {e}");
|
eprintln!("failed to forwards requests from socket: {e}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user