summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--oxish-proto/src/lib.rs33
-rw-r--r--oxish/src/session/mod.rs15
2 files changed, 47 insertions, 1 deletions
diff --git a/oxish-proto/src/lib.rs b/oxish-proto/src/lib.rs
index a67228c..be7b0ea 100644
--- a/oxish-proto/src/lib.rs
+++ b/oxish-proto/src/lib.rs
@@ -492,6 +492,39 @@ impl Encode for Ignore<'_> {
}
}
+/// The `SSH_MSG_GLOBAL_REQUEST` message
+///
+/// Requests that apply to the connection as a whole rather than to a single channel, such as
+/// the client's `[email protected]` liveness probe.
+///
+/// See <https://www.rfc-editor.org/rfc/rfc4254#section-4>.
+#[derive(Debug)]
+pub struct GlobalRequest<'a> {
+ /// The name of the request
+ pub name: &'a [u8],
+ /// Whether the sender wants a `SSH_MSG_REQUEST_SUCCESS` or `SSH_MSG_REQUEST_FAILURE` reply
+ pub want_reply: bool,
+}
+
+impl<'a> TryFrom<IncomingPacket<'a>> for GlobalRequest<'a> {
+ type Error = ProtoError;
+
+ fn try_from(packet: IncomingPacket<'a>) -> Result<Self, Self::Error> {
+ if packet.message_type != MessageType::GlobalRequest {
+ return Err(ProtoError::InvalidPacket("expected global request packet"));
+ }
+
+ let Decoded { value: name, next } = <&[u8]>::decode(packet.payload)?;
+ // Request-specific data follows `want_reply`, but we don't act on any request, so
+ // parsing the boolean is enough to know whether the sender expects a reply.
+ let Decoded {
+ value: want_reply, ..
+ } = bool::decode(next)?;
+
+ Ok(Self { name, want_reply })
+ }
+}
+
impl<'a> Decode<'a> for &'a [u8] {
fn decode(bytes: &'a [u8]) -> Result<Decoded<'a, Self>, ProtoError> {
let len = u32::decode(bytes)?;
diff --git a/oxish/src/session/mod.rs b/oxish/src/session/mod.rs
index 1fdd95c..b61bdeb 100644
--- a/oxish/src/session/mod.rs
+++ b/oxish/src/session/mod.rs
@@ -10,7 +10,8 @@ use std::{
};
use proto::{
- Decoded, Disconnect, Encoder, MessageType, Pretty, ReadState, SessionHostKey, WriteState,
+ Decoded, Disconnect, Encoder, GlobalRequest, MessageType, Pretty, ReadState, SessionHostKey,
+ WriteState,
channels::{ChannelRequest, ChannelRequestType},
crypto::CryptoProvider,
key_exchange::Rekey,
@@ -214,6 +215,18 @@ impl<T: AsyncRead + AsyncWrite + Unpin> Session<T> {
self.post_quantum_kx = post_quantum_kx;
continue;
}
+ MessageType::GlobalRequest => {
+ let request = GlobalRequest::try_from(packet)?;
+ debug!(name = %String::from_utf8_lossy(request.name), "refusing unsupported global request");
+ if request.want_reply {
+ self.conn.send(&MessageType::RequestFailure).await?;
+ }
+ continue;
+ }
+ MessageType::RequestSuccess | MessageType::RequestFailure => {
+ trace!(?packet.message_type, "ignoring unexpected global request reply");
+ continue;
+ }
_ => {}
}