tcell_agent 1.1.12 → 2.2.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 +5 -5
- data/bin/tcell_agent +45 -137
- data/lib/tcell_agent.rb +12 -14
- data/lib/tcell_agent/agent.rb +108 -97
- data/lib/tcell_agent/agent/route_manager.rb +0 -16
- data/lib/tcell_agent/agent/static_agent.rb +9 -30
- data/lib/tcell_agent/config_initializer.rb +66 -0
- data/lib/tcell_agent/configuration.rb +69 -345
- data/lib/tcell_agent/hooks/login_fraud.rb +30 -33
- data/lib/tcell_agent/instrument_servers.rb +23 -0
- data/lib/tcell_agent/instrumentation.rb +12 -10
- data/lib/tcell_agent/instrumentation/cmdi.rb +29 -25
- data/lib/tcell_agent/instrumentation/lfi.rb +84 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +25 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +131 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +102 -0
- data/lib/tcell_agent/logger.rb +49 -114
- data/lib/tcell_agent/patches.rb +6 -7
- data/lib/tcell_agent/policies/appfirewall_policy.rb +26 -0
- data/lib/tcell_agent/policies/command_injection_policy.rb +28 -0
- data/lib/tcell_agent/policies/dataloss_policy.rb +44 -44
- data/lib/tcell_agent/policies/headers_policy.rb +25 -0
- data/lib/tcell_agent/policies/http_redirect_policy.rb +13 -79
- data/lib/tcell_agent/policies/js_agent_policy.rb +27 -0
- data/lib/tcell_agent/policies/local_file_access.rb +28 -0
- data/lib/tcell_agent/policies/login_policy.rb +43 -0
- data/lib/tcell_agent/policies/patches_policy.rb +27 -0
- data/lib/tcell_agent/policies/policies_manager.rb +68 -0
- data/lib/tcell_agent/policies/policy_polling.rb +58 -0
- data/lib/tcell_agent/policies/policy_types.rb +14 -0
- data/lib/tcell_agent/policies/system_enablements.rb +27 -0
- data/lib/tcell_agent/rails/auth/authlogic.rb +46 -75
- data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
- data/lib/tcell_agent/rails/auth/devise.rb +100 -105
- data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
- data/lib/tcell_agent/rails/auth/doorkeeper.rb +62 -76
- data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
- data/lib/tcell_agent/rails/csrf_exception.rb +2 -10
- data/lib/tcell_agent/rails/dlp.rb +35 -23
- data/lib/tcell_agent/rails/dlp_handler.rb +1 -2
- data/lib/tcell_agent/rails/js_agent_insert.rb +12 -13
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +4 -25
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -12
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +1 -2
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +14 -34
- data/lib/tcell_agent/{rails.rb → rails/railties/tcell_agent_railties.rb} +11 -16
- data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
- data/lib/tcell_agent/rails/routes.rb +10 -12
- data/lib/tcell_agent/rails/routes/grape.rb +4 -14
- data/lib/tcell_agent/rails/routes/route_id.rb +3 -1
- data/lib/tcell_agent/rails/settings_reporter.rb +23 -36
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +5 -4
- data/lib/tcell_agent/rust/agent_config.rb +60 -0
- data/lib/tcell_agent/rust/{libtcellagent-alpine-1.3.2.so → libtcellagent-5.0.2.dylib} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-1.3.2.so → libtcellagent-5.0.2.so} +0 -0
- data/lib/tcell_agent/rust/libtcellagent-alpine-5.0.2.so +0 -0
- data/lib/tcell_agent/rust/models.rb +6 -52
- data/lib/tcell_agent/rust/native_agent.rb +549 -0
- data/lib/tcell_agent/rust/native_agent_response.rb +42 -0
- data/lib/tcell_agent/rust/native_library.rb +69 -0
- data/lib/tcell_agent/rust/tcellagent-5.0.2.dll +0 -0
- data/lib/tcell_agent/sensor_events/agent_setting_event.rb +12 -0
- data/lib/tcell_agent/sensor_events/{app_config.rb → app_config_setting_event.rb} +0 -6
- data/lib/tcell_agent/sensor_events/dlp.rb +2 -6
- data/lib/tcell_agent/sensor_events/sensor.rb +0 -62
- data/lib/tcell_agent/sensor_events/server_agent.rb +13 -18
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +0 -108
- data/lib/tcell_agent/sensor_events/util/utils.rb +0 -2
- data/lib/tcell_agent/servers/passenger.rb +1 -28
- data/lib/tcell_agent/servers/puma.rb +3 -21
- data/lib/tcell_agent/servers/rails_server.rb +1 -2
- data/lib/tcell_agent/servers/thin.rb +2 -2
- data/lib/tcell_agent/servers/unicorn.rb +19 -80
- data/lib/tcell_agent/servers/webrick.rb +1 -2
- data/lib/tcell_agent/settings_reporter.rb +11 -90
- data/lib/tcell_agent/sinatra.rb +14 -16
- data/lib/tcell_agent/tcell_context.rb +40 -14
- data/lib/tcell_agent/utils/headers.rb +14 -0
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/configuration_spec.rb +55 -346
- data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +46 -173
- data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +504 -0
- data/spec/lib/tcell_agent/instrumentation/cmdi/kernel_cmdi_spec.rb +435 -0
- data/spec/lib/tcell_agent/instrumentation/cmdi_spec.rb +201 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +326 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +562 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +264 -0
- data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +150 -0
- data/spec/lib/tcell_agent/patches_spec.rb +25 -43
- data/spec/lib/tcell_agent/policies/appfirewall_policy_spec.rb +183 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +57 -0
- data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +84 -773
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +161 -0
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +9 -9
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +243 -198
- data/spec/lib/tcell_agent/policies/js_agent_policy_spec.rb +75 -0
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +165 -33
- data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +84 -277
- data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +104 -0
- data/spec/lib/tcell_agent/policies/policy_polling_spec.rb +6 -0
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +56 -0
- data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +9 -18
- data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +13 -30
- data/spec/lib/tcell_agent/rails/logger_spec.rb +27 -7
- data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +17 -12
- data/spec/lib/tcell_agent/rails/routes/routes_spec.rb +14 -14
- data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +0 -35
- data/spec/lib/tcell_agent/settings_reporter_spec.rb +56 -155
- data/spec/spec_helper.rb +1 -1
- data/spec/support/builders.rb +103 -0
- data/spec/support/force_logger_mocking.rb +38 -0
- data/spec/support/resources/lfi_sample_file.txt +2 -0
- data/spec/support/static_agent_overrides.rb +0 -15
- metadata +72 -83
- data/lib/tcell_agent/agent/event_processor.rb +0 -326
- data/lib/tcell_agent/agent/fork_pipe_manager.rb +0 -113
- data/lib/tcell_agent/agent/policy_manager.rb +0 -219
- data/lib/tcell_agent/agent/policy_types.rb +0 -30
- data/lib/tcell_agent/api.rb +0 -91
- data/lib/tcell_agent/appsensor/injections_reporter.rb +0 -24
- data/lib/tcell_agent/authlogic.rb +0 -26
- data/lib/tcell_agent/config/child_process_events.rb +0 -8
- data/lib/tcell_agent/config/unknown_options.rb +0 -123
- data/lib/tcell_agent/devise.rb +0 -35
- data/lib/tcell_agent/instrumentation/cmdi/backtick.rb +0 -10
- data/lib/tcell_agent/instrumentation/cmdi/exec.rb +0 -14
- data/lib/tcell_agent/instrumentation/cmdi/popen.rb +0 -28
- data/lib/tcell_agent/instrumentation/cmdi/spawn.rb +0 -11
- data/lib/tcell_agent/instrumentation/cmdi/system.rb +0 -11
- data/lib/tcell_agent/policies/http_tx_policy.rb +0 -60
- data/lib/tcell_agent/policies/login_fraud_policy.rb +0 -45
- data/lib/tcell_agent/policies/rust_policies.rb +0 -110
- data/lib/tcell_agent/rails/on_start.rb +0 -41
- data/lib/tcell_agent/rust/libtcellagent-1.3.2.dylib +0 -0
- data/lib/tcell_agent/rust/tcellagent-1.3.2.dll +0 -0
- data/lib/tcell_agent/rust/whisperer.rb +0 -308
- data/lib/tcell_agent/sensor_events/appsensor_event.rb +0 -52
- data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +0 -45
- data/lib/tcell_agent/sensor_events/command_injection.rb +0 -75
- data/lib/tcell_agent/sensor_events/honeytokens.rb +0 -16
- data/lib/tcell_agent/sensor_events/login_fraud.rb +0 -60
- data/lib/tcell_agent/sensor_events/metrics.rb +0 -123
- data/lib/tcell_agent/sensor_events/patches.rb +0 -21
- data/lib/tcell_agent/start_background_thread.rb +0 -55
- data/lib/tcell_agent/system_info.rb +0 -11
- data/lib/tcell_agent/utils/io.rb +0 -38
- data/lib/tcell_agent/utils/passwords.rb +0 -28
- data/lib/tcell_agent/utils/queue_with_timeout.rb +0 -142
- data/spec/lib/tcell_agent/agent/fork_pipe_manager_spec.rb +0 -100
- data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +0 -535
- data/spec/lib/tcell_agent/agent/static_agent_spec.rb +0 -133
- data/spec/lib/tcell_agent/api/api_spec.rb +0 -39
- data/spec/lib/tcell_agent/appsensor/injections_reporter_spec.rb +0 -187
- data/spec/lib/tcell_agent/cmdi_spec.rb +0 -736
- data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -213
- data/spec/lib/tcell_agent/instrumentation_spec.rb +0 -225
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +0 -517
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +0 -22
- data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +0 -293
- data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +0 -198
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +0 -180
- data/spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb +0 -116
- data/spec/lib/tcell_agent/rust/models_spec.rb +0 -120
- data/spec/lib/tcell_agent/rust/whisperer_spec.rb +0 -704
- data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +0 -45
- data/spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb +0 -272
- data/spec/lib/tcell_agent/utils/bounded_queue_spec.rb +0 -52
- data/spec/lib/tcell_agent/utils/passwords_spec.rb +0 -143
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
|
|
4
|
+
describe 'File' do
|
|
5
|
+
before(:all) do
|
|
6
|
+
native_agent = double('native_agent')
|
|
7
|
+
@local_files_policy = TCellAgent::Policies::LocalFileInclusion.new(
|
|
8
|
+
native_agent, {}
|
|
9
|
+
)
|
|
10
|
+
@system_enablements_policy = TCellAgent::Policies::SystemEnablements.new(
|
|
11
|
+
native_agent, {}
|
|
12
|
+
)
|
|
13
|
+
@filename = get_test_resource_path('lfi_sample_file.txt')
|
|
14
|
+
@file_contents = "This is line one.\nThis is line two.\n"
|
|
15
|
+
@new_file_name = '/tmp/' + SecureRandom.uuid
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '.new' do
|
|
19
|
+
context 'empty path' do
|
|
20
|
+
it 'should raise an error' do
|
|
21
|
+
expect do
|
|
22
|
+
File.new
|
|
23
|
+
end.to raise_error(ArgumentError)
|
|
24
|
+
expect do
|
|
25
|
+
File.new(nil)
|
|
26
|
+
end.to raise_error(TypeError)
|
|
27
|
+
expect do
|
|
28
|
+
File.new('')
|
|
29
|
+
end.to raise_error(Errno::ENOENT)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
context 'with a non-existent file' do
|
|
33
|
+
context 'with a directory not blocked for read/write' do
|
|
34
|
+
before(:each) do
|
|
35
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
36
|
+
TCellAgent::PolicyTypes::LFI
|
|
37
|
+
).and_return(@local_files_policy)
|
|
38
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
39
|
+
end
|
|
40
|
+
context 'with a filename and mode r' do
|
|
41
|
+
it 'should raise an ERRNO::ENOENT error' do
|
|
42
|
+
expect do
|
|
43
|
+
File.new(@new_file_name, 'r')
|
|
44
|
+
end.to raise_error(Errno::ENOENT)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
context 'with a filename and mode w' do
|
|
48
|
+
it 'should create the file' do
|
|
49
|
+
File.new(@new_file_name, 'w')
|
|
50
|
+
|
|
51
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
52
|
+
File.delete(@new_file_name)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
context 'with a filename and write mode and file permissions 644' do
|
|
56
|
+
it 'should create the file with the correct permissions' do
|
|
57
|
+
File.new(@new_file_name, 'w', 0o644)
|
|
58
|
+
|
|
59
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
60
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
|
|
61
|
+
File.delete(@new_file_name)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
context 'with a filename and write mode and file permissions 755' do
|
|
65
|
+
it 'should create the file with the correct permissions' do
|
|
66
|
+
File.new(@new_file_name, 'w', 0o755)
|
|
67
|
+
|
|
68
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
69
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
70
|
+
File.delete(@new_file_name)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
context 'with a filename and write mode and file permissions 777' do
|
|
74
|
+
it 'should create the file with permissions 755' do
|
|
75
|
+
File.new(@new_file_name, 'w', 0o777)
|
|
76
|
+
|
|
77
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
78
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
79
|
+
File.delete(@new_file_name)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
context 'with a filename blocked for read/write' do
|
|
84
|
+
before(:each) do
|
|
85
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
86
|
+
TCellAgent::PolicyTypes::LFI
|
|
87
|
+
).and_return(@local_files_policy)
|
|
88
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
89
|
+
end
|
|
90
|
+
context 'with a filename and write mode' do
|
|
91
|
+
it 'should raise an IOError' do
|
|
92
|
+
expect do
|
|
93
|
+
File.new(@new_file_name, 'w')
|
|
94
|
+
end.to raise_error(IOError)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
context 'with a filename and write mode and file permissions 644' do
|
|
98
|
+
it 'should raise an IOError' do
|
|
99
|
+
expect do
|
|
100
|
+
File.new(@new_file_name, 'w', 644)
|
|
101
|
+
end.to raise_error(IOError)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
context 'with an existing file' do
|
|
107
|
+
context 'with a file not blocked for read/write' do
|
|
108
|
+
before(:each) do
|
|
109
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
110
|
+
TCellAgent::PolicyTypes::LFI
|
|
111
|
+
).and_return(@local_files_policy)
|
|
112
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
113
|
+
end
|
|
114
|
+
context 'with a filename' do
|
|
115
|
+
it 'should still be able to read the file' do
|
|
116
|
+
result = File.new(@filename).read
|
|
117
|
+
expect(result).to eq @file_contents
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
context 'with a filename and mode r' do
|
|
121
|
+
it 'should still be able to read the file' do
|
|
122
|
+
result = File.new(@filename, 'r').read
|
|
123
|
+
expect(result).to eq @file_contents
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
context 'with a filenname and mode w' do
|
|
127
|
+
it 'should still be able to write to a file' do
|
|
128
|
+
file = File.new('/dev/null', 'w')
|
|
129
|
+
expect(file.write('dummy message')).to eq 13
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
context 'with a filenname and mode a' do
|
|
133
|
+
it 'should still be able to write to a file' do
|
|
134
|
+
file = File.new('/dev/null', 'a')
|
|
135
|
+
expect(file.write('dummy message')).to eq 13
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
context 'with a file blocked for read/write' do
|
|
140
|
+
before(:each) do
|
|
141
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
142
|
+
TCellAgent::PolicyTypes::LFI
|
|
143
|
+
).and_return(@local_files_policy)
|
|
144
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
145
|
+
end
|
|
146
|
+
context 'with a filename' do
|
|
147
|
+
it 'should not be able to read the file' do
|
|
148
|
+
expect do
|
|
149
|
+
File.new(@filename)
|
|
150
|
+
end.to raise_error(IOError)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
context 'with a filename and mode r' do
|
|
154
|
+
it 'should not be able to read the file' do
|
|
155
|
+
expect do
|
|
156
|
+
File.new(@filename, 'r')
|
|
157
|
+
end.to raise_error(IOError)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
context 'with a filename and mode w' do
|
|
161
|
+
it 'should not be able to write to the file' do
|
|
162
|
+
expect do
|
|
163
|
+
File.new('/dev/null', 'w')
|
|
164
|
+
end.to raise_error(IOError)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe '.open' do
|
|
172
|
+
context 'empty path' do
|
|
173
|
+
it 'should raise an error' do
|
|
174
|
+
expect do
|
|
175
|
+
File.open
|
|
176
|
+
end.to raise_error(ArgumentError)
|
|
177
|
+
expect do
|
|
178
|
+
File.open(nil)
|
|
179
|
+
end.to raise_error(TypeError)
|
|
180
|
+
expect do
|
|
181
|
+
File.open('')
|
|
182
|
+
end.to raise_error(Errno::ENOENT)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
context 'with a non-existent file' do
|
|
186
|
+
before(:all) do
|
|
187
|
+
@new_file_name = '/tmp/' + SecureRandom.uuid
|
|
188
|
+
end
|
|
189
|
+
context 'with a directory not blocked for read/write' do
|
|
190
|
+
before(:each) do
|
|
191
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
192
|
+
TCellAgent::PolicyTypes::LFI
|
|
193
|
+
).and_return(@local_files_policy)
|
|
194
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
195
|
+
end
|
|
196
|
+
context 'with a filename and mode r' do
|
|
197
|
+
it 'should raise an ERRNO::ENOENT error' do
|
|
198
|
+
expect do
|
|
199
|
+
File.open(@new_file_name, 'r')
|
|
200
|
+
end.to raise_error(Errno::ENOENT)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
context 'with a filename and mode w' do
|
|
204
|
+
it 'should create the file' do
|
|
205
|
+
File.open(@new_file_name, 'w')
|
|
206
|
+
|
|
207
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
208
|
+
File.delete(@new_file_name)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
context 'with a filename and write mode and file permissions 644' do
|
|
212
|
+
it 'should create the file with the correct permissions' do
|
|
213
|
+
File.open(@new_file_name, 'w', 0o644)
|
|
214
|
+
|
|
215
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
216
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('644')
|
|
217
|
+
File.delete(@new_file_name)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
context 'with a filename and write mode and file permissions 755' do
|
|
221
|
+
it 'should create the file with the correct permissions' do
|
|
222
|
+
File.open(@new_file_name, 'w', 0o755)
|
|
223
|
+
|
|
224
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
225
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
226
|
+
File.delete(@new_file_name)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
context 'with a filename and write mode and file permissions 777' do
|
|
230
|
+
it 'should create the file with permissions 755' do
|
|
231
|
+
File.open(@new_file_name, 'w', 0o777)
|
|
232
|
+
|
|
233
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
234
|
+
expect(File.stat(@new_file_name).mode.to_s(8)[3..5]).to eq('755')
|
|
235
|
+
File.delete(@new_file_name)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
context 'with a filename blocked for read/write' do
|
|
240
|
+
before(:each) do
|
|
241
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
242
|
+
TCellAgent::PolicyTypes::LFI
|
|
243
|
+
).and_return(@local_files_policy)
|
|
244
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
245
|
+
end
|
|
246
|
+
context 'with a filename and write mode' do
|
|
247
|
+
it 'should raise an IOError' do
|
|
248
|
+
expect do
|
|
249
|
+
File.open(@new_file_name, 'w')
|
|
250
|
+
end.to raise_error(IOError)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
context 'with a filename and write mode and file permissions 644' do
|
|
254
|
+
it 'should raise an IOError' do
|
|
255
|
+
expect do
|
|
256
|
+
File.open(@new_file_name, 'w', 644)
|
|
257
|
+
end.to raise_error(IOError)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
context 'with an existing file' do
|
|
263
|
+
context 'with a file not blocked for read/write' do
|
|
264
|
+
before(:each) do
|
|
265
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
266
|
+
TCellAgent::PolicyTypes::LFI
|
|
267
|
+
).and_return(@local_files_policy)
|
|
268
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
269
|
+
end
|
|
270
|
+
context 'with a filename' do
|
|
271
|
+
it 'should still be able to read the file' do
|
|
272
|
+
result = File.open(@filename).read
|
|
273
|
+
expect(result).to eq @file_contents
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
context 'with a filename and mode r' do
|
|
277
|
+
it 'should still be able to read the file' do
|
|
278
|
+
result = File.open(@filename, 'r').read
|
|
279
|
+
expect(result).to eq @file_contents
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
context 'with a filenname and mode w' do
|
|
283
|
+
it 'should still be able to write to a file' do
|
|
284
|
+
file = File.open('/dev/null', 'w')
|
|
285
|
+
expect(file.write('dummy message')).to eq 13
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
context 'with a filenname and mode a' do
|
|
289
|
+
it 'should still be able to write to a file' do
|
|
290
|
+
file = File.open('/dev/null', 'a')
|
|
291
|
+
expect(file.write('dummy message')).to eq 13
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
context 'with a file blocked for read/write' do
|
|
296
|
+
before(:each) do
|
|
297
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
298
|
+
TCellAgent::PolicyTypes::LFI
|
|
299
|
+
).and_return(@local_files_policy)
|
|
300
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
301
|
+
end
|
|
302
|
+
context 'with a filename' do
|
|
303
|
+
it 'should not be able to read the file' do
|
|
304
|
+
expect do
|
|
305
|
+
File.open(@filename)
|
|
306
|
+
end.to raise_error(IOError)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
context 'with a filename and mode r' do
|
|
310
|
+
it 'should not be able to read the file' do
|
|
311
|
+
expect do
|
|
312
|
+
File.open(@filename, 'r')
|
|
313
|
+
end.to raise_error(IOError)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
context 'with a filename and mode w' do
|
|
317
|
+
it 'should not be able to write to the file' do
|
|
318
|
+
expect do
|
|
319
|
+
File.open('/dev/null', 'w')
|
|
320
|
+
end.to raise_error(IOError)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
|
|
4
|
+
describe 'IO' do
|
|
5
|
+
before do
|
|
6
|
+
native_agent = double('native_agent')
|
|
7
|
+
@local_files_policy = TCellAgent::Policies::LocalFileInclusion.new(
|
|
8
|
+
native_agent, {}
|
|
9
|
+
)
|
|
10
|
+
@cmdi_policy = TCellAgent::Policies::CommandInjectionPolicy.new(
|
|
11
|
+
native_agent, {}
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
before(:all) do
|
|
16
|
+
@filename = get_test_resource_path('lfi_sample_file.txt')
|
|
17
|
+
@file_contents = "This is line one.\nThis is line two.\n"
|
|
18
|
+
@file_length = @file_contents.length
|
|
19
|
+
|
|
20
|
+
@new_file_name = '/tmp/' + SecureRandom.uuid
|
|
21
|
+
@new_file_contents_offset = "This OFFSETe one.\nThis is line two.\n"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '.binread' do
|
|
25
|
+
context 'empty path' do
|
|
26
|
+
it 'should raise an error' do
|
|
27
|
+
expect do
|
|
28
|
+
IO.binread
|
|
29
|
+
end.to raise_error(ArgumentError)
|
|
30
|
+
expect do
|
|
31
|
+
IO.binread(nil)
|
|
32
|
+
end.to raise_error(TypeError)
|
|
33
|
+
expect do
|
|
34
|
+
IO.binread('')
|
|
35
|
+
end.to raise_error(Errno::ENOENT)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
context 'with a file not blocked for read/write' do
|
|
39
|
+
before do |test|
|
|
40
|
+
unless test.metadata[:skip_before]
|
|
41
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
42
|
+
TCellAgent::PolicyTypes::LFI
|
|
43
|
+
).and_return(@local_files_policy)
|
|
44
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
45
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should still be able to execute OS commands', :skip_before do
|
|
50
|
+
result = IO.binread('|echo test')
|
|
51
|
+
expect(result).to eq "test\n"
|
|
52
|
+
end
|
|
53
|
+
context 'with a filename' do
|
|
54
|
+
it 'should still be able to read file' do
|
|
55
|
+
result = IO.binread(@filename)
|
|
56
|
+
expect(result).to eq @file_contents
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
context 'with a filename and a length of 20' do
|
|
60
|
+
it 'should read 20 bytes of the file' do
|
|
61
|
+
result = IO.binread(@filename, 20)
|
|
62
|
+
expect(result).to eq @file_contents[0..19]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
context 'with a filename and a length of 20 and an offset of 5' do
|
|
66
|
+
it 'should read 20 bytes starting from the 5th byte' do
|
|
67
|
+
result = IO.binread(@filename, 20, 5)
|
|
68
|
+
expect(result).to eq @file_contents[5..24]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
context 'with a file blocked for read/write' do
|
|
73
|
+
before do |test|
|
|
74
|
+
unless test.metadata[:skip_before]
|
|
75
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
76
|
+
TCellAgent::PolicyTypes::LFI
|
|
77
|
+
).and_return(@local_files_policy)
|
|
78
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
79
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'should still be able to execute OS commands', :skip_before do
|
|
84
|
+
result = IO.binread('|echo test')
|
|
85
|
+
expect(result).to eq "test\n"
|
|
86
|
+
end
|
|
87
|
+
context 'with a filename' do
|
|
88
|
+
it 'should not be able to read the file' do
|
|
89
|
+
expect do
|
|
90
|
+
IO.binread(@filename)
|
|
91
|
+
end.to raise_error(IOError)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
context 'with a filename and a length of 20' do
|
|
95
|
+
it 'should not be able to read the file' do
|
|
96
|
+
expect do
|
|
97
|
+
IO.binread(@filename, 20)
|
|
98
|
+
end.to raise_error(IOError)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
context 'with a filename and a length of 20 and an offset of 5' do
|
|
102
|
+
it 'should not be able to read the file' do
|
|
103
|
+
expect do
|
|
104
|
+
IO.binread(@filename, 20, 5)
|
|
105
|
+
end.to raise_error(IOError)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe '.binwrite' do
|
|
112
|
+
context 'empty path' do
|
|
113
|
+
it 'should raise an error' do
|
|
114
|
+
expect do
|
|
115
|
+
IO.binwrite
|
|
116
|
+
end.to raise_error(ArgumentError)
|
|
117
|
+
expect do
|
|
118
|
+
IO.binwrite(nil)
|
|
119
|
+
end.to raise_error(ArgumentError)
|
|
120
|
+
expect do
|
|
121
|
+
IO.binwrite('')
|
|
122
|
+
end.to raise_error(ArgumentError)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
context 'with a file not blocked for read/write' do
|
|
126
|
+
before do
|
|
127
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
128
|
+
TCellAgent::PolicyTypes::LFI
|
|
129
|
+
).and_return(@local_files_policy)
|
|
130
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context 'with a nonexistent filename and string' do
|
|
134
|
+
it 'should create the file' do
|
|
135
|
+
IO.binwrite(@new_file_name, '')
|
|
136
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
137
|
+
File.delete(@new_file_name)
|
|
138
|
+
end
|
|
139
|
+
it 'should write to the file' do
|
|
140
|
+
expect(IO.binwrite(@new_file_name, @file_contents)).to eq @file_length
|
|
141
|
+
File.delete(@new_file_name)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
context 'with a nonexistent filename and string and offset' do
|
|
145
|
+
it 'should write to the file at the offset value 5' do
|
|
146
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
147
|
+
TCellAgent::PolicyTypes::LFI
|
|
148
|
+
).and_return(@local_files_policy, @local_files_policy)
|
|
149
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false, false)
|
|
150
|
+
|
|
151
|
+
IO.binwrite(@new_file_name, @file_contents)
|
|
152
|
+
IO.binwrite(@new_file_name, 'OFFSET', 5)
|
|
153
|
+
expect(IO.binread(@new_file_name)).to eq @new_file_contents_offset
|
|
154
|
+
File.delete(@new_file_name)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
context 'with a file blocked for read or write' do
|
|
159
|
+
before do
|
|
160
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
161
|
+
TCellAgent::PolicyTypes::LFI
|
|
162
|
+
).and_return(@local_files_policy)
|
|
163
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context 'with a nonexistent filename and a string' do
|
|
167
|
+
it 'should not be able to write to the file' do
|
|
168
|
+
expect do
|
|
169
|
+
IO.binwrite(@new_file_name, @file_contents)
|
|
170
|
+
end.to raise_error(IOError)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
context 'with a nonexistent filename and a string and an offset' do
|
|
174
|
+
it 'should not be able to write to the file' do
|
|
175
|
+
expect do
|
|
176
|
+
IO.binwrite(@new_file_name, @file_contents)
|
|
177
|
+
end.to raise_error(IOError)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
describe '.foreach' do
|
|
184
|
+
context 'empty path' do
|
|
185
|
+
it 'should raise an error' do
|
|
186
|
+
expect do
|
|
187
|
+
IO.foreach('') { pass }
|
|
188
|
+
end.to raise_error(Errno::ENOENT)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
context 'with a file not blocked for read/write' do
|
|
192
|
+
before do
|
|
193
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
194
|
+
TCellAgent::PolicyTypes::LFI
|
|
195
|
+
).and_return(@local_files_policy)
|
|
196
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context 'with a filename' do
|
|
200
|
+
it 'should be able to read the file' do
|
|
201
|
+
result = ''
|
|
202
|
+
IO.foreach(@filename) { |line| result << line }
|
|
203
|
+
expect(result).to eq @file_contents
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
context 'with a filename and a limit 16' do
|
|
207
|
+
it 'should split each line to a max length of 16' do
|
|
208
|
+
result = ''
|
|
209
|
+
IO.foreach(@filename, 16) { |line| result << line }
|
|
210
|
+
expect(result).to eq @file_contents
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
context 'with a filename and sep' do
|
|
214
|
+
# TODO: no documentation on how to use sep
|
|
215
|
+
end
|
|
216
|
+
context 'with a filename and sep and limit' do
|
|
217
|
+
# TODO: no documentation on how to use sep and limit
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
context 'with a file blocked for read or write' do
|
|
221
|
+
before do
|
|
222
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
223
|
+
TCellAgent::PolicyTypes::LFI
|
|
224
|
+
).and_return(@local_files_policy)
|
|
225
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
context 'with a filename' do
|
|
229
|
+
it 'should not be able to read the file' do
|
|
230
|
+
expect do
|
|
231
|
+
result = ''
|
|
232
|
+
IO.foreach(@filename) { |line| result << line }
|
|
233
|
+
expect(result).to eq @file_contents
|
|
234
|
+
end.to raise_error(IOError)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
describe '.read' do
|
|
241
|
+
context 'empty path' do
|
|
242
|
+
it 'should raise an error' do
|
|
243
|
+
expect do
|
|
244
|
+
IO.read
|
|
245
|
+
end.to raise_error(ArgumentError)
|
|
246
|
+
expect do
|
|
247
|
+
IO.read('')
|
|
248
|
+
end.to raise_error(Errno::ENOENT)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
context 'with a file not blocked for read/write' do
|
|
252
|
+
before do |test|
|
|
253
|
+
unless test.metadata[:skip_before]
|
|
254
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
255
|
+
TCellAgent::PolicyTypes::LFI
|
|
256
|
+
).and_return(@local_files_policy)
|
|
257
|
+
|
|
258
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
259
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it 'should still be able to execute OS commands', :skip_before do
|
|
264
|
+
result = IO.read('|echo test')
|
|
265
|
+
expect(result).to eq "test\n"
|
|
266
|
+
end
|
|
267
|
+
context 'with a filename' do
|
|
268
|
+
it 'should read the file' do
|
|
269
|
+
result = IO.read(@filename)
|
|
270
|
+
expect(result).to eq @file_contents
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
context 'with a filename and a length of 20' do
|
|
274
|
+
it 'should read 20 bytes of the file' do
|
|
275
|
+
result = IO.read(@filename, 20)
|
|
276
|
+
expect(result).to eq @file_contents[0..19]
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
context 'with a filename and a length of 20 and an offset of 5' do
|
|
280
|
+
it 'should read 20 bytes starting from the 5th byte' do
|
|
281
|
+
result = IO.read(@filename, 20, 5)
|
|
282
|
+
expect(result).to eq @file_contents[5..24]
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
context 'with a file blocked for read/write' do
|
|
287
|
+
before do |test|
|
|
288
|
+
unless test.metadata[:skip_before]
|
|
289
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
290
|
+
TCellAgent::PolicyTypes::LFI
|
|
291
|
+
).and_return(@local_files_policy)
|
|
292
|
+
|
|
293
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
294
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
it 'should still be able to execute OS commands', :skip_before do
|
|
299
|
+
result = IO.read('|echo test')
|
|
300
|
+
expect(result).to eq "test\n"
|
|
301
|
+
end
|
|
302
|
+
context 'with a filename' do
|
|
303
|
+
it 'should not be able to read the file' do
|
|
304
|
+
expect do
|
|
305
|
+
IO.read(@filename)
|
|
306
|
+
end.to raise_error(IOError)
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
context 'with a filename and a length 20' do
|
|
310
|
+
it 'should not be able to read the file' do
|
|
311
|
+
expect do
|
|
312
|
+
IO.read(@filename, 20)
|
|
313
|
+
end.to raise_error(IOError)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
context 'with a filename and a length and an offset 5' do
|
|
317
|
+
it 'should not be able to read the file' do
|
|
318
|
+
expect do
|
|
319
|
+
IO.read(@filename, 20, 5)
|
|
320
|
+
end.to raise_error(IOError)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
describe '.readlines' do
|
|
327
|
+
context 'empty path' do
|
|
328
|
+
it 'should raise an error' do
|
|
329
|
+
expect do
|
|
330
|
+
IO.readlines
|
|
331
|
+
end.to raise_error(ArgumentError)
|
|
332
|
+
expect do
|
|
333
|
+
IO.readlines('')
|
|
334
|
+
end.to raise_error(Errno::ENOENT)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
context 'with a file not blocked for read/write' do
|
|
338
|
+
before do |test|
|
|
339
|
+
unless test.metadata[:skip_before]
|
|
340
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
341
|
+
TCellAgent::PolicyTypes::LFI
|
|
342
|
+
).and_return(@local_files_policy)
|
|
343
|
+
|
|
344
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
345
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context 'with a filename' do
|
|
350
|
+
it 'should read the file' do
|
|
351
|
+
result = IO.readlines(@filename)
|
|
352
|
+
expect(result[0] + result[1]).to eq @file_contents
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
context 'with a filename and a limit 20' do
|
|
356
|
+
it 'should read 20 bytes of the file' do
|
|
357
|
+
exp_result = ['This ', 'is li', 'ne on', "e.\n", 'This ', 'is li', 'ne tw', "o.\n"]
|
|
358
|
+
result = IO.readlines(@filename, 5)
|
|
359
|
+
expect(result).to eq exp_result
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
context 'with a filename and a limit of 20 and sep' do
|
|
363
|
+
# TODO
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
context 'with a file blocked for read/write' do
|
|
367
|
+
before do |test|
|
|
368
|
+
unless test.metadata[:skip_before]
|
|
369
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
370
|
+
TCellAgent::PolicyTypes::LFI
|
|
371
|
+
).and_return(@local_files_policy)
|
|
372
|
+
|
|
373
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
374
|
+
expect(TCellAgent::Cmdi).not_to receive(:parse_command_from_open)
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it 'should still be able to execute OS commands', :skip_before do
|
|
379
|
+
result = IO.readlines('|echo test')[0]
|
|
380
|
+
expect(result).to eq "test\n"
|
|
381
|
+
end
|
|
382
|
+
context 'with a filename' do
|
|
383
|
+
it 'should not be able to read the file' do
|
|
384
|
+
expect do
|
|
385
|
+
IO.readlines(@filename)
|
|
386
|
+
end.to raise_error(IOError)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
describe '.sysopen' do
|
|
393
|
+
context 'empty path' do
|
|
394
|
+
it 'should raise an error' do
|
|
395
|
+
expect do
|
|
396
|
+
IO.sysopen
|
|
397
|
+
end.to raise_error(ArgumentError)
|
|
398
|
+
expect do
|
|
399
|
+
IO.sysopen(nil)
|
|
400
|
+
end.to raise_error(TypeError)
|
|
401
|
+
expect do
|
|
402
|
+
IO.sysopen('')
|
|
403
|
+
end.to raise_error(Errno::ENOENT)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
context 'with a nonexistent file' do
|
|
407
|
+
context 'with mode r' do
|
|
408
|
+
it 'should raise an error' do
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
context 'with mode w' do
|
|
412
|
+
it 'should return an integer' do
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
context 'with a file not blocked for read/write' do
|
|
417
|
+
before do
|
|
418
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
419
|
+
TCellAgent::PolicyTypes::LFI
|
|
420
|
+
).and_return(@local_files_policy)
|
|
421
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
context 'with a filename' do
|
|
425
|
+
it 'should return an integer' do
|
|
426
|
+
fd = IO.sysopen(@filename)
|
|
427
|
+
expect(fd).to be_a(Integer)
|
|
428
|
+
end
|
|
429
|
+
it 'should open the file for read' do
|
|
430
|
+
fd = IO.sysopen(@filename)
|
|
431
|
+
expect(IO.new(fd).read).to eq @file_contents
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
context 'with a filename and mode w' do
|
|
435
|
+
it 'should return an integer' do
|
|
436
|
+
fd = IO.sysopen(@new_file_name, 'w')
|
|
437
|
+
expect(fd).to be_a(Integer)
|
|
438
|
+
end
|
|
439
|
+
it 'should open the file for write' do
|
|
440
|
+
fd = IO.sysopen(@new_file_name, 'w')
|
|
441
|
+
file = IO.new(fd, 'w')
|
|
442
|
+
file.puts @file_contents
|
|
443
|
+
file.rewind
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
context 'with a file blocked for read/write' do
|
|
448
|
+
before do
|
|
449
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
450
|
+
TCellAgent::PolicyTypes::LFI
|
|
451
|
+
).and_return(@local_files_policy)
|
|
452
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
context 'with a filename' do
|
|
456
|
+
it 'should not be able to open the file for read' do
|
|
457
|
+
expect do
|
|
458
|
+
IO.sysopen(@filename)
|
|
459
|
+
end.to raise_error(IOError)
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
context 'with a filename and mode' do
|
|
463
|
+
it 'should not be able to open the file for read' do
|
|
464
|
+
expect do
|
|
465
|
+
IO.sysopen(@filename, 'r')
|
|
466
|
+
end.to raise_error(IOError)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
describe '.write' do
|
|
473
|
+
context 'empty path' do
|
|
474
|
+
it 'should raise an error' do
|
|
475
|
+
expect do
|
|
476
|
+
IO.write
|
|
477
|
+
end.to raise_error(ArgumentError)
|
|
478
|
+
expect do
|
|
479
|
+
IO.write(nil)
|
|
480
|
+
end.to raise_error(ArgumentError)
|
|
481
|
+
expect do
|
|
482
|
+
IO.write('')
|
|
483
|
+
end.to raise_error(ArgumentError)
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
context 'with a file not blocked for read/write' do
|
|
487
|
+
before do
|
|
488
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
489
|
+
TCellAgent::PolicyTypes::LFI
|
|
490
|
+
).and_return(@local_files_policy)
|
|
491
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
context 'with a filename that doe not exist' do
|
|
495
|
+
it 'should create the file' do
|
|
496
|
+
IO.write(@new_file_name, @file_contents)
|
|
497
|
+
expect(File.exist?(@new_file_name)).to be_truthy
|
|
498
|
+
File.delete(@new_file_name)
|
|
499
|
+
end
|
|
500
|
+
it 'should write to the file' do
|
|
501
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
502
|
+
TCellAgent::PolicyTypes::LFI
|
|
503
|
+
).and_return(@local_files_policy)
|
|
504
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
505
|
+
|
|
506
|
+
IO.write(@new_file_name, @file_contents)
|
|
507
|
+
expect(IO.read(@new_file_name)).to eq @file_contents
|
|
508
|
+
File.delete(@new_file_name)
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
context 'with a filename that does exist' do
|
|
512
|
+
it 'should overwrite the file' do
|
|
513
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
514
|
+
TCellAgent::PolicyTypes::LFI
|
|
515
|
+
).and_return(@local_files_policy)
|
|
516
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false)
|
|
517
|
+
|
|
518
|
+
IO.write(@new_file_name, @file_contents)
|
|
519
|
+
expect(IO.read(@new_file_name)).to eq @file_contents
|
|
520
|
+
File.delete(@new_file_name)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
context 'with a filename that does exist and an offset 5' do
|
|
524
|
+
it 'should overwrite the file starting at the offset value' do
|
|
525
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
526
|
+
TCellAgent::PolicyTypes::LFI
|
|
527
|
+
).and_return(@local_files_policy, @local_files_policy)
|
|
528
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(false, false)
|
|
529
|
+
|
|
530
|
+
exp_results = @file_contents.dup
|
|
531
|
+
exp_results[1..6] = 'OFFSET'
|
|
532
|
+
IO.write(@new_file_name, @file_contents)
|
|
533
|
+
IO.write(@new_file_name, 'OFFSET', 1)
|
|
534
|
+
expect(IO.read(@new_file_name)).to eq exp_results
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
context 'with a file blocked for read/write' do
|
|
539
|
+
before do
|
|
540
|
+
expect(TCellAgent).to receive(:policy).with(
|
|
541
|
+
TCellAgent::PolicyTypes::LFI
|
|
542
|
+
).and_return(@local_files_policy)
|
|
543
|
+
expect(@local_files_policy).to receive(:block_file_access?).and_return(true)
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
context 'with a filename that does not exist' do
|
|
547
|
+
it 'should not be able to write to the file' do
|
|
548
|
+
expect do
|
|
549
|
+
IO.write(@new_file_name, '')
|
|
550
|
+
end.to raise_error(IOError)
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
context 'with a filename that does exist' do
|
|
554
|
+
it 'should not be able to write to the file' do
|
|
555
|
+
expect do
|
|
556
|
+
IO.write(@filename, @file_contents)
|
|
557
|
+
end.to raise_error(IOError)
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
end
|