aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-05-02 18:45:50 -0400
committerJesse Luehrs <doy@tozt.net>2020-05-02 18:59:11 -0400
commitf035ac5470c7fbcf791e361cb2d611de7edafb0f (patch)
tree8d75832af542bb27ca32163fbadc67758dde50cb
parentbcf1df8dd65fb24c767ca91159fc5639dbd5375f (diff)
downloadrbw-f035ac5470c7fbcf791e361cb2d611de7edafb0f.tar.gz
rbw-f035ac5470c7fbcf791e361cb2d611de7edafb0f.zip
check protocol version before agent communication
-rw-r--r--src/bin/rbw-agent/actions.rs10
-rw-r--r--src/bin/rbw-agent/agent.rs4
-rw-r--r--src/bin/rbw/actions.rs18
-rw-r--r--src/bin/rbw/commands.rs24
-rw-r--r--src/protocol.rs4
5 files changed, 60 insertions, 0 deletions
diff --git a/src/bin/rbw-agent/actions.rs b/src/bin/rbw-agent/actions.rs
index 8823424..52c34fa 100644
--- a/src/bin/rbw-agent/actions.rs
+++ b/src/bin/rbw-agent/actions.rs
@@ -256,6 +256,16 @@ pub async fn encrypt(
Ok(())
}
+pub async fn version(sock: &mut crate::sock::Sock) -> anyhow::Result<()> {
+ sock.send(&rbw::protocol::Response::Version {
+ version: rbw::protocol::VERSION,
+ })
+ .await
+ .context("failed to send response")?;
+
+ Ok(())
+}
+
async fn respond_ack(sock: &mut crate::sock::Sock) -> anyhow::Result<()> {
sock.send(&rbw::protocol::Response::Ack)
.await
diff --git a/src/bin/rbw-agent/agent.rs b/src/bin/rbw-agent/agent.rs
index 9021569..72d6077 100644
--- a/src/bin/rbw-agent/agent.rs
+++ b/src/bin/rbw-agent/agent.rs
@@ -156,6 +156,10 @@ async fn handle_request(
true
}
rbw::protocol::Action::Quit => std::process::exit(0),
+ rbw::protocol::Action::Version => {
+ crate::actions::version(sock).await?;
+ true
+ }
};
if set_timeout {
diff --git a/src/bin/rbw/actions.rs b/src/bin/rbw/actions.rs
index 273b038..399b7f3 100644
--- a/src/bin/rbw/actions.rs
+++ b/src/bin/rbw/actions.rs
@@ -82,6 +82,24 @@ pub fn encrypt(plaintext: &str) -> anyhow::Result<String> {
}
}
+pub fn version() -> anyhow::Result<u32> {
+ let mut sock = crate::sock::Sock::connect()
+ .context("failed to connect to rbw-agent")?;
+ sock.send(&rbw::protocol::Request {
+ tty: std::env::var("TTY").ok(),
+ action: rbw::protocol::Action::Version,
+ })?;
+
+ let res = sock.recv()?;
+ match res {
+ rbw::protocol::Response::Version { version } => Ok(version),
+ rbw::protocol::Response::Error { error } => {
+ Err(anyhow::anyhow!("failed to get version: {}", error))
+ }
+ _ => Err(anyhow::anyhow!("unexpected message: {:?}", res)),
+ }
+}
+
fn simple_action(
action: rbw::protocol::Action,
desc: &str,
diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs
index 6c9d18c..b29987d 100644
--- a/src/bin/rbw/commands.rs
+++ b/src/bin/rbw/commands.rs
@@ -493,6 +493,30 @@ pub fn stop_agent() -> anyhow::Result<()> {
}
fn ensure_agent() -> anyhow::Result<()> {
+ ensure_agent_once()?;
+ let version = crate::actions::version()?;
+ if version != rbw::protocol::VERSION {
+ log::debug!(
+ "client protocol version is {} but agent protocol version is {}",
+ rbw::protocol::VERSION,
+ version
+ );
+ crate::actions::quit()?;
+ ensure_agent_once()?;
+ let version = crate::actions::version()?;
+ if version != rbw::protocol::VERSION {
+ crate::actions::quit()?;
+ return Err(anyhow::anyhow!(
+ "incompatible protocol versions: client ({}), agent ({})",
+ rbw::protocol::VERSION,
+ version
+ ));
+ }
+ }
+ Ok(())
+}
+
+fn ensure_agent_once() -> anyhow::Result<()> {
let agent_path = std::env::var("RBW_AGENT");
let agent_path = agent_path
.as_ref()
diff --git a/src/protocol.rs b/src/protocol.rs
index de8833c..2ef99cd 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -1,3 +1,5 @@
+pub const VERSION: u32 = 1;
+
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct Request {
pub tty: Option<String>,
@@ -14,6 +16,7 @@ pub enum Action {
Decrypt { cipherstring: String },
Encrypt { plaintext: String },
Quit,
+ Version,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
@@ -23,4 +26,5 @@ pub enum Response {
Error { error: String },
Decrypt { plaintext: String },
Encrypt { cipherstring: String },
+ Version { version: u32 },
}