Skip to content

Commit 2dcbfa7

Browse files
committed
[WIP] Error fixes
1 parent 48fad5f commit 2dcbfa7

File tree

12 files changed

+41
-34
lines changed

12 files changed

+41
-34
lines changed

src/pam/converse.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl Drop for SignalGuard {
128128
}
129129

130130
impl CLIConverser {
131-
fn open(&self) -> std::io::Result<(Terminal<'_>, SignalGuard)> {
131+
fn open(&self) -> PamResult<(Terminal<'_>, SignalGuard)> {
132132
let term = if self.use_stdin {
133133
Terminal::open_stdie()?
134134
} else {
@@ -157,12 +157,9 @@ impl Converser for CLIConverser {
157157
} else {
158158
tty.read_password(self.password_timeout)
159159
}
160-
.map_err(|err| {
161-
if let io::ErrorKind::TimedOut = err.kind() {
162-
PamError::TimedOut
163-
} else {
164-
PamError::IoError(err)
165-
}
160+
.map_err(|err| match err {
161+
PamError::IoError(err) if err.kind() == io::ErrorKind::TimedOut => PamError::TimedOut,
162+
err => err,
166163
})
167164
}
168165

src/pam/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ pub enum PamError {
173173
Utf8Error(Utf8Error),
174174
Pam(PamErrorType),
175175
IoError(std::io::Error),
176+
TtyRequired,
176177
EnvListFailure,
177178
InteractionRequired,
179+
IncorrectPasswordAttempt,
178180
TimedOut,
179181
InvalidUser(String, String),
180182
}
@@ -216,13 +218,15 @@ impl fmt::Display for PamError {
216218
}
217219
PamError::Pam(tp) => write!(f, "PAM error: {}", tp.get_err_msg()),
218220
PamError::IoError(e) => write!(f, "IO error: {e}"),
221+
PamError::TtyRequired => write!(f, "A terminal is required to read the password"),
219222
PamError::EnvListFailure => {
220223
write!(
221224
f,
222225
"It was not possible to get a list of environment variables"
223226
)
224227
}
225228
PamError::InteractionRequired => write!(f, "Interaction is required"),
229+
PamError::IncorrectPasswordAttempt => write!(f, "Incorrect password attempt"),
226230
PamError::TimedOut => write!(f, "timed out"),
227231
PamError::InvalidUser(username, other_user) => {
228232
write!(

src/pam/rpassword.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
/// - the general idea of a "SafeString" type that clears its memory
1414
/// (although much more robust than in the original code)
1515
///
16-
use std::io::{self, Error, ErrorKind, Read};
16+
use std::io::{self, ErrorKind, Read};
1717
use std::os::fd::{AsFd, AsRawFd, BorrowedFd};
1818
use std::time::Instant;
1919
use std::{fs, mem};
2020

2121
use libc::{tcsetattr, termios, ECHO, ECHONL, ICANON, TCSANOW, VEOF, VERASE, VKILL};
2222

2323
use crate::cutils::cerr;
24+
use crate::pam::{PamError, PamResult};
2425
use crate::system::time::Duration;
2526

2627
use super::securemem::PamBuffer;
@@ -100,7 +101,7 @@ fn read_unbuffered(
100101
source: &mut dyn io::Read,
101102
sink: &mut dyn io::Write,
102103
hide_input: Hidden<'_>,
103-
) -> io::Result<PamBuffer> {
104+
) -> PamResult<PamBuffer> {
104105
struct ExitGuard<'a> {
105106
pw_len: usize,
106107
feedback: bool,
@@ -137,6 +138,10 @@ fn read_unbuffered(
137138

138139
if let Hidden::Yes(input) | Hidden::WithFeedback(input) = hide_input {
139140
if read_byte == input.term_orig.c_cc[VEOF] {
141+
if state.pw_len == 0 {
142+
//return Err(PamError::NeedsPassword);
143+
}
144+
140145
password.fill(0);
141146
break;
142147
}
@@ -169,10 +174,7 @@ fn read_unbuffered(
169174
let _ = state.sink.write(b"*");
170175
}
171176
} else {
172-
return Err(Error::new(
173-
ErrorKind::OutOfMemory,
174-
"incorrect password attempt",
175-
));
177+
return Err(PamError::IncorrectPasswordAttempt);
176178
}
177179
}
178180

@@ -259,12 +261,13 @@ pub enum Terminal<'a> {
259261

260262
impl Terminal<'_> {
261263
/// Open the current TTY for user communication
262-
pub fn open_tty() -> io::Result<Self> {
264+
pub fn open_tty() -> PamResult<Self> {
263265
Ok(Terminal::Tty(
264266
fs::OpenOptions::new()
265267
.read(true)
266268
.write(true)
267-
.open("/dev/tty")?,
269+
.open("/dev/tty")
270+
.map_err(|_| PamError::TtyRequired)?,
268271
))
269272
}
270273

@@ -274,7 +277,7 @@ impl Terminal<'_> {
274277
}
275278

276279
/// Reads input with TTY echo disabled
277-
pub fn read_password(&mut self, timeout: Option<Duration>) -> io::Result<PamBuffer> {
280+
pub fn read_password(&mut self, timeout: Option<Duration>) -> PamResult<PamBuffer> {
278281
let hide_input = HiddenInput::new()?;
279282
self.read_inner(
280283
timeout,
@@ -286,7 +289,7 @@ impl Terminal<'_> {
286289
pub fn read_password_with_feedback(
287290
&mut self,
288291
timeout: Option<Duration>,
289-
) -> io::Result<PamBuffer> {
292+
) -> PamResult<PamBuffer> {
290293
let hide_input = HiddenInput::new()?;
291294
self.read_inner(
292295
timeout,
@@ -298,15 +301,15 @@ impl Terminal<'_> {
298301
}
299302

300303
/// Reads input with TTY echo enabled
301-
pub fn read_cleartext(&mut self) -> io::Result<PamBuffer> {
304+
pub fn read_cleartext(&mut self) -> PamResult<PamBuffer> {
302305
self.read_inner(None, Hidden::No)
303306
}
304307

305308
fn read_inner(
306309
&mut self,
307310
timeout: Option<Duration>,
308311
hide_input: Hidden<'_>,
309-
) -> io::Result<PamBuffer> {
312+
) -> PamResult<PamBuffer> {
310313
match self {
311314
Terminal::StdIE(stdin, stdout) => {
312315
let mut reader = TimeoutRead::new(stdin.as_fd(), timeout);

test-framework/sudo-compliance-tests/src/sudo/flag_list/credential_caching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn flag_reset_timestamp() {
8787
let diagnostic = if sudo_test::is_original_sudo() {
8888
"sudo: a password is required"
8989
} else {
90-
"sudo: Authentication failed"
90+
"sudo: A terminal is required to read the password"
9191
};
9292
assert_contains!(output.stderr(), diagnostic);
9393
}

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
@@ -96,7 +96,7 @@ fn input_longer_than_max_pam_response_size_is_handled_gracefully() {
9696
assert_contains!(stderr, "sudo: 2 incorrect password attempts");
9797
}
9898
} else {
99-
assert_contains!(stderr, "incorrect authentication attempt");
99+
assert_contains!(stderr, "Incorrect password attempt");
100100
assert_not_contains!(stderr, "panic");
101101
}
102102
}
@@ -124,7 +124,7 @@ fn input_longer_than_password_should_not_be_accepted_as_correct_password() {
124124
if sudo_test::is_original_sudo() {
125125
assert_contains!(stderr, "sudo: 1 incorrect password attempt");
126126
} else {
127-
assert_contains!(stderr, "incorrect authentication attempt");
127+
assert_contains!(stderr, "Incorrect password attempt");
128128
}
129129
}
130130
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn no_tty() {
5252
let diagnostic = if sudo_test::is_original_sudo() {
5353
"a terminal is required to read the password"
5454
} else {
55-
"Maximum 3 incorrect authentication attempts"
55+
"A terminal is required to read the password"
5656
};
5757
assert_contains!(output.stderr(), diagnostic);
5858
}
@@ -96,7 +96,7 @@ fn input_longer_than_password_should_not_be_accepted_as_correct_password() {
9696
let diagnostic = if sudo_test::is_original_sudo() {
9797
"sudo: 1 incorrect password attempt"
9898
} else {
99-
"Authentication failed, try again"
99+
"Incorrect password attempt"
100100
};
101101
assert_contains!(stderr, diagnostic);
102102
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Defaults timestamp_timeout=0.1"
4646
let diagnostic = if sudo_test::is_original_sudo() {
4747
"a password is required"
4848
} else {
49-
"incorrect authentication attempt"
49+
"A terminal is required to read the password"
5050
};
5151
assert_contains!(output.stderr(), diagnostic);
5252
}
@@ -73,7 +73,7 @@ Defaults timestamp_timeout=0"
7373
let diagnostic = if sudo_test::is_original_sudo() {
7474
"a password is required"
7575
} else {
76-
"incorrect authentication attempt"
76+
"A terminal is required to read the password"
7777
};
7878
assert_contains!(output.stderr(), diagnostic);
7979
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn by_default_credential_caching_is_local() {
4545
let diagnostic = if sudo_test::is_original_sudo() {
4646
"a password is required"
4747
} else {
48-
"incorrect authentication attempt"
48+
"A terminal is required to read the password"
4949
};
5050
assert_contains!(output.stderr(), diagnostic);
5151
}
@@ -220,7 +220,7 @@ fn cached_credential_not_shared_between_auth_users() {
220220
let diagnostic = if sudo_test::is_original_sudo() {
221221
"a password is required"
222222
} else {
223-
"incorrect authentication attempt"
223+
"A terminal is required to read the password"
224224
};
225225
assert_contains!(output.stderr(), diagnostic);
226226
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ fn also_works_locally() {
8383
let diagnostic = if sudo_test::is_original_sudo() {
8484
"a password is required"
8585
} else {
86-
"Authentication failed"
86+
"A terminal is required to read the password"
8787
};
8888
assert_contains!(output.stderr(), diagnostic);
8989
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn it_works() {
2424
let diagnostic = if sudo_test::is_original_sudo() {
2525
"a password is required"
2626
} else {
27-
"incorrect authentication attempt"
27+
"A terminal is required to read the password"
2828
};
2929
assert_contains!(output.stderr(), diagnostic);
3030
}
@@ -72,7 +72,7 @@ fn with_command_prompts_for_password() {
7272
let diagnostic = if sudo_test::is_original_sudo() {
7373
"a password is required"
7474
} else {
75-
"incorrect authentication attempt"
75+
"A terminal is required to read the password"
7676
};
7777
assert_contains!(output.stderr(), diagnostic);
7878
}
@@ -144,7 +144,7 @@ fn with_command_does_not_cache_credentials() {
144144
let diagnostic = if sudo_test::is_original_sudo() {
145145
"a password is required"
146146
} else {
147-
"Authentication failed"
147+
"A terminal is required to read the password"
148148
};
149149
assert_contains!(output.stderr(), diagnostic);
150150
}

0 commit comments

Comments
 (0)