From 5b9d6eac061ad8a1a212aaf9104af82b995836bb Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Wed, 29 Nov 2017 15:42:47 -0600 Subject: [PATCH] add windows named pipe support --- .gitignore | 1 + Cargo.lock | 47 +++++++++++++++++++++++ Cargo.toml | 5 ++- src/main.rs | 82 +++++++++++++++++++++-------------------- src/platform_unix.rs | 32 ++++++++++++++++ src/platform_windows.rs | 28 ++++++++++++++ 6 files changed, 154 insertions(+), 41 deletions(-) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 src/platform_unix.rs create mode 100644 src/platform_windows.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6f89c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ceeca24 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,47 @@ +[[package]] +name = "byteorder" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "keepassxc-proxy" +version = "0.1.0" +dependencies = [ + "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "named_pipe 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "named_pipe" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum named_pipe 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "516fe2b5b1131f912a3d4e0cbfec369ca9a65f89d477c15d86ef0fc376faaa55" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index cecbc13..635468a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,7 @@ license = "GPL-3.0" repository = "https://github.com/varjolintu/keepassxc-proxy-rust" [dependencies] -byteorder = "1.1.0" \ No newline at end of file +byteorder = "1.1.0" + +[target.'cfg(windows)'.dependencies] +named_pipe = "0.2" diff --git a/src/main.rs b/src/main.rs index 53002f1..8ee8db1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,83 +1,85 @@ extern crate byteorder; +#[cfg(windows)] +extern crate named_pipe; use std::io::{self, Read, Write}; -use std::os::unix::net::UnixStream; -use std::os::unix::net::UnixListener; -use std::str; use std::thread; -use std::time::Duration; use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; +#[cfg(not(windows))] +#[path = "platform_unix.rs"] +mod platform; + +#[cfg(windows)] +#[path = "platform_windows.rs"] +mod platform; + +use platform::ProxySocket; + fn valid_length(length: u32) -> bool { return length > 0 && length <= 4096; // 1024 ^ 2 is the maximum } -fn read_header() -> (u32) +fn read_header() -> u32 { let stdin = io::stdin(); let mut buf = vec![0; 4]; let mut handle = stdin.lock(); handle.read_exact(&mut buf).unwrap(); - let length: u32 = NativeEndian::read_u32(&buf); - return length; + NativeEndian::read_u32(&buf) } -fn read_body(length: u32, mut socket: &UnixStream) +fn read_body(length: u32, socket: &mut ProxySocket) { let mut buffer = vec![0; length as usize]; let stdin = io::stdin(); let mut handle = stdin.lock(); - match handle.read_exact(&mut buffer) { - Ok(_v) => { - if valid_length(length) { - socket.write(&buffer).unwrap(); - socket.flush().unwrap(); - read_unix_response(length, &socket); - } - }, - Err(_e) => {} + if let Ok(_) = handle.read_exact(&mut buffer) { + if valid_length(length) { + socket.write_u32::(length).unwrap(); + socket.write(&buffer).unwrap(); + socket.flush().unwrap(); + read_response(socket); + } } } -fn read_unix_response(length: u32, mut socket: &UnixStream) +fn read_response(socket: &mut ProxySocket) { - let mut buf = vec![0; length as usize]; + let mut len_buf = vec![0; 4]; - match socket.read(&mut buf) { - Ok(_length) => { - let text = str::from_utf8(&buf).unwrap(); - write_output(text); - }, - Err(_e) => {} - } + if let Ok(_) = socket.read_exact(&mut len_buf) { + let len = NativeEndian::read_u32(&len_buf); + let mut buf = vec![0; len as usize]; + if let Ok(_) = socket.read_exact(&mut buf) { + write_response(&buf, len); + } + } } -fn write_output(text: &str) -{ - let textlen = text.len(); +fn write_response(buf: &[u8], len: u32) { let stdout = io::stdout(); - let mut handle = stdout.lock(); + let mut out = stdout.lock(); - handle.write_u32::(textlen as u32).unwrap(); - handle.write(text.as_bytes()).unwrap(); + out.write_u32::(len).unwrap(); + out.write(buf).unwrap(); + out.flush().unwrap(); } fn main() { - let socket = UnixStream::connect("/tmp/kpxc_server").unwrap(); - let timeout: Option = Some(Duration::from_secs(1)); - socket.set_read_timeout(timeout).unwrap(); + let mut socket = ProxySocket::connect().unwrap(); // Start thread for user input reading - let send_socket = socket.try_clone().expect("Cannot clone socket"); + //let mut send_socket = socket.try_clone().expect("Cannot clone socket"); let ui = thread::spawn(move || { loop { let length = read_header(); - read_body(length, &send_socket); - } - }); + read_body(length, &mut socket); + } + }); - let _ui_res = ui.join(); + let _ui_res = ui.join(); } diff --git a/src/platform_unix.rs b/src/platform_unix.rs new file mode 100644 index 0000000..04ab330 --- /dev/null +++ b/src/platform_unix.rs @@ -0,0 +1,32 @@ +use std::env; +use std::io::{Read, Result, Write}; +use std::os::unix::net::UnixStream; +use std::time::Duration; + +pub struct ProxySocket(UnixStream); + +impl ProxySocket { + pub fn connect() -> Result { + let user = env::var("USER").unwrap(); + let s = UnixStream::connect(format!("/tmp/keepassxc-{}.socket", user))?; + let timeout: Option = Some(Duration::from_secs(1)); + s.set_read_timeout(timeout)?; + Ok(ProxySocket(s)) + } +} + +impl Read for ProxySocket { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.0.read(buf) + } +} + +impl Write for ProxySocket { + fn write(&mut self, buf: &[u8]) -> Result { + self.0.write(buf) + } + + fn flush(&mut self) -> Result<()> { + self.0.flush() + } +} diff --git a/src/platform_windows.rs b/src/platform_windows.rs new file mode 100644 index 0000000..8a10321 --- /dev/null +++ b/src/platform_windows.rs @@ -0,0 +1,28 @@ + +use std::io::{Result, Read, Write}; +use named_pipe::PipeClient; + +pub struct ProxySocket(PipeClient); + +impl ProxySocket { + pub fn connect() -> Result { + let client = PipeClient::connect("\\\\.\\pipe\\KeePassHttp").unwrap(); + Ok(ProxySocket(client)) + } +} + +impl Read for ProxySocket { + fn read(&mut self, buf: &mut [u8]) -> Result { + self.0.read(buf) + } +} + +impl Write for ProxySocket { + fn write(&mut self, buf: &[u8]) -> Result { + self.0.write(buf) + } + + fn flush(&mut self) -> Result<()> { + self.0.flush() + } +}