Initial commit.
This commit is contained in:
commit
a07c8f1f53
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue