aboutsummaryrefslogtreecommitdiff
path: root/cast
diff options
context:
space:
mode:
authorYuri Wiitala <miu@chromium.org>2020-11-20 07:30:07 -0800
committerCommit Bot <commit-bot@chromium.org>2020-11-20 17:59:09 +0000
commita63f1abf172a55dde56701209770e1deb3fc52b1 (patch)
tree57825196d6e707d2920249972c77f34316585549 /cast
parent8dae1eb937cba58791c16a9caaa723676de563a1 (diff)
downloadopenscreen-a63f1abf172a55dde56701209770e1deb3fc52b1.tar.gz
Implement a more-specific AppAgent::IsConnectionAllowed() policy.
Prevents connections if an app is not launched. Or, if an app is launched, connections must match the "transportId" that was in the last RECEIVER_STATUS update. Bug: b/162542369 Change-Id: I99afcf8a4c80d015505fa688b7372b83ae650578 Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2552433 Commit-Queue: Jordan Bayles <jophba@chromium.org> Reviewed-by: Jordan Bayles <jophba@chromium.org>
Diffstat (limited to 'cast')
-rw-r--r--cast/receiver/application_agent.cc11
-rw-r--r--cast/receiver/application_agent_unittest.cc66
2 files changed, 76 insertions, 1 deletions
diff --git a/cast/receiver/application_agent.cc b/cast/receiver/application_agent.cc
index 97f2da22..ec8a44a4 100644
--- a/cast/receiver/application_agent.cc
+++ b/cast/receiver/application_agent.cc
@@ -127,6 +127,7 @@ void ApplicationAgent::OnMessage(VirtualConnectionRouter* router,
if (message_port_.GetSocketId() == ToCastSocketId(socket) &&
!message_port_.client_sender_id().empty() &&
message_port_.client_sender_id() == message.destination_id()) {
+ OSP_DCHECK(message_port_.client_sender_id() != kPlatformReceiverId);
message_port_.OnMessage(router, socket, std::move(message));
return;
}
@@ -179,7 +180,15 @@ void ApplicationAgent::OnMessage(VirtualConnectionRouter* router,
bool ApplicationAgent::IsConnectionAllowed(
const VirtualConnection& virtual_conn) const {
- return true;
+ if (virtual_conn.local_id == kPlatformReceiverId) {
+ return true;
+ }
+ if (!launched_app_ || message_port_.client_sender_id().empty()) {
+ // No app currently launched. Or, there is a launched app, but it did not
+ // call MessagePort::SetClient() to indicate it wants messages routed to it.
+ return false;
+ }
+ return virtual_conn.local_id == message_port_.client_sender_id();
}
void ApplicationAgent::OnClose(CastSocket* socket) {
diff --git a/cast/receiver/application_agent_unittest.cc b/cast/receiver/application_agent_unittest.cc
index 8a02707f..90fe705e 100644
--- a/cast/receiver/application_agent_unittest.cc
+++ b/cast/receiver/application_agent_unittest.cc
@@ -33,6 +33,7 @@ using ::testing::_;
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::Ne;
+using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Sequence;
using ::testing::StrEq;
@@ -585,6 +586,71 @@ TEST_F(ApplicationAgentTest, LaunchesApp_PassesMessages_ThenStopsApp) {
agent()->UnregisterApplication(&some_app);
}
+TEST_F(ApplicationAgentTest, AllowsVirtualConnectionsToApp) {
+ NiceMock<FakeApplication> some_app("1A2B3C4D", "Something Doer");
+ agent()->RegisterApplication(&some_app);
+
+ // Launch the app, using gMock to simulate an app that calls
+ // MessagePort::SetClient() (to permit messaging) and to get the transport ID
+ // of the app.
+ EXPECT_CALL(*idle_app(), DidStop());
+ EXPECT_CALL(some_app, DidLaunch(_, NotNull()))
+ .WillOnce(Invoke([&](Json::Value params, MessagePort* port) {
+ port->SetClient(&some_app, some_app.GetSessionId());
+ }));
+ std::string transport_id;
+ EXPECT_CALL(*sender_inbound(), OnMessage(_, _))
+ .WillRepeatedly(Invoke([&](CastSocket*, CastMessage message) {
+ const Json::Value payload = ValidateAndParseMessage(
+ message, kPlatformReceiverId, kBroadcastId, kReceiverNamespace);
+ if (payload["type"].asString() == "RECEIVER_STATUS") {
+ transport_id =
+ payload["status"]["applications"][0]["transportId"].asString();
+ }
+ }));
+ auto launch_result = sender_outbound()->Send(MakeCastMessage(
+ kPlatformSenderId, kPlatformReceiverId, kReceiverNamespace, R"({
+ "requestId":1,
+ "type":"LAUNCH",
+ "appId":"1A2B3C4D",
+ "appParams":{},
+ "language":"en-US",
+ "supportedAppTypes":["WEB"]
+ })"));
+ ASSERT_TRUE(launch_result.ok()) << launch_result;
+ Mock::VerifyAndClearExpectations(idle_app());
+ Mock::VerifyAndClearExpectations(&some_app);
+ Mock::VerifyAndClearExpectations(sender_inbound());
+
+ // Now that the application has launched, check that the policy allows
+ // connections to both the ApplicationAgent and the running application.
+ auto* const policy =
+ static_cast<ConnectionNamespaceHandler::VirtualConnectionPolicy*>(
+ agent());
+ EXPECT_TRUE(policy->IsConnectionAllowed(
+ VirtualConnection{kPlatformReceiverId, "any-sender-12345", 0}));
+ ASSERT_FALSE(transport_id.empty());
+ EXPECT_TRUE(policy->IsConnectionAllowed(
+ VirtualConnection{transport_id, "any-sender-12345", 0}));
+ EXPECT_FALSE(policy->IsConnectionAllowed(
+ VirtualConnection{"wherever i likes", "any-sender-12345", 0}));
+
+ // Unregister the app, which will automatically stop it too.
+ EXPECT_CALL(some_app, DidStop());
+ EXPECT_CALL(*idle_app(), DidLaunch(_, NotNull()));
+ EXPECT_CALL(*sender_inbound(), OnMessage(_, _)); // RECEIVER_STATUS update.
+ agent()->UnregisterApplication(&some_app);
+
+ // With the app stopped, check that the policy no longer allows connections to
+ // the now-stale |transport_id|.
+ EXPECT_TRUE(policy->IsConnectionAllowed(
+ VirtualConnection{kPlatformReceiverId, "any-sender-12345", 0}));
+ EXPECT_FALSE(policy->IsConnectionAllowed(
+ VirtualConnection{transport_id, "any-sender-12345", 0}));
+ EXPECT_FALSE(policy->IsConnectionAllowed(
+ VirtualConnection{"wherever i likes", "any-sender-12345", 0}));
+}
+
} // namespace
} // namespace cast
} // namespace openscreen