mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-26 08:34:55 +01:00
More Schema updates
This commit is contained in:
parent
91a17e6b57
commit
87102b9f5d
2
schema
2
schema
@ -1 +1 @@
|
|||||||
Subproject commit 9fb856a4dbe8f1e68c77afa3dbff606a27342e7c
|
Subproject commit 95fa6c5eabc8fded8b69ce8e3e87bc5d9c37c027
|
117
src/auth.rs
117
src/auth.rs
@ -12,15 +12,18 @@ use rsasl::{
|
|||||||
ReturnCode,
|
ReturnCode,
|
||||||
Callback,
|
Callback,
|
||||||
SaslCtx,
|
SaslCtx,
|
||||||
|
Step,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use capnp::capability::{Params, Results, Promise};
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::config::Settings;
|
use crate::config::Settings;
|
||||||
|
|
||||||
pub use crate::schema::auth_capnp;
|
pub use crate::schema::auth_capnp;
|
||||||
|
|
||||||
struct AppData;
|
pub struct AppData;
|
||||||
struct SessionData;
|
pub struct SessionData;
|
||||||
|
|
||||||
struct CB;
|
struct CB;
|
||||||
impl Callback<AppData, SessionData> for CB {
|
impl Callback<AppData, SessionData> for CB {
|
||||||
@ -63,6 +66,96 @@ impl Auth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use auth_capnp::authentication::*;
|
||||||
|
impl auth_capnp::authentication::Server for Auth {
|
||||||
|
fn mechanisms(&mut self,
|
||||||
|
_: Params<mechanisms_params::Owned>,
|
||||||
|
mut res: Results<mechanisms_results::Owned>
|
||||||
|
) -> Promise<(), capnp::Error> {
|
||||||
|
let mechs = match self.ctx.server_mech_list() {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => {
|
||||||
|
return Promise::err(capnp::Error {
|
||||||
|
kind: capnp::ErrorKind::Failed,
|
||||||
|
description: format!("SASL Failure: {}", e),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let mechvec: Vec<&str> = mechs.iter().collect();
|
||||||
|
|
||||||
|
let mut res_mechs = res.get().init_mechs(mechvec.len() as u32);
|
||||||
|
for (i, m) in mechvec.into_iter().enumerate() {
|
||||||
|
res_mechs.set(i as u32, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise::ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: return Outcome instead of exceptions
|
||||||
|
fn start(&mut self,
|
||||||
|
params: Params<start_params::Owned>,
|
||||||
|
mut res: Results<start_results::Owned>
|
||||||
|
) -> Promise<(), capnp::Error> {
|
||||||
|
let req = pry!(pry!(params.get()).get_request());
|
||||||
|
|
||||||
|
// Extract the MECHANISM the client wants to use and start a session.
|
||||||
|
// Or fail at that and thrown an exception TODO: return Outcome
|
||||||
|
let mech = pry!(req.get_mechanism());
|
||||||
|
let mut session = match self.ctx.server_start(mech) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) =>
|
||||||
|
return Promise::err(capnp::Error {
|
||||||
|
kind: capnp::ErrorKind::Failed,
|
||||||
|
description: format!("SASL error: {}", e),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the client has provided initial data go use that
|
||||||
|
use auth_capnp::request::initial_response::Which;
|
||||||
|
let step_res = match req.get_initial_response().which() {
|
||||||
|
Err(capnp::NotInSchema(_)) =>
|
||||||
|
return Promise::err(capnp::Error {
|
||||||
|
kind: capnp::ErrorKind::Failed,
|
||||||
|
description: "Initial data is badly formatted".to_string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Ok(Which::None(_)) => {
|
||||||
|
// FIXME: Actually this needs to indicate NO data instead of SOME data of 0 length
|
||||||
|
session.step(&[])
|
||||||
|
}
|
||||||
|
Ok(Which::Initial(data)) => {
|
||||||
|
session.step(pry!(data))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The step may either return an error, a success or the need for more data
|
||||||
|
match step_res {
|
||||||
|
Ok(Step::Done(b)) => {
|
||||||
|
use auth_capnp::response::Result;
|
||||||
|
|
||||||
|
let mut outcome = pry!(res.get().get_response()).init_outcome();
|
||||||
|
outcome.reborrow().set_result(Result::Successful);
|
||||||
|
if b.len() != 0 {
|
||||||
|
outcome.init_additional_data().set_additional(&b);
|
||||||
|
}
|
||||||
|
Promise::ok(())
|
||||||
|
},
|
||||||
|
Ok(Step::NeedsMore(b)) => {
|
||||||
|
pry!(res.get().get_response()).set_challence(&b);
|
||||||
|
Promise::ok(())
|
||||||
|
}
|
||||||
|
// TODO: This should really be an outcome because this is failed auth just as much atm.
|
||||||
|
Err(e) =>
|
||||||
|
return Promise::err(capnp::Error {
|
||||||
|
kind: capnp::ErrorKind::Failed,
|
||||||
|
description: format!("SASL error: {}", e),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn init(log: Logger, config: Settings) -> Result<Auth> {
|
pub async fn init(log: Logger, config: Settings) -> Result<Auth> {
|
||||||
Ok(Auth::new())
|
Ok(Auth::new())
|
||||||
}
|
}
|
||||||
@ -82,9 +175,19 @@ struct AuthCId(String);
|
|||||||
/// This identity is internal to FabAccess and completely independent from the authentication
|
/// This identity is internal to FabAccess and completely independent from the authentication
|
||||||
/// method or source
|
/// method or source
|
||||||
struct AuthZId {
|
struct AuthZId {
|
||||||
|
/// Main User ID. Generally an user name or similar
|
||||||
uid: String,
|
uid: String,
|
||||||
|
/// Sub user ID.
|
||||||
|
///
|
||||||
|
/// Can change scopes for permissions, e.g. having a +admin account with more permissions than
|
||||||
|
/// the default account and +dashboard et.al. accounts that have restricted permissions for
|
||||||
|
/// their applications
|
||||||
subuid: String,
|
subuid: String,
|
||||||
domain: String,
|
/// Realm this account originates.
|
||||||
|
///
|
||||||
|
/// The Realm is usually described by a domain name but local policy may dictate an unrelated
|
||||||
|
/// mapping
|
||||||
|
realm: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// What is a man?! A miserable little pile of secrets!
|
// What is a man?! A miserable little pile of secrets!
|
||||||
@ -93,7 +196,7 @@ struct AuthZId {
|
|||||||
/// This struct contains the user as is passed to the actual authentication/authorization
|
/// This struct contains the user as is passed to the actual authentication/authorization
|
||||||
/// subsystems
|
/// subsystems
|
||||||
///
|
///
|
||||||
struct User {
|
pub struct User {
|
||||||
/// Contains the Authentication ID used
|
/// Contains the Authentication ID used
|
||||||
///
|
///
|
||||||
/// The authentication ID is an identifier for the authentication exchange. This is different
|
/// The authentication ID is an identifier for the authentication exchange. This is different
|
||||||
@ -133,11 +236,13 @@ struct User {
|
|||||||
// b) the given authcid may authenticate as the given authzid. E.g. if a given client certificate
|
// b) the given authcid may authenticate as the given authzid. E.g. if a given client certificate
|
||||||
// has been configured for that user, if a GSSAPI user maps to a given user,
|
// has been configured for that user, if a GSSAPI user maps to a given user,
|
||||||
|
|
||||||
enum AuthError {
|
pub enum AuthError {
|
||||||
/// Authentication ID is bad/unknown/..
|
/// Authentication ID is bad/unknown/..
|
||||||
BadAuthcid,
|
BadAuthcid,
|
||||||
/// Authorization ID is bad/unknown/..
|
/// Authorization ID is unknown/..
|
||||||
BadAuthzid,
|
BadAuthzid,
|
||||||
|
/// Authorization ID is not of form user+uid@realm
|
||||||
|
MalformedAuthzid,
|
||||||
/// User may not use that authorization id
|
/// User may not use that authorization id
|
||||||
NotAllowedAuthzid,
|
NotAllowedAuthzid,
|
||||||
|
|
||||||
|
@ -69,11 +69,9 @@ pub async fn handle_connection(log: Logger, mut stream: TcpStream) -> Result<()>
|
|||||||
match w {
|
match w {
|
||||||
Request(Ok(r)) => {
|
Request(Ok(r)) => {
|
||||||
let m = r.get_mechanism().unwrap();
|
let m = r.get_mechanism().unwrap();
|
||||||
println!("Client wants to AUTH using {:?}",
|
println!("Client wants to AUTH using {:?}", &m);
|
||||||
m);
|
|
||||||
let cm = std::ffi::CString::new(m).unwrap();
|
|
||||||
let mut sasl = auth::Auth::new();
|
let mut sasl = auth::Auth::new();
|
||||||
let mut sess = sasl.ctx.server_start(&cm).unwrap();
|
let mut sess = sasl.ctx.server_start(&m).unwrap();
|
||||||
|
|
||||||
use crate::auth::auth_capnp::request::initial_response::*;
|
use crate::auth::auth_capnp::request::initial_response::*;
|
||||||
match r.get_initial_response().which() {
|
match r.get_initial_response().which() {
|
||||||
|
Loading…
Reference in New Issue
Block a user