Skip to content

Commit 2910eee

Browse files
committed
Fix handling of EOF other than as caused by Ctrl-D
1 parent fb153b0 commit 2910eee

File tree

11 files changed

+52
-35
lines changed

11 files changed

+52
-35
lines changed

src/pam/rpassword.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,11 @@ fn read_unbuffered(
128128
})?;
129129

130130
if read_byte == b'\n' || read_byte == b'\r' {
131-
break;
131+
return Ok(password);
132132
}
133133

134134
if let Hidden::Yes(input) | Hidden::WithFeedback(input) = hide_input {
135135
if read_byte == input.term_orig.c_cc[VEOF] {
136-
if state.pw_len == 0 {
137-
// In case of Ctrl-D we don't want to ask for a password a second time, so
138-
// return an error.
139-
return Err(PamError::NeedsPassword);
140-
}
141-
142-
password.fill(0);
143136
break;
144137
}
145138

@@ -175,7 +168,13 @@ fn read_unbuffered(
175168
}
176169
}
177170

178-
Ok(password)
171+
if state.pw_len == 0 {
172+
// In case of EOF or Ctrl-D we don't want to ask for a password a second
173+
// time, so return an error.
174+
return Err(PamError::NeedsPassword);
175+
} else {
176+
Ok(password)
177+
}
179178
}
180179

181180
/// Write something and immediately flush

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn required_password_is_target_users_fail() {
9898
let diagnostic = if sudo_test::is_original_sudo() {
9999
"Authentication failure"
100100
} else {
101-
"Maximum 3 incorrect authentication attempts"
101+
"Authentication failed, try again."
102102
};
103103
assert_contains!(output.stderr(), diagnostic);
104104
}
@@ -131,7 +131,7 @@ fn password_is_required_when_target_user_is_self() {
131131
let diagnostic = if sudo_test::is_original_sudo() {
132132
"Authentication failure"
133133
} else {
134-
"Maximum 3 incorrect authentication attempts"
134+
"Password is required"
135135
};
136136
assert_contains!(output.stderr(), diagnostic);
137137
}

test-framework/sudo-compliance-tests/src/su/syslog.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,16 @@ fn logs_every_failed_authentication_attempt() {
8585

8686
eprintln!("\n--- /var/log/auth.log ---\n{auth_log}\n--- /var/log/auth.log ---\n");
8787

88-
if sudo_test::is_original_sudo() {
89-
assert_contains!(
90-
auth_log,
91-
format!("su: pam_unix(su:auth): auth could not identify password for [{target_user}]")
92-
);
88+
assert_contains!(
89+
auth_log,
90+
format!("su: pam_unix(su:auth): auth could not identify password for [{target_user}]")
91+
);
9392

93+
if sudo_test::is_original_sudo() {
9494
let tty = "none";
9595
assert_contains!(
9696
auth_log,
9797
format!("FAILED SU (to {target_user}) {invoking_user} on {tty}")
9898
);
99-
} else {
100-
let tty = "";
101-
assert_contains!(auth_log, format!("su: pam_unix(su:auth): authentication failure; logname= uid={invoking_userid} euid=0 tty={tty} ruser={invoking_user} rhost= user={target_user}"));
10299
}
103100
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,6 @@ fn v_flag_without_pwd_fails_if_nopasswd_is_not_set_for_all_users_entries() {
141141
);
142142
}
143143
} else {
144-
assert_contains!(
145-
stderr,
146-
"[sudo: authenticate] Password: \nsudo: Authentication failed, try again.\n[sudo: authenticate] Password: \nsudo: Authentication failed, try again.\n[sudo: authenticate] Password: \nsudo: Maximum 3 incorrect authentication attempts"
147-
);
144+
assert_contains!(stderr, "Password is required");
148145
}
149146
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn incorrect_password() {
3434
let diagnostic = if sudo_test::is_original_sudo() {
3535
"incorrect password attempt"
3636
} else {
37-
"incorrect authentication attempt"
37+
"Authentication failed, try again."
3838
};
3939
assert_contains!(output.stderr(), diagnostic);
4040
}
@@ -54,7 +54,7 @@ fn no_password() {
5454
let diagnostic = if sudo_test::is_original_sudo() {
5555
"no password was provided"
5656
} else {
57-
"incorrect authentication attempt"
57+
"Password is required"
5858
};
5959
assert_contains!(output.stderr(), diagnostic);
6060
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ fn explicit_passwd_overrides_nopasswd() {
4848
if sudo_test::is_original_sudo() {
4949
assert_snapshot!(stderr);
5050
} else {
51-
assert_contains!(stderr, "Maximum 3 incorrect authentication attempts");
51+
assert_contains!(stderr, "Password is required");
5252
}
5353
}

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,32 @@ it could be that the image defaults to a high retry delay value; \
202202
you may want to increase NEW_DELAY_MICROS"
203203
);
204204
}
205+
206+
#[test]
207+
fn no_password_retry_on_empty_stdin() {
208+
let env = Env(format!("{USERNAME} ALL=(ALL:ALL) ALL"))
209+
.user(User(USERNAME).password(PASSWORD))
210+
.build();
211+
212+
let output = Command::new("sh")
213+
.arg("-c")
214+
.arg(format!("echo -n | sudo -S true"))
215+
.as_user(USERNAME)
216+
.output(&env);
217+
218+
output.assert_exit_code(1);
219+
220+
if sudo_test::is_original_sudo() {
221+
assert_eq!(
222+
output.stderr(),
223+
"[sudo] password for ferris: \n\
224+
sudo: no password was provided\n\
225+
sudo: a password is required"
226+
);
227+
} else {
228+
assert_eq!(
229+
output.stderr(),
230+
"[sudo: authenticate] Password: \nsudo: Password is required"
231+
);
232+
}
233+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn user_specifications_evaluated_bottom_to_top() {
167167
let diagnostic = if sudo_test::is_original_sudo() {
168168
"no password was provided"
169169
} else {
170-
"incorrect authentication attempt"
170+
"Password is required"
171171
};
172172
assert_contains!(output.stderr(), diagnostic);
173173

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,5 @@ fn sudo_logs_every_failed_authentication_attempt() {
3939
assert!(!output.status().success());
4040

4141
let auth_log = rsyslog.auth_log();
42-
let diagnostic = if sudo_test::is_original_sudo() {
43-
"auth could not identify password"
44-
} else {
45-
"authentication failure"
46-
};
47-
assert_contains!(auth_log, diagnostic);
42+
assert_contains!(auth_log, "auth could not identify password");
4843
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ fn cached_credential_not_shared_with_target_user_that_are_not_self() {
141141
let diagnostic = if sudo_test::is_original_sudo() {
142142
"a password is required"
143143
} else {
144-
"Maximum 3 incorrect authentication attempts"
144+
"Password is required"
145145
};
146146

147147
assert_contains!(output.stderr(), diagnostic);

0 commit comments

Comments
 (0)