Skip to content

Commit 023b489

Browse files
authored
Merge pull request #297 from zeroSteiner/feat/smb1/symlink
Add #set_unix_link to the SMB1 tree
2 parents 08439d5 + 81aff03 commit 023b489

17 files changed

Lines changed: 893 additions & 5 deletions

lib/ruby_smb/smb1/packet/trans2.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ module Trans2
77
require 'ruby_smb/smb1/packet/trans2/find_information_level'
88
require 'ruby_smb/smb1/packet/trans2/query_information_level'
99
require 'ruby_smb/smb1/packet/trans2/query_fs_information_level'
10+
require 'ruby_smb/smb1/packet/trans2/set_information_level'
11+
require 'ruby_smb/smb1/packet/trans2/set_fs_information_level'
1012
require 'ruby_smb/smb1/packet/trans2/data_block'
1113
require 'ruby_smb/smb1/packet/trans2/win9x_framing'
1214
require 'ruby_smb/smb1/packet/trans2/subcommands'
@@ -23,6 +25,12 @@ module Trans2
2325
require 'ruby_smb/smb1/packet/trans2/set_file_information_response'
2426
require 'ruby_smb/smb1/packet/trans2/query_path_information_request'
2527
require 'ruby_smb/smb1/packet/trans2/query_path_information_response'
28+
require 'ruby_smb/smb1/packet/trans2/set_path_information_request'
29+
require 'ruby_smb/smb1/packet/trans2/set_path_information_response'
30+
require 'ruby_smb/smb1/packet/trans2/query_fs_information_request'
31+
require 'ruby_smb/smb1/packet/trans2/query_fs_information_response'
32+
require 'ruby_smb/smb1/packet/trans2/set_fs_information_request'
33+
require 'ruby_smb/smb1/packet/trans2/set_fs_information_response'
2634
end
2735
end
2836
end

lib/ruby_smb/smb1/packet/trans2/query_fs_information_level.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ module QueryFsInformationLevel
2828
# [NT LANMAN] Query file system attributes.
2929
SMB_QUERY_FS_ATTRIBUTE_INFO = 0x0105 # 261
3030

31+
# [CIFS UNIX Extensions] Query server UNIX extension capabilities.
32+
SMB_QUERY_CIFS_UNIX_INFO = 0x0200 # 512
33+
3134
def self.name(value)
3235
constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
3336
end
3437

3538
require 'ruby_smb/smb1/packet/trans2/query_fs_information_level/query_fs_attribute_info'
39+
require 'ruby_smb/smb1/packet/trans2/query_fs_information_level/query_fs_cifs_unix_info'
3640
end
3741
end
3842
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module RubySMB
2+
module SMB1
3+
module Packet
4+
module Trans2
5+
module QueryFsInformationLevel
6+
# Response data for SMB_QUERY_CIFS_UNIX_INFO (0x0200) from the
7+
# CIFS UNIX Extensions. 12 bytes: major/minor version pair plus
8+
# a 64-bit capability bitfield that the client echoes back in
9+
# SMB_SET_CIFS_UNIX_INFO to enable UNIX extensions for the session.
10+
#
11+
# Outside of MS-CIFS; wire format defined by the CIFS UNIX
12+
# Extensions draft maintained by the Samba team. The parent
13+
# subcommand is documented at
14+
# [MS-CIFS 2.2.6.4 TRANS2_QUERY_FS_INFORMATION (0x0003)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/a96c1c03-cade-4a4a-81a9-b00674d23d93).
15+
# The on-disk layout matches Samba's server-side `unix_info`
16+
# struct at
17+
# [source3/smbd/globals.h:419-424](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/globals.h#L419-L424),
18+
# populated by `call_trans2qfsinfo` at
19+
# [source3/smbd/smb1_trans2.c:1633-1703](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1633-L1703).
20+
class QueryFsCifsUnixInfo < BinData::Record
21+
endian :little
22+
23+
uint16 :major_version, label: 'Major Version'
24+
uint16 :minor_version, label: 'Minor Version'
25+
uint64 :capabilities, label: 'Capabilities'
26+
end
27+
end
28+
end
29+
end
30+
end
31+
end

lib/ruby_smb/smb1/packet/trans2/query_fs_information_request.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ module RubySMB
22
module SMB1
33
module Packet
44
module Trans2
5-
# The Trans2 Parameter Block for this particular Subcommand
5+
# The Trans2 Parameter Block for a QUERY_FS_INFORMATION request as
6+
# defined in
7+
# [MS-CIFS 2.2.6.4.1 Request](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/cfa23a11-0e80-43bd-bbd4-e9cfb99b5dce).
68
class QueryFsInformationRequestTrans2Parameters < BinData::Record
79
endian :little
810

@@ -15,16 +17,22 @@ def length
1517
end
1618
end
1719

18-
# The {RubySMB::SMB1::DataBlock} specific to this packet type.
20+
# The {RubySMB::SMB1::DataBlock} specific to this packet type. See
21+
# [MS-CIFS 2.2.6.4.1 Request](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/cfa23a11-0e80-43bd-bbd4-e9cfb99b5dce).
22+
# The request carries no Trans2 data payload, but the generic
23+
# DataBlock padding helpers require a :trans2_data accessor, so
24+
# we expose a zero-length string.
1925
class QueryFsInformationRequestDataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
2026
uint8 :name, label: 'Name', initial_value: 0x00
2127
string :pad1, length: -> { pad1_length }
2228
query_fs_information_request_trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
23-
# trans2_data: No data is sent by this message.
29+
string :trans2_data, length: 0, label: 'Trans2 Data'
2430
end
2531

2632
# A Trans2 QUERY_FS_INFORMATION Request Packet as defined in
27-
# [2.2.6.4.1](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/cfa23a11-0e80-43bd-bbd4-e9cfb99b5dce)
33+
# [MS-CIFS 2.2.6.4.1 Request](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/cfa23a11-0e80-43bd-bbd4-e9cfb99b5dce).
34+
# See also the subcommand overview at
35+
# [MS-CIFS 2.2.6.4 TRANS2_QUERY_FS_INFORMATION (0x0003)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/a96c1c03-cade-4a4a-81a9-b00674d23d93).
2836
class QueryFsInformationRequest < RubySMB::GenericPacket
2937
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
3038

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module RubySMB
2+
module SMB1
3+
module Packet
4+
module Trans2
5+
# SET_FS Information Levels used in TRANS2_SET_FS_INFORMATION.
6+
#
7+
# MS-CIFS marks the parent subcommand
8+
# [TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
9+
# as "reserved but not implemented" — the info level codes below are
10+
# defined by the CIFS UNIX Extensions draft maintained by the Samba
11+
# team and implemented in
12+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
13+
# They sit in the 0x0200–0x02FF range reserved by
14+
# [MS-CIFS 2.2.2.3 Information Level Codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/03c10ab9-d723-4368-b9a6-c72de3244c77)
15+
# for third-party extensions.
16+
module SetFsInformationLevel
17+
# Client advertises / negotiates CIFS UNIX Extensions support.
18+
# Data block: major:u16, minor:u16, capabilities:u64.
19+
SMB_SET_CIFS_UNIX_INFO = 0x0200
20+
21+
def self.name(value)
22+
constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
23+
end
24+
end
25+
end
26+
end
27+
end
28+
end
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
module RubySMB
2+
module SMB1
3+
module Packet
4+
module Trans2
5+
# The Trans2 Parameter Block for TRANS2_SET_FS_INFORMATION.
6+
# Observed on the wire (and required by Samba) as a 4-byte block
7+
# containing a placeholder file handle plus the information level.
8+
#
9+
# The parent subcommand
10+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
11+
# is marked "reserved but not implemented"; the on-the-wire format
12+
# used here is defined by the CIFS UNIX Extensions draft and
13+
# implemented in
14+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
15+
class SetFsInformationRequestTrans2Parameters < BinData::Record
16+
endian :little
17+
18+
uint16 :fid, label: 'File ID'
19+
uint16 :information_level, label: 'Information Level'
20+
21+
# Returns the length of the Trans2Parameters struct
22+
# in number of bytes
23+
def length
24+
do_num_bytes
25+
end
26+
end
27+
28+
# The Trans2 Data Block for TRANS2_SET_FS_INFORMATION.
29+
#
30+
# The data layout depends on the Information Level being set, so the
31+
# block carries an opaque byte buffer that the caller fills in for
32+
# the target info level. SMB_SET_CIFS_UNIX_INFO (0x0200) for example
33+
# carries a QueryFsCifsUnixInfo-shaped record (major/minor/caps).
34+
#
35+
# Not documented in
36+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3);
37+
# per-level layouts are defined by the CIFS UNIX Extensions draft
38+
# and implemented in
39+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
40+
class SetFsInformationRequestTrans2Data < BinData::Record
41+
string :buffer, read_length: -> { parent.buffer_read_length }
42+
43+
# Returns the length of the Trans2Data struct
44+
# in number of bytes
45+
def length
46+
do_num_bytes
47+
end
48+
end
49+
50+
# The {RubySMB::SMB1::DataBlock} specific to this packet type. The
51+
# parent subcommand
52+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
53+
# is documented as "reserved but not implemented"; this data block
54+
# is structured for the CIFS UNIX Extensions use in
55+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
56+
class SetFsInformationRequestDataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
57+
uint8 :name, label: 'Name', initial_value: 0x00
58+
string :pad1, length: -> { pad1_length }
59+
set_fs_information_request_trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
60+
string :pad2, length: -> { pad2_length }
61+
set_fs_information_request_trans2_data :trans2_data, label: 'Trans2 Data'
62+
end
63+
64+
# A Trans2 SET_FS_INFORMATION Request Packet. The on-disk layout
65+
# described by
66+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
67+
# is marked "reserved but not implemented" and does not document the
68+
# CIFS UNIX Extensions info levels; their wire format is defined by
69+
# the CIFS UNIX Extensions draft and matched by Samba's
70+
# `call_trans2setfsinfo` in
71+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
72+
class SetFsInformationRequest < RubySMB::GenericPacket
73+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
74+
75+
class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
76+
end
77+
78+
smb_header :smb_header
79+
parameter_block :parameter_block
80+
set_fs_information_request_data_block :data_block
81+
82+
def initialize_instance
83+
super
84+
parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::SET_FS_INFORMATION
85+
end
86+
end
87+
end
88+
end
89+
end
90+
end
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
module RubySMB
2+
module SMB1
3+
module Packet
4+
module Trans2
5+
# The Trans2 Parameter Block for a TRANS2_SET_FS_INFORMATION response.
6+
# The field is intentionally empty — servers return only an NT status
7+
# in the SMB header to acknowledge the SET.
8+
#
9+
# Parent subcommand:
10+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
11+
# ("reserved but not implemented"). Response shape observed in the
12+
# CIFS UNIX Extensions implementation in
13+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
14+
class SetFsInformationResponseTrans2Parameters < BinData::Record
15+
def length
16+
do_num_bytes
17+
end
18+
end
19+
20+
# The {RubySMB::SMB1::DataBlock} specific to this packet type.
21+
# Parent subcommand:
22+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
23+
# ("reserved but not implemented"); actual shape used by the CIFS
24+
# UNIX Extensions implementation in
25+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
26+
class SetFsInformationResponseDataBlock < RubySMB::SMB1::Packet::Trans2::DataBlock
27+
uint8 :name, label: 'Name', initial_value: 0x00
28+
string :pad1, length: -> { pad1_length }
29+
set_fs_information_response_trans2_parameters :trans2_parameters, label: 'Trans2 Parameters'
30+
end
31+
32+
# A Trans2 SET_FS_INFORMATION Response Packet. Parent subcommand:
33+
# [MS-CIFS 2.2.6.5 TRANS2_SET_FS_INFORMATION (0x0004)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/ac4b00db-6015-416a-89a1-bf5da2503bc3)
34+
# ("reserved but not implemented"). Response shape is defined by the
35+
# CIFS UNIX Extensions implementation in
36+
# [source3/smbd/smb1_trans2.c:1706-1915 (`call_trans2setfsinfo`)](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L1706-L1915).
37+
class SetFsInformationResponse < RubySMB::GenericPacket
38+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
39+
40+
class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Response::ParameterBlock
41+
end
42+
43+
smb_header :smb_header
44+
parameter_block :parameter_block
45+
set_fs_information_response_data_block :data_block
46+
47+
def initialize_instance
48+
super
49+
parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::SET_FS_INFORMATION
50+
smb_header.flags.reply = 1
51+
end
52+
end
53+
end
54+
end
55+
end
56+
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module RubySMB
2+
module SMB1
3+
module Packet
4+
module Trans2
5+
# Information Level codes valid for Trans2 SET_PATH_INFORMATION and
6+
# SET_FILE_INFORMATION requests. See
7+
# [MS-CIFS 2.2.2.3.4 SET Information Level Codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/0321265e-312a-4721-90fa-cd40a443ed86).
8+
#
9+
# FSCC pass-through levels are defined in
10+
# {RubySMB::Fscc::FileInformation} and require
11+
# `SMB_INFO_PASSTHROUGH` to be added. The constants defined here are
12+
# the CIFS UNIX Extensions info levels used by Samba servers that
13+
# advertise UNIX extensions support in their negotiate response. These
14+
# levels fall outside MS-CIFS; their wire format is defined by the
15+
# CIFS UNIX Extensions draft and implemented by Samba's
16+
# `smb_set_file_unix_link` handler at
17+
# [source3/smbd/smb1_trans2.c:3643-3712](https://github.com/samba-team/samba/blob/33f516c06756e12a9d11f50e2bf309171cdf5c88/source3/smbd/smb1_trans2.c#L3643-L3712).
18+
module SetInformationLevel
19+
# Set the symbolic link target for a file. The Trans2 parameters
20+
# block carries the path being created (the symlink itself); the
21+
# Trans2 data block carries the target path as a null-terminated
22+
# string.
23+
SMB_SET_FILE_UNIX_LINK = 0x0201
24+
25+
# Create a hard link. Data block carries the existing file path.
26+
SMB_SET_FILE_UNIX_HLINK = 0x0203
27+
28+
def self.name(value)
29+
constants.select { |c| c.upcase == c }.find { |c| const_get(c) == value }
30+
end
31+
end
32+
end
33+
end
34+
end
35+
end

0 commit comments

Comments
 (0)