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 anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use openpgp_card_sequoia::card::Card;
|
use openpgp_card_sequoia::card::{Card, Open};
|
||||||
|
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::util::{load_pin, print_gnuk_note};
|
use crate::util::{load_pin, print_gnuk_note};
|
||||||
|
@ -71,197 +71,234 @@ pub enum PinSubCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pin(ident: &str, cmd: PinSubCommand) -> Result<()> {
|
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 card = Card::new(backend);
|
||||||
let mut open = card.transaction()?;
|
let mut open = card.transaction()?;
|
||||||
|
|
||||||
let pinpad_modify = open.feature_pinpad_modify();
|
let pinpad_modify = open.feature_pinpad_modify();
|
||||||
|
|
||||||
|
// TODO de-complicate return, remove question marks
|
||||||
match cmd {
|
match cmd {
|
||||||
PinSubCommand::SetUser {
|
PinSubCommand::SetUser {
|
||||||
user_pin_old,
|
user_pin_old,
|
||||||
user_pin_new,
|
user_pin_new,
|
||||||
} => {
|
} => set_user(user_pin_old, user_pin_new, pinpad_modify, open)?,
|
||||||
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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PinSubCommand::SetAdmin {
|
PinSubCommand::SetAdmin {
|
||||||
admin_pin_old,
|
admin_pin_old,
|
||||||
admin_pin_new,
|
admin_pin_new,
|
||||||
} => {
|
} => set_admin(admin_pin_old, admin_pin_new, pinpad_modify, open)?,
|
||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||||
PinSubCommand::ResetUser {
|
PinSubCommand::ResetUser {
|
||||||
admin_pin,
|
admin_pin,
|
||||||
user_pin_new,
|
user_pin_new,
|
||||||
} => {
|
} => reset_user(admin_pin, user_pin_new, open)?,
|
||||||
// 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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||||
PinSubCommand::SetReset {
|
PinSubCommand::SetReset {
|
||||||
admin_pin,
|
admin_pin,
|
||||||
reset_code,
|
reset_code,
|
||||||
} => {
|
} => set_reset(admin_pin, reset_code, open)?,
|
||||||
// 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());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: this doesn't use pinpad_modify, maybe don't compute it before this?
|
||||||
PinSubCommand::ResetUserRc {
|
PinSubCommand::ResetUserRc {
|
||||||
reset_code,
|
reset_code,
|
||||||
user_pin_new,
|
user_pin_new,
|
||||||
} => {
|
} => reset_user_rc(reset_code, user_pin_new, open)?,
|
||||||
// reset by presenting resetting code
|
}
|
||||||
|
Ok(())
|
||||||
let rst = if let Some(path) = reset_code {
|
}
|
||||||
// load resetting code from file
|
|
||||||
load_pin(&path)?
|
fn set_user(
|
||||||
} else {
|
user_pin_old: Option<PathBuf>,
|
||||||
// input resetting code
|
user_pin_new: Option<PathBuf>,
|
||||||
rpassword::prompt_password("Enter resetting code: ")?
|
pinpad_modify: bool,
|
||||||
.as_bytes()
|
mut open: Open,
|
||||||
.to_vec()
|
) -> Result<()> {
|
||||||
};
|
let res = if !pinpad_modify {
|
||||||
|
// get current user pin
|
||||||
// ask user for new user pin
|
let user_pin1 = util::get_pin(&mut open, user_pin_old, ENTER_USER_PIN)
|
||||||
let pin = match user_pin_new {
|
.expect("this should never be None");
|
||||||
None => util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?,
|
|
||||||
Some(path) => load_pin(&path)?,
|
// verify pin
|
||||||
};
|
open.verify_user(&user_pin1)?;
|
||||||
|
println!("PIN was accepted by the card.\n");
|
||||||
// reset to new user pin
|
|
||||||
match open.reset_user_pin(&rst, &pin) {
|
let pin_new = match user_pin_new {
|
||||||
Err(err) => {
|
None => {
|
||||||
println!("\nFailed to change the User PIN!");
|
// ask user for new user pin
|
||||||
print_gnuk_note(err, &open)?;
|
util::input_pin_twice("Enter new User PIN: ", "Repeat the new User PIN: ")?
|
||||||
}
|
}
|
||||||
Ok(_) => println!("\nUser PIN has been set."),
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue