diff --git a/src/sudo/mod.rs b/src/sudo/mod.rs index 0c8be67c1..f6c33ce19 100644 --- a/src/sudo/mod.rs +++ b/src/sudo/mod.rs @@ -1,9 +1,8 @@ #![forbid(unsafe_code)] use crate::common::resolve::CurrentUser; -use crate::common::{Context, Error}; +use crate::common::Error; use crate::log::dev_info; -use crate::sudoers::{Judgement, Sudoers}; use crate::system::interface::UserId; use crate::system::kernel::kernel_check; use crate::system::timestamp::RecordScope; @@ -15,7 +14,7 @@ pub use cli::SudoAction; #[cfg(not(test))] use cli::SudoAction; use pam::PamAuthenticator; -use pipeline::{Pipeline, PolicyPlugin}; +use pipeline::Pipeline; use std::path::Path; mod cli; @@ -66,43 +65,6 @@ pub(crate) fn candidate_sudoers_file() -> &'static Path { file } -#[derive(Default)] -pub(crate) struct SudoersPolicy {} - -impl PolicyPlugin for SudoersPolicy { - fn init(&mut self) -> Result { - let sudoers_path = candidate_sudoers_file(); - - let (sudoers, syntax_errors) = - Sudoers::open(sudoers_path).map_err(|e| Error::Configuration(format!("{e}")))?; - - for crate::sudoers::Error { - source, - location, - message, - } in syntax_errors - { - let path = source.as_deref().unwrap_or(sudoers_path); - diagnostic::diagnostic!("{message}", path @ location); - } - - Ok(sudoers) - } - - fn judge(&mut self, pre: Sudoers, context: &Context) -> Result { - Ok(pre.check( - &*context.current_user, - &context.hostname, - crate::sudoers::Request { - user: &context.target_user, - group: &context.target_group, - command: &context.command.command, - arguments: &context.command.arguments, - }, - )) - } -} - fn sudo_process() -> Result<(), Error> { crate::log::SudoLogger::new("sudo: ").into_global_logger(); @@ -112,7 +74,6 @@ fn sudo_process() -> Result<(), Error> { kernel_check()?; let pipeline = Pipeline { - policy: SudoersPolicy::default(), authenticator: PamAuthenticator::new_cli(), }; diff --git a/src/sudo/pipeline.rs b/src/sudo/pipeline.rs index b5dd8ca74..d24f72379 100644 --- a/src/sudo/pipeline.rs +++ b/src/sudo/pipeline.rs @@ -2,6 +2,7 @@ use std::ffi::{OsStr, OsString}; use std::process::exit; use super::cli::{SudoRunOptions, SudoValidateOptions}; +use super::diagnostic; use crate::common::context::OptionsForContext; use crate::common::resolve::{AuthUser, CurrentUser}; use crate::common::{Context, Error}; @@ -19,11 +20,6 @@ use crate::system::{escape_os_str_lossy, Process}; mod list; -pub trait PolicyPlugin { - fn init(&mut self) -> Result; - fn judge(&mut self, pre: Sudoers, context: &Context) -> Result; -} - pub trait AuthPlugin { fn init(&mut self, context: &Context) -> Result<(), Error>; fn authenticate(&mut self, non_interactive: bool, max_tries: u16) -> Result<(), Error>; @@ -31,14 +27,45 @@ pub trait AuthPlugin { fn cleanup(&mut self); } -pub struct Pipeline { - pub policy: Policy, +pub struct Pipeline { pub authenticator: Auth, } -impl Pipeline { +fn read_sudoers() -> Result { + let sudoers_path = super::candidate_sudoers_file(); + + let (sudoers, syntax_errors) = + Sudoers::open(sudoers_path).map_err(|e| Error::Configuration(format!("{e}")))?; + + for crate::sudoers::Error { + source, + location, + message, + } in syntax_errors + { + let path = source.as_deref().unwrap_or(sudoers_path); + diagnostic::diagnostic!("{message}", path @ location); + } + + Ok(sudoers) +} + +fn judge(policy: Sudoers, context: &Context) -> Result { + Ok(policy.check( + &*context.current_user, + &context.hostname, + crate::sudoers::Request { + user: &context.target_user, + group: &context.target_group, + command: &context.command.command, + arguments: &context.command.arguments, + }, + )) +} + +impl Pipeline { pub fn run(mut self, cmd_opts: SudoRunOptions) -> Result<(), Error> { - let pre = self.policy.init()?; + let policy = read_sudoers()?; let (ctx_opts, pipe_opts) = cmd_opts.into(); @@ -48,9 +75,9 @@ impl Pipeline { ) } - let mut context = build_context(ctx_opts, &pre)?; + let mut context = build_context(ctx_opts, &policy)?; - let policy = self.policy.judge(pre, &context)?; + let policy = judge(policy, &context)?; let Authorization::Allowed(auth, controls) = policy.authorization() else { return Err(Error::Authorization(context.current_user.name.to_string())); @@ -111,7 +138,7 @@ impl Pipeline { } pub fn run_validate(mut self, cmd_opts: SudoValidateOptions) -> Result<(), Error> { - let pre = self.policy.init()?; + let pre = read_sudoers()?; let mut context = build_context(cmd_opts.into(), &pre)?; match pre.validate_authorization() { diff --git a/src/sudo/pipeline/list.rs b/src/sudo/pipeline/list.rs index 2bf9d5868..96cebf179 100644 --- a/src/sudo/pipeline/list.rs +++ b/src/sudo/pipeline/list.rs @@ -2,15 +2,14 @@ use std::{borrow::Cow, ops::ControlFlow, path::Path}; use crate::{ common::{Context, Error}, - pam::CLIConverser, - sudo::{cli::SudoListOptions, pam::PamAuthenticator, SudoersPolicy}, + sudo::cli::SudoListOptions, sudoers::{Authorization, ListRequest, Request, Sudoers}, system::{interface::UserId, User}, }; -use super::{Pipeline, PolicyPlugin}; +use super::Pipeline; -impl Pipeline> { +impl Pipeline { pub(in crate::sudo) fn run_list(mut self, cmd_opts: SudoListOptions) -> Result<(), Error> { let verbose_list_mode = cmd_opts.list.is_verbose(); let other_user = cmd_opts @@ -24,7 +23,7 @@ impl Pipeline> { let original_command = cmd_opts.positional_args.first().cloned(); - let sudoers = self.policy.init()?; + let sudoers = super::read_sudoers()?; let mut context = super::build_context(cmd_opts.into(), &sudoers)?; if original_command.is_some() && !context.command.resolved {