From d5b635025dfb2fc1f40b68313c7a12894254e4ba Mon Sep 17 00:00:00 2001 From: Gregor Reitzenstein Date: Tue, 9 Feb 2021 17:15:31 +0000 Subject: [PATCH] Actually set the API user as well --- src/api.rs | 2 +- src/api/auth.rs | 29 +++++++++++++++++++++++------ src/api/machine.rs | 4 ++-- src/connection.rs | 9 +++++---- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/api.rs b/src/api.rs index 4819dac..5628c35 100644 --- a/src/api.rs +++ b/src/api.rs @@ -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 // 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(()) } diff --git a/src/api/auth.rs b/src/api/auth.rs index 5cb3461..5f22951 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -22,19 +22,28 @@ use capnp::capability::{Params, Results, Promise}; use crate::api::Session; pub use crate::schema::auth_capnp; +use crate::db::Databases; use crate::db::pass::PassDB; +use crate::db::user::{Internal as UserDB}; pub struct AppData { passdb: Arc, + userdb: Arc, +} +pub struct SessionData { + session: Arc, } -pub struct SessionData; struct CB; impl Callback for CB { - fn callback(mut sasl: SaslCtx, session: SaslSession, prop: Property) -> libc::c_int { + fn callback(mut sasl: SaslCtx, mut session: SaslSession, prop: Property) -> libc::c_int { let ret = match prop { 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) { None => return ReturnCode::GSASL_NO_AUTHID as libc::c_int, Some(a) => { @@ -52,9 +61,15 @@ impl Callback for CB { let pass = pass.unwrap(); - if let Some(sessiondata) = sasl.retrieve_mut() { - if let Ok(Some(b)) = sessiondata.passdb.check(authid, pass.to_bytes()) { + if let Some(appdata) = sasl.retrieve_mut() { + if let Ok(Some(b)) = appdata.passdb.check(authid, pass.to_bytes()) { 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 } else { ReturnCode::GSASL_AUTHENTICATION_ERROR @@ -81,10 +96,10 @@ pub struct Auth { } impl Auth { - pub fn new(passdb: Arc, session: Arc) -> Self { + pub fn new(dbs: Databases, session: Arc) -> Self { 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); @@ -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 use auth_capnp::request::initial_response::Which; let step_res = match req.get_initial_response().which() { diff --git a/src/api/machine.rs b/src/api/machine.rs index e95e245..b64ed77 100644 --- a/src/api/machine.rs +++ b/src/api/machine.rs @@ -100,10 +100,10 @@ impl write::Server for Write { _results: write::UseResults) -> 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 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 { // TODO: Do something with the token we get returned Ok(_tok) => { diff --git a/src/connection.rs b/src/connection.rs index 56cafd8..00cac66 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -4,6 +4,7 @@ use futures::FutureExt; use slog::Logger; +use smol::lock::Mutex; use smol::net::TcpStream; use crate::error::Result; @@ -18,26 +19,26 @@ use crate::db::access::{AccessControl, Permission}; use crate::db::user::User; use crate::network::Network; -#[derive(Debug, Clone)] +#[derive(Debug)] /// Connection context // TODO this should track over several connections pub struct Session { // Session-spezific log pub log: Logger, - pub user: Option, + pub user: Mutex>, pub accessdb: Arc, } impl Session { pub fn new(log: Logger, accessdb: Arc) -> Self { - let user = None; + let user = Mutex::new(None); Session { log, user, accessdb } } /// Check if the current session has a certain permission pub async fn check_permission>(&self, perm: &P) -> Result { - 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 } else { Ok(false)