From 8fffeb1e579fefb11d5852d90e09b3a8ff4147b5 Mon Sep 17 00:00:00 2001 From: MggMuggins Date: Sun, 26 Nov 2017 16:53:37 -0600 Subject: [PATCH 1/4] Implemented groupadd, fix for passwd compile --- Cargo.lock | 26 ++++++++++--- Cargo.toml | 8 +++- README.md | 3 +- src/bin/groupadd.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/bin/passwd.rs | 4 +- 5 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 src/bin/groupadd.rs diff --git a/Cargo.lock b/Cargo.lock index efb0c144be..99ac82a1d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,10 +8,18 @@ name = "argon2rs" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.7.0" @@ -19,9 +27,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2-rfc" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -65,6 +74,11 @@ dependencies = [ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rand" version = "0.3.18" @@ -90,7 +104,6 @@ dependencies = [ [[package]] name = "redox_users" version = "0.1.0" -source = "git+https://github.com/redox-os/users.git#77ce04ba3c2a1e4731e75eb58984598fa8937880" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", @@ -128,25 +141,26 @@ dependencies = [ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.1.0 (git+https://github.com/redox-os/users.git)", + "redox_users 0.1.0", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] "checksum arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)" = "" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" +"checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "" "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f9e406164c25b420480023985bdf65cef366855666ad4cb12cd3eaee82dcb399" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum redox_users 0.1.0 (git+https://github.com/redox-os/users.git)" = "" "checksum scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4ea459fe3ceff01e09534847c49860891d3ff1c12b4eb7731b67f2778fb60190" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" diff --git a/Cargo.toml b/Cargo.toml index 2b1bea0415..9bd6388f3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,17 @@ name = "userutils" version = "0.1.0" +[[bin]] +name = "id" +path = "src/bin/id.rs" + [[bin]] name = "getty" path = "src/bin/getty.rs" [[bin]] -name = "id" -path = "src/bin/id.rs" +name = "groupadd" +path = "src/bin/groupadd.rs" [[bin]] name = "login" diff --git a/README.md b/README.md index a0de2e5b74..62870c925f 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,5 @@ inspiration by BSD systems. They are indeed small, by choice. - `passwd`: Allows users to modify their passwords. - `su`: Allows users to substitute identity. - `sudo`: Enables users to execute a command as another user. -- `whoami`: Display effective user ID. \ No newline at end of file +- `groupadd`: Add a user group +- `whoami`: Display effective user ID. diff --git a/src/bin/groupadd.rs b/src/bin/groupadd.rs new file mode 100644 index 0000000000..1edac7f625 --- /dev/null +++ b/src/bin/groupadd.rs @@ -0,0 +1,90 @@ +#[deny(dead_code)] + +extern crate arg_parser; +extern crate extra; +extern crate redox_users; + +use extra::option::OptionalExt; + +use std::{io, env}; +use std::io::Write; +use std::process::exit; + +use arg_parser::ArgParser; +use redox_users::{add_group, get_uid, get_unique_group_id}; + +const MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#" +NAME + groupadd - add a user group + +SYNOPSIS + groupadd [ -f | --force ] group + groupadd [ -h | --help ] + +DESCRIPTION + The groupadd utility adds a new user group using values + passed on the command line and system defaults. + +OPTIONS + + -f, --force + Simply forces the exit status of the program to 0 + even if the group already exists. A message is still + printed to stdout. + + -h, --help + Display this help and exit. + +AUTHOR + Written by Wesley Hershberger. +"#; /* @MANEND */ + +fn main() { + let stdout = io::stdout(); + let mut stdout = stdout.lock(); + let mut stderr = io::stderr(); + + let mut parser = ArgParser::new(1) + .add_flag(&["h", "help"]) + .add_flag(&["f", "force"]); + parser.parse(env::args()); + + // Shows the help + if parser.found("help") { + stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr); + stdout.flush().try(&mut stderr); + exit(0); + } + + if get_uid() != 0 { + eprintln!("groupadd: privelege elevation required"); + exit(1); + } + + let groupname = if parser.args.is_empty() { + eprintln!("groupadd: no group name specified"); + exit(1); + } else { + &parser.args[0] + }; + + let gid = match get_unique_group_id() { + Some(gid) => gid, + None => { + eprintln!("groupadd: no available gid"); + exit(1); + } + }; + + match add_group(groupname, gid, &[""]) { + Ok(_) => {}, + Err(err) => { + eprintln!("groupadd: {}: {}", err, groupname); + if parser.found("force") { + exit(0); + } else { + exit(1); + } + } + } +} diff --git a/src/bin/passwd.rs b/src/bin/passwd.rs index c644811be6..46064b32b7 100644 --- a/src/bin/passwd.rs +++ b/src/bin/passwd.rs @@ -1,4 +1,4 @@ -#![deny(warnings)] +#![deny(dead_code)] extern crate arg_parser; extern crate extra; @@ -136,4 +136,4 @@ fn main() { eprintln!("passwd: you do not have permission to set the password of '{}'", user.user); exit(1); } -} \ No newline at end of file +} From 464b5c4aa5ddb4e7a021713f84e1347a30a95f54 Mon Sep 17 00:00:00 2001 From: MggMuggins Date: Mon, 27 Nov 2017 17:53:11 -0600 Subject: [PATCH 2/4] Small fixes to better mesh with redox_users changes --- src/bin/groupadd.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/bin/groupadd.rs b/src/bin/groupadd.rs index 1edac7f625..252f6c9862 100644 --- a/src/bin/groupadd.rs +++ b/src/bin/groupadd.rs @@ -11,7 +11,7 @@ use std::io::Write; use std::process::exit; use arg_parser::ArgParser; -use redox_users::{add_group, get_uid, get_unique_group_id}; +use redox_users::{add_group, get_unique_group_id}; const MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#" NAME @@ -56,11 +56,6 @@ fn main() { exit(0); } - if get_uid() != 0 { - eprintln!("groupadd: privelege elevation required"); - exit(1); - } - let groupname = if parser.args.is_empty() { eprintln!("groupadd: no group name specified"); exit(1); @@ -79,8 +74,9 @@ fn main() { match add_group(groupname, gid, &[""]) { Ok(_) => {}, Err(err) => { - eprintln!("groupadd: {}: {}", err, groupname); - if parser.found("force") { + eprintln!("groupadd: {}: group {}", err, groupname); + let msg = format!("{}", err); + if parser.found("force") && msg == "user already exists" { exit(0); } else { exit(1); From d9d3635916f7b0edb341e3e3309364d1a87e4f30 Mon Sep 17 00:00:00 2001 From: MggMuggins Date: Tue, 28 Nov 2017 21:39:20 -0600 Subject: [PATCH 3/4] Implemented useradd; groupadd fix --- Cargo.lock | 4 +- Cargo.toml | 4 ++ src/bin/groupadd.rs | 13 ++-- src/bin/login.rs | 1 - src/bin/passwd.rs | 2 +- src/bin/sudo.rs | 2 +- src/bin/useradd.rs | 170 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 src/bin/useradd.rs diff --git a/Cargo.lock b/Cargo.lock index 99ac82a1d8..7465f76b30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,6 +104,7 @@ dependencies = [ [[package]] name = "redox_users" version = "0.1.0" +source = "git+https://github.com/redox-os/users.git#50f4022e6c713a131bbbfde360cb0f369e96c672" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", @@ -141,7 +142,7 @@ dependencies = [ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.1.0", + "redox_users 0.1.0 (git+https://github.com/redox-os/users.git)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -161,6 +162,7 @@ dependencies = [ "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_users 0.1.0 (git+https://github.com/redox-os/users.git)" = "" "checksum scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4ea459fe3ceff01e09534847c49860891d3ff1c12b4eb7731b67f2778fb60190" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" diff --git a/Cargo.toml b/Cargo.toml index 9bd6388f3f..652998ea8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,10 @@ path = "src/bin/su.rs" name = "sudo" path = "src/bin/sudo.rs" +[[bin]] +name = "useradd" +path = "src/bin/useradd.rs" + [[bin]] name = "whoami" path = "src/bin/whoami.rs" diff --git a/src/bin/groupadd.rs b/src/bin/groupadd.rs index 252f6c9862..91ee1e23b7 100644 --- a/src/bin/groupadd.rs +++ b/src/bin/groupadd.rs @@ -1,4 +1,4 @@ -#[deny(dead_code)] +#![deny(warnings)] extern crate arg_parser; extern crate extra; @@ -26,7 +26,6 @@ DESCRIPTION passed on the command line and system defaults. OPTIONS - -f, --force Simply forces the exit status of the program to 0 even if the group already exists. A message is still @@ -73,14 +72,12 @@ fn main() { match add_group(groupname, gid, &[""]) { Ok(_) => {}, + Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists && parser.found("force") => { + exit(0); + }, Err(err) => { eprintln!("groupadd: {}: group {}", err, groupname); - let msg = format!("{}", err); - if parser.found("force") && msg == "user already exists" { - exit(0); - } else { - exit(1); - } + exit(1); } } } diff --git a/src/bin/login.rs b/src/bin/login.rs index 84f06fd34b..4c96687652 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -114,4 +114,3 @@ pub fn main() { } } } - diff --git a/src/bin/passwd.rs b/src/bin/passwd.rs index 46064b32b7..8d2f088060 100644 --- a/src/bin/passwd.rs +++ b/src/bin/passwd.rs @@ -1,4 +1,4 @@ -#![deny(dead_code)] +#![deny(warnings)] extern crate arg_parser; extern crate extra; diff --git a/src/bin/sudo.rs b/src/bin/sudo.rs index 0801a1965f..07d6c54fb2 100644 --- a/src/bin/sudo.rs +++ b/src/bin/sudo.rs @@ -150,4 +150,4 @@ fn run_command_as_root(cmd: &str, args: &Vec) { exit(1); } } -} \ No newline at end of file +} diff --git a/src/bin/useradd.rs b/src/bin/useradd.rs new file mode 100644 index 0000000000..ba15ccd928 --- /dev/null +++ b/src/bin/useradd.rs @@ -0,0 +1,170 @@ +#![deny(warnings)] + +extern crate arg_parser; +extern crate redox_users; + +use std::{env, io}; +use std::io::Write; +use std::fs::DirBuilder; +use std::os::unix::fs::DirBuilderExt; +use std::process::exit; + +use arg_parser::ArgParser; +use redox_users::{add_group, add_user, get_unique_group_id, get_unique_user_id}; + +const MAN_PAGE: &'static str = /* @MANSTART{useradd} */ r#" +NAME + useradd - add a new user + +SYNOPSYS + useradd [ options ] LOGIN + useradd [ -h | --help ] + +DESCRIPTION + The useradd utility creates a new user based on + system defaults and values passed on the command line. + + Useradd creates a new group for the user by default and + can also be instructed to create the user's home directory. + +OPTIONS + -h, --help + Display this help and exit. + + -c, --comment + Any text string, usually used as the user's full name. + + -d, --home-dir HOME_DIR + The new user will be created with HOME_DIR as their home + directory. The default value is LOGIN prepended with "/home". + This flag DOES NOT create the home directory. See --create-home. + + -m, --create-home + Creates the user's home directory if it does not already exist. + + This option is not enabled by default. This option must be specified + for a home directory to be created. + + -N, --no-user-group + Do not attempt to create the user's user group. + + -s, --shell SHELL + The path to the user's default login shell. If left blank, the + default shell is set as /bin/ion + +AUTHORS + Written by Wesley Hershberger. +"#; /* @MANEND */ +const DEFAULT_SHELL: &'static str = "/bin/ion"; +const DEFAULT_HOME: &'static str = "/home"; +const DEFAULT_MODE: u32 = 0o700; + +fn main() { + let mut stdout = io::stdout(); + + let mut parser = ArgParser::new(1) + .add_flag(&["h", "help"]) + .add_opt("c", "comment") + .add_opt("d", "home-dir") + .add_flag(&["m", "create-home"]) + .add_flag(&["N", "no-user-group"]) + .add_opt("s", "shell"); + parser.parse(env::args()); + + if parser.found("help") { + stdout.write_all(MAN_PAGE.as_bytes()).unwrap(); + stdout.flush().unwrap(); + exit(0); + } + + let login = if parser.args.is_empty() { + eprintln!("useradd: no login specified"); + exit(1); + } else { + &parser.args[0] + }; + + let uid = match get_unique_user_id() { + Some(id) => id, + None => { + eprintln!("useradd: no available uid"); + exit(1); + } + }; + + let gid = match get_unique_group_id() { + Some(id) => id, + None => { + eprintln!("useradd: no available gid"); + exit(1); + } + }; + + let username = if parser.found("comment") { + match parser.get_opt("comment") { + Some(user) => user, + None => { + eprintln!("useradd: invalid argument: -c"); + exit(1); + } + } + } else { + login.to_owned() + }; + + let userhome = if parser.found("home-dir") { + match parser.get_opt("home-dir") { + Some(dir) => dir, + None => { + eprintln!("useradd: invalid argument: -d"); + exit(1); + } + } + } else { + format!("{}/{}", DEFAULT_HOME, login) + }; + + let shell = if parser.found("shell") { + match parser.get_opt("shell") { + Some(sh) => sh, + None => { + eprintln!("useradd: invalid argument: -s"); + exit(1); + } + } + } else { + DEFAULT_SHELL.to_string() + }; + + if !parser.found("no-user-group") { + match add_group(login, gid, &[login]) { + Ok(_) => {}, + Err(err) => { + eprintln!("useradd: error creating group {}: {}", login, err); + exit(1); + } + } + } + + match add_user(login, uid, gid, username.as_str(), userhome.as_str(), shell.as_str()) { + Ok(_) => {}, + Err(err) => { + eprintln!("useradd: {}: {}", err, login); + exit(1); + } + } + + if parser.found("create-home") { + let mut builder = DirBuilder::new(); + builder.mode(DEFAULT_MODE); + + match builder.create(&userhome) { + Ok(_) => {}, + Err(ref err) if err.kind() == io::ErrorKind::AlreadyExists => {}, + Err(err) => { + eprintln!("useradd: failed to create home dir: {}", err); + exit(1); + } + }; + } +} From 65817077ee54407284fcb6b9ac1356de6ec81cdf Mon Sep 17 00:00:00 2001 From: MggMuggins Date: Tue, 28 Nov 2017 22:10:45 -0600 Subject: [PATCH 4/4] Cargo.lock update --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 7465f76b30..c5ce4e8a8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,7 +104,7 @@ dependencies = [ [[package]] name = "redox_users" version = "0.1.0" -source = "git+https://github.com/redox-os/users.git#50f4022e6c713a131bbbfde360cb0f369e96c672" +source = "git+https://github.com/redox-os/users.git#83ea6d2c6d3ea1e3082e4bd8d15633d0f03d3137" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)",