Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions smb-core/src/nt_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ pub enum NTStatus {
UserSessionDeleted = 0xC0000203,
NetworkSessionExpired = 0xC000035C,
FileNotAvailable = 0xC0000467,
FileClosed = 0xC0000128,
EndOfFile = 0xC0000011,
InvalidInfoClass = 0xC0000003,
InvalidDeviceRequest = 0xC0000010,
UnknownError = 0xFFFFFFFF,
}

Expand Down
2 changes: 1 addition & 1 deletion smb/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async fn main() -> SMBResult<()> {
.unencrypted_access(true)
.require_message_signing(false)
.encrypt_data(false)
.add_fs_share("test".into(), "".into(), file_allowed, get_file_perms)
.add_fs_share("test".into(), std::env::var("SMB_SHARE_PATH").unwrap_or_default(), file_allowed, get_file_perms)
.add_ipc_share()
.auth_provider(NTLMAuthProvider::new(vec![
User::new("tejasmehta", "password"),
Expand Down
124 changes: 123 additions & 1 deletion smb/src/protocol/body/close/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::protocol::body::create::file_attributes::SMBFileAttributes;
use crate::protocol::body::create::file_id::SMBFileId;
use crate::protocol::body::filetime::FileTime;

mod flags;
pub mod flags;

#[derive(
Debug,
Expand All @@ -32,6 +32,16 @@ pub struct SMBCloseRequest {
file_id: SMBFileId,
}

impl SMBCloseRequest {
pub fn flags(&self) -> SMBCloseFlags {
self.flags
}

pub fn file_id(&self) -> &SMBFileId {
&self.file_id
}
}

#[derive(
Debug,
PartialEq,
Expand Down Expand Up @@ -63,4 +73,116 @@ pub struct SMBCloseResponse {
end_of_file: u64,
#[smb_direct(start(fixed = 56))]
file_attributes: SMBFileAttributes,
}

impl SMBCloseResponse {
pub fn from_metadata(metadata: &crate::server::share::SMBFileMetadata, attributes: SMBFileAttributes) -> Self {
Self {
flags: SMBCloseFlags::POSTQUERY_ATTRIB,
reserved: PhantomData,
creation_time: metadata.creation_time.clone(),
last_access_time: metadata.last_access_time.clone(),
last_write_time: metadata.last_write_time.clone(),
change_time: metadata.last_modification_time.clone(),
allocation_size: metadata.allocated_size,
end_of_file: metadata.actual_size,
file_attributes: attributes,
}
}

pub fn empty() -> Self {
Self {
flags: SMBCloseFlags::empty(),
reserved: PhantomData,
creation_time: FileTime::zero(),
last_access_time: FileTime::zero(),
last_write_time: FileTime::zero(),
change_time: FileTime::zero(),
allocation_size: 0,
end_of_file: 0,
file_attributes: SMBFileAttributes::empty(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use smb_core::{SMBByteSize, SMBToBytes, SMBFromBytes};

#[test]
fn close_response_empty_has_zero_fields() {
let resp = SMBCloseResponse::empty();
assert_eq!(resp.flags, SMBCloseFlags::empty());
assert_eq!(resp.allocation_size, 0);
assert_eq!(resp.end_of_file, 0);
assert_eq!(resp.file_attributes, SMBFileAttributes::empty());
}

#[test]
fn close_response_empty_serialization_round_trip() {
let resp = SMBCloseResponse::empty();
let bytes = resp.smb_to_bytes();
assert_eq!(bytes.len(), resp.smb_byte_size());
let (_, parsed) = SMBCloseResponse::smb_from_bytes(&bytes).unwrap();
assert_eq!(resp, parsed);
}

#[test]
fn close_response_from_metadata_sets_postquery_flag() {
use crate::server::share::SMBFileMetadata;
let metadata = SMBFileMetadata {
creation_time: FileTime::from_unix(1700000000),
last_access_time: FileTime::from_unix(1700000100),
last_write_time: FileTime::from_unix(1700000200),
last_modification_time: FileTime::from_unix(1700000300),
allocated_size: 4096,
actual_size: 1024,
};
let resp = SMBCloseResponse::from_metadata(&metadata, SMBFileAttributes::NORMAL);
assert!(resp.flags.contains(SMBCloseFlags::POSTQUERY_ATTRIB));
assert_eq!(resp.allocation_size, 4096);
assert_eq!(resp.end_of_file, 1024);
assert_eq!(resp.file_attributes, SMBFileAttributes::NORMAL);
}

#[test]
fn close_response_from_metadata_serialization_round_trip() {
use crate::server::share::SMBFileMetadata;
let metadata = SMBFileMetadata {
creation_time: FileTime::from_unix(1700000000),
last_access_time: FileTime::from_unix(1700000100),
last_write_time: FileTime::from_unix(1700000200),
last_modification_time: FileTime::from_unix(1700000300),
allocated_size: 8192,
actual_size: 2048,
};
let resp = SMBCloseResponse::from_metadata(&metadata, SMBFileAttributes::ARCHIVE);
let bytes = resp.smb_to_bytes();
assert_eq!(bytes.len(), resp.smb_byte_size());
let (_, parsed) = SMBCloseResponse::smb_from_bytes(&bytes).unwrap();
assert_eq!(resp, parsed);
}

#[test]
fn close_request_accessors() {
let file_id = SMBFileId { persistent: 42, volatile: 99 };
let bytes = {
let mut buf = Vec::new();
// struct_size (u16) = 24
buf.extend_from_slice(&24u16.to_le_bytes());
// flags (u16) = POSTQUERY_ATTRIB = 0x0001
buf.extend_from_slice(&1u16.to_le_bytes());
// reserved (4 bytes)
buf.extend_from_slice(&[0u8; 4]);
// file_id: persistent (u64) + volatile (u64)
buf.extend_from_slice(&42u64.to_le_bytes());
buf.extend_from_slice(&99u64.to_le_bytes());
buf
};
let (_, req) = SMBCloseRequest::smb_from_bytes(&bytes).unwrap();
assert_eq!(req.file_id().persistent, file_id.persistent);
assert_eq!(req.file_id().volatile, file_id.volatile);
assert!(req.flags().contains(SMBCloseFlags::POSTQUERY_ATTRIB));
}
}
2 changes: 1 addition & 1 deletion smb/src/protocol/body/create/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub struct SMBCreateRequest {
create_disposition: SMBCreateDisposition,
#[smb_direct(start(fixed = 40))]
create_options: SMBCreateOptions,
#[smb_string(order = 0, start(inner(start = 44, num_type = "u16", subtract = 68)), length(inner(start = 46, num_type = "u16")), underlying = "u16")]
#[smb_string(order = 0, start(inner(start = 44, num_type = "u16", subtract = 64)), length(inner(start = 46, num_type = "u16")), underlying = "u16")]
file_name: String,
#[smb_vector(order = 1, align = 8, length(inner(start = 52, num_type = "u32")), offset(inner(start = 48, num_type = "u32", subtract = 64)))]
contexts: Vec<CreateRequestContext>,
Expand Down
10 changes: 10 additions & 0 deletions smb/src/protocol/body/file_info/access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use serde::{Deserialize, Serialize};

use smb_derive::{SMBByteSize, SMBFromBytes, SMBToBytes};

/// FILE_ACCESS_INFORMATION (MS-FSCC 2.4.1) — 4 bytes
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, SMBByteSize, SMBFromBytes, SMBToBytes)]
pub struct FileAccessInformation {
#[smb_direct(start(fixed = 0))]
pub access_flags: u32,
}
10 changes: 10 additions & 0 deletions smb/src/protocol/body/file_info/alignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use serde::{Deserialize, Serialize};

use smb_derive::{SMBByteSize, SMBFromBytes, SMBToBytes};

/// FILE_ALIGNMENT_INFORMATION (MS-FSCC 2.4.3) — 4 bytes
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, SMBByteSize, SMBFromBytes, SMBToBytes)]
pub struct FileAlignmentInformation {
#[smb_direct(start(fixed = 0))]
pub alignment_requirement: u32,
}
23 changes: 23 additions & 0 deletions smb/src/protocol/body/file_info/basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use serde::{Deserialize, Serialize};

use smb_derive::{SMBByteSize, SMBFromBytes, SMBToBytes};

use crate::protocol::body::create::file_attributes::SMBFileAttributes;
use crate::protocol::body::filetime::FileTime;

/// FILE_BASIC_INFORMATION (MS-FSCC 2.4.7) — 40 bytes
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, SMBByteSize, SMBFromBytes, SMBToBytes)]
pub struct FileBasicInformation {
#[smb_direct(start(fixed = 0))]
pub creation_time: FileTime,
#[smb_direct(start(fixed = 8))]
pub last_access_time: FileTime,
#[smb_direct(start(fixed = 16))]
pub last_write_time: FileTime,
#[smb_direct(start(fixed = 24))]
pub change_time: FileTime,
#[smb_direct(start(fixed = 32))]
pub file_attributes: SMBFileAttributes,
#[smb_direct(start(fixed = 36))]
pub reserved: u32,
}
10 changes: 10 additions & 0 deletions smb/src/protocol/body/file_info/ea.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use serde::{Deserialize, Serialize};

use smb_derive::{SMBByteSize, SMBFromBytes, SMBToBytes};

/// FILE_EA_INFORMATION (MS-FSCC 2.4.12) — 4 bytes
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, SMBByteSize, SMBFromBytes, SMBToBytes)]
pub struct FileEaInformation {
#[smb_direct(start(fixed = 0))]
pub ea_size: u32,
}
10 changes: 10 additions & 0 deletions smb/src/protocol/body/file_info/internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use serde::{Deserialize, Serialize};

use smb_derive::{SMBByteSize, SMBFromBytes, SMBToBytes};

/// FILE_INTERNAL_INFORMATION (MS-FSCC 2.4.20) — 8 bytes
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, SMBByteSize, SMBFromBytes, SMBToBytes)]
pub struct FileInternalInformation {
#[smb_direct(start(fixed = 0))]
pub index_number: u64,
}
Loading
Loading