Struct Channel

Source
pub struct Channel { /* private fields */ }
Expand description

Represents a channel in a Session.

A Session can have multiple channels; there is typically one for the shell/program being run, but additional channels can be opened to forward TCP or other connections.

open_session is often the first thing you will call on the Channel after creating it; this establishes the channel for executing commands.

Then you will typically use either request_exec to run a non-interactive command, or request_pty followed request_shell to set up an interactive remote shell.

§Thread Safety

Channel is strongly associated with the Session to which it belongs. libssh doesn’t allow using anything associated with a given Session from multiple threads concurrently. These Rust bindings encapsulate the underlying Session in an internal mutex, which allows you to safely operate on the various elements of the session and even move them to other threads, but you need to be aware that calling methods on any of those structs will attempt to lock the underlying session, and this can lead to blocking in surprising situations.

Implementations§

Source§

impl Channel

Source

pub fn accept_x11(&self, timeout: Duration) -> Option<Self>

Accept an X11 forwarding channel. Returns a newly created Channel, or None if no X11 request from the server.

Source

pub fn close(&self) -> SshResult<()>

Close a channel. This sends an end of file and then closes the channel. You won’t be able to recover any data the server was going to send or was in buffers.

Source

pub fn get_exit_status(&self) -> Option<c_int>

Get the exit status of the channel (error code from the executed instruction). This function may block until a timeout (or never) if the other side is not willing to close the channel.

Examples found in repository?
examples/whoami.rs (line 140)
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}
Source

pub fn get_exit_signal(&self) -> Option<SignalState>

Get the exit signal status of the channel. If the channel was closed/terminated due to a signal, and the remote system supports the signal concept, the signal state will be set and reported here.

Source

pub fn is_closed(&self) -> bool

Check if the channel is closed or not.

Source

pub fn is_eof(&self) -> bool

Check if remote has sent an EOF.

Source

pub fn send_eof(&self) -> SshResult<()>

Send an end of file on the channel.

You should call this when you have no additional data to send to the channel to signal that information to the remote host.

This doesn’t close the channel. You may still read from it but not write.

Examples found in repository?
examples/whoami.rs (line 133)
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}
Source

pub fn is_open(&self) -> bool

Check if the channel is open or not.

Source

pub fn open_auth_agent(&self) -> SshResult<()>

Open an agent authentication forwarding channel. This type of channel can be opened by a server towards a client in order to provide SSH-Agent services to the server-side process. This channel can only be opened if the client claimed support by sending a channel request beforehand.

Source

pub fn request_auth_agent(&self) -> SshResult<()>

Send an "auth-agent-req" channel request over an existing session channel.

This client-side request will enable forwarding the agent over a secure tunnel. When the server is ready to open one authentication agent channel, an ssh_channel_open_request_auth_agent_callback event will be generated.

Source

pub fn request_env(&self, name: &str, value: &str) -> SshResult<()>

Set environment variable. Some environment variables may be refused by security reasons.

Source

pub fn request_shell(&self) -> SshResult<()>

Requests a shell; asks the server to spawn the user’s shell, rather than directly executing a command specified by the client.

The channel must be a session channel; you need to have called open_session before this will succeed.

Source

pub fn request_exec(&self, command: &str) -> SshResult<()>

Run a shell command without an interactive shell. This is similar to ‘sh -c command’.

The channel must be a session channel; you need to have called open_session before this will succeed.

Examples found in repository?
examples/whoami.rs (line 132)
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}
Source

pub fn request_subsystem(&self, subsys: &str) -> SshResult<()>

Request a subsystem.

You probably don’t need this unless you know what you are doing!

Source

pub fn request_pty(&self, term: &str, columns: u32, rows: u32) -> SshResult<()>

Request a PTY with a specific type and size. A PTY is useful when you want to run an interactive program on the remote host.

term is the initial value for the TERM environment variable. If you’re not sure what to fill for the values, term = "xterm", columns = 80 and rows = 24 are reasonable defaults.

Source

pub fn change_pty_size(&self, columns: u32, rows: u32) -> SshResult<()>

Informs the server that the local size of the PTY has changed

Source

pub fn request_send_break(&self, length: Duration) -> SshResult<()>

Send a break signal to the server (as described in RFC 4335). Sends a break signal to the remote process. Note, that remote system may not support breaks. In such a case this request will be silently ignored.

Source

pub fn request_send_signal(&self, signal: &str) -> SshResult<()>

Send a signal to remote process (as described in RFC 4254, section 6.9). Sends a signal to the remote process. Note, that remote system may not support signals concept. In such a case this request will be silently ignored.

signal is the name of the signal, without the "SIG" prefix. For example, "ABRT", "INT", "KILL" and so on.

The OpenSSH server has only supported signals since OpenSSH version 8.1, released in 2019. https://bugzilla.mindrot.org/show_bug.cgi?id=1424

Source

pub fn open_forward( &self, remote_host: &str, remote_port: u16, source_host: &str, source_port: u16, ) -> SshResult<()>

Open a TCP/IP forwarding channel. remote_host, remote_port identify the destination for the connection. source_host, source_port identify the origin of the connection on the client side; these are used primarily for logging purposes.

This function does not bind the source port and does not automatically forward the content of a socket to the channel. You still have to read/write this channel object to achieve that.

Source

pub fn open_forward_unix( &self, remote_path: &str, source_host: &str, source_port: u16, ) -> SshResult<()>

Open a UNIX domain socket forwarding channel. remote_path is the path to the unix socket to open on the remote machine. source_host and source_port identify the originating connection from the client machine and are used for logging purposes.

This function does not bind the source and does not automatically forward the content of a socket to the channel. You still have to read/write this channel object to achieve that.

Source

pub fn request_x11( &self, single_connection: bool, protocol: Option<&str>, cookie: Option<&str>, screen_number: c_int, ) -> SshResult<()>

Sends the "x11-req" channel request over an existing session channel. This will enable redirecting the display of the remote X11 applications to local X server over an secure tunnel.

Source

pub fn open_session(&self) -> SshResult<()>

Open a session channel (suited for a shell, not TCP forwarding).

Examples found in repository?
examples/whoami.rs (line 131)
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}
Source

pub fn poll_timeout( &self, is_stderr: bool, timeout: Option<Duration>, ) -> SshResult<PollStatus>

Polls a channel for data to read. Returns the number of bytes available for reading. If timeout is None, then blocks until data is available.

Source

pub fn read_timeout( &self, buf: &mut [u8], is_stderr: bool, timeout: Option<Duration>, ) -> SshResult<usize>

Reads data from a channel. This function may fewer bytes than the buf size.

Source

pub fn read_nonblocking( &self, buf: &mut [u8], is_stderr: bool, ) -> SshResult<usize>

Do a nonblocking read on the channel. A nonblocking read on the specified channel. it will return <= count bytes of data read atomically.

Source

pub fn window_size(&self) -> usize

Get the remote window size. This is the maximum amounts of bytes the remote side expects us to send before growing the window again. A nonzero return value does not guarantee the socket is ready to send that much data. Buffering may happen in the local SSH packet buffer, so beware of really big window sizes. A zero return value means that a write will block (if the session is in blocking mode) until the window grows back.

Source

pub fn stdout(&self) -> impl Read + '_

Returns a struct that implements std::io::Read and that will read data from the stdout channel.

Examples found in repository?
examples/whoami.rs (line 136)
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}
Source

pub fn stderr(&self) -> impl Read + '_

Returns a struct that implements std::io::Read and that will read data from the stderr channel.

Source

pub fn stdin(&self) -> impl Write + '_

Returns a struct that implements std::io::Write and that will write data to the stdin channel

Trait Implementations§

Source§

impl Drop for Channel

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for Channel

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.