Commit e64d8c93 authored by Himanshu Jaju's avatar Himanshu Jaju Committed by Commit Bot

Reject incoming share impl

- Implements code to reject an incoming connection
- Adds checks in tests for data written to remote connection

Bug: 1085068
Change-Id: Ic8b1220b881b2adc20b0cd14793b38a1be50732e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332707
Commit-Queue: Himanshu Jaju <himanshujaju@chromium.org>
Reviewed-by: default avatarRichard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795873}
parent 92c9e3b1
......@@ -18,7 +18,7 @@ void FakeNearbyConnection::Read(ReadCallback callback) {
void FakeNearbyConnection::Write(std::vector<uint8_t> bytes) {
DCHECK(!closed_);
NOTIMPLEMENTED();
write_data_.push(std::move(bytes));
}
void FakeNearbyConnection::Close() {
......@@ -38,15 +38,24 @@ void FakeNearbyConnection::RegisterForDisconnection(
void FakeNearbyConnection::AppendReadableData(std::vector<uint8_t> bytes) {
DCHECK(!closed_);
data_.push(std::move(bytes));
read_data_.push(std::move(bytes));
MaybeRunCallback();
}
std::vector<uint8_t> FakeNearbyConnection::GetWrittenData() {
if (write_data_.empty())
return {};
std::vector<uint8_t> bytes = std::move(write_data_.front());
write_data_.pop();
return bytes;
}
void FakeNearbyConnection::MaybeRunCallback() {
DCHECK(!closed_);
if (!callback_ || data_.empty())
if (!callback_ || read_data_.empty())
return;
auto item = std::move(data_.front());
data_.pop();
auto item = std::move(read_data_.front());
read_data_.pop();
std::move(callback_).Run(std::move(item));
}
......@@ -22,13 +22,15 @@ class FakeNearbyConnection : public NearbyConnection {
void RegisterForDisconnection(base::OnceClosure listener) override;
void AppendReadableData(std::vector<uint8_t> bytes);
std::vector<uint8_t> GetWrittenData();
private:
void MaybeRunCallback();
bool closed_ = false;
ReadCallback callback_;
std::queue<std::vector<uint8_t>> data_;
std::queue<std::vector<uint8_t>> read_data_;
std::queue<std::vector<uint8_t>> write_data_;
std::vector<base::OnceClosure> disconnect_listeners_;
};
......
......@@ -107,7 +107,6 @@ FakeNearbyConnectionsManager::GetRawAuthenticationToken(
void FakeNearbyConnectionsManager::UpgradeBandwidth(
const std::string& endpoint_id) {
// TODO(alexchau): Implement.
upgrade_bandwidth_endpoint_ids_.insert(endpoint_id);
}
......
......@@ -32,6 +32,8 @@ namespace {
constexpr base::TimeDelta kReadFramesTimeout = base::TimeDelta::FromSeconds(15);
constexpr base::TimeDelta kReadResponseFrameTimeout =
base::TimeDelta::FromSeconds(60);
constexpr base::TimeDelta kIncomingRejectionDelay =
base::TimeDelta::FromSeconds(2);
std::string ReceiveSurfaceStateToString(
NearbySharingService::ReceiveSurfaceState state) {
......@@ -310,6 +312,32 @@ void NearbySharingServiceImpl::Accept(
void NearbySharingServiceImpl::Reject(
const ShareTarget& share_target,
StatusCodesCallback status_codes_callback) {
NearbyConnection* connection = GetIncomingConnection(share_target);
if (!connection) {
NS_LOG(WARNING) << __func__ << ": Reject invoked for unknown share target";
std::move(status_codes_callback).Run(StatusCodes::kOutOfOrderApiCall);
return;
}
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&NearbySharingServiceImpl::CloseConnection,
weak_ptr_factory_.GetWeakPtr(), share_target),
kIncomingRejectionDelay);
connection->RegisterForDisconnection(
base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget,
weak_ptr_factory_.GetWeakPtr(), share_target));
WriteResponse(*connection, sharing::nearby::ConnectionResponseFrame::REJECT);
NS_LOG(VERBOSE) << __func__
<< ": Successfully wrote a rejection response frame";
OnIncomingTransferUpdate(share_target,
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kRejected)
.build());
std::move(status_codes_callback).Run(StatusCodes::kOk);
}
......@@ -836,6 +864,17 @@ void NearbySharingServiceImpl::Fail(const ShareTarget& share_target,
}
}
void NearbySharingServiceImpl::CloseConnection(
const ShareTarget& share_target) {
NearbyConnection* connection = GetIncomingConnection(share_target);
if (!connection) {
NS_LOG(WARNING) << __func__ << ": Invalid connection for target - "
<< share_target.device_name;
return;
}
connection->Close();
}
void NearbySharingServiceImpl::ReceiveIntroduction(
ShareTarget share_target,
base::Optional<std::string> token) {
......
......@@ -145,6 +145,7 @@ class NearbySharingServiceImpl
void Fail(const ShareTarget& share_target, TransferMetadata::Status status);
void OnIncomingTransferUpdate(const ShareTarget& share_target,
TransferMetadata metadata);
void CloseConnection(const ShareTarget& share_target);
void ReceiveIntroduction(ShareTarget share_target,
base::Optional<std::string> token);
void OnReceivedIntroduction(
......
......@@ -792,6 +792,17 @@ TEST_F(NearbySharingServiceImplTest,
service_->OnIncomingConnection(kEndpointId, {}, &connection);
run_loop.Run();
// Check data written to connection.
std::vector<uint8_t> data = connection.GetWrittenData();
sharing::nearby::Frame frame;
frame.ParseFromArray(data.data(), data.size());
EXPECT_TRUE(frame.has_v1());
EXPECT_TRUE(frame.v1().has_connection_response());
EXPECT_EQ(
sharing::nearby::ConnectionResponseFrame::UNSUPPORTED_ATTACHMENT_TYPE,
frame.v1().connection_response().status());
// To avoid UAF in OnIncomingTransferUpdate().
service_->UnregisterReceiveSurface(&callback);
}
......@@ -913,6 +924,100 @@ TEST_F(NearbySharingServiceImplTest, AcceptValidShareTarget) {
EXPECT_TRUE(
fake_nearby_connections_manager_->DidUpgradeBandwidth(kEndpointId));
// Check data written to connection.
std::vector<uint8_t> data = connection.GetWrittenData();
sharing::nearby::Frame frame;
frame.ParseFromArray(data.data(), data.size());
EXPECT_TRUE(frame.has_v1());
EXPECT_TRUE(frame.v1().has_connection_response());
EXPECT_EQ(sharing::nearby::ConnectionResponseFrame::ACCEPT,
frame.v1().connection_response().status());
// To avoid UAF in OnIncomingTransferUpdate().
service_->UnregisterReceiveSurface(&callback);
}
TEST_F(NearbySharingServiceImplTest, RejectInvalidShareTarget) {
ShareTarget share_target;
base::RunLoop run_loop;
service_->Reject(
share_target,
base::BindLambdaForTesting(
[&](NearbySharingServiceImpl::StatusCodes status_code) {
EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOutOfOrderApiCall,
status_code);
run_loop.Quit();
}));
run_loop.Run();
}
TEST_F(NearbySharingServiceImplTest, RejectValidShareTarget) {
std::string intro = "introduction_frame";
std::vector<uint8_t> bytes(intro.begin(), intro.end());
NiceMock<MockNearbySharingDecoder> mock_decoder;
EXPECT_CALL(mock_decoder, DecodeFrame(testing::Eq(bytes), testing::_))
.WillOnce(testing::Invoke(
[&](const std::vector<uint8_t>& data,
MockNearbySharingDecoder::DecodeFrameCallback callback) {
std::move(callback).Run(GetValidIntroductionFrame());
}));
EXPECT_CALL(mock_nearby_process_manager(),
GetOrStartNearbySharingDecoder(testing::_))
.WillRepeatedly(testing::Return(&mock_decoder));
ShareTarget share_target;
FakeNearbyConnection connection;
connection.AppendReadableData(bytes);
ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE);
SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
NiceMock<MockTransferUpdateCallback> callback;
base::RunLoop run_loop;
EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
.WillOnce(testing::Invoke([&](const ShareTarget& incoming_share_target,
TransferMetadata metadata) {
EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation,
metadata.status());
share_target = incoming_share_target;
run_loop.Quit();
}));
NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface(
&callback, NearbySharingService::ReceiveSurfaceState::kForeground);
EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk);
EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising());
service_->OnIncomingConnection("endpoint_id", {}, &connection);
run_loop.Run();
base::RunLoop run_loop_reject;
EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget& share_target, TransferMetadata metadata) {
EXPECT_EQ(TransferMetadata::Status::kRejected, metadata.status());
}));
service_->Reject(share_target,
base::BindLambdaForTesting(
[&](NearbySharingServiceImpl::StatusCodes status_code) {
EXPECT_EQ(NearbySharingServiceImpl::StatusCodes::kOk,
status_code);
run_loop_reject.Quit();
}));
run_loop_reject.Run();
// Check data written to connection.
std::vector<uint8_t> data = connection.GetWrittenData();
sharing::nearby::Frame frame;
frame.ParseFromArray(data.data(), data.size());
EXPECT_TRUE(frame.has_v1());
EXPECT_TRUE(frame.v1().has_connection_response());
EXPECT_EQ(sharing::nearby::ConnectionResponseFrame::REJECT,
frame.v1().connection_response().status());
// To avoid UAF in OnIncomingTransferUpdate().
service_->UnregisterReceiveSurface(&callback);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment