/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use authenticator::{
authenticatorservice::AuthenticatorService, statecallback::StateCallback, Pin, StatusPinUv,
StatusUpdate,
}; use getopts::Options; use std::sync::mpsc::{channel, RecvError}; use std::{env, thread};
let args: Vec<String> = env::args().collect(); let program = args[0].clone();
letmut opts = Options::new();
opts.optflag("h", "help", "print this help menu").optopt( "t", "timeout", "timeout in seconds", "SEC",
);
opts.optflag("h", "help", "print this help menu"); let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => panic!("{}", f.to_string()),
}; if matches.opt_present("help") {
print_usage(&program, opts); return;
}
letmut manager =
AuthenticatorService::new().expect("The auth service should initialize safely");
manager.add_u2f_usb_hid_platform_transports();
let timeout_ms = match matches.opt_get_default::<u64>("timeout", 25) {
Ok(timeout_s) => {
println!("Using {}s as the timeout", &timeout_s);
timeout_s * 1_000
}
Err(e) => {
println!("{e}");
print_usage(&program, opts); return;
}
};
let new_pin = rpassword::prompt_password_stderr("Enter new PIN: ").expect("Failed to read PIN"); let repeat_new_pin =
rpassword::prompt_password_stderr("Enter it again: ").expect("Failed to read PIN"); if new_pin != repeat_new_pin {
println!("PINs did not match!"); return;
}
let (status_tx, status_rx) = channel::<StatusUpdate>();
thread::spawn(move || loop { match status_rx.recv() {
Ok(StatusUpdate::InteractiveManagement(..)) => {
panic!("STATUS: This can't happen when doing non-interactive usage");
}
Ok(StatusUpdate::SelectDeviceNotice) => {
println!("STATUS: Please select a device by touching one of them.");
}
Ok(StatusUpdate::PresenceRequired) => {
println!("STATUS: waiting for user presence");
}
Ok(StatusUpdate::PinUvError(StatusPinUv::PinRequired(sender))) => { let raw_pin =
rpassword::prompt_password_stderr("Enter PIN: ").expect("Failed to read PIN");
sender.send(Pin::new(&raw_pin)).expect("Failed to send PIN"); continue;
}
Ok(StatusUpdate::PinUvError(StatusPinUv::InvalidPin(sender, attempts))) => {
println!( "Wrong PIN! {}",
attempts.map_or("Try again.".to_string(), |a| format!( "You have {a} attempts left."
))
); let raw_pin =
rpassword::prompt_password_stderr("Enter PIN: ").expect("Failed to read PIN");
sender.send(Pin::new(&raw_pin)).expect("Failed to send PIN"); continue;
}
Ok(StatusUpdate::PinUvError(StatusPinUv::PinAuthBlocked)) => {
panic!("Too many failed attempts in one row. Your device has been temporarily blocked. Please unplug it and plug in again.")
}
Ok(StatusUpdate::PinUvError(StatusPinUv::PinBlocked)) => {
panic!("Too many failed attempts. Your device has been blocked. Reset it.")
}
Ok(StatusUpdate::PinUvError(StatusPinUv::InvalidUv(attempts))) => {
println!( "Wrong UV! {}",
attempts.map_or("Try again.".to_string(), |a| format!( "You have {a} attempts left."
))
); continue;
}
Ok(StatusUpdate::PinUvError(StatusPinUv::UvBlocked)) => {
println!("Too many failed UV-attempts."); continue;
}
Ok(StatusUpdate::PinUvError(e)) => {
panic!("Unexpected error: {:?}", e)
}
Ok(StatusUpdate::SelectResultNotice(_, _)) => {
panic!("Unexpected select device notice")
}
Err(RecvError) => {
println!("STATUS: end"); return;
}
}
});
let (reset_tx, reset_rx) = channel(); let rs_tx = reset_tx; let callback = StateCallback::new(Box::new(move |rv| { let _ = rs_tx.send(rv);
}));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.