ruby_smb 2.0.3 → 2.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 +10 -6
- data/lib/ruby_smb/client/authentication.rb +5 -10
- data/lib/ruby_smb/client/echo.rb +2 -4
- data/lib/ruby_smb/client/negotiation.rb +2 -4
- data/lib/ruby_smb/client/tree_connect.rb +2 -4
- data/lib/ruby_smb/client/utils.rb +16 -10
- data/lib/ruby_smb/client/winreg.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg.rb +2 -2
- data/lib/ruby_smb/error.rb +21 -5
- data/lib/ruby_smb/generic_packet.rb +11 -1
- data/lib/ruby_smb/smb1/file.rb +7 -14
- data/lib/ruby_smb/smb1/pipe.rb +5 -7
- data/lib/ruby_smb/smb1/tree.rb +13 -9
- data/lib/ruby_smb/smb2/file.rb +8 -16
- data/lib/ruby_smb/smb2/pipe.rb +2 -4
- data/lib/ruby_smb/smb2/tree.rb +12 -8
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +17 -12
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +12 -0
- data/spec/lib/ruby_smb/error_spec.rb +34 -5
- data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
- data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +23 -5
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +2 -5
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +23 -0
- metadata +2 -2
- metadata.gz.sig +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43f9f98936e870ad767348eb90c66f17eaf5e56c62b7792e13502c860bf8c4f1
|
4
|
+
data.tar.gz: b57d0bdee72f2fde7ee700771f85cd0f442f3ca5be70b4564b1598df05474860
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08c1bea7f46add92b4bf6746ec3794a7845a0d0dccb8a8d338d7b3fd07133b670b5509bfd1a71fa10dcc11059bcd01b38a0da664c9fe7b86aa8d58738d0215e8'
|
7
|
+
data.tar.gz: 69efcb218b522cd233a593ccd281786732f76c717349f44c776a1a7f9790a697b46ccc63b60ab01b31b58ab38487c2d0c3ff3db7c99f55dd7fda469c1ecc5d90
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -411,8 +411,7 @@ module RubySMB
|
|
411
411
|
raise RubySMB::Error::InvalidPacket.new(
|
412
412
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
413
413
|
expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
|
414
|
-
|
415
|
-
received_cmd: response.smb2_header.command
|
414
|
+
packet: response
|
416
415
|
)
|
417
416
|
end
|
418
417
|
else
|
@@ -423,8 +422,7 @@ module RubySMB
|
|
423
422
|
raise RubySMB::Error::InvalidPacket.new(
|
424
423
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
425
424
|
expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
|
426
|
-
|
427
|
-
received_cmd: response.smb_header.command
|
425
|
+
packet: response
|
428
426
|
)
|
429
427
|
end
|
430
428
|
end
|
@@ -473,11 +471,17 @@ module RubySMB
|
|
473
471
|
break unless is_status_pending?(smb2_header)
|
474
472
|
sleep 1
|
475
473
|
raw_response = recv_packet(encrypt: encrypt_data)
|
474
|
+
rescue IOError
|
475
|
+
# We're expecting an SMB2 packet, but the server sent an SMB1 packet
|
476
|
+
# instead. This behavior has been observed with older versions of Samba
|
477
|
+
# when something goes wrong on the server side. So, we just ignore it
|
478
|
+
# and expect the caller to handle this wrong response packet.
|
479
|
+
break
|
476
480
|
end unless version == 'SMB1'
|
477
481
|
|
478
482
|
self.sequence_counter += 1 if signing_required && !session_key.empty?
|
479
483
|
# update the SMB2 message ID according to the received Credit Charged
|
480
|
-
self.smb2_message_id += smb2_header.credit_charge - 1 if smb2_header && self.
|
484
|
+
self.smb2_message_id += smb2_header.credit_charge - 1 if smb2_header && self.server_supports_multi_credit
|
481
485
|
raw_response
|
482
486
|
end
|
483
487
|
|
@@ -579,7 +583,7 @@ module RubySMB
|
|
579
583
|
# @param [String] host
|
580
584
|
def net_share_enum_all(host)
|
581
585
|
tree = tree_connect("\\\\#{host}\\IPC$")
|
582
|
-
named_pipe = tree.
|
586
|
+
named_pipe = tree.open_pipe(filename: "srvsvc", write: true, read: true)
|
583
587
|
named_pipe.net_share_enum_all(host)
|
584
588
|
end
|
585
589
|
|
@@ -60,8 +60,7 @@ module RubySMB
|
|
60
60
|
raise RubySMB::Error::InvalidPacket.new(
|
61
61
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
62
62
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND,
|
63
|
-
|
64
|
-
received_cmd: packet.smb_header.command
|
63
|
+
packet: packet
|
65
64
|
)
|
66
65
|
end
|
67
66
|
packet
|
@@ -154,8 +153,7 @@ module RubySMB
|
|
154
153
|
raise RubySMB::Error::InvalidPacket.new(
|
155
154
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
156
155
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
157
|
-
|
158
|
-
received_cmd: packet.smb_header.command
|
156
|
+
packet: packet
|
159
157
|
)
|
160
158
|
end
|
161
159
|
packet
|
@@ -168,8 +166,7 @@ module RubySMB
|
|
168
166
|
raise RubySMB::Error::InvalidPacket.new(
|
169
167
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
170
168
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
171
|
-
|
172
|
-
received_cmd: packet.smb_header.command
|
169
|
+
packet: packet
|
173
170
|
)
|
174
171
|
end
|
175
172
|
|
@@ -236,8 +233,7 @@ module RubySMB
|
|
236
233
|
raise RubySMB::Error::InvalidPacket.new(
|
237
234
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
238
235
|
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
239
|
-
|
240
|
-
received_cmd: packet.smb2_header.command
|
236
|
+
packet: packet
|
241
237
|
)
|
242
238
|
end
|
243
239
|
|
@@ -251,8 +247,7 @@ module RubySMB
|
|
251
247
|
raise RubySMB::Error::InvalidPacket.new(
|
252
248
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
253
249
|
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
254
|
-
|
255
|
-
received_cmd: packet.smb2_header.command
|
250
|
+
packet: packet
|
256
251
|
)
|
257
252
|
end
|
258
253
|
|
data/lib/ruby_smb/client/echo.rb
CHANGED
@@ -21,8 +21,7 @@ module RubySMB
|
|
21
21
|
raise RubySMB::Error::InvalidPacket.new(
|
22
22
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
23
23
|
expected_cmd: RubySMB::SMB1::Packet::EchoResponse::COMMAND,
|
24
|
-
|
25
|
-
received_cmd: response.smb_header.command
|
24
|
+
packet: response
|
26
25
|
)
|
27
26
|
end
|
28
27
|
response
|
@@ -40,8 +39,7 @@ module RubySMB
|
|
40
39
|
raise RubySMB::Error::InvalidPacket.new(
|
41
40
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
42
41
|
expected_cmd: RubySMB::SMB2::Packet::EchoResponse::COMMAND,
|
43
|
-
|
44
|
-
received_cmd: response.smb2_header.command
|
42
|
+
packet: response
|
45
43
|
)
|
46
44
|
end
|
47
45
|
response
|
@@ -83,16 +83,14 @@ module RubySMB
|
|
83
83
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
84
84
|
expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
|
85
85
|
expected_custom: "extended_security=1",
|
86
|
-
|
87
|
-
received_cmd: packet.smb_header.command,
|
86
|
+
packet: packet,
|
88
87
|
received_custom: "extended_security=#{extended_security}"
|
89
88
|
)
|
90
89
|
elsif packet.packet_smb_version == 'SMB2'
|
91
90
|
raise RubySMB::Error::InvalidPacket.new(
|
92
91
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
93
92
|
expected_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
|
94
|
-
|
95
|
-
received_cmd: packet.smb2_header.command
|
93
|
+
packet: packet
|
96
94
|
)
|
97
95
|
else
|
98
96
|
raise RubySMB::Error::InvalidPacket, 'Unknown SMB protocol version'
|
@@ -33,8 +33,7 @@ module RubySMB
|
|
33
33
|
raise RubySMB::Error::InvalidPacket.new(
|
34
34
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
35
35
|
expected_cmd: RubySMB::SMB1::Packet::TreeConnectResponse::COMMAND,
|
36
|
-
|
37
|
-
received_cmd: response.smb_header.command
|
36
|
+
packet: response
|
38
37
|
)
|
39
38
|
end
|
40
39
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -73,8 +72,7 @@ module RubySMB
|
|
73
72
|
raise RubySMB::Error::InvalidPacket.new(
|
74
73
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
75
74
|
expected_cmd: RubySMB::SMB2::Packet::TreeConnectResponse::COMMAND,
|
76
|
-
|
77
|
-
received_cmd: response.smb2_header.command
|
75
|
+
packet: response
|
78
76
|
)
|
79
77
|
end
|
80
78
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -24,19 +24,25 @@ module RubySMB
|
|
24
24
|
last_tree.id
|
25
25
|
end
|
26
26
|
|
27
|
-
def open(path, disposition=RubySMB::Dispositions::FILE_OPEN, write: false, read: true)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
def open(path, disposition=RubySMB::Dispositions::FILE_OPEN, write: false, read: true, pipe: false)
|
28
|
+
if pipe
|
29
|
+
file = last_tree.open_pipe(filename: path, write: write, read: read, disposition: disposition)
|
30
|
+
else
|
31
|
+
file = last_tree.open_file(filename: path, write: write, read: read, disposition: disposition)
|
32
|
+
end
|
33
|
+
@last_file_id = if file.respond_to?(:guid)
|
34
|
+
# SMB2 uses guid
|
35
|
+
file.guid.to_binary_s
|
36
|
+
elsif file.respond_to?(:fid)
|
37
|
+
# SMB1 uses fid
|
38
|
+
file.fid.to_binary_s
|
39
|
+
end
|
40
|
+
@open_files[@last_file_id] = file
|
41
|
+
@last_file_id
|
36
42
|
end
|
37
43
|
|
38
44
|
def create_pipe(path, disposition=RubySMB::Dispositions::FILE_OPEN_IF)
|
39
|
-
open(path
|
45
|
+
open(path, disposition, write: true, read: true, pipe: true)
|
40
46
|
end
|
41
47
|
|
42
48
|
#Writes data to an open file handle
|
@@ -6,7 +6,7 @@ module RubySMB
|
|
6
6
|
share = "\\\\#{host}\\IPC$"
|
7
7
|
tree = @tree_connects.find {|tree| tree.share == share}
|
8
8
|
tree = tree_connect(share) unless tree
|
9
|
-
named_pipe = tree.
|
9
|
+
named_pipe = tree.open_pipe(filename: "winreg", write: true, read: true)
|
10
10
|
if block_given?
|
11
11
|
res = yield named_pipe
|
12
12
|
named_pipe.close
|
@@ -387,7 +387,7 @@ module RubySMB
|
|
387
387
|
enum_result
|
388
388
|
ensure
|
389
389
|
close_key(subkey_handle) if subkey_handle
|
390
|
-
close_key(root_key_handle) if root_key_handle
|
390
|
+
close_key(root_key_handle) if root_key_handle && root_key_handle != subkey_handle
|
391
391
|
end
|
392
392
|
|
393
393
|
# Enumerate the values for the specified registry key.
|
@@ -413,7 +413,7 @@ module RubySMB
|
|
413
413
|
enum_result
|
414
414
|
ensure
|
415
415
|
close_key(subkey_handle) if subkey_handle
|
416
|
-
close_key(root_key_handle) if root_key_handle
|
416
|
+
close_key(root_key_handle) if root_key_handle && root_key_handle != subkey_handle
|
417
417
|
end
|
418
418
|
|
419
419
|
end
|
data/lib/ruby_smb/error.rb
CHANGED
@@ -16,23 +16,26 @@ module RubySMB
|
|
16
16
|
# Raised when trying to parse raw binary into a Packet and the data
|
17
17
|
# is invalid.
|
18
18
|
class InvalidPacket < RubySMBError
|
19
|
+
attr_reader :status_code
|
19
20
|
def initialize(args = nil)
|
20
21
|
if args.nil?
|
21
22
|
super
|
22
23
|
elsif args.is_a? String
|
23
24
|
super(args)
|
24
25
|
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[:
|
28
|
-
received_cmd = args[:
|
26
|
+
expected_proto = args[:expected_proto] ? translate_protocol(args[:expected_proto]) : '???'
|
27
|
+
expected_cmd = args[:expected_cmd] || '???'
|
28
|
+
received_proto = args[:packet]&.packet_smb_version || '???'
|
29
|
+
received_cmd = get_cmd(args[:packet]) || '???'
|
30
|
+
@status_code = args[:packet]&.status_code
|
29
31
|
super(
|
30
32
|
"Expecting #{expected_proto} protocol "\
|
31
33
|
"with command=#{expected_cmd}"\
|
32
34
|
"#{(" (" + args[:expected_custom] + ")") if args[:expected_custom]}, "\
|
33
35
|
"got #{received_proto} protocol "\
|
34
36
|
"with command=#{received_cmd}"\
|
35
|
-
"#{(" (" + args[:received_custom] + ")") if args[:received_custom]}"
|
37
|
+
"#{(" (" + args[:received_custom] + ")") if args[:received_custom]}"\
|
38
|
+
"#{(", Status: #{@status_code}") if @status_code}"
|
36
39
|
)
|
37
40
|
else
|
38
41
|
raise ArgumentError, "InvalidPacket expects a String or a Hash, got a #{args.class}"
|
@@ -50,6 +53,19 @@ module RubySMB
|
|
50
53
|
end
|
51
54
|
end
|
52
55
|
private :translate_protocol
|
56
|
+
|
57
|
+
def get_cmd(packet)
|
58
|
+
return nil unless packet
|
59
|
+
case packet.packet_smb_version
|
60
|
+
when 'SMB1'
|
61
|
+
packet.smb_header.command
|
62
|
+
when 'SMB2'
|
63
|
+
packet.smb2_header.command
|
64
|
+
else
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
private :get_cmd
|
53
69
|
end
|
54
70
|
|
55
71
|
# Raised when a response packet has a NTStatus code that was unexpected.
|
@@ -49,7 +49,17 @@ module RubySMB
|
|
49
49
|
when /SMB1/
|
50
50
|
packet = RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
51
51
|
when /SMB2/
|
52
|
-
|
52
|
+
begin
|
53
|
+
packet = RubySMB::SMB2::Packet::ErrorPacket.read(val)
|
54
|
+
rescue RubySMB::Error::InvalidPacket
|
55
|
+
# Handle the case where an SMB2 error packet is expected, but the
|
56
|
+
# server sent an SMB1 empty packet instead. This behavior has been
|
57
|
+
# observed with older versions of Samba when something goes wrong
|
58
|
+
# on the server side. We just want to give it a chance and try to
|
59
|
+
# parse it as an SMB1 empty packet to keep information and avoid
|
60
|
+
# failing as much as possible.
|
61
|
+
packet = RubySMB::SMB1::Packet::EmptyPacket.read(val)
|
62
|
+
end
|
53
63
|
else
|
54
64
|
raise RubySMB::Error::InvalidPacket, 'Not a valid SMB packet'
|
55
65
|
end
|
data/lib/ruby_smb/smb1/file.rb
CHANGED
@@ -86,8 +86,7 @@ module RubySMB
|
|
86
86
|
raise RubySMB::Error::InvalidPacket.new(
|
87
87
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
88
88
|
expected_cmd: RubySMB::SMB1::Packet::CloseResponse::COMMAND,
|
89
|
-
|
90
|
-
received_cmd: response.smb_header.command
|
89
|
+
packet: response
|
91
90
|
)
|
92
91
|
end
|
93
92
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -118,8 +117,7 @@ module RubySMB
|
|
118
117
|
raise RubySMB::Error::InvalidPacket.new(
|
119
118
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
120
119
|
expected_cmd: RubySMB::SMB1::Packet::ReadAndxResponse::COMMAND,
|
121
|
-
|
122
|
-
received_cmd: response.smb_header.command
|
120
|
+
packet: response
|
123
121
|
)
|
124
122
|
end
|
125
123
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -167,8 +165,7 @@ module RubySMB
|
|
167
165
|
raise RubySMB::Error::InvalidPacket.new(
|
168
166
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
169
167
|
expected_cmd: RubySMB::SMB1::Packet::ReadAndxResponse::COMMAND,
|
170
|
-
|
171
|
-
received_cmd: response.smb_header.command
|
168
|
+
packet: response
|
172
169
|
)
|
173
170
|
end
|
174
171
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -189,8 +186,7 @@ module RubySMB
|
|
189
186
|
raise RubySMB::Error::InvalidPacket.new(
|
190
187
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
191
188
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse::COMMAND,
|
192
|
-
|
193
|
-
received_cmd: response.smb_header.command
|
189
|
+
packet: response
|
194
190
|
)
|
195
191
|
end
|
196
192
|
response.status_code
|
@@ -231,8 +227,7 @@ module RubySMB
|
|
231
227
|
raise RubySMB::Error::InvalidPacket.new(
|
232
228
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
233
229
|
expected_cmd: RubySMB::SMB1::Packet::WriteAndxResponse::COMMAND,
|
234
|
-
|
235
|
-
received_cmd: response.smb_header.command
|
230
|
+
packet: response
|
236
231
|
)
|
237
232
|
end
|
238
233
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -271,8 +266,7 @@ module RubySMB
|
|
271
266
|
raise RubySMB::Error::InvalidPacket.new(
|
272
267
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
273
268
|
expected_cmd: RubySMB::SMB1::Packet::WriteAndxResponse::COMMAND,
|
274
|
-
|
275
|
-
received_cmd: response.smb_header.command
|
269
|
+
packet: response
|
276
270
|
)
|
277
271
|
end
|
278
272
|
response.parameter_block.count_low
|
@@ -290,8 +284,7 @@ module RubySMB
|
|
290
284
|
raise RubySMB::Error::InvalidPacket.new(
|
291
285
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
292
286
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse::COMMAND,
|
293
|
-
|
294
|
-
received_cmd: response.smb_header.command
|
287
|
+
packet: response
|
295
288
|
)
|
296
289
|
end
|
297
290
|
response.status_code
|
data/lib/ruby_smb/smb1/pipe.rb
CHANGED
@@ -16,11 +16,11 @@ module RubySMB
|
|
16
16
|
def initialize(tree:, response:, name:)
|
17
17
|
raise ArgumentError, 'No Name Provided' if name.nil?
|
18
18
|
case name
|
19
|
-
when 'srvsvc'
|
19
|
+
when 'srvsvc', '\\srvsvc'
|
20
20
|
extend RubySMB::Dcerpc::Srvsvc
|
21
|
-
when 'winreg'
|
21
|
+
when 'winreg', '\\winreg'
|
22
22
|
extend RubySMB::Dcerpc::Winreg
|
23
|
-
when 'svcctl'
|
23
|
+
when 'svcctl', '\\svcctl'
|
24
24
|
extend RubySMB::Dcerpc::Svcctl
|
25
25
|
end
|
26
26
|
super(tree: tree, response: response, name: name)
|
@@ -43,8 +43,7 @@ module RubySMB
|
|
43
43
|
raise RubySMB::Error::InvalidPacket.new(
|
44
44
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
45
45
|
expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
|
46
|
-
|
47
|
-
received_cmd: response.smb_header.command
|
46
|
+
packet: response
|
48
47
|
)
|
49
48
|
end
|
50
49
|
|
@@ -102,8 +101,7 @@ module RubySMB
|
|
102
101
|
raise RubySMB::Error::InvalidPacket.new(
|
103
102
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
104
103
|
expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND,
|
105
|
-
|
106
|
-
received_cmd: trans_nmpipe_response.smb_header.command
|
104
|
+
packet: trans_nmpipe_response
|
107
105
|
)
|
108
106
|
end
|
109
107
|
unless [WindowsError::NTStatus::STATUS_SUCCESS,
|
data/lib/ruby_smb/smb1/tree.rb
CHANGED
@@ -49,13 +49,20 @@ module RubySMB
|
|
49
49
|
raise RubySMB::Error::InvalidPacket.new(
|
50
50
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
51
51
|
expected_cmd: RubySMB::SMB1::Packet::TreeDisconnectResponse::COMMAND,
|
52
|
-
|
53
|
-
received_cmd: response.smb_header.command
|
52
|
+
packet: response
|
54
53
|
)
|
55
54
|
end
|
56
55
|
response.status_code
|
57
56
|
end
|
58
57
|
|
58
|
+
def open_pipe(opts)
|
59
|
+
# Make sure we don't modify the caller's hash options
|
60
|
+
opts = opts.dup
|
61
|
+
opts[:filename] = opts[:filename].dup
|
62
|
+
opts[:filename].prepend('\\') unless opts[:filename].start_with?('\\')
|
63
|
+
open_file(opts)
|
64
|
+
end
|
65
|
+
|
59
66
|
# Open a file on the remote share.
|
60
67
|
#
|
61
68
|
# @example
|
@@ -135,15 +142,14 @@ module RubySMB
|
|
135
142
|
raise RubySMB::Error::InvalidPacket.new(
|
136
143
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
137
144
|
expected_cmd: RubySMB::SMB1::Packet::NtCreateAndxResponse::COMMAND,
|
138
|
-
|
139
|
-
received_cmd: response.smb_header.command
|
145
|
+
packet: response
|
140
146
|
)
|
141
147
|
end
|
142
148
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
143
149
|
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
144
150
|
end
|
145
151
|
|
146
|
-
case response.parameter_block.resource_type
|
152
|
+
case response.parameter_block.resource_type
|
147
153
|
when RubySMB::SMB1::ResourceType::BYTE_MODE_PIPE, RubySMB::SMB1::ResourceType::MESSAGE_MODE_PIPE
|
148
154
|
RubySMB::SMB1::Pipe.new(name: filename, tree: self, response: response)
|
149
155
|
when RubySMB::SMB1::ResourceType::DISK
|
@@ -195,8 +201,7 @@ module RubySMB
|
|
195
201
|
raise RubySMB::Error::InvalidPacket.new(
|
196
202
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
197
203
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindFirst2Response::COMMAND,
|
198
|
-
|
199
|
-
received_cmd: response.smb_header.command
|
204
|
+
packet: response
|
200
205
|
)
|
201
206
|
end
|
202
207
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -230,8 +235,7 @@ module RubySMB
|
|
230
235
|
raise RubySMB::Error::InvalidPacket.new(
|
231
236
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
232
237
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindNext2Response::COMMAND,
|
233
|
-
|
234
|
-
received_cmd: response.smb_header.command
|
238
|
+
packet: response
|
235
239
|
)
|
236
240
|
end
|
237
241
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
data/lib/ruby_smb/smb2/file.rb
CHANGED
@@ -95,8 +95,7 @@ module RubySMB
|
|
95
95
|
raise RubySMB::Error::InvalidPacket.new(
|
96
96
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
97
97
|
expected_cmd: RubySMB::SMB2::Packet::CloseResponse::COMMAND,
|
98
|
-
|
99
|
-
received_cmd: response.smb2_header.command
|
98
|
+
packet: response
|
100
99
|
)
|
101
100
|
end
|
102
101
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -130,8 +129,7 @@ module RubySMB
|
|
130
129
|
raise RubySMB::Error::InvalidPacket.new(
|
131
130
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
132
131
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
133
|
-
|
134
|
-
received_cmd: response.smb2_header.command
|
132
|
+
packet: response
|
135
133
|
)
|
136
134
|
end
|
137
135
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -153,8 +151,7 @@ module RubySMB
|
|
153
151
|
raise RubySMB::Error::InvalidPacket.new(
|
154
152
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
155
153
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
156
|
-
|
157
|
-
received_cmd: response.smb2_header.command
|
154
|
+
packet: response
|
158
155
|
)
|
159
156
|
end
|
160
157
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -189,8 +186,7 @@ module RubySMB
|
|
189
186
|
raise RubySMB::Error::InvalidPacket.new(
|
190
187
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
191
188
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
192
|
-
|
193
|
-
received_cmd: response.smb2_header.command
|
189
|
+
packet: response
|
194
190
|
)
|
195
191
|
end
|
196
192
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -210,8 +206,7 @@ module RubySMB
|
|
210
206
|
raise RubySMB::Error::InvalidPacket.new(
|
211
207
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
212
208
|
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
213
|
-
|
214
|
-
received_cmd: response.smb2_header.command
|
209
|
+
packet: response
|
215
210
|
)
|
216
211
|
end
|
217
212
|
response.smb2_header.nt_status.to_nt_status
|
@@ -262,8 +257,7 @@ module RubySMB
|
|
262
257
|
raise RubySMB::Error::InvalidPacket.new(
|
263
258
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
264
259
|
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
265
|
-
|
266
|
-
received_cmd: response.smb2_header.command
|
260
|
+
packet: response
|
267
261
|
)
|
268
262
|
end
|
269
263
|
status = response.smb2_header.nt_status.to_nt_status
|
@@ -297,8 +291,7 @@ module RubySMB
|
|
297
291
|
raise RubySMB::Error::InvalidPacket.new(
|
298
292
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
299
293
|
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
300
|
-
|
301
|
-
received_cmd: response.smb2_header.command
|
294
|
+
packet: response
|
302
295
|
)
|
303
296
|
end
|
304
297
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -319,8 +312,7 @@ module RubySMB
|
|
319
312
|
raise RubySMB::Error::InvalidPacket.new(
|
320
313
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
321
314
|
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
322
|
-
|
323
|
-
received_cmd: response.smb2_header.command
|
315
|
+
packet: response
|
324
316
|
)
|
325
317
|
end
|
326
318
|
response.smb2_header.nt_status.to_nt_status
|
data/lib/ruby_smb/smb2/pipe.rb
CHANGED
@@ -42,8 +42,7 @@ module RubySMB
|
|
42
42
|
raise RubySMB::Error::InvalidPacket.new(
|
43
43
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
44
44
|
expected_cmd: RubySMB::SMB2::Packet::IoctlResponse::COMMAND,
|
45
|
-
|
46
|
-
received_cmd: response.smb2_header.command
|
45
|
+
packet: response
|
47
46
|
)
|
48
47
|
end
|
49
48
|
|
@@ -100,8 +99,7 @@ module RubySMB
|
|
100
99
|
raise RubySMB::Error::InvalidPacket.new(
|
101
100
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
102
101
|
expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND,
|
103
|
-
|
104
|
-
received_cmd: ioctl_response.smb2_header.command
|
102
|
+
packet: ioctl_response
|
105
103
|
)
|
106
104
|
end
|
107
105
|
unless [WindowsError::NTStatus::STATUS_SUCCESS,
|
data/lib/ruby_smb/smb2/tree.rb
CHANGED
@@ -50,13 +50,20 @@ module RubySMB
|
|
50
50
|
raise RubySMB::Error::InvalidPacket.new(
|
51
51
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
52
52
|
expected_cmd: RubySMB::SMB2::Packet::TreeDisconnectResponse::COMMAND,
|
53
|
-
|
54
|
-
received_cmd: response.smb2_header.command
|
53
|
+
packet: response
|
55
54
|
)
|
56
55
|
end
|
57
56
|
response.status_code
|
58
57
|
end
|
59
58
|
|
59
|
+
def open_pipe(opts)
|
60
|
+
# Make sure we don't modify the caller's hash options
|
61
|
+
opts = opts.dup
|
62
|
+
opts[:filename] = opts[:filename].dup
|
63
|
+
opts[:filename] = opts[:filename][1..-1] if opts[:filename].start_with? '\\'
|
64
|
+
open_file(opts)
|
65
|
+
end
|
66
|
+
|
60
67
|
def open_file(filename:, attributes: nil, options: nil, disposition: RubySMB::Dispositions::FILE_OPEN,
|
61
68
|
impersonation: RubySMB::ImpersonationLevels::SEC_IMPERSONATE, read: true, write: false, delete: false)
|
62
69
|
|
@@ -108,8 +115,7 @@ module RubySMB
|
|
108
115
|
raise RubySMB::Error::InvalidPacket.new(
|
109
116
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
110
117
|
expected_cmd: RubySMB::SMB2::Packet::CreateResponse::COMMAND,
|
111
|
-
|
112
|
-
received_cmd: response.smb2_header.command
|
118
|
+
packet: response
|
113
119
|
)
|
114
120
|
end
|
115
121
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -167,8 +173,7 @@ module RubySMB
|
|
167
173
|
raise RubySMB::Error::InvalidPacket.new(
|
168
174
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
169
175
|
expected_cmd: RubySMB::SMB2::Packet::QueryDirectoryResponse::COMMAND,
|
170
|
-
|
171
|
-
received_cmd: directory_response.smb2_header.command
|
176
|
+
packet: directory_response
|
172
177
|
)
|
173
178
|
end
|
174
179
|
|
@@ -212,8 +217,7 @@ module RubySMB
|
|
212
217
|
raise RubySMB::Error::InvalidPacket.new(
|
213
218
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
214
219
|
expected_cmd: RubySMB::SMB2::Packet::CreateResponse::COMMAND,
|
215
|
-
|
216
|
-
received_cmd: response.smb2_header.command
|
220
|
+
packet: response
|
217
221
|
)
|
218
222
|
end
|
219
223
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
data/lib/ruby_smb/version.rb
CHANGED
@@ -332,23 +332,28 @@ RSpec.describe RubySMB::Client do
|
|
332
332
|
expect(smb2_client.sequence_counter).to eq(1)
|
333
333
|
end
|
334
334
|
|
335
|
-
it 'updates #
|
335
|
+
it 'updates #smb2_message_id with SMB2 header #credit_charge if the server supports multi credits' do
|
336
336
|
allow(smb2_client).to receive(:is_status_pending?).and_return(false)
|
337
337
|
smb2_client.smb2_message_id = 0
|
338
|
-
smb2_client.
|
338
|
+
smb2_client.server_supports_multi_credit = true
|
339
339
|
smb2_header.credit_charge = 5
|
340
340
|
smb2_client.send_recv(smb2_request)
|
341
341
|
expect(smb2_client.smb2_message_id).to eq(5)
|
342
342
|
end
|
343
343
|
|
344
|
-
it 'does not update #msb2_message_id with SMB2 header #credit_charge if the
|
344
|
+
it 'does not update #msb2_message_id with SMB2 header #credit_charge if the server does not support multi credits' do
|
345
345
|
allow(smb2_client).to receive(:is_status_pending?).and_return(false)
|
346
346
|
smb2_client.smb2_message_id = 0
|
347
|
-
smb2_client.
|
347
|
+
smb2_client.server_supports_multi_credit = false
|
348
348
|
smb2_header.credit_charge = 5
|
349
349
|
smb2_client.send_recv(smb2_request)
|
350
350
|
expect(smb2_client.smb2_message_id).to eq(1)
|
351
351
|
end
|
352
|
+
|
353
|
+
it 'ignores errors thrown when parsing the SMB2 header' do
|
354
|
+
allow(RubySMB::SMB2::SMB2Header).to receive(:read).and_raise(IOError)
|
355
|
+
expect { smb2_client.send_recv(smb2_request) }.to_not raise_error
|
356
|
+
end
|
352
357
|
end
|
353
358
|
|
354
359
|
describe '#is_status_pending?' do
|
@@ -2354,7 +2359,7 @@ RSpec.describe RubySMB::Client do
|
|
2354
2359
|
let(:named_pipe){ double("Named Pipe") }
|
2355
2360
|
|
2356
2361
|
before :example do
|
2357
|
-
allow(tree).to receive(:
|
2362
|
+
allow(tree).to receive(:open_pipe).and_return(named_pipe)
|
2358
2363
|
allow(named_pipe).to receive(:net_share_enum_all)
|
2359
2364
|
end
|
2360
2365
|
|
@@ -2369,8 +2374,8 @@ RSpec.describe RubySMB::Client do
|
|
2369
2374
|
smb1_client.net_share_enum_all(sock.peeraddr)
|
2370
2375
|
end
|
2371
2376
|
|
2372
|
-
it 'it calls the Tree #
|
2373
|
-
expect(tree).to receive(:
|
2377
|
+
it 'it calls the Tree #open_pipe method to open "srvsvc" named pipe' do
|
2378
|
+
expect(tree).to receive(:open_pipe).with(filename: "srvsvc", write: true, read: true).and_return(named_pipe)
|
2374
2379
|
smb1_client.net_share_enum_all(sock.peeraddr)
|
2375
2380
|
end
|
2376
2381
|
|
@@ -2392,8 +2397,8 @@ RSpec.describe RubySMB::Client do
|
|
2392
2397
|
smb2_client.net_share_enum_all(sock.peeraddr)
|
2393
2398
|
end
|
2394
2399
|
|
2395
|
-
it 'it calls the Tree #
|
2396
|
-
expect(tree).to receive(:
|
2400
|
+
it 'it calls the Tree #open_pipe method to open "srvsvc" named pipe' do
|
2401
|
+
expect(tree).to receive(:open_pipe).with(filename: "srvsvc", write: true, read: true).and_return(named_pipe)
|
2397
2402
|
smb2_client.net_share_enum_all(sock.peeraddr)
|
2398
2403
|
end
|
2399
2404
|
|
@@ -2474,7 +2479,7 @@ RSpec.describe RubySMB::Client do
|
|
2474
2479
|
before :example do
|
2475
2480
|
allow(ipc_tree).to receive_messages(
|
2476
2481
|
:share => share,
|
2477
|
-
:
|
2482
|
+
:open_pipe => named_pipe
|
2478
2483
|
)
|
2479
2484
|
allow(client).to receive(:tree_connect).and_return(ipc_tree)
|
2480
2485
|
end
|
@@ -2496,9 +2501,9 @@ RSpec.describe RubySMB::Client do
|
|
2496
2501
|
expect(client).to have_received(:tree_connect).with(share)
|
2497
2502
|
end
|
2498
2503
|
|
2499
|
-
it 'open \'winreg\'
|
2504
|
+
it 'open \'winreg\' pipe on the IPC$ Tree' do
|
2500
2505
|
client.connect_to_winreg(host)
|
2501
|
-
expect(ipc_tree).to have_received(:
|
2506
|
+
expect(ipc_tree).to have_received(:open_pipe).with(filename: "winreg", write: true, read: true)
|
2502
2507
|
end
|
2503
2508
|
|
2504
2509
|
it 'returns the expected opened named pipe' do
|
@@ -669,6 +669,12 @@ RSpec.describe RubySMB::Dcerpc::Winreg do
|
|
669
669
|
expect(winreg).to have_received(:close_key).with(root_key_handle)
|
670
670
|
end
|
671
671
|
|
672
|
+
it 'only closes the key once when there is no subkey' do
|
673
|
+
winreg.enum_registry_key(root_key)
|
674
|
+
expect(winreg).to have_received(:close_key).once
|
675
|
+
expect(winreg).to have_received(:close_key).with(root_key_handle)
|
676
|
+
end
|
677
|
+
|
672
678
|
it 'returns the expected array of enumerated keys' do
|
673
679
|
key1 = 'key1'
|
674
680
|
key2 = 'key2'
|
@@ -742,6 +748,12 @@ RSpec.describe RubySMB::Dcerpc::Winreg do
|
|
742
748
|
expect(winreg).to have_received(:close_key).with(root_key_handle)
|
743
749
|
end
|
744
750
|
|
751
|
+
it 'only closes the key once when there is no subkey' do
|
752
|
+
winreg.enum_registry_values(root_key)
|
753
|
+
expect(winreg).to have_received(:close_key).once
|
754
|
+
expect(winreg).to have_received(:close_key).with(root_key_handle)
|
755
|
+
end
|
756
|
+
|
745
757
|
it 'returns the expected array of enumerated keys' do
|
746
758
|
value1 = 'value1'
|
747
759
|
value2 = 'value2'
|
@@ -9,16 +9,45 @@ RSpec.describe RubySMB::Error::InvalidPacket do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
context 'with a Hash' do
|
12
|
-
|
13
|
-
|
12
|
+
let(:ex) do
|
13
|
+
described_class.new(
|
14
14
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
15
15
|
expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
|
16
16
|
expected_custom: "extended_security=1",
|
17
|
-
|
18
|
-
received_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
|
17
|
+
packet: packet,
|
19
18
|
received_custom: "extended_security=0"
|
20
19
|
)
|
21
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with an SMB2 packet' do
|
23
|
+
let(:packet) { RubySMB::SMB2::Packet::NegotiateResponse.new }
|
24
|
+
|
25
|
+
it 'outputs the expected error message' do
|
26
|
+
expect(ex.to_s).to eq('Expecting SMB1 protocol with command=114 (extended_security=1), got SMB2 protocol with command=0 (extended_security=0), Status: (0x00000000) STATUS_SUCCESS: The operation completed successfully.')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with an SMB1 packet' do
|
31
|
+
let(:packet) { RubySMB::SMB1::Packet::ReadAndxRequest.new }
|
32
|
+
|
33
|
+
it 'outputs the expected error message' do
|
34
|
+
expect(ex.to_s).to eq('Expecting SMB1 protocol with command=114 (extended_security=1), got SMB1 protocol with command=46 (extended_security=0), Status: (0x00000000) STATUS_SUCCESS: The operation completed successfully.')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'without packet' do
|
39
|
+
let(:ex) do
|
40
|
+
described_class.new(
|
41
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
42
|
+
expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
|
43
|
+
expected_custom: "extended_security=1",
|
44
|
+
received_custom: "extended_security=0"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'outputs the expected error message' do
|
49
|
+
expect(ex.to_s).to eq('Expecting SMB1 protocol with command=114 (extended_security=1), got ??? protocol with command=??? (extended_security=0)')
|
50
|
+
end
|
22
51
|
end
|
23
52
|
end
|
24
53
|
|
@@ -88,6 +88,13 @@ RSpec.describe RubySMB::GenericPacket do
|
|
88
88
|
packet = RubySMB::SMB2::Packet::NegotiateResponse.read(smb2_error_packet.to_binary_s)
|
89
89
|
expect(packet.original_command).to eq RubySMB::SMB2::Packet::NegotiateResponse::COMMAND
|
90
90
|
end
|
91
|
+
|
92
|
+
context 'when the server returns an SMB1 error packet' do
|
93
|
+
let(:smb1_error_packet) { RubySMB::SMB1::Packet::EmptyPacket.new }
|
94
|
+
it 'returns the empty packet instead of the asked for class' do
|
95
|
+
expect(RubySMB::SMB2::Packet::NegotiateResponse.read(smb1_error_packet.to_binary_s)).to be_a RubySMB::SMB1::Packet::EmptyPacket
|
96
|
+
end
|
97
|
+
end
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
@@ -521,9 +521,7 @@ RSpec.describe RubySMB::SMB1::File do
|
|
521
521
|
|
522
522
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
523
523
|
allow(response).to receive(:valid?).and_return(false)
|
524
|
-
|
525
|
-
allow(response).to receive(:smb_header).and_return(smb_header)
|
526
|
-
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
524
|
+
allow(response).to receive(:packet_smb_version)
|
527
525
|
expect { file.close }.to raise_error(RubySMB::Error::InvalidPacket)
|
528
526
|
end
|
529
527
|
|
@@ -80,9 +80,7 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
80
80
|
|
81
81
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
82
82
|
allow(response).to receive(:valid?).and_return(false)
|
83
|
-
|
84
|
-
allow(response).to receive(:smb_header).and_return(smb_header)
|
85
|
-
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
83
|
+
allow(response).to receive(:packet_smb_version)
|
86
84
|
expect { pipe.peek }.to raise_error(RubySMB::Error::InvalidPacket)
|
87
85
|
end
|
88
86
|
|
@@ -149,6 +147,13 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
149
147
|
end
|
150
148
|
end
|
151
149
|
|
150
|
+
context 'with \'\\srvsvc\' filename' do
|
151
|
+
it 'extends Srvsvc class' do
|
152
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\srvsvc')
|
153
|
+
expect(pipe.respond_to?(:net_share_enum_all)).to be true
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
152
157
|
context 'with \'winreg\' filename' do
|
153
158
|
it 'extends Winreg class' do
|
154
159
|
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'winreg')
|
@@ -156,12 +161,26 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
156
161
|
end
|
157
162
|
end
|
158
163
|
|
164
|
+
context 'with \'\\winreg\' filename' do
|
165
|
+
it 'extends Winreg class' do
|
166
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\winreg')
|
167
|
+
expect(pipe.respond_to?(:has_registry_key?)).to be true
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
159
171
|
context 'with \'svcctl\' filename' do
|
160
172
|
it 'extends svcctl class' do
|
161
173
|
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'svcctl')
|
162
174
|
expect(pipe.respond_to?(:query_service_config)).to be true
|
163
175
|
end
|
164
176
|
end
|
177
|
+
|
178
|
+
context 'with \'\\svcctl\' filename' do
|
179
|
+
it 'extends svcctl class' do
|
180
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: '\\svcctl')
|
181
|
+
expect(pipe.respond_to?(:query_service_config)).to be true
|
182
|
+
end
|
183
|
+
end
|
165
184
|
end
|
166
185
|
|
167
186
|
describe '#dcerpc_request' do
|
@@ -245,8 +264,7 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
245
264
|
|
246
265
|
context 'when the response is not a Trans packet' do
|
247
266
|
it 'raises an InvalidPacket exception' do
|
248
|
-
allow(trans_nmpipe_response).to
|
249
|
-
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :command)
|
267
|
+
allow(trans_nmpipe_response).to receive(:packet_smb_version)
|
250
268
|
allow(trans_nmpipe_response).to receive(:valid?).and_return(false)
|
251
269
|
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
252
270
|
end
|
@@ -492,4 +492,26 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
492
492
|
end
|
493
493
|
end
|
494
494
|
|
495
|
+
describe '#open_pipe' do
|
496
|
+
let(:opts) { { filename: 'test', write: true } }
|
497
|
+
before :example do
|
498
|
+
allow(tree).to receive(:open_file)
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'calls #open_file with the provided options' do
|
502
|
+
opts[:filename] ='\\test'
|
503
|
+
expect(tree).to receive(:open_file).with(opts)
|
504
|
+
tree.open_pipe(opts)
|
505
|
+
end
|
506
|
+
|
507
|
+
it 'prepends the filename with \\ if needed' do
|
508
|
+
expect(tree).to receive(:open_file).with( { filename: '\\test', write: true } )
|
509
|
+
tree.open_pipe(opts)
|
510
|
+
end
|
511
|
+
|
512
|
+
it 'does not modify the original option hash' do
|
513
|
+
tree.open_pipe(opts)
|
514
|
+
expect(opts).to eq( { filename: 'test', write: true } )
|
515
|
+
end
|
516
|
+
end
|
495
517
|
end
|
@@ -459,9 +459,7 @@ RSpec.describe RubySMB::SMB2::File do
|
|
459
459
|
|
460
460
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
461
461
|
allow(response).to receive(:valid?).and_return(false)
|
462
|
-
|
463
|
-
allow(response).to receive(:smb2_header).and_return(smb2_header)
|
464
|
-
allow(smb2_header).to receive_messages(:protocol => nil, :command => nil)
|
462
|
+
allow(response).to receive(:packet_smb_version)
|
465
463
|
expect { file.close }.to raise_error(RubySMB::Error::InvalidPacket)
|
466
464
|
end
|
467
465
|
|
@@ -86,9 +86,7 @@ RSpec.describe RubySMB::SMB2::Pipe do
|
|
86
86
|
|
87
87
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
88
88
|
allow(response).to receive(:valid?).and_return(false)
|
89
|
-
|
90
|
-
allow(response).to receive(:smb2_header).and_return(smb2_header)
|
91
|
-
allow(smb2_header).to receive_messages(:protocol => nil, :command => nil)
|
89
|
+
allow(response).to receive(:packet_smb_version)
|
92
90
|
expect { pipe.peek }.to raise_error(RubySMB::Error::InvalidPacket)
|
93
91
|
end
|
94
92
|
|
@@ -261,8 +259,7 @@ RSpec.describe RubySMB::SMB2::Pipe do
|
|
261
259
|
|
262
260
|
context 'when the response is not an IoctlResponse packet' do
|
263
261
|
it 'raises an InvalidPacket exception' do
|
264
|
-
allow(ioctl_response).to
|
265
|
-
allow(ioctl_response).to receive_message_chain(:smb2_header, :command)
|
262
|
+
allow(ioctl_response).to receive(:packet_smb_version)
|
266
263
|
allow(ioctl_response).to receive(:valid?).and_return(false)
|
267
264
|
expect { pipe.ioctl_send_recv(dcerpc_request, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
268
265
|
end
|
@@ -531,4 +531,27 @@ RSpec.describe RubySMB::SMB2::Tree do
|
|
531
531
|
end
|
532
532
|
end
|
533
533
|
end
|
534
|
+
|
535
|
+
describe '#open_pipe' do
|
536
|
+
let(:opts) { { filename: '\\test', write: true } }
|
537
|
+
before :example do
|
538
|
+
allow(tree).to receive(:open_file)
|
539
|
+
end
|
540
|
+
|
541
|
+
it 'calls #open_file with the provided options' do
|
542
|
+
opts[:filename] ='test'
|
543
|
+
expect(tree).to receive(:open_file).with(opts)
|
544
|
+
tree.open_pipe(opts)
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'remove the leading \\ from the filename if needed' do
|
548
|
+
expect(tree).to receive(:open_file).with( { filename: 'test', write: true } )
|
549
|
+
tree.open_pipe(opts)
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'does not modify the original option hash' do
|
553
|
+
tree.open_pipe(opts)
|
554
|
+
expect(opts).to eq( { filename: '\\test', write: true } )
|
555
|
+
end
|
556
|
+
end
|
534
557
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_smb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Metasploit Hackers
|
@@ -97,7 +97,7 @@ cert_chain:
|
|
97
97
|
JI/W23RbIRksG2pioMhd4dCXq3FLLlkOV1YfCwWixNB+iIhQPPZVaPNfgPhCn4Dt
|
98
98
|
DeGjje/qA4fkLtRmOtb9PUBq3ToRDE4=
|
99
99
|
-----END CERTIFICATE-----
|
100
|
-
date: 2020-08-
|
100
|
+
date: 2020-08-28 00:00:00.000000000 Z
|
101
101
|
dependencies:
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: redcarpet
|
metadata.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
CpfDǵ�&K��:�Sm�h�t ���HI��Ă)!����A
|
2
|
+
�\ҝ�1��-�ق*��D��o��i����a=�h�o�df�E���`GLU�W&O�~�*'�d'UU�%�M2�c[�YG���@2>�M�<�n6��Χm�qg3"n(��\�O�� �5��w�c�<rf�f�[�!��_�����I����S�,�bf�9��R�U��UZ3�<(mj(��uN7E�����0�������0�Z
|