summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2022-12-07 09:57:03 +0100
committerNeal H. Walfield <neal@pep.foundation>2022-12-07 13:56:34 +0100
commit580979bb2cc5279ee06c49ee6a13f7a668f37d3e (patch)
treec2f3a52d1398a7cebb0774e9b4081172bdae119c
parenta717a840b95271731a90257147cffd64682ea986 (diff)
ipc: Process agent responses more carefully.neal/agent
- A command has an expected response. Process the response before sending the next command.
-rw-r--r--ipc/src/gnupg.rs112
1 files changed, 65 insertions, 47 deletions
diff --git a/ipc/src/gnupg.rs b/ipc/src/gnupg.rs
index 677a82fc..f1de6bc7 100644
--- a/ipc/src/gnupg.rs
+++ b/ipc/src/gnupg.rs
@@ -652,8 +652,16 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
Options => match client.as_mut().poll_next(cx)? {
Poll::Ready(Some(r)) => match r {
- assuan::Response::Ok { .. }
- | assuan::Response::Comment { .. }
+ assuan::Response::Ok { .. } => {
+ if let Some(option) = options.pop() {
+ client.send(option)?;
+ } else {
+ let grip = Keygrip::of(key.public.mpis())?;
+ client.send(format!("SETKEY {}", grip))?;
+ *state = SetKey;
+ }
+ }
+ assuan::Response::Comment { .. }
| assuan::Response::Status { .. } =>
(), // Ignore.
assuan::Response::Error { ref message, .. } =>
@@ -662,21 +670,21 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
return Poll::Ready(protocol_error(&r)),
},
Poll::Ready(None) => {
- if let Some(option) = options.pop() {
- client.send(option)?;
- } else {
- let grip = Keygrip::of(key.public.mpis())?;
- client.send(format!("SETKEY {}", grip))?;
- *state = SetKey;
- }
- },
+ // We're still waiting for the response to an
+ // outstanding OPTION.
+ }
Poll::Pending => return Poll::Pending,
},
SetKey => match client.as_mut().poll_next(cx)? {
Poll::Ready(Some(r)) => match r {
- assuan::Response::Ok { .. }
- | assuan::Response::Comment { .. }
+ assuan::Response::Ok { .. } => {
+ client.send(
+ format!("SETKEYDESC {}",
+ assuan::escape(&key.password_prompt)))?;
+ *state = SetKeyDesc;
+ }
+ assuan::Response::Comment { .. }
| assuan::Response::Status { .. } =>
(), // Ignore.
assuan::Response::Error { ref message, .. } =>
@@ -685,18 +693,19 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
return Poll::Ready(protocol_error(&r)),
},
Poll::Ready(None) => {
- client.send(
- format!("SETKEYDESC {}",
- assuan::escape(&key.password_prompt)))?;
- *state = SetKeyDesc;
- },
+ // We're still waiting for the response to an
+ // outstanding OPTION.
+ }
Poll::Pending => return Poll::Pending,
},
SetKeyDesc => match client.as_mut().poll_next(cx)? {
Poll::Ready(Some(r)) => match r {
- assuan::Response::Ok { .. }
- | assuan::Response::Comment { .. }
+ assuan::Response::Ok { .. } => {
+ client.send("PKDECRYPT")?;
+ *state = PkDecrypt;
+ }
+ assuan::Response::Comment { .. }
| assuan::Response::Status { .. } =>
(), // Ignore.
assuan::Response::Error { ref message, .. } =>
@@ -705,8 +714,8 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
return Poll::Ready(protocol_error(&r)),
},
Poll::Ready(None) => {
- client.send("PKDECRYPT")?;
- *state = PkDecrypt;
+ // We're still waiting for the response to an
+ // outstanding SETKEY.
},
Poll::Pending => return Poll::Pending,
},
@@ -714,22 +723,26 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
PkDecrypt => match client.as_mut().poll_next(cx)? {
Poll::Ready(Some(r)) => match r {
assuan::Response::Inquire { ref keyword, .. }
- if keyword == "CIPHERTEXT" =>
- (), // What we expect.
+ if keyword == "CIPHERTEXT" => {
+ let mut buf = Vec::new();
+ Sexp::try_from(*ciphertext)?
+ .serialize(&mut buf)?;
+ client.data(&buf)?;
+ *state = Inquire(Vec::new(), true);
+ }
assuan::Response::Comment { .. }
| assuan::Response::Status { .. } =>
(), // Ignore.
- assuan::Response::Error { ref message, .. } =>
- return Poll::Ready(operation_failed(message)),
+ assuan::Response::Error { ref message, .. } => {
+ *state = Start;
+ return Poll::Ready(operation_failed(message));
+ }
_ =>
return Poll::Ready(protocol_error(&r)),
},
Poll::Ready(None) => {
- let mut buf = Vec::new();
- Sexp::try_from(*ciphertext)?
- .serialize(&mut buf)?;
- client.data(&buf)?;
- *state = Inquire(Vec::new(), true);
+ // We're still waiting for the response to an
+ // outstanding SETKEYDESC.
},
Poll::Pending => return Poll::Pending,
},
@@ -737,34 +750,39 @@ impl<'a, 'b, 'c> Future for DecryptionRequest<'a, 'b, 'c>
Inquire(ref mut data, ref mut padding) => match client.as_mut().poll_next(cx)? {
Poll::Ready(Some(r)) => match r {
- assuan::Response::Ok { .. }
- | assuan::Response::Comment { .. } =>
+ assuan::Response::Ok { .. } => {
+ // Get rid of the safety-0.
+ //
+ // gpg-agent seems to add a trailing 0,
+ // supposedly for good measure.
+ if data.iter().last() == Some(&0) {
+ let l = data.len();
+ data.truncate(l - 1);
+ }
+
+ return Poll::Ready(
+ Sexp::from_bytes(&data)?.finish_decryption(
+ &key.public, ciphertext, *padding)
+ );
+ }
+ assuan::Response::Comment { .. } =>
(), // Ignore.
assuan::Response::Status { ref keyword, ref message } =>
if keyword == "PADDING" {
*padding = message != "0";
},
- assuan::Response::Error { ref message, .. } =>
- return Poll::Ready(operation_failed(message)),
+ assuan::Response::Error { ref message, .. } => {
+ *state = Start;
+ return Poll::Ready(operation_failed(message));
+ }
assuan::Response::Data { ref partial } =>
data.extend_from_slice(partial),
_ =>
return Poll::Ready(protocol_error(&r)),
},
Poll::Ready(None) => {
- // Get rid of the safety-0.
- //
- // gpg-agent seems to add a trailing 0,
- // supposedly for good measure.
- if data.iter().last() == Some(&0) {
- let l = data.len();
- data.truncate(l - 1);
- }
-
- return Poll::Ready(
- Sexp::from_bytes(&data)?.finish_decryption(
- &key.public, ciphertext, *padding)
- );
+ // We're still waiting for the response to an
+ // outstanding PKDECRYPT.
},
Poll::Pending => return Poll::Pending,
},