From 2fbb100514eab535ae8ed0b83313bac0c5664c13 Mon Sep 17 00:00:00 2001 From: Sergiotarxz Date: Fri, 13 Nov 2020 20:01:31 +0100 Subject: [PATCH] fix: Implementing support for stat directories. --- src/constants.rs | 33 ++++++++++++++++++++++++++++++++- src/packet/data/attrs.rs | 11 ++++++++--- src/packet/dispatch.rs | 36 +++++++++++++++++++++++------------- 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index ff532ae..9bb534b 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -25,7 +25,7 @@ pub const SSH_FXP_NAME: u8 = 104; pub const SSH_FXP_ATTRS: u8 = 105; pub const SSH_FXP_EXTENDED: u8 = 200; pub const SSH_FXP_EXTENDED_REPLY: u8 = 201; -// Status codes +// Status codes. pub const SSH_FX_OK: u32 = 0; pub const SSH_FX_EOF: u32 = 1; pub const SSH_FX_NO_SUCH_FILE: u32 = 2; @@ -35,3 +35,34 @@ pub const SSH_FX_BAD_MESSAGE: u32 = 5; pub const SSH_FX_NO_CONNECTION: u32 = 6; pub const SSH_FX_CONNECTION_LOST: u32 = 7; pub const SSH_FX_OP_UNSUPPORTED: u32 = 8; +// Attrs. +pub const SSH_FILEXFER_ATTR_SIZE: u32 = 0x1; +pub const SSH_FILEXFER_ATTR_UIDGID: u32 = 0x2; +pub const SSH_FILEXFER_ATTR_PERMISSIONS: u32 = 0x4; +pub const SSH_FILEXFER_ATTR_ACMODTIME: u32 = 0x8; +pub const SSH_FILEXFER_ATTR_EXTENDED: u32 = 0x80000000; +// Mode interpretation. +pub const S_IFIFO: u32 = 0o10000; /* named pipe (fifo) */ +pub const S_IFCHR: u32 = 0o20000; /* character special */ +pub const S_IFDIR: u32 = 0o40000; /* directory */ +pub const S_IFBLK: u32 = 0o60000; /* block special */ +pub const S_IFREG: u32 = 0o100000; /* regular */ +pub const S_IFLNK: u32 = 0o120000; /* symbolic link */ +pub const S_IFSOCK: u32 = 0o140000; /* socket */ +// Permission flags. +pub const S_ISUID: u32 = 0o4000; /* set user id on execution */ +pub const S_ISGID: u32 = 0o2000; /* set group id on execution */ +pub const S_ISTXT: u32 = 0o1000; /* sticky bit */ +pub const S_IRWXU: u32 = 0o700; /* RWX mask for owner */ +pub const S_IRUSR: u32 = 0o400; /* R for owner */ +pub const S_IWUSR: u32 = 0o200; /* W for owner */ +pub const S_IXUSR: u32 = 0o100; /* X for owner */ +pub const S_IRWXG: u32 = 0o70; /* RWX mask for group */ +pub const S_IRGRP: u32 = 0o40; /* R for group */ +pub const S_IWGRP: u32 = 0o20; /* W for group */ +pub const S_IXGRP: u32 = 0o10; /* X for group */ +pub const S_IRWXO: u32 = 0o7; /* RWX mask for other */ +pub const S_IROTH: u32 = 0o4; /* R for other */ +pub const S_IWOTH: u32 = 0o2; /* W for other */ +pub const S_IXOTH: u32 = 0o1; /* X for other */ +pub const S_ISVTX: u32 = 0o1000; /* save swapped text even after use */ diff --git a/src/packet/data/attrs.rs b/src/packet/data/attrs.rs index 0fe761b..7219871 100644 --- a/src/packet/data/attrs.rs +++ b/src/packet/data/attrs.rs @@ -1,18 +1,23 @@ pub struct AttrsData { id: u32, attrs: u32, + permission: u32, } impl AttrsData { - pub fn new(id: u32) -> AttrsData { - let attrs: u32 = 0; - AttrsData { id: id, attrs: attrs } + pub fn new(id: u32, attrs: u32, permission: u32) -> AttrsData { + AttrsData { + id: id, + attrs: attrs, + permission: permission, + } } pub fn serialize(&self) -> Vec { let mut serialized_data: Vec = Vec::new(); serialized_data.extend(&self.id.to_be_bytes()); serialized_data.extend(&self.attrs.to_be_bytes()); + serialized_data.extend(&self.permission.to_be_bytes()); serialized_data } } diff --git a/src/packet/dispatch.rs b/src/packet/dispatch.rs index 16525dc..cf50eeb 100644 --- a/src/packet/dispatch.rs +++ b/src/packet/dispatch.rs @@ -1,27 +1,32 @@ use uuid::Uuid; +use crate::constants::SSH_FILEXFER_ATTR_PERMISSIONS; +use crate::constants::SSH_FXP_ATTRS; use crate::constants::SSH_FXP_HANDLE; use crate::constants::SSH_FXP_INIT; +use crate::constants::SSH_FXP_LSTAT; use crate::constants::SSH_FXP_NAME; use crate::constants::SSH_FXP_OPENDIR; use crate::constants::SSH_FXP_REALPATH; +use crate::constants::SSH_FXP_STAT; use crate::constants::SSH_FXP_STATUS; use crate::constants::SSH_FXP_VERSION; -use crate::constants::SSH_FXP_ATTRS; -use crate::constants::SSH_FXP_STAT; -use crate::constants::SSH_FXP_LSTAT; use crate::constants::SSH_FX_FAILURE; use crate::constants::SSH_FX_NO_SUCH_FILE; use crate::constants::SSH_FX_OP_UNSUPPORTED; +use crate::constants::S_IFDIR; +use crate::constants::S_IFREG; +use crate::constants::S_IRWXU; + use crate::handle::DirectoryHandle; +use crate::packet::data::attrs::AttrsData; use crate::packet::data::handle::HandleData; use crate::packet::data::name::NameData; use crate::packet::data::opendir::OpendirData; use crate::packet::data::realpath::RealpathData; +use crate::packet::data::stat::StatData; use crate::packet::data::status::StatusData; use crate::packet::data::version::VersionData; -use crate::packet::data::attrs::AttrsData; -use crate::packet::data::stat::StatData; use crate::packet::header::PacketHeader; use crate::packet::Packet; use crate::php; @@ -51,13 +56,9 @@ pub fn dispatch_packet( SSH_FXP_REALPATH => dispatch_realpath_request(packet), SSH_FXP_OPENDIR => { dispatch_opendir_request(packet, directory_handles, nextcloud_folder, user) - }, - SSH_FXP_STAT => { - dispatch_stat_request(packet, nextcloud_folder, user) - }, - SSH_FXP_LSTAT => { - dispatch_stat_request(packet, nextcloud_folder, user) - }, + } + SSH_FXP_STAT => dispatch_stat_request(packet, nextcloud_folder, user), + SSH_FXP_LSTAT => dispatch_stat_request(packet, nextcloud_folder, user), _ => { eprintln!("{} not implemented.", packet.packet_header.type_packet); let mut id: [u8; 4] = [0; 4]; @@ -107,12 +108,21 @@ fn dispatch_stat_request(packet: Packet, nextcloud_folder: &str, user: &str) -> .serialize(), } } else { + let mut permission: u32 = 0; + let mut attrs: u32 = 0; + attrs |= SSH_FILEXFER_ATTR_PERMISSIONS; + permission |= S_IRWXU; + if php::check_if_is_dir(&stat_data.path, &user, &nextcloud_folder) { + permission |= S_IFDIR; + } else { + permission |= S_IFREG; + } Packet { packet_header: PacketHeader { length: 0, type_packet: SSH_FXP_ATTRS, }, - data: AttrsData::new(stat_data.id).serialize(), + data: AttrsData::new(stat_data.id, attrs, permission).serialize(), } } }