Initial commit.

This commit is contained in:
Andrius Štikonas 2020-12-16 17:34:03 +00:00
commit a07c8f1f53
3 changed files with 128 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

12
Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "polkit_test"
version = "0.1.0"
authors = ["Andrius Štikonas <andrius@stikonas.eu>"]
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"

115
src/main.rs Normal file
View File

@ -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<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
}