Merge branch 'su_no_setuid' into 'master'
Use the sudo daemon rather than setuid for su See merge request redox-os/userutils!53
This commit is contained in:
+13
-9
@@ -6,7 +6,9 @@ use std::process::exit;
|
||||
use std::str;
|
||||
|
||||
use extra::option::OptionalExt;
|
||||
use libc::O_CLOEXEC;
|
||||
use redox_users::{All, AllUsers, Config, get_uid};
|
||||
use syscall::EPERM;
|
||||
use termion::input::TermRead;
|
||||
use userutils::spawn_shell;
|
||||
|
||||
@@ -50,15 +52,17 @@ pub fn main() {
|
||||
|
||||
let uid = get_uid().unwrap_or_exit(1);
|
||||
|
||||
let users = AllUsers::authenticator(Config::default()).unwrap_or_exit(1);
|
||||
let users = AllUsers::basic(Config::default()).unwrap_or_exit(1);
|
||||
let user = users.get_by_name(&target_user).unwrap_or_exit(1);
|
||||
|
||||
// If the user executing su is root, then they can do anything without a password.
|
||||
// Same if the user we're being asked to login as doesn't have a password.
|
||||
if uid == 0 || user.is_passwd_blank() {
|
||||
if uid == 0 {
|
||||
writeln!(stdout).unwrap_or_exit(1);
|
||||
exit(spawn_shell(user).unwrap_or_exit(1));
|
||||
} else {
|
||||
let file = libredox::call::open("/scheme/sudo/su", O_CLOEXEC, 0).unwrap();
|
||||
|
||||
write!(stdout, "password: ").unwrap_or_exit(1);
|
||||
stdout.flush().unwrap_or_exit(1);
|
||||
|
||||
@@ -68,13 +72,13 @@ pub fn main() {
|
||||
.r#try(&mut stderr)
|
||||
.unwrap_or(String::new());
|
||||
|
||||
writeln!(stderr, "\n").unwrap_or_exit(1);
|
||||
|
||||
if user.verify_passwd(&password) {
|
||||
exit(spawn_shell(user).unwrap_or_exit(1));
|
||||
} else {
|
||||
writeln!(stderr, "su: authentication failed").unwrap_or_exit(1);
|
||||
exit(1);
|
||||
match libredox::call::write(file, password.as_bytes()) {
|
||||
Ok(_) => exit(spawn_shell(user).unwrap_or_exit(1)),
|
||||
Err(err) if err.errno() == EPERM => {
|
||||
writeln!(stderr, "su: authentication failed").unwrap_or_exit(1);
|
||||
exit(1);
|
||||
}
|
||||
Err(err) => panic!("{err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-7
@@ -42,7 +42,7 @@ AUTHOR
|
||||
Written by Jeremy Soller, Jose Narvaez, bjorn3.
|
||||
"#; /* @MANEND */
|
||||
|
||||
pub fn main() {
|
||||
fn main() {
|
||||
if env::args().nth(1).as_deref() == Some("--daemon") {
|
||||
daemon_main();
|
||||
}
|
||||
@@ -150,20 +150,21 @@ struct Scheme {
|
||||
}
|
||||
enum Handle {
|
||||
AwaitingPassword { uid: u32 },
|
||||
AwaitingRootPassword,
|
||||
AwaitingContextFd,
|
||||
Placeholder,
|
||||
}
|
||||
|
||||
impl SchemeSync for Scheme {
|
||||
fn open(&mut self, path: &str, _flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
// Path must be empty
|
||||
if path.trim_start_matches('/') != "" {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
let fd = self.next_fd;
|
||||
self.next_fd = self.next_fd.checked_add(1).ok_or(Error::new(EMFILE))?;
|
||||
self.handles
|
||||
.insert(fd, Handle::AwaitingPassword { uid: ctx.uid });
|
||||
let handle = match path {
|
||||
"" => Handle::AwaitingPassword { uid: ctx.uid },
|
||||
"su" => Handle::AwaitingRootPassword,
|
||||
_ => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
self.handles.insert(fd, handle);
|
||||
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: fd,
|
||||
@@ -204,6 +205,18 @@ impl SchemeSync for Scheme {
|
||||
}
|
||||
}
|
||||
}
|
||||
Handle::AwaitingRootPassword => {
|
||||
let users = AllUsers::authenticator(Config::default()).unwrap_or_exit(1);
|
||||
let user = users.get_by_id(0).unwrap_or_exit(1);
|
||||
|
||||
let password = validate_utf8(buf)?;
|
||||
if user.verify_passwd(&password) {
|
||||
*handle = Handle::AwaitingContextFd
|
||||
} else {
|
||||
*handle = Handle::AwaitingRootPassword;
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
}
|
||||
Handle::AwaitingContextFd => {
|
||||
*handle = Handle::AwaitingContextFd;
|
||||
return Err(Error::new(EINVAL));
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ impl AllGroupsExt for AllGroups {
|
||||
/// let user = sys_users.get_by_name("goyox86");
|
||||
/// spawn_shell(user).unwrap();
|
||||
/// ```
|
||||
pub fn spawn_shell(user: &User<auth::Full>) -> IoResult<i32> {
|
||||
pub fn spawn_shell<T: Default>(user: &User<T>) -> IoResult<i32> {
|
||||
let mut command = user.shell_cmd();
|
||||
|
||||
let mut child = command.spawn()?;
|
||||
|
||||
Reference in New Issue
Block a user