login greeter
git clone https://git.lucas.co/cce-display-manager.git
tests/session_worker.rs (1.7K)
1 //! The session worker is a separate process now (`--session-worker`), run by
2 //! the root daemon with the password on its stdin. These run the real binary
3 //! as the (non-root) test user and check the two ways it must refuse before
4 //! it goes anywhere near PAM.
5
6 use std::io::Write;
7 use std::process::{Command, Stdio};
8
9 fn worker(args: &[&str]) -> std::process::Output {
10 let mut child = Command::new(env!("CARGO_BIN_EXE_cce-display-manager"))
11 .args(args)
12 .stdin(Stdio::piped())
13 .stdout(Stdio::piped())
14 .stderr(Stdio::piped())
15 .spawn()
16 .expect("run the binary");
17 // A worker that refuses early may not read this; ignore EPIPE.
18 let _ = child.stdin.take().unwrap().write_all(b"not-a-password");
19 child.wait_with_output().expect("wait")
20 }
21
22 /// Anyone can run the installed binary. As a user it must not open a PAM
23 /// session or report one — and it checks before reading the password.
24 #[test]
25 fn a_non_root_session_worker_refuses() {
26 if unsafe { libc_getuid() } == 0 {
27 eprintln!("running as root; the refusal is not what this run can test");
28 return;
29 }
30 let out = worker(&["--session-worker", "tty1", "nobody", "true", "bash"]);
31 assert_eq!(out.status.code(), Some(1), "{out:?}");
32 assert!(out.stdout.is_empty(), "no SESSION_ID line: {:?}", String::from_utf8_lossy(&out.stdout));
33 }
34
35 /// A malformed worker argv is an error, not a fall-through into the daemon
36 /// (which, as root, would start a second greeter on the tty).
37 #[test]
38 fn a_malformed_session_worker_argv_is_an_error() {
39 let out = worker(&["--session-worker", "tty1"]);
40 assert_eq!(out.status.code(), Some(2), "{out:?}");
41 }
42
43 extern "C" {
44 #[link_name = "getuid"]
45 fn libc_getuid() -> u32;
46 }