diff options
author | Neal H. Walfield <neal@pep.foundation> | 2022-12-07 09:57:03 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2022-12-07 13:56:34 +0100 |
commit | 580979bb2cc5279ee06c49ee6a13f7a668f37d3e (patch) | |
tree | c2f3a52d1398a7cebb0774e9b4081172bdae119c | |
parent | a717a840b95271731a90257147cffd64682ea986 (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.rs | 112 |
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, }, |