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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d5e35bee112d4186cdb919a1041dbd54c72739d
|
4
|
+
data.tar.gz: 002b2dcada90c5617d15d472f5d06c5f1474619d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8516db67fb88bb248314f69eefef87f8021fcc409fa637e43a1b97474665d28e8d24fe470283d895c65374479d13d372d9eed346814eebd6bf144b63805b8bf2
|
7
|
+
data.tar.gz: 21632505b70f1af84724a613eb2344fda82e7c60f63255eb92569bef752fd0dcdf1e0fcb58f7f3cf21200b79fdfc3e592fde3643a42b0b5002db963d5f54e3ba
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -297,15 +297,32 @@ module RubySMB
|
|
297
297
|
# Sends a LOGOFF command to the remote server to terminate the session
|
298
298
|
#
|
299
299
|
# @return [WindowsError::ErrorCode] the NTStatus of the response
|
300
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not a LogoffResponse packet
|
300
301
|
def logoff!
|
301
302
|
if smb2
|
302
303
|
request = RubySMB::SMB2::Packet::LogoffRequest.new
|
303
304
|
raw_response = send_recv(request)
|
304
305
|
response = RubySMB::SMB2::Packet::LogoffResponse.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::LogoffResponse::COMMAND,
|
310
|
+
received_proto: response.smb2_header.protocol,
|
311
|
+
received_cmd: response.smb2_header.command
|
312
|
+
)
|
313
|
+
end
|
305
314
|
else
|
306
315
|
request = RubySMB::SMB1::Packet::LogoffRequest.new
|
307
316
|
raw_response = send_recv(request)
|
308
317
|
response = RubySMB::SMB1::Packet::LogoffResponse.read(raw_response)
|
318
|
+
unless response.valid?
|
319
|
+
raise RubySMB::Error::InvalidPacket.new(
|
320
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
321
|
+
expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
|
322
|
+
received_proto: response.smb_header.protocol,
|
323
|
+
received_cmd: response.smb_header.command
|
324
|
+
)
|
325
|
+
end
|
309
326
|
end
|
310
327
|
wipe_state!
|
311
328
|
response.status_code
|
@@ -380,14 +397,19 @@ module RubySMB
|
|
380
397
|
# @param name [String] the NetBIOS name to request
|
381
398
|
# @return [TrueClass] if session request is granted
|
382
399
|
# @raise [RubySMB::Error::NetBiosSessionService] if session request is refused
|
400
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not a NBSS packet
|
383
401
|
def session_request(name = '*SMBSERVER')
|
384
402
|
session_request = session_request_packet(name)
|
385
403
|
dispatcher.send_packet(session_request, nbss_header: false)
|
386
404
|
raw_response = dispatcher.recv_packet(full_response: true)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
405
|
+
begin
|
406
|
+
session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
|
407
|
+
if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
|
408
|
+
negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
|
409
|
+
raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
|
410
|
+
end
|
411
|
+
rescue IOError
|
412
|
+
raise RubySMB::Error::InvalidPacket, 'Not a NBSS packet'
|
391
413
|
end
|
392
414
|
|
393
415
|
return true
|
@@ -54,14 +54,15 @@ module RubySMB
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def smb1_anonymous_auth_response(raw_response)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response)
|
58
|
+
|
59
|
+
unless packet.valid?
|
60
|
+
raise RubySMB::Error::InvalidPacket.new(
|
61
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
62
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND,
|
63
|
+
received_proto: packet.smb_header.protocol,
|
64
|
+
received_cmd: packet.smb_header.command
|
65
|
+
)
|
65
66
|
end
|
66
67
|
packet
|
67
68
|
end
|
@@ -147,14 +148,15 @@ module RubySMB
|
|
147
148
|
|
148
149
|
# Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
|
149
150
|
def smb1_ntlmssp_final_packet(raw_response)
|
150
|
-
|
151
|
-
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
152
|
-
rescue
|
153
|
-
packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
|
154
|
-
end
|
151
|
+
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
155
152
|
|
156
|
-
unless packet.
|
157
|
-
raise RubySMB::Error::InvalidPacket
|
153
|
+
unless packet.valid?
|
154
|
+
raise RubySMB::Error::InvalidPacket.new(
|
155
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
156
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
157
|
+
received_proto: packet.smb_header.protocol,
|
158
|
+
received_cmd: packet.smb_header.command
|
159
|
+
)
|
158
160
|
end
|
159
161
|
packet
|
160
162
|
end
|
@@ -162,15 +164,20 @@ module RubySMB
|
|
162
164
|
# Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
|
163
165
|
def smb1_ntlmssp_challenge_packet(raw_response)
|
164
166
|
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
165
|
-
|
167
|
+
unless packet.valid?
|
168
|
+
raise RubySMB::Error::InvalidPacket.new(
|
169
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
170
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
171
|
+
received_proto: packet.smb_header.protocol,
|
172
|
+
received_cmd: packet.smb_header.command
|
173
|
+
)
|
174
|
+
end
|
166
175
|
|
176
|
+
status_code = packet.status_code
|
167
177
|
unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
|
168
178
|
raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
|
169
179
|
end
|
170
180
|
|
171
|
-
unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
172
|
-
raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
|
173
|
-
end
|
174
181
|
packet
|
175
182
|
end
|
176
183
|
|
@@ -212,23 +219,34 @@ module RubySMB
|
|
212
219
|
# Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
213
220
|
def smb2_ntlmssp_final_packet(raw_response)
|
214
221
|
packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
|
215
|
-
unless packet.
|
216
|
-
raise RubySMB::Error::InvalidPacket
|
222
|
+
unless packet.valid?
|
223
|
+
raise RubySMB::Error::InvalidPacket.new(
|
224
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
225
|
+
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
226
|
+
received_proto: packet.smb2_header.protocol,
|
227
|
+
received_cmd: packet.smb2_header.command
|
228
|
+
)
|
217
229
|
end
|
230
|
+
|
218
231
|
packet
|
219
232
|
end
|
220
233
|
|
221
234
|
# Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
222
235
|
def smb2_ntlmssp_challenge_packet(raw_response)
|
223
236
|
packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
|
237
|
+
unless packet.valid?
|
238
|
+
raise RubySMB::Error::InvalidPacket.new(
|
239
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
240
|
+
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
241
|
+
received_proto: packet.smb2_header.protocol,
|
242
|
+
received_cmd: packet.smb2_header.command
|
243
|
+
)
|
244
|
+
end
|
245
|
+
|
224
246
|
status_code = packet.status_code
|
225
247
|
unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
|
226
248
|
raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
|
227
249
|
end
|
228
|
-
|
229
|
-
unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP
|
230
|
-
raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}"
|
231
|
-
end
|
232
250
|
packet
|
233
251
|
end
|
234
252
|
|
data/lib/ruby_smb/client/echo.rb
CHANGED
@@ -16,7 +16,16 @@ module RubySMB
|
|
16
16
|
(count - 1).times do
|
17
17
|
raw_response = dispatcher.recv_packet
|
18
18
|
end
|
19
|
-
RubySMB::SMB1::Packet::EchoResponse.read(raw_response)
|
19
|
+
response = RubySMB::SMB1::Packet::EchoResponse.read(raw_response)
|
20
|
+
unless response.valid?
|
21
|
+
raise RubySMB::Error::InvalidPacket.new(
|
22
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
23
|
+
expected_cmd: RubySMB::SMB1::Packet::EchoResponse::COMMAND,
|
24
|
+
received_proto: response.smb_header.protocol,
|
25
|
+
received_cmd: response.smb_header.command
|
26
|
+
)
|
27
|
+
end
|
28
|
+
response
|
20
29
|
end
|
21
30
|
|
22
31
|
# Sends an ECHO request packet and returns the
|
@@ -26,7 +35,16 @@ module RubySMB
|
|
26
35
|
def smb2_echo
|
27
36
|
request = RubySMB::SMB2::Packet::EchoRequest.new
|
28
37
|
raw_response = send_recv(request)
|
29
|
-
RubySMB::SMB2::Packet::EchoResponse.read(raw_response)
|
38
|
+
response = RubySMB::SMB2::Packet::EchoResponse.read(raw_response)
|
39
|
+
unless response.valid?
|
40
|
+
raise RubySMB::Error::InvalidPacket.new(
|
41
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
42
|
+
expected_cmd: RubySMB::SMB2::Packet::EchoResponse::COMMAND,
|
43
|
+
received_proto: response.smb2_header.protocol,
|
44
|
+
received_cmd: response.smb2_header.command
|
45
|
+
)
|
46
|
+
end
|
47
|
+
response
|
30
48
|
end
|
31
49
|
end
|
32
50
|
end
|
@@ -47,23 +47,38 @@ module RubySMB
|
|
47
47
|
def negotiate_response(raw_data)
|
48
48
|
response = nil
|
49
49
|
if smb1
|
50
|
-
|
51
|
-
packet = RubySMB::SMB1::Packet::NegotiateResponseExtended.read raw_data
|
52
|
-
rescue StandardError => e
|
53
|
-
raise RubySMB::Error::InvalidPacket, "Not a Valid SMB1 Negoitate Response #{e.message}"
|
54
|
-
end
|
50
|
+
packet = RubySMB::SMB1::Packet::NegotiateResponseExtended.read raw_data
|
55
51
|
response = packet if packet.valid?
|
56
52
|
end
|
57
53
|
if smb2 && response.nil?
|
58
|
-
|
59
|
-
|
60
|
-
rescue StandardError => e
|
61
|
-
raise RubySMB::Error::InvalidPacket, "Not a Valid SMB2 Negoitate Response #{e.message}"
|
62
|
-
end
|
63
|
-
response = packet
|
54
|
+
packet = RubySMB::SMB2::Packet::NegotiateResponse.read raw_data
|
55
|
+
response = packet if packet.valid?
|
64
56
|
end
|
65
57
|
if response.nil?
|
66
|
-
|
58
|
+
if packet.packet_smb_version == 'SMB1'
|
59
|
+
extended_security = if packet.is_a? RubySMB::SMB1::Packet::NegotiateResponseExtended
|
60
|
+
packet.parameter_block.capabilities.extended_security
|
61
|
+
else
|
62
|
+
"n/a"
|
63
|
+
end
|
64
|
+
raise RubySMB::Error::InvalidPacket.new(
|
65
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
66
|
+
expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
|
67
|
+
expected_custom: "extended_security=1",
|
68
|
+
received_proto: packet.smb_header.protocol,
|
69
|
+
received_cmd: packet.smb_header.command,
|
70
|
+
received_custom: "extended_security=#{extended_security}"
|
71
|
+
)
|
72
|
+
elsif packet.packet_smb_version == 'SMB2'
|
73
|
+
raise RubySMB::Error::InvalidPacket.new(
|
74
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
75
|
+
expected_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
|
76
|
+
received_proto: packet.smb2_header.protocol,
|
77
|
+
received_cmd: packet.smb2_header.command
|
78
|
+
)
|
79
|
+
else
|
80
|
+
raise RubySMB::Error::InvalidPacket, 'Unknown SMB protocol version'
|
81
|
+
end
|
67
82
|
end
|
68
83
|
response
|
69
84
|
end
|
@@ -17,11 +17,7 @@ module RubySMB
|
|
17
17
|
request.smb_header.tid = 65_535
|
18
18
|
request.data_block.path = share
|
19
19
|
raw_response = send_recv(request)
|
20
|
-
|
21
|
-
response = RubySMB::SMB1::Packet::TreeConnectResponse.read(raw_response)
|
22
|
-
rescue EOFError
|
23
|
-
response = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
|
24
|
-
end
|
20
|
+
response = RubySMB::SMB1::Packet::TreeConnectResponse.read(raw_response)
|
25
21
|
smb1_tree_from_response(share, response)
|
26
22
|
end
|
27
23
|
|
@@ -30,9 +26,16 @@ module RubySMB
|
|
30
26
|
# @param share [String] the share path to connect to
|
31
27
|
# @param response [RubySMB::SMB1::Packet::TreeConnectResponse] the response packet to parse into our Tree
|
32
28
|
# @return [RubySMB::SMB1::Tree]
|
29
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response command is not a TreeConnectResponse packet
|
30
|
+
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response status code is not STATUS_SUCCESS
|
33
31
|
def smb1_tree_from_response(share, response)
|
34
|
-
unless response.
|
35
|
-
raise RubySMB::Error::InvalidPacket
|
32
|
+
unless response.valid?
|
33
|
+
raise RubySMB::Error::InvalidPacket.new(
|
34
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
35
|
+
expected_cmd: RubySMB::SMB1::Packet::TreeConnectResponse::COMMAND,
|
36
|
+
received_proto: response.smb_header.protocol,
|
37
|
+
received_cmd: response.smb_header.command
|
38
|
+
)
|
36
39
|
end
|
37
40
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
38
41
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
@@ -54,11 +57,7 @@ module RubySMB
|
|
54
57
|
request.smb2_header.tree_id = 65_535
|
55
58
|
request.encode_path(share)
|
56
59
|
raw_response = send_recv(request)
|
57
|
-
|
58
|
-
response = RubySMB::SMB2::Packet::TreeConnectResponse.read(raw_response)
|
59
|
-
rescue EOFError
|
60
|
-
response = RubySMB::SMB2::Packet::ErrorPacket.read(raw_response)
|
61
|
-
end
|
60
|
+
response = RubySMB::SMB2::Packet::TreeConnectResponse.read(raw_response)
|
62
61
|
smb2_tree_from_response(share, response)
|
63
62
|
end
|
64
63
|
|
@@ -67,9 +66,16 @@ module RubySMB
|
|
67
66
|
# @param share [String] the share path to connect to
|
68
67
|
# @param response [RubySMB::SMB2::Packet::TreeConnectResponse] the response packet to parse into our Tree
|
69
68
|
# @return [RubySMB::SMB2::Tree]
|
69
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response command is not a TreeConnectResponse packet
|
70
|
+
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response status code is not STATUS_SUCCESS
|
70
71
|
def smb2_tree_from_response(share, response)
|
71
|
-
unless response.
|
72
|
-
raise RubySMB::Error::InvalidPacket
|
72
|
+
unless response.valid?
|
73
|
+
raise RubySMB::Error::InvalidPacket.new(
|
74
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
75
|
+
expected_cmd: RubySMB::SMB2::Packet::TreeConnectResponse::COMMAND,
|
76
|
+
received_proto: response.smb2_header.protocol,
|
77
|
+
received_cmd: response.smb2_header.command
|
78
|
+
)
|
73
79
|
end
|
74
80
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
75
81
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
data/lib/ruby_smb/error.rb
CHANGED
@@ -15,7 +15,42 @@ module RubySMB
|
|
15
15
|
|
16
16
|
# Raised when trying to parse raw binary into a Packet and the data
|
17
17
|
# is invalid.
|
18
|
-
class InvalidPacket < RubySMBError
|
18
|
+
class InvalidPacket < RubySMBError
|
19
|
+
def initialize(args = nil)
|
20
|
+
if args.nil?
|
21
|
+
super
|
22
|
+
elsif args.is_a? String
|
23
|
+
super(args)
|
24
|
+
elsif args.is_a? Hash
|
25
|
+
expected_proto = args[:expected_proto] ? translate_protocol(args[:expected_proto]) : "???"
|
26
|
+
expected_cmd = args[:expected_cmd] || "???"
|
27
|
+
received_proto = args[:received_proto] ? translate_protocol(args[:received_proto]) : "???"
|
28
|
+
received_cmd = args[:received_cmd] || "???"
|
29
|
+
super(
|
30
|
+
"Expecting #{expected_proto} protocol "\
|
31
|
+
"with command=#{expected_cmd}"\
|
32
|
+
"#{(" (" + args[:expected_custom] + ")") if args[:expected_custom]}, "\
|
33
|
+
"got #{received_proto} protocol "\
|
34
|
+
"with command=#{received_cmd}"\
|
35
|
+
"#{(" (" + args[:received_custom] + ")") if args[:received_custom]}"
|
36
|
+
)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "InvalidPacket expects a String or a Hash, got a #{args.class}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def translate_protocol(proto)
|
43
|
+
case proto
|
44
|
+
when RubySMB::SMB1::SMB_PROTOCOL_ID
|
45
|
+
'SMB1'
|
46
|
+
when RubySMB::SMB2::SMB2_PROTOCOL_ID
|
47
|
+
'SMB2'
|
48
|
+
else
|
49
|
+
raise ArgumentError, 'Unknown SMB protocol'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
private :translate_protocol
|
53
|
+
end
|
19
54
|
|
20
55
|
# Raised when a response packet has a NTStatus code that was unexpected.
|
21
56
|
class UnexpectedStatusCode < RubySMBError; end
|
@@ -26,5 +61,9 @@ module RubySMB
|
|
26
61
|
# Raised when Protocol Negotiation fails, possibly due to an
|
27
62
|
# unsupported protocol.
|
28
63
|
class NegotiationFailure < RubySMBError; end
|
64
|
+
|
65
|
+
# Raised when trying to parse raw binary into a BitField and the data
|
66
|
+
# is invalid.
|
67
|
+
class InvalidBitField < RubySMBError; end
|
29
68
|
end
|
30
69
|
end
|
@@ -45,14 +45,16 @@ module RubySMB
|
|
45
45
|
rescue IOError => e
|
46
46
|
case self.to_s
|
47
47
|
when /EmptyPacket|ErrorPacket/
|
48
|
-
raise
|
48
|
+
raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
|
49
49
|
when /SMB1/
|
50
|
-
RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
50
|
+
packet = RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
51
51
|
when /SMB2/
|
52
|
-
RubySMB::SMB2::Packet::ErrorPacket.read(val)
|
52
|
+
packet = RubySMB::SMB2::Packet::ErrorPacket.read(val)
|
53
53
|
else
|
54
|
-
raise
|
54
|
+
raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
|
55
55
|
end
|
56
|
+
packet.original_command = self::COMMAND
|
57
|
+
packet
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
@@ -72,6 +74,33 @@ module RubySMB
|
|
72
74
|
status_code
|
73
75
|
end
|
74
76
|
|
77
|
+
# Validates the packet protocol ID and the SMB command
|
78
|
+
#
|
79
|
+
# @return [TrueClass, FalseClass] true if the packet is valid, false otherwise
|
80
|
+
def valid?
|
81
|
+
case packet_smb_version
|
82
|
+
when 'SMB1'
|
83
|
+
return smb_header.protocol == RubySMB::SMB1::SMB_PROTOCOL_ID &&
|
84
|
+
smb_header.command == self.class::COMMAND
|
85
|
+
when 'SMB2'
|
86
|
+
return smb2_header.protocol == RubySMB::SMB2::SMB2_PROTOCOL_ID &&
|
87
|
+
smb2_header.command == self.class::COMMAND
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize_instance
|
92
|
+
super
|
93
|
+
|
94
|
+
unless [RubySMB::SMB1::Packet::EmptyPacket, RubySMB::SMB2::Packet::ErrorPacket].any? {|klass| self.is_a? klass}
|
95
|
+
case packet_smb_version
|
96
|
+
when 'SMB1'
|
97
|
+
smb_header.command = self.class::COMMAND
|
98
|
+
when 'SMB2'
|
99
|
+
smb2_header.command = self.class::COMMAND
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
75
104
|
# Returns an array of hashes representing the
|
76
105
|
# fields for this record.
|
77
106
|
#
|
data/lib/ruby_smb/smb1/dcerpc.rb
CHANGED
@@ -43,8 +43,13 @@ module RubySMB
|
|
43
43
|
|
44
44
|
trans_nmpipe_raw_response = @tree.client.send_recv(request)
|
45
45
|
trans_nmpipe_response = RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.read(trans_nmpipe_raw_response)
|
46
|
-
unless trans_nmpipe_response.
|
47
|
-
raise RubySMB::Error::InvalidPacket
|
46
|
+
unless trans_nmpipe_response.valid?
|
47
|
+
raise RubySMB::Error::InvalidPacket.new(
|
48
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
49
|
+
expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND,
|
50
|
+
received_proto: trans_nmpipe_response.smb_header.protocol,
|
51
|
+
received_cmd: trans_nmpipe_response.smb_header.command
|
52
|
+
)
|
48
53
|
end
|
49
54
|
unless trans_nmpipe_response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
50
55
|
raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code.name
|