From 7c2fb57d5b7104dd2bde519608331c28a69c7f81 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Wed, 31 Jul 2024 23:57:09 +0000 Subject: [PATCH] refactor: more work on this project --- --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,55 @@ ] [[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] name = "anyhow" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -301,6 +350,52 @@ ] [[package]] +name = "clap" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] name = "concurrent-queue" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -524,6 +619,12 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -552,6 +653,12 @@ ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itertools" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -591,6 +698,12 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -656,6 +769,16 @@ ] [[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] name = "object" version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -681,6 +804,12 @@ ] [[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] name = "pam-client" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -734,6 +863,49 @@ ] [[package]] +name = "polkit-agent" +version = "0.1.0" +dependencies = [ + "anyhow", + "pam-client", + "polkit-shared", + "rand", + "serde", + "tokio", + "tracing", + "tracing-subscriber", + "ui-prompt", + "uuid", + "zbus", + "zbus_polkit", +] + +[[package]] +name = "polkit-backend" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "nix", + "pam-client", + "polkit-shared", + "tokio", + "tracing", + "tracing-subscriber", + "ui-prompt", + "zbus", + "zbus_polkit", +] + +[[package]] +name = "polkit-shared" +version = "0.1.0" +dependencies = [ + "serde", + "zbus", +] + +[[package]] name = "polling" version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -839,18 +1011,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "remowt" -version = "0.1.0" -dependencies = [ - "anyhow", - "pam-client", - "serde", - "tokio", - "zbus", - "zbus_polkit", -] [[package]] name = "rpassword" @@ -955,6 +1115,15 @@ ] [[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -979,6 +1148,12 @@ ] [[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] name = "socket2" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -995,6 +1170,12 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1029,6 +1210,36 @@ ] [[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] name = "tokio" version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1103,9 +1314,35 @@ checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1123,12 +1360,44 @@ ] [[package]] +name = "ui-prompt" +version = "0.1.0" +dependencies = [ + "serde", + "thiserror", + "tokio", + "tracing", + "zbus", +] + +[[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,3 @@ -[package] -name = "remowt" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0.86" -pam-client = "0.5.0" -serde = { version = "1.0.204", features = ["derive"] } -tokio = { version = "1.39.2", features = ["rt-multi-thread", "fs", "macros"] } -zbus = { version = "4.4.0", features = ["tokio"] } -zbus_polkit = { version = "4.0.0", features = ["tokio"] } +[workspace] +members = ["cmds/*", "crates/*"] +resolver = "2" --- /dev/null +++ b/cmds/polkit-agent/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "polkit-agent" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.86" +pam-client = "0.5.0" +polkit-shared = { version = "0.1.0", path = "../../crates/polkit-shared" } +rand = "0.8.5" +serde = { version = "1.0.204", features = ["derive"] } +tokio = { version = "1.39.2", features = ["rt-multi-thread", "fs", "macros"] } +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +ui-prompt = { version = "0.1.0", path = "../../crates/ui-prompt" } +uuid = { version = "1.10.0", features = ["v4"] } +zbus = { version = "4.4.0", features = ["tokio"] } +zbus_polkit = { version = "4.0.0", features = ["tokio"] } --- /dev/null +++ b/cmds/polkit-agent/src/main.rs @@ -0,0 +1,177 @@ +use std::collections::HashMap; +use std::future; +use std::marker::PhantomData; +use std::sync::{Mutex, RwLock}; + +use polkit_shared::{BackendRequest, Identity}; +use tokio::runtime::Handle; +use tokio::task::{AbortHandle, JoinHandle, LocalSet}; +use tracing::trace; +use ui_prompt::dbus::DbusPrompterInterface; +use ui_prompt::rofi::RofiPrompter; +use ui_prompt::Prompter; +use zbus::zvariant::{OwnedValue, Str}; +use zbus::ObjectServer; +use zbus::{interface, proxy, Connection}; +use zbus_polkit::policykit1::Subject; + +struct TemporaryPrompterInterface { + connection: Connection, + path: String, + _marker: PhantomData

, +} +impl TemporaryPrompterInterface

{ + async fn new(connection: Connection, prompter: P) -> Self { + let path = format!( + "/remowt/prompters/{}", + uuid::Uuid::new_v4().to_string().replace("-", "_") + ); + let _ = connection + .object_server() + .at(path.clone(), DbusPrompterInterface(prompter)) + .await; + Self { + connection, + path, + _marker: PhantomData, + } + } +} +impl Drop for TemporaryPrompterInterface

{ + fn drop(&mut self) { + // FIXME: block_in_place prevents to moving to current_thread runtime + // There should be a blocking way to remove ObjectServer listener. + // As far as I can see, it is only async because of async RwLock, shouldn't it be + // just a sync lock? + tokio::task::block_in_place(move || { + Handle::current().block_on(async { + let _ = self + .connection + .object_server() + .remove::, String>(self.path.clone()) + .await; + }); + }); + } +} + +struct Agent { + helper: PolkitHelperProxy<'static>, + tasks: Mutex>, + connection: Connection, +} +impl Agent { + async fn new(connection: Connection) -> anyhow::Result { + Ok(Self { + helper: PolkitHelperProxy::new(&connection).await?, + tasks: Mutex::new(HashMap::new()), + connection, + }) + } +} + +#[interface(name = "org.freedesktop.PolicyKit1.AuthenticationAgent")] +impl Agent { + /// BeginAuthentication method + #[allow(clippy::too_many_arguments)] + async fn begin_authentication( + &mut self, + action_id: String, + message: String, + icon_name: String, + details: HashMap, + cookie: String, + identities: Vec, + ) -> zbus::fdo::Result<()> { + trace!("begin auth"); + let task = { + let connection = self.connection.clone(); + let helper = self.helper.clone(); + let cookie = cookie.clone(); + tokio::task::spawn(async move { + trace!("conversation task"); + let prompter = TemporaryPrompterInterface::new(connection, RofiPrompter).await; + helper + .init_conversation( + BackendRequest { + cookie: cookie.to_owned(), + environment: HashMap::new(), + prompter_path: prompter.path.clone(), + // TODO: Let user choose + identity: identities.get(0).expect("first always exists").clone(), + }, // cookie.to_owned(), HashMap::new(), prompter.path.clone() + ) + .await?; + println!("ASKED"); + dbg!(action_id, message, icon_name, details, cookie, identities); + + Ok(()) + }) + }; + + self.tasks + .lock() + .unwrap() + .insert(cookie.clone(), task.abort_handle()); + let result = task.await.expect("join error"); + // The only way to no reach this line, is to either panic in previous line, or if authorization cancelled, + // while cancellation will remove task by itself. + // TODO: But still it would be better to have abort guard, which will remove it from HashMap + self.tasks.lock().unwrap().remove(&cookie); + + result + } + + /// CancelAuthentication method + async fn cancel_authentication(&self, cookie: &str) -> zbus::fdo::Result<()> { + trace!("cancel auth"); + if let Some(abort) = self.tasks.lock().unwrap().remove(cookie) { + abort.abort(); + } + // debug!("Authentication cancled ! {cookie}"); + Ok(()) + } +} + +const OBJ_PATH: &str = "/0lach/polkitAgent"; +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt::init(); + + trace!("started"); + let conn = Connection::system().await?; + + let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&conn).await?; + conn.object_server() + .at(OBJ_PATH, Agent::new(conn.clone()).await?) + .await?; + + let session_id = std::env::var("XDG_SESSION_ID")?; + let mut details = HashMap::new(); + let val: OwnedValue = { + let wrapped: Str<'_> = session_id.into(); + wrapped.into() + }; + details.insert("session-id".to_string(), val); + proxy + .register_authentication_agent( + &Subject { + subject_kind: "unix-session".to_string(), + subject_details: details, + }, + "C", + OBJ_PATH, + ) + .await?; + + future::pending().await +} + +#[proxy( + interface = "lach.PolkitHelper", + default_service = "lach.polkit.helper1", + default_path = "/lach/PolkitHelper" +)] +trait PolkitHelper { + fn init_conversation(&self, request: BackendRequest) -> zbus::Result<()>; +} --- /dev/null +++ b/cmds/polkit-backend/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "polkit-backend" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.86" +clap = { version = "4.5.11", features = ["derive"] } +nix = "0.29.0" +pam-client = "0.5.0" +polkit-shared = { version = "0.1.0", path = "../../crates/polkit-shared" } +tokio = { version = "1.39.2", features = ["macros", "rt", "rt-multi-thread"] } +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +ui-prompt = { version = "0.1.0", path = "../../crates/ui-prompt" } +zbus = { version = "4.4.0", features = ["tokio"] } +zbus_polkit = { version = "4.0.0", features = ["tokio"] } --- /dev/null +++ b/cmds/polkit-backend/etc/systemd/system/remowt-polkit-helper.service @@ -0,0 +1,12 @@ +[Unit] +Description=Remowt polkit helper service + +[Service] +Type=dbus +BusName=lach.polkit.helper1 +ExecStart=@libexecdir@/polkit-helper +# TODO: Hardening + +[Install] +WantedBy=multi-user.target +Alias=dbus-lach.polkit.helper1.service --- /dev/null +++ b/cmds/polkit-backend/share/dbus-1/system-services/lach.polkit.helper1.conf @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=lach.polkit.helper1 +Exec=/bin/false +User=root +SystemdService=dbus-lach.polkit.helper1.service --- /dev/null +++ b/cmds/polkit-backend/share/dbus-1/system.d/lach.polkit.helper1.conf @@ -0,0 +1,12 @@ + + + + + + + + + + + + --- /dev/null +++ b/cmds/polkit-backend/src/main.rs @@ -0,0 +1,238 @@ +use std::collections::{HashMap, HashSet}; +use std::ffi::{CStr, CString}; +use std::future::pending; +use std::sync::LazyLock; + +use anyhow::Context as _; +use clap::Parser; +use nix::unistd::{setuid, Uid, User}; +use pam_client::{Context, ConversationHandler, ErrorCode, Flag}; +use polkit_shared::BackendRequest; +use tokio::runtime::Handle; +use tokio::task::{block_in_place, spawn_blocking}; +use tracing::trace; +use ui_prompt::dbus::DbusPrompterProxyBlocking; +use ui_prompt::{BlockingPrompter, Prompter}; +use zbus::fdo; +use zbus::message::Header; +use zbus::zvariant::OwnedValue; +use zbus::{blocking, interface, proxy, Connection}; + +struct Helper { + connection: Connection, + blocking_connection: blocking::Connection, +} + +static ALLOWED_ENVIRONMENT: LazyLock> = LazyLock::new(|| { + [ + // pam ssh agent auth + "SSH_AUTH_SOCK", + // ssh itself provides this when running PAM + "SSH_AUTH_INFO_0", + // contains user which ran sudo + "SUDO_USER", + ] + .into_iter() + .collect() +}); + +struct Conversation

(P); +impl Conversation

{ + fn prompt_inner(&self, echo: bool, prompt: &CStr) -> Result { + trace!("do prompt"); + let out = self + .0 + .prompt_text( + echo, + &prompt.to_string_lossy(), + "Polkit prompt request", + &[], + ) + .map_err(|e| { + trace!("prompt error: {e}"); + ErrorCode::CONV_ERR + })?; + CString::new(out).map_err(|_| ErrorCode::CONV_AGAIN) + } + fn text_inner(&self, error: bool, msg: &CStr) { + trace!("do text"); + let msg = msg.to_string_lossy(); + let _ = self.0.display_text(error, &msg, &[]); + } +} +impl ConversationHandler for Conversation

{ + fn prompt_echo_on(&mut self, prompt: &CStr) -> Result { + self.prompt_inner(true, prompt) + } + + fn prompt_echo_off(&mut self, prompt: &CStr) -> Result { + self.prompt_inner(false, prompt) + } + + fn text_info(&mut self, msg: &CStr) { + self.text_inner(false, msg) + } + + fn error_msg(&mut self, msg: &CStr) { + self.text_inner(true, msg) + } + + fn radio_prompt(&mut self, prompt: &CStr) -> Result { + let prompt = prompt.to_string_lossy(); + let result = self + .0 + .prompt_radio(&prompt, "Polkit prompt request", &[]) + .map_err(|_| ErrorCode::CONV_ERR)?; + Ok(result) + } +} + +#[proxy( + default_service = "org.freedesktop.DBus", + default_path = "/org/freedesktop/DBus" +)] +trait DBus { + fn get_connection_credentials(&self, body: &str) -> zbus::Result>; +} + +#[interface(name = "lach.PolkitHelper")] +impl Helper { + async fn init_conversation( + &self, + request: BackendRequest, + #[zbus(header)] hdr: Header<'_>, + ) -> fdo::Result<()> { + let Some(sender) = hdr.sender().map(|v| v.to_owned()) else { + trace!("missing sender"); + return Err(fdo::Error::AuthFailed("missing sender".to_owned())); + }; + + let dbus = DBusProxy::new(&self.connection).await?; + + // TOCTOU: sender might be already disconnected, and there might be another + // user with different user id here, but does it matters? + let reply = dbus.get_connection_credentials(&sender).await?; + let uid: u32 = (&reply["UnixUserID"]).try_into().unwrap(); + + let blocking_connection = self.blocking_connection.clone(); + let thread_result: fdo::Result<()> = block_in_place(move || { + trace!("find user"); + let user = User::from_uid(Uid::from_raw(uid)) + .map_err(|_| fdo::Error::AuthFailed("error querying user".to_owned()))? + .ok_or_else(|| fdo::Error::AuthFailed("uid not found".to_owned()))?; + + let responder = DbusPrompterProxyBlocking::new( + &blocking_connection, + sender, + request.prompter_path, + )?; + let conversation = Conversation(responder); + trace!("run context for {}", &user.name); + let mut ctx = Context::new( + // TODO: Should another scope be used? + "login", + Some(&user.name), + conversation, + ) + .map_err(|_| fdo::Error::Failed("pam context init failed".to_owned()))?; + + trace!("fill env"); + for (k, v) in request.environment { + if k.contains('=') || !ALLOWED_ENVIRONMENT.contains(k.as_str()) { + continue; + } + let _ = ctx.putenv(format!("{k}={v}")); + } + + trace!("authenticate"); + ctx.authenticate(Flag::NONE) + .map_err(|_| fdo::Error::AuthFailed("pam authentication failed".to_owned()))?; + + trace!("acct mgmt"); + ctx.acct_mgmt(Flag::NONE) + .map_err(|_| fdo::Error::AuthFailed("pam acct mgmt failed".to_owned()))?; + + Ok(()) + }); + + thread_result?; + + trace!("respond"); + let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&self.connection).await?; + + let identity_details = request + .identity + .details + .iter() + .map(|(k, v)| (k.as_str(), (**v).try_clone().expect("success"))) + .collect::>(); + proxy + .authentication_agent_response2( + uid, + &request.cookie, + &zbus_polkit::policykit1::Identity { + identity_kind: &request.identity.kind, + identity_details: &identity_details, + }, + ) + .await?; + Ok(()) + } +} + +const OBJ_PATH: &str = "/lach/PolkitHelper"; + +#[derive(Parser)] +struct Opts { + /// Not recommended: start as a session connection, then use escalation + /// to respond to polkit requests. + #[arg(long)] + session: bool, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt::init(); + let opts = Opts::parse(); + let connection = if opts.session { + Connection::session().await + } else { + Connection::system().await + } + .context("failed to open connection")?; + + let session = opts.session; + let blocking_connection: anyhow::Result = spawn_blocking(move || { + Ok(if session { + blocking::Connection::session()? + } else { + blocking::Connection::system()? + }) + }) + .await?; + let blocking_connection = blocking_connection.context("failed to open blocking connection")?; + + if opts.session { + setuid(Uid::from_raw(0)) + .context("polkit-backend needs to be suid if run in session mode")?; + } + + connection + .object_server() + .at( + OBJ_PATH, + Helper { + connection: connection.clone(), + blocking_connection, + }, + ) + .await + .context("failed listen path")?; + + connection + .request_name("lach.polkit.helper1") + .await + .context("failed to request name")?; + + pending().await +} --- a/cmds/polkit-helper/Cargo.lock +++ /dev/null @@ -1,1488 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "async-broadcast" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-io" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "tracing", - "windows-sys", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "async-signal" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.72", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - -[[package]] -name = "bytes" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" - -[[package]] -name = "cc" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", -] - -[[package]] -name = "clap" -version = "4.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "endi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" - -[[package]] -name = "enum-repr" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "enumflags2" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "event-listener" -version = "5.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "object" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "pam-client" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bd776116a7ada5ebbe31f54cdc5b1030ed7265686cf7c8a21c057a2f8dab9a" -dependencies = [ - "bitflags 1.3.2", - "enum-repr", - "libc", - "pam-sys", - "rpassword", - "rustversion", -] - -[[package]] -name = "pam-sys" -version = "1.0.0-alpha5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9484729b3e52c0bacdc5191cb6a6a5f31ef4c09c5e4ab1209d3340ad9e997b" -dependencies = [ - "bindgen", - "libc", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "polkit-helper" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "nix", - "pam-client", - "tokio", - "zbus", - "zbus_polkit", -] - -[[package]] -name = "polling" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "rpassword" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956" -dependencies = [ - "libc", - "serde", - "serde_json", - "winapi", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "serde" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys", -] - -[[package]] -name = "tokio" -version = "1.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "tracing", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "toml_datetime" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "xdg-home" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "zbus" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix", - "ordered-stream", - "rand", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.72", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" -dependencies = [ - "serde", - "static_assertions", - "zvariant", -] - -[[package]] -name = "zbus_polkit" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00a29bfa927b29f91b7feb4e1990f2dd1b4604072f493dc2f074cf59e4e0ba90" -dependencies = [ - "enumflags2", - "serde", - "serde_repr", - "static_assertions", - "zbus", -] - -[[package]] -name = "zvariant" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "zvariant_derive", -] - -[[package]] -name = "zvariant_derive" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.72", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] --- a/cmds/polkit-helper/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "polkit-helper" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0.86" -clap = { version = "4.5.11", features = ["derive"] } -nix = "0.29.0" -pam-client = "0.5.0" -tokio = { version = "1.39.2", features = ["macros", "rt"] } -zbus = { version = "4.4.0", features = ["tokio"] } -zbus_polkit = { version = "4.0.0", features = ["tokio"] } --- a/cmds/polkit-helper/src/main.rs +++ /dev/null @@ -1,203 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::ffi::{CStr, CString}; -use std::future::pending; -use std::sync::LazyLock; - -use anyhow::Context as _; -use clap::Parser; -use nix::unistd::{setuid, Uid, User}; -use pam_client::{Context, ConversationHandler, ErrorCode}; -use tokio::task::spawn_blocking; -use zbus::blocking; -use zbus::message::Header; -use zbus::zvariant::OwnedValue; -use zbus::{ - blocking::Connection as BlockingConnection, - fdo::{Error as FdoError, Result as FdoResult}, - interface, proxy, Connection, -}; - -struct Helper { - connection: Connection, - blocking_connection: BlockingConnection, -} - -static ALLOWED_ENVIRONMENT: LazyLock> = LazyLock::new(|| { - [ - // pam ssh agent auth - "SSH_AUTH_SOCK", - // ssh itself provides this when running PAM - "SSH_AUTH_INFO_0", - // contains user which ran sudo - "SUDO_USER", - ] - .into_iter() - .collect() -}); - -struct Conversation { - responder: PolkitResponderProxyBlocking<'static>, -} -impl Conversation { - fn prompt_inner(&self, echo: bool, prompt: &CStr) -> Result { - let out = self - .responder - .prompt(echo, &prompt.to_string_lossy()) - .map_err(|_| ErrorCode::CONV_ERR)?; - Ok(CString::new(out).map_err(|_| ErrorCode::CONV_AGAIN)?) - } - fn text_inner(&self, error: bool, msg: &CStr) { - let msg = msg.to_string_lossy(); - let _ = self.responder.text(error, &msg); - } -} -impl ConversationHandler for Conversation { - fn prompt_echo_on(&mut self, prompt: &CStr) -> Result { - self.prompt_inner(true, prompt) - } - - fn prompt_echo_off(&mut self, prompt: &CStr) -> Result { - self.prompt_inner(false, prompt) - } - - fn text_info(&mut self, msg: &CStr) { - self.text_inner(false, msg) - } - - fn error_msg(&mut self, msg: &CStr) { - self.text_inner(true, msg) - } - - fn radio_prompt(&mut self, prompt: &CStr) -> Result { - let prompt = prompt.to_string_lossy(); - let result = self - .responder - .radio(&prompt) - .map_err(|_| ErrorCode::CONV_ERR)?; - Ok(result) - } -} - -#[proxy( - default_service = "org.freedesktop.DBus", - default_path = "/org/freedesktop/DBus" -)] -trait DBus { - fn get_connection_credentials(&self, body: &str) -> zbus::Result>; -} - -#[proxy(default_path = "/lach/PolkitResponder")] -trait PolkitResponder { - fn prompt(&self, echo: bool, prompt: &str) -> zbus::Result; - fn text(&self, error: bool, msg: &str) -> zbus::Result<()>; - fn radio(&self, msg: &str) -> zbus::Result; -} - -#[interface(name = "lach.PolkitHelper")] -impl Helper { - async fn init_conversation( - &self, - environment: HashMap, - #[zbus(header)] hdr: Header<'_>, - ) -> zbus::fdo::Result<()> { - let Some(sender) = hdr.sender().map(|v| v.to_owned()) else { - return Err(zbus::fdo::Error::AuthFailed("missing sender".to_owned())); - }; - - let dbus = DBusProxy::new(&self.connection).await?; - - let reply = dbus - .get_connection_credentials("org.freedesktop.DBus") - .await?; - let uid: u32 = (&reply["UnixUserID"]).try_into().unwrap(); - - let blocking_connection = self.blocking_connection.clone(); - let thread_result: FdoResult<()> = spawn_blocking(move || { - let user = User::from_uid(Uid::from_raw(uid)) - .map_err(|_| zbus::fdo::Error::AuthFailed("error querying user".to_owned()))? - .ok_or_else(|| zbus::fdo::Error::AuthFailed("uid not found".to_owned()))?; - - let responder = PolkitResponderProxyBlocking::new(&blocking_connection, sender)?; - let conversation = Conversation { responder }; - let mut ctx = Context::new( - // TODO: Should another scope be used? - "login", - Some(&user.name), - conversation, - ) - .map_err(|_| FdoError::Failed("pam context init failed".to_owned()))?; - - for (k, v) in environment { - if k.contains('=') || !ALLOWED_ENVIRONMENT.contains(k.as_str()) { - continue; - } - let _ = ctx.putenv(format!("{k}={v}")); - } - - Ok(()) - }) - .await - .map_err(|_| FdoError::Failed("thread spawn failed".to_owned()))?; - - thread_result?; - // Context::new(hdr.) - // - Ok(()) - } -} - -const OBJ_PATH: &str = "/lach/polkitHelper"; - -#[derive(Parser)] -struct Opts { - /// Not recommended: start as a session connection, then use escalation - /// to respond to polkit requests. - #[arg(long)] - session: bool, -} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> anyhow::Result<()> { - let opts = Opts::parse(); - let connection = if opts.session { - Connection::session().await - } else { - Connection::system().await - } - .context("failed to open connection")?; - - let session = opts.session; - let blocking_connection: anyhow::Result = spawn_blocking(move || { - Ok(if session { - BlockingConnection::session()? - } else { - BlockingConnection::system()? - }) - }) - .await?; - let blocking_connection = blocking_connection.context("failed to open blocking connection")?; - - if opts.session { - setuid(Uid::from_raw(0)) - .context("polkit-helper needs to be suid if run in session mode")?; - } - - connection - .object_server() - .at( - OBJ_PATH, - Helper { - connection: connection.clone(), - blocking_connection, - }, - ) - .await - .context("failed listen path")?; - - connection - .request_name("lach.PolkitHelper") - .await - .context("failed to request name")?; - - pending().await -} --- /dev/null +++ b/crates/polkit-shared/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "polkit-shared" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = { version = "1.0.204", features = ["derive"] } +zbus = "4.4.0" --- /dev/null +++ b/crates/polkit-shared/src/lib.rs @@ -0,0 +1,31 @@ +use std::collections::HashMap; + +use serde::{Deserialize, Serialize}; +use zbus::zvariant::{OwnedValue, Type}; + +#[derive(Serialize, Deserialize, Type, PartialEq, Debug)] +pub struct Identity { + pub kind: String, + pub details: HashMap, +} + +impl Clone for Identity { + fn clone(&self) -> Self { + Self { + kind: self.kind.clone(), + details: self + .details + .iter() + .map(|(k, v)| (k.clone(), v.try_clone().expect("no fds are expected"))) + .collect(), + } + } +} + +#[derive(Serialize, Deserialize, Type, PartialEq, Debug)] +pub struct BackendRequest { + pub cookie: String, + pub environment: HashMap, + pub prompter_path: String, + pub identity: Identity, +} --- /dev/null +++ b/crates/ui-prompt/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "ui-prompt" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = "1.0.204" +thiserror = "1.0.63" +tokio = { version = "1.39.2", features = ["io-util", "macros", "process", "rt"] } +tracing = "0.1.40" +zbus = { version = "4.4.0", optional = true } + +[features] +default = ["dbus"] +dbus = ["dep:zbus"] --- /dev/null +++ b/crates/ui-prompt/src/dbus.rs @@ -0,0 +1,123 @@ +use zbus::interface; +use zbus::{fdo, proxy}; + +use crate::Source; +use crate::{BlockingPrompter, Result}; +use crate::{Error, Prompter}; + +pub struct DbusPrompterInterface

(pub P); +#[interface(name = "lach.PolkitInputHandler")] +impl DbusPrompterInterface

{ + async fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: Vec, + ) -> fdo::Result { + Ok(self.0.prompt_radio(prompt, description, &source).await?) + } + async fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: Vec, + ) -> fdo::Result { + Ok(self + .0 + .prompt_text(echo, prompt, description, &source) + .await?) + } + async fn display_text( + &self, + error: bool, + description: &str, + source: Vec, + ) -> fdo::Result<()> { + Ok(self.0.display_text(error, description, &source).await?) + } +} + +#[proxy(interface = "lach.PolkitInputHandler")] +trait DbusPrompter { + async fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: &[Source], + ) -> fdo::Result; + async fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> fdo::Result; + async fn display_text( + &self, + error: bool, + description: &str, + source: &[Source], + ) -> fdo::Result<()>; +} + +impl Prompter for DbusPrompterProxy<'_> { + async fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + Ok(self.prompt_radio(prompt, description, source).await?) + } + + async fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + Ok(self.prompt_text(echo, prompt, description, source).await?) + } + + async fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()> { + Ok(self.display_text(error, description, source).await?) + } +} +impl BlockingPrompter for DbusPrompterProxyBlocking<'_> { + fn prompt_radio(&self, prompt: &str, description: &str, source: &[Source]) -> Result { + Ok(self.prompt_radio(prompt, description, source)?) + } + + fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + Ok(self.prompt_text(echo, prompt, description, source)?) + } + + fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()> { + Ok(self.display_text(error, description, source)?) + } +} + +impl From for Error { + fn from(value: fdo::Error) -> Self { + if matches!(value, fdo::Error::NoReply(_)) { + return Self::Cancel; + } + Self::InputError(format!("{value}")) + } +} +impl From for fdo::Error { + fn from(value: Error) -> Self { + match value { + Error::Cancel => fdo::Error::NoReply("input was cancelled".to_owned()), + Error::InputError(e) => fdo::Error::Failed(e), + } + } +} --- /dev/null +++ b/crates/ui-prompt/src/lib.rs @@ -0,0 +1,104 @@ +use core::fmt; +use std::borrow::Cow; +use std::future::Future; +use std::result; + +pub mod dbus; +pub mod rofi; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("user has cancelled input")] + Cancel, + #[error("input error: {0}")] + InputError(String), +} + +pub type Result = result::Result; + +#[cfg_attr(feature = "dbus", derive(zbus::zvariant::Type))] +#[derive(serde::Serialize, serde::Deserialize, Clone)] +pub struct Source(Cow<'static, str>); +impl fmt::Display for Source { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +pub trait Prompter { + fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: &[Source], + ) -> impl Future> + Send; + fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> impl Future> + Send; + fn display_text( + &self, + error: bool, + description: &str, + source: &[Source], + ) -> impl Future> + Send; +} +pub trait BlockingPrompter { + fn prompt_radio(&self, prompt: &str, description: &str, source: &[Source]) -> Result; + fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result; + fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()>; +} + +pub struct PrependSourcePrompter

{ + prompter: P, + source: Vec, +} +impl

PrependSourcePrompter

{ + fn source(&self, input: &[Source]) -> Vec { + let mut out = self.source.clone(); + out.extend(input.iter().cloned()); + out + } +} +impl

Prompter for PrependSourcePrompter

+where + P: Prompter + Sync, +{ + async fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + self.prompter + .prompt_radio(prompt, description, &self.source(source)) + .await + } + + async fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + self.prompter + .prompt_text(echo, prompt, description, &self.source(source)) + .await + } + + async fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()> { + self.prompter + .display_text(error, description, &self.source(source)) + .await + } +} --- /dev/null +++ b/crates/ui-prompt/src/rofi.rs @@ -0,0 +1,176 @@ +use std::process::Stdio; + +use tokio::io::AsyncWriteExt; +use tokio::process::Command; +use tracing::trace; + +use crate::{Error, Prompter, Result, Source}; + +pub struct RofiPrompter; + +impl Prompter for RofiPrompter { + async fn prompt_radio( + &self, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + trace!("rofi radio"); + let mut cmd = Command::new("rofi"); + let mesg = if source.is_empty() { + description.to_owned() + } else { + let mut out = format!("{description}\n\nRequested on ",); + for s in source.iter() { + out.push_str(&s.to_string()); + } + out.push_str(""); + out + }; + cmd.args([ + "-dmenu", + "-mesg", + &mesg, + "-sync", + "-only-match", + "-p", + prompt, + ]); + cmd.stdin(Stdio::piped()); + cmd.stdout(Stdio::piped()); + cmd.kill_on_drop(true); + let mut child = cmd + .spawn() + .map_err(|e| Error::InputError(format!("failed to spawn rofi: {e}")))?; + + child + .stdin + .take() + .expect("stdin is piped") + .write_all(b"Yes\nNo\n") + .await + .map_err(|e| Error::InputError(format!("failed to write rofi variants: {e}")))?; + + let out = child + .wait_with_output() + .await + .map_err(|e| Error::InputError(format!("failed to wait for rofi: {e}")))?; + let stdout = out + .stdout + .strip_suffix(b"\n") + .unwrap_or(&out.stdout) + .to_owned(); + + if &stdout == b"Yes" { + Ok(true) + } else if &stdout == b"No" { + Ok(false) + } else { + Err(Error::InputError("bad rofi response".to_owned())) + } + } + + async fn prompt_text( + &self, + echo: bool, + prompt: &str, + description: &str, + source: &[Source], + ) -> Result { + trace!("rofi text"); + let mut cmd = Command::new("rofi"); + let mesg = if source.is_empty() { + description.to_owned() + } else { + let mut out = format!("{description}\n\nRequested on ",); + for s in source.iter() { + out.push_str(&s.to_string()); + } + out.push_str(""); + out + }; + cmd.args(["-dmenu", "-mesg", &mesg, "-p", prompt]); + if !echo { + cmd.arg("-password"); + } + cmd.stdin(Stdio::null()); + cmd.stdout(Stdio::piped()); + cmd.kill_on_drop(true); + let child = cmd + .spawn() + .map_err(|e| Error::InputError(format!("failed to spawn rofi: {e}")))?; + + let out = child + .wait_with_output() + .await + .map_err(|e| Error::InputError(format!("failed to wait for rofi: {e}")))?; + let stdout = out + .stdout + .strip_suffix(b"\n") + .unwrap_or(&out.stdout) + .to_owned(); + + Ok(String::from_utf8_lossy(&stdout).to_string()) + } + + async fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()> { + trace!("rofi display"); + let mut cmd = Command::new("rofi"); + let mut mesg = if source.is_empty() { + description.to_owned() + } else { + let mut out = format!("{description}\n\nComing from ",); + for s in source.iter() { + out.push_str(&s.to_string()); + } + out.push_str(""); + out + }; + if error { + mesg.insert_str(0, ""); + mesg.push_str(""); + } + cmd.args(["-e", &mesg, "-markup"]); + cmd.stdin(Stdio::null()); + cmd.stdout(Stdio::null()); + cmd.kill_on_drop(true); + let mut child = cmd + .spawn() + .map_err(|e| Error::InputError(format!("failed to spawn rofi: {e}")))?; + + child + .wait() + .await + .map_err(|e| Error::InputError(format!("failed to wait for rofi: {e}")))?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::borrow::Cow; + + use crate::rofi::RofiPrompter; + use crate::{PrependSourcePrompter, Prompter as _, Source}; + + #[tokio::test] + async fn test() { + let prompter = PrependSourcePrompter { + prompter: RofiPrompter, + source: vec![Source(Cow::Borrowed("ssh"))], + }; + prompter + .prompt_radio("Enable", "Polkit needs access", &[]) + .await + .expect("rofi"); + prompter + .prompt_text(false, "Password", "Polkit needs access", &[]) + .await + .expect("rofi"); + prompter + .display_text(true, "Polkit needs access", &[]) + .await + .expect("rofi"); + } +} --- a/flake.lock +++ b/flake.lock @@ -1,20 +1,42 @@ { "nodes": { - "flake-utils": { + "crane": { "inputs": { - "systems": "systems" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "lastModified": 1721842668, + "narHash": "sha256-k3oiD2z2AAwBFLa4+xfU+7G5fisRXfkvrMTCJrjZzXo=", + "owner": "ipetkov", + "repo": "crane", + "rev": "529c1a0b1f29f0d78fa3086b8f6a134c71ef3aaf", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", "type": "github" } }, @@ -35,9 +57,11 @@ }, "root": { "inputs": { - "flake-utils": "flake-utils", + "crane": "crane", + "flake-parts": "flake-parts", "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" + "rust-overlay": "rust-overlay", + "shelly": "shelly" } }, "rust-overlay": { @@ -60,18 +84,26 @@ "type": "github" } }, - "systems": { + "shelly": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "lastModified": 1718420551, + "narHash": "sha256-NU8NBXVPj0KuY4Tl/LtZPrbX3PmmmgPuhk/1pzm9cyk=", + "owner": "CertainLach", + "repo": "shelly", + "rev": "4f70221f3f9ad9058f590eefb25251b6760aaa47", "type": "github" }, "original": { - "owner": "nix-systems", - "repo": "default", + "owner": "CertainLach", + "repo": "shelly", "type": "github" } } --- a/flake.nix +++ b/flake.nix @@ -2,28 +2,55 @@ description = "Jrsonnet"; inputs = { nixpkgs.url = "github:nixos/nixpkgs"; - flake-utils.url = "github:numtide/flake-utils"; + flake-parts = { + url = "github:hercules-ci/flake-parts"; + inputs.nixpkgs-lib.follows = "nixpkgs"; + }; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-utils.follows = "flake-utils"; }; + crane = { + url = "github:ipetkov/crane"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + shelly = { + url = "github:CertainLach/shelly"; + inputs = { + flake-parts.follows = "flake-parts"; + nixpkgs.follows = "nixpkgs"; + }; + }; }; - outputs = { nixpkgs, flake-utils, rust-overlay, ... }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { + outputs = inputs @ { + nixpkgs, + flake-parts, + rust-overlay, + crane, + ... + }: + flake-parts.lib.mkFlake {inherit inputs;} { + imports = [inputs.shelly.flakeModule ./nix/nixos-modules.nix]; + systems = nixpkgs.lib.systems.flakeExposed; + perSystem = { + config, + system, + pkgs, + ... + }: let + rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + craneLib = (crane.mkLib pkgs).overrideToolchain rust; + in { + _module.args.pkgs = import nixpkgs { inherit system; - overlays = [ rust-overlay.overlays.default ]; + overlays = [rust-overlay.overlays.default]; }; - rust = ((pkgs.rustChannelOf { date = "2024-07-26"; channel = "nightly"; }).default.override { - extensions = [ "rust-src" "miri" "rust-analyzer" ]; - }); - in - rec { - devShell = pkgs.mkShell { - nativeBuildInputs = with pkgs;[ - rust + packages.polkit-backend = pkgs.callPackage ./nix/polkit-backend.nix { + inherit craneLib; + }; + shelly.shells.default = { + factory = craneLib.devShell; + packages = with pkgs; [ cargo-edit cargo-asm cargo-outdated @@ -37,6 +64,7 @@ pam ]; }; - } - ); + formatter = pkgs.alejandra; + }; + }; } --- /dev/null +++ b/nix/nixos-modules.nix @@ -0,0 +1,13 @@ +{config, ...}: { + flake.nixosModules = rec { + default = polkit-backend; + polkit-backend = {pkgs, ...}: { + services.dbus.packages = [ + config.flake.packages.${pkgs.stdenv.system}.polkit-backend + ]; + systemd.packages = [ + config.flake.packages.${pkgs.stdenv.system}.polkit-backend + ]; + }; + }; +} --- /dev/null +++ b/nix/polkit-backend.nix @@ -0,0 +1,40 @@ +{ + lib, + craneLib, + rustPlatform, + pam, + coreutils, +}: let + crateName = "polkit-backend"; +in + craneLib.buildPackage { + src = lib.cleanSourceWith { + src = ../.; + filter = path: type: + (lib.hasSuffix "\.conf" path) + || (lib.hasSuffix "\.service" path) + || (craneLib.filterCargoSources path type); + }; + + pname = crateName; + installPhase = '' + mkdir -p $out/libexec + cp -ar $src/cmds/${crateName}/share $out/ + cp -ar $src/cmds/${crateName}/etc $out/ + # Reference stripper hook wants write access to that. + chmod a+w -R $out/share + cp target/release/${crateName} $out/libexec/ + + substituteInPlace $out/share/dbus-1/system-services/lach.polkit.helper1.conf \ + --replace-fail /bin/false ${coreutils}/bin/false + substituteInPlace $out/etc/systemd/system/remowt-polkit-helper.service \ + --replace-fail @libexecdir@ ${placeholder "out"}/libexec + ''; + + cargoExtraArgs = "--locked -p ${crateName}"; + + buildInputs = [ + rustPlatform.bindgenHook + pam + ]; + } --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2024-07-20" +components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"] --- a/src/main.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::collections::HashMap; -use std::ffi::{CStr, CString}; -use std::future; - -use pam_client::{Context, ConversationHandler, ErrorCode, Flag}; -use serde::Deserialize; -use zbus::zvariant::{OwnedValue, Str, Type, Value}; -use zbus::{interface, Connection}; -use zbus_polkit::policykit1::Subject; - -/// Helper struct that implements serde::Deserialize -#[derive(Deserialize, Type, PartialEq, Debug)] -pub struct Identity<'s> { - pub kind: &'s str, - pub details: HashMap<&'s str, Value<'s>>, -} -struct Agent { - // sessions: HashMap, -} - -impl Agent { - pub fn new() -> Self { - Self { - // sessions: HashMap::new(), - } - } -} -#[interface(name = "org.freedesktop.PolicyKit1.AuthenticationAgent")] -impl Agent { - /// BeginAuthentication method - async fn begin_authentication( - &mut self, - action_id: &str, - message: &str, - icon_name: &str, - details: HashMap<&str, &str>, - cookie: &str, - identities: Vec>, - ) -> zbus::fdo::Result<()> { - println!("ASKED"); - dbg!(action_id, message, icon_name, details, cookie, identities); - // debug!("Authentication asked !"); - // debug!("action_id: {action_id}, message: {message}, icon_name: {icon_name}, details: {details:?}, cookie: {cookie}, identities: {identities:?}"); - // - // let identities = identities - // .into_iter() - // .map(TryFrom::try_from) - // .collect::, >>::Error>>( - // ) - // .unwrap(); - // let session = Session { - // action_id: action_id.to_string(), - // message: message.to_string(), - // icon_name: icon_name.to_string(), - // cookie: cookie.to_string(), - // identities, - // selected_identity_index: 0, - // }; - // let out = authenticate(&session); - // - // info!("Responder exit code: {}", out.unwrap()); - // - // self.sessions.insert(String::from(cookie), session); - Ok(()) - } - - /// CancelAuthentication method - async fn cancel_authentication(&self, cookie: &str) -> zbus::fdo::Result<()> { - println!("CANCELED"); - // debug!("Authentication cancled ! {cookie}"); - Ok(()) - } -} - -const OBJ_PATH: &str = "/0lach/polkitAgent"; -// #[tokio::main] -async fn mainw() -> anyhow::Result<()> { - let conn = Connection::system().await?; - let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&conn).await?; - conn.object_server().at(OBJ_PATH, Agent::new()).await?; - // conn. - - let session_id = std::env::var("XDG_SESSION_ID")?; - let mut details = HashMap::new(); - let val: OwnedValue = { - let wrapped: Str<'_> = session_id.into(); - wrapped.into() - }; - details.insert("session-id".to_string(), val); - proxy - .register_authentication_agent( - &Subject { - subject_kind: "unix-session".to_string(), - subject_details: details, - }, - "C", - OBJ_PATH, - ) - .await?; - - future::pending::<()>().await; - Ok(()) -} - -struct Conv; -impl ConversationHandler for Conv { - #[doc = " Obtains a string whilst echoing text (e.g. username)"] - #[doc = ""] - #[doc = " # Errors"] - #[doc = " You should return one of the following error codes on failure."] - #[doc = " - [`ErrorCode::CONV_ERR`]: Conversation failure."] - #[doc = " - [`ErrorCode::BUF_ERR`]: Memory allocation error."] - #[doc = " - [`ErrorCode::CONV_AGAIN`]: no result yet, the PAM library should"] - #[doc = " pass [`ErrorCode::INCOMPLETE`] to the application and let it"] - #[doc = " try again later."] - fn prompt_echo_on(&mut self, prompt: &CStr) -> Result { - todo!() - } - - #[doc = " Obtains a string without echoing any text (e.g. password)"] - #[doc = ""] - #[doc = " # Errors"] - #[doc = " You should return one of the following error codes on failure."] - #[doc = " - [`ErrorCode::CONV_ERR`]: Conversation failure."] - #[doc = " - [`ErrorCode::BUF_ERR`]: Memory allocation error."] - #[doc = " - [`ErrorCode::CONV_AGAIN`]: no result yet, the PAM library should"] - #[doc = " pass [`ErrorCode::INCOMPLETE`] to the application and let it"] - #[doc = " try again later."] - fn prompt_echo_off(&mut self, prompt: &CStr) -> Result { - dbg!(prompt); - Ok(CString::new("1").expect("valid")) - } - - #[doc = " Displays some text."] - fn text_info(&mut self, msg: &CStr) { - todo!() - } - - #[doc = " Displays an error message."] - fn error_msg(&mut self, msg: &CStr) { - todo!() - } -} - -#[tokio::main] -async fn main() { - let mut ctx = Context::new("login", Some("lach"), Conv).expect("context init failed"); - - - ctx.set_user_prompt(Some("Hello")); - ctx.authenticate(Flag::NONE).expect("fail?"); - - println!("authenticated!"); -} -- gitstuff