feat: allow to set defaut environment variables when opening a new session
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dysm-rs"
|
name = "dysm-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Dany LE"]
|
authors = ["Dany LE"]
|
||||||
description = "Diya Session Manager"
|
description = "Diya Session Manager"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
# PAM service
|
# PAM service
|
||||||
# the pam service used for authentication
|
# the pam service used for authentication
|
||||||
|
# if not specified, default to diya
|
||||||
pam_service = "diya"
|
pam_service = "diya"
|
||||||
|
|
||||||
# Default session command
|
# Default session command
|
||||||
@@ -14,6 +15,7 @@ pam_service = "diya"
|
|||||||
# any session ruining. Often, this default session will be a login
|
# any session ruining. Often, this default session will be a login
|
||||||
# session that handles the user input and send user
|
# session that handles the user input and send user
|
||||||
# credentials to the daemon via Dbus message
|
# credentials to the daemon via Dbus message
|
||||||
|
# this configuration is mandatory
|
||||||
default_session_command = "/usr/bin/diyac -x /usr/bin/diya-login-shell"
|
default_session_command = "/usr/bin/diyac -x /usr/bin/diya-login-shell"
|
||||||
|
|
||||||
# default session user
|
# default session user
|
||||||
@@ -23,12 +25,21 @@ default_session_user = "xdg"
|
|||||||
|
|
||||||
# if false keep only one session at a time
|
# if false keep only one session at a time
|
||||||
# open a new session will close any previously opened session
|
# open a new session will close any previously opened session
|
||||||
# default true, optional
|
# default true (if not specified), optional
|
||||||
enable_multiple_session = false
|
enable_multiple_session = false
|
||||||
|
|
||||||
# User session command
|
# User session command
|
||||||
# The command to run to start a user session after the
|
# The command to run to start a user session after the
|
||||||
# login session is successful
|
# login session is successful
|
||||||
# the logged in user will own this session
|
# the logged in user will own this session
|
||||||
|
# this configuration is mandatory
|
||||||
|
user_session_command = "/usr/bin/diyac -x /usr/bin/diya-shell"
|
||||||
|
|
||||||
|
# setting environment variables
|
||||||
|
# when opening a session, optional
|
||||||
|
[session.envars]
|
||||||
|
# format key = string value
|
||||||
|
# example
|
||||||
|
DBUS_SESSION_BUS_ADDRESS = "unix:path=/tmp/dbus-1"
|
||||||
|
DBUS_SESSION_BUS_PID = "3598"
|
||||||
|
|
||||||
user_session_command = "/usr/bin/diyac -x /usr/bin/diya-shell"
|
|
||||||
39
src/auth.rs
39
src/auth.rs
@@ -35,6 +35,7 @@ use nix::unistd::execvpe;
|
|||||||
use nix::unistd::setgroups;
|
use nix::unistd::setgroups;
|
||||||
use nix::unistd::User;
|
use nix::unistd::User;
|
||||||
use nix::unistd::{getgrouplist, initgroups, setgid, setuid};
|
use nix::unistd::{getgrouplist, initgroups, setgid, setuid};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@@ -196,6 +197,7 @@ pub trait Session {
|
|||||||
///
|
///
|
||||||
/// - `&self` - Object that implement this trait
|
/// - `&self` - Object that implement this trait
|
||||||
/// - `command` (`&str`) - Command to executed in a new user session
|
/// - `command` (`&str`) - Command to executed in a new user session
|
||||||
|
/// - `envars` (`&HashMap<String, String>`) - environment variable for the new session
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
@@ -205,7 +207,11 @@ pub trait Session {
|
|||||||
///
|
///
|
||||||
/// Any error raised during session opening
|
/// Any error raised during session opening
|
||||||
///
|
///
|
||||||
fn run(&self, command: &str) -> Result<(), Box<dyn std::error::Error>>;
|
fn run(
|
||||||
|
&self,
|
||||||
|
command: &str,
|
||||||
|
envars: &HashMap<String, String>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
/// End the currently running session
|
/// End the currently running session
|
||||||
///
|
///
|
||||||
@@ -234,6 +240,7 @@ trait DropPrivilege {
|
|||||||
///
|
///
|
||||||
/// - `&self` - Object that define this trait
|
/// - `&self` - Object that define this trait
|
||||||
/// - `command` (`&str`) - Command that will be executed un the user session after privilege dropping
|
/// - `command` (`&str`) - Command that will be executed un the user session after privilege dropping
|
||||||
|
/// - `envars` (`&HashMap<String, String>`) - environment variable for the new session
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
@@ -242,7 +249,11 @@ trait DropPrivilege {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
/// Any error
|
/// Any error
|
||||||
///
|
///
|
||||||
fn drop_and_run(&self, command: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn drop_and_run(
|
||||||
|
&self,
|
||||||
|
command: &str,
|
||||||
|
envars: &HashMap<String, String>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
DEBUG!("Run command: {} as user: {}", command, self.username());
|
DEBUG!("Run command: {} as user: {}", command, self.username());
|
||||||
let user =
|
let user =
|
||||||
User::from_name(self.username())?.ok_or(ERR!("Unknown user {}", self.username()))?;
|
User::from_name(self.username())?.ok_or(ERR!("Unknown user {}", self.username()))?;
|
||||||
@@ -258,8 +269,12 @@ trait DropPrivilege {
|
|||||||
let arg_c = CString::new("-c")?;
|
let arg_c = CString::new("-c")?;
|
||||||
let arg_cmd = CString::new(command)?;
|
let arg_cmd = CString::new(command)?;
|
||||||
let args = vec![arg0.as_c_str(), arg_c.as_c_str(), arg_cmd.as_c_str()];
|
let args = vec![arg0.as_c_str(), arg_c.as_c_str(), arg_cmd.as_c_str()];
|
||||||
let env_user = CString::new(format!("USER={}", self.username()))?;
|
|
||||||
let envs = vec![env_user.as_c_str()];
|
let mut envs_c_string = vec![CString::new(format!("USER={}", self.username()))?];
|
||||||
|
for (k, v) in envars {
|
||||||
|
envs_c_string.push(CString::new(format!("{}={}", k, v))?);
|
||||||
|
}
|
||||||
|
let envs: Vec<&CStr> = envs_c_string.iter().map(|e| e.as_c_str()).collect();
|
||||||
execvpe(shell.as_c_str(), &args, &envs)?;
|
execvpe(shell.as_c_str(), &args, &envs)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -511,8 +526,12 @@ impl Session for AnonymousSession {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, command: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn run(
|
||||||
self.drop_and_run(command)
|
&self,
|
||||||
|
command: &str,
|
||||||
|
envars: &HashMap<String, String>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
self.drop_and_run(command, envars)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&self) -> Result<(), Box<dyn std::error::Error>> {
|
fn end(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -535,10 +554,14 @@ impl Session for PamSession {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, command: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn run(
|
||||||
|
&self,
|
||||||
|
command: &str,
|
||||||
|
envars: &HashMap<String, String>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
self.pam_set_credentials(PAM_ESTABLISH_CRED)?
|
self.pam_set_credentials(PAM_ESTABLISH_CRED)?
|
||||||
.pam_open_session()?
|
.pam_open_session()?
|
||||||
.drop_and_run(command)
|
.drop_and_run(command, envars)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&self) -> Result<(), Box<dyn std::error::Error>> {
|
fn end(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
//! the `Display` trait for easy debugging and logging.
|
//! the `Display` trait for easy debugging and logging.
|
||||||
use crate::INFO;
|
use crate::INFO;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::path::PathBuf;
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
|
||||||
/// Configuration
|
/// Configuration
|
||||||
@@ -25,6 +25,8 @@ pub struct Configuration {
|
|||||||
user_session_command: String,
|
user_session_command: String,
|
||||||
/// flag to enable multiple session
|
/// flag to enable multiple session
|
||||||
enable_multiple_session: bool,
|
enable_multiple_session: bool,
|
||||||
|
/// Session environment variables
|
||||||
|
session_envars: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
@@ -77,6 +79,23 @@ impl Configuration {
|
|||||||
.get("enable_multiple_session")
|
.get("enable_multiple_session")
|
||||||
.and_then(Value::as_bool)
|
.and_then(Value::as_bool)
|
||||||
.unwrap_or(true),
|
.unwrap_or(true),
|
||||||
|
session_envars: table
|
||||||
|
.get("session")
|
||||||
|
.and_then(Value::as_table)
|
||||||
|
.and_then(|table| table.get("envars"))
|
||||||
|
.and_then(Value::as_table)
|
||||||
|
.and_then(|table| {
|
||||||
|
Some(
|
||||||
|
table
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(k, v)| {
|
||||||
|
v.as_str()
|
||||||
|
.and_then(|value| Some((k.to_string(), value.to_string())))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(HashMap::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +139,14 @@ impl Configuration {
|
|||||||
pub fn enable_multiple_session(&self) -> bool {
|
pub fn enable_multiple_session(&self) -> bool {
|
||||||
self.enable_multiple_session
|
self.enable_multiple_session
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Session default environment variables
|
||||||
|
///
|
||||||
|
/// # Returs
|
||||||
|
/// HashMap<String, String>
|
||||||
|
pub fn session_envars(&self) -> &HashMap<String, String> {
|
||||||
|
&self.session_envars
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Configuration {
|
impl fmt::Display for Configuration {
|
||||||
@@ -141,6 +168,10 @@ impl fmt::Display for Configuration {
|
|||||||
" - Enable multiple session: {}",
|
" - Enable multiple session: {}",
|
||||||
self.enable_multiple_session
|
self.enable_multiple_session
|
||||||
)?;
|
)?;
|
||||||
|
writeln!(f, " - Session environment variables:")?;
|
||||||
|
for (k, v) in &self.session_envars {
|
||||||
|
writeln!(f, " + {} = '{}'", k, v)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ impl SessionManager {
|
|||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
DEBUG!("Authenticate success");
|
DEBUG!("Authenticate success");
|
||||||
invocation.return_value(Some(&Variant::tuple_from_iter([true.to_variant()])));
|
invocation.return_value(Some(&Variant::tuple_from_iter([true.to_variant()])));
|
||||||
if ! self.config.enable_multiple_session() {
|
if !self.config.enable_multiple_session() {
|
||||||
self.drop_all_sessions();
|
self.drop_all_sessions();
|
||||||
}
|
}
|
||||||
match self.open_session(self.config.user_session_command(), &session) {
|
match self.open_session(self.config.user_session_command(), &session) {
|
||||||
@@ -445,7 +445,9 @@ impl SessionManager {
|
|||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
ForkResult::Child => {
|
ForkResult::Child => {
|
||||||
session.run(command).expect("This should not happend");
|
session
|
||||||
|
.run(command, self.config.session_envars())
|
||||||
|
.expect("This should not happend");
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/tests.rs
12
src/tests.rs
@@ -20,4 +20,16 @@ fn test_configuration_loading() {
|
|||||||
"/usr/bin/diyac -x /usr/bin/diya-shell"
|
"/usr/bin/diyac -x /usr/bin/diya-shell"
|
||||||
);
|
);
|
||||||
assert_eq!(config.enable_multiple_session(), false);
|
assert_eq!(config.enable_multiple_session(), false);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
config
|
||||||
|
.session_envars()
|
||||||
|
.get("DBUS_SESSION_BUS_ADDRESS")
|
||||||
|
.unwrap(),
|
||||||
|
"unix:path=/tmp/dbus-1"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
config.session_envars().get("DBUS_SESSION_BUS_PID").unwrap(),
|
||||||
|
"3598"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user