diff --git a/Cargo.lock b/Cargo.lock index 1e11455..7313ed1 100644 Binary files a/Cargo.lock and b/Cargo.lock differ diff --git a/emgauwa-core.toml b/emgauwa-core.toml index 6b879a4..e2f54d6 100644 --- a/emgauwa-core.toml +++ b/emgauwa-core.toml @@ -1,7 +1,7 @@ port = 4419 host = "127.0.0.1" -# Set to a user AND a group to drop privileges to after binding to the port +# Set to a user and a group to drop privileges to after binding to the port #user = "emgauwa" #group = "emgauwa" diff --git a/emgauwa-core/Cargo.toml b/emgauwa-core/Cargo.toml index c48d1b1..72e3c00 100644 --- a/emgauwa-core/Cargo.toml +++ b/emgauwa-core/Cargo.toml @@ -23,3 +23,4 @@ serde_json = "1.0" serde_derive = "1.0" futures = "0.3.29" +libc = "0.2" diff --git a/emgauwa-core/src/main.rs b/emgauwa-core/src/main.rs index e310aa6..f07aca9 100644 --- a/emgauwa-core/src/main.rs +++ b/emgauwa-core/src/main.rs @@ -2,14 +2,15 @@ use actix_cors::Cors; use std::net::TcpListener; use std::str::FromStr; +use crate::utils::drop_privileges; use actix_web::middleware::TrailingSlash; use actix_web::{middleware, web, App, HttpServer}; use emgauwa_lib::handlers; -use emgauwa_lib::utils::drop_privileges; use log::{trace, LevelFilter}; use simple_logger::SimpleLogger; mod settings; +mod utils; #[actix_web::main] async fn main() -> std::io::Result<()> { @@ -27,23 +28,13 @@ async fn main() -> std::io::Result<()> { let listener = TcpListener::bind(format!("{}:{}", settings.host, settings.port)) .expect("Error creating listener"); - if !settings.user.is_empty() && !settings.group.is_empty() { - log::info!( - "Dropping privileges to {}:{}", - settings.user, - settings.group - ); - drop_privileges(&settings.user, &settings.group).expect("Error dropping privileges"); - } + drop_privileges(&settings).expect("Error dropping privileges"); let pool = emgauwa_lib::db::init(&settings.database).await; log::info!("Starting server on {}:{}", settings.host, settings.port); HttpServer::new(move || { - let cors = Cors::default() - .allow_any_method() - .allow_any_header() - .max_age(3600); + let cors = Cors::default().allow_any_method().allow_any_header(); let origins = settings.origins.clone(); let cors = match settings.origins.is_empty() { diff --git a/emgauwa-core/src/utils.rs b/emgauwa-core/src/utils.rs new file mode 100644 index 0000000..4328baf --- /dev/null +++ b/emgauwa-core/src/utils.rs @@ -0,0 +1,64 @@ +use crate::settings::Settings; +use std::ffi::CString; +use std::io::{Error, ErrorKind}; + +// https://blog.lxsang.me/post/id/28.0 +pub fn drop_privileges(settings: &Settings) -> Result<(), Error> { + log::info!( + "Dropping privileges to {}:{}", + settings.user, + settings.group + ); + + // the group id need to be set first, because, when the user privileges drop, + // we are unable to drop the group privileges + if !settings.group.is_empty() { + drop_privileges_group(&settings.group)?; + } + if !settings.user.is_empty() { + drop_privileges_user(&settings.user)?; + } + Ok(()) +} + +fn drop_privileges_group(group: &str) -> Result<(), Error> { + // get the gid from username + if let Ok(cstr) = CString::new(group.as_bytes()) { + let p = unsafe { libc::getgrnam(cstr.as_ptr()) }; + if p.is_null() { + eprintln!("Unable to getgrnam of group: {}", group); + return Err(Error::last_os_error()); + } + if unsafe { libc::setgid((*p).gr_gid) } != 0 { + eprintln!("Unable to setgid of group: {}", group); + return Err(Error::last_os_error()); + } + } else { + return Err(Error::new( + ErrorKind::Other, + "Cannot create CString from String (group)!", + )); + } + Ok(()) +} + +fn drop_privileges_user(user: &str) -> Result<(), Error> { + // get the uid from username + if let Ok(cstr) = CString::new(user.as_bytes()) { + let p = unsafe { libc::getpwnam(cstr.as_ptr()) }; + if p.is_null() { + eprintln!("Unable to getpwnam of user: {}", user); + return Err(Error::last_os_error()); + } + if unsafe { libc::setuid((*p).pw_uid) } != 0 { + eprintln!("Unable to setuid of user: {}", user); + return Err(Error::last_os_error()); + } + } else { + return Err(Error::new( + ErrorKind::Other, + "Cannot create CString from String (user)!", + )); + } + Ok(()) +} diff --git a/emgauwa-lib/Cargo.toml b/emgauwa-lib/Cargo.toml index dad6bfe..f79008e 100644 --- a/emgauwa-lib/Cargo.toml +++ b/emgauwa-lib/Cargo.toml @@ -24,4 +24,3 @@ libsqlite3-sys = { version = "*", features = ["bundled"] } log = "0.4" uuid = "1.6" futures = "0.3" -libc = "0.2" diff --git a/emgauwa-lib/src/utils.rs b/emgauwa-lib/src/utils.rs index c3901fd..b74f68b 100644 --- a/emgauwa-lib/src/utils.rs +++ b/emgauwa-lib/src/utils.rs @@ -1,6 +1,3 @@ -use std::ffi::CString; -use std::io::{Error, ErrorKind}; - pub fn load_settings(config_name: &str, env_prefix: &str) -> T where for<'de> T: serde::Deserialize<'de>, @@ -19,46 +16,3 @@ where .try_deserialize::() .expect("Error reading settings") } - -// https://blog.lxsang.me/post/id/28.0 -pub fn drop_privileges(user: &str, group: &str) -> Result<(), Error> { - // the group id need to be set first, otherwise, - // when the user privileges drop, it is unable to - // drop the group privileges - // get the gid from username - if let Ok(cstr) = CString::new(group.as_bytes()) { - let p = unsafe { libc::getgrnam(cstr.as_ptr()) }; - if p.is_null() { - eprintln!("Unable to getgrnam of group: {}", group); - return Err(Error::last_os_error()); - } - if unsafe { libc::setgid((*p).gr_gid) } != 0 { - eprintln!("Unable to setgid of group: {}", group); - return Err(Error::last_os_error()); - } - } else { - return Err(Error::new( - ErrorKind::Other, - "Cannot create CString from String (group)!", - )); - } - // drop the user privileges - // get the uid from username - if let Ok(cstr) = CString::new(user.as_bytes()) { - let p = unsafe { libc::getpwnam(cstr.as_ptr()) }; - if p.is_null() { - eprintln!("Unable to getpwnam of user: {}", user); - return Err(Error::last_os_error()); - } - if unsafe { libc::setuid((*p).pw_uid) } != 0 { - eprintln!("Unable to setuid of user: {}", user); - return Err(Error::last_os_error()); - } - } else { - return Err(Error::new( - ErrorKind::Other, - "Cannot create CString from String (user)!", - )); - } - Ok(()) -}