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 serde::{Deserialize, Serialize};
use std::fmt;
use std::time::Duration;
use url::Url;
use uuid::Uuid;
@ -25,8 +26,8 @@ pub enum DbPasswordV1 {
SSHA512(Vec<u8>, Vec<u8>),
}
impl std::fmt::Debug for DbPasswordV1 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl fmt::Debug for DbPasswordV1 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DbPasswordV1::PBKDF2(_, _, _) => write!(f, "PBKDF2"),
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)]
pub struct DbValueCredV1 {
#[serde(rename = "t")]

View file

@ -325,9 +325,9 @@ impl TryFrom<DbCred> for Credential {
}
| DbCred::Pw {
password: Some(db_password),
webauthn: None,
totp: None,
backup_code: None,
webauthn: _,
totp: _,
backup_code: _,
claims: _,
uuid,
} => {
@ -345,9 +345,9 @@ impl TryFrom<DbCred> for Credential {
}
| DbCred::GPw {
password: Some(db_password),
webauthn: None,
totp: None,
backup_code: None,
webauthn: _,
totp: _,
backup_code: _,
claims: _,
uuid,
} => {
@ -361,7 +361,7 @@ impl TryFrom<DbCred> for Credential {
}
DbCred::PwMfa {
password: Some(db_password),
webauthn: Some(db_webauthn),
webauthn: maybe_db_webauthn,
totp,
backup_code,
claims: _,
@ -374,21 +374,24 @@ impl TryFrom<DbCred> for Credential {
None => None,
};
let v_webauthn = db_webauthn
.into_iter()
.map(|wc| {
(
wc.label,
SecurityKey::from(WebauthnCredential::from(CredentialV3 {
cred_id: wc.id,
cred: wc.cred,
counter: wc.counter,
verified: wc.verified,
registration_policy: wc.registration_policy,
})),
)
})
.collect();
let v_webauthn = match maybe_db_webauthn {
Some(db_webauthn) => db_webauthn
.into_iter()
.map(|wc| {
(
wc.label,
SecurityKey::from(WebauthnCredential::from(CredentialV3 {
cred_id: wc.id,
cred: wc.cred,
counter: wc.counter,
verified: wc.verified,
registration_policy: wc.registration_policy,
})),
)
})
.collect(),
None => Default::default(),
};
let v_backup_code = match backup_code {
Some(dbb) => Some(BackupCodes::try_from(dbb)?),
@ -405,10 +408,10 @@ impl TryFrom<DbCred> for Credential {
}
}
DbCred::Wn {
password: None,
password: _,
webauthn: Some(db_webauthn),
totp: None,
backup_code: None,
totp: _,
backup_code: _,
claims: _,
uuid,
} => {
@ -436,19 +439,33 @@ impl TryFrom<DbCred> for Credential {
Err(())
}
}
DbCred::TmpWn { .. } => {
todo!()
DbCred::TmpWn {
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 {
password: db_password,
totp: Some(db_totp),
totp: maybe_db_totp,
backup_code,
webauthn: db_webauthn,
uuid,
} => {
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 {
Some(dbb) => Some(BackupCodes::try_from(dbb)?),
@ -466,8 +483,10 @@ impl TryFrom<DbCred> for Credential {
Err(())
}
}
_ => {
error!("Database content may be corrupt - invalid credential");
credential => {
error!("Database content may be corrupt - invalid credential state");
debug!(%credential);
debug!(?credential);
Err(())
}
}