Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fifth batch of FreeBSD changes for the compliance test suite #922

Merged
merged 8 commits into from
Dec 2, 2024
27 changes: 16 additions & 11 deletions test-framework/sudo-compliance-tests/src/su/flag_shell.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sudo_test::{Command, Env, TextFile, User, BIN_TRUE};
use sudo_test::{Command, Env, TextFile, User, BIN_BASH, BIN_TRUE};

use crate::{Result, PASSWORD, USERNAME};

Expand Down Expand Up @@ -182,7 +182,7 @@ echo {message}"
format!(
"# {restricted_shell_path}
/usr/bin/sh
/usr/bin/bash"
{BIN_BASH}"
),
)
.user(invoking_user)
Expand Down Expand Up @@ -213,13 +213,18 @@ echo {message}"
#[test]
fn when_no_etc_shells_file_uses_a_default_list() -> Result<()> {
let default_list = ["/bin/sh"];
let not_in_list = [
"/bin/bash",
"/usr/bin/bash",
"/usr/bin/sh",
"/bin/dash",
"/usr/bin/dash",
];
let not_in_list = if cfg!(target_os = "freebsd") {
&["/usr/local/bin/bash", "/usr/local/bin/dash"][..]
} else {
&[
"/bin/bash",
"/usr/bin/bash",
"/usr/bin/sh",
"/bin/dash",
"/usr/bin/dash",
BIN_BASH,
][..]
};
let invoking_user = USERNAME;
let target_user = "ghost";

Expand Down Expand Up @@ -282,13 +287,13 @@ fn shell_canonical_path_is_not_used_when_determining_if_shell_is_restricted_or_n
let shell = "/tmp/bash-symlink";

let env = Env("")
.file("/etc/shells", "/usr/bin/bash")
.file("/etc/shells", BIN_BASH)
.user(invoking_user)
.user(User(target_user).shell(shell).password(PASSWORD))
.build()?;

Command::new("ln")
.args(["-s", "/usr/bin/bash", shell])
.args(["-s", BIN_BASH, shell])
.output(&env)?
.assert_success()?;

Expand Down
1 change: 1 addition & 0 deletions test-framework/sudo-compliance-tests/src/su/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use sudo_test::{Command, Env, User};
use crate::{Result, PASSWORD, USERNAME};

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't support /etc/security")]
squell marked this conversation as resolved.
Show resolved Hide resolved
fn etc_security_limits_rules_apply_according_to_the_target_user() -> Result<()> {
let target_user = "ghost";
let original = "2048";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,19 @@ fn sigwinch_works(use_pty: bool) -> Result<()> {
}

#[test]
#[cfg_attr(
bjorn3 marked this conversation as resolved.
Show resolved Hide resolved
target_os = "freebsd",
ignore = "gh924: podman on freebsd puts each docker exec command in a jail with separate /dev/pts"
)]
fn sigwinch_works_pty() -> Result<()> {
sigwinch_works(true)
}

#[test]
#[cfg_attr(
target_os = "freebsd",
ignore = "gh924: podman on freebsd puts each docker exec command in a jail with separate /dev/pts"
)]
fn sigwinch_works_no_pty() -> Result<()> {
sigwinch_works(false)
}
4 changes: 2 additions & 2 deletions test-framework/sudo-compliance-tests/src/sudo/flag_login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ echo $@";
#[test]
fn shell_is_invoked_as_a_login_shell() -> Result<()> {
let env = Env(SUDOERS_ALL_ALL_NOPASSWD)
.user(User(USERNAME).shell("/bin/bash"))
.user(User(USERNAME).shell("/bin/sh"))
.build()?;

let expected = "-bash";
let expected = "-sh";
let actual = Command::new("sudo")
.args(["-u", "ferris", "-i", "echo", "$0"])
.output(&env)?
Expand Down
6 changes: 3 additions & 3 deletions test-framework/sudo-compliance-tests/src/sudo/flag_shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,13 @@ fn shell_is_not_invoked_as_a_login_shell() -> Result<()> {
let env = Env(SUDOERS_ALL_ALL_NOPASSWD).build()?;

let actual = Command::new("env")
.args(["SHELL=/bin/bash", "sudo", "-s", "echo", "$0"])
.args(["SHELL=/bin/sh", "sudo", "-s", "echo", "$0"])
.output(&env)?
.stdout()?;

// man bash says "A login shell is one whose first character of argument zero is a -"
assert_ne!("-bash", actual);
assert_eq!("/bin/bash", actual);
assert_ne!("-sh", actual);
assert_eq!("/bin/sh", actual);

Ok(())
}
Expand Down
8 changes: 8 additions & 0 deletions test-framework/sudo-compliance-tests/src/sudo/pam/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ fn remove_comments_and_whitespace(contents: &str) -> String {
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn stock_pam_d_sudo() -> Result<()> {
let env = Env("").build()?;

Expand Down Expand Up @@ -70,6 +71,7 @@ fn stock_pam_d_sudo() -> Result<()> {
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn preserves_pam_env() -> Result<()> {
let set_name = "SET_VAR";
let set_value = "set";
Expand Down Expand Up @@ -101,6 +103,7 @@ fn preserves_pam_env() -> Result<()> {
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn pam_env_has_precedence_over_callers_env() -> Result<()> {
let set_name = "SET_VAR";
let set_value = "set";
Expand Down Expand Up @@ -180,16 +183,19 @@ fn env_list_has_precendece_over_pam_env(env_list: EnvList) -> Result<()> {
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn env_keep_has_precedence_over_pam_env() -> Result<()> {
env_list_has_precendece_over_pam_env(EnvList::Keep)
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn env_check_has_precedence_over_pam_env() -> Result<()> {
env_list_has_precendece_over_pam_env(EnvList::Check)
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn var_rejected_by_env_check_falls_back_to_pam_env_value() -> Result<()> {
let set_name = "SET_VAR";
let set_value = "set";
Expand Down Expand Up @@ -233,6 +239,7 @@ fn var_rejected_by_env_check_falls_back_to_pam_env_value() -> Result<()> {
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn default_and_override_pam_env_vars_are_parentheses_checked_but_set_vars_are_not() -> Result<()> {
let set_name = "SET_VAR";
let set_value = "() set";
Expand Down Expand Up @@ -264,6 +271,7 @@ fn default_and_override_pam_env_vars_are_parentheses_checked_but_set_vars_are_no
}

#[test]
#[cfg_attr(target_os = "freebsd", ignore = "FreeBSD doesn't have pam_env.so")]
fn pam_env_vars_are_not_env_checked() -> Result<()> {
let set_name = "SET_VAR";
let set_value = "%set";
Expand Down
24 changes: 16 additions & 8 deletions test-framework/sudo-compliance-tests/src/sudo/path_search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,23 @@ fn paths_are_matched_using_realpath_in_arguments() -> Result<()> {
fn arg0_native_is_passed_from_commandline() -> Result<()> {
let env = Env(SUDOERS_ALL_ALL_NOPASSWD).build()?;

let output = Command::new("sh")
.args([
"-c",
"ln -s /bin /nib; sudo /nib/sleep --invalid-flag; true",
])
.output(&env)?;
// On FreeBSD awk is one of the few programs which print arg0 in error messages. On Linux
// however it doesn't print arg0 unlike most programs, so we use a random program instead.
if cfg!(target_os = "freebsd") {
let output = Command::new("sh")
.args(["-c", "ln -s /usr/bin /nib; sudo /nib/awk --invalid-flag; true"])
.output(&env)?;

let stderr = output.stderr();
assert_starts_with!(stderr, "/nib/awk:");
} else {
let output = Command::new("sh")
.args(["-c", "ln -s /bin /nib; sudo /nib/ls --invalid-flag; true"])
.output(&env)?;

let stderr = output.stderr();
assert_starts_with!(stderr, "/nib/sleep:");
let stderr = output.stderr();
assert_starts_with!(stderr, "/nib/ls:");
}

Ok(())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ ALL ALL=(ALL:ALL) NOPASSWD: ALL")
.file(path, TextFile("#!/bin/sh").chmod("100"))
.build()?;

let match_in_relative_path_when_path_is_unset = "unset PATH; cd /bin; /usr/bin/sudo true";
// `true` is in `/usr/bin/`
let match_in_relative_path_when_path_is_unset = "unset PATH; cd /usr/bin; /usr/bin/sudo true";
let match_in_absolute_path_when_path_is_unset = "unset PATH; cd /; /usr/bin/sudo my-script";
// `true` is in `/usr/bin/true`
let match_in_relative_path_when_path_is_set = "export PATH=/usr/bin; cd /bin; sudo true";
// default PATH does not include `/root`
let match_in_absolute_path_when_path_is_set = "cd /; /usr/bin/sudo my-script";
let match_in_relative_path_when_path_is_set = "export PATH=/tmp; cd /usr/bin; /usr/bin/sudo true";
let match_in_absolute_path_when_path_is_set = "export PATH=/tmp; cd /; /usr/bin/sudo my-script";

let scripts = [
match_in_relative_path_when_path_is_unset,
Expand Down
8 changes: 8 additions & 0 deletions test-framework/sudo-test/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ pub const BIN_TRUE: &str = "/usr/bin/true";

/// The path to the `false` binary.
pub const BIN_FALSE: &str = "/usr/bin/false";

/// The path to the `bash` binary.
#[cfg(not(target_os = "freebsd"))]
pub const BIN_BASH: &str = "/usr/bin/bash";

/// The path to the `bash` binary.
#[cfg(target_os = "freebsd")]
pub const BIN_BASH: &str = "/usr/local/bin/bash";