mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-14 19:27:56 +01:00
170 lines
5.1 KiB
Rust
170 lines
5.1 KiB
Rust
use api::utils::l10n_string;
|
|
|
|
use std::ops::Deref;
|
|
use capnp::capability::Promise;
|
|
use capnp::Error;
|
|
use capnp_rpc::pry;
|
|
|
|
use rsasl::{rsasl_err_to_str, SASL, Session as SaslSession, Property, ReturnCode};
|
|
use rsasl::session::Step::{Done, NeedsMore};
|
|
|
|
use api::auth::authentication::{
|
|
Server,
|
|
AbortParams,
|
|
AbortResults,
|
|
StepParams,
|
|
StepResults,
|
|
};
|
|
use api::auth::response::{
|
|
Reason,
|
|
Action,
|
|
};
|
|
use crate::users::{UserDB, PassDB};
|
|
|
|
struct Callback;
|
|
|
|
struct AppData {
|
|
userdb: UserDB,
|
|
passdb: PassDB,
|
|
}
|
|
|
|
struct SessionData;
|
|
|
|
impl rsasl::Callback<AppData, SessionData> for Callback {
|
|
fn callback(sasl: &mut SASL<AppData, SessionData>,
|
|
session: &mut SaslSession<SessionData>,
|
|
prop: Property
|
|
) -> Result<(), ReturnCode>
|
|
{
|
|
match prop {
|
|
Property::GSASL_VALIDATE_SIMPLE => {
|
|
// Access the authentication id, i.e. the username to check the password for
|
|
let authcid = session
|
|
.get_property(Property::GSASL_AUTHID)
|
|
.ok_or(rsasl::GSASL_NO_AUTHID)
|
|
.map_err(|_| rsasl::GSASL_NO_AUTHID)
|
|
.and_then(|cstr| cstr.to_str()
|
|
.map_err(|_| rsasl::GSASL_NO_AUTHID))?;
|
|
|
|
// Access the password itself
|
|
let password = session
|
|
.get_property(Property::GSASL_PASSWORD)
|
|
.ok_or(rsasl::GSASL_NO_PASSWORD)
|
|
.and_then(|cstr| cstr.to_str()
|
|
.map_err(|_| rsasl::GSASL_NO_AUTHID))?;
|
|
|
|
let AppData { userdb: _, passdb } = sasl.retrieve_mut()
|
|
.ok_or(rsasl::GSASL_NO_CALLBACK)?;
|
|
|
|
if let Ok(Some(Ok(true))) = passdb.verify_password(authcid, &password.as_bytes()) {
|
|
Ok(())
|
|
} else {
|
|
Err(rsasl::GSASL_AUTHENTICATION_ERROR)
|
|
}
|
|
},
|
|
_ => Err(rsasl::GSASL_NO_CALLBACK),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Authentication {
|
|
state: State<SessionData>,
|
|
}
|
|
|
|
enum State<E> {
|
|
InvalidMechanism,
|
|
Finished,
|
|
Aborted,
|
|
Running(SaslSession<E>)
|
|
}
|
|
|
|
impl Server for Authentication {
|
|
fn step(&mut self, params: StepParams, mut results: StepResults) -> Promise<(), Error> {
|
|
use State::*;
|
|
match self.state {
|
|
InvalidMechanism => {
|
|
let builder = results.get();
|
|
let mut b = builder.init_error();
|
|
b.set_reason(Reason::BadMechanism);
|
|
b.set_action(Action::Permanent);
|
|
},
|
|
Finished => {
|
|
let builder = results.get();
|
|
let mut b = builder.init_error();
|
|
b.set_reason(Reason::Finished);
|
|
b.set_action(Action::Permanent);
|
|
},
|
|
Aborted => {
|
|
let builder = results.get();
|
|
let mut b = builder.init_error();
|
|
b.set_reason(Reason::Aborted);
|
|
b.set_action(Action::Permanent);
|
|
},
|
|
Running(ref mut session) => {
|
|
// TODO: If null what happens?
|
|
let data: &[u8] = pry!(pry!(params.get()).get_data());
|
|
|
|
let mut builder = results.get();
|
|
match session.step(data) {
|
|
Ok(Done(data)) => {
|
|
let mut b = builder.init_successful();
|
|
if !data.is_empty() {
|
|
b.reborrow().set_additional_data(data.deref())
|
|
}
|
|
let mut session_builder = b.init_session();
|
|
let session = super::session::Session::new();
|
|
session.build(&mut session_builder);
|
|
},
|
|
Ok(NeedsMore(data)) => {
|
|
builder.set_challenge(data.deref());
|
|
},
|
|
Err(_) => {
|
|
let mut b = builder.init_error();
|
|
b.set_reason(Reason::Aborted);
|
|
b.set_action(Action::Permanent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Promise::ok(())
|
|
}
|
|
|
|
fn abort(&mut self, _: AbortParams, _: AbortResults) -> Promise<(), Error> {
|
|
Promise::ok(())
|
|
}
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
struct SaslE {
|
|
e: ReturnCode,
|
|
}
|
|
|
|
impl l10n_string::Server for SaslE {
|
|
fn get(&mut self,
|
|
params: l10n_string::GetParams,
|
|
mut results: l10n_string::GetResults
|
|
) -> Promise<(), Error>
|
|
{
|
|
let lang = pry!(pry!(params.get()).get_lang());
|
|
if lang == "en" {
|
|
let mut builder = results.get();
|
|
builder.set_lang("en");
|
|
builder.set_content(rsasl_err_to_str(self.e)
|
|
.unwrap_or("Unknown gsasl error"));
|
|
}
|
|
|
|
Promise::ok(())
|
|
}
|
|
|
|
fn available(
|
|
&mut self,
|
|
_: l10n_string::AvailableParams,
|
|
mut results: l10n_string::AvailableResults
|
|
) -> Promise<(), Error> {
|
|
let builder = results.get();
|
|
let mut langs = builder.init_langs(1);
|
|
langs.set(0, "en");
|
|
Promise::ok(())
|
|
}
|
|
} |