ruby_smb 1.1.0 → 2.0.0

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.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +1 -4
  4. data/.travis.yml +3 -5
  5. data/Gemfile +6 -2
  6. data/examples/negotiate.rb +51 -8
  7. data/examples/read_file_encryption.rb +56 -0
  8. data/lib/ruby_smb.rb +4 -0
  9. data/lib/ruby_smb/client.rb +172 -16
  10. data/lib/ruby_smb/client/authentication.rb +27 -8
  11. data/lib/ruby_smb/client/encryption.rb +62 -0
  12. data/lib/ruby_smb/client/negotiation.rb +133 -12
  13. data/lib/ruby_smb/client/signing.rb +19 -0
  14. data/lib/ruby_smb/client/tree_connect.rb +4 -4
  15. data/lib/ruby_smb/client/utils.rb +8 -7
  16. data/lib/ruby_smb/crypto.rb +30 -0
  17. data/lib/ruby_smb/dispatcher/socket.rb +2 -2
  18. data/lib/ruby_smb/error.rb +28 -1
  19. data/lib/ruby_smb/smb1/commands.rb +1 -1
  20. data/lib/ruby_smb/smb1/file.rb +4 -4
  21. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +1 -1
  22. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -2
  23. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  24. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -2
  25. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +1 -1
  26. data/lib/ruby_smb/smb1/pipe.rb +2 -2
  27. data/lib/ruby_smb/smb1/tree.rb +3 -3
  28. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  29. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  30. data/lib/ruby_smb/smb2/file.rb +25 -43
  31. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  32. data/lib/ruby_smb/smb2/packet.rb +2 -0
  33. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  34. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -14
  35. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +49 -3
  36. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  37. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +92 -6
  38. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -26
  39. data/lib/ruby_smb/smb2/pipe.rb +3 -16
  40. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  41. data/lib/ruby_smb/smb2/tree.rb +23 -17
  42. data/lib/ruby_smb/version.rb +1 -1
  43. data/ruby_smb.gemspec +3 -1
  44. data/spec/lib/ruby_smb/client_spec.rb +1256 -57
  45. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  46. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  47. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  48. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  49. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  50. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  51. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  52. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  53. data/spec/lib/ruby_smb/smb2/file_spec.rb +86 -62
  54. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  55. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  56. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  57. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  58. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  59. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  60. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -30
  61. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +0 -40
  62. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  63. data/spec/lib/ruby_smb/smb2/tree_spec.rb +53 -8
  64. metadata +124 -75
  65. metadata.gz.sig +0 -0
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Crypto::KDF do
4
+ describe '.counter_mode' do
5
+ it 'generates the expected 128-bit key' do
6
+ expected_key = "\x3c\x5e\x0a\x1b\x0a\xce\xa5\xb2\x64\x3f\xab\x78\xdc\x82\x31\x3b".b
7
+ expect(described_class.counter_mode('ki', 'label', 'context')).to eq(expected_key)
8
+ end
9
+
10
+ it 'generates the expected 256-bit key' do
11
+ expected_key =
12
+ "\x33\x4d\xa9\x6d\x24\x7e\xcb\x14\xf6\x24\x00\x97\x26\x51\xd5\xb4"\
13
+ "\x54\x5f\xda\x95\xf0\x5a\xcb\x25\x92\x57\xae\x71\x1c\x37\x20\x5b".b
14
+ expect(described_class.counter_mode('ki', 'label', 'context', length: 256)).to eq(expected_key)
15
+ end
16
+
17
+ it 'raises the expected exception when an error occurs' do
18
+ allow(OpenSSL::Digest).to receive(:new).and_raise(OpenSSL::OpenSSLError)
19
+ expect { described_class.counter_mode('ki', 'label', 'context') }.to raise_error(
20
+ RubySMB::Error::EncryptionError,
21
+ "Crypto::KDF.counter_mode OpenSSL error: OpenSSL::OpenSSLError"
22
+ )
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Error::InvalidPacket do
4
+ context 'with a String' do
5
+ it 'outputs the expected error message' do
6
+ ex = described_class.new('My exception')
7
+ expect(ex.to_s).to eq('My exception')
8
+ end
9
+ end
10
+
11
+ context 'with a Hash' do
12
+ it 'outputs the expected error message' do
13
+ ex = described_class.new(
14
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
15
+ expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
16
+ expected_custom: "extended_security=1",
17
+ received_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
18
+ received_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
19
+ received_custom: "extended_security=0"
20
+ )
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)')
22
+ end
23
+ end
24
+
25
+ context 'with an unsupported type' do
26
+ it 'raises the expected exception' do
27
+ expect { described_class.new(['wrong']) }.to raise_error(
28
+ ArgumentError,
29
+ 'InvalidPacket expects a String or a Hash, got a Array'
30
+ )
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ RSpec.describe RubySMB::Error::UnexpectedStatusCode do
37
+ context 'with a WindowsError::ErrorCode' do
38
+ it 'outputs the expected error message' do
39
+ ex = described_class.new(WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW)
40
+ expect(ex.to_s).to eq('The server responded with an unexpected status code: STATUS_BUFFER_OVERFLOW')
41
+ end
42
+ end
43
+
44
+ context 'with an Integer' do
45
+ it 'outputs the expected error message' do
46
+ ex = described_class.new(0x80000005)
47
+ expect(ex.to_s).to eq('The server responded with an unexpected status code: STATUS_BUFFER_OVERFLOW')
48
+ end
49
+ end
50
+
51
+ context 'with an unsupported type' do
52
+ it 'raises the expected exception' do
53
+ expect { described_class.new(['wrong']) }.to raise_error(
54
+ ArgumentError,
55
+ 'Status code must be a WindowsError::ErrorCode or an Integer, got Array'
56
+ )
57
+ end
58
+ end
59
+ end
@@ -10,8 +10,8 @@ RSpec.describe RubySMB::SMB1::Packet::SessionSetupLegacyRequest do
10
10
  expect(header).to be_a RubySMB::SMB1::SMBHeader
11
11
  end
12
12
 
13
- it 'should have the command set to SMB_COM_NEGOTIATE' do
14
- expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
13
+ it 'should have the command set to SMB_COM_SESSION_SETUP_ANDX' do
14
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
15
15
  end
16
16
 
17
17
  it 'should not have the response flag set' do
@@ -10,8 +10,8 @@ RSpec.describe RubySMB::SMB1::Packet::SessionSetupLegacyResponse do
10
10
  expect(header).to be_a RubySMB::SMB1::SMBHeader
11
11
  end
12
12
 
13
- it 'should have the command set to SMB_COM_NEGOTIATE' do
14
- expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
13
+ it 'should have the command set to SMB_COM_SESSION_SETUP_ANDX' do
14
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
15
15
  end
16
16
 
17
17
  it 'should have the response flag set' do
@@ -10,8 +10,8 @@ RSpec.describe RubySMB::SMB1::Packet::SessionSetupRequest do
10
10
  expect(header).to be_a RubySMB::SMB1::SMBHeader
11
11
  end
12
12
 
13
- it 'should have the command set to SMB_COM_NEGOTIATE' do
14
- expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
13
+ it 'should have the command set to SMB_COM_SESSION_SETUP_ANDX' do
14
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
15
15
  end
16
16
 
17
17
  it 'should not have the response flag set' do
@@ -11,7 +11,7 @@ RSpec.describe RubySMB::SMB1::Packet::SessionSetupResponse do
11
11
  end
12
12
 
13
13
  it 'should have the command set to SMB_COM_NEGOTIATE' do
14
- expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
14
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
15
15
  end
16
16
 
17
17
  it 'should have the response flag set' do
@@ -5,6 +5,7 @@ RSpec.describe RubySMB::SMB2::BitField::SessionFlags do
5
5
 
6
6
  it { is_expected.to respond_to :guest }
7
7
  it { is_expected.to respond_to :null }
8
+ it { is_expected.to respond_to :encrypt_data }
8
9
 
9
10
  it 'is little endian' do
10
11
  expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
@@ -25,4 +26,12 @@ RSpec.describe RubySMB::SMB2::BitField::SessionFlags do
25
26
 
26
27
  it_behaves_like 'bit field with one flag set', :null, 'v', 0x00000002
27
28
  end
29
+
30
+ describe '#encrypt_data' do
31
+ it 'should be a 1-bit field per the SMB spec' do
32
+ expect(flags.encrypt_data).to be_a BinData::Bit1
33
+ end
34
+
35
+ it_behaves_like 'bit field with one flag set', :encrypt_data, 'v', 0x00000004
36
+ end
28
37
  end
@@ -1,6 +1,8 @@
1
1
  RSpec.describe RubySMB::SMB2::BitField::ShareFlags do
2
2
  subject(:flags) { described_class.new }
3
3
 
4
+ it { is_expected.to respond_to :vdo_caching }
5
+ it { is_expected.to respond_to :auto_caching }
4
6
  it { is_expected.to respond_to :dfs_root }
5
7
  it { is_expected.to respond_to :dfs }
6
8
  it { is_expected.to respond_to :encrypt }
@@ -11,11 +13,28 @@ RSpec.describe RubySMB::SMB2::BitField::ShareFlags do
11
13
  it { is_expected.to respond_to :namespace_caching }
12
14
  it { is_expected.to respond_to :shared_delete }
13
15
  it { is_expected.to respond_to :restrict_exclusive_opens }
16
+ it { is_expected.to respond_to :identity_remoting }
14
17
 
15
18
  it 'is little endian' do
16
19
  expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
17
20
  end
18
21
 
22
+ describe '#vdo_caching' do
23
+ it 'should be a 1-bit field per the SMB spec' do
24
+ expect(flags.vdo_caching).to be_a BinData::Bit1
25
+ end
26
+
27
+ it_behaves_like 'bit field with one flag set', :vdo_caching, 'V', 0x00000020
28
+ end
29
+
30
+ describe '#auto_caching' do
31
+ it 'should be a 1-bit field per the SMB spec' do
32
+ expect(flags.auto_caching).to be_a BinData::Bit1
33
+ end
34
+
35
+ it_behaves_like 'bit field with one flag set', :auto_caching, 'V', 0x00000010
36
+ end
37
+
19
38
  describe '#dfs' do
20
39
  it 'should be a 1-bit field per the SMB spec' do
21
40
  expect(flags.dfs).to be_a BinData::Bit1
@@ -96,6 +115,14 @@ RSpec.describe RubySMB::SMB2::BitField::ShareFlags do
96
115
  it_behaves_like 'bit field with one flag set', :encrypt, 'V', 0x00008000
97
116
  end
98
117
 
118
+ describe '#identity_remoting' do
119
+ it 'should be a 1-bit field per the SMB spec' do
120
+ expect(flags.identity_remoting).to be_a BinData::Bit1
121
+ end
122
+
123
+ it_behaves_like 'bit field with one flag set', :identity_remoting, 'V', 0x00040000
124
+ end
125
+
99
126
  describe '#set_manual_caching' do
100
127
  it 'turns off the caching bits' do
101
128
  flags.set_manual_caching
@@ -43,6 +43,7 @@ RSpec.describe RubySMB::SMB2::File do
43
43
  it { is_expected.to respond_to :size }
44
44
  it { is_expected.to respond_to :size_on_disk }
45
45
  it { is_expected.to respond_to :tree }
46
+ it { is_expected.to respond_to :encryption_required }
46
47
 
47
48
  it 'pulls the attributes from the response packet' do
48
49
  expect(file.attributes).to eq create_response.file_attributes
@@ -52,10 +53,18 @@ RSpec.describe RubySMB::SMB2::File do
52
53
  expect(file.guid).to eq create_response.file_id
53
54
  end
54
55
 
55
- it 'pulls the timestamps from the response packet' do
56
+ it 'pulls the last access timestamps from the response packet' do
56
57
  expect(file.last_access).to eq create_response.last_access.to_datetime
57
58
  end
58
59
 
60
+ it 'pulls the last change timestamps from the response packet' do
61
+ expect(file.last_change).to eq create_response.last_change.to_datetime
62
+ end
63
+
64
+ it 'pulls the last write timestamps from the response packet' do
65
+ expect(file.last_write).to eq create_response.last_write.to_datetime
66
+ end
67
+
59
68
  it 'pulls the size from the response packet' do
60
69
  expect(file.size).to eq create_response.end_of_file
61
70
  end
@@ -64,6 +73,10 @@ RSpec.describe RubySMB::SMB2::File do
64
73
  expect(file.size_on_disk).to eq create_response.allocation_size
65
74
  end
66
75
 
76
+ it 'sets the encryption_required flag to false by default' do
77
+ expect(file.encryption_required).to be false
78
+ end
79
+
67
80
  describe '#set_header_fields' do
68
81
  let(:request) { RubySMB::SMB2::Packet::ReadRequest.new }
69
82
  it 'calls the set_header_field method from the Tree' do
@@ -113,11 +126,17 @@ RSpec.describe RubySMB::SMB2::File do
113
126
 
114
127
  it 'uses a single packet to read the entire file' do
115
128
  expect(file).to receive(:read_packet).with(read_length: 108, offset: 0).and_return(small_read)
116
- expect(client).to receive(:send_recv).with(small_read).and_return 'fake data'
129
+ expect(client).to receive(:send_recv).with(small_read, encrypt: false).and_return 'fake data'
117
130
  expect(RubySMB::SMB2::Packet::ReadResponse).to receive(:read).with('fake data').and_return(small_response)
118
131
  expect(file.read).to eq 'fake data'
119
132
  end
120
133
 
134
+ it 'calls Client #send_recv with encryption set if required' do
135
+ file.encryption_required = true
136
+ expect(client).to receive(:send_recv).with(small_read, encrypt: true)
137
+ file.read
138
+ end
139
+
121
140
  context 'when the response is not valid' do
122
141
  it 'raise an InvalidPacket exception' do
123
142
  small_response.smb2_header.command = RubySMB::SMB2::Commands::LOGOFF
@@ -155,6 +174,14 @@ RSpec.describe RubySMB::SMB2::File do
155
174
  file.read(bytes: (described_class::MAX_PACKET_SIZE * 2))
156
175
  end
157
176
 
177
+ it 'calls Client #send_recv with encryption set if required' do
178
+ read_request = double('Read Request')
179
+ allow(file).to receive(:read_packet).and_return(read_request)
180
+ file.encryption_required = true
181
+ expect(client).to receive(:send_recv).twice.with(read_request, encrypt: true)
182
+ file.read(bytes: (described_class::MAX_PACKET_SIZE * 2))
183
+ end
184
+
158
185
  context 'when the second response is not valid' do
159
186
  it 'raise an InvalidPacket exception' do
160
187
  allow(file).to receive(:read_packet).with(read_length: described_class::MAX_PACKET_SIZE, offset: described_class::MAX_PACKET_SIZE) do
@@ -204,6 +231,14 @@ RSpec.describe RubySMB::SMB2::File do
204
231
  expect(client).to receive(:send_recv).once.and_return(write_response.to_binary_s)
205
232
  file.write(data: 'test')
206
233
  end
234
+
235
+ it 'calls Client #send_recv with encryption set if required' do
236
+ write_request = double('Write Request')
237
+ allow(file).to receive(:write_packet).and_return(write_request)
238
+ file.encryption_required = true
239
+ expect(client).to receive(:send_recv).once.with(write_request, encrypt: true).and_return(write_response.to_binary_s)
240
+ file.write(data: 'test')
241
+ end
207
242
  end
208
243
 
209
244
  context 'for a large write' do
@@ -211,6 +246,14 @@ RSpec.describe RubySMB::SMB2::File do
211
246
  expect(client).to receive(:send_recv).twice.and_return(write_response.to_binary_s)
212
247
  file.write(data: SecureRandom.random_bytes(described_class::MAX_PACKET_SIZE + 1))
213
248
  end
249
+
250
+ it 'calls Client #send_recv with encryption set if required' do
251
+ write_request = double('Write Request')
252
+ allow(file).to receive(:write_packet).and_return(write_request)
253
+ file.encryption_required = true
254
+ expect(client).to receive(:send_recv).twice.with(write_request, encrypt: true).and_return(write_response.to_binary_s)
255
+ file.write(data: SecureRandom.random_bytes(described_class::MAX_PACKET_SIZE + 1))
256
+ end
214
257
  end
215
258
 
216
259
  it 'raises an InvalidPacket exception if the response is not valid' do
@@ -248,7 +291,7 @@ RSpec.describe RubySMB::SMB2::File do
248
291
 
249
292
  it 'uses a single packet to delete the entire file' do
250
293
  expect(file).to receive(:delete_packet).and_return(small_delete)
251
- expect(client).to receive(:send_recv).with(small_delete).and_return 'raw_response'
294
+ expect(client).to receive(:send_recv).with(small_delete, encrypt: false).and_return 'raw_response'
252
295
  expect(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).with('raw_response').and_return(small_response)
253
296
  expect(file.delete).to eq WindowsError::NTStatus::STATUS_SUCCESS
254
297
  end
@@ -260,6 +303,14 @@ RSpec.describe RubySMB::SMB2::File do
260
303
  allow(small_response).to receive(:valid?).and_return(false)
261
304
  expect { file.delete }.to raise_error(RubySMB::Error::InvalidPacket)
262
305
  end
306
+
307
+ it 'calls Client #send_recv with encryption set if required' do
308
+ allow(file).to receive(:delete_packet)
309
+ allow(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).and_return(small_response)
310
+ file.encryption_required = true
311
+ expect(client).to receive(:send_recv).with(small_delete, encrypt: true)
312
+ file.delete
313
+ end
263
314
  end
264
315
  end
265
316
 
@@ -291,11 +342,18 @@ RSpec.describe RubySMB::SMB2::File do
291
342
 
292
343
  it 'uses a single packet to rename the entire file' do
293
344
  expect(file).to receive(:rename_packet).and_return(small_rename)
294
- expect(client).to receive(:send_recv).with(small_rename).and_return 'raw_response'
345
+ expect(client).to receive(:send_recv).with(small_rename, encrypt: false).and_return 'raw_response'
295
346
  expect(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).with('raw_response').and_return(small_response)
296
347
  expect(file.rename('new_file.txt')).to eq WindowsError::NTStatus::STATUS_SUCCESS
297
348
  end
298
349
 
350
+ it 'calls Client #send_recv with encryption set if required' do
351
+ allow(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).and_return(small_response)
352
+ file.encryption_required = true
353
+ expect(client).to receive(:send_recv).with(small_rename, encrypt: true)
354
+ file.rename('new_file.txt')
355
+ end
356
+
299
357
  it 'raises an InvalidPacket exception if the response is not valid' do
300
358
  allow(client).to receive(:send_recv)
301
359
  allow(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).and_return(small_response)
@@ -330,7 +388,13 @@ RSpec.describe RubySMB::SMB2::File do
330
388
  end
331
389
 
332
390
  it 'calls Client #send_recv with the expected request' do
333
- expect(client).to receive(:send_recv).with(request)
391
+ expect(client).to receive(:send_recv).with(request, encrypt: false)
392
+ file.close
393
+ end
394
+
395
+ it 'calls Client #send_recv with encryption set if required' do
396
+ file.encryption_required = true
397
+ expect(client).to receive(:send_recv).with(request, encrypt: true)
334
398
  file.close
335
399
  end
336
400
 
@@ -394,7 +458,15 @@ RSpec.describe RubySMB::SMB2::File do
394
458
  it 'calls Client #send_recv with the expected request' do
395
459
  request = double('Request')
396
460
  allow(file).to receive(:read_packet).and_return(request)
397
- expect(client).to receive(:send_recv).with(request)
461
+ expect(client).to receive(:send_recv).with(request, encrypt: false)
462
+ file.send_recv_read
463
+ end
464
+
465
+ it 'calls Client #send_recv with encryption set if required' do
466
+ request = double('Request')
467
+ allow(file).to receive(:read_packet).and_return(request)
468
+ file.encryption_required = true
469
+ expect(client).to receive(:send_recv).with(request, encrypt: true)
398
470
  file.send_recv_read
399
471
  end
400
472
 
@@ -408,33 +480,6 @@ RSpec.describe RubySMB::SMB2::File do
408
480
  expect { file.send_recv_read }.to raise_error(RubySMB::Error::InvalidPacket)
409
481
  end
410
482
 
411
- context 'when the response status code is STATUS_PENDING' do
412
- before :example do
413
- allow(file).to receive(:sleep)
414
- allow(read_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_PENDING)
415
- allow(dispatcher).to receive(:recv_packet).and_return(raw_response)
416
- end
417
-
418
- it 'wait 1 second and calls Client dispatcher #recv_packet method one more time' do
419
- expect(file).to receive(:sleep).with(1)
420
- expect(dispatcher).to receive(:recv_packet)
421
- file.send_recv_read
422
- end
423
-
424
- it 'parses the response as a SMB2 ReadResponse packet' do
425
- expect(RubySMB::SMB2::Packet::ReadResponse).to receive(:read).twice.with(raw_response)
426
- file.send_recv_read
427
- end
428
-
429
- it 'raises an InvalidPacket exception if the response is not valid' do
430
- allow(dispatcher).to receive(:recv_packet) do
431
- allow(read_response).to receive(:valid?).and_return(false)
432
- raw_response
433
- end
434
- expect { file.send_recv_read }.to raise_error(RubySMB::Error::InvalidPacket)
435
- end
436
- end
437
-
438
483
  it 'raises an UnexpectedStatusCode exception if the response status code is not STATUS_SUCCESS' do
439
484
  allow(read_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND)
440
485
  expect { file.send_recv_read }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
@@ -457,7 +502,7 @@ RSpec.describe RubySMB::SMB2::File do
457
502
 
458
503
  before :example do
459
504
  allow(file).to receive(:write_packet).and_return(request)
460
- allow(client).to receive(:send_recv).and_return(raw_response)
505
+ allow(client).to receive(:send_recv).and_return(raw_response, encrypt: false)
461
506
  allow(RubySMB::SMB2::Packet::WriteResponse).to receive(:read).with(raw_response).and_return(write_response)
462
507
  end
463
508
 
@@ -478,40 +523,19 @@ RSpec.describe RubySMB::SMB2::File do
478
523
  end
479
524
 
480
525
  it 'calls Client #send_recv with the expected request' do
481
- expect(client).to receive(:send_recv).with(request)
526
+ expect(client).to receive(:send_recv).with(request, encrypt: false)
482
527
  file.send_recv_write
483
528
  end
484
529
 
485
- it 'parses the response as a SMB1 WriteResponse packet' do
486
- expect(RubySMB::SMB2::Packet::WriteResponse).to receive(:read).with(raw_response)
530
+ it 'calls Client #send_recv with encryption set if required' do
531
+ file.encryption_required = true
532
+ expect(client).to receive(:send_recv).with(request, encrypt: true)
487
533
  file.send_recv_write
488
534
  end
489
535
 
490
- context 'when the response status code is STATUS_PENDING' do
491
- before :example do
492
- allow(file).to receive(:sleep)
493
- allow(write_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_PENDING)
494
- allow(dispatcher).to receive(:recv_packet).and_return(raw_response)
495
- end
496
-
497
- it 'wait 1 second and calls Client dispatcher #recv_packet method one more time' do
498
- expect(file).to receive(:sleep).with(1)
499
- expect(dispatcher).to receive(:recv_packet)
500
- file.send_recv_write
501
- end
502
-
503
- it 'parses the response as a SMB2 WriteResponse packet' do
504
- expect(RubySMB::SMB2::Packet::WriteResponse).to receive(:read).twice.with(raw_response)
505
- file.send_recv_write
506
- end
507
-
508
- it 'raises an InvalidPacket exception if the response is not valid' do
509
- allow(dispatcher).to receive(:recv_packet) do
510
- allow(write_response).to receive(:valid?).and_return(false)
511
- raw_response
512
- end
513
- expect { file.send_recv_write }.to raise_error(RubySMB::Error::InvalidPacket)
514
- end
536
+ it 'parses the response as a SMB1 WriteResponse packet' do
537
+ expect(RubySMB::SMB2::Packet::WriteResponse).to receive(:read).with(raw_response)
538
+ file.send_recv_write
515
539
  end
516
540
 
517
541
  it 'raises an InvalidPacket exception if the response is not valid' do