mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Harden Nearby Connections WifiLan bandwidth upgrade
PiperOrigin-RevId: 937051504
This commit is contained in:
committed by
Copybara-Service
parent
1f71b0713b
commit
488d79d420
@@ -79,21 +79,40 @@ WifiLanBwuHandler::CreateUpgradedEndpointChannel(
|
||||
<< address_candidate.ip_address().size();
|
||||
continue;
|
||||
}
|
||||
if (service_address.IsLoopbackAddress() ||
|
||||
service_address.IsLinkLocalAddress()) {
|
||||
LOG(WARNING) << "Loopback/link-local address candidate is rejected.";
|
||||
return {
|
||||
Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL)};
|
||||
}
|
||||
address_candidates.push_back(std::move(service_address));
|
||||
}
|
||||
// Only use ip_address and wifi_port if address_candidates is empty.
|
||||
if (address_candidates.empty()) {
|
||||
address_candidates.push_back(ServiceAddress{
|
||||
.address =
|
||||
std::vector<char>(upgrade_path_info_socket.ip_address().begin(),
|
||||
upgrade_path_info_socket.ip_address().end()),
|
||||
.port = static_cast<uint16_t>(upgrade_path_info_socket.wifi_port())});
|
||||
if (upgrade_path_info_socket.ip_address().size() != 4) {
|
||||
LOG(ERROR) << "WifiLanBwuHandler: fallback ip_address size is not 4 "
|
||||
<< "(IPv4 only).";
|
||||
return {
|
||||
Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_IP_ADDRESS_ERROR)};
|
||||
}
|
||||
ServiceAddress service_address;
|
||||
service_address.address = {upgrade_path_info_socket.ip_address().begin(),
|
||||
upgrade_path_info_socket.ip_address().end()};
|
||||
service_address.port =
|
||||
static_cast<uint16_t>(upgrade_path_info_socket.wifi_port());
|
||||
if (service_address.IsLoopbackAddress() ||
|
||||
service_address.IsLinkLocalAddress()) {
|
||||
LOG(WARNING) << "Loopback/link-local fallback address is rejected.";
|
||||
return {
|
||||
Error(OperationResultCode::CONNECTIVITY_WIFI_LAN_INVALID_CREDENTIAL)};
|
||||
}
|
||||
address_candidates.push_back(std::move(service_address));
|
||||
}
|
||||
Error error;
|
||||
for (const auto& address_candidate : address_candidates) {
|
||||
VLOG(1) << "WifiLanBwuHandler is attempting to connect to available "
|
||||
"WifiLan service (" << address_candidate << ") for endpoint "
|
||||
<< endpoint_id;
|
||||
"WifiLan service ("
|
||||
<< address_candidate << ") for endpoint " << endpoint_id;
|
||||
std::shared_ptr<CancellationFlag> cancellation_flag =
|
||||
client->GetCancellationFlag(endpoint_id);
|
||||
ErrorOr<WifiLanSocket> socket_result = wifi_lan_medium_.Connect(
|
||||
|
||||
@@ -209,6 +209,71 @@ TEST_F(WifiLanBwuHandlerTest,
|
||||
EXPECT_TRUE(result.has_value());
|
||||
};
|
||||
|
||||
TEST_F(WifiLanBwuHandlerTest,
|
||||
CreateUpgradedEndpointChannel_RejectLoopbackAndLinkLocalCandidates) {
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
||||
|
||||
// 1st candidate: Loopback
|
||||
auto* address_candidate =
|
||||
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
||||
address_candidate->set_ip_address(std::string("\x7f\x00\x00\x01", 4));
|
||||
address_candidate->set_port(8080);
|
||||
|
||||
// 2nd candidate: Link-Local (169.254.1.1)
|
||||
address_candidate =
|
||||
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
||||
address_candidate->set_ip_address("\xa9\xfe\x01\x01");
|
||||
address_candidate->set_port(8080);
|
||||
|
||||
// 3rd candidate: Valid IP
|
||||
address_candidate =
|
||||
path_info.mutable_wifi_lan_socket()->add_address_candidates();
|
||||
address_candidate->set_ip_address(kIpv4Address);
|
||||
address_candidate->set_port(8080);
|
||||
|
||||
auto result = handler_.CreateUpgradedEndpointChannel(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId),
|
||||
std::move(path_info));
|
||||
|
||||
EXPECT_FALSE(result.has_value());
|
||||
}
|
||||
|
||||
TEST_F(WifiLanBwuHandlerTest,
|
||||
CreateUpgradedEndpointChannel_RejectLoopbackFallbackIp) {
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
||||
path_info.mutable_wifi_lan_socket()->set_ip_address(
|
||||
std::string("\x7f\x00\x00\x01", 4));
|
||||
path_info.mutable_wifi_lan_socket()->set_wifi_port(8080);
|
||||
|
||||
auto result = handler_.CreateUpgradedEndpointChannel(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId),
|
||||
std::move(path_info));
|
||||
|
||||
EXPECT_FALSE(result.has_value());
|
||||
}
|
||||
|
||||
TEST_F(WifiLanBwuHandlerTest,
|
||||
CreateUpgradedEndpointChannel_RejectInvalidFallbackIpLength) {
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
BandwidthUpgradeNegotiationFrame::UpgradePathInfo path_info;
|
||||
path_info.mutable_wifi_lan_socket()->set_ip_address("123");
|
||||
path_info.mutable_wifi_lan_socket()->set_wifi_port(8080);
|
||||
|
||||
auto result = handler_.CreateUpgradedEndpointChannel(
|
||||
&client, std::string(kServiceId), std::string(kEndpointId),
|
||||
std::move(path_info));
|
||||
|
||||
EXPECT_FALSE(result.has_value());
|
||||
}
|
||||
|
||||
TEST_F(WifiLanBwuHandlerTest, InitializeUpgradedMediumForEndpoint_Success) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
@@ -289,9 +354,8 @@ TEST_F(WifiLanBwuHandlerTest,
|
||||
mediums_.GetWifiLan().IsAcceptingConnections("service_id_UPGRADE"));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
WifiLanBwuHandlerTest,
|
||||
InitializeUpgradedMediumForEndpoint_AlreadyAccepting_KeepAccepting) {
|
||||
TEST_F(WifiLanBwuHandlerTest,
|
||||
InitializeUpgradedMediumForEndpoint_AlreadyAccepting_KeepAccepting) {
|
||||
MediumEnvironment::Instance().Start({.use_simulated_clock = true});
|
||||
ClientProxy client;
|
||||
client.AddCancellationFlag(std::string(kEndpointId));
|
||||
|
||||
@@ -240,7 +240,7 @@ Exception EnsureValidBandwidthUpgradeWifiHotspotPathAvailableFrame(
|
||||
const std::regex ip4_pattern(std::string(kIpv4PatternString).c_str());
|
||||
if (!wifi_hotspot_credentials.gateway().empty() &&
|
||||
!(std::regex_match(wifi_hotspot_credentials.gateway(), ip4_pattern))) {
|
||||
return {Exception::kInvalidProtocolBuffer};
|
||||
return {Exception::kInvalidProtocolBuffer};
|
||||
}
|
||||
for (const auto& address_candidate :
|
||||
wifi_hotspot_credentials.address_candidates()) {
|
||||
@@ -300,8 +300,7 @@ Exception EnsureValidBandwidthUpgradeWifiDirectPathAvailableFrame(
|
||||
kWifiPasswordSsidMinLength, kWifiPasswordSsidMaxLength);
|
||||
bool device_name_valid =
|
||||
wifi_direct_credentials.has_device_name() &&
|
||||
wifi_direct_credentials.device_name().length() <
|
||||
kWifiDirectSsidMaxLength;
|
||||
wifi_direct_credentials.device_name().length() < kWifiDirectSsidMaxLength;
|
||||
bool pin_valid =
|
||||
wifi_direct_credentials.has_pin() &&
|
||||
WithinRange(wifi_direct_credentials.pin().length(),
|
||||
|
||||
@@ -768,9 +768,8 @@ TEST(OfflineFramesValidatorTest,
|
||||
std::string wifi_direct_pin_wrong_length = "01234567890123456";
|
||||
std::string bytes = ForBwuWifiDirectPathAvailable(
|
||||
wifi_direct_ssid, std::string(kWifiDirectPassword), kPort,
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption,
|
||||
std::string(kGateway), std::string(kWifiDirectDeviceName),
|
||||
wifi_direct_pin_wrong_length);
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption, std::string(kGateway),
|
||||
std::string(kWifiDirectDeviceName), wifi_direct_pin_wrong_length);
|
||||
offline_frame_1.ParseFromString(bytes);
|
||||
|
||||
auto ret_value = EnsureValidOfflineFrame(offline_frame_1);
|
||||
@@ -784,9 +783,8 @@ TEST(OfflineFramesValidatorTest,
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
|
||||
bytes = ForBwuWifiDirectPathAvailable(
|
||||
wifi_direct_ssid_wrong_length, std::string(kWifiDirectPassword), kPort,
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption,
|
||||
std::string(kGateway), wifi_direct_device_name_wrong_length,
|
||||
std::string(kWifiDirectPin));
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption, std::string(kGateway),
|
||||
wifi_direct_device_name_wrong_length, std::string(kWifiDirectPin));
|
||||
offline_frame_2.ParseFromString(bytes);
|
||||
|
||||
ret_value = EnsureValidOfflineFrame(offline_frame_2);
|
||||
@@ -807,9 +805,8 @@ TEST(OfflineFramesValidatorTest,
|
||||
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
|
||||
std::string bytes = ForBwuWifiDirectPathAvailable(
|
||||
std::string(kWifiDirectSsid), long_wifi_direct_password, kPort,
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption,
|
||||
std::string(kGateway), std::string(kWifiDirectDeviceName),
|
||||
long_wifi_direct_pin);
|
||||
kWifiDirectFrequency, kSupportsDisablingEncryption, std::string(kGateway),
|
||||
std::string(kWifiDirectDeviceName), long_wifi_direct_pin);
|
||||
offline_frame_2.ParseFromString(bytes);
|
||||
|
||||
auto ret_value = EnsureValidOfflineFrame(offline_frame_2);
|
||||
|
||||
@@ -80,8 +80,6 @@ cc_library(
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/meta:type_traits",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/strings:string_view",
|
||||
|
||||
@@ -14,11 +14,17 @@
|
||||
|
||||
#include "internal/platform/service_address.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "connections/implementation/proto/offline_wire_formats.pb.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace {
|
||||
constexpr absl::string_view kIpv6LoopbackAddress(
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 16);
|
||||
} // namespace
|
||||
|
||||
void ServiceAddressToProto(
|
||||
const ServiceAddress& service_address,
|
||||
@@ -42,4 +48,31 @@ bool ServiceAddressFromProto(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceAddress::IsLoopbackAddress() const {
|
||||
if (address.size() == 4) {
|
||||
// IPv4 loopback: 127.0.0.0/8
|
||||
return address[0] == 127;
|
||||
} else if (address.size() == 16) {
|
||||
// IPv6 loopback: ::1
|
||||
return absl::string_view(address.data(), address.size()) ==
|
||||
kIpv6LoopbackAddress;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServiceAddress::IsLinkLocalAddress() const {
|
||||
if (address.size() == 4) {
|
||||
// IPv4 link-local: 169.254.0.0/16
|
||||
uint8_t b0 = static_cast<uint8_t>(address[0]);
|
||||
uint8_t b1 = static_cast<uint8_t>(address[1]);
|
||||
return b0 == 169 && b1 == 254;
|
||||
} else if (address.size() == 16) {
|
||||
// IPv6 link-local: fe80::/10
|
||||
uint8_t b0 = static_cast<uint8_t>(address[0]);
|
||||
uint8_t b1 = static_cast<uint8_t>(address[1]);
|
||||
return b0 == 0xfe && (b1 & 0xc0) == 0x80;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_SERVICE_ADDRESS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -33,6 +32,14 @@ struct ServiceAddress {
|
||||
uint16_t port;
|
||||
|
||||
bool operator==(const ServiceAddress& other) const = default;
|
||||
|
||||
// Returns true if the address is a loopback address (IPv4 127.0.0.0/8 or
|
||||
// IPv6 ::1).
|
||||
bool IsLoopbackAddress() const;
|
||||
|
||||
// Returns true if the address is a link-local address (IPv4 169.254.0.0/16 or
|
||||
// IPv6 fe80::/10).
|
||||
bool IsLinkLocalAddress() const;
|
||||
};
|
||||
|
||||
// Support logging of ServiceAddress.
|
||||
|
||||
@@ -118,5 +118,104 @@ TEST(ServiceAddressTest, ServiceAddressEquality) {
|
||||
EXPECT_EQ(service_address5, service_address6);
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLoopbackAddressIPv4) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {127, 0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_TRUE(service_address.IsLoopbackAddress());
|
||||
|
||||
ServiceAddress not_loopback = {
|
||||
.address = {10, 0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_loopback.IsLoopbackAddress());
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLoopbackAddressIPv6) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_TRUE(service_address.IsLoopbackAddress());
|
||||
|
||||
ServiceAddress not_loopback = {
|
||||
.address = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_loopback.IsLoopbackAddress());
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLinkLocalAddressIPv4) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {static_cast<char>(169), static_cast<char>(254), 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_TRUE(service_address.IsLinkLocalAddress());
|
||||
|
||||
ServiceAddress not_link_local = {
|
||||
.address = {169, static_cast<char>(253), 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_link_local.IsLinkLocalAddress());
|
||||
|
||||
ServiceAddress not_link_local_b0 = {
|
||||
.address = {100, static_cast<char>(254), 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_link_local_b0.IsLinkLocalAddress());
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLinkLocalAddressIPv6) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {static_cast<char>(0xfe), static_cast<char>(0x80), 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_TRUE(service_address.IsLinkLocalAddress());
|
||||
|
||||
ServiceAddress not_link_local = {
|
||||
.address = {static_cast<char>(0xfd), static_cast<char>(0x80), 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_link_local.IsLinkLocalAddress());
|
||||
|
||||
ServiceAddress not_link_local_b1 = {
|
||||
.address = {static_cast<char>(0xfe), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(not_link_local_b1.IsLinkLocalAddress());
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLoopbackAddressInvalidLength) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {127, 0, 0},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(service_address.IsLoopbackAddress());
|
||||
|
||||
ServiceAddress empty_address = {
|
||||
.address = {},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(empty_address.IsLoopbackAddress());
|
||||
}
|
||||
|
||||
TEST(ServiceAddressTest, IsLinkLocalAddressInvalidLength) {
|
||||
ServiceAddress service_address = {
|
||||
.address = {static_cast<char>(169), static_cast<char>(254), 0},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(service_address.IsLinkLocalAddress());
|
||||
|
||||
ServiceAddress empty_address = {
|
||||
.address = {},
|
||||
.port = 8080,
|
||||
};
|
||||
EXPECT_FALSE(empty_address.IsLinkLocalAddress());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby
|
||||
|
||||
Reference in New Issue
Block a user