ruby_smb 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.travis.yml +4 -1
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/pipes.rb +2 -1
- data/examples/read_registry_key_value.rb +32 -0
- 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/client/utils.rb +2 -2
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/client.rb +28 -4
- 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/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -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/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dispatcher/socket.rb +3 -1
- data/lib/ruby_smb/error.rb +40 -1
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/file.rb +67 -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 +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 +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 +86 -5
- data/lib/ruby_smb/smb1/tree.rb +40 -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 +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 +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 +98 -11
- data/lib/ruby_smb/smb2/tree.rb +44 -6
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +0 -1
- data/ruby_smb.gemspec +3 -3
- data/spec/lib/ruby_smb/client_spec.rb +271 -11
- 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 +3 -1
- 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/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/file_spec.rb +295 -2
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -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 +322 -145
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
- data.tar.gz.sig +0 -0
- metadata +70 -11
- 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
|
@@ -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
|
|
@@ -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
|
|