Skip to content

Commit 5875646

Browse files
committed
Add tests
1 parent 6648977 commit 5875646

File tree

2 files changed

+250
-0
lines changed

2 files changed

+250
-0
lines changed

test-framework/sudo-compliance-tests/src/sudo/pass_auth.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
// NOTE all these tests assume that the invoking user passes the sudoers file 'User_List' criteria
44

5+
mod askpass;
56
mod stdin;
67
mod tty;
78

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
use sudo_test::{Command, Env, TextFile, User};
2+
3+
use crate::{PASSWORD, USERNAME};
4+
5+
use super::MAX_PASSWORD_SIZE;
6+
7+
const CHMOD_EXEC: &str = "555";
8+
9+
fn generate_askpass(password: &str) -> TextFile {
10+
TextFile(format!("#!/bin/sh\necho {password}")).chmod(CHMOD_EXEC)
11+
}
12+
13+
#[test]
14+
fn correct_password() {
15+
let env = Env(format!("{USERNAME} ALL=(ALL:ALL) ALL"))
16+
.file("/bin/askpass", generate_askpass(PASSWORD))
17+
.user(User(USERNAME).password(PASSWORD))
18+
.build();
19+
20+
Command::new("sh")
21+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
22+
.as_user(USERNAME)
23+
.output(&env)
24+
.assert_success();
25+
}
26+
27+
#[test]
28+
fn incorrect_password() {
29+
let env = Env(format!("{USERNAME} ALL=(ALL:ALL) ALL"))
30+
.file("/bin/askpass", generate_askpass("incorrect-password"))
31+
.user(User(USERNAME).password("strong-password"))
32+
.build();
33+
34+
let output = Command::new("sh")
35+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
36+
.as_user(USERNAME)
37+
.output(&env);
38+
output.assert_exit_code(1);
39+
40+
let diagnostic = if sudo_test::is_original_sudo() {
41+
"incorrect password attempt"
42+
} else {
43+
"Authentication failed, try again."
44+
};
45+
assert_contains!(output.stderr(), diagnostic);
46+
}
47+
48+
#[test]
49+
fn no_password() {
50+
let env = Env(format!("{USERNAME} ALL=(ALL:ALL) ALL"))
51+
.file("/bin/askpass", TextFile("#!/bin/sh").chmod(CHMOD_EXEC))
52+
.user(User(USERNAME).password(PASSWORD))
53+
.build();
54+
55+
let output = Command::new("sh")
56+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
57+
.as_user(USERNAME)
58+
.output(&env);
59+
output.assert_exit_code(1);
60+
61+
let diagnostic = if sudo_test::is_original_sudo() {
62+
"no password was provided"
63+
} else {
64+
"Authentication required but not attempted"
65+
};
66+
assert_contains!(output.stderr(), diagnostic);
67+
}
68+
69+
#[test]
70+
fn longest_possible_password_works() {
71+
let password = "a".repeat(MAX_PASSWORD_SIZE);
72+
73+
let env = Env("ALL ALL=(ALL:ALL) ALL")
74+
.file("/bin/askpass", generate_askpass(&password))
75+
.user(User(USERNAME).password(&password))
76+
.build();
77+
78+
Command::new("sh")
79+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
80+
.as_user(USERNAME)
81+
.output(&env)
82+
.assert_success();
83+
}
84+
85+
#[test]
86+
fn input_longer_than_max_pam_response_size_is_handled_gracefully() {
87+
let input = "a".repeat(5 * MAX_PASSWORD_SIZE / 2);
88+
89+
let env = Env("ALL ALL=(ALL:ALL) ALL")
90+
.file("/bin/askpass", generate_askpass(&input))
91+
.user(USERNAME)
92+
.build();
93+
94+
let output = Command::new("sh")
95+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
96+
.as_user(USERNAME)
97+
.output(&env);
98+
99+
output.assert_exit_code(1);
100+
101+
let stderr = output.stderr();
102+
if sudo_test::is_original_sudo() {
103+
assert_contains!(stderr, "sudo: 3 incorrect password attempts");
104+
} else {
105+
assert_contains!(stderr, "Incorrect authentication attempt");
106+
assert_not_contains!(stderr, "panic");
107+
}
108+
}
109+
110+
#[test]
111+
fn input_longer_than_password_should_not_be_accepted_as_correct_password() {
112+
let password = "a".repeat(MAX_PASSWORD_SIZE);
113+
114+
let input_sizes = [MAX_PASSWORD_SIZE + 1, MAX_PASSWORD_SIZE + 2];
115+
116+
for input_size in input_sizes {
117+
let input = "a".repeat(input_size);
118+
119+
let env = Env("ALL ALL=(ALL:ALL) ALL")
120+
.file("/bin/askpass", generate_askpass(&input))
121+
.user(User(USERNAME).password(password.clone()))
122+
.build();
123+
124+
let output = Command::new("sh")
125+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
126+
.as_user(USERNAME)
127+
.output(&env);
128+
129+
output.assert_exit_code(1);
130+
131+
let stderr = output.stderr();
132+
if sudo_test::is_original_sudo() {
133+
assert_contains!(stderr, "sudo: 3 incorrect password attempt");
134+
} else {
135+
assert_contains!(stderr, "Incorrect authentication attempt");
136+
}
137+
}
138+
}
139+
140+
#[test]
141+
fn sudo_askpass_not_set() {
142+
let env = Env("ALL ALL=(ALL:ALL) ALL").user(User(USERNAME)).build();
143+
144+
let output = Command::new("sudo")
145+
.args(["-A", "true"])
146+
.as_user(USERNAME)
147+
.output(&env);
148+
149+
output.assert_exit_code(1);
150+
151+
let stderr = output.stderr();
152+
if sudo_test::is_original_sudo() {
153+
assert_contains!(
154+
stderr,
155+
"no askpass program specified, try setting SUDO_ASKPASS"
156+
);
157+
} else {
158+
assert_contains!(stderr, "No askpass program specified in SUDO_ASKPASS");
159+
}
160+
}
161+
162+
#[test]
163+
fn sudo_askpass_not_absolute_path() {
164+
let env = Env("ALL ALL=(ALL:ALL) ALL").user(User(USERNAME)).build();
165+
166+
let output = Command::new("sh")
167+
.args(["-c", "SUDO_ASKPASS=askpass sudo -A true"])
168+
.as_user(USERNAME)
169+
.output(&env);
170+
171+
output.assert_exit_code(1);
172+
173+
let stderr = output.stderr();
174+
if sudo_test::is_original_sudo() {
175+
assert_contains!(stderr, "unable to run askpass: No such file or directory");
176+
} else {
177+
assert_contains!(stderr, "Askpass program `askpass` is not absolute path");
178+
}
179+
}
180+
181+
#[test]
182+
fn askpass_not_executable() {
183+
let env = Env("ALL ALL=(ALL:ALL) ALL")
184+
.file("/bin/askpass", format!("#!/bin/sh\necho {PASSWORD}"))
185+
.user(User(USERNAME).password(PASSWORD))
186+
.build();
187+
188+
let output = Command::new("sh")
189+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
190+
.as_user(USERNAME)
191+
.output(&env);
192+
193+
output.assert_exit_code(1);
194+
195+
let stderr = output.stderr();
196+
if sudo_test::is_original_sudo() {
197+
assert_contains!(stderr, "unable to run /bin/askpass: Permission denied");
198+
} else {
199+
assert_contains!(
200+
stderr,
201+
"Failed to run askpass program /bin/askpass: Permission denied (os error 13)"
202+
);
203+
}
204+
}
205+
206+
#[test]
207+
fn askpass_exit_code_ignored() {
208+
let env = Env("ALL ALL=(ALL:ALL) ALL")
209+
.file(
210+
"/bin/askpass",
211+
TextFile(format!("#!/bin/sh\necho {PASSWORD}\nfalse")).chmod(CHMOD_EXEC),
212+
)
213+
.user(User(USERNAME).password(PASSWORD))
214+
.build();
215+
216+
Command::new("sh")
217+
.args(["-c", "SUDO_ASKPASS=/bin/askpass sudo -A true"])
218+
.as_user(USERNAME)
219+
.output(&env)
220+
.assert_success();
221+
}
222+
223+
#[test]
224+
fn prompt_given_as_argument() {
225+
let env = Env("ALL ALL=(ALL:ALL) ALL")
226+
.file(
227+
"/bin/askpass",
228+
TextFile(format!(
229+
"#!/bin/sh\necho \"$1\" > /tmp/prompt\necho {PASSWORD}"
230+
))
231+
.chmod(CHMOD_EXEC),
232+
)
233+
.user(User(USERNAME).password(PASSWORD))
234+
.build();
235+
236+
Command::new("sh")
237+
.args([
238+
"-c",
239+
"SUDO_ASKPASS=/bin/askpass sudo -A -p 'my fancy prompt' true",
240+
])
241+
.as_user(USERNAME)
242+
.output(&env)
243+
.assert_success();
244+
245+
let output = Command::new("cat").arg("/tmp/prompt").output(&env);
246+
assert_contains!(output.stdout(), "my fancy prompt");
247+
}
248+
249+
// FIXME correct prompt argument

0 commit comments

Comments
 (0)