aboutsummaryrefslogtreecommitdiff
path: root/nitrocli/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'nitrocli/src/main.rs')
-rw-r--r--nitrocli/src/main.rs130
1 files changed, 2 insertions, 128 deletions
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index c190d1b..86e9188 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -68,6 +68,7 @@
//! Nitrocli is a program providing a command line interface to certain
//! commands of the Nitrokey Storage device.
+mod commands;
mod error;
mod pinentry;
@@ -80,133 +81,6 @@ use crate::error::Error;
type Result<T> = result::Result<T, Error>;
-const PIN_TYPE: pinentry::PinType = pinentry::PinType::User;
-
-/// Create an `error::Error` with an error message of the format `msg: err`.
-fn get_error(msg: &str, err: &nitrokey::CommandError) -> Error {
- Error::Error(format!("{}: {:?}", msg, err))
-}
-
-/// Connect to a Nitrokey Storage device and return it.
-fn get_storage_device() -> Result<nitrokey::Storage> {
- nitrokey::Storage::connect()
- .or_else(|_| Err(Error::Error("Nitrokey device not found".to_string())))
-}
-
-/// Return a string representation of the given volume status.
-fn get_volume_status(status: &nitrokey::VolumeStatus) -> &'static str {
- if status.active {
- if status.read_only {
- "read-only"
- } else {
- "active"
- }
- } else {
- "inactive"
- }
-}
-
-/// Pretty print the response of a status command.
-fn print_status(status: &nitrokey::StorageStatus) {
- // We omit displaying information about the smartcard here as this
- // program really is only about the SD card portion of the device.
- println!(
- r#"Status:
- SD card ID: {id:#x}
- firmware version: {fwv0}.{fwv1}
- firmware: {fw}
- storage keys: {sk}
- user retry count: {urc}
- admin retry count: {arc}
- volumes:
- unencrypted: {vu}
- encrypted: {ve}
- hidden: {vh}"#,
- id = status.serial_number_sd_card,
- fwv0 = status.firmware_version_major,
- fwv1 = status.firmware_version_minor,
- fw = if status.firmware_locked {
- "locked"
- } else {
- "unlocked"
- },
- sk = if status.stick_initialized {
- "created"
- } else {
- "not created"
- },
- urc = status.user_retry_count,
- arc = status.admin_retry_count,
- vu = get_volume_status(&status.unencrypted_volume),
- ve = get_volume_status(&status.encrypted_volume),
- vh = get_volume_status(&status.hidden_volume),
- );
-}
-
-/// Inquire the status of the nitrokey.
-fn status() -> Result<()> {
- let status = get_storage_device()?
- .get_status()
- .map_err(|err| get_error("Getting Storage status failed", &err))?;
-
- print_status(&status);
- Ok(())
-}
-
-/// Open the encrypted volume on the nitrokey.
-fn open() -> Result<()> {
- let device = get_storage_device()?;
-
- let mut retry = 3;
- let mut error_msg: Option<&str> = None;
- loop {
- // TODO: Rethink the usage of String::from_utf8_lossy here. We may
- // not want to silently modify the password!
- let passphrase = pinentry::inquire_passphrase(PIN_TYPE, error_msg)?;
- let passphrase = String::from_utf8_lossy(&passphrase);
- match device.enable_encrypted_volume(&passphrase) {
- Ok(()) => return Ok(()),
- Err(err) => match err {
- nitrokey::CommandError::WrongPassword => {
- pinentry::clear_passphrase(PIN_TYPE)?;
- retry -= 1;
-
- if retry > 0 {
- error_msg = Some("Wrong password, please reenter");
- continue;
- }
- let error = "Opening encrypted volume failed: Wrong password";
- return Err(Error::Error(error.to_string()));
- }
- err => return Err(get_error("Opening encrypted volume failed", &err)),
- },
- };
- }
-}
-
-#[link(name = "c")]
-extern "C" {
- fn sync();
-}
-
-/// Close the previously opened encrypted volume.
-fn close() -> Result<()> {
- // Flush all filesystem caches to disk. We are mostly interested in
- // making sure that the encrypted volume on the nitrokey we are
- // about to close is not closed while not all data was written to
- // it.
- unsafe { sync() };
-
- get_storage_device()?
- .disable_encrypted_volume()
- .map_err(|err| get_error("Closing encrypted volume failed", &err))
-}
-
-/// Clear the PIN stored when opening the nitrokey's encrypted volume.
-fn clear() -> Result<()> {
- pinentry::clear_passphrase(PIN_TYPE)
-}
-
// A macro for generating a match of the different supported commands.
// Each supplied command is converted into a string and matched against.
macro_rules! commands {
@@ -237,7 +111,7 @@ fn run() -> i32 {
return 1;
}
- commands!(&argv[1], [status, open, close, clear]);
+ commands!(&argv[1], [commands::status, commands::open, commands::close, commands::clear]);
}
fn main() {