From cbf4e9d62f0e9e5e63b16dffb4e824f1d6315438 Mon Sep 17 00:00:00 2001 From: Vivian Roest Date: Fri, 15 Dec 2023 21:26:29 +0100 Subject: [PATCH] mvp --- .gitignore | 2 + Cargo.lock | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 ++ src/main.rs | 139 +++++++++++++++++++++++++++++++ 4 files changed, 380 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c403c34 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c17ed80 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,230 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color-eyre" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "eyre" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gnome-autounlock-keyring" +version = "0.1.0" +dependencies = [ + "color-eyre", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[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 = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..bc6102e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "gnome-autounlock-keyring" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +color-eyre = "0.6.2" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..870ca4b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,139 @@ +use color_eyre::eyre::{bail, eyre, WrapErr}; +use std::env; +use std::io::{Read, Write}; +use std::os::unix::net::UnixStream; +use std::path::{Path, PathBuf}; + +fn get_control_socket() -> Option { + let gnome_var = env::var("GNOME_KEYRING_CONTROL") + .ok() + .map(|el| PathBuf::from(el).join("control")) + .and_then(|el| el.exists().then_some(el)); + + let xdg_var = env::var("XDG_RUNTIME_DIR") + .ok() + .map(|el| PathBuf::from(el).join("keyring").join("control")) + .and_then(|el| el.exists().then_some(el)); + + gnome_var.or(xdg_var) +} + +enum ControlOp { + Initialize = 0, + Unlock = 1, + Change = 2, + Quit = 4, +} + +impl ControlOp { + fn to_bytes(self) -> [u8; 4] { + (self as u32).to_be_bytes() + } +} + +#[derive(Debug)] +enum ControlResult { + Ok = 0, + Denied = 1, + Failed = 2, + NoDaemon = 3, +} + +impl ControlResult { + fn from_u32(n: u32) -> Option { + match n { + 0 => Some(ControlResult::Ok), + 1 => Some(ControlResult::Denied), + 2 => Some(ControlResult::Failed), + 3 => Some(ControlResult::NoDaemon), + _ => None, + } + } +} + +fn unlock_keyring(password: &str) -> color_eyre::Result { + let socket = get_control_socket() + .ok_or_else(|| eyre!("Could not find gnome keyring control socket path"))?; + let mut stream = UnixStream::connect(socket) + .wrap_err("Could not connect to the gnome keyring unix socket")?; + + let ret = stream + .write(&[0]) + .wrap_err("could not write credential byte")?; + + if ret != 1 { + bail!("writing cred byte failed") + } + + // oplen is + // 8 = packet size + op code + // 4 size of length of pw byte + let oplen: u32 = 8 + 4 + password.len() as u32; + + // write length + let ret = stream + .write(&oplen.to_be_bytes()) + .wrap_err("could not write oplen")?; + + if ret != 4 { + bail!("writing oplen failed") + } + + // write unlock + let ret = stream + .write(&ControlOp::Unlock.to_bytes()) + .wrap_err("could not write unlock")?; + + if ret != 4 { + bail!("writing unlock failed") + } + + // write pw len + let ret = stream + .write(&(password.len() as u32).to_be_bytes()) + .wrap_err("could not write password length")?; + + if ret != 4 { + bail!("writing pwlen failed") + } + + let mut pw_buf = password.as_bytes(); + + while !pw_buf.is_empty() { + let ret = stream.write(pw_buf).wrap_err("writing password failed")?; + pw_buf = &pw_buf[ret..] + } + + let mut buf = [0; 4]; + let val = stream + .read(&mut buf) + .wrap_err("could not read response length")?; + if val != 4 { + bail!("invalid response length length") + } + + let len = u32::from_be_bytes(buf); + if len != 8 { + bail!("invalid response length"); + } + + let val = stream.read(&mut buf).wrap_err("could not read response")?; + if val != 4 { + bail!("invalid response length (2)") + } + + let resp = u32::from_be_bytes(buf); + let code = ControlResult::from_u32(resp).ok_or_else(|| eyre!("invalid resp"))?; + + Ok(code) +} + +fn main() -> color_eyre::Result<()> { + color_eyre::install().unwrap(); + + let res = unlock_keyring("example")?; + + dbg!(res); + + Ok(()) +}