mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-21 22:47:55 +01:00
Update to latest rsasl
This commit is contained in:
parent
3cf152a164
commit
0ed53f5cc9
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -937,9 +937,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "desfire"
|
||||
version = "0.2.0-alpha2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "337f0fcd6ef888be0962aeff547f1b219f4190ea785b5c33328f071e91405411"
|
||||
version = "0.2.0-alpha1"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"block-modes",
|
||||
@ -2506,8 +2504,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rsasl"
|
||||
version = "2.0.0-rc.2"
|
||||
source = "git+https://github.com/dequbed/rsasl.git?branch=development#19d2346dc76e5f3b449e3e3ab35c72205c6c4907"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "103603eacc28423095a1366653d823e5d2f4bac86bf7874b8f370d320b671207"
|
||||
dependencies = [
|
||||
"acid_io",
|
||||
"linkme",
|
||||
|
12
Cargo.toml
12
Cargo.toml
@ -84,7 +84,9 @@ capnp = "0.14"
|
||||
capnp-rpc = "0.14.1"
|
||||
|
||||
# API Authentication
|
||||
desfire = "0.2.0-alpha1"
|
||||
#desfire = "0.2.0-alpha1"
|
||||
desfire = { path = "../nfc_rs" }
|
||||
|
||||
hex = { version = "0.4.3", features = ["serde"] }
|
||||
|
||||
futures-signals = "0.3.22"
|
||||
@ -112,10 +114,9 @@ rustls-native-certs = "0.6.1"
|
||||
shadow-rs = "0.11"
|
||||
|
||||
[dependencies.rsasl]
|
||||
git = "https://github.com/dequbed/rsasl.git"
|
||||
branch = "development"
|
||||
version = "2.0.0-rc.3"
|
||||
default_features = false
|
||||
features = ["unstable_custom_mechanism", "provider", "registry_static", "plain"]
|
||||
features = ["unstable_custom_mechanism", "provider", "registry_static", "config_builder", "plain"]
|
||||
|
||||
[dev-dependencies]
|
||||
futures-test = "0.3.16"
|
||||
@ -126,3 +127,6 @@ shadow-rs = "0.11"
|
||||
|
||||
[workspace]
|
||||
members = ["runtime/*", "modules/*", "api"]
|
||||
|
||||
[patch.crates-io]
|
||||
desfire = { path = "../nfc_rs" }
|
@ -3,7 +3,7 @@ use desfire::desfire::Desfire;
|
||||
use desfire::error::Error as DesfireError;
|
||||
use desfire::iso7816_4::apduresponse::APDUResponse;
|
||||
use rsasl::callback::SessionData;
|
||||
use rsasl::mechanism::{Authentication, MechanismError, MechanismErrorKind, State, ThisProvider};
|
||||
use rsasl::mechanism::{Authentication, MechanismData, MechanismError, MechanismErrorKind, State, ThisProvider};
|
||||
use rsasl::prelude::{MessageSent, SASLConfig, SASLError, SessionError};
|
||||
use rsasl::property::AuthId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -177,7 +177,7 @@ impl FabFire {
|
||||
impl Authentication for FabFire {
|
||||
fn step(
|
||||
&mut self,
|
||||
session: &mut SessionData,
|
||||
session: &mut MechanismData<'_>,
|
||||
input: Option<&[u8]>,
|
||||
writer: &mut dyn Write,
|
||||
) -> Result<State, SessionError> {
|
||||
|
@ -1,12 +1,14 @@
|
||||
use crate::users::Users;
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use miette::{IntoDiagnostic, WrapErr};
|
||||
use std::sync::Arc;
|
||||
use rsasl::callback::{CallbackError, Request, SessionCallback, SessionData};
|
||||
use rsasl::callback::{CallbackError, Request, SessionCallback, SessionData, Context};
|
||||
use rsasl::mechanism::SessionError;
|
||||
use rsasl::prelude::{Mechname, SASLConfig, SASLServer, Session};
|
||||
use rsasl::property::AuthId;
|
||||
use rsasl::prelude::{Mechname, SASLConfig, SASLServer, Session, Validation};
|
||||
use rsasl::property::{AuthId, AuthzId, Password};
|
||||
use rsasl::validate::{Validate, ValidationError};
|
||||
|
||||
use crate::authentication::fabfire::FabFireCardKey;
|
||||
use crate::users::db::User;
|
||||
|
||||
mod fabfire;
|
||||
|
||||
@ -21,7 +23,7 @@ impl Callback {
|
||||
}
|
||||
}
|
||||
impl SessionCallback for Callback {
|
||||
fn callback(&self, session_data: &SessionData, context: &rsasl::callback::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::<AuthId>() {
|
||||
request.satisfy_with::<FabFireCardKey, _>(|| {
|
||||
let user = self.users.get_user(authid).ok_or(CallbackError::NoValue)?;
|
||||
@ -35,48 +37,51 @@ impl SessionCallback for Callback {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*fn validate(
|
||||
&self,
|
||||
session: &mut SessionData,
|
||||
validation: Validation,
|
||||
_mechanism: &Mechname,
|
||||
) -> Result<(), SessionError> {
|
||||
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();
|
||||
match validation {
|
||||
validations::SIMPLE => {
|
||||
let authnid = session
|
||||
.get_property::<AuthId>()
|
||||
.ok_or(SessionError::no_property::<AuthId>())?;
|
||||
tracing::debug!(authid=%authnid, "SIMPLE validation requested");
|
||||
if validate.is::<V>() {
|
||||
match session_data.mechanism().mechanism.as_str() {
|
||||
"PLAIN" => {
|
||||
let authcid = context.get_ref::<AuthId>()
|
||||
.ok_or(ValidationError::MissingRequiredProperty)?;
|
||||
let authzid = context.get_ref::<AuthzId>();
|
||||
let password = context.get_ref::<Password>()
|
||||
.ok_or(ValidationError::MissingRequiredProperty)?;
|
||||
|
||||
if let Some(user) = self.users.get_user(authnid.as_str()) {
|
||||
let passwd = session
|
||||
.get_property::<Password>()
|
||||
.ok_or(SessionError::no_property::<Password>())?;
|
||||
|
||||
if user
|
||||
.check_password(passwd.as_bytes())
|
||||
.map_err(|_e| SessionError::AuthenticationFailure)?
|
||||
{
|
||||
return Ok(());
|
||||
} else {
|
||||
tracing::warn!(authid=%authnid, "AUTH FAILED: bad password");
|
||||
if authzid.is_some() {
|
||||
return Ok(())
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(authid=%authnid, "AUTH FAILED: no such user '{}'", authnid);
|
||||
}
|
||||
|
||||
Err(SessionError::AuthenticationFailure)
|
||||
}
|
||||
_ => {
|
||||
tracing::error!(?validation, "Unimplemented validation requested");
|
||||
Err(SessionError::no_validate(validation))
|
||||
if let Some(user) = self.users.get_user(authcid) {
|
||||
match user.check_password(password) {
|
||||
Ok(true) => {
|
||||
validate.finalize::<V>(user)
|
||||
}
|
||||
Ok(false) => {
|
||||
tracing::warn!(authid=%authcid, "AUTH FAILED: bad password");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!(authid=%authcid, "Bad DB entry: {}", error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(authid=%authcid, "AUTH FAILED: no such user");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct V;
|
||||
impl Validation for V {
|
||||
type Value = User;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Inner {
|
||||
rsasl: Arc<SASLConfig>,
|
||||
}
|
||||
@ -101,7 +106,7 @@ impl AuthenticationHandle {
|
||||
.with_callback(Callback::new(userdb))
|
||||
.unwrap();
|
||||
|
||||
let mechs: Vec<&'static str> = SASLServer::new(config.clone())
|
||||
let mechs: Vec<&'static str> = SASLServer::<V>::new(config.clone())
|
||||
.get_available()
|
||||
.into_iter()
|
||||
.map(|m| m.mechanism.as_str())
|
||||
@ -114,17 +119,14 @@ impl AuthenticationHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self, mechanism: &Mechname) -> miette::Result<Session> {
|
||||
pub fn start(&self, mechanism: &Mechname) -> miette::Result<Session<V>> {
|
||||
Ok(SASLServer::new(self.inner.rsasl.clone())
|
||||
.start_suggested(mechanism)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to start a SASL authentication with the given mechanism")?)
|
||||
}
|
||||
|
||||
pub fn list_available_mechs(&self) -> impl IntoIterator<Item = &Mechname> {
|
||||
pub fn sess(&self) -> SASLServer<V> {
|
||||
SASLServer::new(self.inner.rsasl.clone())
|
||||
.get_available()
|
||||
.into_iter()
|
||||
.map(|m| m.mechanism)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ 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";
|
||||
|
||||
@ -28,7 +29,7 @@ impl Authentication {
|
||||
pub fn new(
|
||||
parent: &Span,
|
||||
mechanism: &Mechname, /* TODO: this is stored in session as well, get it out of there. */
|
||||
session: Session,
|
||||
session: Session<V>,
|
||||
sessionmanager: SessionManager,
|
||||
) -> Self {
|
||||
let span = tracing::info_span!(
|
||||
@ -93,7 +94,7 @@ enum State {
|
||||
InvalidMechanism,
|
||||
Finished,
|
||||
Aborted,
|
||||
Running(Session, SessionManager),
|
||||
Running(Session<V>, SessionManager),
|
||||
}
|
||||
|
||||
impl AuthenticationSystem for Authentication {
|
||||
@ -122,36 +123,35 @@ impl AuthenticationSystem for Authentication {
|
||||
{
|
||||
let data: &[u8] = pry!(pry!(params.get()).get_data());
|
||||
|
||||
let mut out = Cursor::new(Vec::new());
|
||||
let mut out = Vec::new();
|
||||
match session.step(Some(data), &mut out) {
|
||||
Ok(SaslState::Finished(sent)) => {
|
||||
self.state = State::Finished;
|
||||
|
||||
let uid = pry!(session.get_property::<AuthId>().ok_or_else(|| {
|
||||
tracing::warn!("Authentication didn't provide an authid as required.");
|
||||
capnp::Error::failed(
|
||||
"Authentication didn't provide an authid as required".to_string(),
|
||||
)
|
||||
}));
|
||||
let session = pry!(manager.open(&self.span, uid.as_ref()).ok_or_else(|| {
|
||||
tracing::warn!(uid = uid.as_str(), "Failed to lookup the given user");
|
||||
capnp::Error::failed("Failed to lookup the given user".to_string())
|
||||
}));
|
||||
if let Some(user) = session.validation() {
|
||||
let session = manager.open(&self.span, user);
|
||||
response = Response {
|
||||
union_field: "successful",
|
||||
};
|
||||
|
||||
response = Response {
|
||||
union_field: "successful",
|
||||
};
|
||||
let mut builder = builder.init_successful();
|
||||
if sent == MessageSent::Yes {
|
||||
builder.set_additional_data(out.as_slice());
|
||||
}
|
||||
|
||||
let mut builder = builder.init_successful();
|
||||
if sent == MessageSent::Yes {
|
||||
builder.set_additional_data(out.into_inner().as_slice());
|
||||
APISession::build(session, builder)
|
||||
} else {
|
||||
let mut builder = builder.init_failed();
|
||||
builder.set_code(ErrorCode::InvalidCredentials);
|
||||
|
||||
response = Response {
|
||||
union_field: "error",
|
||||
};
|
||||
}
|
||||
|
||||
APISession::build(session, builder)
|
||||
}
|
||||
Ok(SaslState::Running) => {
|
||||
self.state = State::Running(session, manager);
|
||||
builder.set_challenge(out.into_inner().as_slice());
|
||||
builder.set_challenge(out.as_slice());
|
||||
|
||||
response = Response {
|
||||
union_field: "challenge",
|
||||
|
@ -95,9 +95,10 @@ impl bootstrap::Server for BootCap {
|
||||
let builder = result.get();
|
||||
let mechs: Vec<_> = self
|
||||
.authentication
|
||||
.list_available_mechs()
|
||||
.sess()
|
||||
.get_available()
|
||||
.into_iter()
|
||||
.map(|m| m.as_str())
|
||||
.map(|m| m.mechanism.as_str())
|
||||
.collect();
|
||||
let mut mechbuilder = builder.init_mechs(mechs.len() as u32);
|
||||
for (i, m) in mechs.iter().enumerate() {
|
||||
@ -146,7 +147,7 @@ impl bootstrap::Server for BootCap {
|
||||
|
||||
tracing::trace!(params.mechanism = mechanism, "method call");
|
||||
|
||||
let mechname = Mechname::new(mechanism.as_bytes());
|
||||
let mechname = Mechname::parse(mechanism.as_bytes());
|
||||
let auth = if let Ok(mechname) = mechname {
|
||||
if let Ok(session) = self.authentication.start(mechname) {
|
||||
Authentication::new(&self.span, mechname, session, self.sessionmanager.clone())
|
||||
|
@ -56,7 +56,7 @@ impl InitiatorCallbacks {
|
||||
}
|
||||
|
||||
pub fn open_session(&self, uid: &str) -> Option<SessionHandle> {
|
||||
self.sessions.open(&self.span, uid)
|
||||
self.sessions.try_open(&self.span, uid)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use crate::resources::Resource;
|
||||
use crate::users::{db, UserRef};
|
||||
use crate::Users;
|
||||
use tracing::Span;
|
||||
use crate::users::db::User;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SessionManager {
|
||||
@ -16,25 +17,25 @@ impl SessionManager {
|
||||
Self { users, roles }
|
||||
}
|
||||
|
||||
pub fn try_open(&self, parent: &Span, uid: impl AsRef<str>) -> Option<SessionHandle> {
|
||||
self.users.get_user(uid.as_ref()).map(|user| self.open(parent, user))
|
||||
}
|
||||
|
||||
// TODO: make infallible
|
||||
pub fn open(&self, parent: &Span, uid: impl AsRef<str>) -> Option<SessionHandle> {
|
||||
let uid = uid.as_ref();
|
||||
if let Some(user) = self.users.get_user(uid) {
|
||||
let span = tracing::info_span!(
|
||||
target: "bffh::api",
|
||||
parent: parent,
|
||||
"session",
|
||||
uid = uid,
|
||||
);
|
||||
tracing::trace!(parent: &span, uid, ?user, "opening session");
|
||||
Some(SessionHandle {
|
||||
span,
|
||||
users: self.users.clone(),
|
||||
roles: self.roles.clone(),
|
||||
user: UserRef::new(user.id),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
pub fn open(&self, parent: &Span, user: User) -> SessionHandle {
|
||||
let uid = user.id.as_str();
|
||||
let span = tracing::info_span!(
|
||||
target: "bffh::api",
|
||||
parent: parent,
|
||||
"session",
|
||||
uid,
|
||||
);
|
||||
tracing::trace!(parent: &span, uid, ?user, "opening session");
|
||||
SessionHandle {
|
||||
span,
|
||||
users: self.users.clone(),
|
||||
roles: self.roles.clone(),
|
||||
user: UserRef::new(user.id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,11 +34,9 @@ fn hash_pw(pw: &[u8]) -> argon2::Result<String> {
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn check_password(&self, pwd: &[u8]) -> miette::Result<bool> {
|
||||
pub fn check_password(&self, pwd: &[u8]) -> Result<bool, argon2::Error> {
|
||||
if let Some(ref encoded) = self.userdata.passwd {
|
||||
argon2::verify_encoded(encoded, pwd)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Stored password is an invalid string")
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user