add windows named pipe support

This commit is contained in:
Andy Brandt
2017-11-29 15:42:47 -06:00
parent 6c5f96f407
commit 5b9d6eac06
6 changed files with 154 additions and 41 deletions
+1
View File
@@ -0,0 +1 @@
/target/
Generated
+47
View File
@@ -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"
+3
View File
@@ -8,3 +8,6 @@ repository = "https://github.com/varjolintu/keepassxc-proxy-rust"
[dependencies] [dependencies]
byteorder = "1.1.0" byteorder = "1.1.0"
[target.'cfg(windows)'.dependencies]
named_pipe = "0.2"
+42 -40
View File
@@ -1,83 +1,85 @@
extern crate byteorder; extern crate byteorder;
#[cfg(windows)]
extern crate named_pipe;
use std::io::{self, Read, Write}; 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::thread;
use std::time::Duration;
use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; 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 fn valid_length(length: u32) -> bool
{ {
return length > 0 && length <= 4096; // 1024 ^ 2 is the maximum return length > 0 && length <= 4096; // 1024 ^ 2 is the maximum
} }
fn read_header() -> (u32) fn read_header() -> u32
{ {
let stdin = io::stdin(); let stdin = io::stdin();
let mut buf = vec![0; 4]; let mut buf = vec![0; 4];
let mut handle = stdin.lock(); let mut handle = stdin.lock();
handle.read_exact(&mut buf).unwrap(); handle.read_exact(&mut buf).unwrap();
let length: u32 = NativeEndian::read_u32(&buf); NativeEndian::read_u32(&buf)
return length;
} }
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 mut buffer = vec![0; length as usize];
let stdin = io::stdin(); let stdin = io::stdin();
let mut handle = stdin.lock(); let mut handle = stdin.lock();
match handle.read_exact(&mut buffer) { if let Ok(_) = handle.read_exact(&mut buffer) {
Ok(_v) => { if valid_length(length) {
if valid_length(length) { socket.write_u32::<NativeEndian>(length).unwrap();
socket.write(&buffer).unwrap(); socket.write(&buffer).unwrap();
socket.flush().unwrap(); socket.flush().unwrap();
read_unix_response(length, &socket); read_response(socket);
} }
},
Err(_e) => {}
} }
} }
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) { if let Ok(_) = socket.read_exact(&mut len_buf) {
Ok(_length) => { let len = NativeEndian::read_u32(&len_buf);
let text = str::from_utf8(&buf).unwrap(); let mut buf = vec![0; len as usize];
write_output(text); if let Ok(_) = socket.read_exact(&mut buf) {
}, write_response(&buf, len);
Err(_e) => {} }
} }
} }
fn write_output(text: &str) fn write_response(buf: &[u8], len: u32) {
{
let textlen = text.len();
let stdout = io::stdout(); let stdout = io::stdout();
let mut handle = stdout.lock(); let mut out = stdout.lock();
handle.write_u32::<NativeEndian>(textlen as u32).unwrap(); out.write_u32::<NativeEndian>(len).unwrap();
handle.write(text.as_bytes()).unwrap(); out.write(buf).unwrap();
out.flush().unwrap();
} }
fn main() { fn main() {
let socket = UnixStream::connect("/tmp/kpxc_server").unwrap(); let mut socket = ProxySocket::connect().unwrap();
let timeout: Option<Duration> = Some(Duration::from_secs(1));
socket.set_read_timeout(timeout).unwrap();
// Start thread for user input reading // 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 || { let ui = thread::spawn(move || {
loop { loop {
let length = read_header(); let length = read_header();
read_body(length, &send_socket); read_body(length, &mut socket);
} }
}); });
let _ui_res = ui.join(); let _ui_res = ui.join();
} }
+32
View File
@@ -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<ProxySocket> {
let user = env::var("USER").unwrap();
let s = UnixStream::connect(format!("/tmp/keepassxc-{}.socket", user))?;
let timeout: Option<Duration> = 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<usize> {
self.0.read(buf)
}
}
impl Write for ProxySocket {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
}
+28
View File
@@ -0,0 +1,28 @@
use std::io::{Result, Read, Write};
use named_pipe::PipeClient;
pub struct ProxySocket(PipeClient);
impl ProxySocket {
pub fn connect() -> Result<ProxySocket> {
let client = PipeClient::connect("\\\\.\\pipe\\KeePassHttp").unwrap();
Ok(ProxySocket(client))
}
}
impl Read for ProxySocket {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}
}
impl Write for ProxySocket {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> Result<()> {
self.0.flush()
}
}