This commit is contained in:
Albert S. 2020-09-14 19:19:20 +02:00
parent 1c03d47dac
commit dce3d063f7
1 changed files with 31 additions and 22 deletions

View File

@ -47,7 +47,9 @@ 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); 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<()> { fn errnowrapper(ret: libc::c_int) -> std::io::Result<()> {
@ -75,12 +77,16 @@ fn getpwnam(username: &str) -> std::io::Result<Passwd> {
fn getstr(str: *mut libc::c_char) -> String { fn getstr(str: *mut libc::c_char) -> String {
unsafe { CStr::from_ptr(str).to_string_lossy().into_owned() } unsafe { CStr::from_ptr(str).to_string_lossy().into_owned() }
} }
let username_c = CString::new(username).unwrap(); let username_c = CString::new(username).unwrap();
let username_ptr = username_c.as_ptr(); let username_ptr = username_c.as_ptr();
let pwnamresult: *mut libc::passwd = unsafe { libc::getpwnam(username_ptr) }; let pwnamresult: *mut libc::passwd = unsafe { libc::getpwnam(username_ptr) };
if pwnamresult.is_null() { if pwnamresult.is_null() {
return Err(Error::new(Error::last_os_error().kind(),"Lookup of user failed: ".to_owned() + &Error::last_os_error().to_string())); return Err(Error::new(
} Error::last_os_error().kind(),
"Lookup of user failed: ".to_owned() +
&Error::last_os_error().to_string(),
));
}
unsafe { unsafe {
Ok(Passwd { Ok(Passwd {
pw_name: getstr((*pwnamresult).pw_name), pw_name: getstr((*pwnamresult).pw_name),
@ -172,8 +178,7 @@ 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 let saved_envs: Vec<String> = envs.iter()
.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()?;
@ -201,7 +206,9 @@ fn become_user(passwd: &Passwd) -> std::io::Result<()> {
fn drop_privs(entry: &Entry) -> std::io::Result<()> { fn drop_privs(entry: &Entry) -> std::io::Result<()> {
if entry.no_new_privs { if entry.no_new_privs {
errnowrapper(unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0) })?; errnowrapper(unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0) })?;
errnowrapper(unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) })?; errnowrapper(unsafe {
libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)
})?;
} }
Ok(()) Ok(())
} }
@ -255,12 +262,13 @@ 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).or_else(|e| { setup_environment(&destuserpasswd, &entry.inherit_envs)
return Err(Error::new( .or_else(|e| {
ErrorKind::Other, return Err(Error::new(
"Environment setup failure: ".to_owned() + &e.to_string(), ErrorKind::Other,
)); "Environment setup failure: ".to_owned() + &e.to_string(),
})?; ));
})?;
drop_privs(&entry).or_else(|e| { drop_privs(&entry).or_else(|e| {
return Err(Error::new( return Err(Error::new(
@ -270,12 +278,13 @@ fn exec(entryname: &str, cmdargs: &Vec<String>) -> std::io::Result<()> {
})?; })?;
unsafe { unsafe {
errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr())).or_else(|e| { errnowrapper(libc::execv(to_cstring(entry.cmd), args.as_ptr()))
return Err(Error::new( .or_else(|e| {
ErrorKind::Other, return Err(Error::new(
"execv failed: ".to_owned() + &e.to_string(), ErrorKind::Other,
)); "execv failed: ".to_owned() + &e.to_string(),
})?; ));
})?;
} }
std::process::exit(0); std::process::exit(0);
} }