ruby_smb 1.0.3 → 2.0.1
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +3 -2
- data/Gemfile +6 -2
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/negotiate.rb +51 -8
- data/examples/pipes.rb +2 -1
- data/examples/read_file_encryption.rb +56 -0
- data/examples/read_registry_key_value.rb +32 -0
- data/lib/ruby_smb.rb +4 -1
- data/lib/ruby_smb/client.rb +233 -22
- data/lib/ruby_smb/client/authentication.rb +70 -33
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/encryption.rb +62 -0
- data/lib/ruby_smb/client/negotiation.rb +172 -24
- data/lib/ruby_smb/client/signing.rb +19 -0
- data/lib/ruby_smb/client/tree_connect.rb +24 -18
- data/lib/ruby_smb/client/utils.rb +8 -7
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/crypto.rb +30 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dcerpc/bind.rb +2 -2
- data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
- data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
- data/lib/ruby_smb/dcerpc/request.rb +28 -9
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
- data/lib/ruby_smb/dispatcher/socket.rb +4 -3
- data/lib/ruby_smb/error.rb +68 -2
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +66 -15
- 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 +10 -1
- 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 +3 -2
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
- 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 +3 -6
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +87 -6
- data/lib/ruby_smb/smb1/tree.rb +50 -3
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
- data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
- data/lib/ruby_smb/smb2/file.rb +103 -25
- data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- 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/compression_transform_header.rb +41 -0
- 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 +15 -3
- 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 +51 -17
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
- 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/transform_header.rb +84 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
- 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 +86 -12
- data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
- data/lib/ruby_smb/smb2/tree.rb +65 -21
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +1612 -108
- data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
- data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
- data/spec/lib/ruby_smb/error_spec.rb +59 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
- data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
- 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 +272 -149
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
- data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
- data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
- metadata +191 -83
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
- data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::SMB1::Packet::EmptyPacket do
|
4
|
+
subject(:packet) { described_class.new }
|
5
|
+
|
6
|
+
describe '#smb_header' do
|
7
|
+
subject(:header) { packet.smb_header }
|
8
|
+
|
9
|
+
it 'is a standard SMB Header' do
|
10
|
+
expect(header).to be_a RubySMB::SMB1::SMBHeader
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#parameter_block' do
|
15
|
+
subject(:parameter_block) { packet.parameter_block }
|
16
|
+
|
17
|
+
it 'is a standard ParameterBlock' do
|
18
|
+
expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be empty' do
|
22
|
+
expect(parameter_block.to_binary_s).to eq "\x00"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#data_block' do
|
27
|
+
subject(:data_block) { packet.data_block }
|
28
|
+
|
29
|
+
it 'is a standard DataBlock' do
|
30
|
+
expect(data_block).to be_a RubySMB::SMB1::DataBlock
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should be empty' do
|
34
|
+
expect(data_block.to_binary_s).to eq "\x00\x00"
|
35
|
+
end
|
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
|
+
|
58
|
+
it 'returns false if the packet parameter block size is not 0' do
|
59
|
+
packet.parameter_block.word_count = 10
|
60
|
+
expect(packet).to_not be_valid
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns false if the packet data block size is not 0' do
|
64
|
+
packet.data_block.byte_count = 10
|
65
|
+
expect(packet).to_not be_valid
|
66
|
+
end
|
67
|
+
end
|
68
|
+
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
|
14
|
-
expect(header.command).to eq RubySMB::SMB1::Commands::
|
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
|
14
|
-
expect(header.command).to eq RubySMB::SMB1::Commands::
|
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
|
14
|
-
expect(header.command).to eq RubySMB::SMB1::Commands::
|
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::
|
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
|
@@ -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
|
@@ -1,15 +1,12 @@
|
|
1
1
|
RSpec.describe RubySMB::SMB1::Pipe do
|
2
2
|
|
3
|
+
it { expect(described_class).to be < RubySMB::SMB1::File }
|
4
|
+
|
3
5
|
let(:peek_nmpipe_response) {
|
4
6
|
packet = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.new
|
5
7
|
packet.data_block.trans_parameters.read("\x10\x20\x00\x00\x03\x00")
|
6
8
|
packet
|
7
9
|
}
|
8
|
-
|
9
|
-
describe RubySMB::SMB1::Pipe do
|
10
|
-
it { expect(described_class).to be < RubySMB::SMB1::File }
|
11
|
-
end
|
12
|
-
|
13
10
|
let(:dispatcher) { RubySMB::Dispatcher::Socket.new(double('socket')) }
|
14
11
|
let(:client) { RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin') }
|
15
12
|
let(:connect_response) {
|
@@ -37,6 +34,68 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
37
34
|
described_class.new(tree: tree, response: nt_create_andx_response, name: filename)
|
38
35
|
}
|
39
36
|
|
37
|
+
describe '#peek' do
|
38
|
+
let(:request) { RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest.new }
|
39
|
+
let(:raw_response) { double('Raw response') }
|
40
|
+
let(:response) { double('Response') }
|
41
|
+
|
42
|
+
before :example do
|
43
|
+
allow(RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest).to receive(:new).and_return(request)
|
44
|
+
allow(client).to receive(:send_recv).and_return(raw_response)
|
45
|
+
allow(RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse).to receive(:read).and_return(response)
|
46
|
+
allow(response).to receive(:valid?).and_return(true)
|
47
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_SUCCESS)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'creates a PeekNmpipeRequest'do
|
51
|
+
expect(RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest).to receive(:new)
|
52
|
+
pipe.peek
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'sets the request #fid field' do
|
56
|
+
expect(request).to receive(:fid=).with(pipe.fid)
|
57
|
+
pipe.peek
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets the request #max_data_count fieldto the peek_size argument' do
|
61
|
+
peek_size = 5
|
62
|
+
pipe.peek(peek_size: peek_size)
|
63
|
+
expect(request.parameter_block.max_data_count).to eq(peek_size)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'calls Tree #set_header_fields' do
|
67
|
+
expect(tree).to receive(:set_header_fields).with(request)
|
68
|
+
pipe.peek
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'calls Client #send_recv' do
|
72
|
+
expect(client).to receive(:send_recv).with(request)
|
73
|
+
pipe.peek
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'parses the response as a SMB1 PeekNmpipeResponse packet' do
|
77
|
+
expect(RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse).to receive(:read).with(raw_response)
|
78
|
+
pipe.peek
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'raises an InvalidPacket exception if the response is not valid' do
|
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)
|
86
|
+
expect { pipe.peek }.to raise_error(RubySMB::Error::InvalidPacket)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raises an UnexpectedStatusCode exception if the response status code is not STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW' do
|
90
|
+
allow(response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND)
|
91
|
+
expect { pipe.peek }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns the expected response' do
|
95
|
+
expect(pipe.peek).to eq(response)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
40
99
|
describe '#peek_available' do
|
41
100
|
it 'reads the correct number of bytes available' do
|
42
101
|
allow(pipe).to receive(:peek) { peek_nmpipe_response }
|
@@ -62,202 +121,266 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
62
121
|
end
|
63
122
|
end
|
64
123
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
allow(pipe).to receive(:bind)
|
72
|
-
allow(pipe).to receive(:request).and_return(dcerpc_response)
|
73
|
-
allow(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:parse_response).and_return([])
|
124
|
+
describe '#initialize' do
|
125
|
+
context 'when name is not provided' do
|
126
|
+
it 'raises an ArgumentError' do
|
127
|
+
expect {
|
128
|
+
described_class.new(tree: tree, response: nt_create_andx_response, name: nil)
|
129
|
+
}.to raise_error(ArgumentError)
|
74
130
|
end
|
131
|
+
end
|
75
132
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
133
|
+
it 'calls the superclass with the expected arguments' do
|
134
|
+
expect(pipe.tree).to eq(tree)
|
135
|
+
expect(pipe.name).to eq(filename)
|
136
|
+
expect(pipe.attributes).to eq(nt_create_andx_response.parameter_block.ext_file_attributes)
|
137
|
+
expect(pipe.fid).to eq(nt_create_andx_response.parameter_block.fid)
|
138
|
+
expect(pipe.last_access).to eq(nt_create_andx_response.parameter_block.last_access_time.to_datetime)
|
139
|
+
expect(pipe.last_change).to eq(nt_create_andx_response.parameter_block.last_change_time.to_datetime)
|
140
|
+
expect(pipe.last_write).to eq(nt_create_andx_response.parameter_block.last_write_time.to_datetime)
|
141
|
+
expect(pipe.size).to eq(nt_create_andx_response.parameter_block.end_of_file)
|
142
|
+
expect(pipe.size_on_disk).to eq(nt_create_andx_response.parameter_block.allocation_size)
|
143
|
+
end
|
80
144
|
|
81
|
-
|
82
|
-
|
83
|
-
pipe.
|
145
|
+
context 'with \'srvsvc\' filename' do
|
146
|
+
it 'extends Srvsvc class' do
|
147
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'srvsvc')
|
148
|
+
expect(pipe.respond_to?(:net_share_enum_all)).to be true
|
84
149
|
end
|
150
|
+
end
|
85
151
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
expect(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:parse_response).with(stub)
|
91
|
-
pipe.net_share_enum_all(host)
|
152
|
+
context 'with \'winreg\' filename' do
|
153
|
+
it 'extends Winreg class' do
|
154
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'winreg')
|
155
|
+
expect(pipe.respond_to?(:has_registry_key?)).to be true
|
92
156
|
end
|
157
|
+
end
|
158
|
+
end
|
93
159
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
160
|
+
describe '#dcerpc_request' do
|
161
|
+
let(:options) { { host: '1.2.3.4' } }
|
162
|
+
let(:stub_packet ) { RubySMB::Dcerpc::Winreg::OpenKeyRequest.new }
|
163
|
+
let(:dcerpc_request) { double('DCERPC Request') }
|
164
|
+
let(:request_stub) { double('Request stub') }
|
165
|
+
let(:binary_dcerpc_request) { double('Binary DCERPC Request') }
|
166
|
+
let(:trans_nmpipe_request) { double('TransactNmpipeRequest') }
|
167
|
+
let(:trans_data) { double('Trans data') }
|
168
|
+
let(:trans_nmpipe_raw_response) { double('Trans nmpipe raw response') }
|
169
|
+
let(:trans_nmpipe_response) { double('TransactNmpipeResponse') }
|
170
|
+
let(:raw_data) { double('Raw data') }
|
171
|
+
let(:dcerpc_response) { double('DCERPC Response') }
|
172
|
+
let(:result) { 'Result' }
|
173
|
+
|
174
|
+
before :example do
|
175
|
+
allow(RubySMB::Dcerpc::Request).to receive(:new).and_return(dcerpc_request)
|
176
|
+
allow(dcerpc_request).to receive_messages(
|
177
|
+
:stub => request_stub,
|
178
|
+
:to_binary_s => binary_dcerpc_request
|
179
|
+
)
|
180
|
+
allow(request_stub).to receive(:read)
|
181
|
+
allow(RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest).to receive(:new).and_return(trans_nmpipe_request)
|
182
|
+
allow(tree).to receive(:set_header_fields)
|
183
|
+
allow(trans_nmpipe_request).to receive_message_chain(:data_block, :trans_data => trans_data)
|
184
|
+
allow(trans_nmpipe_request).to receive(:set_fid)
|
185
|
+
allow(trans_data).to receive(:write_data=)
|
186
|
+
allow(client).to receive(:send_recv).and_return(trans_nmpipe_raw_response)
|
187
|
+
allow(RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse).to receive(:read).and_return(trans_nmpipe_response)
|
188
|
+
allow(trans_nmpipe_response).to receive_messages(
|
189
|
+
:valid? => true,
|
190
|
+
:status_code => WindowsError::NTStatus::STATUS_SUCCESS
|
191
|
+
)
|
192
|
+
allow(trans_nmpipe_response).to receive_message_chain(:data_block, :trans_data, :read_data, :to_binary_s => raw_data)
|
193
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_return(dcerpc_response)
|
194
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::RESPONSE)
|
195
|
+
allow(dcerpc_response).to receive(:stub).and_return(result)
|
110
196
|
end
|
111
197
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
198
|
+
it 'creates a Request packet with the expected arguments' do
|
199
|
+
pipe.dcerpc_request(stub_packet, options)
|
200
|
+
expect(options).to eq( { host: '1.2.3.4', endpoint: 'Winreg' })
|
201
|
+
expect(RubySMB::Dcerpc::Request).to have_received(:new).with({ opnum: stub_packet.opnum }, options)
|
202
|
+
end
|
116
203
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
bind_ack_packet.p_result_list.n_results = 1
|
122
|
-
bind_ack_packet.p_result_list.p_results[0].result = RubySMB::Dcerpc::BindAck::ACCEPTANCE
|
123
|
-
allow(RubySMB::Dcerpc::BindAck).to receive(:read).and_return(bind_ack_packet)
|
124
|
-
end
|
204
|
+
it 'sets DCERPC request stub to the stub packet passed as argument' do
|
205
|
+
pipe.dcerpc_request(stub_packet, options)
|
206
|
+
expect(request_stub).to have_received(:read).with(stub_packet.to_binary_s)
|
207
|
+
end
|
125
208
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
209
|
+
it 'creates a Trans TransactNmpipeRequest packet' do
|
210
|
+
pipe.dcerpc_request(stub_packet, options)
|
211
|
+
expect(RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest).to have_received(:new).with(options)
|
212
|
+
end
|
130
213
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
214
|
+
it 'calls Tree #set_header_fields' do
|
215
|
+
pipe.dcerpc_request(stub_packet, options)
|
216
|
+
expect(tree).to have_received(:set_header_fields).with(trans_nmpipe_request)
|
217
|
+
end
|
135
218
|
|
136
|
-
|
137
|
-
|
138
|
-
|
219
|
+
it 'calls TransactNmpipeRequest #set_fid' do
|
220
|
+
pipe.dcerpc_request(stub_packet, options)
|
221
|
+
expect(trans_nmpipe_request).to have_received(:set_fid).with(pipe.fid)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'sets the expected #write_data request property' do
|
225
|
+
pipe.dcerpc_request(stub_packet, options)
|
226
|
+
expect(trans_data).to have_received(:write_data=).with(binary_dcerpc_request)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'sends the expected request' do
|
230
|
+
pipe.dcerpc_request(stub_packet, options)
|
231
|
+
expect(client).to have_received(:send_recv).with(trans_nmpipe_request)
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'creates a Trans TransactNmpipeResponse packet from the response' do
|
235
|
+
pipe.dcerpc_request(stub_packet, options)
|
236
|
+
expect(RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse).to have_received(:read).with(trans_nmpipe_raw_response)
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'when the response is not a Trans packet' do
|
240
|
+
it 'raises an InvalidPacket exception' do
|
241
|
+
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :protocol)
|
242
|
+
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :command)
|
243
|
+
allow(trans_nmpipe_response).to receive(:valid?).and_return(false)
|
244
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
139
245
|
end
|
246
|
+
end
|
140
247
|
|
141
|
-
|
142
|
-
|
143
|
-
allow(
|
144
|
-
expect(
|
145
|
-
pipe.bind(options)
|
248
|
+
context 'when the response status code is not STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW' do
|
249
|
+
it 'raises an UnexpectedStatusCode exception' do
|
250
|
+
allow(trans_nmpipe_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_INVALID_HANDLE)
|
251
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
146
252
|
end
|
253
|
+
end
|
147
254
|
|
148
|
-
|
149
|
-
|
150
|
-
expect { pipe.
|
255
|
+
context 'when the response status code is STATUS_SUCCESS' do
|
256
|
+
it 'does not raise any exception' do
|
257
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.not_to raise_error
|
151
258
|
end
|
152
259
|
|
153
|
-
it '
|
154
|
-
|
155
|
-
|
156
|
-
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::BindError)
|
260
|
+
it 'creates a DCERPC Response packet from the response' do
|
261
|
+
pipe.dcerpc_request(stub_packet, options)
|
262
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data)
|
157
263
|
end
|
158
264
|
|
159
|
-
|
160
|
-
|
161
|
-
|
265
|
+
context 'when an IOError occurs while parsing the DCERPC response' do
|
266
|
+
it 'raises an InvalidPacket exception' do
|
267
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_raise(IOError)
|
268
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
269
|
+
end
|
162
270
|
end
|
163
271
|
|
164
|
-
|
165
|
-
|
166
|
-
|
272
|
+
context 'when the response is not a DCERPC Response packet' do
|
273
|
+
it 'raises an InvalidPacket exception' do
|
274
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
275
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
276
|
+
end
|
167
277
|
end
|
168
278
|
|
169
|
-
it 'returns the expected
|
170
|
-
expect(pipe.
|
279
|
+
it 'returns the expected stub data' do
|
280
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
171
281
|
end
|
172
282
|
end
|
173
283
|
|
174
|
-
|
175
|
-
let(:
|
176
|
-
let(:
|
177
|
-
let(:req_packet) { RubySMB::Dcerpc::Request.new({ :opnum => opnum }, options) }
|
178
|
-
let(:nmpipe_packet) { RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest.new(options) }
|
179
|
-
let(:nmpipe_response) { RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.new }
|
180
|
-
let(:res_packet) { RubySMB::Dcerpc::Response.new }
|
181
|
-
|
284
|
+
context 'when the response status code is STATUS_BUFFER_OVERFLOW' do
|
285
|
+
let(:data_count) { 100 }
|
286
|
+
let(:added_raw_data) { double('Added raw data') }
|
182
287
|
before :example do
|
183
|
-
allow(
|
184
|
-
allow(
|
185
|
-
allow(
|
186
|
-
allow(
|
187
|
-
allow(
|
288
|
+
allow(trans_nmpipe_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW)
|
289
|
+
allow(trans_nmpipe_response).to receive_message_chain(:parameter_block, :data_count => data_count)
|
290
|
+
allow(pipe).to receive(:read).and_return(added_raw_data)
|
291
|
+
allow(raw_data).to receive(:<<)
|
292
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :first_frag => 1)
|
293
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 1)
|
188
294
|
end
|
189
295
|
|
190
|
-
it '
|
191
|
-
expect(
|
192
|
-
pipe.request(opnum, options)
|
296
|
+
it 'does not raise any exception' do
|
297
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.not_to raise_error
|
193
298
|
end
|
194
299
|
|
195
|
-
it '
|
196
|
-
|
197
|
-
pipe.
|
300
|
+
it 'reads the expected number of bytes and concatenate it the first response raw data' do
|
301
|
+
pipe.dcerpc_request(stub_packet, options)
|
302
|
+
expect(pipe).to have_received(:read).with(bytes: tree.client.max_buffer_size - data_count)
|
303
|
+
expect(raw_data).to have_received(:<<).with(added_raw_data)
|
198
304
|
end
|
199
305
|
|
200
|
-
it '
|
201
|
-
|
202
|
-
|
306
|
+
it 'creates a DCERPC Response packet from the updated raw data' do
|
307
|
+
pipe.dcerpc_request(stub_packet, options)
|
308
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data)
|
203
309
|
end
|
204
310
|
|
205
|
-
|
206
|
-
|
207
|
-
|
311
|
+
context 'when an IOError occurs while parsing the DCERPC response' do
|
312
|
+
it 'raises an InvalidPacket exception' do
|
313
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_raise(IOError)
|
314
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
315
|
+
end
|
208
316
|
end
|
209
317
|
|
210
|
-
|
211
|
-
|
212
|
-
|
318
|
+
context 'when the response is not a DCERPC Response packet' do
|
319
|
+
it 'raises an InvalidPacket exception' do
|
320
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
321
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
213
322
|
end
|
214
|
-
pipe.request(opnum, options)
|
215
323
|
end
|
216
324
|
|
217
|
-
|
218
|
-
|
219
|
-
|
325
|
+
context 'when the response is not the first fragment' do
|
326
|
+
it 'raises an InvalidPacket exception' do
|
327
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :first_frag => 0)
|
328
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
329
|
+
end
|
220
330
|
end
|
221
331
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end
|
332
|
+
context 'when the response is the last fragment' do
|
333
|
+
it 'only reads the pipe once' do
|
334
|
+
pipe.dcerpc_request(stub_packet, options)
|
335
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).once
|
336
|
+
end
|
228
337
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
expect { pipe.request(opnum, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
338
|
+
it 'returns the expected stub data' do
|
339
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
340
|
+
end
|
233
341
|
end
|
234
342
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
343
|
+
context 'when the response is not the last fragment' do
|
344
|
+
let(:raw_data2) { double('Raw data #2') }
|
345
|
+
let(:dcerpc_response2) { double('DCERPC Response #2') }
|
346
|
+
let(:result2) { 'Result #2' }
|
347
|
+
before :example do
|
348
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 0)
|
349
|
+
allow(pipe).to receive(:read).with(bytes: tree.client.max_buffer_size).and_return(raw_data2)
|
350
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).with(raw_data2).and_return(dcerpc_response2)
|
351
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::RESPONSE)
|
352
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 1)
|
353
|
+
allow(dcerpc_response2).to receive(:stub).and_return(result2)
|
354
|
+
end
|
239
355
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
end
|
356
|
+
it 'reads the expected number of bytes' do
|
357
|
+
pipe.dcerpc_request(stub_packet, options)
|
358
|
+
expect(pipe).to have_received(:read).with(bytes: tree.client.max_buffer_size)
|
359
|
+
end
|
245
360
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
361
|
+
it 'creates a DCERPC Response packet from the new raw data' do
|
362
|
+
pipe.dcerpc_request(stub_packet, options)
|
363
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data2)
|
364
|
+
end
|
250
365
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
366
|
+
context 'when an IOError occurs while parsing the new DCERPC response' do
|
367
|
+
it 'raises an InvalidPacket exception' do
|
368
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).with(raw_data2).and_raise(IOError)
|
369
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
370
|
+
end
|
371
|
+
end
|
256
372
|
|
257
|
-
|
258
|
-
|
373
|
+
context 'when the new response is not a DCERPC Response packet' do
|
374
|
+
it 'raises an InvalidPacket exception' do
|
375
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
376
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'returns the expected stub data' do
|
381
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
382
|
+
end
|
259
383
|
end
|
260
384
|
end
|
261
385
|
end
|
262
|
-
|
263
386
|
end
|