diff options
author | Daniel Mueller <deso@posteo.net> | 2017-04-09 20:53:54 -0700 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2017-04-09 20:53:54 -0700 |
commit | 3ce72e0ce1a0442786bc2600a7f276ae1994d90e (patch) | |
tree | 3263b7bf43242520d421f7af14367d273e544f15 | |
parent | 1e4a359f42e081851b98a12511ffe24968bfc6da (diff) | |
download | nitrocli-3ce72e0ce1a0442786bc2600a7f276ae1994d90e.tar.gz nitrocli-3ce72e0ce1a0442786bc2600a7f276ae1994d90e.tar.bz2 |
Wait until encrypted volume is opened/closed
Until now we treated any response but "ok" and "idle" to the encrypted
volume opening command as an error and reported it. However, the opening
process is a potentially long running and it is very likely that the
nitrokey reports a couple of "busy" messages.
This change implements the logic to wait until the nitrokey either
reports an error or a successful open.
-rw-r--r-- | nitrocli/src/main.rs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs index 2408188..f3f7d7f 100644 --- a/nitrocli/src/main.rs +++ b/nitrocli/src/main.rs @@ -228,6 +228,25 @@ fn status() -> Result<()> { } +/// Poll the nitrokey until it reports to no longer be busy. +fn wait(handle: &mut libhid::Handle) -> Result<nitrokey::StorageStatus> { + type Response = nitrokey::Response<nitrokey::StorageResponse>; + + loop { + thread::sleep(time::Duration::from_millis(SEND_RECV_DELAY_MS)); + + let report = receive::<nitrokey::EmptyPayload>(handle)?; + let response = AsRef::<Response>::as_ref(&report.data); + let status = response.data.storage_status; + + if status != nitrokey::StorageStatus::Busy && + status != nitrokey::StorageStatus::BusyProgressbar { + return Ok(status); + } + } +} + + /// Open the encrypted volume on the nitrokey. fn open() -> Result<()> { type Response = nitrokey::Response<nitrokey::StorageResponse>; @@ -241,7 +260,7 @@ fn open() -> Result<()> { let report = transmit::<_, nitrokey::EmptyPayload>(handle, &report)?; let response = AsRef::<Response>::as_ref(&report.data); - let status = response.data.storage_status; + let mut status = response.data.storage_status; if status == nitrokey::StorageStatus::WrongPassword { pinentry::clear_passphrase()?; @@ -254,6 +273,10 @@ fn open() -> Result<()> { let error = "Opening encrypted volume failed: Wrong password"; return Err(Error::Error(error.to_string())); } + if status == nitrokey::StorageStatus::Busy || + status == nitrokey::StorageStatus::BusyProgressbar { + status = wait(handle)?; + } if status != nitrokey::StorageStatus::Okay && status != nitrokey::StorageStatus::Idle { let status = format!("{:?}", status); let error = format!("Opening encrypted volume failed: {}", status); @@ -267,11 +290,25 @@ fn open() -> Result<()> { /// Close the previously opened encrypted volume. fn close() -> Result<()> { + type Response = nitrokey::Response<nitrokey::StorageResponse>; + return nitrokey_do(&|handle| { let payload = nitrokey::DisableEncryptedVolumeCommand::new(); let report = nitrokey::Report::from(payload); - transmit::<_, nitrokey::EmptyPayload>(handle, &report)?; + let report = transmit::<_, nitrokey::EmptyPayload>(handle, &report)?; + let response = AsRef::<Response>::as_ref(&report.data); + let mut status = response.data.storage_status; + + if status == nitrokey::StorageStatus::Busy || + status == nitrokey::StorageStatus::BusyProgressbar { + status = wait(handle)?; + } + if status != nitrokey::StorageStatus::Okay && status != nitrokey::StorageStatus::Idle { + let status = format!("{:?}", status); + let error = format!("Closing encrypted volume failed: {}", status); + return Err(Error::Error(error)); + } return Ok(()); }); } |