use crate::bridge::BridgeServer;
use crate::command::*;
use crate::{PrivilegeLevel, Token};
use std::convert::TryInto;
use std::io::Result as IoResult;
fn spawn_with_current_io_streams(token: &Token) -> IoResult<()> {
let mut cmd = Command::with_environment_for_token(token)?;
cmd.set_command_from_current_process()?;
let proc = cmd.spawn_as_user(token)?;
proc.wait_for(None)?;
let exit_code = proc.exit_code()?;
std::process::exit(exit_code.try_into().unwrap());
}
pub fn spawn_with_normal_privileges() -> IoResult<()> {
let token = Token::with_current_process()?;
let level = token.privilege_level()?;
match level {
PrivilegeLevel::NotPrivileged => Ok(()),
PrivilegeLevel::Elevated => {
let target_token = Token::with_shell_process()?;
let mut server = BridgeServer::new();
let mut argv = std::env::args_os().collect();
let mut bridge_cmd = server.start_for_command(&mut argv, &target_token)?;
let proc = bridge_cmd.spawn_with_token(&target_token)?;
std::process::exit(server.serve(proc)? as _);
}
PrivilegeLevel::HighIntegrityAdmin => {
let medium_token = token.as_medium_integrity_safer_token()?;
spawn_with_current_io_streams(&medium_token)
}
}
}
pub fn spawn_with_elevated_privileges() -> IoResult<()> {
let token = Token::with_current_process()?;
let level = token.privilege_level()?;
let target_token = match level {
PrivilegeLevel::NotPrivileged => token.as_medium_integrity_safer_token()?,
PrivilegeLevel::HighIntegrityAdmin | PrivilegeLevel::Elevated => return Ok(()),
};
let mut server = BridgeServer::new();
let mut argv = std::env::args_os().collect();
let mut bridge_cmd = server.start_for_command(&mut argv, &target_token)?;
let proc = bridge_cmd.spawn_with_token(&target_token)?;
std::process::exit(server.serve(proc)? as _);
}
#[no_mangle]
pub extern "C" fn deelevate_is_privileged_process() -> i32 {
match Token::with_current_process().and_then(|token| token.privilege_level()) {
Ok(PrivilegeLevel::Elevated) | Ok(PrivilegeLevel::HighIntegrityAdmin) => 1,
Ok(PrivilegeLevel::NotPrivileged) => 0,
Err(e) => {
eprintln!(
"An error occurred while determining the privilege level: {}",
e
);
std::process::exit(1);
}
}
}
#[no_mangle]
pub extern "C" fn deelevate_requires_normal_privileges() {
if let Err(e) = spawn_with_normal_privileges() {
eprintln!(
"This program requires running with Normal privileges and \
encountered an issue while attempting to run in that context: {}",
e
);
std::process::exit(1);
}
}
#[no_mangle]
pub extern "C" fn deelevate_requires_elevated_privileges() {
if let Err(e) = spawn_with_elevated_privileges() {
eprintln!(
"This program requires running with Elevated privileges and \
encountered an issue while attempting to run in that context: {}",
e
);
std::process::exit(1);
}
}