ruby_smb 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/ruby_smb/client.rb +26 -4
- data/lib/ruby_smb/client/authentication.rb +43 -25
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/negotiation.rb +27 -12
- data/lib/ruby_smb/client/tree_connect.rb +20 -14
- data/lib/ruby_smb/error.rb +40 -1
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/dcerpc.rb +7 -2
- data/lib/ruby_smb/smb1/file.rb +60 -11
- data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +7 -0
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +8 -3
- data/lib/ruby_smb/smb1/tree.rb +40 -2
- data/lib/ruby_smb/smb2/dcerpc.rb +7 -2
- data/lib/ruby_smb/smb2/file.rb +97 -1
- data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/error_packet.rb +7 -0
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
- data/lib/ruby_smb/smb2/pipe.rb +9 -9
- data/lib/ruby_smb/smb2/tree.rb +44 -6
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +123 -11
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +182 -1
- data/spec/lib/ruby_smb/smb1/packet/{error_packet_spec.rb → empty_packet_spec.rb} +21 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +63 -2
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/file_spec.rb +295 -2
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +51 -0
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +69 -3
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
- metadata +6 -4
- metadata.gz.sig +0 -0
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# This class represents an SMB1 TreeConnect Request Packet as defined in
|
5
5
|
# [2.2.4.7.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/cc246330.aspx)
|
6
6
|
class TreeConnectRequest < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
8
|
+
|
7
9
|
# A SMB1 Parameter Block as defined by the {TreeConnectRequest}
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
and_x_block :andx_block
|
@@ -22,10 +24,6 @@ module RubySMB
|
|
22
24
|
parameter_block :parameter_block
|
23
25
|
data_block :data_block
|
24
26
|
|
25
|
-
def initialize_instance
|
26
|
-
super
|
27
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
28
|
-
end
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# A SMB1 TreeConnect Response Packet as defined in
|
5
5
|
# [2.2.4.7.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/cc246331.aspx)
|
6
6
|
class TreeConnectResponse < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
8
|
+
|
7
9
|
# A SMB1 Parameter Block as defined by the {SessionSetupResponse}
|
8
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
9
11
|
and_x_block :andx_block
|
@@ -24,7 +26,6 @@ module RubySMB
|
|
24
26
|
|
25
27
|
def initialize_instance
|
26
28
|
super
|
27
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
28
29
|
smb_header.flags.reply = 1
|
29
30
|
end
|
30
31
|
|
@@ -34,12 +35,17 @@ module RubySMB
|
|
34
35
|
#
|
35
36
|
# @return [RubySMB::SMB1::BitField::DirectoryAccessMask] if a directory was connected to
|
36
37
|
# @return [RubySMB::SMB1::BitField::FileAccessMask] if anything else was connected to
|
38
|
+
# @raise [RubySMB::Error::InvalidBitField] if ACCESS_MASK bit field is not valid
|
37
39
|
def access_rights
|
38
40
|
if is_directory?
|
39
41
|
parameter_block.access_rights
|
40
42
|
else
|
41
43
|
mask = parameter_block.access_rights.to_binary_s
|
42
|
-
|
44
|
+
begin
|
45
|
+
RubySMB::SMB1::BitField::FileAccessMask.read(mask)
|
46
|
+
rescue IOError
|
47
|
+
raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Maximal Share Access Rights'
|
48
|
+
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
@@ -54,7 +60,11 @@ module RubySMB
|
|
54
60
|
parameter_block.guest_access_rights
|
55
61
|
else
|
56
62
|
mask = parameter_block.guest_access_rights.to_binary_s
|
57
|
-
|
63
|
+
begin
|
64
|
+
RubySMB::SMB1::BitField::FileAccessMask.read(mask)
|
65
|
+
rescue IOError
|
66
|
+
raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Guest Share Access Rights'
|
67
|
+
end
|
58
68
|
end
|
59
69
|
end
|
60
70
|
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# This class represents an SMB1 TreeDisonnect Request Packet as defined in
|
5
5
|
# [2.2.4.51.1 Request](https://msdn.microsoft.com/en-us/library/ee441622.aspx)
|
6
6
|
class TreeDisconnectRequest < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
|
8
|
+
|
7
9
|
# The Parameter Block for this packet is empty save the Word Count
|
8
10
|
# The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
|
9
11
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
@@ -17,10 +19,6 @@ module RubySMB
|
|
17
19
|
parameter_block :parameter_block
|
18
20
|
data_block :data_block
|
19
21
|
|
20
|
-
def initialize_instance
|
21
|
-
super
|
22
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
|
23
|
-
end
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# This class represents an SMB1 TreeDisonnect Response Packet as defined in
|
5
5
|
# [2.2.4.51.2 Response](https://msdn.microsoft.com/en-us/library/ee441823.aspx)
|
6
6
|
class TreeDisconnectResponse < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
|
8
|
+
|
7
9
|
# The Parameter Block for this packet is empty save the Word Count
|
8
10
|
# The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
|
9
11
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
@@ -19,7 +21,6 @@ module RubySMB
|
|
19
21
|
|
20
22
|
def initialize_instance
|
21
23
|
super
|
22
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
|
23
24
|
smb_header.flags.reply = 1
|
24
25
|
end
|
25
26
|
end
|
@@ -5,6 +5,8 @@ module RubySMB
|
|
5
5
|
# [2.2.4.43.1 Request](https://msdn.microsoft.com/en-us/library/ee441954.aspx)
|
6
6
|
# [2.2.4.3.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/ff469893.aspx)
|
7
7
|
class WriteAndxRequest < RubySMB::GenericPacket
|
8
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
|
9
|
+
|
8
10
|
# A SMB1 Parameter Block as defined by the {WriteAndxRequest}
|
9
11
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
10
12
|
endian :little
|
@@ -49,11 +51,6 @@ module RubySMB
|
|
49
51
|
parameter_block :parameter_block
|
50
52
|
data_block :data_block
|
51
53
|
|
52
|
-
def initialize_instance
|
53
|
-
super
|
54
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
|
55
|
-
end
|
56
|
-
|
57
54
|
# Specifies whether the offset is a 32-bit (default) or 64-bit value. When `is_64_bit`
|
58
55
|
# is true, a 64-bit offset will be used and the OffsetHigh field will be added to the structure.
|
59
56
|
#
|
@@ -5,6 +5,8 @@ module RubySMB
|
|
5
5
|
# [2.2.4.43.2 Response](https://msdn.microsoft.com/en-us/library/ee441673.aspx)
|
6
6
|
# [2.2.4.3.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/ff469858.aspx)
|
7
7
|
class WriteAndxResponse < RubySMB::GenericPacket
|
8
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
|
9
|
+
|
8
10
|
# A SMB1 Parameter Block as defined by the {WriteAndxResponse}
|
9
11
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
10
12
|
endian :little
|
@@ -26,7 +28,6 @@ module RubySMB
|
|
26
28
|
|
27
29
|
def initialize_instance
|
28
30
|
super
|
29
|
-
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
|
30
31
|
smb_header.flags.reply = 1
|
31
32
|
end
|
32
33
|
end
|
data/lib/ruby_smb/smb1/pipe.rb
CHANGED
@@ -26,14 +26,19 @@ module RubySMB
|
|
26
26
|
packet = @tree.set_header_fields(packet)
|
27
27
|
raw_response = @tree.client.send_recv(packet)
|
28
28
|
response = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.read(raw_response)
|
29
|
+
unless response.valid?
|
30
|
+
raise RubySMB::Error::InvalidPacket.new(
|
31
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
32
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
|
33
|
+
received_proto: response.smb_header.protocol,
|
34
|
+
received_cmd: response.smb_header.command
|
35
|
+
)
|
36
|
+
end
|
29
37
|
|
30
38
|
unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
31
39
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
32
40
|
end
|
33
41
|
|
34
|
-
unless response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_TRANSACTION
|
35
|
-
raise RubySMB::Error::InvalidPacket, 'Not a TransResponse packet'
|
36
|
-
end
|
37
42
|
response
|
38
43
|
end
|
39
44
|
|
data/lib/ruby_smb/smb1/tree.rb
CHANGED
@@ -39,11 +39,20 @@ module RubySMB
|
|
39
39
|
# Disconnects this Tree from the current session
|
40
40
|
#
|
41
41
|
# @return [WindowsError::ErrorCode] the NTStatus sent back by the server.
|
42
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a TreeDisconnectResponse packet
|
42
43
|
def disconnect!
|
43
44
|
request = RubySMB::SMB1::Packet::TreeDisconnectRequest.new
|
44
45
|
request = set_header_fields(request)
|
45
46
|
raw_response = client.send_recv(request)
|
46
47
|
response = RubySMB::SMB1::Packet::TreeDisconnectResponse.read(raw_response)
|
48
|
+
unless response.valid?
|
49
|
+
raise RubySMB::Error::InvalidPacket.new(
|
50
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
51
|
+
expected_cmd: RubySMB::SMB1::Packet::TreeDisconnectResponse::COMMAND,
|
52
|
+
received_proto: response.smb_header.protocol,
|
53
|
+
received_cmd: response.smb_header.command
|
54
|
+
)
|
55
|
+
end
|
47
56
|
response.status_code
|
48
57
|
end
|
49
58
|
|
@@ -113,8 +122,13 @@ module RubySMB
|
|
113
122
|
|
114
123
|
raw_response = @client.send_recv(nt_create_andx_request)
|
115
124
|
response = RubySMB::SMB1::Packet::NtCreateAndxResponse.read(raw_response)
|
116
|
-
unless response.
|
117
|
-
raise RubySMB::Error::InvalidPacket
|
125
|
+
unless response.valid?
|
126
|
+
raise RubySMB::Error::InvalidPacket.new(
|
127
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
128
|
+
expected_cmd: RubySMB::SMB1::Packet::NtCreateAndxResponse::COMMAND,
|
129
|
+
received_proto: response.smb_header.protocol,
|
130
|
+
received_cmd: response.smb_header.command
|
131
|
+
)
|
118
132
|
end
|
119
133
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
120
134
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
@@ -140,6 +154,8 @@ module RubySMB
|
|
140
154
|
# @param pattern [String] search pattern
|
141
155
|
# @param type [Class] file information class
|
142
156
|
# @return [Array] array of directory structures
|
157
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a Trans2 packet
|
158
|
+
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
143
159
|
def list(directory: '\\', pattern: '*', unicode: true,
|
144
160
|
type: RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo)
|
145
161
|
find_first_request = RubySMB::SMB1::Packet::Trans2::FindFirst2Request.new
|
@@ -166,6 +182,17 @@ module RubySMB
|
|
166
182
|
|
167
183
|
raw_response = client.send_recv(find_first_request)
|
168
184
|
response = RubySMB::SMB1::Packet::Trans2::FindFirst2Response.read(raw_response)
|
185
|
+
unless response.valid?
|
186
|
+
raise RubySMB::Error::InvalidPacket.new(
|
187
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
188
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindFirst2Response::COMMAND,
|
189
|
+
received_proto: response.smb_header.protocol,
|
190
|
+
received_cmd: response.smb_header.command
|
191
|
+
)
|
192
|
+
end
|
193
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
194
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
195
|
+
end
|
169
196
|
|
170
197
|
results = response.results(type, unicode: unicode)
|
171
198
|
|
@@ -190,6 +217,17 @@ module RubySMB
|
|
190
217
|
|
191
218
|
raw_response = client.send_recv(find_next_request)
|
192
219
|
response = RubySMB::SMB1::Packet::Trans2::FindNext2Response.read(raw_response)
|
220
|
+
unless response.valid?
|
221
|
+
raise RubySMB::Error::InvalidPacket.new(
|
222
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
223
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindNext2Response::COMMAND,
|
224
|
+
received_proto: response.smb_header.protocol,
|
225
|
+
received_cmd: response.smb_header.command
|
226
|
+
)
|
227
|
+
end
|
228
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
229
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
230
|
+
end
|
193
231
|
|
194
232
|
results += response.results(type, unicode: unicode)
|
195
233
|
|
data/lib/ruby_smb/smb2/dcerpc.rb
CHANGED
@@ -55,8 +55,13 @@ module RubySMB
|
|
55
55
|
request.buffer = action.to_binary_s
|
56
56
|
ioctl_raw_response = @tree.client.send_recv(request)
|
57
57
|
ioctl_response = RubySMB::SMB2::Packet::IoctlResponse.read(ioctl_raw_response)
|
58
|
-
unless ioctl_response.
|
59
|
-
raise RubySMB::Error::InvalidPacket
|
58
|
+
unless ioctl_response.valid?
|
59
|
+
raise RubySMB::Error::InvalidPacket.new(
|
60
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
61
|
+
expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND,
|
62
|
+
received_proto: ioctl_response.smb2_header.protocol,
|
63
|
+
received_cmd: ioctl_response.smb2_header.command
|
64
|
+
)
|
60
65
|
end
|
61
66
|
unless ioctl_response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
62
67
|
raise RubySMB::Error::UnexpectedStatusCode, ioctl_response.status_code.name
|
data/lib/ruby_smb/smb2/file.rb
CHANGED
@@ -79,11 +79,24 @@ module RubySMB
|
|
79
79
|
# Closes the handle to the remote file.
|
80
80
|
#
|
81
81
|
# @return [WindowsError::ErrorCode] the NTStatus code returned by the operation
|
82
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a CloseResponse packet
|
83
|
+
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
82
84
|
def close
|
83
85
|
close_request = set_header_fields(RubySMB::SMB2::Packet::CloseRequest.new)
|
84
86
|
raw_response = tree.client.send_recv(close_request)
|
85
87
|
response = RubySMB::SMB2::Packet::CloseResponse.read(raw_response)
|
86
|
-
response.
|
88
|
+
unless response.valid?
|
89
|
+
raise RubySMB::Error::InvalidPacket.new(
|
90
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
91
|
+
expected_cmd: RubySMB::SMB2::Packet::CloseResponse::COMMAND,
|
92
|
+
received_proto: response.smb2_header.protocol,
|
93
|
+
received_cmd: response.smb2_header.command
|
94
|
+
)
|
95
|
+
end
|
96
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
97
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
98
|
+
end
|
99
|
+
response.status_code
|
87
100
|
end
|
88
101
|
|
89
102
|
# Read from the file, a specific number of bytes
|
@@ -93,6 +106,8 @@ module RubySMB
|
|
93
106
|
# @param bytes [Integer] the number of bytes to read
|
94
107
|
# @param offset [Integer] the byte offset in the file to start reading from
|
95
108
|
# @return [String] the data read from the file
|
109
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a ReadResponse packet
|
110
|
+
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
96
111
|
def read(bytes: size, offset: 0)
|
97
112
|
atomic_read_size = if bytes > tree.client.server_max_read_size
|
98
113
|
tree.client.server_max_read_size
|
@@ -103,6 +118,17 @@ module RubySMB
|
|
103
118
|
read_request = read_packet(read_length: atomic_read_size, offset: offset)
|
104
119
|
raw_response = tree.client.send_recv(read_request)
|
105
120
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
121
|
+
unless response.valid?
|
122
|
+
raise RubySMB::Error::InvalidPacket.new(
|
123
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
124
|
+
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
125
|
+
received_proto: response.smb2_header.protocol,
|
126
|
+
received_cmd: response.smb2_header.command
|
127
|
+
)
|
128
|
+
end
|
129
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
130
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
131
|
+
end
|
106
132
|
|
107
133
|
data = response.buffer.to_binary_s
|
108
134
|
|
@@ -115,6 +141,17 @@ module RubySMB
|
|
115
141
|
read_request = read_packet(read_length: atomic_read_size, offset: offset)
|
116
142
|
raw_response = tree.client.send_recv(read_request)
|
117
143
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
144
|
+
unless response.valid?
|
145
|
+
raise RubySMB::Error::InvalidPacket.new(
|
146
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
147
|
+
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
148
|
+
received_proto: response.smb2_header.protocol,
|
149
|
+
received_cmd: response.smb2_header.command
|
150
|
+
)
|
151
|
+
end
|
152
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
153
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
154
|
+
end
|
118
155
|
|
119
156
|
data << response.buffer.to_binary_s
|
120
157
|
remaining_bytes -= atomic_read_size
|
@@ -138,10 +175,26 @@ module RubySMB
|
|
138
175
|
read_request = read_packet(read_length: read_length, offset: offset)
|
139
176
|
raw_response = tree.client.send_recv(read_request)
|
140
177
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
178
|
+
unless response.valid?
|
179
|
+
raise RubySMB::Error::InvalidPacket.new(
|
180
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
181
|
+
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
182
|
+
received_proto: response.smb2_header.protocol,
|
183
|
+
received_cmd: response.smb2_header.command
|
184
|
+
)
|
185
|
+
end
|
141
186
|
if response.status_code == WindowsError::NTStatus::STATUS_PENDING
|
142
187
|
sleep 1
|
143
188
|
raw_response = tree.client.dispatcher.recv_packet
|
144
189
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
190
|
+
unless response.valid?
|
191
|
+
raise RubySMB::Error::InvalidPacket.new(
|
192
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
193
|
+
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
194
|
+
received_proto: response.smb2_header.protocol,
|
195
|
+
received_cmd: response.smb2_header.command
|
196
|
+
)
|
197
|
+
end
|
145
198
|
elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
|
146
199
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
147
200
|
end
|
@@ -151,9 +204,18 @@ module RubySMB
|
|
151
204
|
# Delete a file on close
|
152
205
|
#
|
153
206
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
207
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
|
154
208
|
def delete
|
155
209
|
raw_response = tree.client.send_recv(delete_packet)
|
156
210
|
response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
|
211
|
+
unless response.valid?
|
212
|
+
raise RubySMB::Error::InvalidPacket.new(
|
213
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
214
|
+
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
215
|
+
received_proto: response.smb2_header.protocol,
|
216
|
+
received_cmd: response.smb2_header.command
|
217
|
+
)
|
218
|
+
end
|
157
219
|
response.smb2_header.nt_status.to_nt_status
|
158
220
|
end
|
159
221
|
|
@@ -182,6 +244,7 @@ module RubySMB
|
|
182
244
|
# @param data [String] the data to write to the file
|
183
245
|
# @param offset [Integer] the offset in the file to start writing from
|
184
246
|
# @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
|
247
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a WriteResponse packet
|
185
248
|
def write(data:'', offset: 0)
|
186
249
|
buffer = data.dup
|
187
250
|
bytes = data.length
|
@@ -195,6 +258,14 @@ module RubySMB
|
|
195
258
|
write_request = write_packet(data: buffer.slice!(0,atomic_write_size), offset: offset)
|
196
259
|
raw_response = tree.client.send_recv(write_request)
|
197
260
|
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
261
|
+
unless response.valid?
|
262
|
+
raise RubySMB::Error::InvalidPacket.new(
|
263
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
264
|
+
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
265
|
+
received_proto: response.smb2_header.protocol,
|
266
|
+
received_cmd: response.smb2_header.command
|
267
|
+
)
|
268
|
+
end
|
198
269
|
status = response.smb2_header.nt_status.to_nt_status
|
199
270
|
|
200
271
|
offset+= atomic_write_size
|
@@ -220,10 +291,26 @@ module RubySMB
|
|
220
291
|
pkt = write_packet(data: data, offset: offset)
|
221
292
|
raw_response = tree.client.send_recv(pkt)
|
222
293
|
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
294
|
+
unless response.valid?
|
295
|
+
raise RubySMB::Error::InvalidPacket.new(
|
296
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
297
|
+
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
298
|
+
received_proto: response.smb2_header.protocol,
|
299
|
+
received_cmd: response.smb2_header.command
|
300
|
+
)
|
301
|
+
end
|
223
302
|
if response.status_code == WindowsError::NTStatus::STATUS_PENDING
|
224
303
|
sleep 1
|
225
304
|
raw_response = tree.client.dispatcher.recv_packet
|
226
305
|
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
306
|
+
unless response.valid?
|
307
|
+
raise RubySMB::Error::InvalidPacket.new(
|
308
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
309
|
+
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
310
|
+
received_proto: response.smb2_header.protocol,
|
311
|
+
received_cmd: response.smb2_header.command
|
312
|
+
)
|
313
|
+
end
|
227
314
|
elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
|
228
315
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
229
316
|
end
|
@@ -234,9 +321,18 @@ module RubySMB
|
|
234
321
|
#
|
235
322
|
# @param new_file_name [String] the new name
|
236
323
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
324
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
|
237
325
|
def rename(new_file_name)
|
238
326
|
raw_response = tree.client.send_recv(rename_packet(new_file_name))
|
239
327
|
response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
|
328
|
+
unless response.valid?
|
329
|
+
raise RubySMB::Error::InvalidPacket.new(
|
330
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
331
|
+
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
332
|
+
received_proto: response.smb2_header.protocol,
|
333
|
+
received_cmd: response.smb2_header.command
|
334
|
+
)
|
335
|
+
end
|
240
336
|
response.smb2_header.nt_status.to_nt_status
|
241
337
|
end
|
242
338
|
|
@@ -4,6 +4,8 @@ module RubySMB
|
|
4
4
|
# An SMB2 Close Request Packet as defined in
|
5
5
|
# [2.2.15 SMB2 CLOSE Request](https://msdn.microsoft.com/en-us/library/cc246523.aspx)
|
6
6
|
class CloseRequest < RubySMB::GenericPacket
|
7
|
+
COMMAND = RubySMB::SMB2::Commands::CLOSE
|
8
|
+
|
7
9
|
endian :little
|
8
10
|
|
9
11
|
smb2_header :smb2_header
|
@@ -12,10 +14,6 @@ module RubySMB
|
|
12
14
|
uint32 :reserved, label: 'Reserved Space'
|
13
15
|
smb2_fileid :file_id, label: 'File ID'
|
14
16
|
|
15
|
-
def initialize_instance
|
16
|
-
super
|
17
|
-
smb2_header.command = RubySMB::SMB2::Commands::CLOSE
|
18
|
-
end
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|