ruby_smb 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|