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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6cce717ed3175b8027db1e414fae576e984ff4c88a158568014b4c4eb06406f7
4
- data.tar.gz: fb9223d4f15a3ed99aca553523dd957ceb3173cef87b4ba3d29a409ae4baffda
3
+ metadata.gz: 43f9f98936e870ad767348eb90c66f17eaf5e56c62b7792e13502c860bf8c4f1
4
+ data.tar.gz: b57d0bdee72f2fde7ee700771f85cd0f442f3ca5be70b4564b1598df05474860
5
5
  SHA512:
6
- metadata.gz: 94319bee008719b00933ab82140fafd65c13344858f6677ecb26502cf22d087de0200c0feab9304959ac38df17fcac6540707e2b55457d8d92370484fbfbcd06
7
- data.tar.gz: bf55746b294b17d9a4633e1344d976bfdc13df89e96c1ea5861c55999fdd0e1367d25b0e7e1ec455d4666a9fe0d41bfc7b943c84bc00606e2705f952319f4cb2
6
+ metadata.gz: '08c1bea7f46add92b4bf6746ec3794a7845a0d0dccb8a8d338d7b3fd07133b670b5509bfd1a71fa10dcc11059bcd01b38a0da664c9fe7b86aa8d58738d0215e8'
7
+ data.tar.gz: 69efcb218b522cd233a593ccd281786732f76c717349f44c776a1a7f9790a697b46ccc63b60ab01b31b58ab38487c2d0c3ff3db7c99f55dd7fda469c1ecc5d90
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb_header.protocol,
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.dialect != '0x0202'
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.open_file(filename: "srvsvc", write: true, read: true)
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
- received_proto: packet.smb_header.protocol,
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
- received_proto: packet.smb_header.protocol,
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
- received_proto: packet.smb_header.protocol,
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
- received_proto: packet.smb2_header.protocol,
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
- received_proto: packet.smb2_header.protocol,
255
- received_cmd: packet.smb2_header.command
250
+ packet: packet
256
251
  )
257
252
  end
258
253
 
@@ -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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: packet.smb_header.protocol,
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
- received_proto: packet.smb2_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- file = last_tree.open_file(filename: path.sub(/^\\/, ''), write: write, read: read, disposition: disposition)
29
- @last_file_id = if file.respond_to?(:guid)
30
- file.guid.to_binary_s
31
- elsif file.respond_to?(:fid)
32
- file.fid.to_binary_s
33
- end
34
- @open_files[@last_file_id] = file
35
- @last_file_id
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.gsub(/\\/, ''), disposition, write: true, read: true)
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.open_file(filename: "winreg", write: true, read: true)
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
@@ -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[:received_proto] ? translate_protocol(args[:received_proto]) : "???"
28
- received_cmd = args[:received_cmd] || "???"
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
- packet = RubySMB::SMB2::Packet::ErrorPacket.read(val)
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
@@ -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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
294
- received_cmd: response.smb_header.command
287
+ packet: response
295
288
  )
296
289
  end
297
290
  response.status_code
@@ -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
- received_proto: response.smb_header.protocol,
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
- received_proto: trans_nmpipe_response.smb_header.protocol,
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,
@@ -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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
- received_proto: response.smb_header.protocol,
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
@@ -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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
@@ -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
- received_proto: response.smb2_header.protocol,
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
- received_proto: ioctl_response.smb2_header.protocol,
104
- received_cmd: ioctl_response.smb2_header.command
102
+ packet: ioctl_response
105
103
  )
106
104
  end
107
105
  unless [WindowsError::NTStatus::STATUS_SUCCESS,
@@ -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
- received_proto: response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
- received_proto: directory_response.smb2_header.protocol,
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
- received_proto: response.smb2_header.protocol,
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
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '2.0.3'.freeze
2
+ VERSION = '2.0.4'.freeze
3
3
  end
@@ -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 #msb2_message_id with SMB2 header #credit_charge if the dialect is not 0x0202' do
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.dialect = '0x0210'
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 dialect is 0x0202' do
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.dialect = '0x0202'
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(:open_file).and_return(named_pipe)
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 #open_file method to open "srvsvc" named pipe' do
2373
- expect(tree).to receive(:open_file).with(filename: "srvsvc", write: true, read: true).and_return(named_pipe)
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 #open_file method to open "srvsvc" named pipe' do
2396
- expect(tree).to receive(:open_file).with(filename: "srvsvc", write: true, read: true).and_return(named_pipe)
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
- :open_file => named_pipe
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\' file on the IPC$ Tree' do
2504
+ it 'open \'winreg\' pipe on the IPC$ Tree' do
2500
2505
  client.connect_to_winreg(host)
2501
- expect(ipc_tree).to have_received(:open_file).with(filename: "winreg", write: true, read: true)
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
- it 'outputs the expected error message' do
13
- ex = described_class.new(
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
- received_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
18
- received_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
17
+ packet: packet,
19
18
  received_custom: "extended_security=0"
20
19
  )
21
- expect(ex.to_s).to eq('Expecting SMB1 protocol with command=114 (extended_security=1), got SMB2 protocol with command=0 (extended_security=0)')
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
- smb_header = double('SMB Header')
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
- smb_header = double('SMB Header')
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 receive_message_chain(:smb_header, :protocol)
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
- smb2_header = double('SMB2 Header')
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
- smb2_header = double('SMB2 Header')
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 receive_message_chain(:smb2_header, :protocol)
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.3
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-17 00:00:00.000000000 Z
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
- N�� H-
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