Initial commit.
This commit is contained in:
parent
a4e28bad1a
commit
53ddf776b3
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "fake_sftp"
|
||||
version = "0.1.0"
|
||||
authors = ["sergiotarxz <sergiotarxz@posteo.net>"]
|
||||
edition = "2018"
|
||||
include = [ "lib/**/*.php" ]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.3.1"
|
||||
serde = { version = "1.0.63", features = [ "derive" ] }
|
184
src/main.rs
Normal file
184
src/main.rs
Normal file
@ -0,0 +1,184 @@
|
||||
use std::convert::TryInto;
|
||||
use std::io::{stdin, BufReader, BufWriter, Read, Write};
|
||||
use std::process::Command;
|
||||
use std::vec::Vec;
|
||||
|
||||
const SSH_FXP_INIT: u8 = 1;
|
||||
const SSH_FXP_VERSION: u8 = 2;
|
||||
const SSH_FXP_OPEN: u8 = 3;
|
||||
const SSH_FXP_CLOSE: u8 = 4;
|
||||
const SSH_FXP_READ: u8 = 5;
|
||||
const SSH_FXP_WRITE: u8 = 6;
|
||||
const SSH_FXP_LSTAT: u8 = 7;
|
||||
const SSH_FXP_FSTAT: u8 = 8;
|
||||
const SSH_FXP_SETSTAT: u8 = 9;
|
||||
const SSH_FXP_FSETSTAT: u8 = 10;
|
||||
const SSH_FXP_OPENDIR: u8 = 11;
|
||||
const SSH_FXP_READDIR: u8 = 12;
|
||||
const SSH_FXP_REMOVE: u8 = 13;
|
||||
const SSH_FXP_MKDIR: u8 = 14;
|
||||
const SSH_FXP_RMDIR: u8 = 15;
|
||||
const SSH_FXP_REALPATH: u8 = 16;
|
||||
const SSH_FXP_STAT: u8 = 17;
|
||||
const SSH_FXP_RENAME: u8 = 18;
|
||||
const SSH_FXP_READLINK: u8 = 19;
|
||||
const SSH_FXP_SYMLINK: u8 = 20;
|
||||
const SSH_FXP_STATUS: u8 = 101;
|
||||
const SSH_FXP_HANDLE: u8 = 102;
|
||||
const SSH_FXP_DATA: u8 = 103;
|
||||
const SSH_FXP_NAME: u8 = 104;
|
||||
const SSH_FXP_ATTRS: u8 = 105;
|
||||
const SSH_FXP_EXTENDED: u8 = 200;
|
||||
const SSH_FXP_EXTENDED_REPLY: u8 = 201;
|
||||
const NEXTCLOUD_PATH: &str = "/var/www/nextcloud.sergiotarxz.freemyip.com/htdocs/";
|
||||
|
||||
fn main() {
|
||||
eprintln!("{}", execute_php("echo \"hola rusty mundo\";"));
|
||||
loop {
|
||||
let packet = Packet::read_packet();
|
||||
dispatch_packet(packet)
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_php(command: &str) -> String {
|
||||
let output = Command::new("php")
|
||||
.args(&["-r", command])
|
||||
.output()
|
||||
.expect("");
|
||||
let mut buff_stderr = BufWriter::new(std::io::stderr());
|
||||
buff_stderr.write(&output.stderr);
|
||||
buff_stderr.flush();
|
||||
return String::from_utf8(output.stdout).expect("Unable to parse php response");
|
||||
}
|
||||
|
||||
fn dispatch_packet(packet: Packet) {
|
||||
let mut buff_stdout = BufWriter::new(std::io::stdout());
|
||||
if packet.packet_header.type_packet == SSH_FXP_INIT {
|
||||
let init_packet_data: VersionPacketData = match VersionPacketData::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 = VersionPacketData {
|
||||
version: 3,
|
||||
extension_data: Vec::new(),
|
||||
};
|
||||
let mut response_packet = Packet {
|
||||
packet_header: PacketHeader {
|
||||
length: 0,
|
||||
type_packet: SSH_FXP_VERSION,
|
||||
},
|
||||
data: version_packet_data.serialize(),
|
||||
};
|
||||
let serialized_response = response_packet.serialize();
|
||||
eprintln!("{:#?}", serialized_response);
|
||||
buff_stdout.write(&serialized_response);
|
||||
buff_stdout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
impl VersionPacketData {
|
||||
fn deserialize(x: &[u8]) -> Result<VersionPacketData, std::string::String> {
|
||||
if x.len() < 4 {
|
||||
return Err("Error parsing version from init packet header.".to_string());
|
||||
} else {
|
||||
let mut u32_byte_array: [u8; 4] = [0; 4];
|
||||
let mut extension_data = Vec::new();
|
||||
u32_byte_array.copy_from_slice(&x[0..4]);
|
||||
if x.len() > 4 {
|
||||
extension_data.extend(&x[4..]);
|
||||
}
|
||||
return Ok(VersionPacketData {
|
||||
version: u32::from_be_bytes(u32_byte_array),
|
||||
extension_data: extension_data,
|
||||
});
|
||||
}
|
||||
}
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
let mut return_bytes = Vec::new();
|
||||
let u32_byte_array: [u8; 4] = self.version.to_be_bytes();
|
||||
return_bytes.extend(&u32_byte_array);
|
||||
if self.extension_data.len() > 0 {
|
||||
return_bytes.extend(&self.extension_data);
|
||||
}
|
||||
return_bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
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: PacketHeader = PacketHeader::deserialize(&packet_header);
|
||||
eprintln!(
|
||||
"Packet length {} and type {}.",
|
||||
packet_header.length, packet_header.type_packet
|
||||
);
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
data.resize(packet_header.length as usize - 1, 0);
|
||||
match buff_stdin.read(&mut data) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => panic!("Could not fetch data: {}", err),
|
||||
};
|
||||
eprintln!("{:#?}", data);
|
||||
Packet::deserialize(packet_header, data)
|
||||
}
|
||||
fn deserialize(packet_header: PacketHeader, data: Vec<u8>) -> Packet {
|
||||
Packet {
|
||||
packet_header: packet_header,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
struct PacketHeader {
|
||||
length: u32,
|
||||
type_packet: u8,
|
||||
}
|
||||
impl PacketHeader {
|
||||
fn deserialize(x: &[u8; 5]) -> PacketHeader {
|
||||
let mut u32_byte_array: [u8; 4] = [0; 4];
|
||||
u32_byte_array.copy_from_slice(&x[0..4]);
|
||||
PacketHeader {
|
||||
length: u32::from_be_bytes(u32_byte_array),
|
||||
type_packet: x[4],
|
||||
}
|
||||
}
|
||||
fn serialize(&self) -> [u8; 5] {
|
||||
let serializated_data: [u8; 5] = [0; 5];
|
||||
let length = self.length.to_be_bytes();
|
||||
let type_packet = self.type_packet;
|
||||
let mut return_bytes = length.to_vec();
|
||||
return_bytes.extend(&[type_packet][..]);
|
||||
let boxed_return_bytes: Box<[u8; 5]> = return_bytes
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.expect("Unable to serialize.");
|
||||
*boxed_return_bytes
|
||||
}
|
||||
}
|
||||
|
||||
struct Packet {
|
||||
packet_header: PacketHeader,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
struct VersionPacketData {
|
||||
version: u32,
|
||||
extension_data: Vec<u8>,
|
||||
}
|
Loading…
Reference in New Issue
Block a user