mirror of https://github.com/ospab/ostp.git
fix(cli): setup wizard used a fake password hash, locking admins out of their own panel
The Server+Panel setup wizard's panel-password hashing was a placeholder:
std::collections::hash_map::DefaultHasher (SipHash, not cryptographic, and
not even a 256-bit output - only the first 8 of 32 bytes were real, the
rest zero-padded), left in by the comment "sha2 is not a direct dep of
ostp/Cargo.toml, so we use std's hasher as a placeholder digest here."
api.rs's handle_login computes the REAL SHA256 hex digest of the submitted
password and compares it against config.json's stored password_hash. Since
the wizard's placeholder never produces the same value as real SHA256 of
the same password, anyone who set up a panel through this wizard could
never actually log into it with the password it just showed them - a
complete functional break of the wizard-driven admin flow, not a corner
case.
Added sha2 as a direct ostp dependency and replaced the placeholder with
the exact same format!("{:x}", Sha256::digest(..)) api.rs's login check
uses.
This commit is contained in:
parent
d9686c9344
commit
9a891310f9
|
|
@ -21,3 +21,4 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|||
ostp-core = { path = "../ostp-core" }
|
||||
colored = "2.1"
|
||||
rlimit = "0.11.0"
|
||||
sha2.workspace = true
|
||||
|
|
|
|||
|
|
@ -720,24 +720,11 @@ fn run_setup_wizard(config_path: &std::path::Path) -> Result<()> {
|
|||
}) as char
|
||||
}).collect();
|
||||
let password = wizard_prompt("Admin password (blank for random)", &rand_pass);
|
||||
let pass_hash = {
|
||||
use std::fmt::Write as _;
|
||||
let mut hash = String::new();
|
||||
let digest: [u8; 32] = {
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
// Panel password hashing. sha2 is not a direct dep of ostp/Cargo.toml,
|
||||
// so we use std's hasher as a placeholder digest here.
|
||||
let mut h = DefaultHasher::new();
|
||||
password.hash(&mut h);
|
||||
let v = h.finish();
|
||||
let mut out = [0u8; 32];
|
||||
out[..8].copy_from_slice(&v.to_be_bytes());
|
||||
out
|
||||
};
|
||||
for b in digest { let _ = write!(hash, "{:02x}", b); }
|
||||
hash
|
||||
};
|
||||
// Must match api.rs's handle_login exactly (format!("{:x}", Sha256::digest(..))) -
|
||||
// this used to be a DefaultHasher (SipHash) placeholder that produced a
|
||||
// differently-shaped digest, so a password set up through this wizard could
|
||||
// never actually log into the panel it just configured.
|
||||
let pass_hash = format!("{:x}", sha2::Sha256::digest(password.as_bytes()));
|
||||
|
||||
wizard_step(4, TOTAL, "Saving configuration");
|
||||
let panel_bind = format!("0.0.0.0:{}", panel_port);
|
||||
|
|
|
|||
Loading…
Reference in New Issue