parse error codes at compile time
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
Code,Name,Description
|
||||
0x00,"CTAP1_ERR_SUCCESS, CTAP2_OK",Indicates successful response.
|
||||
0x01,CTAP1_ERR_INVALID_COMMAND,The command is not a valid CTAP command.
|
||||
0x02,CTAP1_ERR_INVALID_PARAMETER,The command included an invalid parameter.
|
||||
0x03,CTAP1_ERR_INVALID_LENGTH,Invalid message or item length.
|
||||
0x04,CTAP1_ERR_INVALID_SEQ,Invalid message sequencing.
|
||||
0x05,CTAP1_ERR_TIMEOUT,Message timed out.
|
||||
0x06,CTAP1_ERR_CHANNEL_BUSY,Channel busy.
|
||||
0x0A,CTAP1_ERR_LOCK_REQUIRED,Command requires channel lock.
|
||||
0x0B,CTAP1_ERR_INVALID_CHANNEL,Command not allowed on this cid.
|
||||
0x11,CTAP2_ERR_CBOR_UNEXPECTED_TYPE,Invalid/unexpected CBOR error.
|
||||
0x12,CTAP2_ERR_INVALID_CBOR,Error when parsing CBOR.
|
||||
0x14,CTAP2_ERR_MISSING_PARAMETER,Missing non-optional parameter.
|
||||
0x15,CTAP2_ERR_LIMIT_EXCEEDED,Limit for number of items exceeded.
|
||||
0x16,CTAP2_ERR_UNSUPPORTED_EXTENSION,Unsupported extension.
|
||||
0x19,CTAP2_ERR_CREDENTIAL_EXCLUDED,Valid credential found in the exclude list.
|
||||
0x21,CTAP2_ERR_PROCESSING,Processing (Lengthy operation is in progress).
|
||||
0x22,CTAP2_ERR_INVALID_CREDENTIAL,Credential not valid for the authenticator.
|
||||
0x23,CTAP2_ERR_USER_ACTION_PENDING,Authentication is waiting for user interaction.
|
||||
0x24,CTAP2_ERR_OPERATION_PENDING,"Processing, lengthy operation is in progress."
|
||||
0x25,CTAP2_ERR_NO_OPERATIONS,No request is pending.
|
||||
0x26,CTAP2_ERR_UNSUPPORTED_ALGORITHM,Authenticator does not support requested algorithm.
|
||||
0x27,CTAP2_ERR_OPERATION_DENIED,Not authorized for requested operation.
|
||||
0x28,CTAP2_ERR_KEY_STORE_FULL,Internal key storage is full.
|
||||
0x29,CTAP2_ERR_NOT_BUSY,Authenticator cannot cancel as it is not busy.
|
||||
0x2A,CTAP2_ERR_NO_OPERATION_PENDING,No outstanding operations.
|
||||
0x2B,CTAP2_ERR_UNSUPPORTED_OPTION,Unsupported option.
|
||||
0x2C,CTAP2_ERR_INVALID_OPTION,Not a valid option for current operation.
|
||||
0x2D,CTAP2_ERR_KEEPALIVE_CANCEL,Pending keep alive was cancelled.
|
||||
0x2E,CTAP2_ERR_NO_CREDENTIALS,No valid credentials provided.
|
||||
0x2F,CTAP2_ERR_USER_ACTION_TIMEOUT,Timeout waiting for user interaction.
|
||||
0x30,CTAP2_ERR_NOT_ALLOWED,"Continuation command, such as, authenticatorGetNextAssertion not allowed."
|
||||
0x31,CTAP2_ERR_PIN_INVALID,PIN Invalid.
|
||||
0x32,CTAP2_ERR_PIN_BLOCKED,PIN Blocked.
|
||||
0x33,CTAP2_ERR_PIN_AUTH_INVALID,"PIN authentication, pinAuth, verification failed."
|
||||
0x34,CTAP2_ERR_PIN_AUTH_BLOCKED,"PIN authentication,pinAuth, blocked. Requires power recycle to reset."
|
||||
0x35,CTAP2_ERR_PIN_NOT_SET,No PIN has been set.
|
||||
0x36,CTAP2_ERR_PIN_REQUIRED,PIN is required for the selected operation.
|
||||
0x37,CTAP2_ERR_PIN_POLICY_VIOLATION,PIN policy violation. Currently only enforces minimum length.
|
||||
0x38,CTAP2_ERR_PIN_TOKEN_EXPIRED,pinToken expired on authenticator.
|
||||
0x39,CTAP2_ERR_REQUEST_TOO_LARGE,Authenticator cannot handle this request due to memory constraints.
|
||||
0x3A,CTAP2_ERR_ACTION_TIMEOUT,The current operation has timed out.
|
||||
0x3B,CTAP2_ERR_UP_REQUIRED,User presence is required for the requested operation.
|
||||
0x7F,CTAP1_ERR_OTHER,Other unspecified error.
|
||||
0xDF,CTAP2_ERR_SPEC_LAST,CTAP 2 spec last error.
|
||||
0xE0,CTAP2_ERR_EXTENSION_FIRST,Extension specific error.
|
||||
0xEF,CTAP2_ERR_EXTENSION_LAST,Extension specific error.
|
||||
0xF0,CTAP2_ERR_VENDOR_FIRST,Vendor specific error.
|
||||
0xFF,CTAP2_ERR_VENDOR_LAST,Vendor specific error.
|
|
92
src/error.rs
92
src/error.rs
@@ -5,8 +5,8 @@
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
use cbor_codec::{DecodeError, EncodeError};
|
||||
use csv_core::{ReadFieldResult, Reader};
|
||||
use failure::_core::fmt::{Error, Formatter};
|
||||
use failure::_core::option::Option;
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
@@ -19,6 +19,32 @@ pub struct FidoError(Context<FidoErrorKind>);
|
||||
#[derive(Debug, Copy, Clone, Fail, Eq, PartialEq)]
|
||||
pub struct CborErrorCode(u8);
|
||||
|
||||
// generated using build.rs
|
||||
include!(concat!(env!("OUT_DIR"), "/ctap_error_codes.rs"));
|
||||
|
||||
impl CborErrorCode {
|
||||
fn detail(&self) -> Option<(u8, &'static str, &'static str)> {
|
||||
for (code, name, desc) in CTAP_ERROR_CODES {
|
||||
if *code == self.0 as usize {
|
||||
return Some((self.0, name, desc));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<&'static str> {
|
||||
self.detail().map(|(_, name, _)| name)
|
||||
}
|
||||
|
||||
pub fn description(&self) -> Option<&'static str> {
|
||||
self.detail().map(|(_, _, desc)| desc)
|
||||
}
|
||||
|
||||
pub fn code(&self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
|
||||
pub enum FidoErrorKind {
|
||||
#[fail(display = "Read/write error with device.")]
|
||||
@@ -116,58 +142,24 @@ impl From<u8> for CborErrorCode {
|
||||
|
||||
impl Display for CborErrorCode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
let messages = include_str!("ctap_error_codes.csv");
|
||||
let mut rdr = Reader::new();
|
||||
let mut bytes = messages.as_bytes();
|
||||
let mut col: usize = 0;
|
||||
let mut row: usize = 0;
|
||||
let mut correct_row: bool = false;
|
||||
let mut field = [0u8; 1024];
|
||||
let mut name: Option<String> = None;
|
||||
let mut desc: Option<String> = None;
|
||||
loop {
|
||||
let (result, nin, read) = rdr.read_field(&bytes, &mut field);
|
||||
bytes = &bytes[nin..];
|
||||
match result {
|
||||
ReadFieldResult::InputEmpty => {}
|
||||
ReadFieldResult::OutputFull => panic!("field too large"),
|
||||
ReadFieldResult::Field { record_end } => {
|
||||
let text = String::from_utf8(field[..read].iter().cloned().collect()).unwrap();
|
||||
if row > 0 {
|
||||
match col {
|
||||
0 if i64::from_str_radix(&text[2..], 16)
|
||||
.expect("malformed ctap_error_codes.csv")
|
||||
== self.0 as i64 =>
|
||||
{
|
||||
correct_row = true
|
||||
}
|
||||
1 | 2 if correct_row => {
|
||||
if let Some(_) = name {
|
||||
desc = Some(text);
|
||||
break;
|
||||
} else {
|
||||
name = Some(text);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
col += 1;
|
||||
if record_end {
|
||||
col = 0;
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
ReadFieldResult::End => break,
|
||||
}
|
||||
}
|
||||
if let Some((code, _name, desc)) =
|
||||
name.and_then(|name| desc.map(|desc| (self.0, name, desc)))
|
||||
{
|
||||
if let Some((code, _name, desc)) = self.detail() {
|
||||
write!(f, "CborError: 0x{:x?}: {}", code, desc)?;
|
||||
} else {
|
||||
write!(f, "CborError: 0x{:x?}", self.0)?;
|
||||
write!(f, "CborError: 0x{:x?}: unknown", self.code())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn cbor_error_code() {
|
||||
assert_eq!(
|
||||
CborErrorCode(0x33).to_string(),
|
||||
"CborError: 0x33: PIN authentication, pinAuth, verification failed."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user