Add ability to drop privileges after binding to port
This commit is contained in:
parent
3b596de06f
commit
7ed3a9e52d
7 changed files with 78 additions and 4 deletions
BIN
Cargo.lock
generated
BIN
Cargo.lock
generated
Binary file not shown.
|
@ -1,6 +1,10 @@
|
||||||
port = 4419
|
port = 4419
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
|
|
||||||
|
# Set to a user AND a group to drop privileges to after binding to the port
|
||||||
|
#user = "emgauwa"
|
||||||
|
#group = "emgauwa"
|
||||||
|
|
||||||
# Leave empty to allow all origins (will always respond with Origin and not "*")
|
# Leave empty to allow all origins (will always respond with Origin and not "*")
|
||||||
#origins = ["http://localhost", "https://emgauwa.app"]
|
#origins = ["http://localhost", "https://emgauwa.app"]
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
|
use std::net::TcpListener;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use actix_web::middleware::TrailingSlash;
|
use actix_web::middleware::TrailingSlash;
|
||||||
use actix_web::{middleware, web, App, HttpServer};
|
use actix_web::{middleware, web, App, HttpServer};
|
||||||
use emgauwa_lib::handlers;
|
use emgauwa_lib::handlers;
|
||||||
|
use emgauwa_lib::utils::drop_privileges;
|
||||||
use log::{trace, LevelFilter};
|
use log::{trace, LevelFilter};
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
|
@ -22,6 +24,18 @@ async fn main() -> std::io::Result<()> {
|
||||||
.init()
|
.init()
|
||||||
.expect("Error initializing logger.");
|
.expect("Error initializing logger.");
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
let pool = emgauwa_lib::db::init(&settings.database).await;
|
let pool = emgauwa_lib::db::init(&settings.database).await;
|
||||||
|
|
||||||
log::info!("Starting server on {}:{}", settings.host, settings.port);
|
log::info!("Starting server on {}:{}", settings.host, settings.port);
|
||||||
|
@ -55,7 +69,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
.service(handlers::v1::schedules::delete)
|
.service(handlers::v1::schedules::delete)
|
||||||
.service(handlers::v1::ws::controllers::index)
|
.service(handlers::v1::ws::controllers::index)
|
||||||
})
|
})
|
||||||
.bind(format!("{}:{}", settings.host, settings.port))?
|
.listen(listener)?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,14 @@ pub struct Logging {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub database: String,
|
pub database: String,
|
||||||
pub port: u16,
|
|
||||||
pub host: String,
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
pub origins: Vec<String>,
|
pub origins: Vec<String>,
|
||||||
|
|
||||||
|
pub user: String,
|
||||||
|
pub group: String,
|
||||||
|
|
||||||
pub logging: Logging,
|
pub logging: Logging,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +29,14 @@ impl Default for Settings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Settings {
|
Settings {
|
||||||
database: String::from("sqlite://emgauwa-core.sqlite"),
|
database: String::from("sqlite://emgauwa-core.sqlite"),
|
||||||
port: constants::DEFAULT_PORT,
|
|
||||||
host: String::from("127.0.0.1"),
|
host: String::from("127.0.0.1"),
|
||||||
|
port: constants::DEFAULT_PORT,
|
||||||
origins: Vec::new(),
|
origins: Vec::new(),
|
||||||
|
|
||||||
|
user: String::from(""),
|
||||||
|
group: String::from(""),
|
||||||
|
|
||||||
logging: Logging::default(),
|
logging: Logging::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,4 @@ libsqlite3-sys = { version = "*", features = ["bundled"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
uuid = "1.6"
|
uuid = "1.6"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
libc = "0.2"
|
||||||
|
|
|
@ -6,7 +6,6 @@ use actix::{Actor, StreamHandler};
|
||||||
use actix_web::{get, web, HttpRequest, HttpResponse};
|
use actix_web::{get, web, HttpRequest, HttpResponse};
|
||||||
use actix_web_actors::ws;
|
use actix_web_actors::ws;
|
||||||
use actix_web_actors::ws::ProtocolError;
|
use actix_web_actors::ws::ProtocolError;
|
||||||
use futures::FutureExt;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use sqlx::pool::PoolConnection;
|
use sqlx::pool::PoolConnection;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
|
|
||||||
pub fn load_settings<T>(config_name: &str, env_prefix: &str) -> T
|
pub fn load_settings<T>(config_name: &str, env_prefix: &str) -> T
|
||||||
where
|
where
|
||||||
for<'de> T: serde::Deserialize<'de>,
|
for<'de> T: serde::Deserialize<'de>,
|
||||||
|
@ -16,3 +19,46 @@ where
|
||||||
.try_deserialize::<T>()
|
.try_deserialize::<T>()
|
||||||
.expect("Error reading settings")
|
.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(())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue