opgpcard: Reorganize pin
This commit is contained in:
parent
b6dfa08d52
commit
1ecaf396c7
1 changed files with 204 additions and 167 deletions
|
@ -7,7 +7,7 @@ use std::path::PathBuf;
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
|
||||
use openpgp_card_sequoia::card::Card;
|
||||
use openpgp_card_sequoia::card::{Card, Open};
|
||||
|
||||
use crate::util;
|
||||
use crate::util::{load_pin, print_gnuk_note};
|
||||
|
@ -71,197 +71,234 @@ pub enum PinSubCommand {
|
|||
}
|
||||
|
||||
pub fn pin(ident: &str, cmd: PinSubCommand) -> Result<()> {
|
||||
let backend = util::open_card(&ident)?;
|
||||
let backend = util::open_card(ident)?;
|
||||
let mut card = Card::new(backend);
|
||||
let mut open = card.transaction()?;
|
||||
|
||||
let pinpad_modify = open.feature_pinpad_modify();
|
||||
|
||||
// TODO de-complicate return, remove question marks
|
||||
match cmd {
|
||||
PinSubCommand::SetUser {
|
||||
user_pin_old,
|
||||
user_pin_new,
|
||||
} => {
|
||||
let res = if !pinpad_modify {
|
||||
// get current user pin
|
||||
let user_pin1 = util::get_pin(&mut open, user_pin_old, ENTER_USER_PIN)
|
||||
.expect("this should never be None");
|
||||
} => set_user(user_pin_old, user_pin_new, pinpad_modify, open)?,
|
||||
|
||||
// verify pin
|
||||
open.verify_user(&user_pin1)?;
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
let pin_new = match user_pin_new {
|
||||
None => {
|
||||
// ask user for new user pin
|
||||
util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?
|
||||
}
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// set new user pin
|
||||
open.change_user_pin(&user_pin1, &pin_new)
|
||||
} else {
|
||||
// set new user pin via pinpad
|
||||
open.change_user_pin_pinpad(&|| {
|
||||
println!("Enter old User PIN on card reader pinpad, then new User PIN (twice).")
|
||||
})
|
||||
};
|
||||
|
||||
if res.is_err() {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
println!("{:?}", res);
|
||||
|
||||
if let Err(err) = res {
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
} else {
|
||||
println!("\nUser PIN has been set.");
|
||||
}
|
||||
}
|
||||
PinSubCommand::SetAdmin {
|
||||
admin_pin_old,
|
||||
admin_pin_new,
|
||||
} => {
|
||||
if !pinpad_modify {
|
||||
// get current admin pin
|
||||
let admin_pin1 = util::get_pin(&mut open, admin_pin_old, ENTER_ADMIN_PIN)
|
||||
.expect("this should never be None");
|
||||
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin1)?;
|
||||
// (Verifying the PIN here fixes this class of problems:
|
||||
// https://developers.yubico.com/PGP/PGP_PIN_Change_Behavior.html
|
||||
// It is also just generally more user friendly than failing later)
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
let pin_new = match admin_pin_new {
|
||||
None => {
|
||||
// ask user for new admin pin
|
||||
util::input_pin_twice(
|
||||
"Enter new Admin PIN: ",
|
||||
"Repeat the new Admin PIN: ",
|
||||
)?
|
||||
}
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// set new admin pin
|
||||
open.change_admin_pin(&admin_pin1, &pin_new)?;
|
||||
} else {
|
||||
// set new admin pin via pinpad
|
||||
open.change_admin_pin_pinpad(&|| {
|
||||
println!(
|
||||
"Enter old Admin PIN on card reader pinpad, then new Admin PIN (twice)."
|
||||
)
|
||||
})?;
|
||||
};
|
||||
|
||||
println!("\nAdmin PIN has been set.");
|
||||
}
|
||||
} => set_admin(admin_pin_old, admin_pin_new, pinpad_modify, open)?,
|
||||
|
||||
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||
PinSubCommand::ResetUser {
|
||||
admin_pin,
|
||||
user_pin_new,
|
||||
} => {
|
||||
// verify admin pin
|
||||
match util::get_pin(&mut open, admin_pin, ENTER_ADMIN_PIN) {
|
||||
Some(admin_pin) => {
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin)?;
|
||||
}
|
||||
None => {
|
||||
open.verify_admin_pinpad(&|| println!("Enter Admin PIN on pinpad."))?;
|
||||
}
|
||||
}
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
// ask user for new user pin
|
||||
let pin = match user_pin_new {
|
||||
None => util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
let res = if let Some(mut admin) = open.admin_card() {
|
||||
admin.reset_user_pin(&pin)
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("Failed to use card in admin-mode.").into());
|
||||
};
|
||||
|
||||
if res.is_err() {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
if let Err(err) = res {
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
} else {
|
||||
println!("\nUser PIN has been set.");
|
||||
}
|
||||
}
|
||||
} => reset_user(admin_pin, user_pin_new, open)?,
|
||||
|
||||
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||
PinSubCommand::SetReset {
|
||||
admin_pin,
|
||||
reset_code,
|
||||
} => {
|
||||
// verify admin pin
|
||||
match util::get_pin(&mut open, admin_pin, ENTER_ADMIN_PIN) {
|
||||
Some(admin_pin) => {
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin)?;
|
||||
}
|
||||
None => {
|
||||
open.verify_admin_pinpad(&|| println!("Enter Admin PIN on pinpad."))?;
|
||||
}
|
||||
}
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
// ask user for new resetting code
|
||||
let code = match reset_code {
|
||||
None => util::input_pin_twice(
|
||||
"Enter new resetting code: ",
|
||||
"Repeat the new resetting code: ",
|
||||
)?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
if let Some(mut admin) = open.admin_card() {
|
||||
admin.set_resetting_code(&code)?;
|
||||
println!("\nResetting code has been set.");
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("Failed to use card in admin-mode.").into());
|
||||
};
|
||||
}
|
||||
} => set_reset(admin_pin, reset_code, open)?,
|
||||
|
||||
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||
PinSubCommand::ResetUserRc {
|
||||
reset_code,
|
||||
user_pin_new,
|
||||
} => {
|
||||
// reset by presenting resetting code
|
||||
|
||||
let rst = if let Some(path) = reset_code {
|
||||
// load resetting code from file
|
||||
load_pin(&path)?
|
||||
} else {
|
||||
// input resetting code
|
||||
rpassword::prompt_password("Enter resetting code: ")?
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
};
|
||||
|
||||
// ask user for new user pin
|
||||
let pin = match user_pin_new {
|
||||
None => util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// reset to new user pin
|
||||
match open.reset_user_pin(&rst, &pin) {
|
||||
Err(err) => {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
Ok(_) => println!("\nUser PIN has been set."),
|
||||
}
|
||||
}
|
||||
} => reset_user_rc(reset_code, user_pin_new, open)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_user(
|
||||
user_pin_old: Option<PathBuf>,
|
||||
user_pin_new: Option<PathBuf>,
|
||||
pinpad_modify: bool,
|
||||
mut open: Open,
|
||||
) -> Result<()> {
|
||||
let res = if !pinpad_modify {
|
||||
// get current user pin
|
||||
let user_pin1 = util::get_pin(&mut open, user_pin_old, ENTER_USER_PIN)
|
||||
.expect("this should never be None");
|
||||
|
||||
// verify pin
|
||||
open.verify_user(&user_pin1)?;
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
let pin_new = match user_pin_new {
|
||||
None => {
|
||||
// ask user for new user pin
|
||||
util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?
|
||||
}
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// set new user pin
|
||||
open.change_user_pin(&user_pin1, &pin_new)
|
||||
} else {
|
||||
// set new user pin via pinpad
|
||||
open.change_user_pin_pinpad(&|| {
|
||||
println!("Enter old User PIN on card reader pinpad, then new User PIN (twice).")
|
||||
})
|
||||
};
|
||||
|
||||
if res.is_err() {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
println!("{:?}", res);
|
||||
|
||||
if let Err(err) = res {
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
} else {
|
||||
println!("\nUser PIN has been set.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_admin(
|
||||
admin_pin_old: Option<PathBuf>,
|
||||
admin_pin_new: Option<PathBuf>,
|
||||
pinpad_modify: bool,
|
||||
mut open: Open,
|
||||
) -> Result<()> {
|
||||
if !pinpad_modify {
|
||||
// get current admin pin
|
||||
let admin_pin1 = util::get_pin(&mut open, admin_pin_old, ENTER_ADMIN_PIN)
|
||||
.expect("this should never be None");
|
||||
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin1)?;
|
||||
// (Verifying the PIN here fixes this class of problems:
|
||||
// https://developers.yubico.com/PGP/PGP_PIN_Change_Behavior.html
|
||||
// It is also just generally more user friendly than failing later)
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
let pin_new = match admin_pin_new {
|
||||
None => {
|
||||
// ask user for new admin pin
|
||||
util::input_pin_twice("Enter new Admin PIN: ", "Repeat the new Admin PIN: ")?
|
||||
}
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// set new admin pin
|
||||
open.change_admin_pin(&admin_pin1, &pin_new)?;
|
||||
} else {
|
||||
// set new admin pin via pinpad
|
||||
open.change_admin_pin_pinpad(&|| {
|
||||
println!("Enter old Admin PIN on card reader pinpad, then new Admin PIN (twice).")
|
||||
})?;
|
||||
};
|
||||
|
||||
println!("\nAdmin PIN has been set.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_user(
|
||||
admin_pin: Option<PathBuf>,
|
||||
user_pin_new: Option<PathBuf>,
|
||||
mut open: Open,
|
||||
) -> Result<()> {
|
||||
// verify admin pin
|
||||
match util::get_pin(&mut open, admin_pin, ENTER_ADMIN_PIN) {
|
||||
Some(admin_pin) => {
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin)?;
|
||||
}
|
||||
None => {
|
||||
open.verify_admin_pinpad(&|| println!("Enter Admin PIN on pinpad."))?;
|
||||
}
|
||||
}
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
// ask user for new user pin
|
||||
let pin = match user_pin_new {
|
||||
None => util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
let res = if let Some(mut admin) = open.admin_card() {
|
||||
admin.reset_user_pin(&pin)
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("Failed to use card in admin-mode.").into());
|
||||
};
|
||||
|
||||
if res.is_err() {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
if let Err(err) = res {
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
} else {
|
||||
println!("\nUser PIN has been set.");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_reset(
|
||||
admin_pin: Option<PathBuf>,
|
||||
reset_code: Option<PathBuf>,
|
||||
mut open: Open,
|
||||
) -> Result<()> {
|
||||
// verify admin pin
|
||||
match util::get_pin(&mut open, admin_pin, ENTER_ADMIN_PIN) {
|
||||
Some(admin_pin) => {
|
||||
// verify pin
|
||||
open.verify_admin(&admin_pin)?;
|
||||
}
|
||||
None => {
|
||||
open.verify_admin_pinpad(&|| println!("Enter Admin PIN on pinpad."))?;
|
||||
}
|
||||
}
|
||||
println!("PIN was accepted by the card.\n");
|
||||
|
||||
// ask user for new resetting code
|
||||
let code = match reset_code {
|
||||
None => util::input_pin_twice(
|
||||
"Enter new resetting code: ",
|
||||
"Repeat the new resetting code: ",
|
||||
)?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
if let Some(mut admin) = open.admin_card() {
|
||||
admin.set_resetting_code(&code)?;
|
||||
println!("\nResetting code has been set.");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Failed to use card in admin-mode.").into())
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_user_rc(
|
||||
reset_code: Option<PathBuf>,
|
||||
user_pin_new: Option<PathBuf>,
|
||||
mut open: Open,
|
||||
) -> Result<()> {
|
||||
// reset by presenting resetting code
|
||||
|
||||
let rst = if let Some(path) = reset_code {
|
||||
// load resetting code from file
|
||||
load_pin(&path)?
|
||||
} else {
|
||||
// input resetting code
|
||||
rpassword::prompt_password("Enter resetting code: ")?
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
};
|
||||
|
||||
// ask user for new user pin
|
||||
let pin = match user_pin_new {
|
||||
None => util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?,
|
||||
Some(path) => load_pin(&path)?,
|
||||
};
|
||||
|
||||
// reset to new user pin
|
||||
match open.reset_user_pin(&rst, &pin) {
|
||||
Err(err) => {
|
||||
println!("\nFailed to change the User PIN!");
|
||||
print_gnuk_note(err, &open)?;
|
||||
}
|
||||
Ok(_) => println!("\nUser PIN has been set."),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue