git.lucas.co / cce-display-manager
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 }