Initial commit.

This commit is contained in:
sergiotarxz 2020-11-06 15:21:46 +01:00
parent a4e28bad1a
commit 53ddf776b3
3 changed files with 199 additions and 0 deletions

12
Cargo.toml Normal file
View 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" ] }

3
lib/a.php Normal file
View File

@ -0,0 +1,3 @@
<?
echo "hello rust!";
?>

184
src/main.rs Normal file
View 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>,
}