rustfmt
This commit is contained in:
parent
21b208bff9
commit
352989756c
191
src/main.rs
191
src/main.rs
@ -9,8 +9,7 @@ use std::ffi::CStr;
|
||||
extern crate libc;
|
||||
use libc::passwd;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
struct Entry {
|
||||
users: Vec<String>,
|
||||
dest_user: String,
|
||||
cmd: String,
|
||||
@ -19,14 +18,10 @@ struct Entry
|
||||
inherit_envs: Vec<String>,
|
||||
no_new_privs: bool,
|
||||
arbitrary_args: bool,
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl Entry
|
||||
{
|
||||
fn new() -> Entry
|
||||
{
|
||||
impl Entry {
|
||||
fn new() -> Entry {
|
||||
return Entry {
|
||||
users: Vec::new(),
|
||||
dest_user: String::new(),
|
||||
@ -36,13 +31,12 @@ impl Entry
|
||||
inherit_envs: Vec::new(),
|
||||
no_new_privs: true,
|
||||
arbitrary_args: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Passwd
|
||||
{
|
||||
struct Passwd {
|
||||
pw_name: String,
|
||||
pw_passwd: String,
|
||||
pw_uid: libc::uid_t,
|
||||
@ -53,54 +47,42 @@ struct Passwd
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return errnowrapper( unsafe { libc::initgroups(userarg.unwrap().as_ptr(), group)});
|
||||
return errnowrapper(unsafe {
|
||||
libc::initgroups(userarg.unwrap().as_ptr(), group)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
fn errnowrapper(ret : libc::c_int) -> std::io::Result<()>
|
||||
{
|
||||
if ret != 0
|
||||
{
|
||||
fn errnowrapper(ret: libc::c_int) -> std::io::Result<()> {
|
||||
if ret != 0 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn setuid(id : libc::uid_t) -> std::io::Result<()>
|
||||
{
|
||||
fn setuid(id: libc::uid_t) -> std::io::Result<()> {
|
||||
return errnowrapper(unsafe { libc::setuid(id) });
|
||||
}
|
||||
|
||||
fn setgid(gid : libc::gid_t) -> std::io::Result<()>
|
||||
{
|
||||
fn setgid(gid: libc::gid_t) -> std::io::Result<()> {
|
||||
return errnowrapper(unsafe { libc::setgid(gid) });
|
||||
}
|
||||
|
||||
fn geteuid() -> u32
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fn geteuid() -> u32 {
|
||||
unsafe {
|
||||
return libc::geteuid();
|
||||
}
|
||||
}
|
||||
|
||||
fn getpwnam(username : &str) -> std::io::Result<Passwd>
|
||||
{
|
||||
fn getstr(str : *mut libc::c_char) -> String
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
CStr::from_ptr(str).to_string_lossy().into_owned()
|
||||
fn getpwnam(username: &str) -> std::io::Result<Passwd> {
|
||||
fn getstr(str: *mut libc::c_char) -> String {
|
||||
unsafe { CStr::from_ptr(str).to_string_lossy().into_owned() }
|
||||
}
|
||||
}
|
||||
unsafe
|
||||
{
|
||||
unsafe {
|
||||
let pwnamresult: *mut passwd = libc::getpwnam(CString::new(username).unwrap().as_ptr());
|
||||
if pwnamresult.is_null()
|
||||
{
|
||||
if pwnamresult.is_null() {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
Ok(Passwd {
|
||||
@ -116,52 +98,44 @@ fn getpwnam(username : &str) -> std::io::Result<Passwd>
|
||||
|
||||
}
|
||||
|
||||
fn ensure_allowed(userid : libc::uid_t, entry : &Entry ) -> std::io::Result<()>
|
||||
{
|
||||
fn ensure_allowed(userid: libc::uid_t, entry: &Entry) -> std::io::Result<()> {
|
||||
if userid == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
for user in &entry.users
|
||||
{
|
||||
for user in &entry.users {
|
||||
let passwd: Passwd = getpwnam(&user)?;
|
||||
if passwd.pw_uid == userid
|
||||
{
|
||||
if passwd.pw_uid == userid {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let passwd: Passwd = getpwnam(&entry.dest_user)?;
|
||||
if passwd.pw_uid == userid
|
||||
{
|
||||
if passwd.pw_uid == userid {
|
||||
return Ok(());
|
||||
}
|
||||
return Err(Error::new(ErrorKind::PermissionDenied, "Not allowed to become target user"));
|
||||
return Err(Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
"Not allowed to become target user",
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
fn usage()
|
||||
{
|
||||
fn usage() {
|
||||
println!("Usage: raou ENRTYNAME");
|
||||
}
|
||||
fn add_multi(vec : &mut Vec<String>, val: String)
|
||||
{
|
||||
if val.contains(',')
|
||||
{
|
||||
fn add_multi(vec: &mut Vec<String>, val: String) {
|
||||
if val.contains(',') {
|
||||
let splitted = val.split(',');
|
||||
for part in splitted {
|
||||
vec.push(part.to_owned());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
vec.push(val);
|
||||
}
|
||||
}
|
||||
fn assign(entry : &mut Entry, key: &str, value: &str)
|
||||
{
|
||||
fn assign(entry: &mut Entry, key: &str, value: &str) {
|
||||
let val = value.to_owned();
|
||||
match key
|
||||
{
|
||||
match key {
|
||||
"path" => entry.cmd = val,
|
||||
"user" => add_multi(&mut entry.users, val),
|
||||
"env_vars" => add_multi(&mut entry.inherit_envs, val),
|
||||
@ -176,21 +150,18 @@ fn assign(entry : &mut Entry, key: &str, value: &str)
|
||||
|
||||
}
|
||||
}
|
||||
fn assign_from_line(entry : &mut Entry, line : &str)
|
||||
{
|
||||
fn assign_from_line(entry: &mut Entry, line: &str) {
|
||||
let mut splitted = line.splitn(2, ' ');
|
||||
let key = splitted.next();
|
||||
let value = splitted.next();
|
||||
|
||||
if ! key.is_some() || ! value.is_some()
|
||||
{
|
||||
if !key.is_some() || !value.is_some() {
|
||||
return;
|
||||
}
|
||||
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 f = File::open(filepath)?;
|
||||
|
||||
@ -203,14 +174,14 @@ fn create_entry_from_file(filepath : &str) -> std::io::Result<Entry>
|
||||
}
|
||||
|
||||
//TODO: clearenv does not set errno?
|
||||
fn clearenv() -> std::io::Result<()>
|
||||
{
|
||||
fn clearenv() -> std::io::Result<()> {
|
||||
return errnowrapper(unsafe { libc::clearenv() });
|
||||
}
|
||||
//TODO: AsRef for envs?
|
||||
fn setup_environment(passwd : &Passwd, envs : &[String]) -> std::io::Result<()>
|
||||
{
|
||||
let saved_envs : Vec<String> = envs.iter().map(|s| std::env::var(s).expect("No such var")).collect();
|
||||
fn setup_environment(passwd: &Passwd, envs: &[String]) -> std::io::Result<()> {
|
||||
let saved_envs: Vec<String> = envs.iter()
|
||||
.map(|s| std::env::var(s).expect("No such var"))
|
||||
.collect();
|
||||
clearenv()?;
|
||||
|
||||
//TODO: set_var does not have a return val?
|
||||
@ -219,26 +190,22 @@ fn setup_environment(passwd : &Passwd, envs : &[String]) -> std::io::Result<()>
|
||||
std::env::set_var("LOGNAME", &passwd.pw_name);
|
||||
std::env::set_var("SHELL", &passwd.pw_shell);
|
||||
|
||||
for (i, item) in saved_envs.iter().enumerate()
|
||||
{
|
||||
for (i, item) in saved_envs.iter().enumerate() {
|
||||
std::env::set_var(&envs[i], item);
|
||||
}
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
fn become_user(passwd : &Passwd) -> std::io::Result<()>
|
||||
{
|
||||
fn become_user(passwd: &Passwd) -> std::io::Result<()> {
|
||||
initgroups(&(passwd.pw_name), passwd.pw_gid)?;
|
||||
setgid(passwd.pw_gid)?;
|
||||
setuid(passwd.pw_uid)?;
|
||||
std::env::set_current_dir(&passwd.pw_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
fn init_sandbox(entry : &Entry) -> std::io::Result<()>
|
||||
{
|
||||
if(entry.no_new_privs)
|
||||
{
|
||||
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)
|
||||
})?;
|
||||
@ -252,38 +219,38 @@ fn to_cstring<T: AsRef<str>>(s : T) -> * const libc::c_char {
|
||||
return CString::new(s.as_ref()).unwrap().into_raw();
|
||||
}
|
||||
|
||||
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>;
|
||||
if entry.arbitrary_args && cmdargs.len() > 2
|
||||
{
|
||||
if entry.arbitrary_args && cmdargs.len() > 2 {
|
||||
args = cmdargs.iter().skip(2).map(to_cstring).collect();
|
||||
} else {
|
||||
args = entry
|
||||
.args
|
||||
.as_str()
|
||||
.split_whitespace()
|
||||
.map(to_cstring)
|
||||
.collect();
|
||||
}
|
||||
else
|
||||
{
|
||||
args = entry.args.as_str().split_whitespace().map(to_cstring).collect();
|
||||
}
|
||||
if ! &entry.argv0.is_empty()
|
||||
{
|
||||
if !&entry.argv0.is_empty() {
|
||||
args.insert(0, to_cstring(&entry.argv0));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
let cmdbegin = &entry.cmd.rfind("/").unwrap() + 1;
|
||||
args.insert(0, to_cstring(&entry.cmd.split_at(cmdbegin).1));
|
||||
}
|
||||
args.push(std::ptr::null());
|
||||
return args;
|
||||
}
|
||||
fn exec(entryname : &str, cmdargs : &Vec<String>) -> std::io::Result<()>
|
||||
{
|
||||
fn exec(entryname: &str, cmdargs: &Vec<String>) -> std::io::Result<()> {
|
||||
let mut filepath: String = String::from("/etc/raou.d/");
|
||||
filepath = filepath + entryname;
|
||||
|
||||
if !std::path::Path::new(&filepath).exists() {
|
||||
return Err(std::io::Error::new(ErrorKind::NotFound, "The entry ".to_owned() + &filepath + " does not exist"));
|
||||
return Err(std::io::Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"The entry ".to_owned() + &filepath + " does not exist",
|
||||
));
|
||||
}
|
||||
let entry: Entry = create_entry_from_file(&filepath)?;
|
||||
let destuserpasswd: Passwd = getpwnam(&entry.dest_user)?;
|
||||
@ -295,12 +262,34 @@ fn exec(entryname : &str, cmdargs : &Vec<String>) -> std::io::Result<()>
|
||||
|
||||
|
||||
ensure_allowed(currentuser, &entry)?;
|
||||
become_user(&destuserpasswd).or_else(|e| return Err(Error::new(ErrorKind::PermissionDenied, "Failed to switch user: ".to_owned() + &e.to_string())))?;
|
||||
setup_environment(&destuserpasswd, &entry.inherit_envs).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(ErrorKind::Other, "Sandbox init failure: ".to_owned() + &e.to_string())))?;
|
||||
become_user(&destuserpasswd).or_else(|e| {
|
||||
return Err(Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
"Failed to switch user: ".to_owned() + &e.to_string(),
|
||||
));
|
||||
})?;
|
||||
setup_environment(&destuserpasswd, &entry.inherit_envs)
|
||||
.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(
|
||||
ErrorKind::Other,
|
||||
"Sandbox init failure: ".to_owned() + &e.to_string(),
|
||||
));
|
||||
})?;
|
||||
|
||||
unsafe {
|
||||
errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr())).or_else(|e| return Err(Error::new(ErrorKind::Other, "execv failed: ".to_owned() + &e.to_string())))?;
|
||||
errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr()))
|
||||
.or_else(|e| {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"execv failed: ".to_owned() + &e.to_string(),
|
||||
));
|
||||
})?;
|
||||
}
|
||||
std::process::exit(0);
|
||||
Ok(())
|
||||
@ -319,9 +308,7 @@ fn main() -> Result<(), std::io::Error> {
|
||||
|
||||
std::process::exit(1);
|
||||
}
|
||||
_ => {
|
||||
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
usage();
|
||||
|
Loading…
x
Reference in New Issue
Block a user