Making clippy happy (#420)

This commit is contained in:
James Hodgkinson 2021-04-25 11:35:56 +10:00 committed by GitHub
parent 01e9aa982d
commit de431451f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 446 additions and 540 deletions

View file

@ -101,7 +101,7 @@ An improved design will have Credential become an enum representing the valid au
Anonymous,
Password(),
GeneratedPassword(),
PasswordMFA(),
PasswordMfa(),
PasswordWebauthn(),
Webauthn(),
WebauthnVerified(),
@ -160,7 +160,7 @@ the correct way to handle these).
Anonymous,
Password,
// This covers PasswordWebauthn as well.
PasswordMFA,
PasswordMfa,
Webauthn,
WebauthnVerified,
PasswordWebauthnVerified,

View file

@ -24,7 +24,7 @@ An example of this display for the CLI:
expire_at: <date>
- <credential_id>
type: Password|APIKey|PasswordMFA
type: Password|APIKey|PasswordMfa
locked: true|false
valid_from: <date>
expire_at: <date>

View file

@ -368,7 +368,7 @@ impl KanidmAsyncClient {
pub async fn auth_step_totp(&mut self, totp: u32) -> Result<AuthResponse, ClientError> {
let auth_req = AuthRequest {
step: AuthStep::Cred(AuthCredential::TOTP(totp)),
step: AuthStep::Cred(AuthCredential::Totp(totp)),
};
let r: Result<AuthResponse, _> = self.perform_auth_post_request("/v1/auth", auth_req).await;
@ -463,17 +463,17 @@ impl KanidmAsyncClient {
Err(e) => return Err(e),
};
if !mechs.contains(&AuthMech::PasswordMFA) {
debug!("PasswordMFA mech not presented");
if !mechs.contains(&AuthMech::PasswordMfa) {
debug!("PasswordMfa mech not presented");
return Err(ClientError::AuthenticationFailed);
}
let state = match self.auth_step_begin(AuthMech::PasswordMFA).await {
let state = match self.auth_step_begin(AuthMech::PasswordMfa).await {
Ok(s) => s,
Err(e) => return Err(e),
};
if !state.contains(&AuthAllowed::TOTP) {
if !state.contains(&AuthAllowed::Totp) {
debug!("TOTP step not offered.");
return Err(ClientError::AuthenticationFailed);
}
@ -818,8 +818,8 @@ impl KanidmAsyncClient {
&self,
id: &str,
label: &str,
) -> Result<(Uuid, TOTPSecret), ClientError> {
let r = SetCredentialRequest::TOTPGenerate(label.to_string());
) -> Result<(Uuid, TotpSecret), ClientError> {
let r = SetCredentialRequest::TotpGenerate(label.to_string());
let res: Result<SetCredentialResponse, ClientError> = self
.perform_put_request(
format!("/v1/account/{}/_credential/primary", id).as_str(),
@ -827,7 +827,7 @@ impl KanidmAsyncClient {
)
.await;
match res {
Ok(SetCredentialResponse::TOTPCheck(u, s)) => Ok((u, s)),
Ok(SetCredentialResponse::TotpCheck(u, s)) => Ok((u, s)),
Ok(_) => Err(ClientError::EmptyResponse),
Err(e) => Err(e),
}
@ -840,7 +840,7 @@ impl KanidmAsyncClient {
otp: u32,
session: Uuid,
) -> Result<bool, ClientError> {
let r = SetCredentialRequest::TOTPVerify(session, otp);
let r = SetCredentialRequest::TotpVerify(session, otp);
let res: Result<SetCredentialResponse, ClientError> = self
.perform_put_request(
format!("/v1/account/{}/_credential/primary", id).as_str(),
@ -849,7 +849,7 @@ impl KanidmAsyncClient {
.await;
match res {
Ok(SetCredentialResponse::Success) => Ok(true),
Ok(SetCredentialResponse::TOTPCheck(u, s)) => Err(ClientError::TOTPVerifyFailed(u, s)),
Ok(SetCredentialResponse::TotpCheck(u, s)) => Err(ClientError::TotpVerifyFailed(u, s)),
Ok(_) => Err(ClientError::EmptyResponse),
Err(e) => Err(e),
}
@ -859,7 +859,7 @@ impl KanidmAsyncClient {
&self,
id: &str,
) -> Result<bool, ClientError> {
let r = SetCredentialRequest::TOTPRemove;
let r = SetCredentialRequest::TotpRemove;
let res: Result<SetCredentialResponse, ClientError> = self
.perform_put_request(
format!("/v1/account/{}/_credential/primary", id).as_str(),

View file

@ -45,7 +45,7 @@ pub enum ClientError {
Transport(reqwest::Error),
AuthenticationFailed,
EmptyResponse,
TOTPVerifyFailed(Uuid, TOTPSecret),
TotpVerifyFailed(Uuid, TotpSecret),
JSONDecode(reqwest::Error, String),
JSONEncode(SerdeJsonError),
SystemError,
@ -555,7 +555,7 @@ impl KanidmClient {
&self,
id: &str,
label: &str,
) -> Result<(Uuid, TOTPSecret), ClientError> {
) -> Result<(Uuid, TotpSecret), ClientError> {
tokio_block_on(
self.asclient
.idm_account_primary_credential_generate_totp(id, label),

View file

@ -10,6 +10,7 @@ use kanidm_client::{KanidmClient, KanidmClientBuilder};
use async_std::task;
use tokio::sync::mpsc;
pub const ADMIN_TEST_USER: &str = "admin";
pub const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
static PORT_ALLOC: AtomicU16 = AtomicU16::new(18080);
@ -47,6 +48,7 @@ pub fn run_test(test_fn: fn(KanidmClient) -> ()) {
};
let int_config = Box::new(IntegrationTestConfig {
admin_user: ADMIN_TEST_USER.to_string(),
admin_password: ADMIN_TEST_PASSWORD.to_string(),
});
@ -57,9 +59,9 @@ pub fn run_test(test_fn: fn(KanidmClient) -> ()) {
config.integration_test_config = Some(int_config);
config.log_level = Some(LogLevel::Quiet as u32);
// config.log_level = Some(LogLevel::Verbose as u32);
// config.log_level = Some(LogLevel::FullTrace as u32);
config.threads = 1;
// config.log_level = Some(LogLevel::FullTrace as u32);
let t_handle = thread::spawn(move || {
// Spawn a thread for the test runner, this should have a unique
// port....

View file

@ -5,7 +5,7 @@ use kanidm_client::KanidmClient;
use kanidm_proto::v1::{Filter, Modify, ModifyList};
mod common;
use crate::common::{run_test, ADMIN_TEST_PASSWORD};
use crate::common::{run_test, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER};
static USER_READABLE_ATTRS: [&str; 9] = [
"name",
@ -113,7 +113,7 @@ fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option<boo
fn add_all_attrs(mut rsclient: &mut KanidmClient, id: &str, group_name: &str) {
// Extend with posix attrs to test read attr: gidnumber and loginshell
rsclient
.idm_group_add_members("idm_admins", &["admin"])
.idm_group_add_members("idm_admins", &[ADMIN_TEST_USER])
.unwrap();
rsclient
.idm_account_unix_extend(id, None, Some(&"/bin/bash"))
@ -136,7 +136,7 @@ fn add_all_attrs(mut rsclient: &mut KanidmClient, id: &str, group_name: &str) {
.idm_account_radius_credential_regenerate(id)
.unwrap();
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
}
}
@ -155,10 +155,13 @@ fn create_user_with_all_attrs(
fn login_account(rsclient: &mut KanidmClient, id: &str) -> () {
rsclient
.idm_group_add_members("idm_people_account_password_import_priv", &["admin"])
.idm_group_add_members(
"idm_people_account_password_import_priv",
&[ADMIN_TEST_USER],
)
.unwrap();
rsclient
.idm_group_add_members("idm_people_extend_priv", &["admin"])
.idm_group_add_members("idm_people_extend_priv", &[ADMIN_TEST_USER])
.unwrap();
rsclient
@ -225,7 +228,7 @@ fn test_modify_group(rsclient: &KanidmClient, group_names: &[&str], is_modificab
fn test_default_entries_rbac_users() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user_with_all_attrs(&mut rsclient, "self_account", Some("self_group"));
@ -263,7 +266,7 @@ fn test_default_entries_rbac_users() {
fn test_default_entries_rbac_account_managers() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "account_manager", "idm_account_manage_priv");
@ -295,7 +298,7 @@ fn test_default_entries_rbac_account_managers() {
fn test_default_entries_rbac_group_managers() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "group_manager", "idm_group_manage_priv");
@ -336,7 +339,7 @@ fn test_default_entries_rbac_group_managers() {
fn test_default_entries_rbac_admins_access_control_entries() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
static ACP_COMMON_ATTRS: [&str; 4] =
["name", "description", "acp_receiver", "acp_targetscope"];
@ -384,7 +387,7 @@ fn test_default_entries_rbac_admins_access_control_entries() {
fn test_default_entries_rbac_admins_schema_entries() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
let default_classnames: HashSet<String> = [
"access_control_create",
@ -495,7 +498,7 @@ fn test_default_entries_rbac_admins_schema_entries() {
fn test_default_entries_rbac_admins_group_entries() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "test", "test_group");
@ -511,7 +514,7 @@ fn test_default_entries_rbac_admins_group_entries() {
fn test_default_entries_rbac_admins_ha_accounts() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
static MAIN_ATTRS: [&str; 3] = ["name", "displayname", "primary_credential"];
@ -524,7 +527,7 @@ fn test_default_entries_rbac_admins_ha_accounts() {
fn test_default_entries_rbac_admins_recycle_accounts() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "test", "test_group");
@ -543,7 +546,7 @@ fn test_default_entries_rbac_admins_recycle_accounts() {
fn test_default_entries_rbac_people_managers() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "read_people_manager", "idm_people_read_priv");
@ -564,7 +567,7 @@ fn test_default_entries_rbac_people_managers() {
let _ = rsclient.logout();
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "write_people_manager", "idm_people_write_priv");
login_account(&mut rsclient, "write_people_manager");
@ -582,7 +585,7 @@ fn test_default_entries_rbac_people_managers() {
fn test_default_entries_rbac_anonymous_entry() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
rsclient
@ -607,7 +610,7 @@ fn test_default_entries_rbac_anonymous_entry() {
fn test_default_entries_rbac_radius_servers() {
run_test(|mut rsclient: KanidmClient| {
rsclient
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.unwrap();
create_user(&rsclient, "radius_server", "idm_radius_servers");
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));

View file

@ -3,7 +3,7 @@ use std::time::SystemTime;
use log::debug;
use kanidm::credential::totp::TOTP;
use kanidm::credential::totp::Totp;
use kanidm_client::KanidmClient;
use kanidm_proto::v1::{CredentialDetailType, Entry, Filter, Modify, ModifyList};
@ -46,7 +46,7 @@ fn test_server_modify() {
run_test(|mut rsclient: KanidmClient| {
// Build a self mod.
let f = Filter::SelfUUID;
let f = Filter::SelfUuid;
let m = ModifyList::new_list(vec![
Modify::Purged("displayname".to_string()),
Modify::Present("displayname".to_string(), "test".to_string()),
@ -761,7 +761,7 @@ fn test_server_rest_totp_auth_lifecycle() {
.idm_account_primary_credential_generate_totp("demo_account", "demo")
.unwrap();
let r_tok: TOTP = tok.into();
let r_tok: Totp = tok.into();
let totp = r_tok
.do_totp_duration_from_epoch(
&SystemTime::now()
@ -960,7 +960,7 @@ fn test_server_rest_webauthn_mfa_auth_lifecycle() {
.auth_webauthn_complete(auth)
.expect("Failed to authenticate");
// Set a password to cause the state to change to PasswordMFA
// Set a password to cause the state to change to PasswordMfa
assert!(rsclient
.idm_account_primary_credential_set_password("demo_account", "sohdi3iuHo6mai7noh0a")
.is_ok());

View file

@ -49,7 +49,7 @@ pub enum ConsistencyError {
MemberOfInvalid(u64),
InvalidAttributeType(String),
DuplicateUniqueAttribute(String),
InvalidSPN(u64),
InvalidSpn(u64),
SqliteIntegrityFailure,
}
@ -66,23 +66,23 @@ pub enum OperationError {
SchemaViolation(SchemaError),
Plugin(PluginError),
FilterGeneration,
FilterUUIDResolution,
FilterUuidResolution,
InvalidAttributeName(String),
InvalidAttribute(String),
InvalidDBState,
InvalidDbState,
InvalidCacheState,
InvalidValueState,
InvalidEntryID,
InvalidEntryId,
InvalidRequestState,
InvalidState,
InvalidEntryState,
InvalidUuid,
InvalidReplCID,
InvalidACPState(String),
InvalidAcpState(String),
InvalidSchemaState(String),
InvalidAccountState(String),
BackendEngine,
SQLiteError, //(RusqliteError)
SqliteError, //(RusqliteError)
FsError,
SerdeJsonError,
SerdeCborError,
@ -286,7 +286,7 @@ pub enum CredentialDetailType {
GeneratedPassword,
Webauthn(Vec<String>),
/// totp, webauthn
PasswordMFA(bool, Vec<String>),
PasswordMfa(bool, Vec<String>),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -317,7 +317,7 @@ impl fmt::Display for CredentialDetail {
write!(f, "")
}
}
CredentialDetailType::PasswordMFA(totp, labels) => {
CredentialDetailType::PasswordMfa(totp, labels) => {
writeln!(f, "password: set")?;
if *totp {
writeln!(f, "totp: enabled")?;
@ -391,7 +391,7 @@ pub enum Filter {
#[serde(alias = "AndNot")]
AndNot(Box<Filter>),
#[serde(rename = "self", alias = "Self")]
SelfUUID,
SelfUuid,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@ -496,7 +496,7 @@ impl ModifyRequest {
pub enum AuthCredential {
Anonymous,
Password(String),
TOTP(u32),
Totp(u32),
Webauthn(PublicKeyCredential),
}
@ -505,7 +505,7 @@ impl fmt::Debug for AuthCredential {
match self {
AuthCredential::Anonymous => write!(fmt, "Anonymous"),
AuthCredential::Password(_) => write!(fmt, "Password(_)"),
AuthCredential::TOTP(_) => write!(fmt, "TOTP(_)"),
AuthCredential::Totp(_) => write!(fmt, "TOTP(_)"),
AuthCredential::Webauthn(_) => write!(fmt, "Webauthn(_)"),
}
}
@ -516,7 +516,7 @@ impl fmt::Debug for AuthCredential {
pub enum AuthMech {
Anonymous,
Password,
PasswordMFA,
PasswordMfa,
Webauthn,
// WebauthnVerified,
// PasswordWebauthnVerified
@ -533,7 +533,7 @@ impl fmt::Display for AuthMech {
match self {
AuthMech::Anonymous => write!(f, "Anonymous (no credentials)"),
AuthMech::Password => write!(f, "Passwold Only"),
AuthMech::PasswordMFA => write!(f, "TOTP or Token, and Password"),
AuthMech::PasswordMfa => write!(f, "TOTP or Token, and Password"),
AuthMech::Webauthn => write!(f, "Webauthn Token"),
}
}
@ -565,7 +565,7 @@ pub struct AuthRequest {
pub enum AuthAllowed {
Anonymous,
Password,
TOTP,
Totp,
Webauthn(RequestChallengeResponse),
}
@ -588,8 +588,8 @@ impl Ord for AuthAllowed {
(_, AuthAllowed::Anonymous) => Ordering::Greater,
(AuthAllowed::Password, _) => Ordering::Less,
(_, AuthAllowed::Password) => Ordering::Greater,
(AuthAllowed::TOTP, _) => Ordering::Less,
(_, AuthAllowed::TOTP) => Ordering::Greater,
(AuthAllowed::Totp, _) => Ordering::Less,
(_, AuthAllowed::Totp) => Ordering::Greater,
(AuthAllowed::Webauthn(_), _) => Ordering::Less,
// Unreachable
// (_, AuthAllowed::Webauthn(_)) => Ordering::Greater,
@ -609,7 +609,7 @@ impl fmt::Display for AuthAllowed {
match self {
AuthAllowed::Anonymous => write!(f, "Anonymous (no credentials)"),
AuthAllowed::Password => write!(f, "Password"),
AuthAllowed::TOTP => write!(f, "TOTP"),
AuthAllowed::Totp => write!(f, "TOTP"),
AuthAllowed::Webauthn(_) => write!(f, "Webauthn Token"),
}
}
@ -641,9 +641,9 @@ pub struct AuthResponse {
pub enum SetCredentialRequest {
Password(String),
GeneratePassword,
TOTPGenerate(String),
TOTPVerify(Uuid, u32),
TOTPRemove,
TotpGenerate(String),
TotpVerify(Uuid, u32),
TotpRemove,
// Start the rego.
WebauthnBegin(String),
// Finish it.
@ -654,32 +654,32 @@ pub enum SetCredentialRequest {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TOTPAlgo {
pub enum TotpAlgo {
Sha1,
Sha256,
Sha512,
}
impl fmt::Display for TOTPAlgo {
impl fmt::Display for TotpAlgo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TOTPAlgo::Sha1 => write!(f, "SHA1"),
TOTPAlgo::Sha256 => write!(f, "SHA256"),
TOTPAlgo::Sha512 => write!(f, "SHA512"),
TotpAlgo::Sha1 => write!(f, "SHA1"),
TotpAlgo::Sha256 => write!(f, "SHA256"),
TotpAlgo::Sha512 => write!(f, "SHA512"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TOTPSecret {
pub struct TotpSecret {
pub accountname: String,
pub issuer: String,
pub secret: Vec<u8>,
pub algo: TOTPAlgo,
pub algo: TotpAlgo,
pub step: u64,
}
impl TOTPSecret {
impl TotpSecret {
/// https://github.com/google/google-authenticator/wiki/Key-Uri-Format
pub fn to_uri(&self) -> String {
// label = accountname / issuer (“:” / “%3A”) *”%20” accountname
@ -714,7 +714,7 @@ impl TOTPSecret {
pub enum SetCredentialResponse {
Success,
Token(String),
TOTPCheck(Uuid, TOTPSecret),
TotpCheck(Uuid, TotpSecret),
WebauthnCreateChallenge(Uuid, CreationChallengeResponse),
}
@ -789,7 +789,7 @@ impl SingleStringRequest {
#[cfg(test)]
mod tests {
use crate::v1::Filter as ProtoFilter;
use crate::v1::{TOTPAlgo, TOTPSecret};
use crate::v1::{TotpAlgo, TotpSecret};
#[test]
fn test_protofilter_simple() {
@ -800,23 +800,23 @@ mod tests {
#[test]
fn totp_to_string() {
let totp = TOTPSecret {
let totp = TotpSecret {
accountname: "william".to_string(),
issuer: "blackhats".to_string(),
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
step: 30,
algo: TOTPAlgo::Sha256,
algo: TotpAlgo::Sha256,
};
let s = totp.to_uri();
assert!(s == "otpauth://totp/blackhats:william?secret=VK54ZXI&issuer=blackhats&algorithm=SHA256&digits=6&period=30");
// check that invalid issuer/accounts are cleaned up.
let totp = TOTPSecret {
let totp = TotpSecret {
accountname: "william:%3A".to_string(),
issuer: "blackhats australia".to_string(),
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
step: 30,
algo: TOTPAlgo::Sha256,
algo: TotpAlgo::Sha256,
};
let s = totp.to_uri();
assert!(s == "otpauth://totp/blackhats%20australia:william?secret=VK54ZXI&issuer=blackhats%20australia&algorithm=SHA256&digits=6&period=30");

View file

@ -18,7 +18,7 @@ impl AccountOpt {
AccountCredential::RegisterWebauthn(acs) => acs.copt.debug,
AccountCredential::RemoveWebauthn(acs) => acs.copt.debug,
AccountCredential::RegisterTotp(acs) => acs.copt.debug,
AccountCredential::RemoveTOTP(acs) => acs.copt.debug,
AccountCredential::RemoveTotp(acs) => acs.copt.debug,
AccountCredential::Status(acs) => acs.copt.debug,
},
AccountOpt::Radius(acopt) => match acopt {
@ -213,7 +213,7 @@ impl AccountOpt {
}
}
}
AccountCredential::RemoveTOTP(acsopt) => {
AccountCredential::RemoveTotp(acsopt) => {
let client = acsopt.copt.to_client();
match client.idm_account_primary_credential_remove_totp(
acsopt.aopts.account_id.as_str(),

View file

@ -256,7 +256,7 @@ impl LoginOpt {
let res = match choice {
AuthAllowed::Anonymous => client.auth_step_anonymous(),
AuthAllowed::Password => self.do_password(&mut client),
AuthAllowed::TOTP => self.do_totp(&mut client),
AuthAllowed::Totp => self.do_totp(&mut client),
AuthAllowed::Webauthn(chal) => self.do_webauthn(&mut client, chal.clone()),
};

View file

@ -164,7 +164,7 @@ pub enum AccountCredential {
RegisterTotp(AccountNamedTagOpt),
/// Remove TOTP from the account. If no TOTP exists, no action is taken.
#[structopt(name = "remove_totp")]
RemoveTOTP(AccountNamedOpt),
RemoveTotp(AccountNamedOpt),
/// Show the status of the accounts credentials.
#[structopt(name = "status")]
Status(AccountNamedOpt),

View file

@ -21,6 +21,7 @@ use async_std::task;
use tokio::sync::mpsc;
static PORT_ALLOC: AtomicU16 = AtomicU16::new(28080);
const ADMIN_TEST_USER: &str = "admin";
const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test";
@ -55,6 +56,7 @@ fn run_test(fix_fn: fn(&mut KanidmClient) -> (), test_fn: fn(CacheLayer, KanidmA
};
let int_config = Box::new(IntegrationTestConfig {
admin_user: ADMIN_TEST_USER.to_string(),
admin_password: ADMIN_TEST_PASSWORD.to_string(),
});

View file

@ -68,7 +68,7 @@ impl AccessControlSearch {
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &CLASS_ACS) {
ladmin_error!(audit, "class access_control_search not present.");
return Err(OperationError::InvalidACPState(
return Err(OperationError::InvalidAcpState(
"Missing access_control_search".to_string(),
));
}
@ -77,7 +77,7 @@ impl AccessControlSearch {
.get_ava_as_str("acp_search_attr")
.ok_or_else(|| {
ladmin_error!(audit, "Missing acp_search_attr");
OperationError::InvalidACPState("Missing acp_search_attr".to_string())
OperationError::InvalidAcpState("Missing acp_search_attr".to_string())
})?
.map(AttrString::from)
.collect();
@ -123,7 +123,7 @@ impl AccessControlDelete {
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &CLASS_ACD) {
ladmin_error!(audit, "class access_control_delete not present.");
return Err(OperationError::InvalidACPState(
return Err(OperationError::InvalidAcpState(
"Missing access_control_delete".to_string(),
));
}
@ -166,7 +166,7 @@ impl AccessControlCreate {
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &CLASS_ACC) {
ladmin_error!(audit, "class access_control_create not present.");
return Err(OperationError::InvalidACPState(
return Err(OperationError::InvalidAcpState(
"Missing access_control_create".to_string(),
));
}
@ -226,7 +226,7 @@ impl AccessControlModify {
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &CLASS_ACM) {
ladmin_error!(audit, "class access_control_modify not present.");
return Err(OperationError::InvalidACPState(
return Err(OperationError::InvalidAcpState(
"Missing access_control_modify".to_string(),
));
}
@ -304,7 +304,7 @@ impl AccessControlProfile {
// Assert we have class access_control_profile
if !value.attribute_value_pres("class", &CLASS_ACP) {
ladmin_error!(audit, "class access_control_profile not present.");
return Err(OperationError::InvalidACPState(
return Err(OperationError::InvalidAcpState(
"Missing access_control_profile".to_string(),
));
}
@ -314,7 +314,7 @@ impl AccessControlProfile {
.get_ava_single_str("name")
.ok_or_else(|| {
ladmin_error!(audit, "Missing name");
OperationError::InvalidACPState("Missing name".to_string())
OperationError::InvalidAcpState("Missing name".to_string())
})?
.to_string();
// copy uuid
@ -326,7 +326,7 @@ impl AccessControlProfile {
.cloned()
.ok_or_else(|| {
ladmin_error!(audit, "Missing acp_receiver");
OperationError::InvalidACPState("Missing acp_receiver".to_string())
OperationError::InvalidAcpState("Missing acp_receiver".to_string())
})?;
// targetscope, and turn to real filter
let targetscope_f: ProtoFilter = value
@ -335,7 +335,7 @@ impl AccessControlProfile {
.cloned()
.ok_or_else(|| {
ladmin_error!(audit, "Missing acp_targetscope");
OperationError::InvalidACPState("Missing acp_targetscope".to_string())
OperationError::InvalidAcpState("Missing acp_targetscope".to_string())
})?;
let event = Event::from_internal();

View file

@ -9,8 +9,8 @@ use crate::event::{
ReviveRecycledEvent,
};
use crate::idm::event::{
GeneratePasswordEvent, GenerateTOTPEvent, PasswordChangeEvent, RegenerateRadiusSecretEvent,
RemoveTOTPEvent, RemoveWebauthnEvent, UnixPasswordChangeEvent, VerifyTOTPEvent,
GeneratePasswordEvent, GenerateTotpEvent, PasswordChangeEvent, RegenerateRadiusSecretEvent,
RemoveTotpEvent, RemoveWebauthnEvent, UnixPasswordChangeEvent, VerifyTotpEvent,
WebauthnDoRegisterEvent, WebauthnInitRegisterEvent,
};
use crate::modify::{Modify, ModifyInvalid, ModifyList};
@ -622,8 +622,8 @@ impl QueryServerWriteV1 {
.and_then(|r| idms_prox_write.commit(&mut audit).map(|_| r))
.map(SetCredentialResponse::Token)
}
SetCredentialRequest::TOTPGenerate(label) => {
let gte = GenerateTOTPEvent::from_parts(
SetCredentialRequest::TotpGenerate(label) => {
let gte = GenerateTotpEvent::from_parts(
&mut audit,
&idms_prox_write.qs_write,
msg.uat.as_ref(),
@ -642,8 +642,8 @@ impl QueryServerWriteV1 {
.generate_account_totp(&mut audit, &gte, ct)
.and_then(|r| idms_prox_write.commit(&mut audit).map(|_| r))
}
SetCredentialRequest::TOTPVerify(uuid, chal) => {
let vte = VerifyTOTPEvent::from_parts(
SetCredentialRequest::TotpVerify(uuid, chal) => {
let vte = VerifyTotpEvent::from_parts(
&mut audit,
&idms_prox_write.qs_write,
msg.uat.as_ref(),
@ -663,8 +663,8 @@ impl QueryServerWriteV1 {
.verify_account_totp(&mut audit, &vte, ct)
.and_then(|r| idms_prox_write.commit(&mut audit).map(|_| r))
}
SetCredentialRequest::TOTPRemove => {
let rte = RemoveTOTPEvent::from_parts(
SetCredentialRequest::TotpRemove => {
let rte = RemoveTotpEvent::from_parts(
&mut audit,
&idms_prox_write.qs_write,
msg.uat.as_ref(),

View file

@ -590,7 +590,7 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
entries.try_for_each(|e| {
ltrace!(au, "Inserting {:?} to cache", e.get_id());
if e.get_id() == 0 {
Err(OperationError::InvalidEntryID)
Err(OperationError::InvalidEntryId)
} else {
(*self.allids).insert_id(e.get_id());
self.entry_cache
@ -627,7 +627,7 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
idl.try_for_each(|i| {
ltrace!(au, "Removing {:?} from cache", i);
if i == 0 {
Err(OperationError::InvalidEntryID)
Err(OperationError::InvalidEntryId)
} else {
(*self.allids).remove_id(i);
self.entry_cache.remove_dirty(i);

View file

@ -36,13 +36,13 @@ impl TryFrom<IdSqliteEntry> for IdRawEntry {
fn try_from(value: IdSqliteEntry) -> Result<Self, Self::Error> {
if value.id <= 0 {
return Err(OperationError::InvalidEntryID);
return Err(OperationError::InvalidEntryId);
}
Ok(IdRawEntry {
id: value
.id
.try_into()
.map_err(|_| OperationError::InvalidEntryID)?,
.map_err(|_| OperationError::InvalidEntryId)?,
data: value.data,
})
}
@ -53,13 +53,13 @@ impl TryFrom<IdRawEntry> for IdSqliteEntry {
fn try_from(value: IdRawEntry) -> Result<Self, Self::Error> {
if value.id == 0 {
return Err(OperationError::InvalidEntryID);
return Err(OperationError::InvalidEntryId);
}
Ok(IdSqliteEntry {
id: value
.id
.try_into()
.map_err(|_| OperationError::InvalidEntryID)?,
.map_err(|_| OperationError::InvalidEntryId)?,
data: value.data,
})
}
@ -109,7 +109,7 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT id, data FROM id2entry")
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let id2entry_iter = stmt
.query_map([], |row| {
@ -120,13 +120,13 @@ pub trait IdlSqliteTransaction {
})
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
id2entry_iter
.map(|v| {
v.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
.and_then(|ise| {
// Convert the idsqlite to id raw
@ -141,7 +141,7 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT id, data FROM id2entry WHERE id = :idl")
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
// TODO #258: Can this actually just load in a single select?
@ -151,12 +151,12 @@ pub trait IdlSqliteTransaction {
/*
let decompressed: Result<Vec<i64>, _> = idli.into_iter()
.map(|u| i64::try_from(u).map_err(|_| OperationError::InvalidEntryID))
.map(|u| i64::try_from(u).map_err(|_| OperationError::InvalidEntryId))
.collect();
*/
for id in idli {
let iid = i64::try_from(id).map_err(|_| OperationError::InvalidEntryID)?;
let iid = i64::try_from(id).map_err(|_| OperationError::InvalidEntryId)?;
let id2entry_iter = stmt
.query_map(&[&iid], |row| {
Ok(IdSqliteEntry {
@ -166,14 +166,14 @@ pub trait IdlSqliteTransaction {
})
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let r: Result<Vec<_>, _> = id2entry_iter
.map(|v| {
v.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
.and_then(|ise| {
// Convert the idsqlite to id raw
@ -201,13 +201,13 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT COUNT(name) from sqlite_master where name = :tname")
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let i: Option<i64> = stmt
.query_row(&[(":tname", &tname)], |row| row.get(0))
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
if i.unwrap_or(0) == 0 {
@ -238,7 +238,7 @@ pub trait IdlSqliteTransaction {
);
let mut stmt = self.get_conn().prepare(query.as_str()).map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let idl_raw: Option<Vec<u8>> = stmt
.query_row(&[(":idx_key", &idx_key)], |row| row.get(0))
@ -246,7 +246,7 @@ pub trait IdlSqliteTransaction {
.optional()
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let idl = match idl_raw {
@ -274,7 +274,7 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT uuid FROM idx_name2uuid WHERE name = :name")
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let uuid_raw: Option<String> = stmt
.query_row(&[(":name", &name)], |row| row.get(0))
@ -282,7 +282,7 @@ pub trait IdlSqliteTransaction {
.optional()
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok());
@ -305,7 +305,7 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT spn FROM idx_uuid2spn WHERE uuid = :uuid")
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let spn_raw: Option<Vec<u8>> = stmt
.query_row(&[(":uuid", &uuids)], |row| row.get(0))
@ -313,7 +313,7 @@ pub trait IdlSqliteTransaction {
.optional()
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let spn: Option<Value> = match spn_raw {
@ -346,7 +346,7 @@ pub trait IdlSqliteTransaction {
.prepare("SELECT rdn FROM idx_uuid2rdn WHERE uuid = :uuid")
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let rdn: Option<String> = stmt
.query_row(&[(":uuid", &uuids)], |row| row.get(0))
@ -354,7 +354,7 @@ pub trait IdlSqliteTransaction {
.optional()
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
ltrace!(audit, "Got rdn for uuid {:?} -> {:?}", uuid, rdn);
@ -377,7 +377,7 @@ pub trait IdlSqliteTransaction {
})
// If no sid, we return none.
})
.map_err(|_| OperationError::SQLiteError)?;
.map_err(|_| OperationError::SqliteError)?;
Ok(match data {
Some(d) => Some(
@ -401,7 +401,7 @@ pub trait IdlSqliteTransaction {
})
// If no sid, we return none.
})
.map_err(|_| OperationError::SQLiteError)?;
.map_err(|_| OperationError::SqliteError)?;
Ok(match data {
Some(d) => Some(
@ -533,19 +533,19 @@ impl IdlSqliteWriteTransaction {
let mut stmt = self
.conn
.prepare("SELECT MAX(id) as id_max FROM id2entry")
.map_err(|_| OperationError::SQLiteError)?;
.map_err(|_| OperationError::SqliteError)?;
// This exists checks for if any rows WERE returned
// that way we know to shortcut or not.
let v = stmt.exists([]).map_err(|_| OperationError::SQLiteError)?;
let v = stmt.exists([]).map_err(|_| OperationError::SqliteError)?;
if v {
// We have some rows, let get max!
let i: Option<i64> = stmt
.query_row([], |row| row.get(0))
.map_err(|_| OperationError::SQLiteError)?;
.map_err(|_| OperationError::SqliteError)?;
i.unwrap_or(0)
.try_into()
.map_err(|_| OperationError::InvalidEntryID)
.map_err(|_| OperationError::InvalidEntryId)
} else {
// No rows are present, return a 0.
Ok(0)
@ -608,7 +608,7 @@ impl IdlSqliteWriteTransaction {
.prepare("INSERT OR REPLACE INTO id2entry (id, data) VALUES(:id, :data)")
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
entries.try_for_each(|e| {
@ -621,7 +621,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
})
})
@ -638,18 +638,18 @@ impl IdlSqliteWriteTransaction {
.prepare("DELETE FROM id2entry WHERE id = :id")
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
idl.try_for_each(|id| {
let iid: i64 = id
.try_into()
.map_err(|_| OperationError::InvalidEntryID)
.map_err(|_| OperationError::InvalidEntryId)
.and_then(|i| {
if i > 0 {
Ok(i)
} else {
Err(OperationError::InvalidEntryID)
Err(OperationError::InvalidEntryId)
}
})?;
@ -657,7 +657,7 @@ impl IdlSqliteWriteTransaction {
stmt.execute(&[&iid]).map(|_| ()).map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
})
})
@ -671,17 +671,17 @@ impl IdlSqliteWriteTransaction {
.prepare("DELETE FROM id2entry WHERE id = :id")
.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let iid: i64 = id
.try_into()
.map_err(|_| OperationError::InvalidEntryID)
.map_err(|_| OperationError::InvalidEntryId)
.and_then(|i| {
if i > 0 {
Ok(i)
} else {
Err(OperationError::InvalidEntryID)
Err(OperationError::InvalidEntryId)
}
})?;
@ -689,7 +689,7 @@ impl IdlSqliteWriteTransaction {
stmt.execute(&[&iid]).map(|_| ()).map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
// })
}
@ -718,7 +718,7 @@ impl IdlSqliteWriteTransaction {
.and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)]))
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
} else {
ltrace!(audit, "writing idl -> {}", idl);
@ -745,7 +745,7 @@ impl IdlSqliteWriteTransaction {
})
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
// Get rid of the sqlite rows usize
@ -762,7 +762,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -785,7 +785,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -800,7 +800,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -813,7 +813,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -840,7 +840,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
None => self
@ -850,7 +850,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
}),
}
}
@ -864,7 +864,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -883,7 +883,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
}),
None => self
.conn
@ -892,7 +892,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
}),
}
}
@ -919,7 +919,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -929,18 +929,18 @@ impl IdlSqliteWriteTransaction {
.prepare("SELECT name from sqlite_master where type='table' and name LIKE 'idx_%'")
.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let idx_table_iter = stmt.query_map([], |row| row.get(0)).map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let r: Result<_, _> = idx_table_iter
.map(|v| {
v.map_err(|e| {
ladmin_error!(audit, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
})
.collect();
@ -958,7 +958,7 @@ impl IdlSqliteWriteTransaction {
.and_then(|mut stmt| stmt.execute([]).map(|_| ()))
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
})
}
@ -970,7 +970,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -988,7 +988,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
eprintln!("CRITICAL: rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -1006,7 +1006,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
eprintln!("CRITICAL: rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -1024,7 +1024,7 @@ impl IdlSqliteWriteTransaction {
.map(|_| ())
.map_err(|e| {
eprintln!("CRITICAL: rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -1044,7 +1044,7 @@ impl IdlSqliteWriteTransaction {
})
// If no sid, we return none.
})
.map_err(|_| OperationError::SQLiteError)?;
.map_err(|_| OperationError::SqliteError)?;
Ok(match data {
Some(d) => Some(
@ -1089,7 +1089,7 @@ impl IdlSqliteWriteTransaction {
pub(crate) fn set_db_index_version(&self, v: i64) -> Result<(), OperationError> {
self.set_db_version_key(DBV_INDEXV, v).map_err(|e| {
eprintln!("CRITICAL: rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}
@ -1097,22 +1097,22 @@ impl IdlSqliteWriteTransaction {
ltrace!(au, "Building allids...");
let mut stmt = self.conn.prepare("SELECT id FROM id2entry").map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let res = stmt.query_map([], |row| row.get(0)).map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
res.map(|v| {
v.map_err(|e| {
ladmin_error!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
.and_then(|id: i64| {
// Convert the idsqlite to id raw
id.try_into().map_err(|e| {
ladmin_error!(au, "I64 Parse Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
})
})
@ -1143,7 +1143,7 @@ impl IdlSqliteWriteTransaction {
)
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
// If the table is empty, populate the versions as 0.
@ -1174,7 +1174,7 @@ impl IdlSqliteWriteTransaction {
})
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
dbv_id2entry = 1;
@ -1197,7 +1197,7 @@ impl IdlSqliteWriteTransaction {
)
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
dbv_id2entry = 2;
@ -1216,7 +1216,7 @@ impl IdlSqliteWriteTransaction {
)
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
dbv_id2entry = 3;
ladmin_info!(
@ -1242,7 +1242,7 @@ impl IdlSqliteWriteTransaction {
self.set_db_version_key(DBV_ID2ENTRY, dbv_id2entry)
.map_err(|e| {
ladmin_error!(audit, "sqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
// NOTE: Indexing is configured in a different step!
@ -1259,7 +1259,7 @@ impl IdlSqlite {
cfg: &BackendConfig,
vacuum: bool,
) -> Result<Self, OperationError> {
if cfg.path == "" {
if cfg.path.is_empty() {
debug_assert!(cfg.pool_size == 1);
}
// If provided, set the page size to match the tuning we want. By default we use 4096. The VACUUM
@ -1279,48 +1279,48 @@ impl IdlSqlite {
let vconn = Connection::open_with_flags(cfg.path.as_str(), flags).map_err(|e| {
ladmin_error!(audit, "rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn
.pragma_update(None, "journal_mode", &"DELETE")
.map_err(|e| {
ladmin_error!(audit, "rusqlite journal_mode update error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn.close().map_err(|e| {
ladmin_error!(audit, "rusqlite db close error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
let vconn = Connection::open_with_flags(cfg.path.as_str(), flags).map_err(|e| {
ladmin_error!(audit, "rusqlite error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn
.pragma_update(None, "page_size", &(cfg.fstype as u32))
.map_err(|e| {
ladmin_error!(audit, "rusqlite page_size update error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn.execute_batch("VACUUM").map_err(|e| {
ladmin_error!(audit, "rusqlite vacuum error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn
.pragma_update(None, "journal_mode", &"WAL")
.map_err(|e| {
ladmin_error!(audit, "rusqlite journal_mode update error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
vconn.close().map_err(|e| {
ladmin_error!(audit, "rusqlite db close error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
limmediate_warning!(audit, "NOTICE: db vacuum complete\n");
@ -1341,7 +1341,7 @@ impl IdlSqlite {
// Look at max_size and thread_pool here for perf later
let pool = builder2.build(manager).map_err(|e| {
ladmin_error!(audit, "r2d2 error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})?;
Ok(IdlSqlite { pool })
@ -1355,7 +1355,7 @@ impl IdlSqlite {
.query_row("select count(id) from id2entry", [], |row| row.get(0))
.map_err(|e| {
ltrace!(au, "SQLite Error {:?}", e);
OperationError::SQLiteError
OperationError::SqliteError
})
}

View file

@ -121,7 +121,7 @@ impl IdRawEntry {
) -> Result<Entry<EntrySealed, EntryCommitted>, OperationError> {
let db_e = serde_cbor::from_slice(self.data.as_slice())
.map_err(|_| OperationError::SerdeCborError)?;
// let id = u64::try_from(self.id).map_err(|_| OperationError::InvalidEntryID)?;
// let id = u64::try_from(self.id).map_err(|_| OperationError::InvalidEntryId)?;
Entry::from_dbentry(au, db_e, self.id).map_err(|_| OperationError::CorruptedEntry(self.id))
}
}
@ -836,10 +836,10 @@ impl<'a> BackendWriteTransaction<'a> {
.iter()
.map(|e| {
let id = i64::try_from(e.get_id())
.map_err(|_| OperationError::InvalidEntryID)
.map_err(|_| OperationError::InvalidEntryId)
.and_then(|id| {
if id == 0 {
Err(OperationError::InvalidEntryID)
Err(OperationError::InvalidEntryId)
} else {
Ok(id)
}
@ -1375,7 +1375,7 @@ impl Backend {
info!("CPU Flags -> {}", env!("KANIDM_CPU_FLAGS"));
// If in memory, reduce pool to 1
if &cfg.path == "" {
if cfg.path.is_empty() {
cfg.pool_size = 1;
}

View file

@ -3,6 +3,7 @@ use std::fmt;
#[derive(Serialize, Deserialize, Debug)]
pub struct IntegrationTestConfig {
pub admin_user: String,
pub admin_password: String,
}

View file

@ -18,7 +18,7 @@ pub mod webauthn;
use crate::credential::policy::CryptoPolicy;
use crate::credential::softlock::CredSoftLockPolicy;
use crate::credential::totp::TOTP;
use crate::credential::totp::Totp;
// NIST 800-63.b salt should be 112 bits -> 14 8u8.
// I choose tinfoil hat though ...
@ -207,10 +207,7 @@ impl Password {
}
pub fn requires_upgrade(&self) -> bool {
match &self.material {
KDF::PBKDF2(_, _, _) => false,
_ => true,
}
!matches!(&self.material, KDF::PBKDF2(_, _, _))
}
}
@ -243,7 +240,7 @@ pub enum CredentialType {
Password(Password),
GeneratedPassword(Password),
Webauthn(Map<String, WebauthnCredential>),
PasswordMFA(Password, Option<TOTP>, Map<String, WebauthnCredential>),
PasswordMfa(Password, Option<Totp>, Map<String, WebauthnCredential>),
// PasswordWebauthn(Password, Map<String, WebauthnCredential>),
// WebauthnVerified(Map<String, WebauthnCredential>),
// PasswordWebauthnVerified(Password, Map<String, WebauthnCredential>),
@ -262,10 +259,10 @@ impl Into<CredentialDetail> for &Credential {
labels.sort_unstable();
CredentialDetailType::Webauthn(labels)
}
CredentialType::PasswordMFA(_, totp, wan) => {
CredentialType::PasswordMfa(_, totp, wan) => {
let mut labels: Vec<_> = wan.keys().cloned().collect();
labels.sort_unstable();
CredentialDetailType::PasswordMFA(totp.is_some(), labels)
CredentialDetailType::PasswordMfa(totp.is_some(), labels)
}
},
}
@ -292,7 +289,7 @@ impl TryFrom<DbCredV1> for Credential {
};
let v_totp = match totp {
Some(dbt) => Some(TOTP::try_from(dbt)?),
Some(dbt) => Some(Totp::try_from(dbt)?),
None => None,
};
@ -320,7 +317,7 @@ impl TryFrom<DbCredV1> for Credential {
DbCredTypeV1::GPw => v_password.map(CredentialType::GeneratedPassword),
// In the future this could use .zip
DbCredTypeV1::PwMfa => match (v_password, v_webauthn) {
(Some(pw), Some(wn)) => Some(CredentialType::PasswordMFA(pw, v_totp, wn)),
(Some(pw), Some(wn)) => Some(CredentialType::PasswordMfa(pw, v_totp, wn)),
_ => None,
},
DbCredTypeV1::Wn => v_webauthn.map(CredentialType::Webauthn),
@ -371,9 +368,9 @@ impl Credential {
CredentialType::Password(pw) | CredentialType::GeneratedPassword(pw) => {
let mut wan = Map::new();
wan.insert(label, cred);
CredentialType::PasswordMFA(pw.clone(), None, wan)
CredentialType::PasswordMfa(pw.clone(), None, wan)
}
CredentialType::PasswordMFA(pw, totp, map) => {
CredentialType::PasswordMfa(pw, totp, map) => {
let mut nmap = map.clone();
if nmap.insert(label.clone(), cred).is_some() {
return Err(OperationError::InvalidAttribute(format!(
@ -381,7 +378,7 @@ impl Credential {
label
)));
}
CredentialType::PasswordMFA(pw.clone(), totp.clone(), nmap)
CredentialType::PasswordMfa(pw.clone(), totp.clone(), nmap)
}
CredentialType::Webauthn(map) => {
let mut nmap = map.clone();
@ -410,7 +407,7 @@ impl Credential {
"Webauthn is not present on this credential".to_string(),
));
}
CredentialType::PasswordMFA(pw, totp, map) => {
CredentialType::PasswordMfa(pw, totp, map) => {
let mut nmap = map.clone();
if nmap.remove(label).is_none() {
return Err(OperationError::InvalidAttribute(format!(
@ -420,12 +417,12 @@ impl Credential {
}
if nmap.is_empty() {
if totp.is_some() {
CredentialType::PasswordMFA(pw.clone(), totp.clone(), nmap)
CredentialType::PasswordMfa(pw.clone(), totp.clone(), nmap)
} else {
CredentialType::Password(pw.clone())
}
} else {
CredentialType::PasswordMFA(pw.clone(), totp.clone(), nmap)
CredentialType::PasswordMfa(pw.clone(), totp.clone(), nmap)
}
}
CredentialType::Webauthn(map) => {
@ -465,7 +462,7 @@ impl Credential {
// No action required
return Ok(None);
}
CredentialType::PasswordMFA(_, _, map) | CredentialType::Webauthn(map) => map
CredentialType::PasswordMfa(_, _, map) | CredentialType::Webauthn(map) => map
.iter()
.fold(None, |acc, (k, v)| {
if acc.is_none() && &v.cred_id == cid && v.counter < counter {
@ -498,8 +495,8 @@ impl Credential {
return Err(OperationError::InvalidState);
}
CredentialType::Webauthn(_) => CredentialType::Webauthn(map),
CredentialType::PasswordMFA(pw, totp, _) => {
CredentialType::PasswordMFA(pw.clone(), totp.clone(), map)
CredentialType::PasswordMfa(pw, totp, _) => {
CredentialType::PasswordMfa(pw.clone(), totp.clone(), map)
}
};
@ -515,7 +512,7 @@ impl Credential {
CredentialType::Password(_) | CredentialType::GeneratedPassword(_) => Err(
OperationError::InvalidAccountState("non-webauthn cred type?".to_string()),
),
CredentialType::PasswordMFA(_, _, map) | CredentialType::Webauthn(map) => Ok(map),
CredentialType::PasswordMfa(_, _, map) | CredentialType::Webauthn(map) => Ok(map),
}
}
@ -523,7 +520,7 @@ impl Credential {
match &self.type_ {
CredentialType::Password(pw)
| CredentialType::GeneratedPassword(pw)
| CredentialType::PasswordMFA(pw, _, _) => Ok(pw),
| CredentialType::PasswordMfa(pw, _, _) => Ok(pw),
CredentialType::Webauthn(_) => Err(OperationError::InvalidAccountState(
"non-password cred type?".to_string(),
)),
@ -555,7 +552,7 @@ impl Credential {
claims,
uuid,
},
CredentialType::PasswordMFA(pw, totp, map) => DbCredV1 {
CredentialType::PasswordMfa(pw, totp, map) => DbCredV1 {
type_: DbCredTypeV1::PwMfa,
password: Some(pw.to_dbpasswordv1()),
webauthn: Some(
@ -598,10 +595,10 @@ impl Credential {
let type_ = match &self.type_ {
CredentialType::Password(_) => CredentialType::Password(pw),
CredentialType::GeneratedPassword(_) => CredentialType::GeneratedPassword(pw),
CredentialType::PasswordMFA(_, totp, wan) => {
CredentialType::PasswordMFA(pw, totp.clone(), wan.clone())
CredentialType::PasswordMfa(_, totp, wan) => {
CredentialType::PasswordMfa(pw, totp.clone(), wan.clone())
}
CredentialType::Webauthn(wan) => CredentialType::PasswordMFA(pw, None, wan.clone()),
CredentialType::Webauthn(wan) => CredentialType::PasswordMfa(pw, None, wan.clone()),
};
Credential {
type_,
@ -611,13 +608,13 @@ impl Credential {
}
// We don't make totp accessible from outside the crate for now.
pub(crate) fn update_totp(&self, totp: TOTP) -> Self {
pub(crate) fn update_totp(&self, totp: Totp) -> Self {
let type_ = match &self.type_ {
CredentialType::Password(pw) | CredentialType::GeneratedPassword(pw) => {
CredentialType::PasswordMFA(pw.clone(), Some(totp), Map::new())
CredentialType::PasswordMfa(pw.clone(), Some(totp), Map::new())
}
CredentialType::PasswordMFA(pw, _, wan) => {
CredentialType::PasswordMFA(pw.clone(), Some(totp), wan.clone())
CredentialType::PasswordMfa(pw, _, wan) => {
CredentialType::PasswordMfa(pw.clone(), Some(totp), wan.clone())
}
CredentialType::Webauthn(wan) => {
debug_assert!(false);
@ -633,11 +630,11 @@ impl Credential {
pub(crate) fn remove_totp(&self) -> Self {
let type_ = match &self.type_ {
CredentialType::PasswordMFA(pw, Some(_), wan) => {
CredentialType::PasswordMfa(pw, Some(_), wan) => {
if wan.is_empty() {
CredentialType::Password(pw.clone())
} else {
CredentialType::PasswordMFA(pw.clone(), None, wan.clone())
CredentialType::PasswordMfa(pw.clone(), None, wan.clone())
}
}
_ => self.type_.clone(),
@ -662,9 +659,9 @@ impl Credential {
CredentialType::Password(_pw) | CredentialType::GeneratedPassword(_pw) => {
Some(CredSoftLockPolicy::Password)
}
CredentialType::PasswordMFA(_pw, totp, wan) => {
CredentialType::PasswordMfa(_pw, totp, wan) => {
if let Some(r_totp) = totp {
Some(CredSoftLockPolicy::TOTP(r_totp.step))
Some(CredSoftLockPolicy::Totp(r_totp.step))
} else if !wan.is_empty() {
Some(CredSoftLockPolicy::Webauthn)
} else {
@ -700,7 +697,7 @@ impl CredentialType {
fn is_valid(&self) -> bool {
match self {
CredentialType::Password(_) | CredentialType::GeneratedPassword(_) => true,
CredentialType::PasswordMFA(_, m_totp, webauthn) => {
CredentialType::PasswordMfa(_, m_totp, webauthn) => {
m_totp.is_some() || !webauthn.is_empty()
}
CredentialType::Webauthn(webauthn) => !webauthn.is_empty(),

View file

@ -63,7 +63,7 @@ const ONEDAY: u64 = 86400;
#[derive(Debug, Clone)]
pub enum CredSoftLockPolicy {
Password,
TOTP(u64),
Totp(u64),
Webauthn,
}
@ -89,7 +89,7 @@ impl CredSoftLockPolicy {
LockState::Locked(count, reset_at, reset_at)
}
}
CredSoftLockPolicy::TOTP(step) => {
CredSoftLockPolicy::Totp(step) => {
// reset at is based on the next step ending.
let next_window_end = ct.as_secs() + step;
let rem = next_window_end % step;
@ -170,10 +170,7 @@ impl CredSoftLock {
/// Is this credential valid to proceed at this point in time.
pub fn is_valid(&self) -> bool {
match self.state {
LockState::Locked(_count, _reset_at, _unlock_at) => false,
_ => true,
}
!matches!(self.state, LockState::Locked(_count, _reset_at, _unlock_at))
}
/// Document a failure of authentication at this time.
@ -320,7 +317,7 @@ mod tests {
#[test]
fn test_credential_softlock_policy_totp() {
let policy = CredSoftLockPolicy::TOTP(TOTP_DEFAULT_STEP);
let policy = CredSoftLockPolicy::Totp(TOTP_DEFAULT_STEP);
assert!(
policy.failure_next_state(1, Duration::from_secs(10))

View file

@ -7,51 +7,51 @@ use std::convert::TryFrom;
use std::convert::TryInto;
use std::time::{Duration, SystemTime};
use kanidm_proto::v1::TOTPAlgo as ProtoTOTPAlgo;
use kanidm_proto::v1::TOTPSecret as ProtoTOTP;
use kanidm_proto::v1::TotpAlgo as ProtoTotpAlgo;
use kanidm_proto::v1::TotpSecret as ProtoTotp;
// This is 64 bits of entropy, as the examples in https://tools.ietf.org/html/rfc6238 show.
const SECRET_SIZE_BYTES: usize = 8;
pub const TOTP_DEFAULT_STEP: u64 = 30;
#[derive(Debug, PartialEq)]
pub enum TOTPError {
pub enum TotpError {
OpenSSLError,
HmacError,
TimeError,
}
#[derive(Debug, Clone)]
pub enum TOTPAlgo {
pub enum TotpAlgo {
Sha1,
Sha256,
Sha512,
}
impl TOTPAlgo {
pub(crate) fn digest(&self, key: &[u8], counter: u64) -> Result<Vec<u8>, TOTPError> {
let key = PKey::hmac(key).map_err(|_e| TOTPError::OpenSSLError)?;
impl TotpAlgo {
pub(crate) fn digest(&self, key: &[u8], counter: u64) -> Result<Vec<u8>, TotpError> {
let key = PKey::hmac(key).map_err(|_e| TotpError::OpenSSLError)?;
let mut signer =
match self {
TOTPAlgo::Sha1 => Signer::new(MessageDigest::sha1(), &key)
.map_err(|_e| TOTPError::OpenSSLError)?,
TOTPAlgo::Sha256 => Signer::new(MessageDigest::sha256(), &key)
.map_err(|_e| TOTPError::OpenSSLError)?,
TOTPAlgo::Sha512 => Signer::new(MessageDigest::sha512(), &key)
.map_err(|_e| TOTPError::OpenSSLError)?,
TotpAlgo::Sha1 => Signer::new(MessageDigest::sha1(), &key)
.map_err(|_e| TotpError::OpenSSLError)?,
TotpAlgo::Sha256 => Signer::new(MessageDigest::sha256(), &key)
.map_err(|_e| TotpError::OpenSSLError)?,
TotpAlgo::Sha512 => Signer::new(MessageDigest::sha512(), &key)
.map_err(|_e| TotpError::OpenSSLError)?,
};
signer
.update(&counter.to_be_bytes())
.map_err(|_e| TOTPError::OpenSSLError)?;
let hmac = signer.sign_to_vec().map_err(|_e| TOTPError::OpenSSLError)?;
.map_err(|_e| TotpError::OpenSSLError)?;
let hmac = signer.sign_to_vec().map_err(|_e| TotpError::OpenSSLError)?;
let expect = match self {
TOTPAlgo::Sha1 => 20,
TOTPAlgo::Sha256 => 32,
TOTPAlgo::Sha512 => 64,
TotpAlgo::Sha1 => 20,
TotpAlgo::Sha256 => 32,
TotpAlgo::Sha512 => 64,
};
if hmac.len() != expect {
return Err(TOTPError::HmacError);
return Err(TotpError::HmacError);
}
Ok(hmac)
}
@ -59,23 +59,23 @@ impl TOTPAlgo {
/// https://tools.ietf.org/html/rfc6238 which relies on https://tools.ietf.org/html/rfc4226
#[derive(Debug, Clone)]
pub struct TOTP {
pub struct Totp {
label: String,
secret: Vec<u8>,
pub(crate) step: u64,
algo: TOTPAlgo,
algo: TotpAlgo,
}
impl TryFrom<DbTotpV1> for TOTP {
impl TryFrom<DbTotpV1> for Totp {
type Error = ();
fn try_from(value: DbTotpV1) -> Result<Self, Self::Error> {
let algo = match value.a {
DbTotpAlgoV1::S1 => TOTPAlgo::Sha1,
DbTotpAlgoV1::S256 => TOTPAlgo::Sha256,
DbTotpAlgoV1::S512 => TOTPAlgo::Sha512,
DbTotpAlgoV1::S1 => TotpAlgo::Sha1,
DbTotpAlgoV1::S256 => TotpAlgo::Sha256,
DbTotpAlgoV1::S512 => TotpAlgo::Sha512,
};
Ok(TOTP {
Ok(Totp {
label: value.l,
secret: value.k,
step: value.s,
@ -84,24 +84,24 @@ impl TryFrom<DbTotpV1> for TOTP {
}
}
impl From<ProtoTOTP> for TOTP {
fn from(value: ProtoTOTP) -> Self {
TOTP {
impl From<ProtoTotp> for Totp {
fn from(value: ProtoTotp) -> Self {
Totp {
label: "test_token".to_string(),
secret: value.secret,
algo: match value.algo {
ProtoTOTPAlgo::Sha1 => TOTPAlgo::Sha1,
ProtoTOTPAlgo::Sha256 => TOTPAlgo::Sha256,
ProtoTOTPAlgo::Sha512 => TOTPAlgo::Sha512,
ProtoTotpAlgo::Sha1 => TotpAlgo::Sha1,
ProtoTotpAlgo::Sha256 => TotpAlgo::Sha256,
ProtoTotpAlgo::Sha512 => TotpAlgo::Sha512,
},
step: value.step,
}
}
}
impl TOTP {
pub fn new(label: String, secret: Vec<u8>, step: u64, algo: TOTPAlgo) -> Self {
TOTP {
impl Totp {
pub fn new(label: String, secret: Vec<u8>, step: u64, algo: TotpAlgo) -> Self {
Totp {
label,
secret,
step,
@ -113,8 +113,8 @@ impl TOTP {
pub fn generate_secure(label: String, step: u64) -> Self {
let mut rng = rand::thread_rng();
let secret: Vec<u8> = (0..SECRET_SIZE_BYTES).map(|_| rng.gen()).collect();
let algo = TOTPAlgo::Sha512;
TOTP {
let algo = TotpAlgo::Sha512;
Totp {
label,
secret,
step,
@ -128,40 +128,40 @@ impl TOTP {
k: self.secret.clone(),
s: self.step,
a: match self.algo {
TOTPAlgo::Sha1 => DbTotpAlgoV1::S1,
TOTPAlgo::Sha256 => DbTotpAlgoV1::S256,
TOTPAlgo::Sha512 => DbTotpAlgoV1::S512,
TotpAlgo::Sha1 => DbTotpAlgoV1::S1,
TotpAlgo::Sha256 => DbTotpAlgoV1::S256,
TotpAlgo::Sha512 => DbTotpAlgoV1::S512,
},
}
}
fn digest(&self, counter: u64) -> Result<u32, TOTPError> {
fn digest(&self, counter: u64) -> Result<u32, TotpError> {
let hmac = self.algo.digest(&self.secret, counter)?;
// Now take the hmac and encode it as hotp expects.
// https://tools.ietf.org/html/rfc4226#page-7
let offset = hmac
.last()
.map(|v| (v & 0xf) as usize)
.ok_or(TOTPError::HmacError)?;
.ok_or(TotpError::HmacError)?;
let bytes: [u8; 4] = hmac[offset..offset + 4]
.try_into()
.map_err(|_| TOTPError::HmacError)?;
.map_err(|_| TotpError::HmacError)?;
let otp = u32::from_be_bytes(bytes);
Ok((otp & 0x7fff_ffff) % 1_000_000)
}
pub fn do_totp_duration_from_epoch(&self, time: &Duration) -> Result<u32, TOTPError> {
pub fn do_totp_duration_from_epoch(&self, time: &Duration) -> Result<u32, TotpError> {
let secs = time.as_secs();
// do the window calculation
let counter = secs / self.step;
self.digest(counter)
}
pub fn do_totp(&self, time: &SystemTime) -> Result<u32, TOTPError> {
pub fn do_totp(&self, time: &SystemTime) -> Result<u32, TotpError> {
let dur = time
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|_| TOTPError::TimeError)?;
.map_err(|_| TotpError::TimeError)?;
self.do_totp_duration_from_epoch(&dur)
}
@ -173,8 +173,8 @@ impl TOTP {
}
}
pub fn to_proto(&self, accountname: &str, issuer: &str) -> ProtoTOTP {
ProtoTOTP {
pub fn to_proto(&self, accountname: &str, issuer: &str) -> ProtoTotp {
ProtoTotp {
accountname: accountname
.replace(":", "")
.replace("%3A", "")
@ -186,9 +186,9 @@ impl TOTP {
secret: self.secret.clone(),
step: self.step,
algo: match self.algo {
TOTPAlgo::Sha1 => ProtoTOTPAlgo::Sha1,
TOTPAlgo::Sha256 => ProtoTOTPAlgo::Sha256,
TOTPAlgo::Sha512 => ProtoTOTPAlgo::Sha512,
TotpAlgo::Sha1 => ProtoTotpAlgo::Sha1,
TotpAlgo::Sha256 => ProtoTotpAlgo::Sha256,
TotpAlgo::Sha512 => ProtoTotpAlgo::Sha512,
},
}
}
@ -196,21 +196,21 @@ impl TOTP {
#[cfg(test)]
mod tests {
use crate::credential::totp::{TOTPAlgo, TOTPError, TOTP, TOTP_DEFAULT_STEP};
use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP};
use std::time::Duration;
#[test]
fn hotp_basic() {
let otp_sha1 = TOTP::new("".to_string(), vec![0], 30, TOTPAlgo::Sha1);
let otp_sha1 = Totp::new("".to_string(), vec![0], 30, TotpAlgo::Sha1);
assert!(otp_sha1.digest(0) == Ok(328482));
let otp_sha256 = TOTP::new("".to_string(), vec![0], 30, TOTPAlgo::Sha256);
let otp_sha256 = Totp::new("".to_string(), vec![0], 30, TotpAlgo::Sha256);
assert!(otp_sha256.digest(0) == Ok(356306));
let otp_sha512 = TOTP::new("".to_string(), vec![0], 30, TOTPAlgo::Sha512);
let otp_sha512 = Totp::new("".to_string(), vec![0], 30, TotpAlgo::Sha512);
assert!(otp_sha512.digest(0) == Ok(674061));
}
fn do_test(key: Vec<u8>, algo: TOTPAlgo, secs: u64, step: u64, expect: Result<u32, TOTPError>) {
let otp = TOTP::new("".to_string(), key.clone(), step, algo.clone());
fn do_test(key: Vec<u8>, algo: TotpAlgo, secs: u64, step: u64, expect: Result<u32, TotpError>) {
let otp = Totp::new("".to_string(), key.clone(), step, algo.clone());
let d = Duration::from_secs(secs);
let r = otp.do_totp_duration_from_epoch(&d);
debug!(
@ -224,14 +224,14 @@ mod tests {
fn totp_sha1_vectors() {
do_test(
vec![0x00, 0x00, 0x00, 0x00],
TOTPAlgo::Sha1,
TotpAlgo::Sha1,
1585368920,
TOTP_DEFAULT_STEP,
Ok(728926),
);
do_test(
vec![0x00, 0xaa, 0xbb, 0xcc],
TOTPAlgo::Sha1,
TotpAlgo::Sha1,
1585369498,
TOTP_DEFAULT_STEP,
Ok(985074),
@ -242,14 +242,14 @@ mod tests {
fn totp_sha256_vectors() {
do_test(
vec![0x00, 0x00, 0x00, 0x00],
TOTPAlgo::Sha256,
TotpAlgo::Sha256,
1585369682,
TOTP_DEFAULT_STEP,
Ok(795483),
);
do_test(
vec![0x00, 0xaa, 0xbb, 0xcc],
TOTPAlgo::Sha256,
TotpAlgo::Sha256,
1585369689,
TOTP_DEFAULT_STEP,
Ok(728402),
@ -260,14 +260,14 @@ mod tests {
fn totp_sha512_vectors() {
do_test(
vec![0x00, 0x00, 0x00, 0x00],
TOTPAlgo::Sha512,
TotpAlgo::Sha512,
1585369775,
TOTP_DEFAULT_STEP,
Ok(587735),
);
do_test(
vec![0x00, 0xaa, 0xbb, 0xcc],
TOTPAlgo::Sha512,
TotpAlgo::Sha512,
1585369780,
TOTP_DEFAULT_STEP,
Ok(952181),

View file

@ -246,10 +246,7 @@ impl Event {
}
pub fn is_internal(&self) -> bool {
match self.origin {
EventOrigin::Internal => true,
_ => false,
}
matches!(self.origin, EventOrigin::Internal)
}
pub fn get_uuid(&self) -> Option<Uuid> {

View file

@ -75,7 +75,7 @@ pub fn f_andnot(fc: FC) -> FC {
#[allow(dead_code)]
pub fn f_self<'a>() -> FC<'a> {
FC::SelfUUID
FC::SelfUuid
}
#[allow(dead_code)]
@ -116,7 +116,7 @@ pub enum FC<'a> {
And(Vec<FC<'a>>),
Inclusion(Vec<FC<'a>>),
AndNot(Box<FC<'a>>),
SelfUUID,
SelfUuid,
// Not(Box<FC>),
}
@ -132,7 +132,7 @@ enum FilterComp {
And(Vec<FilterComp>),
Inclusion(Vec<FilterComp>),
AndNot(Box<FilterComp>),
SelfUUID,
SelfUuid,
// Does this mean we can add a true not to the type now?
// Not(Box<FilterComp>),
}
@ -285,7 +285,7 @@ impl Filter<FilterValid> {
>,
>,
) -> Result<Filter<FilterValidResolved>, OperationError> {
// Given a filter, resolve Not and SelfUUID to real terms.
// Given a filter, resolve Not and SelfUuid to real terms.
//
// The benefit of moving optimisation to this step is from various inputs, we can
// get to a resolved + optimised filter, and then we can cache those outputs in many
@ -323,7 +323,7 @@ impl Filter<FilterValid> {
None => f.fast_optimise(),
}
})
.ok_or(OperationError::FilterUUIDResolution)?,
.ok_or(OperationError::FilterUuidResolution)?,
},
};
@ -546,7 +546,7 @@ impl FilterComp {
FC::And(v) => FilterComp::And(v.into_iter().map(FilterComp::new).collect()),
FC::Inclusion(v) => FilterComp::Inclusion(v.into_iter().map(FilterComp::new).collect()),
FC::AndNot(b) => FilterComp::AndNot(Box::new(FilterComp::new(*b))),
FC::SelfUUID => FilterComp::SelfUUID,
FC::SelfUuid => FilterComp::SelfUuid,
}
}
@ -594,7 +594,7 @@ impl FilterComp {
FilterComp::And(vs) => vs.iter().for_each(|f| f.get_attr_set(r_set)),
FilterComp::Inclusion(vs) => vs.iter().for_each(|f| f.get_attr_set(r_set)),
FilterComp::AndNot(f) => f.get_attr_set(r_set),
FilterComp::SelfUUID => {
FilterComp::SelfUuid => {
r_set.insert("uuid");
}
}
@ -714,9 +714,9 @@ impl FilterComp {
.validate(schema)
.map(|r_filter| FilterComp::AndNot(Box::new(r_filter)))
}
FilterComp::SelfUUID => {
FilterComp::SelfUuid => {
// Pretty hard to mess this one up ;)
Ok(FilterComp::SelfUUID)
Ok(FilterComp::SelfUuid)
}
}
}
@ -770,7 +770,7 @@ impl FilterComp {
.ok_or(OperationError::ResourceLimit)?;
FilterComp::AndNot(Box::new(Self::from_ro(audit, l, qs, ndepth, elems)?))
}
ProtoFilter::SelfUUID => FilterComp::SelfUUID,
ProtoFilter::SelfUuid => FilterComp::SelfUuid,
})
}
@ -824,7 +824,7 @@ impl FilterComp {
FilterComp::AndNot(Box::new(Self::from_rw(audit, l, qs, ndepth, elems)?))
}
ProtoFilter::SelfUUID => FilterComp::SelfUUID,
ProtoFilter::SelfUuid => FilterComp::SelfUuid,
})
}
@ -1036,7 +1036,7 @@ impl FilterResolved {
idxmeta,
)))
}
FilterComp::SelfUUID => panic!("Not possible to resolve SelfUUID in from_invalid!"),
FilterComp::SelfUuid => panic!("Not possible to resolve SelfUuid in from_invalid!"),
}
}
@ -1092,7 +1092,7 @@ impl FilterResolved {
FilterResolved::resolve_idx((*f).clone(), ev, idxmeta)
.map(|fi| FilterResolved::AndNot(Box::new(fi)))
}
FilterComp::SelfUUID => ev.get_uuid().map(|uuid| {
FilterComp::SelfUuid => ev.get_uuid().map(|uuid| {
let uuid_s = AttrString::from("uuid");
let idxkref = IdxKeyRef::new(&uuid_s, &IndexType::EQUALITY);
let idx = idxmeta.contains(&idxkref as &dyn IdxKeyToRef);
@ -1138,7 +1138,7 @@ impl FilterResolved {
.map(|fi| FilterResolved::AndNot(Box::new(fi)))
}
FilterComp::SelfUUID => ev.get_uuid().map(|uuid| {
FilterComp::SelfUuid => ev.get_uuid().map(|uuid| {
FilterResolved::Eq(
AttrString::from("uuid"),
PartialValue::new_uuid(uuid),
@ -1173,10 +1173,7 @@ impl FilterResolved {
let (f_list_inc, mut f_list_new): (Vec<_>, Vec<_>) = f_list
.iter()
.map(|f_ref| f_ref.optimise())
.partition(|f| match f {
FilterResolved::Inclusion(_) => true,
_ => false,
});
.partition(|f| matches!(f, FilterResolved::Inclusion(_)));
f_list_inc.into_iter().for_each(|fc| {
if let FilterResolved::Inclusion(mut l) = fc {
@ -1193,10 +1190,7 @@ impl FilterResolved {
let (f_list_and, mut f_list_new): (Vec<_>, Vec<_>) = f_list
.iter()
.map(|f_ref| f_ref.optimise())
.partition(|f| match f {
FilterResolved::And(_) => true,
_ => false,
});
.partition(|f| matches!(f, FilterResolved::And(_)));
// now, iterate over this list - for each "and" term, fold
// it's elements to this level.
@ -1234,10 +1228,7 @@ impl FilterResolved {
// Optimise all inner items.
.map(|f_ref| f_ref.optimise())
// Split out inner-or terms to fold into this term.
.partition(|f| match f {
FilterResolved::Or(_) => true,
_ => false,
});
.partition(|f| matches!(f, FilterResolved::Or(_)));
// Append the inner terms.
f_list_or.into_iter().for_each(|fc| {
@ -1264,10 +1255,7 @@ impl FilterResolved {
}
pub fn is_andnot(&self) -> bool {
match self {
FilterResolved::AndNot(_) => true,
_ => false,
}
matches!(self, FilterResolved::AndNot(_))
}
}

View file

@ -7,7 +7,7 @@ use kanidm_proto::v1::UserAuthToken;
use crate::constants::UUID_ANONYMOUS;
use crate::credential::policy::CryptoPolicy;
use crate::credential::totp::TOTP;
use crate::credential::totp::Totp;
use crate::credential::{softlock::CredSoftLockPolicy, Credential};
use crate::idm::claim::Claim;
use crate::idm::group::Group;
@ -260,7 +260,7 @@ impl Account {
pub(crate) fn gen_totp_mod(
&self,
token: TOTP,
token: Totp,
) -> Result<ModifyList<ModifyInvalid>, OperationError> {
match &self.primary {
// Change the cred

View file

@ -5,7 +5,7 @@ use crate::prelude::*;
use kanidm_proto::v1::OperationError;
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech};
use crate::credential::{totp::TOTP, Credential, CredentialType, Password};
use crate::credential::{totp::Totp, Credential, CredentialType, Password};
use crate::idm::delayed::{DelayedAction, PasswordUpgrade, WebauthnCounterIncrement};
// use crossbeam::channel::Sender;
@ -50,7 +50,7 @@ enum CredVerifyState {
struct CredMfa {
pw: Password,
pw_state: CredVerifyState,
totp: Option<TOTP>,
totp: Option<Totp>,
wan: Option<(RequestChallengeResponse, AuthenticationState)>,
mfa_state: CredVerifyState,
}
@ -67,7 +67,7 @@ enum CredHandler {
Anonymous,
// AppPassword (?)
Password(Password),
PasswordMFA(Box<CredMfa>),
PasswordMfa(Box<CredMfa>),
Webauthn(CredWebauthn),
// Webauthn + Password
}
@ -83,7 +83,7 @@ impl CredHandler {
CredentialType::Password(pw) | CredentialType::GeneratedPassword(pw) => {
Ok(CredHandler::Password(pw.clone()))
}
CredentialType::PasswordMFA(pw, maybe_totp, maybe_wan) => {
CredentialType::PasswordMfa(pw, maybe_totp, maybe_wan) => {
let wan = if !maybe_wan.is_empty() {
webauthn
.generate_challenge_authenticate(maybe_wan.values().cloned().collect())
@ -111,12 +111,12 @@ impl CredHandler {
if cmfa.totp.is_none() && cmfa.wan.is_none() {
lsecurity_critical!(
au,
"Unable to create CredHandler::PasswordMFA - totp and webauthn are both not present. Credentials MAY be corrupt!"
"Unable to create CredHandler::PasswordMfa - totp and webauthn are both not present. Credentials MAY be corrupt!"
);
return Err(());
}
Ok(CredHandler::PasswordMFA(cmfa))
Ok(CredHandler::PasswordMfa(cmfa))
}
CredentialType::Webauthn(wan) => webauthn
.generate_challenge_authenticate(wan.values().cloned().collect())
@ -258,19 +258,19 @@ impl CredHandler {
CredState::Denied(BAD_WEBAUTHN_MSG)
})
}
(AuthCredential::TOTP(totp_chal), Some(totp), _) => {
(AuthCredential::Totp(totp_chal), Some(totp), _) => {
if totp.verify(*totp_chal, ts) {
pw_mfa.mfa_state = CredVerifyState::Success;
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Continue - TOTP OK, password -"
"Handler::PasswordMfa -> Result::Continue - TOTP OK, password -"
);
CredState::Continue(vec![AuthAllowed::Password])
} else {
pw_mfa.mfa_state = CredVerifyState::Fail;
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - TOTP Fail, password -"
"Handler::PasswordMfa -> Result::Denied - TOTP Fail, password -"
);
CredState::Denied(BAD_TOTP_MSG)
}
@ -278,7 +278,7 @@ impl CredHandler {
_ => {
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - invalid cred type for handler"
"Handler::PasswordMfa -> Result::Denied - invalid cred type for handler"
);
CredState::Denied(BAD_AUTH_TYPE_MSG)
}
@ -294,7 +294,7 @@ impl CredHandler {
pw_mfa.pw_state = CredVerifyState::Fail;
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - Password found in badlist during login"
"Handler::PasswordMfa -> Result::Denied - Password found in badlist during login"
);
CredState::Denied(PW_BADLIST_MSG)
}
@ -302,7 +302,7 @@ impl CredHandler {
pw_mfa.pw_state = CredVerifyState::Success;
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Success - TOTP OK, password OK"
"Handler::PasswordMfa -> Result::Success - TOTP OK, password OK"
);
Self::maybe_pw_upgrade(
au,
@ -318,7 +318,7 @@ impl CredHandler {
pw_mfa.pw_state = CredVerifyState::Fail;
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - TOTP OK, password Fail"
"Handler::PasswordMfa -> Result::Denied - TOTP OK, password Fail"
);
CredState::Denied(BAD_PASSWORD_MSG)
}
@ -326,7 +326,7 @@ impl CredHandler {
_ => {
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - invalid cred type for handler"
"Handler::PasswordMfa -> Result::Denied - invalid cred type for handler"
);
CredState::Denied(BAD_AUTH_TYPE_MSG)
}
@ -335,12 +335,12 @@ impl CredHandler {
_ => {
lsecurity!(
au,
"Handler::PasswordMFA -> Result::Denied - invalid credential mfa and pw state"
"Handler::PasswordMfa -> Result::Denied - invalid credential mfa and pw state"
);
CredState::Denied(BAD_AUTH_TYPE_MSG)
}
}
} // end CredHandler::PasswordMFA
} // end CredHandler::PasswordMfa
pub fn validate_webauthn(
au: &mut AuditScope,
@ -395,6 +395,7 @@ impl CredHandler {
}
}
#[allow(clippy::too_many_arguments)]
pub fn validate(
&mut self,
au: &mut AuditScope,
@ -410,7 +411,7 @@ impl CredHandler {
CredHandler::Password(ref mut pw) => {
Self::validate_password(au, cred, pw, who, async_tx, pw_badlist_set)
}
CredHandler::PasswordMFA(ref mut pw_mfa) => Self::validate_password_mfa(
CredHandler::PasswordMfa(ref mut pw_mfa) => Self::validate_password_mfa(
au,
cred,
ts,
@ -430,10 +431,10 @@ impl CredHandler {
match &self {
CredHandler::Anonymous => vec![AuthAllowed::Anonymous],
CredHandler::Password(_) => vec![AuthAllowed::Password],
CredHandler::PasswordMFA(ref pw_mfa) => pw_mfa
CredHandler::PasswordMfa(ref pw_mfa) => pw_mfa
.totp
.iter()
.map(|_| AuthAllowed::TOTP)
.map(|_| AuthAllowed::Totp)
.chain(
pw_mfa
.wan
@ -449,7 +450,7 @@ impl CredHandler {
match (self, mech) {
(CredHandler::Anonymous, AuthMech::Anonymous)
| (CredHandler::Password(_), AuthMech::Password)
| (CredHandler::PasswordMFA(_), AuthMech::PasswordMFA)
| (CredHandler::PasswordMfa(_), AuthMech::PasswordMfa)
| (CredHandler::Webauthn(_), AuthMech::Webauthn) => true,
(_, _) => false,
}
@ -459,7 +460,7 @@ impl CredHandler {
match self {
CredHandler::Anonymous => AuthMech::Anonymous,
CredHandler::Password(_) => AuthMech::Password,
CredHandler::PasswordMFA(_) => AuthMech::PasswordMFA,
CredHandler::PasswordMfa(_) => AuthMech::PasswordMfa,
CredHandler::Webauthn(_) => AuthMech::Webauthn,
}
}
@ -727,7 +728,7 @@ impl AuthSession {
#[cfg(test)]
mod tests {
use crate::credential::policy::CryptoPolicy;
use crate::credential::totp::{TOTP, TOTP_DEFAULT_STEP};
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
use crate::credential::webauthn::WebauthnDomainConfig;
use crate::credential::Credential;
use crate::idm::authsession::{
@ -994,7 +995,7 @@ mod tests {
if let AuthState::Choose(auth_mechs) = state {
assert!(
true == auth_mechs.iter().fold(false, |acc, x| match x {
AuthMech::PasswordMFA => true,
AuthMech::PasswordMfa => true,
_ => acc,
})
);
@ -1003,7 +1004,7 @@ mod tests {
}
let state = session
.start_session($audit, &AuthMech::PasswordMFA)
.start_session($audit, &AuthMech::PasswordMfa)
.expect("Failed to select anonymous mech.");
let mut rchal = None;
@ -1016,7 +1017,7 @@ mod tests {
rchal = Some(chal.clone());
true
}
AuthAllowed::TOTP => true,
AuthAllowed::Totp => true,
_ => acc,
})
);
@ -1043,7 +1044,7 @@ mod tests {
let ts = Duration::from_secs(12345);
// manually load in a cred
let totp = TOTP::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp = Totp::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp_good = totp
.do_totp_duration_from_epoch(&ts)
@ -1106,7 +1107,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_bad),
&AuthCredential::Totp(totp_bad),
&ts,
&async_tx,
&webauthn,
@ -1123,7 +1124,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_good),
&AuthCredential::Totp(totp_good),
&ts,
&async_tx,
&webauthn,
@ -1150,7 +1151,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_good),
&AuthCredential::Totp(totp_good),
&ts,
&async_tx,
&webauthn,
@ -1190,7 +1191,7 @@ mod tests {
let ts = Duration::from_secs(12345);
// manually load in a cred
let totp = TOTP::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp = Totp::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp_good = totp
.do_totp_duration_from_epoch(&ts)
@ -1218,7 +1219,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_good),
&AuthCredential::Totp(totp_good),
&ts,
&async_tx,
&webauthn,
@ -1498,7 +1499,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(0),
&AuthCredential::Totp(0),
&ts,
&async_tx,
&webauthn,
@ -1627,7 +1628,7 @@ mod tests {
let (webauthn, mut wa, wan_cred) = setup_webauthn(account.name.as_str());
let totp = TOTP::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp = Totp::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp_good = totp
.do_totp_duration_from_epoch(&ts)
.expect("failed to perform totp.");
@ -1671,7 +1672,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_bad),
&AuthCredential::Totp(totp_bad),
&ts,
&async_tx,
&webauthn,
@ -1748,7 +1749,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_good),
&AuthCredential::Totp(totp_good),
&ts,
&async_tx,
&webauthn,
@ -1774,7 +1775,7 @@ mod tests {
match session.validate_creds(
&mut audit,
&AuthCredential::TOTP(totp_good),
&AuthCredential::Totp(totp_good),
&ts,
&async_tx,
&webauthn,

View file

@ -264,13 +264,13 @@ impl UnixUserAuthEvent {
}
#[derive(Debug)]
pub struct GenerateTOTPEvent {
pub struct GenerateTotpEvent {
pub event: Event,
pub target: Uuid,
pub label: String,
}
impl GenerateTOTPEvent {
impl GenerateTotpEvent {
pub fn from_parts(
audit: &mut AuditScope,
qs: &QueryServerWriteTransaction,
@ -280,7 +280,7 @@ impl GenerateTOTPEvent {
) -> Result<Self, OperationError> {
let e = Event::from_rw_uat(audit, qs, uat)?;
Ok(GenerateTOTPEvent {
Ok(GenerateTotpEvent {
event: e,
target,
label,
@ -291,7 +291,7 @@ impl GenerateTOTPEvent {
pub fn new_internal(target: Uuid) -> Self {
let e = Event::from_internal();
GenerateTOTPEvent {
GenerateTotpEvent {
event: e,
target,
label: "internal_token".to_string(),
@ -300,14 +300,14 @@ impl GenerateTOTPEvent {
}
#[derive(Debug)]
pub struct VerifyTOTPEvent {
pub struct VerifyTotpEvent {
pub event: Event,
pub target: Uuid,
pub session: Uuid,
pub chal: u32,
}
impl VerifyTOTPEvent {
impl VerifyTotpEvent {
pub fn from_parts(
audit: &mut AuditScope,
qs: &QueryServerWriteTransaction,
@ -318,7 +318,7 @@ impl VerifyTOTPEvent {
) -> Result<Self, OperationError> {
let e = Event::from_rw_uat(audit, qs, uat)?;
Ok(VerifyTOTPEvent {
Ok(VerifyTotpEvent {
event: e,
target,
session,
@ -330,7 +330,7 @@ impl VerifyTOTPEvent {
pub fn new_internal(target: Uuid, session: Uuid, chal: u32) -> Self {
let e = Event::from_internal();
VerifyTOTPEvent {
VerifyTotpEvent {
event: e,
target,
session,
@ -340,12 +340,12 @@ impl VerifyTOTPEvent {
}
#[derive(Debug)]
pub struct RemoveTOTPEvent {
pub struct RemoveTotpEvent {
pub event: Event,
pub target: Uuid,
}
impl RemoveTOTPEvent {
impl RemoveTotpEvent {
pub fn from_parts(
audit: &mut AuditScope,
qs: &QueryServerWriteTransaction,
@ -354,14 +354,14 @@ impl RemoveTOTPEvent {
) -> Result<Self, OperationError> {
let e = Event::from_rw_uat(audit, qs, uat)?;
Ok(RemoveTOTPEvent { event: e, target })
Ok(RemoveTotpEvent { event: e, target })
}
#[cfg(test)]
pub fn new_internal(target: Uuid) -> Self {
let e = Event::from_internal();
RemoveTOTPEvent { event: e, target }
RemoveTotpEvent { event: e, target }
}
}

View file

@ -1,9 +1,9 @@
use crate::audit::AuditScope;
use crate::credential::totp::{TOTP, TOTP_DEFAULT_STEP};
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
use crate::credential::webauthn::WebauthnDomainConfig;
use crate::event::EventOriginId;
use crate::idm::account::Account;
use kanidm_proto::v1::TOTPSecret;
use kanidm_proto::v1::TotpSecret;
use kanidm_proto::v1::{OperationError, SetCredentialResponse};
use std::mem;
use std::time::Duration;
@ -15,13 +15,13 @@ use webauthn_rs::RegistrationState as WebauthnRegistrationState;
use webauthn_rs::{proto::UserVerificationPolicy, Webauthn};
pub(crate) enum MfaRegCred {
TOTP(TOTP),
Totp(Totp),
Webauthn(String, WebauthnCredential),
}
pub(crate) enum MfaRegNext {
Success,
TOTPCheck(TOTPSecret),
TotpCheck(TotpSecret),
WebauthnChallenge(CreationChallengeResponse),
}
@ -30,7 +30,7 @@ impl MfaRegNext {
pub fn to_proto(self, u: Uuid) -> SetCredentialResponse {
match self {
MfaRegNext::Success => SetCredentialResponse::Success,
MfaRegNext::TOTPCheck(secret) => SetCredentialResponse::TOTPCheck(u, secret),
MfaRegNext::TotpCheck(secret) => SetCredentialResponse::TotpCheck(u, secret),
MfaRegNext::WebauthnChallenge(ccr) => {
SetCredentialResponse::WebauthnCreateChallenge(u, ccr)
}
@ -40,8 +40,8 @@ impl MfaRegNext {
#[derive(Clone)]
enum MfaRegState {
TOTPInit(TOTP),
TOTPDone,
TotpInit(Totp),
TotpDone,
WebauthnInit(String, WebauthnRegistrationState),
WebauthnDone,
}
@ -65,13 +65,13 @@ impl MfaRegSession {
) -> Result<(Self, MfaRegNext), OperationError> {
// Based on the req, init our session, and the return the next step.
// Store the ID of the event that start's the attempt
let token = TOTP::generate_secure(label, TOTP_DEFAULT_STEP);
let token = Totp::generate_secure(label, TOTP_DEFAULT_STEP);
let accountname = account.name.as_str();
let issuer = account.spn.as_str();
let next = MfaRegNext::TOTPCheck(token.to_proto(accountname, issuer));
let next = MfaRegNext::TotpCheck(token.to_proto(accountname, issuer));
let state = MfaRegState::TOTPInit(token);
let state = MfaRegState::TotpInit(token);
let s = MfaRegSession {
origin,
account,
@ -93,13 +93,13 @@ impl MfaRegSession {
};
match &self.state {
MfaRegState::TOTPInit(token) => {
MfaRegState::TotpInit(token) => {
if token.verify(chal, ct) {
let mut nstate = MfaRegState::TOTPDone;
let mut nstate = MfaRegState::TotpDone;
mem::swap(&mut self.state, &mut nstate);
match nstate {
MfaRegState::TOTPInit(token) => {
Ok((MfaRegNext::Success, Some(MfaRegCred::TOTP(token))))
MfaRegState::TotpInit(token) => {
Ok((MfaRegNext::Success, Some(MfaRegCred::Totp(token))))
}
_ => Err(OperationError::InvalidState),
}
@ -108,7 +108,7 @@ impl MfaRegSession {
let accountname = self.account.name.as_str();
let issuer = self.account.spn.as_str();
Ok((
MfaRegNext::TOTPCheck(token.to_proto(accountname, issuer)),
MfaRegNext::TotpCheck(token.to_proto(accountname, issuer)),
None,
))
}

View file

@ -5,10 +5,10 @@ use crate::event::{AuthEvent, AuthEventStep, AuthResult};
use crate::idm::account::Account;
use crate::idm::authsession::AuthSession;
use crate::idm::event::{
CredentialStatusEvent, GeneratePasswordEvent, GenerateTOTPEvent, LdapAuthEvent,
PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent, RemoveTOTPEvent,
CredentialStatusEvent, GeneratePasswordEvent, GenerateTotpEvent, LdapAuthEvent,
PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent, RemoveTotpEvent,
RemoveWebauthnEvent, UnixGroupTokenEvent, UnixPasswordChangeEvent, UnixUserAuthEvent,
UnixUserTokenEvent, VerifyTOTPEvent, WebauthnDoRegisterEvent, WebauthnInitRegisterEvent,
UnixUserTokenEvent, VerifyTotpEvent, WebauthnDoRegisterEvent, WebauthnInitRegisterEvent,
};
use crate::idm::mfareg::{MfaRegCred, MfaRegNext, MfaRegSession};
use crate::idm::radius::RadiusAccount;
@ -1294,7 +1294,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
pub fn generate_account_totp(
&mut self,
au: &mut AuditScope,
gte: &GenerateTOTPEvent,
gte: &GenerateTotpEvent,
ct: Duration,
) -> Result<SetCredentialResponse, OperationError> {
let account = self.target_to_account(au, &gte.target)?;
@ -1318,7 +1318,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
pub fn verify_account_totp(
&mut self,
au: &mut AuditScope,
vte: &VerifyTOTPEvent,
vte: &VerifyTotpEvent,
ct: Duration,
) -> Result<SetCredentialResponse, OperationError> {
let sessionid = vte.session;
@ -1337,7 +1337,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
e
})?;
if let (MfaRegNext::Success, Some(MfaRegCred::TOTP(token))) = (&next, opt_cred) {
if let (MfaRegNext::Success, Some(MfaRegCred::Totp(token))) = (&next, opt_cred) {
// Purge the session.
let session = self
.mfareg_sessions
@ -1376,7 +1376,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
pub fn remove_account_totp(
&mut self,
au: &mut AuditScope,
rte: &RemoveTOTPEvent,
rte: &RemoveTotpEvent,
) -> Result<SetCredentialResponse, OperationError> {
ltrace!(au, "Attempting to remove totp -> {:?}", rte.target);
@ -1534,14 +1534,14 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
#[cfg(test)]
mod tests {
use crate::credential::policy::CryptoPolicy;
use crate::credential::totp::TOTP;
use crate::credential::totp::Totp;
use crate::credential::{Credential, Password};
use crate::event::{AuthEvent, AuthResult, CreateEvent, ModifyEvent};
use crate::idm::delayed::{DelayedAction, WebauthnCounterIncrement};
use crate::idm::event::{
GenerateTOTPEvent, PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent,
RemoveTOTPEvent, RemoveWebauthnEvent, UnixGroupTokenEvent, UnixPasswordChangeEvent,
UnixUserAuthEvent, UnixUserTokenEvent, VerifyTOTPEvent, WebauthnDoRegisterEvent,
GenerateTotpEvent, PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent,
RemoveTotpEvent, RemoveWebauthnEvent, UnixGroupTokenEvent, UnixPasswordChangeEvent,
UnixUserAuthEvent, UnixUserTokenEvent, VerifyTotpEvent, WebauthnDoRegisterEvent,
WebauthnInitRegisterEvent,
};
use crate::idm::AuthState;
@ -2312,7 +2312,7 @@ mod tests {
let mut idms_prox_write = idms.proxy_write(ct.clone());
// verify with no session (fail)
let vte1 = VerifyTOTPEvent::new_internal(UUID_ADMIN.clone(), Uuid::new_v4(), 0);
let vte1 = VerifyTotpEvent::new_internal(UUID_ADMIN.clone(), Uuid::new_v4(), 0);
match idms_prox_write.verify_account_totp(au, &vte1, ct.clone()) {
Err(e) => {
@ -2322,18 +2322,18 @@ mod tests {
};
// reg, expire session, attempt verify (fail)
let gte1 = GenerateTOTPEvent::new_internal(UUID_ADMIN.clone());
let gte1 = GenerateTotpEvent::new_internal(UUID_ADMIN.clone());
let res = idms_prox_write
.generate_account_totp(au, &gte1, ct.clone())
.unwrap();
let sesid = match res {
SetCredentialResponse::TOTPCheck(id, _) => id,
SetCredentialResponse::TotpCheck(id, _) => id,
_ => panic!("invalid state!"),
};
idms_prox_write.expire_mfareg_sessions(expire.clone());
let vte2 = VerifyTOTPEvent::new_internal(UUID_ADMIN.clone(), sesid, 0);
let vte2 = VerifyTotpEvent::new_internal(UUID_ADMIN.clone(), sesid, 0);
match idms_prox_write.verify_account_totp(au, &vte1, ct.clone()) {
Err(e) => {
@ -2347,16 +2347,16 @@ mod tests {
.generate_account_totp(au, &gte1, ct.clone())
.unwrap();
let (sesid, tok) = match res {
SetCredentialResponse::TOTPCheck(id, tok) => (id, tok),
SetCredentialResponse::TotpCheck(id, tok) => (id, tok),
_ => panic!("invalid state!"),
};
// get the correct otp
let r_tok: TOTP = tok.into();
let r_tok: Totp = tok.into();
let chal = r_tok
.do_totp_duration_from_epoch(&ct)
.expect("Failed to do totp?");
// attempt the verify
let vte3 = VerifyTOTPEvent::new_internal(UUID_ADMIN.clone(), sesid, chal);
let vte3 = VerifyTotpEvent::new_internal(UUID_ADMIN.clone(), sesid, chal);
match idms_prox_write.verify_account_totp(au, &vte3, ct.clone()) {
Err(e) => assert!(e == OperationError::InvalidState),
@ -2375,16 +2375,16 @@ mod tests {
.generate_account_totp(au, &gte1, ct.clone())
.unwrap();
let (sesid, tok) = match res {
SetCredentialResponse::TOTPCheck(id, tok) => (id, tok),
SetCredentialResponse::TotpCheck(id, tok) => (id, tok),
_ => panic!("invalid state!"),
};
// get the correct otp
let r_tok: TOTP = tok.into();
let r_tok: Totp = tok.into();
let chal = r_tok
.do_totp_duration_from_epoch(&ct)
.expect("Failed to do totp?");
// attempt the verify
let vte3 = VerifyTOTPEvent::new_internal(UUID_ANONYMOUS.clone(), sesid, chal);
let vte3 = VerifyTotpEvent::new_internal(UUID_ANONYMOUS.clone(), sesid, chal);
match idms_prox_write.verify_account_totp(au, &vte3, ct.clone()) {
Err(e) => assert!(e == OperationError::InvalidRequestState),
@ -2396,14 +2396,14 @@ mod tests {
.generate_account_totp(au, &gte1, ct.clone())
.unwrap();
let (_sesid, _tok) = match res {
SetCredentialResponse::TOTPCheck(id, tok) => (id, tok),
SetCredentialResponse::TotpCheck(id, tok) => (id, tok),
_ => panic!("invalid state!"),
};
// We can reuse the OTP/Vte2 from before, since we want the invalid otp.
match idms_prox_write.verify_account_totp(au, &vte2, ct.clone()) {
// On failure we get back another attempt to setup the token.
Ok(SetCredentialResponse::TOTPCheck(_id, _tok)) => {}
Ok(SetCredentialResponse::TotpCheck(_id, _tok)) => {}
_ => panic!(),
};
idms_prox_write.expire_mfareg_sessions(expire.clone());
@ -2414,16 +2414,16 @@ mod tests {
.generate_account_totp(au, &gte1, ct.clone())
.unwrap();
let (sesid, tok) = match res {
SetCredentialResponse::TOTPCheck(id, tok) => (id, tok),
SetCredentialResponse::TotpCheck(id, tok) => (id, tok),
_ => panic!("invalid state!"),
};
// We can't reuse the OTP/Vte from before, since the token seed changes
let r_tok: TOTP = tok.into();
let r_tok: Totp = tok.into();
let chal = r_tok
.do_totp_duration_from_epoch(&ct)
.expect("Failed to do totp?");
// attempt the verify
let vte3 = VerifyTOTPEvent::new_internal(UUID_ADMIN.clone(), sesid, chal);
let vte3 = VerifyTotpEvent::new_internal(UUID_ADMIN.clone(), sesid, chal);
match idms_prox_write.verify_account_totp(au, &vte3, ct.clone()) {
Ok(SetCredentialResponse::Success) => {}
@ -2432,7 +2432,7 @@ mod tests {
idms_prox_write.expire_mfareg_sessions(expire.clone());
// Test removing the TOTP and then authing with password only.
let rte = RemoveTOTPEvent::new_internal(UUID_ADMIN.clone());
let rte = RemoveTotpEvent::new_internal(UUID_ADMIN.clone());
idms_prox_write.remove_account_totp(au, &rte).unwrap();
assert!(idms_prox_write.commit(au).is_ok());

View file

@ -108,7 +108,7 @@ impl LdapServer {
) -> Result<Vec<LdapMsg>, OperationError> {
ladmin_info!(au, "Attempt LDAP Search for {}", uat.spn);
// If the request is "", Base, Present("objectclass"), [], then we want the rootdse.
if sr.base == "" && sr.scope == LdapSearchScope::Base {
if sr.base.is_empty() && sr.scope == LdapSearchScope::Base {
ladmin_info!(au, "LDAP Search success - RootDSE");
Ok(vec![
sr.gen_result_entry(self.rootdse.clone()),
@ -296,12 +296,12 @@ impl LdapServer {
lsecurity!(
au,
"Attempt LDAP Bind for {}",
if dn == "" { "anonymous" } else { dn }
if dn.is_empty() { "anonymous" } else { dn }
);
let mut idm_auth = idms.auth_async().await;
let target_uuid: Uuid = if dn == "" {
if pw == "" {
let target_uuid: Uuid = if dn.is_empty() {
if pw.is_empty() {
lsecurity!(au, "✅ LDAP Bind success anonymous");
*UUID_ANONYMOUS
} else {
@ -321,7 +321,7 @@ impl LdapServer {
ltrace!(au, "rdn val is -> {:?}", rdn);
if rdn == "" {
if rdn.is_empty() {
// That's weird ...
return Err(OperationError::NoMatchingEntries);
}
@ -427,9 +427,11 @@ impl LdapServer {
fn ldap_domain_to_dc(input: &str) -> String {
let mut output: String = String::new();
input.split('.').for_each(|dc| {
output.push_str("dc=");
output.push_str(dc);
output.push_str(",");
// output.push_str("dc=");
// output.push_str(dc);
// #[allow(clippy::single_char_add_str)]
// output.push_str(",");
output.push_str(concat!("dc=", dc, ","));
});
// Remove the last ','
output.pop();

View file

@ -124,7 +124,7 @@ impl Plugin for PasswordImport {
#[cfg(test)]
mod tests {
use crate::credential::policy::CryptoPolicy;
use crate::credential::totp::{TOTP, TOTP_DEFAULT_STEP};
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
use crate::credential::{Credential, CredentialType};
use crate::modify::{Modify, ModifyList};
use crate::prelude::*;
@ -234,7 +234,7 @@ mod tests {
}"#,
);
let totp = TOTP::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let totp = Totp::generate_secure("test_totp".to_string(), TOTP_DEFAULT_STEP);
let p = CryptoPolicy::minimum();
let c = Credential::new_password_only(&p, "password")
.unwrap()
@ -263,7 +263,7 @@ mod tests {
.get_ava_single_credential("primary_credential")
.expect("failed to get primary cred.");
match &c.type_ {
CredentialType::PasswordMFA(_pw, totp, webauthn) => {
CredentialType::PasswordMfa(_pw, totp, webauthn) => {
assert!(totp.is_some());
assert!(webauthn.is_empty());
}

View file

@ -219,7 +219,7 @@ impl Plugin for Spn {
e.get_uuid()
);
debug_assert!(false);
r.push(Err(ConsistencyError::InvalidSPN(e.get_id())));
r.push(Err(ConsistencyError::InvalidSpn(e.get_id())));
continue;
}
};
@ -235,12 +235,12 @@ impl Plugin for Spn {
g_spn,
);
debug_assert!(false);
r.push(Err(ConsistencyError::InvalidSPN(e.get_id())))
r.push(Err(ConsistencyError::InvalidSpn(e.get_id())))
}
}
None => {
ladmin_error!(au, "Entry {:?} does not contain an SPN", e.get_uuid(),);
r.push(Err(ConsistencyError::InvalidSPN(e.get_id())))
r.push(Err(ConsistencyError::InvalidSpn(e.get_id())))
}
}
}

View file

@ -1957,7 +1957,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
Err(e) => Err(OperationError::SchemaViolation(e)),
}
} else {
Err(OperationError::InvalidDBState)
Err(OperationError::InvalidDbState)
}
}
Err(e) => {
@ -2022,7 +2022,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
Ok(())
}
} else {
Err(OperationError::InvalidDBState)
Err(OperationError::InvalidDbState)
}
}
Err(er) => {

View file

@ -288,10 +288,7 @@ impl PartialValue {
}
pub fn is_utf8(&self) -> bool {
match self {
PartialValue::Utf8(_) => true,
_ => false,
}
matches!(self, PartialValue::Utf8(_))
}
pub fn new_iutf8(s: &str) -> Self {
@ -315,17 +312,11 @@ impl PartialValue {
*/
pub fn is_iutf8(&self) -> bool {
match self {
PartialValue::Iutf8(_) => true,
_ => false,
}
matches!(self, PartialValue::Iutf8(_))
}
pub fn is_iname(&self) -> bool {
match self {
PartialValue::Iname(_) => true,
_ => false,
}
matches!(self, PartialValue::Iname(_))
}
pub fn new_bool(b: bool) -> Self {
@ -340,10 +331,7 @@ impl PartialValue {
}
pub fn is_bool(&self) -> bool {
match self {
PartialValue::Bool(_) => true,
_ => false,
}
matches!(self, PartialValue::Bool(_))
}
pub fn new_uuid(u: Uuid) -> Self {
@ -362,10 +350,7 @@ impl PartialValue {
}
pub fn is_uuid(&self) -> bool {
match self {
PartialValue::Uuid(_) => true,
_ => false,
}
matches!(self, PartialValue::Uuid(_))
}
pub fn new_refer(u: Uuid) -> Self {
@ -384,10 +369,7 @@ impl PartialValue {
}
pub fn is_refer(&self) -> bool {
match self {
PartialValue::Refer(_) => true,
_ => false,
}
matches!(self, PartialValue::Refer(_))
}
pub fn new_indexs(s: &str) -> Option<Self> {
@ -399,10 +381,7 @@ impl PartialValue {
}
pub fn is_index(&self) -> bool {
match self {
PartialValue::Index(_) => true,
_ => false,
}
matches!(self, PartialValue::Index(_))
}
pub fn new_syntaxs(s: &str) -> Option<Self> {
@ -414,10 +393,7 @@ impl PartialValue {
}
pub fn is_syntax(&self) -> bool {
match self {
PartialValue::Syntax(_) => true,
_ => false,
}
matches!(self, PartialValue::Syntax(_))
}
pub fn new_json_filter(s: &str) -> Option<Self> {
@ -429,10 +405,7 @@ impl PartialValue {
}
pub fn is_json_filter(&self) -> bool {
match self {
PartialValue::JsonFilt(_) => true,
_ => false,
}
matches!(self, PartialValue::JsonFilt(_))
}
pub fn new_credential_tag(s: &str) -> Self {
@ -440,10 +413,7 @@ impl PartialValue {
}
pub fn is_credential(&self) -> bool {
match self {
PartialValue::Cred(_) => true,
_ => false,
}
matches!(self, PartialValue::Cred(_))
}
pub fn new_radius_string() -> Self {
@ -451,10 +421,7 @@ impl PartialValue {
}
pub fn is_radius_string(&self) -> bool {
match self {
PartialValue::RadiusCred => true,
_ => false,
}
matches!(self, PartialValue::RadiusCred)
}
pub fn new_sshkey_tag(s: String) -> Self {
@ -466,10 +433,7 @@ impl PartialValue {
}
pub fn is_sshkey(&self) -> bool {
match self {
PartialValue::SshKey(_) => true,
_ => false,
}
matches!(self, PartialValue::SshKey(_))
}
pub fn new_spn_s(s: &str) -> Option<Self> {
@ -491,10 +455,7 @@ impl PartialValue {
}
pub fn is_spn(&self) -> bool {
match self {
PartialValue::Spn(_, _) => true,
_ => false,
}
matches!(self, PartialValue::Spn(_, _))
}
pub fn new_uint32(u: u32) -> Self {
@ -506,10 +467,7 @@ impl PartialValue {
}
pub fn is_uint32(&self) -> bool {
match self {
PartialValue::Uint32(_) => true,
_ => false,
}
matches!(self, PartialValue::Uint32(_))
}
pub fn new_cid(c: Cid) -> Self {
@ -521,10 +479,7 @@ impl PartialValue {
}
pub fn is_cid(&self) -> bool {
match self {
PartialValue::Cid(_) => true,
_ => false,
}
matches!(self, PartialValue::Cid(_))
}
pub fn new_nsuniqueid_s(s: &str) -> Self {
@ -532,10 +487,7 @@ impl PartialValue {
}
pub fn is_nsuniqueid(&self) -> bool {
match self {
PartialValue::Nsuniqueid(_) => true,
_ => false,
}
matches!(self, PartialValue::Nsuniqueid(_))
}
pub fn new_datetime_epoch(ts: Duration) -> Self {
@ -550,10 +502,7 @@ impl PartialValue {
}
pub fn is_datetime(&self) -> bool {
match self {
PartialValue::DateTime(_) => true,
_ => false,
}
matches!(self, PartialValue::DateTime(_))
}
pub fn to_str(&self) -> Option<&str> {
@ -744,10 +693,7 @@ impl Value {
}
pub fn is_utf8(&self) -> bool {
match self.pv {
PartialValue::Utf8(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Utf8(_))
}
pub fn new_iutf8(s: &str) -> Self {
@ -758,10 +704,7 @@ impl Value {
}
pub fn is_insensitive_utf8(&self) -> bool {
match self.pv {
PartialValue::Iutf8(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Iutf8(_))
}
pub fn new_iname(s: &str) -> Self {
@ -772,10 +715,7 @@ impl Value {
}
pub fn is_iname(&self) -> bool {
match self.pv {
PartialValue::Iname(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Iname(_))
}
pub fn new_uuid(u: Uuid) -> Self {
@ -801,10 +741,7 @@ impl Value {
// Is this correct? Should ref be seperate?
pub fn is_uuid(&self) -> bool {
match self.pv {
PartialValue::Uuid(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Uuid(_))
}
pub fn new_class(s: &str) -> Self {
@ -837,10 +774,7 @@ impl Value {
#[inline]
pub fn is_bool(&self) -> bool {
match self.pv {
PartialValue::Bool(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Bool(_))
}
pub fn new_syntaxs(s: &str) -> Option<Self> {
@ -851,10 +785,7 @@ impl Value {
}
pub fn is_syntax(&self) -> bool {
match self.pv {
PartialValue::Syntax(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Syntax(_))
}
pub fn new_indexs(s: &str) -> Option<Self> {
@ -865,10 +796,7 @@ impl Value {
}
pub fn is_index(&self) -> bool {
match self.pv {
PartialValue::Index(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Index(_))
}
pub fn new_refer(u: Uuid) -> Self {
@ -893,10 +821,7 @@ impl Value {
}
pub fn is_refer(&self) -> bool {
match self.pv {
PartialValue::Refer(_) => true,
_ => false,
}
matches!(self.pv, PartialValue::Refer(_))
}
pub fn new_json_filter(s: &str) -> Option<Self> {
@ -925,10 +850,7 @@ impl Value {
}
pub fn is_credential(&self) -> bool {
match &self.pv {
PartialValue::Cred(_) => true,
_ => false,
}
matches!(&self.pv, PartialValue::Cred(_))
}
pub fn to_credential(&self) -> Option<&Credential> {
@ -1394,10 +1316,7 @@ impl Value {
}
}
PartialValue::Cred(_) => match &self.data {
Some(v) => match v.as_ref() {
DataValue::Cred(_) => true,
_ => false,
},
Some(v) => matches!(v.as_ref(), DataValue::Cred(_)),
None => false,
},
PartialValue::SshKey(_) => match &self.data {
@ -1410,10 +1329,7 @@ impl Value {
None => false,
},
PartialValue::RadiusCred => match &self.data {
Some(v) => match v.as_ref() {
DataValue::RadiusCred(_) => true,
_ => false,
},
Some(v) => matches!(v.as_ref(), DataValue::RadiusCred(_)),
None => false,
},
PartialValue::Nsuniqueid(s) => NSUNIQUEID_RE.is_match(s),

View file

@ -262,7 +262,7 @@ impl Component for LoginApp {
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
ConsoleService::log(format!("create").as_str());
ConsoleService::log("create");
// First we need to work out what state we are in.
let lstorage = StorageService::new(yew::services::storage::Area::Local).unwrap();
@ -328,7 +328,7 @@ impl Component for LoginApp {
Ok(totp) => {
self.state = LoginState::Totp(TotpState::Disabled);
let authreq = AuthRequest {
step: AuthStep::Cred(AuthCredential::TOTP(totp)),
step: AuthStep::Cred(AuthCredential::Totp(totp)),
};
self.auth_step(authreq);
}
@ -411,7 +411,7 @@ impl Component for LoginApp {
// Go to the password view.
self.state = LoginState::Password(true);
}
AuthAllowed::TOTP => {
AuthAllowed::Totp => {
self.state = LoginState::Totp(TotpState::Enabled);
}
AuthAllowed::Webauthn(challenge) => {