ruby_smb 1.0.3 → 1.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 +26 -4
- data/lib/ruby_smb/client/authentication.rb +43 -25
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/negotiation.rb +27 -12
- data/lib/ruby_smb/client/tree_connect.rb +20 -14
- data/lib/ruby_smb/error.rb +40 -1
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/dcerpc.rb +7 -2
- data/lib/ruby_smb/smb1/file.rb +60 -11
- data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +7 -0
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +8 -3
- data/lib/ruby_smb/smb1/tree.rb +40 -2
- data/lib/ruby_smb/smb2/dcerpc.rb +7 -2
- data/lib/ruby_smb/smb2/file.rb +97 -1
- data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/error_packet.rb +7 -0
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
- data/lib/ruby_smb/smb2/pipe.rb +9 -9
- data/lib/ruby_smb/smb2/tree.rb +44 -6
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +123 -11
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +182 -1
- data/spec/lib/ruby_smb/smb1/packet/{error_packet_spec.rb → empty_packet_spec.rb} +21 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +63 -2
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/file_spec.rb +295 -2
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +51 -0
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +69 -3
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
- metadata +6 -4
- metadata.gz.sig +0 -0
@@ -163,7 +163,7 @@ RSpec.describe RubySMB::SMB1::File do
|
|
163
163
|
end
|
164
164
|
|
165
165
|
context 'when sending the request packet and gets a response back' do
|
166
|
-
context 'when the response is not
|
166
|
+
context 'when the response is not valid' do
|
167
167
|
it 'raise an InvalidPacket exception' do
|
168
168
|
read_andx_response.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
169
169
|
expect { file.read }.to raise_error(RubySMB::Error::InvalidPacket)
|
@@ -181,6 +181,7 @@ RSpec.describe RubySMB::SMB1::File do
|
|
181
181
|
let(:empty_packet) do
|
182
182
|
empty_packet = RubySMB::SMB1::Packet::EmptyPacket.new
|
183
183
|
empty_packet.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_READ_ANDX
|
184
|
+
empty_packet.original_command = RubySMB::SMB1::Commands::SMB_COM_READ_ANDX
|
184
185
|
empty_packet
|
185
186
|
end
|
186
187
|
|
@@ -345,6 +346,11 @@ RSpec.describe RubySMB::SMB1::File do
|
|
345
346
|
set_info_res.smb_header.nt_status = status.value
|
346
347
|
expect(file.delete).to eq status
|
347
348
|
end
|
349
|
+
|
350
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
351
|
+
allow(set_info_res).to receive(:valid?).and_return(false)
|
352
|
+
expect { file.delete }.to raise_error(RubySMB::Error::InvalidPacket)
|
353
|
+
end
|
348
354
|
end
|
349
355
|
|
350
356
|
describe '#delete_packet' do
|
@@ -415,6 +421,11 @@ RSpec.describe RubySMB::SMB1::File do
|
|
415
421
|
set_info_res.smb_header.nt_status = status.value
|
416
422
|
expect(file.rename(filename)).to eq status
|
417
423
|
end
|
424
|
+
|
425
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
426
|
+
allow(set_info_res).to receive(:valid?).and_return(false)
|
427
|
+
expect { file.rename(filename) }.to raise_error(RubySMB::Error::InvalidPacket)
|
428
|
+
end
|
418
429
|
end
|
419
430
|
|
420
431
|
describe '#rename_packet' do
|
@@ -465,5 +476,175 @@ RSpec.describe RubySMB::SMB1::File do
|
|
465
476
|
expect(parameter_block.max_data_count).to eq 16_384
|
466
477
|
end
|
467
478
|
end
|
479
|
+
|
480
|
+
describe '#close' do
|
481
|
+
let(:request) { double('CloseRequest') }
|
482
|
+
let(:response) { double('CloseResponse') }
|
483
|
+
let(:raw_response) { double('Raw response') }
|
484
|
+
|
485
|
+
before :example do
|
486
|
+
allow(RubySMB::SMB1::Packet::CloseRequest).to receive(:new).and_return(request)
|
487
|
+
allow(file).to receive(:set_header_fields).and_return(request)
|
488
|
+
allow(client).to receive(:send_recv).and_return(raw_response)
|
489
|
+
allow(RubySMB::SMB1::Packet::CloseResponse).to receive(:read).and_return(response)
|
490
|
+
allow(response).to receive(:valid?).and_return(true)
|
491
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_SUCCESS)
|
492
|
+
end
|
493
|
+
|
494
|
+
it 'creates a new SMB1 CloseRequest packet' do
|
495
|
+
expect(RubySMB::SMB1::Packet::CloseRequest).to receive(:new)
|
496
|
+
file.close
|
497
|
+
end
|
498
|
+
|
499
|
+
it 'calls Tree #set_header_fields to set SetFileInformationRequest headers' do
|
500
|
+
expect(file).to receive(:set_header_fields).with(request)
|
501
|
+
file.close
|
502
|
+
end
|
503
|
+
|
504
|
+
it 'calls Client #send_recv with the expected request' do
|
505
|
+
expect(client).to receive(:send_recv).with(request)
|
506
|
+
file.close
|
507
|
+
end
|
508
|
+
|
509
|
+
it 'parses the response as a SMB1 CloseResponse packet' do
|
510
|
+
expect(RubySMB::SMB1::Packet::CloseResponse).to receive(:read).with(raw_response)
|
511
|
+
file.close
|
512
|
+
end
|
513
|
+
|
514
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
515
|
+
allow(response).to receive(:valid?).and_return(false)
|
516
|
+
smb_header = double('SMB Header')
|
517
|
+
allow(response).to receive(:smb_header).and_return(smb_header)
|
518
|
+
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
519
|
+
expect { file.close }.to raise_error(RubySMB::Error::InvalidPacket)
|
520
|
+
end
|
521
|
+
|
522
|
+
it 'raises an UnexpectedStatusCode exception if the response status code is not STATUS_SUCCESS' do
|
523
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND)
|
524
|
+
expect { file.close }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
525
|
+
end
|
526
|
+
|
527
|
+
it 'returns the response status code' do
|
528
|
+
expect(file.close).to eq WindowsError::NTStatus::STATUS_SUCCESS
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
describe '#send_recv_read' do
|
533
|
+
let(:read_data) { 'read data' }
|
534
|
+
let(:raw_response) { double('fake raw response data') }
|
535
|
+
let(:read_andx_response) {
|
536
|
+
res = RubySMB::SMB1::Packet::ReadAndxResponse.new
|
537
|
+
res.data_block.data = read_data
|
538
|
+
res
|
539
|
+
}
|
540
|
+
|
541
|
+
before :example do
|
542
|
+
allow(client).to receive(:send_recv).and_return(raw_response)
|
543
|
+
allow(RubySMB::SMB1::Packet::ReadAndxResponse).to receive(:read).with(raw_response).and_return(read_andx_response)
|
544
|
+
end
|
545
|
+
|
546
|
+
context 'when the number of bytes to read is not provided' do
|
547
|
+
it 'reads 0 bytes by default' do
|
548
|
+
expect(file).to receive(:read_packet).with(read_length: 0, offset: 0).once.and_call_original
|
549
|
+
file.send_recv_read
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
it 'only reads the number of bytes provided as argument' do
|
554
|
+
bytes = 5
|
555
|
+
expect(file).to receive(:read_packet).with(read_length: bytes, offset: 0).once.and_call_original
|
556
|
+
file.send_recv_read(read_length: bytes)
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'reads from the offset provided as argument' do
|
560
|
+
offset = 3
|
561
|
+
expect(file).to receive(:read_packet).with(read_length: 0, offset: offset).once.and_call_original
|
562
|
+
file.send_recv_read(offset: offset)
|
563
|
+
end
|
564
|
+
|
565
|
+
it 'calls Client #send_recv with the expected request' do
|
566
|
+
request = double('Request')
|
567
|
+
allow(file).to receive(:read_packet).and_return(request)
|
568
|
+
expect(client).to receive(:send_recv).with(request)
|
569
|
+
file.send_recv_read
|
570
|
+
end
|
571
|
+
|
572
|
+
it 'parses the response as a SMB1 ReadAndxResponse packet' do
|
573
|
+
expect(RubySMB::SMB1::Packet::ReadAndxResponse).to receive(:read).with(raw_response)
|
574
|
+
file.send_recv_read
|
575
|
+
end
|
576
|
+
|
577
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
578
|
+
allow(read_andx_response).to receive(:valid?).and_return(false)
|
579
|
+
expect { file.send_recv_read }.to raise_error(RubySMB::Error::InvalidPacket)
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'raises an UnexpectedStatusCode exception if the response status code is not STATUS_SUCCESS' do
|
583
|
+
allow(read_andx_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND)
|
584
|
+
expect { file.send_recv_read }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
585
|
+
end
|
586
|
+
|
587
|
+
it 'returns the expected string' do
|
588
|
+
expect(file.send_recv_read).to eq(read_data)
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
describe '#send_recv_write' do
|
593
|
+
let(:write_data) { 'write data' }
|
594
|
+
let(:request) { double('Request') }
|
595
|
+
let(:raw_response) { double('fake raw response data') }
|
596
|
+
let(:write_andx_response) {
|
597
|
+
res = RubySMB::SMB1::Packet::WriteAndxResponse.new
|
598
|
+
res.parameter_block.count_low = write_data.size
|
599
|
+
res
|
600
|
+
}
|
601
|
+
|
602
|
+
before :example do
|
603
|
+
allow(file).to receive(:write_packet).and_return(request)
|
604
|
+
allow(request).to receive(:set_64_bit_offset)
|
605
|
+
allow(client).to receive(:send_recv).and_return(raw_response)
|
606
|
+
allow(RubySMB::SMB1::Packet::WriteAndxResponse).to receive(:read).with(raw_response).and_return(write_andx_response)
|
607
|
+
end
|
608
|
+
|
609
|
+
it 'reads 0 bytes from offset 0 by default' do
|
610
|
+
expect(file).to receive(:write_packet).with(data: '', offset: 0).once.and_call_original
|
611
|
+
file.send_recv_write
|
612
|
+
end
|
613
|
+
|
614
|
+
it 'writes the data provided as argument' do
|
615
|
+
expect(file).to receive(:write_packet).with(data: write_data, offset: 0).once.and_call_original
|
616
|
+
file.send_recv_write(data: write_data)
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'reads from the offset provided as argument' do
|
620
|
+
offset = 3
|
621
|
+
expect(file).to receive(:write_packet).with(data: '', offset: offset).once.and_call_original
|
622
|
+
file.send_recv_write(offset: offset)
|
623
|
+
end
|
624
|
+
|
625
|
+
it 'sets the 64 bit offset to true' do
|
626
|
+
expect(request).to receive(:set_64_bit_offset).with(true)
|
627
|
+
file.send_recv_write
|
628
|
+
end
|
629
|
+
|
630
|
+
it 'calls Client #send_recv with the expected request' do
|
631
|
+
expect(client).to receive(:send_recv).with(request)
|
632
|
+
file.send_recv_write
|
633
|
+
end
|
634
|
+
|
635
|
+
it 'parses the response as a SMB1 WriteAndxResponse packet' do
|
636
|
+
expect(RubySMB::SMB1::Packet::WriteAndxResponse).to receive(:read).with(raw_response)
|
637
|
+
file.send_recv_write
|
638
|
+
end
|
639
|
+
|
640
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
641
|
+
allow(write_andx_response).to receive(:valid?).and_return(false)
|
642
|
+
expect { file.send_recv_write }.to raise_error(RubySMB::Error::InvalidPacket)
|
643
|
+
end
|
644
|
+
|
645
|
+
it 'returns the expected response #count_low value' do
|
646
|
+
expect(file.send_recv_write).to eq(write_data.size)
|
647
|
+
end
|
648
|
+
end
|
468
649
|
end
|
469
650
|
|
@@ -34,4 +34,25 @@ RSpec.describe RubySMB::SMB1::Packet::EmptyPacket do
|
|
34
34
|
expect(data_block.to_binary_s).to eq "\x00\x00"
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
describe '#valid?' do
|
39
|
+
before :example do
|
40
|
+
packet.original_command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
41
|
+
packet.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns true if the packet protocol ID and header command are valid' do
|
45
|
+
expect(packet).to be_valid
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns false if the packet protocol ID is wrong' do
|
49
|
+
packet.smb_header.protocol = RubySMB::SMB2::SMB2_PROTOCOL_ID
|
50
|
+
expect(packet).to_not be_valid
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns false if the packet header command is wrong' do
|
54
|
+
packet.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_NEGOTIATE
|
55
|
+
expect(packet).to_not be_valid
|
56
|
+
end
|
57
|
+
end
|
37
58
|
end
|
@@ -80,6 +80,8 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
80
80
|
|
81
81
|
let(:names_blob) { names_array.collect(&:to_binary_s).join('') }
|
82
82
|
|
83
|
+
let(:find_info) { FindFileFullDirectoryInfo.new }
|
84
|
+
|
83
85
|
it 'returns an array of parsed FindFileFullDirectoryInfo structs' do
|
84
86
|
packet.data_block.trans2_data.buffer = names_blob
|
85
87
|
expect(packet.results(FindFileFullDirectoryInfo, unicode: false)).to eq names_array
|
@@ -87,7 +89,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
87
89
|
|
88
90
|
it 'sets the FindFileFullDirectoryInfo unicode attribute when unicode argument is true' do
|
89
91
|
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
90
|
-
find_info = FindFileFullDirectoryInfo.new
|
91
92
|
allow(FindFileFullDirectoryInfo).to receive(:new).and_return find_info
|
92
93
|
expect(find_info).to receive(:unicode=).with(true).once
|
93
94
|
packet.results(FindFileFullDirectoryInfo, unicode: true)
|
@@ -95,10 +96,18 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
95
96
|
|
96
97
|
it 'does not set the FindFileFullDirectoryInfo unicode attribute when unicode argument is false' do
|
97
98
|
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
98
|
-
find_info = FindFileFullDirectoryInfo.new
|
99
99
|
allow(FindFileFullDirectoryInfo).to receive(:new).and_return find_info
|
100
100
|
expect(find_info).to receive(:unicode=).with(false).once
|
101
101
|
packet.results(FindFileFullDirectoryInfo, unicode: false)
|
102
102
|
end
|
103
|
+
|
104
|
+
context 'when the File Information is not a valid' do
|
105
|
+
it 'raises an InvalidPacket exception' do
|
106
|
+
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
107
|
+
allow(FindFileFullDirectoryInfo).to receive(:new).and_return(find_info)
|
108
|
+
allow(find_info).to receive(:read).and_raise(IOError)
|
109
|
+
expect { packet.results(FindFileFullDirectoryInfo, unicode: false) }.to raise_error(RubySMB::Error::InvalidPacket)
|
110
|
+
end
|
111
|
+
end
|
103
112
|
end
|
104
113
|
end
|
@@ -78,6 +78,8 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
78
78
|
|
79
79
|
let(:names_blob) { names_array.collect(&:to_binary_s).join('') }
|
80
80
|
|
81
|
+
let(:find_info) { FindFileFullDirectoryInfo.new }
|
82
|
+
|
81
83
|
it 'returns an array of parsed FindFileFullDirectoryInfo structs' do
|
82
84
|
packet.data_block.trans2_data.buffer = names_blob
|
83
85
|
expect(packet.results(FindFileFullDirectoryInfo, unicode: false)).to eq names_array
|
@@ -85,7 +87,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
85
87
|
|
86
88
|
it 'sets the FindFileFullDirectoryInfo unicode attribute when unicode argument is true' do
|
87
89
|
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
88
|
-
find_info = FindFileFullDirectoryInfo.new
|
89
90
|
allow(FindFileFullDirectoryInfo).to receive(:new).and_return find_info
|
90
91
|
expect(find_info).to receive(:unicode=).with(true).once
|
91
92
|
packet.results(FindFileFullDirectoryInfo, unicode: true)
|
@@ -93,10 +94,18 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
93
94
|
|
94
95
|
it 'does not set the FindFileFullDirectoryInfo unicode attribute when unicode argument is false' do
|
95
96
|
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
96
|
-
find_info = FindFileFullDirectoryInfo.new
|
97
97
|
allow(FindFileFullDirectoryInfo).to receive(:new).and_return find_info
|
98
98
|
expect(find_info).to receive(:unicode=).with(false).once
|
99
99
|
packet.results(FindFileFullDirectoryInfo, unicode: false)
|
100
100
|
end
|
101
|
+
|
102
|
+
context 'when the File Information is not a valid' do
|
103
|
+
it 'raises an InvalidPacket exception' do
|
104
|
+
packet.data_block.trans2_data.buffer = names1.to_binary_s
|
105
|
+
allow(FindFileFullDirectoryInfo).to receive(:new).and_return(find_info)
|
106
|
+
allow(find_info).to receive(:read).and_raise(IOError)
|
107
|
+
expect { packet.results(FindFileFullDirectoryInfo, unicode: false) }.to raise_error(RubySMB::Error::InvalidPacket)
|
108
|
+
end
|
109
|
+
end
|
101
110
|
end
|
102
111
|
end
|
@@ -104,4 +104,44 @@ RSpec.describe RubySMB::SMB1::Packet::TreeConnectResponse do
|
|
104
104
|
expect(file_response.guest_access_rights).to be_a RubySMB::SMB1::BitField::FileAccessMask
|
105
105
|
end
|
106
106
|
end
|
107
|
+
|
108
|
+
describe '#access_rights' do
|
109
|
+
it 'is a DirectoryAccessMask if the Tree is a directory' do
|
110
|
+
allow(packet).to receive(:is_directory?).and_return(true)
|
111
|
+
expect(packet.access_rights).to be_a RubySMB::SMB1::BitField::DirectoryAccessMask
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is a FileAccessMask if the Tree is not a directory' do
|
115
|
+
allow(packet).to receive(:is_directory?).and_return(false)
|
116
|
+
expect(packet.access_rights).to be_a RubySMB::SMB1::BitField::FileAccessMask
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when it is not a valid FileAccessMask' do
|
120
|
+
it 'raises an InvalidBitField exception' do
|
121
|
+
allow(packet).to receive(:is_directory?).and_return(false)
|
122
|
+
allow(RubySMB::SMB1::BitField::FileAccessMask).to receive(:read).and_raise(IOError)
|
123
|
+
expect { packet.access_rights }.to raise_error(RubySMB::Error::InvalidBitField)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#guest_access_rights' do
|
129
|
+
it 'is a DirectoryAccessMask if the Tree is a directory' do
|
130
|
+
allow(packet).to receive(:is_directory?).and_return(true)
|
131
|
+
expect(packet.guest_access_rights).to be_a RubySMB::SMB1::BitField::DirectoryAccessMask
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'is a FileAccessMask if the Tree is not a directory' do
|
135
|
+
allow(packet).to receive(:is_directory?).and_return(false)
|
136
|
+
expect(packet.guest_access_rights).to be_a RubySMB::SMB1::BitField::FileAccessMask
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'when it is not a valid FileAccessMask' do
|
140
|
+
it 'raises an InvalidBitField exception' do
|
141
|
+
allow(packet).to receive(:is_directory?).and_return(false)
|
142
|
+
allow(RubySMB::SMB1::BitField::FileAccessMask).to receive(:read).and_raise(IOError)
|
143
|
+
expect { packet.guest_access_rights }.to raise_error(RubySMB::Error::InvalidBitField)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
107
147
|
end
|
@@ -37,6 +37,68 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
37
37
|
described_class.new(tree: tree, response: nt_create_andx_response, name: filename)
|
38
38
|
}
|
39
39
|
|
40
|
+
describe '#peek' do
|
41
|
+
let(:request) { RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest.new }
|
42
|
+
let(:raw_response) { double('Raw response') }
|
43
|
+
let(:response) { double('Response') }
|
44
|
+
|
45
|
+
before :example do
|
46
|
+
allow(RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest).to receive(:new).and_return(request)
|
47
|
+
allow(client).to receive(:send_recv).and_return(raw_response)
|
48
|
+
allow(RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse).to receive(:read).and_return(response)
|
49
|
+
allow(response).to receive(:valid?).and_return(true)
|
50
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_SUCCESS)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'creates a PeekNmpipeRequest'do
|
54
|
+
expect(RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest).to receive(:new)
|
55
|
+
pipe.peek
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'sets the request #fid field' do
|
59
|
+
expect(request).to receive(:fid=).with(pipe.fid)
|
60
|
+
pipe.peek
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'sets the request #max_data_count fieldto the peek_size argument' do
|
64
|
+
peek_size = 5
|
65
|
+
pipe.peek(peek_size: peek_size)
|
66
|
+
expect(request.parameter_block.max_data_count).to eq(peek_size)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'calls Tree #set_header_fields' do
|
70
|
+
expect(tree).to receive(:set_header_fields).with(request)
|
71
|
+
pipe.peek
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'calls Client #send_recv' do
|
75
|
+
expect(client).to receive(:send_recv).with(request)
|
76
|
+
pipe.peek
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'parses the response as a SMB1 PeekNmpipeResponse packet' do
|
80
|
+
expect(RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse).to receive(:read).with(raw_response)
|
81
|
+
pipe.peek
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
85
|
+
allow(response).to receive(:valid?).and_return(false)
|
86
|
+
smb_header = double('SMB Header')
|
87
|
+
allow(response).to receive(:smb_header).and_return(smb_header)
|
88
|
+
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
89
|
+
expect { pipe.peek }.to raise_error(RubySMB::Error::InvalidPacket)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'raises an UnexpectedStatusCode exception if the response status code is not STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW' do
|
93
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND)
|
94
|
+
expect { pipe.peek }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'returns the expected response' do
|
98
|
+
expect(pipe.peek).to eq(response)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
40
102
|
describe '#peek_available' do
|
41
103
|
it 'reads the correct number of bytes available' do
|
42
104
|
allow(pipe).to receive(:peek) { peek_nmpipe_response }
|
@@ -227,8 +289,7 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
227
289
|
end
|
228
290
|
|
229
291
|
it 'raises the expected exception when it is not a Trans packet' do
|
230
|
-
|
231
|
-
allow(RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse).to receive(:read).and_return(response)
|
292
|
+
nmpipe_response.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
|
232
293
|
expect { pipe.request(opnum, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
233
294
|
end
|
234
295
|
|
@@ -46,25 +46,34 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
describe '#disconnect!' do
|
49
|
-
|
49
|
+
let(:disco_response) { double('Response') }
|
50
|
+
|
51
|
+
before :example do
|
50
52
|
allow(RubySMB::SMB1::Packet::TreeDisconnectRequest).to receive(:new).and_return(disco_req)
|
51
|
-
allow(
|
53
|
+
allow(RubySMB::SMB1::Packet::TreeDisconnectResponse).to receive(:read).and_return(disco_resp)
|
54
|
+
allow(client).to receive(:send_recv)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'calls #set_header_fields' do
|
52
58
|
expect(tree).to receive(:set_header_fields).with(disco_req)
|
53
59
|
tree.disconnect!
|
54
60
|
end
|
55
61
|
|
56
62
|
it 'sends a TreeDisconnectRequest with the Tree ID in the header' do
|
57
|
-
allow(RubySMB::SMB1::Packet::TreeDisconnectRequest).to receive(:new).and_return(disco_req)
|
58
63
|
modified_req = disco_req
|
59
64
|
modified_req.smb_header.tid = tree.id
|
60
|
-
expect(client).to receive(:send_recv).with(modified_req)
|
65
|
+
expect(client).to receive(:send_recv).with(modified_req)
|
61
66
|
tree.disconnect!
|
62
67
|
end
|
63
68
|
|
64
69
|
it 'returns the NTStatus code from the response' do
|
65
|
-
allow(client).to receive(:send_recv).and_return(disco_resp.to_binary_s)
|
66
70
|
expect(tree.disconnect!).to eq disco_resp.status_code
|
67
71
|
end
|
72
|
+
|
73
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
74
|
+
allow(disco_resp).to receive(:valid?).and_return(false)
|
75
|
+
expect { tree.disconnect! }.to raise_error(RubySMB::Error::InvalidPacket)
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
70
79
|
describe '#open_file' do
|
@@ -239,14 +248,14 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
239
248
|
end
|
240
249
|
|
241
250
|
context 'when the response is not a NtCreateAndxResponse packet' do
|
242
|
-
it '
|
251
|
+
it 'raises an InvalidPacket exception' do
|
243
252
|
nt_create_andx_response.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
244
253
|
expect { tree.open_file(filename: filename) }.to raise_error(RubySMB::Error::InvalidPacket)
|
245
254
|
end
|
246
255
|
end
|
247
256
|
|
248
257
|
context 'when the response status code is not STATUS_SUCCESS' do
|
249
|
-
it '
|
258
|
+
it 'raises an UnexpectedStatusCode exception' do
|
250
259
|
nt_create_andx_response.smb_header.nt_status = WindowsError::NTStatus::STATUS_INVALID_HANDLE.value
|
251
260
|
expect { tree.open_file(filename: filename) }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
252
261
|
end
|
@@ -342,6 +351,20 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
342
351
|
expect(tree.list).to eq([file_info1, file_info2])
|
343
352
|
end
|
344
353
|
|
354
|
+
context 'when the response is not a valid Trans2 FindFirst2Response' do
|
355
|
+
it 'raises an InvalidPacket exception' do
|
356
|
+
find_first2_res.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
357
|
+
expect { tree.list }.to raise_error(RubySMB::Error::InvalidPacket)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context 'when the response status code is not STATUS_SUCCESS' do
|
362
|
+
it 'raises an UnexpectedStatusCode exception' do
|
363
|
+
find_first2_res.smb_header.nt_status = WindowsError::NTStatus::STATUS_INVALID_HANDLE.value
|
364
|
+
expect { tree.list }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
345
368
|
context 'when more requests are needed to get all the information' do
|
346
369
|
let(:find_next2_req) { RubySMB::SMB1::Packet::Trans2::FindNext2Request.new }
|
347
370
|
let(:file_info2) do
|
@@ -414,6 +437,20 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
414
437
|
it 'returns the expected FindFileFullDirectoryInfo structures' do
|
415
438
|
expect(tree.list).to eq([file_info1, file_info2])
|
416
439
|
end
|
440
|
+
|
441
|
+
context 'when the response is not a valid Trans2 FindNext2Response' do
|
442
|
+
it 'raises an InvalidPacket exception' do
|
443
|
+
find_next2_res.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
|
444
|
+
expect { tree.list }.to raise_error(RubySMB::Error::InvalidPacket)
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
context 'when the response status code is not STATUS_SUCCESS' do
|
449
|
+
it 'raises an UnexpectedStatusCode exception' do
|
450
|
+
find_next2_res.smb_header.nt_status = WindowsError::NTStatus::STATUS_INVALID_HANDLE.value
|
451
|
+
expect { tree.list }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
452
|
+
end
|
453
|
+
end
|
417
454
|
end
|
418
455
|
end
|
419
456
|
|