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
// 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(())
}

View File

@ -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<PassDB>,
userdb: Arc<UserDB>,
}
pub struct SessionData {
session: Arc<Session>,
}
pub struct SessionData;
struct 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 {
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<AppData, SessionData> 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<PassDB>, session: Arc<Session>) -> Self {
pub fn new(dbs: Databases, session: Arc<Session>) -> 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() {

View File

@ -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) => {

View File

@ -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<User>,
pub user: Mutex<Option<User>>,
pub accessdb: Arc<AccessControl>,
}
impl Session {
pub fn new(log: Logger, accessdb: Arc<AccessControl>) -> 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<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
} else {
Ok(false)