Add userutils
This commit is contained in:
parent
5d7b0a3889
commit
0d1afaa016
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -25,3 +25,6 @@
|
|||
[submodule "programs/smith"]
|
||||
path = programs/smith
|
||||
url = https://github.com/IGI-111/Smith.git
|
||||
[submodule "programs/userutils"]
|
||||
path = programs/userutils
|
||||
url = https://github.com/redox-os/userutils.git
|
||||
|
|
26
Makefile
26
Makefile
|
@ -28,15 +28,11 @@ clean:
|
|||
cargo clean --manifest-path drivers/ps2d/Cargo.toml
|
||||
cargo clean --manifest-path drivers/pcid/Cargo.toml
|
||||
cargo clean --manifest-path drivers/vesad/Cargo.toml
|
||||
cargo clean --manifest-path programs/getty/Cargo.toml
|
||||
cargo clean --manifest-path programs/id/Cargo.toml
|
||||
cargo clean --manifest-path programs/init/Cargo.toml
|
||||
cargo clean --manifest-path programs/sudo/Cargo.toml
|
||||
cargo clean --manifest-path programs/ion/Cargo.toml
|
||||
cargo clean --manifest-path programs/login/Cargo.toml
|
||||
cargo clean --manifest-path programs/sudo/Cargo.toml
|
||||
cargo clean --manifest-path programs/coreutils/Cargo.toml
|
||||
cargo clean --manifest-path programs/extrautils/Cargo.toml
|
||||
cargo clean --manifest-path programs/userutils/Cargo.toml
|
||||
cargo clean --manifest-path programs/smith/Cargo.toml
|
||||
cargo clean --manifest-path schemes/example/Cargo.toml
|
||||
cargo clean --manifest-path schemes/redoxfs/Cargo.toml
|
||||
|
@ -217,6 +213,12 @@ filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.r
|
|||
strip $@
|
||||
rm $@.d
|
||||
|
||||
filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib
|
||||
mkdir -p filesystem/bin
|
||||
$(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@
|
||||
strip $@
|
||||
rm $@.d
|
||||
|
||||
filesystem/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib
|
||||
mkdir -p filesystem/bin
|
||||
$(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@
|
||||
|
@ -269,6 +271,12 @@ extrautils: \
|
|||
filesystem/bin/rem \
|
||||
#filesystem/bin/dmesg filesystem/bin/info filesystem/bin/man filesystem/bin/watch
|
||||
|
||||
userutils: \
|
||||
filesystem/bin/getty \
|
||||
filesystem/bin/id \
|
||||
filesystem/bin/login \
|
||||
filesystem/bin/su \
|
||||
filesystem/bin/sudo
|
||||
|
||||
schemes: \
|
||||
filesystem/bin/example
|
||||
|
@ -277,13 +285,10 @@ $(BUILD)/filesystem.bin: \
|
|||
drivers \
|
||||
coreutils \
|
||||
extrautils \
|
||||
userutils \
|
||||
schemes \
|
||||
filesystem/bin/getty \
|
||||
filesystem/bin/id \
|
||||
filesystem/bin/ion \
|
||||
filesystem/bin/login \
|
||||
filesystem/bin/smith \
|
||||
filesystem/bin/sudo
|
||||
filesystem/bin/smith
|
||||
rm -rf $@ $(BUILD)/filesystem/
|
||||
echo exit | cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-utility $@ 8
|
||||
mkdir -p $(BUILD)/filesystem/
|
||||
|
@ -294,6 +299,7 @@ $(BUILD)/filesystem.bin: \
|
|||
-chown -R 1000:1000 $(BUILD)/filesystem/home/user/
|
||||
-chmod 700 $(BUILD)/filesystem/root/
|
||||
-chmod 700 $(BUILD)/filesystem/home/user/
|
||||
-chmod +s $(BUILD)/filesystem/bin/su
|
||||
-chmod +s $(BUILD)/filesystem/bin/sudo
|
||||
sync
|
||||
-fusermount -u $(BUILD)/filesystem/
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit dc2ebd63734f30f345732fcd2e51e3f485d0ed0d
|
||||
Subproject commit adbf93876da794bde338ed8d53e5e7c4f14549dc
|
|
@ -1,6 +0,0 @@
|
|||
[package]
|
||||
name = "getty"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../../syscall/" }
|
|
@ -1,51 +0,0 @@
|
|||
#![feature(question_mark)]
|
||||
|
||||
extern crate syscall;
|
||||
|
||||
use std::io::Write;
|
||||
use std::process::Command;
|
||||
use std::{env, io, str, thread};
|
||||
|
||||
pub fn main() {
|
||||
let mut args = env::args().skip(1);
|
||||
|
||||
let tty = args.next().expect("getty: no tty provided");
|
||||
|
||||
let _ = syscall::close(2);
|
||||
let _ = syscall::close(1);
|
||||
let _ = syscall::close(0);
|
||||
|
||||
let _ = syscall::open(&tty, syscall::flag::O_RDWR);
|
||||
let _ = syscall::open(&tty, syscall::flag::O_RDWR);
|
||||
let _ = syscall::open(&tty, syscall::flag::O_RDWR);
|
||||
|
||||
env::set_current_dir("file:").unwrap();
|
||||
|
||||
env::set_var("TTY", &tty);
|
||||
{
|
||||
let mut path = [0; 4096];
|
||||
if let Ok(count) = syscall::fpath(0, &mut path) {
|
||||
let path_str = str::from_utf8(&path[..count]).unwrap_or("");
|
||||
let reference = path_str.split(':').nth(1).unwrap_or("");
|
||||
let mut parts = reference.split('/');
|
||||
env::set_var("COLUMNS", parts.next().unwrap_or("80"));
|
||||
env::set_var("LINES", parts.next().unwrap_or("30"));
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
loop {
|
||||
stdout.write(b"\x1Bc").unwrap();
|
||||
let _ = stdout.flush();
|
||||
match Command::new("file:bin/login").spawn() {
|
||||
Ok(mut child) => match child.wait() {
|
||||
Ok(_status) => (), //println!("getty: waited for login: {:?}", status.code()),
|
||||
Err(err) => panic!("getty: failed to wait for login: {}", err)
|
||||
},
|
||||
Err(err) => panic!("getty: failed to execute login: {}", err)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
[package]
|
||||
name = "id"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../../syscall/" }
|
|
@ -1,9 +0,0 @@
|
|||
extern crate syscall;
|
||||
|
||||
use std::env;
|
||||
|
||||
pub fn main() {
|
||||
let uid = syscall::getuid().expect("id: failed to get UID");
|
||||
let gid = syscall::getgid().expect("id: failed to get GID");
|
||||
println!("uid={}({}) gid={}({})", uid, env::var("USER").unwrap_or(String::new()), gid, "");
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
[package]
|
||||
name = "login"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
termion = "*"
|
||||
|
||||
[dependencies.octavo]
|
||||
git = "https://github.com/libOctavo/octavo"
|
||||
default-features = false
|
||||
features = ["digest"]
|
||||
|
||||
[replace]
|
||||
"libc:0.2.16" = { git = "https://github.com/redox-os/liblibc.git", branch = "new_kernel" }
|
||||
"rustc-serialize:0.3.19" = { git = "https://github.com/redox-os/rustc-serialize.git" }
|
|
@ -1,149 +0,0 @@
|
|||
#![feature(question_mark)]
|
||||
|
||||
extern crate octavo;
|
||||
extern crate termion;
|
||||
|
||||
use octavo::octavo_digest::Digest;
|
||||
use octavo::octavo_digest::sha3::Sha512;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
use termion::input::TermRead;
|
||||
|
||||
pub struct Passwd<'a> {
|
||||
user: &'a str,
|
||||
hash: &'a str,
|
||||
uid: u32,
|
||||
gid: u32,
|
||||
name: &'a str,
|
||||
home: &'a str,
|
||||
shell: &'a str
|
||||
}
|
||||
|
||||
impl<'a> Passwd<'a> {
|
||||
pub fn parse(line: &'a str) -> Result<Passwd<'a>, ()> {
|
||||
let mut parts = line.split(';');
|
||||
|
||||
let user = parts.next().ok_or(())?;
|
||||
let hash = parts.next().ok_or(())?;
|
||||
let uid = parts.next().ok_or(())?.parse::<u32>().or(Err(()))?;
|
||||
let gid = parts.next().ok_or(())?.parse::<u32>().or(Err(()))?;
|
||||
let name = parts.next().ok_or(())?;
|
||||
let home = parts.next().ok_or(())?;
|
||||
let shell = parts.next().ok_or(())?;
|
||||
|
||||
Ok(Passwd {
|
||||
user: user,
|
||||
hash: hash,
|
||||
uid: uid,
|
||||
gid: gid,
|
||||
name: name,
|
||||
home: home,
|
||||
shell: shell
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
if let Ok(mut issue) = File::open("/etc/issue") {
|
||||
io::copy(&mut issue, &mut stdout).unwrap();
|
||||
let _ = stdout.flush();
|
||||
}
|
||||
|
||||
loop {
|
||||
stdout.write_all(b"\x1B[1mredox login:\x1B[0m ").unwrap();
|
||||
let _ = stdout.flush();
|
||||
|
||||
let user = (&mut stdin as &mut Read).read_line().unwrap().unwrap_or(String::new());
|
||||
if ! user.is_empty() {
|
||||
let mut passwd_string = String::new();
|
||||
File::open("file:etc/passwd").unwrap().read_to_string(&mut passwd_string).unwrap();
|
||||
|
||||
let mut passwd_option = None;
|
||||
for line in passwd_string.lines() {
|
||||
if let Ok(passwd) = Passwd::parse(line) {
|
||||
if user == passwd.user && "" == passwd.hash {
|
||||
passwd_option = Some(passwd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if passwd_option.is_none() {
|
||||
stdout.write_all(b"\x1B[1mpassword:\x1B[0m ").unwrap();
|
||||
let _ = stdout.flush();
|
||||
|
||||
if let Some(password) = stdin.read_passwd(&mut stdout).unwrap() {
|
||||
stdout.write(b"\n").unwrap();
|
||||
let _ = stdout.flush();
|
||||
|
||||
let password_hash = {
|
||||
let mut output = vec![0; Sha512::output_bytes()];
|
||||
let mut hash = Sha512::default();
|
||||
hash.update(&password.as_bytes());
|
||||
hash.result(&mut output);
|
||||
let mut encoded = String::new();
|
||||
for b in output.iter() {
|
||||
encoded.push_str(&format!("{:X}", b));
|
||||
}
|
||||
encoded
|
||||
};
|
||||
|
||||
if let Ok(mut debug) = File::open("debug:") {
|
||||
let _ = write!(debug, "{};{}\n", user, password_hash);
|
||||
}
|
||||
|
||||
for line in passwd_string.lines() {
|
||||
if let Ok(passwd) = Passwd::parse(line) {
|
||||
if user == passwd.user && password_hash == passwd.hash {
|
||||
passwd_option = Some(passwd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(passwd) = passwd_option {
|
||||
if let Ok(mut motd) = File::open("/etc/motd") {
|
||||
io::copy(&mut motd, &mut stdout).unwrap();
|
||||
let _ = stdout.flush();
|
||||
}
|
||||
|
||||
let mut command = Command::new(passwd.shell);
|
||||
|
||||
command.uid(passwd.uid);
|
||||
command.gid(passwd.gid);
|
||||
|
||||
command.current_dir(passwd.home);
|
||||
|
||||
command.env("USER", &user);
|
||||
command.env("HOME", passwd.home);
|
||||
command.env("PATH", "file:bin");
|
||||
|
||||
match command.spawn() {
|
||||
Ok(mut child) => match child.wait() {
|
||||
Ok(_status) => (), //println!("login: waited for {}: {:?}", sh, status.code()),
|
||||
Err(err) => panic!("login: failed to wait for '{}': {}", passwd.shell, err)
|
||||
},
|
||||
Err(err) => panic!("login: failed to execute '{}': {}", passwd.shell, err)
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
stdout.write(b"\nLogin failed\n").unwrap();
|
||||
let _ = stdout.flush();
|
||||
}
|
||||
} else {
|
||||
stdout.write(b"\n").unwrap();
|
||||
let _ = stdout.flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
[package]
|
||||
name = "sudo"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../../syscall/" }
|
|
@ -1,123 +0,0 @@
|
|||
#![feature(question_mark)]
|
||||
|
||||
extern crate syscall;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::{self, Command};
|
||||
|
||||
pub struct Passwd<'a> {
|
||||
user: &'a str,
|
||||
hash: &'a str,
|
||||
uid: u32,
|
||||
gid: u32,
|
||||
name: &'a str,
|
||||
home: &'a str,
|
||||
shell: &'a str
|
||||
}
|
||||
|
||||
impl<'a> Passwd<'a> {
|
||||
pub fn parse(line: &'a str) -> Result<Passwd<'a>, ()> {
|
||||
let mut parts = line.split(';');
|
||||
|
||||
let user = parts.next().ok_or(())?;
|
||||
let hash = parts.next().ok_or(())?;
|
||||
let uid = parts.next().ok_or(())?.parse::<u32>().or(Err(()))?;
|
||||
let gid = parts.next().ok_or(())?.parse::<u32>().or(Err(()))?;
|
||||
let name = parts.next().ok_or(())?;
|
||||
let home = parts.next().ok_or(())?;
|
||||
let shell = parts.next().ok_or(())?;
|
||||
|
||||
Ok(Passwd {
|
||||
user: user,
|
||||
hash: hash,
|
||||
uid: uid,
|
||||
gid: gid,
|
||||
name: name,
|
||||
home: home,
|
||||
shell: shell
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Group<'a> {
|
||||
group: &'a str,
|
||||
gid: u32,
|
||||
users: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Group<'a> {
|
||||
pub fn parse(line: &'a str) -> Result<Group<'a>, ()> {
|
||||
let mut parts = line.split(';');
|
||||
|
||||
let group = parts.next().ok_or(())?;
|
||||
let gid = parts.next().ok_or(())?.parse::<u32>().or(Err(()))?;
|
||||
let users = parts.next().ok_or(())?;
|
||||
|
||||
Ok(Group {
|
||||
group: group,
|
||||
gid: gid,
|
||||
users: users
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut args = env::args().skip(1);
|
||||
let cmd = args.next().expect("sudo: no command provided");
|
||||
|
||||
let uid = syscall::getuid().unwrap() as u32;
|
||||
|
||||
if uid != 0 {
|
||||
let mut passwd_string = String::new();
|
||||
File::open("file:etc/passwd").unwrap().read_to_string(&mut passwd_string).unwrap();
|
||||
|
||||
let mut passwd_option = None;
|
||||
for line in passwd_string.lines() {
|
||||
if let Ok(passwd) = Passwd::parse(line) {
|
||||
if uid == passwd.uid {
|
||||
passwd_option = Some(passwd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let passwd = passwd_option.expect("sudo: user not found in passwd");
|
||||
|
||||
let mut group_string = String::new();
|
||||
File::open("file:etc/group").unwrap().read_to_string(&mut group_string).unwrap();
|
||||
|
||||
let mut group_option = None;
|
||||
for line in group_string.lines() {
|
||||
if let Ok(group) = Group::parse(line) {
|
||||
if group.group == "sudo" && group.users.split(',').any(|name| name == passwd.user) {
|
||||
group_option = Some(group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if group_option.is_none() {
|
||||
panic!("sudo: '{}' not in sudo group", passwd.user);
|
||||
}
|
||||
}
|
||||
|
||||
let mut command = Command::new(&cmd);
|
||||
for arg in args {
|
||||
command.arg(&arg);
|
||||
}
|
||||
|
||||
command.uid(0);
|
||||
command.gid(0);
|
||||
command.env("USER", "root");
|
||||
|
||||
match command.spawn() {
|
||||
Ok(mut child) => match child.wait() {
|
||||
Ok(status) => process::exit(status.code().unwrap_or(0)),
|
||||
Err(err) => panic!("sudo: failed to wait for {}: {}", cmd, err)
|
||||
},
|
||||
Err(err) => panic!("sudo: failed to execute {}: {}", cmd, err)
|
||||
}
|
||||
}
|
1
programs/userutils
Submodule
1
programs/userutils
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit eaf26765c12efe5519fb2af72557dc0ee8286bcd
|
Loading…
Reference in a new issue