commit a07c8f1f53eff88a61d0bb00ecb05aff9a4af55f Author: Andrius Štikonas Date: Wed Dec 16 17:34:03 2020 +0000 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..450117e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "polkit_test" +version = "0.1.0" +authors = ["Andrius Štikonas "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +zbus = "1.3.0" +zbus_polkit = "1.1.0" + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f53e128 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,115 @@ +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, input: Vec, #[zbus(header)] header: MessageHeader<'_>) -> (bool, Vec, Vec, 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, #[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, Vec, i32) { +// } +} + + +fn main() -> Result<(), Box> { + 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 +}