Actually set the API user as well

This commit is contained in:
Gregor Reitzenstein 2021-02-09 17:15:31 +00:00
parent 38eb26b684
commit d5b635025d
4 changed files with 31 additions and 13 deletions

View File

@ -39,7 +39,7 @@ impl connection_capnp::bootstrap::Server for Bootstrap {
// TODO: When should we allow multiple auth and how do me make sure that does not leak // TODO: When should we allow multiple auth and how do me make sure that does not leak
// priviledges (e.g. due to previously issues caps)? // priviledges (e.g. due to previously issues caps)?
res.get().set_auth(capnp_rpc::new_client(auth::Auth::new(self.db.passdb.clone(), self.session.clone()))); res.get().set_auth(capnp_rpc::new_client(auth::Auth::new(self.db.clone(), self.session.clone())));
Promise::ok(()) Promise::ok(())
} }

View File

@ -22,19 +22,28 @@ use capnp::capability::{Params, Results, Promise};
use crate::api::Session; use crate::api::Session;
pub use crate::schema::auth_capnp; pub use crate::schema::auth_capnp;
use crate::db::Databases;
use crate::db::pass::PassDB; use crate::db::pass::PassDB;
use crate::db::user::{Internal as UserDB};
pub struct AppData { pub struct AppData {
passdb: Arc<PassDB>, passdb: Arc<PassDB>,
userdb: Arc<UserDB>,
}
pub struct SessionData {
session: Arc<Session>,
} }
pub struct SessionData;
struct CB; struct CB;
impl Callback<AppData, SessionData> for CB { impl Callback<AppData, SessionData> for CB {
fn callback(mut sasl: SaslCtx<AppData, SessionData>, session: SaslSession<SessionData>, prop: Property) -> libc::c_int { fn callback(mut sasl: SaslCtx<AppData, SessionData>, mut session: SaslSession<SessionData>, prop: Property) -> libc::c_int {
let ret = match prop { let ret = match prop {
Property::GSASL_VALIDATE_SIMPLE => { Property::GSASL_VALIDATE_SIMPLE => {
// FIXME: get_property and retrive_mut can't be used interleaved but that's
// technically safe.
let cap_session = session.retrieve_mut().map(|sd| sd.session.clone());
let authid = match session.get_property(Property::GSASL_AUTHID) { let authid = match session.get_property(Property::GSASL_AUTHID) {
None => return ReturnCode::GSASL_NO_AUTHID as libc::c_int, None => return ReturnCode::GSASL_NO_AUTHID as libc::c_int,
Some(a) => { Some(a) => {
@ -52,9 +61,15 @@ impl Callback<AppData, SessionData> for CB {
let pass = pass.unwrap(); let pass = pass.unwrap();
if let Some(sessiondata) = sasl.retrieve_mut() { if let Some(appdata) = sasl.retrieve_mut() {
if let Ok(Some(b)) = sessiondata.passdb.check(authid, pass.to_bytes()) { if let Ok(Some(b)) = appdata.passdb.check(authid, pass.to_bytes()) {
if b { if b {
if let Some(s) = cap_session {
if let Ok(Some(user)) = appdata.userdb.get_user(authid) {
s.user.try_lock().unwrap().replace(user);
}
}
ReturnCode::GSASL_OK ReturnCode::GSASL_OK
} else { } else {
ReturnCode::GSASL_AUTHENTICATION_ERROR ReturnCode::GSASL_AUTHENTICATION_ERROR
@ -81,10 +96,10 @@ pub struct Auth {
} }
impl Auth { impl Auth {
pub fn new(passdb: Arc<PassDB>, session: Arc<Session>) -> Self { pub fn new(dbs: Databases, session: Arc<Session>) -> Self {
let mut ctx = SASL::new().unwrap(); let mut ctx = SASL::new().unwrap();
let appdata = Box::new(AppData { passdb }); let appdata = Box::new(AppData { passdb: dbs.passdb.clone(), userdb: dbs.userdb.clone() });
ctx.store(appdata); ctx.store(appdata);
@ -141,6 +156,8 @@ impl auth_capnp::authentication::Server for Auth {
}), }),
}; };
session.store(Box::new(SessionData { session: self.session.clone() }));
// If the client has provided initial data go use that // If the client has provided initial data go use that
use auth_capnp::request::initial_response::Which; use auth_capnp::request::initial_response::Which;
let step_res = match req.get_initial_response().which() { let step_res = match req.get_initial_response().which() {

View File

@ -100,10 +100,10 @@ impl write::Server for Write {
_results: write::UseResults) _results: write::UseResults)
-> Promise<(), Error> -> Promise<(), Error>
{ {
let uid = self.0.session.user.as_ref().map(|u| u.id.clone()); let uid = self.0.session.user.try_lock().unwrap().as_ref().map(|u| u.id.clone());
let new_state = MachineState::used(uid.clone()); let new_state = MachineState::used(uid.clone());
let this = self.0.clone(); let this = self.0.clone();
let f = this.machine.request_state_change(this.session.user.as_ref(), new_state) let f = this.machine.request_state_change(this.session.user.try_lock().unwrap().as_ref(), new_state)
.map(|res_token| match res_token { .map(|res_token| match res_token {
// TODO: Do something with the token we get returned // TODO: Do something with the token we get returned
Ok(_tok) => { Ok(_tok) => {

View File

@ -4,6 +4,7 @@ use futures::FutureExt;
use slog::Logger; use slog::Logger;
use smol::lock::Mutex;
use smol::net::TcpStream; use smol::net::TcpStream;
use crate::error::Result; use crate::error::Result;
@ -18,26 +19,26 @@ use crate::db::access::{AccessControl, Permission};
use crate::db::user::User; use crate::db::user::User;
use crate::network::Network; use crate::network::Network;
#[derive(Debug, Clone)] #[derive(Debug)]
/// Connection context /// Connection context
// TODO this should track over several connections // TODO this should track over several connections
pub struct Session { pub struct Session {
// Session-spezific log // Session-spezific log
pub log: Logger, pub log: Logger,
pub user: Option<User>, pub user: Mutex<Option<User>>,
pub accessdb: Arc<AccessControl>, pub accessdb: Arc<AccessControl>,
} }
impl Session { impl Session {
pub fn new(log: Logger, accessdb: Arc<AccessControl>) -> Self { pub fn new(log: Logger, accessdb: Arc<AccessControl>) -> Self {
let user = None; let user = Mutex::new(None);
Session { log, user, accessdb } Session { log, user, accessdb }
} }
/// Check if the current session has a certain permission /// Check if the current session has a certain permission
pub async fn check_permission<P: AsRef<Permission>>(&self, perm: &P) -> Result<bool> { pub async fn check_permission<P: AsRef<Permission>>(&self, perm: &P) -> Result<bool> {
if let Some(user) = self.user.as_ref() { if let Some(user) = self.user.lock().await.as_ref() {
self.accessdb.check(&user.data, perm).await self.accessdb.check(&user.data, perm).await
} else { } else {
Ok(false) Ok(false)