diff --git a/bffhd/authentication/fabfire/mod.rs b/bffhd/authentication/fabfire/mod.rs index 5d2d5bb..6c7cb62 100644 --- a/bffhd/authentication/fabfire/mod.rs +++ b/bffhd/authentication/fabfire/mod.rs @@ -2,7 +2,7 @@ mod server; pub use server::FabFire; use rsasl::mechname::Mechname; -use rsasl::registry::{Mechanism, MECHANISMS, Side}; +use rsasl::registry::{Mechanism, Side, MECHANISMS}; const MECHNAME: &'static Mechname = &Mechname::const_new_unchecked(b"X-FABFIRE"); @@ -10,8 +10,8 @@ const MECHNAME: &'static Mechname = &Mechname::const_new_unchecked(b"X-FABFIRE") pub static FABFIRE: Mechanism = Mechanism::build(MECHNAME, 300, None, Some(FabFire::new_server), Side::Client); -use std::marker::PhantomData; use rsasl::property::SizedProperty; +use std::marker::PhantomData; // All Property types must implement Debug. #[derive(Debug)] diff --git a/bffhd/authentication/fabfire/server.rs b/bffhd/authentication/fabfire/server.rs index 36c61f8..ea1a8a5 100644 --- a/bffhd/authentication/fabfire/server.rs +++ b/bffhd/authentication/fabfire/server.rs @@ -3,7 +3,10 @@ use desfire::desfire::Desfire; use desfire::error::Error as DesfireError; use desfire::iso7816_4::apduresponse::APDUResponse; use rsasl::callback::SessionData; -use rsasl::mechanism::{Authentication, MechanismData, MechanismError, MechanismErrorKind, State, ThisProvider}; +use rsasl::mechanism::{ + Authentication, Demand, DemandReply, MechanismData, MechanismError, MechanismErrorKind, + Provider, State, ThisProvider, +}; use rsasl::prelude::{MessageSent, SASLConfig, SASLError, SessionError}; use rsasl::property::AuthId; use serde::{Deserialize, Serialize}; @@ -62,9 +65,7 @@ impl Display for FabFireError { } } -impl std::error::Error for FabFireError { - -} +impl std::error::Error for FabFireError {} impl MechanismError for FabFireError { fn kind(&self) -> MechanismErrorKind { @@ -92,6 +93,7 @@ struct CardInfo { } struct KeyInfo { + authid: String, key_id: u8, key: Box<[u8]>, } @@ -493,11 +495,20 @@ impl Authentication for FabFire { Ok(_) => { match apdu_response.body { Some(data) => { - let token = String::from_utf8(data).unwrap(); - let prov = - ThisProvider::::with(token.trim_matches(char::from(0))); - let key = session.need_with::(&prov, |key| Ok(Box::from(key.as_slice())))?; - self.key_info = Some(KeyInfo { key_id: 0x01, key }); + let authid = String::from_utf8(data) + .unwrap() + .trim_matches(char::from(0)) + .to_string(); + let prov = ThisProvider::::with(&authid); + let key = session + .need_with::(&prov, |key| { + Ok(Box::from(key.as_slice())) + })?; + self.key_info = Some(KeyInfo { + authid, + key_id: 0x01, + key, + }); } None => { tracing::error!("No data in response"); @@ -679,6 +690,25 @@ impl Authentication for FabFire { writer .write_all(&send_buf) .map_err(|e| SessionError::Io { source: e })?; + + struct Prov<'a> { + authid: &'a str, + } + impl<'a> Provider<'a> for Prov<'a> { + fn provide( + &self, + req: &mut Demand<'a>, + ) -> DemandReply<()> + { + req.provide_ref::(self.authid)? + .done() + } + } + let prov = Prov { + authid: &self.key_info.as_ref().unwrap().authid, + }; + session.validate(&prov)?; + return Ok(State::Finished(MessageSent::Yes)); } Err(e) => { diff --git a/bffhd/authentication/fabfire_bin/mod.rs b/bffhd/authentication/fabfire_bin/mod.rs new file mode 100644 index 0000000..87e74d6 --- /dev/null +++ b/bffhd/authentication/fabfire_bin/mod.rs @@ -0,0 +1,11 @@ +mod server; +pub use server::FabFire; + +use rsasl::mechname::Mechname; +use rsasl::registry::{Mechanism, Side, MECHANISMS}; + +const MECHNAME: &'static Mechname = &Mechname::const_new_unchecked(b"X-FABFIRE-BIN"); + +#[linkme::distributed_slice(MECHANISMS)] +pub static FABFIRE: Mechanism = + Mechanism::build(MECHNAME, 300, None, Some(FabFire::new_server), Side::Client); diff --git a/bffhd/authentication/fabfire_bin/server.rs b/bffhd/authentication/fabfire_bin/server.rs new file mode 100644 index 0000000..db563ce --- /dev/null +++ b/bffhd/authentication/fabfire_bin/server.rs @@ -0,0 +1,526 @@ +use desfire::desfire::desfire::MAX_BYTES_PER_TRANSACTION; +use desfire::desfire::Desfire; +use desfire::error::Error as DesfireError; +use desfire::iso7816_4::apduresponse::APDUResponse; +use rsasl::callback::SessionData; +use rsasl::mechanism::{ + Authentication, Demand, DemandReply, MechanismData, MechanismError, MechanismErrorKind, + Provider, State, ThisProvider, +}; +use rsasl::prelude::{MessageSent, SASLConfig, SASLError, SessionError}; +use rsasl::property::AuthId; +use serde::{Deserialize, Serialize}; +use std::convert::TryFrom; +use std::fmt::{Debug, Display, Formatter}; +use std::io::Write; +use std::sync::Arc; + +use crate::authentication::fabfire::FabFireCardKey; + +enum FabFireError { + ParseError, + SerializationError, + DeserializationError(serde_json::Error), + CardError(DesfireError), + InvalidMagic(String), + InvalidToken(String), + InvalidURN(String), + InvalidCredentials(String), + Session(SessionError), +} + +impl Debug for FabFireError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + FabFireError::ParseError => write!(f, "ParseError"), + FabFireError::SerializationError => write!(f, "SerializationError"), + FabFireError::DeserializationError(e) => write!(f, "DeserializationError: {}", e), + FabFireError::CardError(err) => write!(f, "CardError: {}", err), + FabFireError::InvalidMagic(magic) => write!(f, "InvalidMagic: {}", magic), + FabFireError::InvalidToken(token) => write!(f, "InvalidToken: {}", token), + FabFireError::InvalidURN(urn) => write!(f, "InvalidURN: {}", urn), + FabFireError::InvalidCredentials(credentials) => { + write!(f, "InvalidCredentials: {}", credentials) + } + FabFireError::Session(err) => write!(f, "Session: {}", err), + } + } +} + +impl Display for FabFireError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + FabFireError::ParseError => write!(f, "ParseError"), + FabFireError::SerializationError => write!(f, "SerializationError"), + FabFireError::DeserializationError(e) => write!(f, "DeserializationError: {}", e), + FabFireError::CardError(err) => write!(f, "CardError: {}", err), + FabFireError::InvalidMagic(magic) => write!(f, "InvalidMagic: {}", magic), + FabFireError::InvalidToken(token) => write!(f, "InvalidToken: {}", token), + FabFireError::InvalidURN(urn) => write!(f, "InvalidURN: {}", urn), + FabFireError::InvalidCredentials(credentials) => { + write!(f, "InvalidCredentials: {}", credentials) + } + FabFireError::Session(err) => write!(f, "Session: {}", err), + } + } +} + +impl std::error::Error for FabFireError {} + +impl MechanismError for FabFireError { + fn kind(&self) -> MechanismErrorKind { + match self { + FabFireError::ParseError => MechanismErrorKind::Parse, + FabFireError::SerializationError => MechanismErrorKind::Protocol, + FabFireError::DeserializationError(_) => MechanismErrorKind::Parse, + FabFireError::CardError(_) => MechanismErrorKind::Protocol, + FabFireError::InvalidMagic(_) => MechanismErrorKind::Protocol, + FabFireError::InvalidToken(_) => MechanismErrorKind::Protocol, + FabFireError::InvalidURN(_) => MechanismErrorKind::Protocol, + FabFireError::InvalidCredentials(_) => MechanismErrorKind::Protocol, + FabFireError::Session(_) => MechanismErrorKind::Protocol, + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +struct CardInfo { + #[serde(rename = "UID", with = "hex")] + uid: [u8; 7], + key_old: Option>, + key_new: Option>, +} + +struct KeyInfo { + authid: String, + key_id: u8, + key: Box<[u8]>, +} + +struct AuthInfo { + rnd_a: Vec, + rnd_b: Vec, + iv: Vec, +} + +enum Step { + New, + SelectApp, + VerifyMagic, + GetURN, + GetToken, + Authenticate1, + Authenticate2, +} + +pub struct FabFire { + step: Step, + card_info: Option, + key_info: Option, + auth_info: Option, + app_id: u32, + local_urn: String, + desfire: Desfire, +} + +const MAGIC: &'static str = "FABACCESS\0DESFIRE\01.0\0"; + +impl FabFire { + pub fn new_server(_sasl: &SASLConfig) -> Result, SASLError> { + Ok(Box::new(Self { + step: Step::New, + card_info: None, + key_info: None, + auth_info: None, + app_id: 0x464142, + local_urn: "urn:fabaccess:lab:innovisionlab".to_string(), + desfire: Desfire { + card: None, + session_key: None, + cbc_iv: None, + }, + })) + } +} + +impl Authentication for FabFire { + fn step( + &mut self, + session: &mut MechanismData<'_>, + input: Option<&[u8]>, + writer: &mut dyn Write, + ) -> Result { + match self.step { + Step::New => { + tracing::trace!("Step: New"); + //receive card info (especially card UID) from reader + return match input { + None => Err(SessionError::InputDataRequired), + Some(_) => { + //select application + return match self.desfire.select_application_cmd(self.app_id) { + Ok(buf) => match Vec::::try_from(buf) { + Ok(data) => { + self.step = Step::SelectApp; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!( + "Failed to convert APDUCommand to Vec: {:?}", + e + ); + return Err(FabFireError::SerializationError.into()); + } + }, + Err(e) => { + tracing::error!("Failed to generate APDUCommand: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }; + } + }; + } + Step::SelectApp => { + tracing::trace!("Step: SelectApp"); + // check that we successfully selected the application + + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + apdu_response + .check() + .map_err(|e| FabFireError::CardError(e))?; + + // request the contents of the file containing the magic string + const MAGIC_FILE_ID: u8 = 0x01; + + return match self + .desfire + .read_data_chunk_cmd(MAGIC_FILE_ID, 0, MAGIC.len()) + { + Ok(buf) => match Vec::::try_from(buf) { + Ok(data) => { + self.step = Step::VerifyMagic; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!("Failed to convert APDUCommand to Vec: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }, + Err(e) => { + tracing::error!("Failed to generate APDUCommand: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }; + } + Step::VerifyMagic => { + tracing::trace!("Step: VerifyMagic"); + // verify the magic string to determine that we have a valid fabfire card + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + match apdu_response.check() { + Ok(_) => { + match apdu_response.body { + Some(data) => { + if std::str::from_utf8(data.as_slice()) != Ok(MAGIC) { + tracing::error!("Invalid magic string"); + return Err(FabFireError::ParseError.into()); + } + } + None => { + tracing::error!("No data returned from card"); + return Err(FabFireError::ParseError.into()); + } + }; + } + Err(e) => { + tracing::error!("Got invalid APDUResponse: {:?}", e); + return Err(FabFireError::ParseError.into()); + } + } + + // request the contents of the file containing the URN + const URN_FILE_ID: u8 = 0x02; + + return match self.desfire.read_data_chunk_cmd( + URN_FILE_ID, + 0, + self.local_urn.as_bytes().len(), + ) { + // TODO: support urn longer than 47 Bytes + Ok(buf) => match Vec::::try_from(buf) { + Ok(data) => { + self.step = Step::GetURN; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!("Failed to convert APDUCommand to Vec: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }, + Err(e) => { + tracing::error!("Failed to generate APDUCommand: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }; + } + Step::GetURN => { + tracing::trace!("Step: GetURN"); + // parse the urn and match it to our local urn + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + match apdu_response.check() { + Ok(_) => { + match apdu_response.body { + Some(data) => { + let received_urn = String::from_utf8(data).unwrap(); + if received_urn != self.local_urn { + tracing::error!( + "URN mismatch: {:?} != {:?}", + received_urn, + self.local_urn + ); + return Err(FabFireError::ParseError.into()); + } + } + None => { + tracing::error!("No data returned from card"); + return Err(FabFireError::ParseError.into()); + } + }; + } + Err(e) => { + tracing::error!("Got invalid APDUResponse: {:?}", e); + return Err(FabFireError::ParseError.into()); + } + } + // request the contents of the file containing the URN + const TOKEN_FILE_ID: u8 = 0x03; + + return match self.desfire.read_data_chunk_cmd( + TOKEN_FILE_ID, + 0, + MAX_BYTES_PER_TRANSACTION, + ) { + // TODO: support data longer than 47 Bytes + Ok(buf) => match Vec::::try_from(buf) { + Ok(data) => { + self.step = Step::GetToken; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!("Failed to convert APDUCommand to Vec: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }, + Err(e) => { + tracing::error!("Failed to generate APDUCommand: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }; + } + Step::GetToken => { + // println!("Step: GetToken"); + // parse the token and select the appropriate user + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + match apdu_response.check() { + Ok(_) => { + match apdu_response.body { + Some(data) => { + let authid = String::from_utf8(data) + .unwrap() + .trim_matches(char::from(0)) + .to_string(); + let prov = ThisProvider::::with(&authid); + let key = session + .need_with::(&prov, |key| { + Ok(Box::from(key.as_slice())) + })?; + self.key_info = Some(KeyInfo { + authid, + key_id: 0x01, + key, + }); + } + None => { + tracing::error!("No data in response"); + return Err(FabFireError::ParseError.into()); + } + }; + } + Err(e) => { + tracing::error!("Failed to check response: {:?}", e); + return Err(FabFireError::ParseError.into()); + } + } + + return match self + .desfire + .authenticate_iso_aes_challenge_cmd(self.key_info.as_ref().unwrap().key_id) + { + Ok(buf) => match Vec::::try_from(buf) { + Ok(data) => { + self.step = Step::Authenticate1; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!("Failed to convert to Vec: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }, + Err(e) => { + tracing::error!("Failed to create authenticate command: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + }; + } + Step::Authenticate1 => { + tracing::trace!("Step: Authenticate1"); + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + return match apdu_response.check() { + Ok(_) => { + match apdu_response.body { + Some(data) => { + let rnd_b_enc = data.as_slice(); + + //FIXME: This is ugly, we should find a better way to make the function testable + //TODO: Check if we need a CSPRNG here + let rnd_a: [u8; 16] = rand::random(); + + let (cmd_challenge_response, rnd_b, iv) = self + .desfire + .authenticate_iso_aes_response_cmd( + rnd_b_enc, + &*(self.key_info.as_ref().unwrap().key), + &rnd_a, + ) + .unwrap(); + self.auth_info = Some(AuthInfo { + rnd_a: Vec::::from(rnd_a), + rnd_b, + iv, + }); + match Vec::::try_from(cmd_challenge_response) { + Ok(data) => { + self.step = Step::Authenticate2; + writer + .write_all(&data) + .map_err(|e| SessionError::Io { source: e })?; + Ok(State::Running) + } + Err(e) => { + tracing::error!("Failed to convert to Vec: {:?}", e); + return Err(FabFireError::SerializationError.into()); + } + } + } + None => { + tracing::error!("Got invalid response: {:?}", apdu_response); + Err(FabFireError::ParseError.into()) + } + } + } + Err(e) => { + tracing::error!("Failed to check response: {:?}", e); + Err(FabFireError::ParseError.into()) + } + }; + } + Step::Authenticate2 => { + // println!("Step: Authenticate2"); + let apdu_response = match input { + Some(data) => APDUResponse::new(data), + None => return Err(SessionError::InputDataRequired), + }; + + match apdu_response.check() { + Ok(_) => { + match apdu_response.body { + Some(data) => match self.auth_info.as_ref() { + None => { + return Err(FabFireError::ParseError.into()); + } + Some(auth_info) => { + if self + .desfire + .authenticate_iso_aes_verify( + data.as_slice(), + auth_info.rnd_a.as_slice(), + auth_info.rnd_b.as_slice(), + &*(self.key_info.as_ref().unwrap().key), + auth_info.iv.as_slice(), + ) + .is_ok() + { + struct Prov<'a> { + authid: &'a str, + } + impl<'a> Provider<'a> for Prov<'a> { + fn provide( + &self, + req: &mut Demand<'a>, + ) -> DemandReply<()> + { + req.provide_ref::(self.authid)?.done() + } + } + let prov = Prov { + authid: &self.key_info.as_ref().unwrap().authid, + }; + session.validate(&prov)?; + return Ok(State::Finished(MessageSent::Yes)); + } + } + }, + None => { + tracing::error!("got empty response"); + return Err(FabFireError::ParseError.into()); + } + }; + } + Err(_e) => { + tracing::error!("Got invalid response: {:?}", apdu_response); + return Err( + FabFireError::InvalidCredentials(format!("{}", apdu_response)).into(), + ); + } + } + } + } + + return Ok(State::Finished(MessageSent::No)); + } +} diff --git a/bffhd/authentication/mod.rs b/bffhd/authentication/mod.rs index 68ff703..6ec5c8d 100644 --- a/bffhd/authentication/mod.rs +++ b/bffhd/authentication/mod.rs @@ -1,16 +1,17 @@ use crate::users::Users; use miette::{IntoDiagnostic, WrapErr}; -use std::sync::Arc; -use rsasl::callback::{CallbackError, Request, SessionCallback, SessionData, Context}; +use rsasl::callback::{CallbackError, Context, Request, SessionCallback, SessionData}; use rsasl::mechanism::SessionError; use rsasl::prelude::{Mechname, SASLConfig, SASLServer, Session, Validation}; use rsasl::property::{AuthId, AuthzId, Password}; use rsasl::validate::{Validate, ValidationError}; +use std::sync::Arc; use crate::authentication::fabfire::FabFireCardKey; use crate::users::db::User; mod fabfire; +mod fabfire_bin; struct Callback { users: Users, @@ -23,41 +24,55 @@ impl Callback { } } impl SessionCallback for Callback { - fn callback(&self, session_data: &SessionData, context: &Context, request: &mut Request) -> Result<(), SessionError> { + fn callback( + &self, + session_data: &SessionData, + context: &Context, + request: &mut Request, + ) -> Result<(), SessionError> { if let Some(authid) = context.get_ref::() { request.satisfy_with::(|| { let user = self.users.get_user(authid).ok_or(CallbackError::NoValue)?; - let kv = user.userdata.kv.get("cardkey").ok_or(CallbackError::NoValue)?; - let card_key = <[u8; 16]>::try_from( - hex::decode(kv).map_err(|_| CallbackError::NoValue)?, - ).map_err(|_| CallbackError::NoValue)?; + let kv = user + .userdata + .kv + .get("cardkey") + .ok_or(CallbackError::NoValue)?; + let card_key = + <[u8; 16]>::try_from(hex::decode(kv).map_err(|_| CallbackError::NoValue)?) + .map_err(|_| CallbackError::NoValue)?; Ok(card_key) })?; } Ok(()) } - fn validate(&self, session_data: &SessionData, context: &Context, validate: &mut Validate<'_>) -> Result<(), ValidationError> { + fn validate( + &self, + session_data: &SessionData, + context: &Context, + validate: &mut Validate<'_>, + ) -> Result<(), ValidationError> { let span = tracing::info_span!(parent: &self.span, "validate"); let _guard = span.enter(); if validate.is::() { match session_data.mechanism().mechanism.as_str() { "PLAIN" => { - let authcid = context.get_ref::() + let authcid = context + .get_ref::() .ok_or(ValidationError::MissingRequiredProperty)?; let authzid = context.get_ref::(); - let password = context.get_ref::() + let password = context + .get_ref::() .ok_or(ValidationError::MissingRequiredProperty)?; - if authzid.is_some() { - return Ok(()) - } + // if authzid.is_some() { + // return Ok(()) + // } if let Some(user) = self.users.get_user(authcid) { match user.check_password(password) { - Ok(true) => { - validate.finalize::(user) - } + Ok(true) => validate.finalize::(user), Ok(false) => { tracing::warn!(authid=%authcid, "AUTH FAILED: bad password"); } @@ -69,6 +84,14 @@ impl SessionCallback for Callback { tracing::warn!(authid=%authcid, "AUTH FAILED: no such user"); } } + "X-FABFIRE" | "X-FABFIRE-BIN" => { + let authcid = context + .get_ref::() + .ok_or(ValidationError::MissingRequiredProperty)?; + if let Some(user) = self.users.get_user(authcid) { + validate.finalize::(user) + } + } _ => {} } } diff --git a/bffhd/capnp/authenticationsystem.rs b/bffhd/capnp/authenticationsystem.rs index 943933c..c81f547 100644 --- a/bffhd/capnp/authenticationsystem.rs +++ b/bffhd/capnp/authenticationsystem.rs @@ -2,21 +2,21 @@ use capnp::capability::Promise; use capnp::Error; use capnp_rpc::pry; use rsasl::mechname::Mechname; +use rsasl::prelude::State as SaslState; +use rsasl::prelude::{MessageSent, Session}; use rsasl::property::AuthId; use std::fmt; use std::fmt::{Formatter, Write}; use std::io::Cursor; -use rsasl::prelude::{MessageSent, Session}; -use rsasl::prelude::State as SaslState; use tracing::Span; +use crate::authentication::V; use crate::capnp::session::APISession; use crate::session::SessionManager; use api::authenticationsystem_capnp::authentication::{ AbortParams, AbortResults, Server as AuthenticationSystem, StepParams, StepResults, }; use api::authenticationsystem_capnp::{response, response::Error as ErrorCode}; -use crate::authentication::V; const TARGET: &str = "bffh::api::authenticationsystem"; diff --git a/bffhd/initiators/process.rs b/bffhd/initiators/process.rs index d714ec3..79f6bde 100644 --- a/bffhd/initiators/process.rs +++ b/bffhd/initiators/process.rs @@ -1,5 +1,6 @@ use super::Initiator; use super::InitiatorCallbacks; +use crate::resources::modules::fabaccess::Status; use crate::resources::state::State; use crate::utils::linebuffer::LineBuffer; use async_process::{Child, ChildStderr, ChildStdout, Command, Stdio}; @@ -11,7 +12,6 @@ use std::future::Future; use std::io; use std::pin::Pin; use std::task::{Context, Poll}; -use crate::resources::modules::fabaccess::Status; #[derive(Debug, Serialize, Deserialize)] pub enum InputMessage { @@ -63,7 +63,12 @@ struct ProcessState { impl ProcessState { pub fn new(stdout: ChildStdout, stderr: ChildStderr, child: Child) -> Self { - Self { stdout, stderr, stderr_closed: false, child } + Self { + stdout, + stderr, + stderr_closed: false, + child, + } } fn try_process(&mut self, buffer: &[u8], callbacks: &mut InitiatorCallbacks) -> usize { @@ -100,7 +105,9 @@ impl ProcessState { let InputMessage::SetState(status) = state; callbacks.set_status(status); } - Err(error) => tracing::warn!(%error, "process initiator did not send a valid line"), + Err(error) => { + tracing::warn!(%error, "process initiator did not send a valid line") + } } } } @@ -202,8 +209,8 @@ impl Future for Process { impl Initiator for Process { fn new(params: &HashMap, callbacks: InitiatorCallbacks) -> miette::Result - where - Self: Sized, + where + Self: Sized, { let cmd = params .get("cmd") diff --git a/bffhd/session/mod.rs b/bffhd/session/mod.rs index dee72a6..2ac2be7 100644 --- a/bffhd/session/mod.rs +++ b/bffhd/session/mod.rs @@ -1,10 +1,10 @@ use crate::authorization::permissions::Permission; use crate::authorization::roles::Roles; use crate::resources::Resource; +use crate::users::db::User; use crate::users::{db, UserRef}; use crate::Users; use tracing::Span; -use crate::users::db::User; #[derive(Clone)] pub struct SessionManager { @@ -18,7 +18,9 @@ impl SessionManager { } pub fn try_open(&self, parent: &Span, uid: impl AsRef) -> Option { - self.users.get_user(uid.as_ref()).map(|user| self.open(parent, user)) + self.users + .get_user(uid.as_ref()) + .map(|user| self.open(parent, user)) } // TODO: make infallible