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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: mojo/shell/capability_filter_unittest.cc
diff --git a/mojo/shell/capability_filter_unittest.cc b/mojo/shell/capability_filter_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..52126ce92860381a0bc5cf91678f6b33c9fe7d32
--- /dev/null
+++ b/mojo/shell/capability_filter_unittest.cc
@@ -0,0 +1,381 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
sky 2015/07/22 15:57:45 2015
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/application/public/cpp/connect.h"
+#include "mojo/application/public/cpp/interface_factory.h"
+#include "mojo/common/weak_binding_set.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/shell/application_loader.h"
+#include "mojo/shell/application_manager.h"
+#include "mojo/shell/test.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace shell {
+namespace {
+
+// Quits |loop| when either:
+// - all of the |valid_calls| are received, or
+// - one of the |invalid_calls| is received.
+class CallValidator {
+ public:
+ CallValidator(base::MessageLoop* loop,
+ const std::set<std::string>& valid_calls,
+ const std::set<std::string>& invalid_calls)
+ : loop_(loop),
+ valid_calls_(valid_calls),
+ invalid_calls_(invalid_calls) {
+ }
+
+ static std::string FormatCall(const std::string& function,
+ const std::string& service_url,
+ const std::string& remote_url) {
+ return base::StringPrintf("%s %s %s", function.c_str(), service_url.c_str(),
+ remote_url.c_str());
+ }
+
+ void Call(const std::string& function,
+ const std::string& service_url,
+ const std::string& remote_url) {
+ std::string call = FormatCall(function, service_url, remote_url);
+ {
+ auto i = invalid_calls_.find(call);
+ if (i != invalid_calls_.end()) {
+ loop_->Quit();
+ return;
+ }
+ }
+
+ {
+ auto i = valid_calls_.find(call);
+ if (i != valid_calls_.end())
+ valid_calls_.erase(i);
+ if (valid_calls_.empty())
+ loop_->Quit();
+ }
+ }
+
+ bool called_all_valid() const { return valid_calls_.empty(); }
+
+ private:
+ base::MessageLoop* loop_;
+ std::set<std::string> valid_calls_;
+ std::set<std::string> invalid_calls_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallValidator);
+};
+
+// This class models an application who will use the shell to interact with a
+// system service. The shell may limit this application's visibility of the full
+// set of interfaces exposed by that service.
+class TestApplication : public ApplicationDelegate,
+ public ApplicationLoader,
+ public InterfaceFactory<Driver>,
+ public Driver {
+ public:
+ explicit TestApplication(bool connect_to_test_service_2)
+ : connect_to_test_service_2_(connect_to_test_service_2) {}
+ ~TestApplication() override {}
+
+ private:
+ // Overridden from ApplicationDelegate:
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ connection->AddService<Driver>(this);
+ return true;
+ }
+
+ // Overridden from ApplicationLoader:
+ void Load(const GURL& url, InterfaceRequest<Application> request) override {
+ app_.reset(new ApplicationImpl(this, request.Pass()));
+ }
+
+ // Overridden from InterfaceFactory<Driver>:
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<Driver> request) override {
+ driver_bindings_.AddBinding(this, request.Pass());
+ }
+
+ // Overridden from Driver:
+ void Run() override {
+ URLRequestPtr request(URLRequest::New());
+ request->url = String::From("test:service");
+ ApplicationConnection* connection =
+ app_->ConnectToApplication(request.Pass());
+ connection->ConnectToService(&safe_);
+ safe_->SafeMethod();
+ connection->ConnectToService(&unsafe_);
+ unsafe_->UnsafeMethod();
+
+ if (connect_to_test_service_2_) {
+ URLRequestPtr request2(URLRequest::New());
+ request2->url = String::From("test:service2");
+ ApplicationConnection* connection2 =
+ app_->ConnectToApplication(request2.Pass());
+ connection2->ConnectToService(&safe_2_);
+ safe_2_->SafeMethod();
+ connection2->ConnectToService(&unsafe_2_);
+ unsafe_2_->UnsafeMethod();
+
+ }
+ }
+
+ bool connect_to_test_service_2_;
+ scoped_ptr<ApplicationImpl> app_;
+ WeakBindingSet<Driver> driver_bindings_;
+ SafePtr safe_;
+ UnsafePtr unsafe_;
+ SafePtr safe_2_;
+ UnsafePtr unsafe_2_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestApplication);
+};
+
+class SafeImpl : public Safe {
+ public:
+ SafeImpl(CallValidator* validator,
+ const std::string& service_url,
+ const std::string& remote_url,
+ InterfaceRequest<Safe> request)
+ : validator_(validator),
+ service_url_(service_url),
+ remote_url_(remote_url),
+ binding_(this, request.Pass()) {}
+ ~SafeImpl() override {}
+
+ private:
+ // Overridden from Safe:
+ virtual void SafeMethod() override {
+ validator_->Call("SafeMethod", service_url_, remote_url_);
+ }
+
+ CallValidator* validator_;
+ std::string service_url_;
+ std::string remote_url_;
+ StrongBinding<Safe> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(SafeImpl);
+};
+
+class UnsafeImpl : public Unsafe {
+ public:
+ UnsafeImpl(CallValidator* validator,
+ const std::string& service_url,
+ const std::string& remote_url,
+ InterfaceRequest<Unsafe> request)
+ : validator_(validator),
+ service_url_(service_url),
+ remote_url_(remote_url),
+ binding_(this, request.Pass()) {}
+ ~UnsafeImpl() override {}
+
+ private:
+ // Overridden from Unsafe:
+ virtual void UnsafeMethod() override {
+ validator_->Call("UnsafeMethod", service_url_, remote_url_);
+ }
+
+ CallValidator* validator_;
+ std::string service_url_;
+ std::string remote_url_;
+ StrongBinding<Unsafe> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnsafeImpl);
+};
+
+// This class models a system service that exposes two interfaces, Safe and
+// Unsafe. The interface Unsafe is not to be exposed to untrusted applications.
+class ServiceApplication : public ApplicationDelegate,
+ public ApplicationLoader,
+ public InterfaceFactory<Safe>,
+ public InterfaceFactory<Unsafe> {
+ public:
+ explicit ServiceApplication(CallValidator* validator)
+ : validator_(validator) {}
+ ~ServiceApplication() override {}
+
+ private:
+ // Overridden from ApplicationDelegate:
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ connection->AddService<Safe>(this);
+ connection->AddService<Unsafe>(this);
+ return true;
+ }
+
+ // Overridden from ApplicationLoader:
+ void Load(const GURL& url,
+ InterfaceRequest<Application> application_request) override {
+ app_.reset(new ApplicationImpl(this, application_request.Pass()));
+ }
+
+ // Overridden from InterfaceFactory<Safe>:
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<Safe> request) override {
+ new SafeImpl(validator_, app_->url(), connection->GetRemoteApplicationURL(),
+ request.Pass());
+ }
+
+ // Overridden from InterfaceFactory<Unsafe>:
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<Unsafe> request) override {
+ new UnsafeImpl(validator_, app_->url(),
+ connection->GetRemoteApplicationURL(), request.Pass());
+ }
+
+ scoped_ptr<ApplicationImpl> app_;
+ CallValidator* validator_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceApplication);
+};
+
+class TestApplicationManagerDelegate : public ApplicationManager::Delegate {
+ public:
+ TestApplicationManagerDelegate() {}
+ ~TestApplicationManagerDelegate() override {}
+
+ private:
+ // Overridden from ApplicationManager::Delegate:
+ GURL ResolveMappings(const GURL& url) override {
+ return url;
+ }
+ GURL ResolveMojoURL(const GURL& url) override {
+ return url;
+ }
+ bool CreateFetcher(const GURL& url,
+ const Fetcher::FetchCallback& loader_callback) override {
+ return false;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestApplicationManagerDelegate);
+};
+
+class CapabilityFilterTest : public testing::Test {
+ public:
+ CapabilityFilterTest() {}
+ ~CapabilityFilterTest() override {}
+
+ protected:
+ void RunDriver(const std::string& url, CapabilityFilterPtr filter) {
+ ServiceProviderPtr services;
+ URLRequestPtr request(URLRequest::New());
+ request->url = String::From(url);
+ application_manager_->ConnectToApplication(
+ NULL, request.Pass(), std::string(), GURL(), GetProxy(&services),
+ nullptr, filter.Pass(), base::MessageLoop::QuitWhenIdleClosure());
+ DriverPtr driver;
+ ConnectToService(services.get(), &driver);
+ driver->Run();
+ }
+
+ base::MessageLoop* loop() { return &loop_; }
+ ApplicationManager* application_manager() {
+ return application_manager_.get();
+ }
+
+ private:
+ // Overridden from testing::Test:
+ void SetUp() override {
+ application_manager_.reset(new ApplicationManager(&test_delegate_));
+ }
+ void TearDown() override {
+ application_manager_.reset();
+ }
+
+ base::ShadowingAtExitManager at_exit_;
+ TestApplicationManagerDelegate test_delegate_;
+ base::MessageLoop loop_;
+ scoped_ptr<ApplicationManager> application_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(CapabilityFilterTest);
+};
+
+TEST_F(CapabilityFilterTest, RestrictedInterfaces) {
+ std::set<std::string> valid_calls;
+ valid_calls.insert("SafeMethod test:service test:untrusted_application");
+ valid_calls.insert("SafeMethod test:service test:trusted_application");
+ valid_calls.insert("UnsafeMethod test:service test:trusted_application");
+ std::set<std::string> invalid_calls;
+ invalid_calls.insert("UnsafeMethod test:service test:untrusted_application");
+ CallValidator validator(loop(), valid_calls, invalid_calls);
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new TestApplication(false)),
+ GURL("test:trusted_application"));
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new TestApplication(false)),
+ GURL("test:untrusted_application"));
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new ServiceApplication(&validator)),
+ GURL("test:service"));
+
+ Array<String> interfaces(Array<String>::New(1));
+ interfaces[0] = String::From(std::string(Safe::Name_));
+ CapabilityFilterPtr filter(CapabilityFilter::New());
+ filter->filter.insert("test:service", interfaces.Pass());
+
+ // This first instance is restricted and will only be able to call the safe
+ // method.
+ RunDriver("test:untrusted_application", filter.Pass());
+
+ // This instance of the application should see both method calls.
+ RunDriver("test:trusted_application", nullptr);
+
+ loop()->Run();
+
+ EXPECT_TRUE(validator.called_all_valid());
+}
+
+TEST_F(CapabilityFilterTest, RestrictedApplications) {
+ std::set<std::string> valid_calls;
+ valid_calls.insert("SafeMethod test:service test:trusted_application");
+ valid_calls.insert("SafeMethod test:service test:untrusted_application");
+ valid_calls.insert("SafeMethod test:service2 test:trusted_application");
+ valid_calls.insert("UnsafeMethod test:service test:trusted_application");
+ valid_calls.insert("UnsafeMethod test:service2 test:trusted_application");
+
+ std::set<std::string> invalid_calls;
+ invalid_calls.insert("SafeMethod test:service2 test:untrusted_application");
+ invalid_calls.insert("UnsafeMethod test:service test:untrusted_application");
+ invalid_calls.insert("UnsafeMethod test:service2 test:untrusted_application");
+
+ CallValidator validator(loop(), valid_calls, invalid_calls);
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new TestApplication(true)),
+ GURL("test:trusted_application"));
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new TestApplication(true)),
+ GURL("test:untrusted_application"));
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new ServiceApplication(&validator)),
+ GURL("test:service"));
+ application_manager()->SetLoaderForURL(
+ make_scoped_ptr(new ServiceApplication(&validator)),
+ GURL("test:service2"));
+
+ Array<String> interfaces(Array<String>::New(1));
+ interfaces[0] = String::From(std::string(Safe::Name_));
+ CapabilityFilterPtr filter(CapabilityFilter::New());
+ filter->filter.insert("test:service", interfaces.Pass());
+
+ // This first instance is restricted and will only be able to call the safe
+ // method.
+ RunDriver("test:untrusted_application", filter.Pass());
+
+ // This instance of the application should see both method calls.
+ RunDriver("test:trusted_application", nullptr);
+
+ loop()->Run();
+
+ EXPECT_TRUE(validator.called_all_valid());
+}
+
+} // namespace
+} // namespace shell
+} // namespace mojo

Powered by Google App Engine
This is Rietveld 408576698