also set dumpable to 0, minor improvements
This commit is contained in:
parent
f445ce7b1f
commit
bb8de3b6c7
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1,3 +1,5 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.43"
|
version = "0.2.43"
|
||||||
|
79
src/main.rs
79
src/main.rs
@ -1,10 +1,10 @@
|
|||||||
use std::env::Args;
|
use std::env::Args;
|
||||||
use std::io::{Error, ErrorKind};
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::io::BufRead;
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
use libc::passwd;
|
use libc::passwd;
|
||||||
@ -35,7 +35,6 @@ impl Entry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Passwd {
|
struct Passwd {
|
||||||
pw_name: String,
|
pw_name: String,
|
||||||
pw_passwd: String,
|
pw_passwd: String,
|
||||||
@ -46,15 +45,11 @@ struct Passwd {
|
|||||||
pw_shell: String,
|
pw_shell: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn initgroups(user: &str, group: libc::gid_t) -> std::io::Result<()> {
|
fn initgroups(user: &str, group: libc::gid_t) -> std::io::Result<()> {
|
||||||
let userarg = CString::new(user);
|
let userarg = CString::new(user);
|
||||||
return errnowrapper(unsafe {
|
return errnowrapper(unsafe { libc::initgroups(userarg.unwrap().as_ptr(), group) });
|
||||||
libc::initgroups(userarg.unwrap().as_ptr(), group)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn errnowrapper(ret: libc::c_int) -> std::io::Result<()> {
|
fn errnowrapper(ret: libc::c_int) -> std::io::Result<()> {
|
||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
return Err(Error::last_os_error());
|
return Err(Error::last_os_error());
|
||||||
@ -95,7 +90,6 @@ fn getpwnam(username: &str) -> std::io::Result<Passwd> {
|
|||||||
pw_shell: getstr((*pwnamresult).pw_shell),
|
pw_shell: getstr((*pwnamresult).pw_shell),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> {
|
fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> {
|
||||||
@ -119,7 +113,6 @@ fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn usage() {
|
fn usage() {
|
||||||
println!("Usage: raou ENRTYNAME");
|
println!("Usage: raou ENRTYNAME");
|
||||||
}
|
}
|
||||||
@ -141,13 +134,12 @@ fn assign(entry: &mut Entry, key: &str, value: &str) {
|
|||||||
"env_vars" => add_multi(&mut entry.inherit_envs, val),
|
"env_vars" => add_multi(&mut entry.inherit_envs, val),
|
||||||
"argv0" => entry.argv0 = val,
|
"argv0" => entry.argv0 = val,
|
||||||
"target_user" => entry.dest_user = val,
|
"target_user" => entry.dest_user = val,
|
||||||
"allow_args" => entry.arbitrary_args = (val == "1" || val == "true"),
|
"allow_args" => entry.arbitrary_args = val == "1" || val == "true",
|
||||||
"args" => entry.args = val,
|
"args" => entry.args = val,
|
||||||
"no_new_privs" => entry.no_new_privs = (val == "1" || val == "true"),
|
"no_new_privs" => entry.no_new_privs = val == "1" || val == "true",
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Ignoring invalid key {}", key);
|
eprintln!("Ignoring invalid key {}", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn assign_from_line(entry: &mut Entry, line: &str) {
|
fn assign_from_line(entry: &mut Entry, line: &str) {
|
||||||
@ -159,7 +151,6 @@ fn assign_from_line(entry: &mut Entry, line: &str) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assign(entry, key.unwrap(), value.unwrap())
|
assign(entry, key.unwrap(), value.unwrap())
|
||||||
|
|
||||||
}
|
}
|
||||||
fn create_entry_from_file(filepath: &str) -> std::io::Result<Entry> {
|
fn create_entry_from_file(filepath: &str) -> std::io::Result<Entry> {
|
||||||
let mut entry: Entry = Entry::new();
|
let mut entry: Entry = Entry::new();
|
||||||
@ -179,7 +170,8 @@ fn clearenv() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
//TODO: AsRef for envs?
|
//TODO: AsRef for envs?
|
||||||
fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> {
|
fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> {
|
||||||
let saved_envs: Vec<String> = envs.iter()
|
let saved_envs: Vec<String> = envs
|
||||||
|
.iter()
|
||||||
.map(|s| std::env::var(s).expect("No such var"))
|
.map(|s| std::env::var(s).expect("No such var"))
|
||||||
.collect();
|
.collect();
|
||||||
clearenv()?;
|
clearenv()?;
|
||||||
@ -194,7 +186,6 @@ fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> {
|
|||||||
std::env::set_var(&envs[i], item);
|
std::env::set_var(&envs[i], item);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn become_user(passwd: &Passwd) -> std::io::Result<()> {
|
fn become_user(passwd: &Passwd) -> std::io::Result<()> {
|
||||||
@ -204,13 +195,12 @@ fn become_user(passwd: &Passwd) -> std::io::Result<()> {
|
|||||||
std::env::set_current_dir(&passwd.pw_dir)?;
|
std::env::set_current_dir(&passwd.pw_dir)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn init_sandbox(entry: &Entry) -> std::io::Result<()> {
|
|
||||||
if (entry.no_new_privs) {
|
|
||||||
errnowrapper(unsafe {
|
|
||||||
libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fn drop_privs(entry: &Entry) -> std::io::Result<()> {
|
||||||
|
if entry.no_new_privs {
|
||||||
|
errnowrapper(unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0) })?;
|
||||||
|
errnowrapper(unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) })?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,8 +210,6 @@ fn to_cstring<T: AsRef<str>>(s: T) -> *const libc::c_char {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_execv_args(entry: &Entry, cmdargs: &Vec<String>) -> Vec<*const libc::c_char> {
|
fn create_execv_args(entry: &Entry, cmdargs: &Vec<String>) -> Vec<*const libc::c_char> {
|
||||||
|
|
||||||
|
|
||||||
let mut args: Vec<*const libc::c_char>;
|
let mut args: Vec<*const libc::c_char>;
|
||||||
if entry.arbitrary_args && cmdargs.len() > 2 {
|
if entry.arbitrary_args && cmdargs.len() > 2 {
|
||||||
args = cmdargs.iter().skip(2).map(to_cstring).collect();
|
args = cmdargs.iter().skip(2).map(to_cstring).collect();
|
||||||
@ -256,11 +244,8 @@ fn exec(entryname: &str, cmdargs: &Vec<String>) -> std::io::Result<()> {
|
|||||||
let destuserpasswd: Passwd = getpwnam(&entry.dest_user)?;
|
let destuserpasswd: Passwd = getpwnam(&entry.dest_user)?;
|
||||||
let currentuser: u32 = geteuid();
|
let currentuser: u32 = geteuid();
|
||||||
|
|
||||||
|
|
||||||
let args = create_execv_args(&entry, &cmdargs);
|
let args = create_execv_args(&entry, &cmdargs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ensure_allowed(currentuser, &entry)?;
|
ensure_allowed(currentuser, &entry)?;
|
||||||
become_user(&destuserpasswd).or_else(|e| {
|
become_user(&destuserpasswd).or_else(|e| {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -268,39 +253,35 @@ fn exec(entryname: &str, cmdargs: &Vec<String>) -> std::io::Result<()> {
|
|||||||
"Failed to switch user: ".to_owned() + &e.to_string(),
|
"Failed to switch user: ".to_owned() + &e.to_string(),
|
||||||
));
|
));
|
||||||
})?;
|
})?;
|
||||||
setup_environment(&destuserpasswd, &entry.inherit_envs)
|
setup_environment(&destuserpasswd, &entry.inherit_envs).or_else(|e| {
|
||||||
.or_else(|e| {
|
|
||||||
return Err(Error::new(
|
|
||||||
ErrorKind::Other,
|
|
||||||
"Environment setup failure: ".to_owned() + &e.to_string(),
|
|
||||||
));
|
|
||||||
})?;
|
|
||||||
init_sandbox(&entry).or_else(|e| {
|
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
"Sandbox init failure: ".to_owned() + &e.to_string(),
|
"Environment setup failure: ".to_owned() + &e.to_string(),
|
||||||
|
));
|
||||||
|
})?;
|
||||||
|
|
||||||
|
drop_privs(&entry).or_else(|e| {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::Other,
|
||||||
|
"Failed to drop priviliges: ".to_owned() + &e.to_string(),
|
||||||
));
|
));
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr()))
|
errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr())).or_else(|e| {
|
||||||
.or_else(|e| {
|
return Err(Error::new(
|
||||||
return Err(Error::new(
|
ErrorKind::Other,
|
||||||
ErrorKind::Other,
|
"execv failed: ".to_owned() + &e.to_string(),
|
||||||
"execv failed: ".to_owned() + &e.to_string(),
|
));
|
||||||
));
|
})?;
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
|
|
||||||
let argv: Args = std::env::args();
|
let argv: Args = std::env::args();
|
||||||
let cmdargs: Vec<String> = argv.collect();
|
let cmdargs: Vec<String> = argv.collect();
|
||||||
let entryname = cmdargs.get(1);
|
let entryname = cmdargs.get(1);
|
||||||
if entryname.is_some() {
|
if entryname.is_some() {
|
||||||
|
|
||||||
match exec(&entryname.unwrap(), &cmdargs) {
|
match exec(&entryname.unwrap(), &cmdargs) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("The following error ocurred:");
|
eprintln!("The following error ocurred:");
|
||||||
|
Loading…
Reference in New Issue
Block a user