diff options
author | Yuri Wiitala <miu@chromium.org> | 2020-11-20 07:30:07 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-20 17:59:09 +0000 |
commit | a63f1abf172a55dde56701209770e1deb3fc52b1 (patch) | |
tree | 57825196d6e707d2920249972c77f34316585549 /cast | |
parent | 8dae1eb937cba58791c16a9caaa723676de563a1 (diff) | |
download | openscreen-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.cc | 11 | ||||
-rw-r--r-- | cast/receiver/application_agent_unittest.cc | 66 |
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 |