aboutsummaryrefslogtreecommitdiff
path: root/nitrokey/src/util.rs
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2020-01-29 12:25:33 +0100
committerDaniel Mueller <deso@posteo.net>2020-02-03 09:40:32 -0800
commit51d0fbb73eb42325fb2a0832810fd9e1d4339743 (patch)
tree766cfda4a1a9e47ac6cef5f558b3dc93c8372eeb /nitrokey/src/util.rs
parent3dd4b7795f9a9a4285fe6add70a578e3a84bb59f (diff)
downloadnitrocli-51d0fbb73eb42325fb2a0832810fd9e1d4339743.tar.gz
nitrocli-51d0fbb73eb42325fb2a0832810fd9e1d4339743.tar.bz2
Update nitrokey dependency to 0.6.0
nitrokey 0.6.0 introduced the SerialNumber struct (instead of representing serial numbers as strings). We no longer have to manually format the serial number as SerialNumber implements Display. Import subrepo nitrokey/:nitrokey at 2a8ce725407f32db5ad61c37475719737c9b5c9c
Diffstat (limited to 'nitrokey/src/util.rs')
-rw-r--r--nitrokey/src/util.rs61
1 files changed, 39 insertions, 22 deletions
diff --git a/nitrokey/src/util.rs b/nitrokey/src/util.rs
index 5a56c55..b17b071 100644
--- a/nitrokey/src/util.rs
+++ b/nitrokey/src/util.rs
@@ -30,26 +30,38 @@ pub enum LogLevel {
DebugL2,
}
+pub fn str_from_ptr<'a>(ptr: *const c_char) -> Result<&'a str, Error> {
+ unsafe { CStr::from_ptr(ptr) }.to_str().map_err(Error::from)
+}
+
pub fn owned_str_from_ptr(ptr: *const c_char) -> Result<String, Error> {
- unsafe { CStr::from_ptr(ptr) }
- .to_str()
- .map(String::from)
- .map_err(Error::from)
+ str_from_ptr(ptr).map(ToOwned::to_owned)
}
-pub fn result_from_string(ptr: *const c_char) -> Result<String, Error> {
+pub fn run_with_string<R, F>(ptr: *const c_char, op: F) -> Result<R, Error>
+where
+ F: FnOnce(&str) -> Result<R, Error>,
+{
if ptr.is_null() {
- return Err(Error::UnexpectedError);
+ return Err(Error::UnexpectedError(
+ "libnitrokey returned a null pointer".to_owned(),
+ ));
}
- let s = owned_str_from_ptr(ptr)?;
+ let result = str_from_ptr(ptr).and_then(op);
unsafe { free(ptr as *mut c_void) };
- // An empty string can both indicate an error or be a valid return value. In this case, we
- // have to check the last command status to decide what to return.
- if s.is_empty() {
- get_last_result().map(|_| s)
- } else {
- Ok(s)
- }
+ result
+}
+
+pub fn result_from_string(ptr: *const c_char) -> Result<String, Error> {
+ run_with_string(ptr, |s| {
+ // An empty string can both indicate an error or be a valid return value. In this case, we
+ // have to check the last command status to decide what to return.
+ if s.is_empty() {
+ get_last_result().map(|_| s.to_owned())
+ } else {
+ Ok(s.to_owned())
+ }
+ })
}
pub fn result_or_error<T>(value: T) -> Result<T, Error> {
@@ -69,16 +81,21 @@ pub fn get_last_result() -> Result<(), Error> {
}
pub fn get_last_error() -> Error {
- match get_last_result() {
- Ok(()) => Error::UnexpectedError,
- Err(err) => err,
- }
+ get_last_result().err().unwrap_or_else(|| {
+ Error::UnexpectedError("Expected an error, but command status is zero".to_owned())
+ })
}
-pub fn generate_password(length: usize) -> Result<Vec<u8>, Error> {
- let mut data = vec![0u8; length];
- OsRng.fill_bytes(&mut data[..]);
- Ok(data)
+pub fn generate_password(length: usize) -> Result<CString, Error> {
+ loop {
+ // Randomly generate a password until we get a string *without* null bytes. Otherwise
+ // the string would be cut off prematurely due to null-termination in C.
+ let mut data = vec![0u8; length];
+ OsRng.fill_bytes(&mut data[..]);
+ if let Ok(s) = CString::new(data) {
+ return Ok(s);
+ }
+ }
}
pub fn get_cstring<T: Into<Vec<u8>>>(s: T) -> Result<CString, Error> {