-
-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement streamlocal-forward for remote => local UDS forwarding (#312)
I left a `// NEED HELP` comment on places where I didn't fully figure out what to do, so I'd really appreciate it if some maintainers helped me out in those places. --------- Co-authored-by: Eugene <[email protected]>
- Loading branch information
Showing
9 changed files
with
278 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ This is a fork of [Thrussh](https://nest.pijul.com/pijul/thrussh) by Pierre-Éti | |
* `direct-tcpip` (local port forwarding) | ||
* `forward-tcpip` (remote port forwarding) ✨ | ||
* `direct-streamlocal` (local UNIX socket forwarding, client only) ✨ | ||
* `forward-streamlocal` (remote UNIX socket forwarding) ✨ | ||
* Ciphers: | ||
* `[email protected]` | ||
* `[email protected]` ✨ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -293,7 +293,7 @@ impl Session { | |
|
||
/// Requests cancellation of TCP/IP forwarding from the server | ||
/// | ||
/// If `want_reply` is `true`, returns a oneshot receiveing the server's reply: | ||
/// If `reply_channel` is not None, sets want_reply and returns the server's response via the channel, | ||
/// `true` for a success message, or `false` for failure | ||
pub fn cancel_tcpip_forward( | ||
&mut self, | ||
|
@@ -318,6 +318,58 @@ impl Session { | |
} | ||
} | ||
|
||
/// Requests a UDS forwarding from the server, `socket path` being the server side socket path. | ||
/// | ||
/// If `reply_channel` is not None, sets want_reply and returns the server's response via the channel, | ||
/// `true` for a success message, or `false` for failure | ||
pub fn streamlocal_forward( | ||
&mut self, | ||
reply_channel: Option<oneshot::Sender<bool>>, | ||
socket_path: &str, | ||
) { | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
let want_reply = reply_channel.is_some(); | ||
if let Some(reply_channel) = reply_channel { | ||
self.open_global_requests.push_back( | ||
crate::session::GlobalRequestResponse::StreamLocalForward(reply_channel), | ||
); | ||
} | ||
push_packet!(enc.write, { | ||
enc.write.push(msg::GLOBAL_REQUEST); | ||
enc.write | ||
.extend_ssh_string(b"[email protected]"); | ||
enc.write.push(want_reply as u8); | ||
enc.write.extend_ssh_string(socket_path.as_bytes()); | ||
}); | ||
} | ||
} | ||
|
||
/// Requests cancellation of UDS forwarding from the server | ||
/// | ||
/// If `reply_channel` is not None, sets want_reply and returns the server's response via the channel, | ||
/// `true` for a success message and `false` for failure. | ||
pub fn cancel_streamlocal_forward( | ||
&mut self, | ||
reply_channel: Option<oneshot::Sender<bool>>, | ||
socket_path: &str, | ||
) { | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
let want_reply = reply_channel.is_some(); | ||
if let Some(reply_channel) = reply_channel { | ||
self.open_global_requests.push_back( | ||
crate::session::GlobalRequestResponse::CancelStreamLocalForward(reply_channel), | ||
); | ||
} | ||
push_packet!(enc.write, { | ||
enc.write.push(msg::GLOBAL_REQUEST); | ||
enc.write | ||
.extend_ssh_string(b"[email protected]"); | ||
enc.write.push(want_reply as u8); | ||
enc.write.extend_ssh_string(socket_path.as_bytes()); | ||
}); | ||
} | ||
} | ||
|
||
pub fn send_keepalive(&mut self, want_reply: bool) { | ||
self.open_global_requests | ||
.push_back(crate::session::GlobalRequestResponse::Keepalive); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,9 @@ impl OpenChannelMessage { | |
} | ||
b"direct-tcpip" => ChannelType::DirectTcpip(TcpChannelInfo::new(r)?), | ||
b"forwarded-tcpip" => ChannelType::ForwardedTcpIp(TcpChannelInfo::new(r)?), | ||
b"[email protected]" => { | ||
ChannelType::ForwardedStreamLocal(StreamLocalChannelInfo::new(r)?) | ||
} | ||
b"[email protected]" => ChannelType::AgentForward, | ||
t => ChannelType::Unknown { typ: t.to_vec() }, | ||
}; | ||
|
@@ -91,6 +94,7 @@ pub enum ChannelType { | |
}, | ||
DirectTcpip(TcpChannelInfo), | ||
ForwardedTcpIp(TcpChannelInfo), | ||
ForwardedStreamLocal(StreamLocalChannelInfo), | ||
AgentForward, | ||
Unknown { | ||
typ: Vec<u8>, | ||
|
@@ -105,6 +109,21 @@ pub struct TcpChannelInfo { | |
pub originator_port: u32, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct StreamLocalChannelInfo { | ||
pub socket_path: String, | ||
} | ||
|
||
impl StreamLocalChannelInfo { | ||
fn new(r: &mut Position) -> Result<Self, crate::Error> { | ||
let socket_path = std::str::from_utf8(r.read_string().map_err(crate::Error::from)?) | ||
.map_err(crate::Error::from)? | ||
.to_owned(); | ||
|
||
Ok(Self { socket_path }) | ||
} | ||
} | ||
|
||
impl TcpChannelInfo { | ||
fn new(r: &mut Position) -> Result<Self, crate::Error> { | ||
let host_to_connect = std::str::from_utf8(r.read_string().map_err(crate::Error::from)?) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1023,6 +1023,40 @@ impl Session { | |
} | ||
Ok(()) | ||
} | ||
b"[email protected]" => { | ||
let server_socket_path = | ||
std::str::from_utf8(r.read_string().map_err(crate::Error::from)?) | ||
.map_err(crate::Error::from)?; | ||
debug!("handler.streamlocal_forward {:?}", server_socket_path); | ||
let result = handler | ||
.streamlocal_forward(server_socket_path, self) | ||
.await?; | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
if result { | ||
push_packet!(enc.write, enc.write.push(msg::REQUEST_SUCCESS)) | ||
} else { | ||
push_packet!(enc.write, enc.write.push(msg::REQUEST_FAILURE)) | ||
} | ||
} | ||
Ok(()) | ||
} | ||
b"[email protected]" => { | ||
let socket_path = | ||
std::str::from_utf8(r.read_string().map_err(crate::Error::from)?) | ||
.map_err(crate::Error::from)?; | ||
debug!("handler.cancel_streamlocal_forward {:?}", socket_path); | ||
let result = handler | ||
.cancel_streamlocal_forward(socket_path, self) | ||
.await?; | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
if result { | ||
push_packet!(enc.write, enc.write.push(msg::REQUEST_SUCCESS)) | ||
} else { | ||
push_packet!(enc.write, enc.write.push(msg::REQUEST_FAILURE)) | ||
} | ||
} | ||
Ok(()) | ||
} | ||
_ => { | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
push_packet!(enc.write, { | ||
|
@@ -1087,7 +1121,7 @@ impl Session { | |
Some(GlobalRequestResponse::CancelTcpIpForward(return_channel)) => { | ||
let _ = return_channel.send(true); | ||
} | ||
None => { | ||
_ => { | ||
error!("Received global request failure for unknown request!") | ||
} | ||
} | ||
|
@@ -1105,7 +1139,7 @@ impl Session { | |
Some(GlobalRequestResponse::CancelTcpIpForward(return_channel)) => { | ||
let _ = return_channel.send(false); | ||
} | ||
None => { | ||
_ => { | ||
error!("Received global request failure for unknown request!") | ||
} | ||
} | ||
|
@@ -1211,6 +1245,16 @@ impl Session { | |
} | ||
result | ||
} | ||
ChannelType::ForwardedStreamLocal(_) => { | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
msg.fail( | ||
&mut enc.write, | ||
msg::SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, | ||
b"Unsupported channel type", | ||
); | ||
} | ||
Ok(false) | ||
} | ||
ChannelType::AgentForward => { | ||
if let Some(ref mut enc) = self.common.encrypted { | ||
msg.fail( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.