polkit-test/src/main.rs

116 lines
3.9 KiB
Rust

use std::fs::{self, OpenOptions};
use std::error::Error;
use std::convert::TryInto;
use std::io::{Seek, SeekFrom, Write};
use std::process::{Command, Stdio};
use zbus_polkit::policykit1::*;
use zbus::{Connection, dbus_interface, fdo, MessageHeader};
struct ExternalCommandHelper;
#[dbus_interface(name = "org.kde.kpmcore.externalcommand")]
impl ExternalCommandHelper {
fn run_command(&self, command: &str, arguments: Vec<String>, input: Vec<u8>, #[zbus(header)] header: MessageHeader<'_>) -> (bool, Vec<u8>, Vec<u8>, i32) {
let authorized = is_authorized(header);
if !authorized {
// FIXME: Send AccessDenied error back
return (false, vec![0; 0], vec![0; 0], 1)
}
//Implement command whitelist
let mut child = Command::new(command)
.args(&arguments)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn().unwrap(); // FIXME unwrap
let child_stdin = child.stdin.as_mut().unwrap();
child_stdin.write_all(&input).unwrap();
let result = child.wait_with_output();
match result {
Ok(v) => return (true, v.stdout, v.stderr, v.status.code().unwrap()), // FIXME: unwrap
Err(_) => return (false, vec![0; 0], vec![0; 0], 1)
}
}
fn create_file(&self, file_path: &str, file_contents: Vec<u8>, #[zbus(header)] header: MessageHeader<'_>) -> bool {
let authorized = is_authorized(header);
if !authorized {
// FIXME: Send AccessDenied error back
return false
}
if !file_path.contains("/etc/fstab") {
return false
}
let result = fs::write(file_path, file_contents);
match result {
Ok(()) => return true,
Err(_) => return false,
}
}
fn write_data(&self, data: &[u8], target_device: &str, target_first_byte: u64, #[zbus(header)] header: MessageHeader<'_>) -> bool {
let authorized = is_authorized(header);
if !authorized {
// FIXME: Send AccessDenied error back
return false
}
let mut file = OpenOptions::new().write(true).open(target_device).unwrap();
let result = file.seek(SeekFrom::Start(target_first_byte));
match result {
Ok(_) => match file.write(data) {
Ok(_) => true,
Err(_) => false,
}
Err(_) => false,
}
}
// fn copyblocks(&self, source_device: &str, source_first_byte: i64, source_length: i64, target_device: &str, target_first_byte: i64, block_size: i64, #[zbus(header)] header: MessageHeader<'_>) -> (bool, Vec<u8>, Vec<u8>, i32) {
// }
}
fn main() -> Result<(), Box<dyn Error>> {
let connection = Connection::new_system()?;
fdo::DBusProxy::new(&connection)?.request_name(
"org.kde.kpmcore.helperinterface",
fdo::RequestNameFlags::ReplaceExisting.into(),
)?;
let mut object_server = zbus::ObjectServer::new(&connection);
let helper = ExternalCommandHelper;
object_server.at(&"/Helper".try_into()?, helper)?;
loop {
if let Err(err) = object_server.try_handle_next() {
eprintln!("{}", err);
}
}
}
fn is_authorized(header: MessageHeader<'_>) -> bool
{
let sender = header.sender().unwrap().unwrap();
println!("Sender: {}", sender);
let connection = Connection::new_system().unwrap();
let proxy = AuthorityProxy::new(&connection).unwrap();
let subject = Subject::new_for_message_header(&header).unwrap();
let result = proxy.check_authorization(
&subject,
"org.kde.kpmcore.externalcommand.init",
std::collections::HashMap::new(),
CheckAuthorizationFlags::AllowUserInteraction.into(),
"",
).unwrap();
result.is_authorized
}