1use crate::error::Error;
7use crate::proxy::prompt::{Completed, PromptProxy, PromptProxyBlocking};
8use crate::proxy::service::{ServiceProxy, ServiceProxyBlocking};
9use crate::proxy::SecretStruct;
10use crate::session::encrypt;
11use crate::session::Session;
12use crate::ss::SS_DBUS_NAME;
13
14use futures_util::StreamExt;
15use zbus::{
16 proxy::CacheProperties,
17 zvariant::{self, ObjectPath},
18};
19
20pub(crate) enum LockAction {
22 Lock,
23 Unlock,
24}
25
26pub(crate) async fn lock_or_unlock(
27 conn: zbus::Connection,
28 service_proxy: &ServiceProxy<'_>,
29 object_path: &ObjectPath<'_>,
30 lock_action: LockAction,
31) -> Result<(), Error> {
32 let objects = vec![object_path];
33
34 let lock_action_res = match lock_action {
35 LockAction::Lock => service_proxy.lock(objects).await?,
36 LockAction::Unlock => service_proxy.unlock(objects).await?,
37 };
38
39 if lock_action_res.object_paths.is_empty() {
40 exec_prompt(conn, &lock_action_res.prompt).await?;
41 }
42 Ok(())
43}
44
45pub(crate) fn lock_or_unlock_blocking(
46 conn: zbus::blocking::Connection,
47 service_proxy: &ServiceProxyBlocking,
48 object_path: &ObjectPath,
49 lock_action: LockAction,
50) -> Result<(), Error> {
51 let objects = vec![object_path];
52
53 let lock_action_res = match lock_action {
54 LockAction::Lock => service_proxy.lock(objects)?,
55 LockAction::Unlock => service_proxy.unlock(objects)?,
56 };
57
58 if lock_action_res.object_paths.is_empty() {
59 exec_prompt_blocking(conn, &lock_action_res.prompt)?;
60 }
61 Ok(())
62}
63
64pub(crate) fn format_secret(
65 session: &Session,
66 secret: &[u8],
67 content_type: &str,
68) -> Result<SecretStruct, Error> {
69 let content_type = content_type.to_owned();
70
71 if let Some(session_key) = session.get_aes_key() {
72 let mut aes_iv = [0; 16];
73 getrandom::getrandom(&mut aes_iv).expect("platform RNG failed");
74
75 let encrypted_secret = encrypt(secret, session_key, &aes_iv);
76
77 let parameters = aes_iv.to_vec();
79 let value = encrypted_secret;
80
81 Ok(SecretStruct {
82 session: session.object_path.clone(),
83 parameters,
84 value,
85 content_type,
86 })
87 } else {
88 let parameters = Vec::new();
90 let value = secret.to_vec();
91
92 Ok(SecretStruct {
93 session: session.object_path.clone(),
94 parameters,
95 value,
96 content_type,
97 })
98 }
99}
100
101const NO_WINDOW_ID: &str = "";
103
104pub(crate) async fn exec_prompt(
105 conn: zbus::Connection,
106 prompt: &ObjectPath<'_>,
107) -> Result<zvariant::OwnedValue, Error> {
108 let prompt_proxy = PromptProxy::builder(&conn)
109 .destination(SS_DBUS_NAME)?
110 .path(prompt)?
111 .cache_properties(CacheProperties::No)
112 .build()
113 .await?;
114
115 let mut receive_completed_iter = prompt_proxy.receive_completed().await?;
116 prompt_proxy.prompt(NO_WINDOW_ID).await?;
117
118 handle_signal(receive_completed_iter.next().await.unwrap())
119}
120
121pub(crate) fn exec_prompt_blocking(
122 conn: zbus::blocking::Connection,
123 prompt: &ObjectPath,
124) -> Result<zvariant::OwnedValue, Error> {
125 let prompt_proxy = PromptProxyBlocking::builder(&conn)
126 .destination(SS_DBUS_NAME)?
127 .path(prompt)?
128 .cache_properties(CacheProperties::No)
129 .build()?;
130
131 let mut receive_completed_iter = prompt_proxy.receive_completed()?;
132 prompt_proxy.prompt(NO_WINDOW_ID)?;
133
134 handle_signal(receive_completed_iter.next().unwrap())
135}
136
137fn handle_signal(signal: Completed) -> Result<zvariant::OwnedValue, Error> {
138 let args = signal.args()?;
139 if args.dismissed {
140 Err(Error::Prompt)
141 } else {
142 zvariant::OwnedValue::try_from(args.result).map_err(From::from)
143 }
144}
145
146pub(crate) fn handle_conn_error(e: zbus::Error) -> Error {
147 match e {
148 zbus::Error::InterfaceNotFound | zbus::Error::Address(_) => Error::Unavailable,
149 zbus::Error::InputOutput(e) if e.kind() == std::io::ErrorKind::NotFound => {
150 Error::Unavailable
151 }
152 e => e.into(),
153 }
154}