Working version

This commit is contained in:
Gijs Burghoorn 2021-12-31 16:04:29 +01:00
parent 5e57289de8
commit 62f5f88276
7 changed files with 474 additions and 394 deletions

395
Cargo.lock generated
View file

@ -2,24 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "argh"
version = "0.1.7"
@ -50,39 +32,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f8c380fa28aa1b36107cd97f0196474bb7241bb95a453c5c01a15ac74b2eac"
[[package]]
name = "atty"
version = "0.2.14"
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bindgen"
version = "0.55.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443"
dependencies = [
"bitflags",
"cexpr",
"cfg-if 0.1.10",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
@ -97,13 +50,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cexpr"
version = "0.4.0"
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
dependencies = [
"nom",
]
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
@ -118,29 +68,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.3.0"
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"glob",
"libc",
"libloading",
"libc 0.2.112",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "clap"
version = "2.34.0"
name = "chvt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
checksum = "885dc9d5804abecc1a08047b3dd3f9ce85e6900f956ea80c082bef47b7b148ef"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
"libc 0.2.112",
"nix 0.15.0",
]
[[package]]
@ -151,7 +98,7 @@ checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d"
dependencies = [
"bitflags",
"crossterm_winapi 0.8.0",
"libc",
"libc 0.2.112",
"mio",
"parking_lot",
"signal-hook",
@ -167,7 +114,7 @@ checksum = "c85525306c4291d1b73ce93c8acf9c339f9b213aef6c1d85c3830cbf1c16325c"
dependencies = [
"bitflags",
"crossterm_winapi 0.9.0",
"libc",
"libc 0.2.112",
"mio",
"parking_lot",
"signal-hook",
@ -194,27 +141,13 @@ dependencies = [
]
[[package]]
name = "enum-repr"
version = "0.2.6"
name = "fern"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18"
checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"chrono",
"log",
"regex",
"termcolor",
]
[[package]]
@ -224,16 +157,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"libc",
"libc 0.2.112",
"wasi",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "heck"
version = "0.3.3"
@ -243,24 +170,6 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -276,12 +185,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lemurs"
version = "0.1.0"
@ -289,32 +192,34 @@ dependencies = [
"argh",
"bitflags",
"cassowary",
"chrono",
"chvt",
"crossterm 0.22.1",
"pam-client",
"fern",
"log",
"nix 0.23.1",
"pam",
"pgs-files",
"rand",
"serde",
"simple-signal",
"tui",
"unicode-segmentation",
"unicode-width",
"users",
]
[[package]]
name = "libc"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]]
name = "libc"
version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]]
name = "libloading"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52"
dependencies = [
"cfg-if 1.0.0",
"winapi",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -334,10 +239,13 @@ dependencies = [
]
[[package]]
name = "memchr"
version = "2.4.1"
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
@ -345,7 +253,7 @@ version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
dependencies = [
"libc",
"libc 0.2.112",
"log",
"miow",
"ntapi",
@ -362,13 +270,29 @@ dependencies = [
]
[[package]]
name = "nom"
version = "5.1.2"
name = "nix"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
dependencies = [
"memchr",
"version_check",
"bitflags",
"cc",
"cfg-if 0.1.10",
"libc 0.2.112",
"void",
]
[[package]]
name = "nix"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
dependencies = [
"bitflags",
"cc",
"cfg-if 1.0.0",
"libc 0.2.112",
"memoffset",
]
[[package]]
@ -380,6 +304,25 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "numtoa"
version = "0.1.0"
@ -387,27 +330,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "pam-client"
version = "0.3.1"
name = "pam"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ad089b829c2f58605a72ca23f9387216001b3a67df345df9a42b473decd667"
checksum = "fa2bdc959c201c047004a1420a92aaa1dd1a6b64d5ef333aa3a4ac764fb93097"
dependencies = [
"bitflags",
"enum-repr",
"libc",
"libc 0.2.112",
"pam-sys",
"rpassword",
"rustversion",
"users",
]
[[package]]
name = "pam-sys"
version = "1.0.0-alpha3"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84d5e08cf74c37eb6bb11b8a2af8df35e24c3d45738f2ae1f7004ac30ed7cd09"
checksum = "cd4858311a097f01a0006ef7d0cd50bca81ec430c949d7bf95cbefd202282434"
dependencies = [
"bindgen",
"libc",
"libc 0.2.112",
]
[[package]]
@ -429,17 +368,20 @@ checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"libc 0.2.112",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
name = "pgs-files"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
checksum = "6a7b7d377867a5a16859f9521ea3b884438f6e3eb096ffd18014243125faf715"
dependencies = [
"libc 0.1.12",
]
[[package]]
name = "ppv-lite86"
@ -456,12 +398,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.14"
@ -477,7 +413,7 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"libc 0.2.112",
"rand_chacha",
"rand_core",
"rand_hc",
@ -529,45 +465,6 @@ dependencies = [
"redox_syscall",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rpassword"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustversion"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -594,19 +491,13 @@ dependencies = [
"syn",
]
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "signal-hook"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
dependencies = [
"libc",
"libc 0.2.112",
"signal-hook-registry",
]
@ -616,7 +507,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4"
dependencies = [
"libc",
"libc 0.2.112",
"mio",
"signal-hook",
]
@ -627,7 +518,17 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
"libc 0.2.112",
]
[[package]]
name = "simple-signal"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53f7da44adcc42667d57483bd93f81295f27d66897804b757573b61b6f13288b"
dependencies = [
"lazy_static",
"libc 0.2.112",
]
[[package]]
@ -636,12 +537,6 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.84"
@ -653,34 +548,27 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
dependencies = [
"libc",
"libc 0.2.112",
"numtoa",
"redox_syscall",
"redox_termios",
]
[[package]]
name = "textwrap"
version = "0.11.0"
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"unicode-width",
"libc 0.2.112",
"wasi",
"winapi",
]
[[package]]
@ -717,25 +605,18 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "users"
version = "0.11.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
checksum = "7fed7d0912567d35f88010c23dbaf865e9da8b5227295e8dc0f2fdd109155ab7"
dependencies = [
"libc",
"log",
"libc 0.2.112",
]
[[package]]
name = "vec_map"
version = "0.8.2"
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
@ -743,15 +624,6 @@ version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -768,15 +640,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View file

@ -11,7 +11,13 @@ unicode-segmentation = "1.2"
unicode-width = "0.1"
crossterm = { version = "0.22" }
serde = { version = "1", features = ["derive"]}
rand = "0.8"
argh = "0.1"
pam-client = "0.3.1"
users = "0.11.0"
pam = "0.7.0"
pgs-files = "0.0.7"
simple-signal = "1.1.0"
log = "0.4.0"
fern = "0.5.2"
chvt = "0.2.0"
rand = "0.8.4"
chrono = "0.4"
nix = "0.23.1"

View file

@ -0,0 +1,13 @@
use std::io;
use std::path::PathBuf;
use pgs_files::passwd::PasswdEntry;
pub trait GraphicalEnvironment {
fn start(&mut self, passwd_entry: &PasswdEntry) -> io::Result<()>;
fn desktop(&self, script: PathBuf, passwd_entry: &PasswdEntry, groups: &[u32]);
fn stop(&mut self);
}
mod x;
pub use x::X;

View file

@ -0,0 +1,122 @@
use nix::unistd::{initgroups, Uid, Gid, setuid, setgid};
use rand::Rng;
use std::env;
use std::io;
use std::os::unix::process::CommandExt;
use std::process::{Child, Command};
use std::{thread, time};
use std::fs::File;
use std::path::{Path, PathBuf};
use log::{error, info};
use super::GraphicalEnvironment;
use pgs_files::passwd::PasswdEntry;
const DISPLAY: &str = ":1";
const VIRTUAL_TERMINAL: &str = "vt01";
const SYSTEM_SHELL: &str = "/bin/sh";
pub fn mcookie() -> String {
let mut rng = rand::thread_rng();
let cookie: u128 = rng.gen();
format!("{:032x}", cookie)
}
pub struct X {
child: Option<Child>,
}
impl X {
pub fn new() -> Self {
Self { child: None }
}
}
impl GraphicalEnvironment for X {
fn start(&mut self, passwd_entry: &PasswdEntry) -> io::Result<()> {
if self.child.is_some() {
// TODO: Replace this with an error
error!("Server already started");
panic!("Server already started");
}
info!("Setup Xauth");
// Setup xauth
let xauth_dir =
PathBuf::from(env::var("XDG_CONFIG_HOME").unwrap_or(passwd_entry.dir.to_string()));
let xauth_path = xauth_dir.join(".Xauthority");
env::set_var("XAUTHORITY", xauth_path.clone());
env::set_var("DISPLAY", DISPLAY);
File::create(xauth_path).unwrap();
Command::new(SYSTEM_SHELL)
.arg("-c")
.arg(format!("/usr/bin/xauth add {} . {}", DISPLAY, mcookie()))
.status()
.unwrap(); // TODO: Remove unwrap
info!("Xauth setup");
info!("Starting X server");
// Start the X server
self.child = Some(
Command::new(SYSTEM_SHELL)
.arg("-c")
.arg(format!("/usr/bin/X {} {}", DISPLAY, VIRTUAL_TERMINAL))
.spawn()?,
);
info!("X server is booted!!!");
// Wait for XServer to boot-up
// TODO: There should be a better way of doing this.
thread::sleep(time::Duration::from_secs(1));
Ok(())
}
fn desktop(&self, script: PathBuf, passwd_entry: &PasswdEntry, _groups: &[u32]) {
// Init environment for current TTY
crate::pam::init_environment(&passwd_entry);
let uid = Uid::from_raw(passwd_entry.uid);
let gid = Gid::from_raw(passwd_entry.gid);
initgroups(
std::ffi::CString::new(passwd_entry.name.clone())
.unwrap()
.as_c_str(),
gid,
)
.unwrap();
setgid(gid).unwrap();
setuid(uid).unwrap();
let mut child = Command::new(SYSTEM_SHELL)
.arg("-c")
.arg(format!(
"{} {}",
"/etc/lemurs/xsetup.sh",
script.to_str().unwrap()
))
.uid(passwd_entry.uid)
.gid(passwd_entry.gid)
// .groups(groups)
.spawn()
.unwrap(); // TODO: Remove unwrap
child.wait().unwrap(); // TODO: Remove unwrap
}
fn stop(&mut self) {
if let Some(ref mut child) = self.child {
child.kill().unwrap(); // TODO: Remove unwrap
}
}
}

21
src/initrcs.rs Normal file
View file

@ -0,0 +1,21 @@
use crate::ui::WindowManager;
use std::fs;
const INITRCS_FOLDER_PATH: &str = "/etc/lemurs/wms";
pub fn get_window_managers() -> Vec<WindowManager> {
let wms = match fs::read_dir(INITRCS_FOLDER_PATH) {
Ok(paths) => paths,
Err(_) => return Vec::new(),
};
wms
.map(|entry| {
let entry = entry.unwrap();
WindowManager::new(
entry.file_name().into_string().unwrap(), // TODO: Remove unwrap
entry.path(),
)
})
.collect()
}

View file

@ -3,21 +3,22 @@ use crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::{error::Error, io, os::unix::prelude::MetadataExt};
use log::{error, info};
use std::{error::Error, io};
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Constraint, Direction, Layout},
style::{Color, Style},
text::Span,
widgets::{Block, Borders, Paragraph},
widgets::Paragraph,
Frame, Terminal,
};
use unicode_width::UnicodeWidthStr;
mod input_field;
mod window_manager_selector;
use input_field::{InputFieldDisplayType, InputFieldWidget};
use window_manager_selector::{WindowManager, WindowManagerSelectorWidget};
mod graphical_environments;
mod ui;
mod pam;
mod initrcs;
use graphical_environments::{GraphicalEnvironment, X};
use ui::{InputFieldDisplayType, InputFieldWidget, WindowManagerSelectorWidget};
enum InputMode {
WindowManager,
@ -42,38 +43,51 @@ struct App {
/// Error Message
error_msg: Option<AuthError>,
graphical_environment: X,
}
impl Default for App {
fn default() -> App {
App {
window_manager_widget: WindowManagerSelectorWidget::new(vec![
WindowManager::new(
"bspwm",
vec![("exec".to_string(), vec!["bspwm".to_string()])],
),
WindowManager::new("i3", vec![("exec".to_string(), vec!["i3".to_string()])]),
WindowManager::new(
"awesome",
vec![("exec".to_string(), vec!["awesome".to_string()])],
),
WindowManager::new(
"create file",
vec![(
"/usr/bin/touch".to_string(),
vec!["/home/gburghoorn/Projects/lemurs/test".to_string()],
)],
),
]),
window_manager_widget: WindowManagerSelectorWidget::new(initrcs::get_window_managers()),
username_widget: InputFieldWidget::new("Username", InputFieldDisplayType::Echo),
password_widget: InputFieldWidget::new("Password", InputFieldDisplayType::Replace('*')),
input_mode: InputMode::Normal,
error_msg: None,
graphical_environment: X::new(),
}
}
}
fn main() -> Result<(), Box<dyn Error>> {
fern::Dispatch::new()
// Perform allocation-free log formatting
.format(|out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.target(),
record.level(),
message
))
})
// Add blanket level filter -
.level(log::LevelFilter::Debug)
// - and per-module overrides
.level_for("hyper", log::LevelFilter::Info)
// Output to stdout, files, and other Dispatch configurations
.chain(fern::log_file("/tmp/lemurs.log")?)
// Apply globally
.apply()?;
info!("Lemurs booting up");
// de-hardcode 2
if chvt::chvt(2).is_err() {
error!("Couldn't change tty");
};
// setup terminal
enable_raw_mode()?;
let mut stdout = io::stdout();
@ -81,10 +95,14 @@ fn main() -> Result<(), Box<dyn Error>> {
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
info!("UI booted up");
// create app and run it
let app = App::default();
let res = run_app(&mut terminal, app);
info!("Finished running UI");
// restore terminal
disable_raw_mode()?;
execute!(
@ -94,10 +112,14 @@ fn main() -> Result<(), Box<dyn Error>> {
)?;
terminal.show_cursor()?;
info!("Reset terminal environment");
if let Err(err) = res {
println!("{:?}", err)
}
// TODO: Listen to signals
Ok(())
}
@ -145,51 +167,10 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<(
key_code => app.username_widget.key_press(key_code),
},
InputMode::Password => match key.code {
KeyCode::Enter => {
match authenticate(
app.username_widget.get_content(),
app.password_widget.get_content(),
) {
Err(err) => app.error_msg = Some(err),
Ok((mut context, uid)) => {
// Open session and initialize credentials
let session = match context.open_session(Flag::NONE) {
Err(_) => {
app.error_msg = Some(AuthError::SessionOpen);
continue;
}
Ok(session) => session,
};
// Run a process in the PAM environment
match app.window_manager_widget.selected() {
Some(wm) => {
for (cmd, args) in wm.cmds.iter() {
match Command::new(cmd)
.args(args)
.env_clear()
.envs(session.envlist().iter_tuples())
.uid(uid)
// .gid(...)
.spawn()
{
Ok(mut child) => match child.wait() {
Err(_) => {
app.error_msg = Some(AuthError::Child)
}
_ => {}
},
Err(_) => {
app.error_msg = Some(AuthError::CommandFail)
}
}
}
}
None => app.error_msg = Some(AuthError::Weird), // TODO: THink of something here
}
}
}
}
KeyCode::Enter => match login(&mut app) {
Err(err) => app.error_msg = Some(err),
_ => {}
},
KeyCode::Tab => {
if key.modifiers == KeyModifiers::SHIFT {
app.input_mode = InputMode::Username;
@ -204,7 +185,7 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> io::Result<(
key_code => app.password_widget.key_press(key_code),
},
}
}
}
}
}
@ -246,15 +227,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
use AuthError::*;
let error_widget = Paragraph::new(match error_msg {
PamContext => "Failed to initialize PAM context",
Authentication => "Authentication Failed",
AccountValidation => "Account validation failed",
UsernameNotFound => "Username not found",
UIDNotFound => "UID not found",
SessionOpen => "Failed to open session",
CommandFail => "Failed to run command",
Weird => "Weird error",
Child => "Child failed",
PamError(_) => "Authentication failed",
})
.style(Style::default().fg(Color::Red));
@ -262,56 +235,56 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
}
}
use pam_client::conv_mock::Conversation;
use pam_client::{Context, Flag};
use std::os::unix::process::CommandExt;
use std::process::Command;
use crate::pam::{open_session, PamError};
enum AuthError {
PamContext,
Authentication,
AccountValidation,
UsernameNotFound,
UIDNotFound,
SessionOpen,
CommandFail,
Weird,
Child,
PamError(PamError),
}
fn authenticate(
username: String,
password: String,
) -> Result<
(
pam_client::Context<pam_client::conv_mock::Conversation>,
u32,
),
AuthError,
> {
let mut context = Context::new(
"lemurs", // Service name
None,
Conversation::with_credentials(username, password),
)
.map_err(|_| AuthError::PamContext)?;
fn login(app: &mut App) -> Result<(), AuthError> {
// if (!testing) {
// signal(SIGSEGV, sig_handler);
// signal(SIGTRAP, sig_handler);
// }
// Authenticate the user
context
.authenticate(Flag::NONE)
.map_err(|_| AuthError::Authentication)?;
info!("Login attempt");
// Validate the account
context
.acct_mgmt(Flag::NONE)
.map_err(|_| AuthError::AccountValidation)?;
let username = app.username_widget.get_content();
let password = app.password_widget.get_content();
let initrc_path = app
.window_manager_widget
.selected()
.map(|selected| selected.initrc_path.clone())
.unwrap();
// Get resulting user name and map to a user id
let username = context.user().map_err(|_| AuthError::UsernameNotFound)?;
let uid = match users::get_user_by_name(&username) {
Some(user) => user.uid(), // Left as an exercise to the reader
None => return Err(AuthError::UIDNotFound),
};
info!(
"Gotten information. Username: '{}', Initrc_path: '{}'",
username,
initrc_path.to_str().unwrap_or("Not Found")
);
Ok((context, uid))
let (authenticator, passwd_entry, groups) =
open_session(username, password).map_err(|e| AuthError::PamError(e))?;
info!("Opened session");
info!("Booting X Server");
app.graphical_environment.start(&passwd_entry).unwrap(); // TODO: Remove unwrap
info!("X Server started");
info!("Booting Desktop");
app.graphical_environment
.desktop(initrc_path, &passwd_entry, &groups);
info!("Desktop shutdown");
app.graphical_environment.stop();
info!("X server shut down");
// Logout
drop(authenticator);
Ok(())
}

82
src/pam.rs Normal file
View file

@ -0,0 +1,82 @@
use log::{error, info};
use std::path::PathBuf;
use pam::{Authenticator, Converse};
use std::env;
use pgs_files::group::get_all_entries;
use pgs_files::passwd::{get_entry_by_name, PasswdEntry};
const SYSTEM_SHELL: &str = "/bin/sh";
pub enum PamError {
FailedToSpawn, // TODO: Add io::Result
Authentication,
AccountValidation,
UsernameNotFound,
SessionOpen,
EnvironmentError,
Child,
}
pub fn init_environment(passwd: &PasswdEntry) {
env::set_var("HOME", &passwd.dir);
env::set_var("PWD", &passwd.dir);
env::set_var("SHELL", &passwd.shell);
env::set_var("USER", &passwd.name);
env::set_var("LOGNAME", &passwd.name);
env::set_var("PATH", "/usr/local/sbin:/usr/local/bin:/usr/bin");
// env::set_var("MAIL", "..."); TODO: Add
}
pub fn open_session<'a>(
username: impl ToString,
password: impl ToString,
) -> Result<(Authenticator<'a, impl Converse>, PasswdEntry, Vec<u32>), PamError> {
let username = username.to_string();
let password = password.to_string();
info!("Started opening session");
let mut authenticator = Authenticator::with_password(
"login", // Service name
)
.map_err(|_| PamError::Authentication)?;
info!("Gotten Authenticator");
// Authenticate the user
authenticator
.get_handler()
.set_credentials(&username, &password);
info!("Got handler");
// Validate the account
authenticator
.authenticate()
.map_err(|_| PamError::AccountValidation)?;
info!("Validated");
// NOTE: Maybe we should also load all groups here
let passwd_entry = get_entry_by_name(&username).ok_or(PamError::UsernameNotFound)?;
let groups = get_all_entries()
.into_iter()
.filter(|entry| entry.members.contains(&username))
.map(|entry| entry.gid)
.collect();
// Init environment for current TTY
init_environment(&passwd_entry);
info!("Initiated environment");
authenticator
.open_session()
.map_err(|_| PamError::SessionOpen)?;
info!("Opened session");
// NOTE: Logout happens automatically here with `drop` of session and context
Ok((authenticator, passwd_entry, groups))
}