ruby_smb 2.0.3 → 2.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 +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
|