Match nologin shells by file name, not full path
The nologin filter compared against fixed FHS paths, so accounts whose shell lives elsewhere passed through. On NixOS the 32 nixbld build users have UIDs in the 30001-30032 range and a shell at /run/current-system/sw/bin/nologin, and were listed as login candidates. Comparing the file name instead covers every distribution layout.
This commit is contained in:
Generated
+1
-1
@@ -575,7 +575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "moongreet"
|
||||
version = "0.10.1"
|
||||
version = "0.10.2"
|
||||
dependencies = [
|
||||
"gdk-pixbuf",
|
||||
"gdk4",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "moongreet"
|
||||
version = "0.10.1"
|
||||
version = "0.10.2"
|
||||
edition = "2024"
|
||||
description = "A greetd greeter for Wayland with GTK4 and Layer Shell"
|
||||
license = "MIT"
|
||||
|
||||
+36
-8
@@ -11,13 +11,12 @@ const DEFAULT_PASSWD: &str = "/etc/passwd";
|
||||
const DEFAULT_ACCOUNTSSERVICE_DIR: &str = "/var/lib/AccountsService/icons";
|
||||
const GRESOURCE_PREFIX: &str = "/dev/moonarch/moongreet";
|
||||
|
||||
/// Shells that indicate a user cannot log in.
|
||||
const NOLOGIN_SHELLS: &[&str] = &[
|
||||
"/usr/sbin/nologin",
|
||||
"/sbin/nologin",
|
||||
"/bin/false",
|
||||
"/usr/bin/nologin",
|
||||
];
|
||||
/// Shell file names that indicate a user cannot log in.
|
||||
///
|
||||
/// Matched on the file name rather than the full path: distributions place
|
||||
/// these binaries in different locations, and on NixOS the path is
|
||||
/// /run/current-system/sw/bin/nologin.
|
||||
const NOLOGIN_SHELLS: &[&str] = &["nologin", "false"];
|
||||
|
||||
/// Represents a system user suitable for login.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -73,7 +72,11 @@ pub fn get_users(passwd_path: Option<&Path>) -> Vec<User> {
|
||||
if !(MIN_UID..=MAX_UID).contains(&uid) {
|
||||
continue;
|
||||
}
|
||||
if NOLOGIN_SHELLS.contains(&shell) {
|
||||
let shell_name = Path::new(shell)
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.unwrap_or(shell);
|
||||
if NOLOGIN_SHELLS.contains(&shell_name) {
|
||||
continue;
|
||||
}
|
||||
// Path traversal prevention
|
||||
@@ -194,6 +197,31 @@ mod tests {
|
||||
assert!(users.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_nologin_users_at_any_path() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = make_passwd(
|
||||
dir.path(),
|
||||
"nixbld1:x:30001:30000:Nix build user 1:/var/empty:/run/current-system/sw/bin/nologin\n\
|
||||
svc:x:1001:1001::/var/empty:/nix/store/abc123-shadow-4.17.4/bin/nologin\n\
|
||||
disabled:x:1002:1002::/home/disabled:/run/current-system/sw/bin/false\n",
|
||||
);
|
||||
let users = get_users(Some(&path));
|
||||
assert!(users.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keep_login_shell_with_similar_name() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = make_passwd(
|
||||
dir.path(),
|
||||
"alice:x:1000:1000:Alice:/home/alice:/run/current-system/sw/bin/zsh\n",
|
||||
);
|
||||
let users = get_users(Some(&path));
|
||||
assert_eq!(users.len(), 1);
|
||||
assert_eq!(users[0].username, "alice");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_users_with_slash_in_name() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user