use clap::Parser;
use qssh::auth::PasswordAuthManager;
use std::path::PathBuf;
use zeroize::Zeroize;
#[derive(Parser, Debug)]
#[clap(name = "qssh-passwd")]
#[clap(about = "Manage QSSH user passwords")]
struct Args {
username: String,
#[clap(short = 'f', long)]
file: Option<String>,
#[clap(short = 'd', long)]
delete: bool,
#[clap(short = 'c', long)]
check: bool,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
let password_file = args.file
.unwrap_or_else(|| "/etc/qssh/passwords".to_string());
let manager = PasswordAuthManager::new(PathBuf::from(&password_file));
if let Err(e) = manager.load_passwords().await {
eprintln!("Warning: Failed to load existing passwords: {}", e);
}
if args.check {
eprint!("Enter password to verify: ");
let mut password = rpassword::read_password().unwrap();
let result = manager.verify_password(&args.username, &password).await;
password.zeroize();
match result {
Ok(true) => {
println!("Password correct for user {}", args.username);
std::process::exit(0);
}
Ok(false) => {
println!("Invalid password or user not found");
std::process::exit(1);
}
Err(e) => {
eprintln!("Error verifying password: {}", e);
std::process::exit(2);
}
}
} else if args.delete {
match manager.set_password(&args.username, "").await {
Ok(()) => {
println!("Password deleted for user {}", args.username);
}
Err(e) => {
eprintln!("Failed to delete password: {}", e);
std::process::exit(1);
}
}
} else {
eprint!("Enter new password for {}: ", args.username);
let mut password = rpassword::read_password().unwrap();
eprint!("Confirm password: ");
let mut confirm = rpassword::read_password().unwrap();
if password != confirm {
password.zeroize();
confirm.zeroize();
eprintln!("Passwords do not match");
std::process::exit(1);
}
confirm.zeroize();
if password.is_empty() {
eprintln!("Password cannot be empty");
std::process::exit(1);
}
let result = manager.set_password(&args.username, &password).await;
password.zeroize();
match result {
Ok(()) => {
println!("Password set for user {}", args.username);
println!("Password file: {}", password_file);
}
Err(e) => {
eprintln!("Failed to set password: {}", e);
std::process::exit(1);
}
}
}
}