Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: mojo/shell/capability_filter_unittest.cc

Issue 1244233002: Allow trusted brokers to restrict connections for spawned applications to whitelisted applications … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
sky 2015/07/22 15:57:45 2015
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/at_exit.h"
6 #include "base/bind.h"
7 #include "base/macros.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "mojo/application/public/cpp/application_connection.h"
11 #include "mojo/application/public/cpp/application_delegate.h"
12 #include "mojo/application/public/cpp/application_impl.h"
13 #include "mojo/application/public/cpp/connect.h"
14 #include "mojo/application/public/cpp/interface_factory.h"
15 #include "mojo/common/weak_binding_set.h"
16 #include "mojo/public/cpp/bindings/strong_binding.h"
17 #include "mojo/shell/application_loader.h"
18 #include "mojo/shell/application_manager.h"
19 #include "mojo/shell/test.mojom.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace mojo {
23 namespace shell {
24 namespace {
25
26 // Quits |loop| when either:
27 // - all of the |valid_calls| are received, or
28 // - one of the |invalid_calls| is received.
29 class CallValidator {
30 public:
31 CallValidator(base::MessageLoop* loop,
32 const std::set<std::string>& valid_calls,
33 const std::set<std::string>& invalid_calls)
34 : loop_(loop),
35 valid_calls_(valid_calls),
36 invalid_calls_(invalid_calls) {
37 }
38
39 static std::string FormatCall(const std::string& function,
40 const std::string& service_url,
41 const std::string& remote_url) {
42 return base::StringPrintf("%s %s %s", function.c_str(), service_url.c_str(),
43 remote_url.c_str());
44 }
45
46 void Call(const std::string& function,
47 const std::string& service_url,
48 const std::string& remote_url) {
49 std::string call = FormatCall(function, service_url, remote_url);
50 {
51 auto i = invalid_calls_.find(call);
52 if (i != invalid_calls_.end()) {
53 loop_->Quit();
54 return;
55 }
56 }
57
58 {
59 auto i = valid_calls_.find(call);
60 if (i != valid_calls_.end())
61 valid_calls_.erase(i);
62 if (valid_calls_.empty())
63 loop_->Quit();
64 }
65 }
66
67 bool called_all_valid() const { return valid_calls_.empty(); }
68
69 private:
70 base::MessageLoop* loop_;
71 std::set<std::string> valid_calls_;
72 std::set<std::string> invalid_calls_;
73
74 DISALLOW_COPY_AND_ASSIGN(CallValidator);
75 };
76
77 // This class models an application who will use the shell to interact with a
78 // system service. The shell may limit this application's visibility of the full
79 // set of interfaces exposed by that service.
80 class TestApplication : public ApplicationDelegate,
81 public ApplicationLoader,
82 public InterfaceFactory<Driver>,
83 public Driver {
84 public:
85 explicit TestApplication(bool connect_to_test_service_2)
86 : connect_to_test_service_2_(connect_to_test_service_2) {}
87 ~TestApplication() override {}
88
89 private:
90 // Overridden from ApplicationDelegate:
91 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
92 connection->AddService<Driver>(this);
93 return true;
94 }
95
96 // Overridden from ApplicationLoader:
97 void Load(const GURL& url, InterfaceRequest<Application> request) override {
98 app_.reset(new ApplicationImpl(this, request.Pass()));
99 }
100
101 // Overridden from InterfaceFactory<Driver>:
102 void Create(ApplicationConnection* connection,
103 InterfaceRequest<Driver> request) override {
104 driver_bindings_.AddBinding(this, request.Pass());
105 }
106
107 // Overridden from Driver:
108 void Run() override {
109 URLRequestPtr request(URLRequest::New());
110 request->url = String::From("test:service");
111 ApplicationConnection* connection =
112 app_->ConnectToApplication(request.Pass());
113 connection->ConnectToService(&safe_);
114 safe_->SafeMethod();
115 connection->ConnectToService(&unsafe_);
116 unsafe_->UnsafeMethod();
117
118 if (connect_to_test_service_2_) {
119 URLRequestPtr request2(URLRequest::New());
120 request2->url = String::From("test:service2");
121 ApplicationConnection* connection2 =
122 app_->ConnectToApplication(request2.Pass());
123 connection2->ConnectToService(&safe_2_);
124 safe_2_->SafeMethod();
125 connection2->ConnectToService(&unsafe_2_);
126 unsafe_2_->UnsafeMethod();
127
128 }
129 }
130
131 bool connect_to_test_service_2_;
132 scoped_ptr<ApplicationImpl> app_;
133 WeakBindingSet<Driver> driver_bindings_;
134 SafePtr safe_;
135 UnsafePtr unsafe_;
136 SafePtr safe_2_;
137 UnsafePtr unsafe_2_;
138
139 DISALLOW_COPY_AND_ASSIGN(TestApplication);
140 };
141
142 class SafeImpl : public Safe {
143 public:
144 SafeImpl(CallValidator* validator,
145 const std::string& service_url,
146 const std::string& remote_url,
147 InterfaceRequest<Safe> request)
148 : validator_(validator),
149 service_url_(service_url),
150 remote_url_(remote_url),
151 binding_(this, request.Pass()) {}
152 ~SafeImpl() override {}
153
154 private:
155 // Overridden from Safe:
156 virtual void SafeMethod() override {
157 validator_->Call("SafeMethod", service_url_, remote_url_);
158 }
159
160 CallValidator* validator_;
161 std::string service_url_;
162 std::string remote_url_;
163 StrongBinding<Safe> binding_;
164
165 DISALLOW_COPY_AND_ASSIGN(SafeImpl);
166 };
167
168 class UnsafeImpl : public Unsafe {
169 public:
170 UnsafeImpl(CallValidator* validator,
171 const std::string& service_url,
172 const std::string& remote_url,
173 InterfaceRequest<Unsafe> request)
174 : validator_(validator),
175 service_url_(service_url),
176 remote_url_(remote_url),
177 binding_(this, request.Pass()) {}
178 ~UnsafeImpl() override {}
179
180 private:
181 // Overridden from Unsafe:
182 virtual void UnsafeMethod() override {
183 validator_->Call("UnsafeMethod", service_url_, remote_url_);
184 }
185
186 CallValidator* validator_;
187 std::string service_url_;
188 std::string remote_url_;
189 StrongBinding<Unsafe> binding_;
190
191 DISALLOW_COPY_AND_ASSIGN(UnsafeImpl);
192 };
193
194 // This class models a system service that exposes two interfaces, Safe and
195 // Unsafe. The interface Unsafe is not to be exposed to untrusted applications.
196 class ServiceApplication : public ApplicationDelegate,
197 public ApplicationLoader,
198 public InterfaceFactory<Safe>,
199 public InterfaceFactory<Unsafe> {
200 public:
201 explicit ServiceApplication(CallValidator* validator)
202 : validator_(validator) {}
203 ~ServiceApplication() override {}
204
205 private:
206 // Overridden from ApplicationDelegate:
207 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
208 connection->AddService<Safe>(this);
209 connection->AddService<Unsafe>(this);
210 return true;
211 }
212
213 // Overridden from ApplicationLoader:
214 void Load(const GURL& url,
215 InterfaceRequest<Application> application_request) override {
216 app_.reset(new ApplicationImpl(this, application_request.Pass()));
217 }
218
219 // Overridden from InterfaceFactory<Safe>:
220 void Create(ApplicationConnection* connection,
221 InterfaceRequest<Safe> request) override {
222 new SafeImpl(validator_, app_->url(), connection->GetRemoteApplicationURL(),
223 request.Pass());
224 }
225
226 // Overridden from InterfaceFactory<Unsafe>:
227 void Create(ApplicationConnection* connection,
228 InterfaceRequest<Unsafe> request) override {
229 new UnsafeImpl(validator_, app_->url(),
230 connection->GetRemoteApplicationURL(), request.Pass());
231 }
232
233 scoped_ptr<ApplicationImpl> app_;
234 CallValidator* validator_;
235
236 DISALLOW_COPY_AND_ASSIGN(ServiceApplication);
237 };
238
239 class TestApplicationManagerDelegate : public ApplicationManager::Delegate {
240 public:
241 TestApplicationManagerDelegate() {}
242 ~TestApplicationManagerDelegate() override {}
243
244 private:
245 // Overridden from ApplicationManager::Delegate:
246 GURL ResolveMappings(const GURL& url) override {
247 return url;
248 }
249 GURL ResolveMojoURL(const GURL& url) override {
250 return url;
251 }
252 bool CreateFetcher(const GURL& url,
253 const Fetcher::FetchCallback& loader_callback) override {
254 return false;
255 }
256
257 DISALLOW_COPY_AND_ASSIGN(TestApplicationManagerDelegate);
258 };
259
260 class CapabilityFilterTest : public testing::Test {
261 public:
262 CapabilityFilterTest() {}
263 ~CapabilityFilterTest() override {}
264
265 protected:
266 void RunDriver(const std::string& url, CapabilityFilterPtr filter) {
267 ServiceProviderPtr services;
268 URLRequestPtr request(URLRequest::New());
269 request->url = String::From(url);
270 application_manager_->ConnectToApplication(
271 NULL, request.Pass(), std::string(), GURL(), GetProxy(&services),
272 nullptr, filter.Pass(), base::MessageLoop::QuitWhenIdleClosure());
273 DriverPtr driver;
274 ConnectToService(services.get(), &driver);
275 driver->Run();
276 }
277
278 base::MessageLoop* loop() { return &loop_; }
279 ApplicationManager* application_manager() {
280 return application_manager_.get();
281 }
282
283 private:
284 // Overridden from testing::Test:
285 void SetUp() override {
286 application_manager_.reset(new ApplicationManager(&test_delegate_));
287 }
288 void TearDown() override {
289 application_manager_.reset();
290 }
291
292 base::ShadowingAtExitManager at_exit_;
293 TestApplicationManagerDelegate test_delegate_;
294 base::MessageLoop loop_;
295 scoped_ptr<ApplicationManager> application_manager_;
296
297 DISALLOW_COPY_AND_ASSIGN(CapabilityFilterTest);
298 };
299
300 TEST_F(CapabilityFilterTest, RestrictedInterfaces) {
301 std::set<std::string> valid_calls;
302 valid_calls.insert("SafeMethod test:service test:untrusted_application");
303 valid_calls.insert("SafeMethod test:service test:trusted_application");
304 valid_calls.insert("UnsafeMethod test:service test:trusted_application");
305 std::set<std::string> invalid_calls;
306 invalid_calls.insert("UnsafeMethod test:service test:untrusted_application");
307 CallValidator validator(loop(), valid_calls, invalid_calls);
308 application_manager()->SetLoaderForURL(
309 make_scoped_ptr(new TestApplication(false)),
310 GURL("test:trusted_application"));
311 application_manager()->SetLoaderForURL(
312 make_scoped_ptr(new TestApplication(false)),
313 GURL("test:untrusted_application"));
314 application_manager()->SetLoaderForURL(
315 make_scoped_ptr(new ServiceApplication(&validator)),
316 GURL("test:service"));
317
318 Array<String> interfaces(Array<String>::New(1));
319 interfaces[0] = String::From(std::string(Safe::Name_));
320 CapabilityFilterPtr filter(CapabilityFilter::New());
321 filter->filter.insert("test:service", interfaces.Pass());
322
323 // This first instance is restricted and will only be able to call the safe
324 // method.
325 RunDriver("test:untrusted_application", filter.Pass());
326
327 // This instance of the application should see both method calls.
328 RunDriver("test:trusted_application", nullptr);
329
330 loop()->Run();
331
332 EXPECT_TRUE(validator.called_all_valid());
333 }
334
335 TEST_F(CapabilityFilterTest, RestrictedApplications) {
336 std::set<std::string> valid_calls;
337 valid_calls.insert("SafeMethod test:service test:trusted_application");
338 valid_calls.insert("SafeMethod test:service test:untrusted_application");
339 valid_calls.insert("SafeMethod test:service2 test:trusted_application");
340 valid_calls.insert("UnsafeMethod test:service test:trusted_application");
341 valid_calls.insert("UnsafeMethod test:service2 test:trusted_application");
342
343 std::set<std::string> invalid_calls;
344 invalid_calls.insert("SafeMethod test:service2 test:untrusted_application");
345 invalid_calls.insert("UnsafeMethod test:service test:untrusted_application");
346 invalid_calls.insert("UnsafeMethod test:service2 test:untrusted_application");
347
348 CallValidator validator(loop(), valid_calls, invalid_calls);
349 application_manager()->SetLoaderForURL(
350 make_scoped_ptr(new TestApplication(true)),
351 GURL("test:trusted_application"));
352 application_manager()->SetLoaderForURL(
353 make_scoped_ptr(new TestApplication(true)),
354 GURL("test:untrusted_application"));
355 application_manager()->SetLoaderForURL(
356 make_scoped_ptr(new ServiceApplication(&validator)),
357 GURL("test:service"));
358 application_manager()->SetLoaderForURL(
359 make_scoped_ptr(new ServiceApplication(&validator)),
360 GURL("test:service2"));
361
362 Array<String> interfaces(Array<String>::New(1));
363 interfaces[0] = String::From(std::string(Safe::Name_));
364 CapabilityFilterPtr filter(CapabilityFilter::New());
365 filter->filter.insert("test:service", interfaces.Pass());
366
367 // This first instance is restricted and will only be able to call the safe
368 // method.
369 RunDriver("test:untrusted_application", filter.Pass());
370
371 // This instance of the application should see both method calls.
372 RunDriver("test:trusted_application", nullptr);
373
374 loop()->Run();
375
376 EXPECT_TRUE(validator.called_all_valid());
377 }
378
379 } // namespace
380 } // namespace shell
381 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698