116 lines
3.9 KiB
Rust
116 lines
3.9 KiB
Rust
pub mod data;
|
|
pub mod header;
|
|
pub mod types;
|
|
|
|
use crate::constants::SSH_FXP_INIT;
|
|
use crate::constants::SSH_FXP_REALPATH;
|
|
use crate::constants::SSH_FXP_VERSION;
|
|
use crate::constants::SSH_FXP_NAME;
|
|
|
|
use std::io::{BufReader, BufWriter, Read, Write};
|
|
use std::process::exit;
|
|
|
|
pub fn dispatch_packet(packet: Packet) {
|
|
let mut buff_stdout = BufWriter::new(std::io::stdout());
|
|
let mut response: Packet = match packet.packet_header.type_packet {
|
|
SSH_FXP_INIT => dispatch_version_request(packet),
|
|
SSH_FXP_REALPATH => dispatch_realpath_request(packet),
|
|
_ => panic!("{} not implemented.", packet.packet_header.type_packet),
|
|
};
|
|
let serialized_response = response.serialize();
|
|
eprintln!("Writing response.");
|
|
eprintln!("{:#?}", &serialized_response);
|
|
buff_stdout
|
|
.write(&serialized_response)
|
|
.expect("Unable to write to stdout.");
|
|
buff_stdout.flush().expect("Unable to flush stdout.");
|
|
}
|
|
|
|
fn dispatch_realpath_request(packet: Packet) -> Packet {
|
|
let realpath_packet_data: data::realpath::RealpathData =
|
|
data::realpath::RealpathData::deserialize(&packet.data);
|
|
let path = crate::sftp::realpath(&realpath_packet_data.path);
|
|
let id = realpath_packet_data.id;
|
|
Packet {
|
|
packet_header: header::PacketHeader {
|
|
length: 0,
|
|
type_packet: SSH_FXP_NAME,
|
|
},
|
|
data: crate::packet::data::name::NameData::new(id, &[path]).serialize(),
|
|
}
|
|
}
|
|
|
|
fn dispatch_version_request(packet: Packet) -> Packet {
|
|
let init_packet_data: data::version::VersionData =
|
|
match data::version::VersionData::deserialize(&packet.data) {
|
|
Ok(ok) => ok,
|
|
Err(err) => panic!(err),
|
|
};
|
|
eprintln!("The client version is {}.", init_packet_data.version);
|
|
if init_packet_data.version < 3 {
|
|
panic!("Unsupported version, minimal client version 3.");
|
|
}
|
|
let version_packet_data = data::version::VersionData {
|
|
version: 3,
|
|
extension_data: Vec::new(),
|
|
};
|
|
Packet {
|
|
packet_header: header::PacketHeader {
|
|
length: 0,
|
|
type_packet: SSH_FXP_VERSION,
|
|
},
|
|
data: version_packet_data.serialize(),
|
|
}
|
|
}
|
|
|
|
pub struct Packet {
|
|
pub packet_header: header::PacketHeader,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
impl Packet {
|
|
pub fn read_packet() -> Packet {
|
|
let mut packet_header: [u8; 5] = [0; 5];
|
|
let mut buff_stdin = BufReader::new(std::io::stdin());
|
|
match buff_stdin.read(&mut packet_header) {
|
|
Ok(ok) => ok,
|
|
Err(err) => panic!("Could not fetch packet: {}", err),
|
|
};
|
|
eprintln!("{:#?}", packet_header);
|
|
let packet_header: header::PacketHeader = header::PacketHeader::deserialize(&packet_header);
|
|
eprintln!(
|
|
"Packet length {} and type {}.",
|
|
packet_header.length, packet_header.type_packet
|
|
);
|
|
let mut data: Vec<u8> = Vec::new();
|
|
if packet_header.length == 0 {
|
|
exit(0);
|
|
}
|
|
if packet_header.length as usize - 1 > 34000 {
|
|
panic!(
|
|
"This packet is bigger than supported {}, refusing to allocate memory to handle that.", packet_header.length
|
|
);
|
|
}
|
|
data.resize(packet_header.length as usize - 1, 10);
|
|
match buff_stdin.read(&mut data) {
|
|
Ok(ok) => ok,
|
|
Err(err) => panic!("Could not fetch data: {}", err),
|
|
};
|
|
eprintln!("{:#?}", data);
|
|
Packet::deserialize(packet_header, &data)
|
|
}
|
|
pub fn deserialize(packet_header: header::PacketHeader, data: &[u8]) -> Packet {
|
|
Packet {
|
|
packet_header: packet_header,
|
|
data: data.to_vec(),
|
|
}
|
|
}
|
|
pub fn serialize(&mut self) -> Vec<u8> {
|
|
self.packet_header.length = (self.data.len() + 1) as u32;
|
|
let mut return_bytes = Vec::new();
|
|
return_bytes.extend(&self.packet_header.serialize());
|
|
return_bytes.extend(&self.data);
|
|
return_bytes
|
|
}
|
|
}
|