Skip to content

Build Better Errors #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ sha2 = "^0.8.2"
base64 = "^0.10"
env_logger = "^0.6"
getopts = "^0.2"
assert_matches = "1.2"
126 changes: 66 additions & 60 deletions src/authenticatorservice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use std::sync::{mpsc::Sender, Arc, Mutex};

use crate::consts::PARAMETER_SIZE;
use crate::errors::*;
use crate::statecallback::StateCallback;

pub trait AuthenticatorTransport {
Expand All @@ -18,8 +19,8 @@ pub trait AuthenticatorTransport {
application: crate::AppId,
key_handles: Vec<crate::KeyHandle>,
status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::RegisterResult, crate::Error>>,
) -> Result<(), crate::Error>;
callback: StateCallback<crate::Result<crate::RegisterResult>>,
) -> crate::Result<()>;

/// The implementation of this method must return quickly and should
/// report its status via the status and callback methods
Expand All @@ -31,10 +32,10 @@ pub trait AuthenticatorTransport {
app_ids: Vec<crate::AppId>,
key_handles: Vec<crate::KeyHandle>,
status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::SignResult, crate::Error>>,
) -> Result<(), crate::Error>;
callback: StateCallback<crate::Result<crate::SignResult>>,
) -> crate::Result<()>;

fn cancel(&mut self) -> Result<(), crate::Error>;
fn cancel(&mut self) -> crate::Result<()>;
}

pub struct AuthenticatorService {
Expand All @@ -61,7 +62,7 @@ fn clone_and_configure_cancellation_callback<T>(
}

impl AuthenticatorService {
pub fn new() -> Result<Self, crate::Error> {
pub fn new() -> crate::Result<Self> {
Ok(Self {
transports: Vec::new(),
})
Expand Down Expand Up @@ -91,21 +92,21 @@ impl AuthenticatorService {
application: crate::AppId,
key_handles: Vec<crate::KeyHandle>,
status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::RegisterResult, crate::Error>>,
) -> Result<(), crate::Error> {
callback: StateCallback<crate::Result<crate::RegisterResult>>,
) -> crate::Result<()> {
if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}

for key_handle in &key_handles {
if key_handle.credential.len() > 256 {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}
}

let iterable_transports = self.transports.clone();
if iterable_transports.is_empty() {
return Err(crate::Error::NotSupported);
return Err(AuthenticatorError::NoConfiguredTransports);
}

debug!(
Expand Down Expand Up @@ -145,31 +146,31 @@ impl AuthenticatorService {
app_ids: Vec<crate::AppId>,
key_handles: Vec<crate::KeyHandle>,
status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::SignResult, crate::Error>>,
) -> Result<(), crate::Error> {
callback: StateCallback<crate::Result<crate::SignResult>>,
) -> crate::Result<()> {
if challenge.len() != PARAMETER_SIZE {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}

if app_ids.is_empty() {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}

for app_id in &app_ids {
if app_id.len() != PARAMETER_SIZE {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}
}

for key_handle in &key_handles {
if key_handle.credential.len() > 256 {
return Err(crate::Error::Unknown);
return Err(AuthenticatorError::InvalidRelyingPartyInput);
}
}

let iterable_transports = self.transports.clone();
if iterable_transports.is_empty() {
return Err(crate::Error::NotSupported);
return Err(AuthenticatorError::NoConfiguredTransports);
}

for (idx, transport_mutex) in iterable_transports.iter().enumerate() {
Expand All @@ -190,9 +191,9 @@ impl AuthenticatorService {
Ok(())
}

pub fn cancel(&mut self) -> Result<(), crate::Error> {
pub fn cancel(&mut self) -> crate::Result<()> {
if self.transports.is_empty() {
return Err(crate::Error::NotSupported);
return Err(AuthenticatorError::NoConfiguredTransports);
}

for transport_mutex in &mut self.transports {
Expand Down Expand Up @@ -259,8 +260,8 @@ mod tests {
_application: crate::AppId,
_key_handles: Vec<crate::KeyHandle>,
_status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::RegisterResult, crate::Error>>,
) -> Result<(), crate::Error> {
callback: StateCallback<crate::Result<crate::RegisterResult>>,
) -> crate::Result<()> {
if self.consent {
let rv = Ok((vec![0u8; 16], self.dev_info()));
thread::spawn(move || callback.call(rv));
Expand All @@ -276,19 +277,24 @@ mod tests {
_app_ids: Vec<crate::AppId>,
_key_handles: Vec<crate::KeyHandle>,
_status: Sender<crate::StatusUpdate>,
callback: StateCallback<Result<crate::SignResult, crate::Error>>,
) -> Result<(), crate::Error> {
callback: StateCallback<crate::Result<crate::SignResult>>,
) -> crate::Result<()> {
if self.consent {
let rv = Ok((vec![0u8; 0], vec![0u8; 0], vec![0u8; 0], self.dev_info()));
thread::spawn(move || callback.call(rv));
}
Ok(())
}

fn cancel(&mut self) -> Result<(), crate::Error> {
fn cancel(&mut self) -> crate::Result<()> {
self.was_cancelled
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.map_or(Err(crate::Error::InvalidState), |_| Ok(()))
.map_or(
Err(crate::errors::AuthenticatorError::U2FToken(
crate::errors::U2FTokenError::InvalidState,
)),
|_| Ok(()),
)
}
}

Expand All @@ -315,7 +321,7 @@ mod tests {
let mut s = AuthenticatorService::new().unwrap();
s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));

assert_eq!(
assert_matches!(
s.register(
RegisterFlags::empty(),
1_000,
Expand All @@ -326,10 +332,10 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);

assert_eq!(
assert_matches!(
s.sign(
SignFlags::empty(),
1_000,
Expand All @@ -340,7 +346,7 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);
}

Expand All @@ -352,7 +358,7 @@ mod tests {
let mut s = AuthenticatorService::new().unwrap();
s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));

assert_eq!(
assert_matches!(
s.register(
RegisterFlags::empty(),
1_000,
Expand All @@ -363,10 +369,10 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);

assert_eq!(
assert_matches!(
s.sign(
SignFlags::empty(),
1_000,
Expand All @@ -377,7 +383,7 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);
}

Expand All @@ -392,7 +398,7 @@ mod tests {
let mut s = AuthenticatorService::new().unwrap();
s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));

assert_eq!(
assert_matches!(
s.register(
RegisterFlags::empty(),
100,
Expand All @@ -405,7 +411,7 @@ mod tests {
Ok(())
);

assert_eq!(
assert_matches!(
s.sign(
SignFlags::empty(),
100,
Expand All @@ -432,7 +438,7 @@ mod tests {
let mut s = AuthenticatorService::new().unwrap();
s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));

assert_eq!(
assert_matches!(
s.register(
RegisterFlags::empty(),
1_000,
Expand All @@ -443,10 +449,10 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);

assert_eq!(
assert_matches!(
s.sign(
SignFlags::empty(),
1_000,
Expand All @@ -457,7 +463,7 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::Unknown
crate::errors::AuthenticatorError::InvalidRelyingPartyInput
);
}

Expand All @@ -467,7 +473,7 @@ mod tests {
let (status_tx, _) = channel::<StatusUpdate>();

let mut s = AuthenticatorService::new().unwrap();
assert_eq!(
assert_matches!(
s.register(
RegisterFlags::empty(),
1_000,
Expand All @@ -478,10 +484,10 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::NotSupported
crate::errors::AuthenticatorError::NoConfiguredTransports
);

assert_eq!(
assert_matches!(
s.sign(
SignFlags::empty(),
1_000,
Expand All @@ -492,10 +498,13 @@ mod tests {
StateCallback::new(Box::new(move |_rv| {})),
)
.unwrap_err(),
crate::Error::NotSupported
crate::errors::AuthenticatorError::NoConfiguredTransports
);

assert_eq!(s.cancel().unwrap_err(), crate::Error::NotSupported);
assert_matches!(
s.cancel().unwrap_err(),
crate::errors::AuthenticatorError::NoConfiguredTransports
);
}

#[test]
Expand All @@ -517,18 +526,17 @@ mod tests {
s.add_transport(Box::new(ttd_three));

let callback = StateCallback::new(Box::new(move |_rv| {}));
assert_eq!(
s.register(
assert!(s
.register(
RegisterFlags::empty(),
1_000,
mk_challenge(),
mk_appid(),
vec![],
status_tx.clone(),
callback.clone(),
),
Ok(())
);
)
.is_ok());
callback.wait();

assert_eq!(was_cancelled_one.load(Ordering::SeqCst), false);
Expand All @@ -555,18 +563,17 @@ mod tests {
s.add_transport(Box::new(ttd_three));

let callback = StateCallback::new(Box::new(move |_rv| {}));
assert_eq!(
s.sign(
assert!(s
.sign(
SignFlags::empty(),
1_000,
mk_challenge(),
vec![mk_appid()],
vec![mk_key()],
status_tx,
callback.clone(),
),
Ok(())
);
)
.is_ok());
callback.wait();

assert_eq!(was_cancelled_one.load(Ordering::SeqCst), false);
Expand All @@ -591,18 +598,17 @@ mod tests {
s.add_transport(Box::new(ttd_two));

let callback = StateCallback::new(Box::new(move |_rv| {}));
assert_eq!(
s.register(
assert!(s
.register(
RegisterFlags::empty(),
1_000,
mk_challenge(),
mk_appid(),
vec![],
status_tx.clone(),
callback.clone(),
),
Ok(())
);
)
.is_ok());
callback.wait();

let one = was_cancelled_one.load(Ordering::SeqCst);
Expand Down
Loading