Ignore U2F challenge if not provided. Also checked that error_code has to be 0 for a successfull registration

This commit is contained in:
Daniel García 2018-07-13 12:28:35 +02:00
parent 6378d96d1a
commit 75615bb5c8
2 changed files with 38 additions and 4 deletions

View File

@ -254,6 +254,29 @@ struct EnableU2FData {
DeviceResponse: String, DeviceResponse: String,
} }
// This struct is copied from the U2F lib
// because challenge is not always sent
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct RegisterResponseCopy {
pub registration_data: String,
pub version: String,
pub challenge: Option<String>,
pub error_code: Option<NumberOrString>,
pub client_data: String,
}
impl RegisterResponseCopy {
fn into_response(self, challenge: String) -> RegisterResponse {
RegisterResponse {
registration_data: self.registration_data,
version: self.version,
challenge: challenge,
client_data: self.client_data,
}
}
}
#[post("/two-factor/u2f", data = "<data>")] #[post("/two-factor/u2f", data = "<data>")]
fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn) -> JsonResult { fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn) -> JsonResult {
let data: EnableU2FData = data.into_inner().data; let data: EnableU2FData = data.into_inner().data;
@ -278,8 +301,19 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn)
println!("RegisterResponse {:#?}", &data.DeviceResponse); println!("RegisterResponse {:#?}", &data.DeviceResponse);
let response: RegisterResponse = let response_copy: RegisterResponseCopy =
serde_json::from_str(&data.DeviceResponse).expect("Can't parse DeviceResponse data"); serde_json::from_str(&data.DeviceResponse).expect("Can't parse RegisterResponse data");
let error_code = response_copy
.error_code
.clone()
.map_or("0".into(), NumberOrString::into_string);
if error_code != "0" {
err!("Error registering U2F token")
}
let response = response_copy.into_response(challenge.challenge.clone());
match U2F.register_response(challenge.clone(), response) { match U2F.register_response(challenge.clone(), response) {
Ok(registration) => { Ok(registration) => {
@ -337,7 +371,7 @@ fn _create_u2f_challenge(user_uuid: &str, type_: TwoFactorType, conn: &DbConn) -
// because it doesn't implement Deserialize // because it doesn't implement Deserialize
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RegistrationCopy { struct RegistrationCopy {
pub key_handle: Vec<u8>, pub key_handle: Vec<u8>,
pub pub_key: Vec<u8>, pub pub_key: Vec<u8>,
pub attestation_cert: Option<Vec<u8>>, pub attestation_cert: Option<Vec<u8>>,

View File

@ -26,7 +26,7 @@ struct PasswordData {
MasterPasswordHash: String MasterPasswordHash: String
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug, Clone)]
#[serde(untagged)] #[serde(untagged)]
enum NumberOrString { enum NumberOrString {
Number(i32), Number(i32),