Skip to content

Commit

Permalink
add -S/--stdin support
Browse files Browse the repository at this point in the history
  • Loading branch information
squell committed Apr 17, 2023
1 parent cf1b02f commit d493f56
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 14 deletions.
2 changes: 2 additions & 0 deletions lib/sudo-common/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct Context<'a> {
pub command: CommandAndArguments<'a>,
pub target_user: User,
pub target_group: Group,
pub stdin: bool,
// system
pub hostname: String,
pub path: String,
Expand Down Expand Up @@ -50,6 +51,7 @@ impl<'a> Context<'a> {
login: sudo_options.login,
shell: sudo_options.shell,
chdir: sudo_options.directory.clone(),
stdin: sudo_options.stdin,
pid: sudo_system::Process::process_id(),
})
}
Expand Down
1 change: 1 addition & 0 deletions lib/sudo-env/tests/env_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ fn create_test_context<'a>(sudo_options: &'a SudoOptions) -> Context<'a> {
login: sudo_options.login,
shell: sudo_options.shell,
chdir: sudo_options.directory.clone(),
stdin: sudo_options.stdin,
pid: std::process::id() as i32,
}
}
Expand Down
8 changes: 4 additions & 4 deletions lib/sudo-pam/src/converse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,17 @@ where
/// A converser that uses stdin/stdout/stderr to display messages and to request
/// input from the user.
pub struct CLIConverser {
pub(crate) use_tty: bool,
pub(crate) use_stdin: bool,
}

use rpassword::Terminal;

impl CLIConverser {
fn open(&self) -> std::io::Result<Terminal> {
if self.use_tty {
Terminal::open_tty()
} else {
if self.use_stdin {
Terminal::open_stdie()
} else {
Terminal::open_tty()
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/sudo-pam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,8 @@ impl<'a, C: Converser> PamContext<'a, C> {

impl<'a> PamContext<'a, CLIConverser> {
/// Create a builder that uses the CLI conversation function.
pub fn builder_cli(use_tty: bool) -> PamContextBuilder<CLIConverser> {
PamContextBuilder::default().converser(CLIConverser { use_tty })
pub fn builder_cli(use_stdin: bool) -> PamContextBuilder<CLIConverser> {
PamContextBuilder::default().converser(CLIConverser { use_stdin })
}
}

Expand Down
12 changes: 9 additions & 3 deletions lib/sudo-pam/src/rpassword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
///
/// - the "HiddenInput" struct and implementation
/// * replaced occurences of explicit 'i32' and 'c_int' with RawFd
/// * make it return an Option ("None" if the given fd is not a terminal)
/// - the general idea of a "SafeString" type that clears its memory
/// (although much more robust than in the original code)
///
use std::io::{self, Read};
use std::os::fd::{AsFd, AsRawFd, RawFd};
use std::{fs, iter, mem};

use libc::{tcsetattr, termios, ECHO, ECHONL, TCSANOW};
use libc::{isatty, tcsetattr, termios, ECHO, ECHONL, TCSANOW};

use sudo_cutils::cerr;

Expand All @@ -28,9 +29,14 @@ pub struct HiddenInput {
}

impl HiddenInput {
fn new(tty: &impl AsRawFd) -> io::Result<HiddenInput> {
fn new(tty: &impl AsRawFd) -> io::Result<Option<HiddenInput>> {
let fd = tty.as_raw_fd();

// If the file descriptor is not a terminal, there is nothing to hide
if unsafe { isatty(fd) } == 0 {
return Ok(None);
}

// Make two copies of the terminal settings. The first one will be modified
// and the second one will act as a backup for when we want to set the
// terminal back to its original state.
Expand All @@ -46,7 +52,7 @@ impl HiddenInput {
// Save the settings for now.
cerr(unsafe { tcsetattr(fd, TCSANOW, &term) })?;

Ok(HiddenInput { fd, term_orig })
Ok(Some(HiddenInput { fd, term_orig }))
}
}

Expand Down
2 changes: 1 addition & 1 deletion sudo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ fn sudo_process() -> Result<std::process::ExitStatus, Error> {
match policy.authorization() {
Authorization::Required => {
// authenticate user using pam
authenticate(&context.current_user.name)?;
authenticate(&context)?;
}
Authorization::Passed => {}
Authorization::Forbidden => {
Expand Down
8 changes: 4 additions & 4 deletions sudo/src/pam.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use sudo_common::error::Error;
use sudo_common::{error::Error, Context};

pub fn authenticate(username: &str) -> Result<(), Error> {
let mut pam = sudo_pam::PamContext::builder_cli(true)
.target_user(username)
pub fn authenticate(ctx: &Context) -> Result<(), Error> {
let mut pam = sudo_pam::PamContext::builder_cli(ctx.stdin)
.target_user(&ctx.current_user.name)
.service_name("sudo")
.build()?;

Expand Down

0 comments on commit d493f56

Please sign in to comment.