mirror of
https://github.com/Noratrieb/cluelessh.git
synced 2026-01-14 16:35:06 +01:00
glorious sans-io tests
This commit is contained in:
parent
d68caf8e3c
commit
8c1f3afd89
3 changed files with 107 additions and 12 deletions
|
|
@ -399,13 +399,14 @@ impl ServerChannelsState {
|
||||||
pub fn do_operation(&mut self, op: ChannelOperation) {
|
pub fn do_operation(&mut self, op: ChannelOperation) {
|
||||||
op.trace();
|
op.trace();
|
||||||
|
|
||||||
let channel = self
|
let Ok(channel) = self.channel(op.number) else {
|
||||||
.channel(op.number)
|
debug!(number = %op.number, "Dropping operation as channel does not exist, probably because it has been closed");
|
||||||
.expect("passed channel ID that does not exist");
|
return;
|
||||||
|
};
|
||||||
let peer = channel.peer_channel;
|
let peer = channel.peer_channel;
|
||||||
|
|
||||||
if channel.we_closed {
|
if channel.we_closed {
|
||||||
debug!("Dropping operation as channel has been closed already");
|
debug!(number = %op.number, "Dropping operation as channel has been closed already");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,20 +535,88 @@ impl ChannelOperation {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ssh_transport::packet::Packet;
|
use ssh_transport::{numbers, packet::Packet};
|
||||||
|
|
||||||
use crate::ServerChannelsState;
|
use crate::{ChannelNumber, ChannelOperation, ChannelOperationKind, ServerChannelsState};
|
||||||
|
|
||||||
|
fn assert_response(state: &mut ServerChannelsState, types: &[u8]) {
|
||||||
|
let response = state
|
||||||
|
.packets_to_send()
|
||||||
|
.map(|p| numbers::packet_type_to_string(p.packet_type()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let expected = types
|
||||||
|
.iter()
|
||||||
|
.map(|p| numbers::packet_type_to_string(*p))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
assert_eq!(expected, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_session_channel(state: &mut ServerChannelsState) {
|
||||||
|
state
|
||||||
|
.recv_packet(Packet::new_msg_channel_open_session(
|
||||||
|
b"session", 0, 2048, 1024,
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
assert_response(state, &[numbers::SSH_MSG_CHANNEL_OPEN_CONFIRMATION]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interactive_pty() {
|
||||||
|
let state = &mut ServerChannelsState::new();
|
||||||
|
open_session_channel(state);
|
||||||
|
|
||||||
|
state
|
||||||
|
.recv_packet(Packet::new_msg_channel_request_pty_req(
|
||||||
|
0, b"pty-req", true, b"xterm", 80, 24, 0, 0, b"",
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
state.do_operation(ChannelNumber(0).construct_op(ChannelOperationKind::Success));
|
||||||
|
assert_response(state, &[numbers::SSH_MSG_CHANNEL_SUCCESS]);
|
||||||
|
|
||||||
|
state
|
||||||
|
.recv_packet(Packet::new_msg_channel_request_shell(0, b"shell", true))
|
||||||
|
.unwrap();
|
||||||
|
state.do_operation(ChannelNumber(0).construct_op(ChannelOperationKind::Success));
|
||||||
|
assert_response(state, &[numbers::SSH_MSG_CHANNEL_SUCCESS]);
|
||||||
|
|
||||||
|
state
|
||||||
|
.recv_packet(Packet::new_msg_channel_data(0, b"hello, world"))
|
||||||
|
.unwrap();
|
||||||
|
assert_response(state, &[]);
|
||||||
|
|
||||||
|
state.recv_packet(Packet::new_msg_channel_eof(0)).unwrap();
|
||||||
|
assert_response(state, &[]);
|
||||||
|
|
||||||
|
state.recv_packet(Packet::new_msg_channel_close(0)).unwrap();
|
||||||
|
assert_response(state, &[numbers::SSH_MSG_CHANNEL_CLOSE]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn only_single_close_for_double_close_operation() {
|
fn only_single_close_for_double_close_operation() {
|
||||||
let state = ServerChannelsState::new();
|
let state = &mut ServerChannelsState::new();
|
||||||
//state.recv_packet();
|
open_session_channel(state);
|
||||||
|
state.do_operation(ChannelOperation {
|
||||||
|
number: ChannelNumber(0),
|
||||||
|
kind: ChannelOperationKind::Close,
|
||||||
|
});
|
||||||
|
state.do_operation(ChannelOperation {
|
||||||
|
number: ChannelNumber(0),
|
||||||
|
kind: ChannelOperationKind::Close,
|
||||||
|
});
|
||||||
|
assert_response(state, &[numbers::SSH_MSG_CHANNEL_CLOSE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
fn ignore_operation_after_close() {
|
||||||
fn panic_when_data_operation_after_close() {
|
let mut state = &mut ServerChannelsState::new();
|
||||||
let state = ServerChannelsState::new();
|
open_session_channel(state);
|
||||||
//state.recv_packet();
|
state.recv_packet(Packet::new_msg_channel_close(0)).unwrap();
|
||||||
|
assert_response(&mut state, &[numbers::SSH_MSG_CHANNEL_CLOSE]);
|
||||||
|
state.do_operation(ChannelOperation {
|
||||||
|
number: ChannelNumber(0),
|
||||||
|
kind: ChannelOperationKind::Data(vec![0]),
|
||||||
|
});
|
||||||
|
assert_response(state, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,10 @@ pub struct Packet {
|
||||||
impl Packet {
|
impl Packet {
|
||||||
pub const DEFAULT_BLOCK_SIZE: u8 = 8;
|
pub const DEFAULT_BLOCK_SIZE: u8 = 8;
|
||||||
|
|
||||||
|
pub fn packet_type(&self) -> u8 {
|
||||||
|
self.payload[0]
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn from_full(bytes: &[u8]) -> Result<Self> {
|
pub(crate) fn from_full(bytes: &[u8]) -> Result<Self> {
|
||||||
let Some(padding_length) = bytes.first() else {
|
let Some(padding_length) = bytes.first() else {
|
||||||
return Err(client_error!("empty packet"));
|
return Err(client_error!("empty packet"));
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,12 @@ ctors! {
|
||||||
fn new_msg_request_failure(SSH_MSG_REQUEST_FAILURE;);
|
fn new_msg_request_failure(SSH_MSG_REQUEST_FAILURE;);
|
||||||
|
|
||||||
// 90 to 127 Channel related messages
|
// 90 to 127 Channel related messages
|
||||||
|
fn new_msg_channel_open_session(SSH_MSG_CHANNEL_OPEN;
|
||||||
|
session: string,
|
||||||
|
sender_channel: u32,
|
||||||
|
initial_window_size: u32,
|
||||||
|
maximum_packet_size: u32,
|
||||||
|
);
|
||||||
fn new_msg_channel_open_confirmation(SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
|
fn new_msg_channel_open_confirmation(SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
|
||||||
peer_channel: u32,
|
peer_channel: u32,
|
||||||
sender_channel: u32,
|
sender_channel: u32,
|
||||||
|
|
@ -96,6 +102,22 @@ ctors! {
|
||||||
fn new_msg_channel_eof(SSH_MSG_CHANNEL_EOF; recipient_channel: u32);
|
fn new_msg_channel_eof(SSH_MSG_CHANNEL_EOF; recipient_channel: u32);
|
||||||
fn new_msg_channel_close(SSH_MSG_CHANNEL_CLOSE; recipient_channel: u32);
|
fn new_msg_channel_close(SSH_MSG_CHANNEL_CLOSE; recipient_channel: u32);
|
||||||
|
|
||||||
|
fn new_msg_channel_request_pty_req(SSH_MSG_CHANNEL_REQUEST;
|
||||||
|
recipient_channel: u32,
|
||||||
|
kind_pty_req: string,
|
||||||
|
want_reply: bool,
|
||||||
|
term: string,
|
||||||
|
term_width_char: u32,
|
||||||
|
term_height_rows: u32,
|
||||||
|
term_width_px: u32,
|
||||||
|
term_height_px: u32,
|
||||||
|
term_modes: string,
|
||||||
|
);
|
||||||
|
fn new_msg_channel_request_shell(SSH_MSG_CHANNEL_REQUEST;
|
||||||
|
recipient_channel: u32,
|
||||||
|
kind_shell: string,
|
||||||
|
want_reply: bool,
|
||||||
|
);
|
||||||
fn new_msg_channel_request_exit_status(SSH_MSG_CHANNEL_REQUEST; recipient_channel: u32, kind_exit_status: string, false_: bool, exit_status: u32);
|
fn new_msg_channel_request_exit_status(SSH_MSG_CHANNEL_REQUEST; recipient_channel: u32, kind_exit_status: string, false_: bool, exit_status: u32);
|
||||||
|
|
||||||
fn new_msg_channel_success(SSH_MSG_CHANNEL_SUCCESS; recipient_channel: u32);
|
fn new_msg_channel_success(SSH_MSG_CHANNEL_SUCCESS; recipient_channel: u32);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue