Skip to content

Commit 1180951

Browse files
committed
create sudo -e pipeline
1 parent e20a1f1 commit 1180951

File tree

3 files changed

+50
-47
lines changed

3 files changed

+50
-47
lines changed

src/common/context.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::io;
22

33
use crate::common::{HARDENED_ENUM_VALUE_0, HARDENED_ENUM_VALUE_1, HARDENED_ENUM_VALUE_2};
44
use crate::exec::{RunOptions, Umask};
5-
use crate::sudo::{SudoListOptions, SudoRunOptions, SudoValidateOptions};
5+
#[cfg_attr(not(feature = "sudoedit"), allow(unused_imports))]
6+
use crate::sudo::{SudoEditOptions, SudoListOptions, SudoRunOptions, SudoValidateOptions};
67
use crate::sudoers::Sudoers;
78
use crate::system::{Group, Hostname, Process, User};
89

@@ -100,6 +101,42 @@ impl Context {
100101
})
101102
}
102103

104+
#[cfg(feature = "sudoedit")]
105+
pub fn from_edit_opts(sudo_options: SudoEditOptions) -> Result<Context, Error> {
106+
let hostname = Hostname::resolve();
107+
let current_user = CurrentUser::resolve()?;
108+
109+
let (target_user, target_group) =
110+
resolve_target_user_and_group(&sudo_options.user, &sudo_options.group, &current_user)?;
111+
112+
// TODO: the more Rust way of doing things would be to create an alternative for sudoedit instead;
113+
// but a stringly typed interface feels the most decent thing to do (if we can pull it off)
114+
// since "sudoedit" really is like a builtin command to sudo.
115+
let command = CommandAndArguments {
116+
command: std::path::PathBuf::from("sudoedit"),
117+
arguments: sudo_options.positional_args,
118+
..Default::default()
119+
};
120+
121+
Ok(Context {
122+
hostname,
123+
command,
124+
current_user,
125+
target_user,
126+
target_group,
127+
use_session_records: !sudo_options.reset_timestamp,
128+
launch: Default::default(),
129+
chdir: sudo_options.chdir,
130+
stdin: sudo_options.stdin,
131+
bell: sudo_options.bell,
132+
prompt: sudo_options.prompt,
133+
non_interactive: sudo_options.non_interactive,
134+
process: Process::new(),
135+
use_pty: true,
136+
noexec: false,
137+
umask: Umask::Preserve,
138+
})
139+
}
103140
pub fn from_validate_opts(sudo_options: SudoValidateOptions) -> Result<Context, Error> {
104141
let hostname = Hostname::resolve();
105142
let current_user = CurrentUser::resolve()?;

src/sudo/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use cli::SudoAction;
1515
use std::path::PathBuf;
1616

1717
mod cli;
18-
pub(crate) use cli::{SudoListOptions, SudoRunOptions, SudoValidateOptions};
18+
pub(crate) use cli::{SudoEditOptions, SudoListOptions, SudoRunOptions, SudoValidateOptions};
1919

2020
pub(crate) mod diagnostic;
2121
mod env;

src/sudo/pipeline/edit.rs

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
use std::process::exit;
22

3-
use super::super::cli::SudoRunOptions;
3+
use super::super::cli::SudoEditOptions;
44
use crate::common::{Context, Error};
55
use crate::exec::ExitReason;
6-
use crate::sudo::env::environment;
7-
use crate::sudo::pam::pre_exec;
86
use crate::sudoers::Authorization;
97

10-
pub fn run_edit(mut cmd_opts: SudoRunOptions) -> Result<(), Error> {
11-
let mut policy = super::read_sudoers()?;
8+
pub fn run_edit(edit_opts: SudoEditOptions) -> Result<(), Error> {
9+
let policy = super::read_sudoers()?;
1210

13-
let user_requested_env_vars = std::mem::take(&mut cmd_opts.env_var_list);
14-
15-
let mut context = Context::from_run_opts(cmd_opts, &mut policy)?;
11+
let mut context = Context::from_edit_opts(edit_opts)?;
1612

1713
let policy = super::judge(policy, &context)?;
1814

@@ -23,48 +19,18 @@ pub fn run_edit(mut cmd_opts: SudoRunOptions) -> Result<(), Error> {
2319
super::apply_policy_to_context(&mut context, &controls)?;
2420
let mut pam_context = super::auth_and_update_record_file(&context, auth)?;
2521

26-
// build environment
27-
let additional_env = pre_exec(&mut pam_context, &context.target_user.name)?;
28-
29-
let current_env = environment::system_environment();
30-
let (checked_vars, trusted_vars) = if controls.trust_environment {
31-
(vec![], user_requested_env_vars)
32-
} else {
33-
(user_requested_env_vars, vec![])
34-
};
35-
36-
let mut target_env = environment::get_target_environment(
37-
current_env,
38-
additional_env,
39-
checked_vars,
40-
&context,
41-
&controls,
42-
)?;
43-
44-
environment::dangerous_extend(&mut target_env, trusted_vars);
45-
4622
let pid = context.process.pid;
4723

48-
// prepare switch of apparmor profile
49-
#[cfg(feature = "apparmor")]
50-
if let Some(profile) = controls.apparmor_profile {
51-
crate::apparmor::set_profile_for_next_exec(&profile)
52-
.map_err(|err| Error::AppArmor(profile, err))?;
53-
}
54-
5524
// run command and return corresponding exit code
56-
let command_exit_reason = if context.command.resolved {
25+
let command_exit_reason = {
5726
super::log_command_execution(&context);
5827

59-
crate::exec::run_command(
60-
context
61-
.try_as_run_options()
62-
.map_err(|io_error| Error::Io(Some(context.command.command.clone()), io_error))?,
63-
target_env,
64-
)
65-
.map_err(|io_error| Error::Io(Some(context.command.command), io_error))
66-
} else {
67-
Err(Error::CommandNotFound(context.command.command))
28+
eprintln_ignore_io_error!(
29+
"this would launch sudoedit as requested, to edit the files: {:?}",
30+
context.command.arguments.as_slice()
31+
);
32+
33+
Ok::<_, std::io::Error>(ExitReason::Code(42))
6834
};
6935

7036
pam_context.close_session();

0 commit comments

Comments
 (0)