Fix credential parsing (#988)

This commit is contained in:
Firstyear 2022-08-09 12:58:54 +10:00 committed by GitHub
parent 7e617a6320
commit 955d9d940d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 147 additions and 33 deletions

View file

@ -1,5 +1,6 @@
use hashbrown::HashSet; use hashbrown::HashSet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::time::Duration; use std::time::Duration;
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
@ -25,8 +26,8 @@ pub enum DbPasswordV1 {
SSHA512(Vec<u8>, Vec<u8>), SSHA512(Vec<u8>, Vec<u8>),
} }
impl std::fmt::Debug for DbPasswordV1 { impl fmt::Debug for DbPasswordV1 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
DbPasswordV1::PBKDF2(_, _, _) => write!(f, "PBKDF2"), DbPasswordV1::PBKDF2(_, _, _) => write!(f, "PBKDF2"),
DbPasswordV1::SSHA512(_, _) => write!(f, "SSHA512"), DbPasswordV1::SSHA512(_, _) => write!(f, "SSHA512"),
@ -182,6 +183,100 @@ pub enum DbCred {
}, },
} }
impl fmt::Display for DbCred {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DbCred::Pw {
password,
webauthn,
totp,
backup_code,
claims,
uuid,
} => write!(
f,
"Pw (p {}, w {}, t {}, b {}, c {}, u {})",
password.is_some(),
webauthn.is_some(),
totp.is_some(),
backup_code.is_some(),
claims.len(),
uuid
),
DbCred::GPw {
password,
webauthn,
totp,
backup_code,
claims,
uuid,
} => write!(
f,
"GPw (p {}, w {}, t {}, b {}, c {}, u {})",
password.is_some(),
webauthn.is_some(),
totp.is_some(),
backup_code.is_some(),
claims.len(),
uuid
),
DbCred::PwMfa {
password,
webauthn,
totp,
backup_code,
claims,
uuid,
} => write!(
f,
"PwMfa (p {}, w {}, t {}, b {}, c {}, u {})",
password.is_some(),
webauthn.is_some(),
totp.is_some(),
backup_code.is_some(),
claims.len(),
uuid
),
DbCred::Wn {
password,
webauthn,
totp,
backup_code,
claims,
uuid,
} => write!(
f,
"Wn (p {}, w {}, t {}, b {}, c {}, u {})",
password.is_some(),
webauthn.is_some(),
totp.is_some(),
backup_code.is_some(),
claims.len(),
uuid
),
DbCred::TmpWn { webauthn, uuid } => {
write!(f, "TmpWn ( w {}, u {} )", webauthn.len(), uuid)
}
DbCred::V2Password { password: _, uuid } => write!(f, "V2Pw ( u {} )", uuid),
DbCred::V2GenPassword { password: _, uuid } => write!(f, "V2GPw ( u {} )", uuid),
DbCred::V2PasswordMfa {
password: _,
totp,
backup_code,
webauthn,
uuid,
} => write!(
f,
"V2PwMfa (p true, w {}, t {}, b {}, u {})",
webauthn.len(),
totp.is_some(),
backup_code.is_some(),
uuid
),
}
}
}
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct DbValueCredV1 { pub struct DbValueCredV1 {
#[serde(rename = "t")] #[serde(rename = "t")]

View file

@ -325,9 +325,9 @@ impl TryFrom<DbCred> for Credential {
} }
| DbCred::Pw { | DbCred::Pw {
password: Some(db_password), password: Some(db_password),
webauthn: None, webauthn: _,
totp: None, totp: _,
backup_code: None, backup_code: _,
claims: _, claims: _,
uuid, uuid,
} => { } => {
@ -345,9 +345,9 @@ impl TryFrom<DbCred> for Credential {
} }
| DbCred::GPw { | DbCred::GPw {
password: Some(db_password), password: Some(db_password),
webauthn: None, webauthn: _,
totp: None, totp: _,
backup_code: None, backup_code: _,
claims: _, claims: _,
uuid, uuid,
} => { } => {
@ -361,7 +361,7 @@ impl TryFrom<DbCred> for Credential {
} }
DbCred::PwMfa { DbCred::PwMfa {
password: Some(db_password), password: Some(db_password),
webauthn: Some(db_webauthn), webauthn: maybe_db_webauthn,
totp, totp,
backup_code, backup_code,
claims: _, claims: _,
@ -374,7 +374,8 @@ impl TryFrom<DbCred> for Credential {
None => None, None => None,
}; };
let v_webauthn = db_webauthn let v_webauthn = match maybe_db_webauthn {
Some(db_webauthn) => db_webauthn
.into_iter() .into_iter()
.map(|wc| { .map(|wc| {
( (
@ -388,7 +389,9 @@ impl TryFrom<DbCred> for Credential {
})), })),
) )
}) })
.collect(); .collect(),
None => Default::default(),
};
let v_backup_code = match backup_code { let v_backup_code = match backup_code {
Some(dbb) => Some(BackupCodes::try_from(dbb)?), Some(dbb) => Some(BackupCodes::try_from(dbb)?),
@ -405,10 +408,10 @@ impl TryFrom<DbCred> for Credential {
} }
} }
DbCred::Wn { DbCred::Wn {
password: None, password: _,
webauthn: Some(db_webauthn), webauthn: Some(db_webauthn),
totp: None, totp: _,
backup_code: None, backup_code: _,
claims: _, claims: _,
uuid, uuid,
} => { } => {
@ -436,19 +439,33 @@ impl TryFrom<DbCred> for Credential {
Err(()) Err(())
} }
} }
DbCred::TmpWn { .. } => { DbCred::TmpWn {
todo!() webauthn: db_webauthn,
uuid,
} => {
let v_webauthn = db_webauthn.into_iter().collect();
let type_ = CredentialType::Webauthn(v_webauthn);
if type_.is_valid() {
Ok(Credential { type_, uuid })
} else {
Err(())
}
} }
DbCred::V2PasswordMfa { DbCred::V2PasswordMfa {
password: db_password, password: db_password,
totp: Some(db_totp), totp: maybe_db_totp,
backup_code, backup_code,
webauthn: db_webauthn, webauthn: db_webauthn,
uuid, uuid,
} => { } => {
let v_password = Password::try_from(db_password)?; let v_password = Password::try_from(db_password)?;
let v_totp = Some(Totp::try_from(db_totp)?); let v_totp = if let Some(db_totp) = maybe_db_totp {
Some(Totp::try_from(db_totp)?)
} else {
None
};
let v_backup_code = match backup_code { let v_backup_code = match backup_code {
Some(dbb) => Some(BackupCodes::try_from(dbb)?), Some(dbb) => Some(BackupCodes::try_from(dbb)?),
@ -466,8 +483,10 @@ impl TryFrom<DbCred> for Credential {
Err(()) Err(())
} }
} }
_ => { credential => {
error!("Database content may be corrupt - invalid credential"); error!("Database content may be corrupt - invalid credential state");
debug!(%credential);
debug!(?credential);
Err(()) Err(())
} }
} }