mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 19:44:08 +00:00
[socket] Add an IPv4 allow list (#20025)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
co-authored by
J. Nick Koston
parent
a531ea07a2
commit
5def4d46ca
@@ -0,0 +1,75 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "esphome/components/socket/ipv4_allow.h"
|
||||
#include "esphome/components/socket/socket.h"
|
||||
|
||||
#ifdef USE_HOST
|
||||
|
||||
namespace esphome::socket::testing {
|
||||
|
||||
// The size_t count packs into the pointer's padding; no RAM over a uint8_t.
|
||||
static_assert(sizeof(Ipv4Allow) == 2 * sizeof(void *), "unexpected padding in Ipv4Allow");
|
||||
|
||||
// 192.168.175.20/32 and 192.168.175.0/24, network order, host bits cleared,
|
||||
// mirroring what add_ipv4_allow emits.
|
||||
static const Ipv4AllowEntry ENTRIES[] = {
|
||||
{htonl(0xC0A8AF14), htonl(0xFFFFFFFF)},
|
||||
{htonl(0xC0A8AF00), htonl(0xFFFFFF00)},
|
||||
};
|
||||
|
||||
// Runs the peer through the same parser production addresses go through.
|
||||
static bool allows_peer(const Ipv4Allow &list, const char *ip) {
|
||||
struct sockaddr_storage peer {};
|
||||
EXPECT_NE(set_sockaddr(reinterpret_cast<struct sockaddr *>(&peer), sizeof(peer), ip, 0), 0);
|
||||
return list.allows(reinterpret_cast<const struct sockaddr *>(&peer));
|
||||
}
|
||||
|
||||
TEST(Ipv4Allow, EmptyAllowsEveryPeer) {
|
||||
Ipv4Allow list;
|
||||
EXPECT_TRUE(list.allows(htonl(0xC0A8AF01)));
|
||||
EXPECT_TRUE(allows_peer(list, "10.0.0.1"));
|
||||
EXPECT_TRUE(allows_peer(list, "fe80::1"));
|
||||
}
|
||||
|
||||
TEST(Ipv4Allow, MatchesHostAndNetworkEntries) {
|
||||
Ipv4Allow list;
|
||||
list.set(ENTRIES, std::size(ENTRIES));
|
||||
EXPECT_TRUE(list.allows(htonl(0xC0A8AF14)));
|
||||
EXPECT_TRUE(list.allows(htonl(0xC0A8AF01)));
|
||||
EXPECT_TRUE(list.allows(htonl(0xC0A8AFFF)));
|
||||
EXPECT_FALSE(list.allows(htonl(0xC0A8B001)));
|
||||
}
|
||||
|
||||
TEST(Ipv4Allow, ChecksTheV4PeerInsideASockaddr) {
|
||||
Ipv4Allow list;
|
||||
list.set(ENTRIES, std::size(ENTRIES));
|
||||
EXPECT_TRUE(allows_peer(list, "192.168.175.66"));
|
||||
EXPECT_FALSE(allows_peer(list, "10.0.0.1"));
|
||||
}
|
||||
|
||||
TEST(Ipv4Allow, UnwrapsAV4MappedIpv6Peer) {
|
||||
Ipv4Allow list;
|
||||
list.set(ENTRIES, std::size(ENTRIES));
|
||||
EXPECT_TRUE(allows_peer(list, "::ffff:192.168.175.66"));
|
||||
// A native IPv6 peer cannot match an IPv4 list.
|
||||
EXPECT_FALSE(allows_peer(list, "fe80::1"));
|
||||
}
|
||||
|
||||
TEST(Ipv4Allow, InstancesKeepIndependentLists) {
|
||||
// One bridge per allow list; each instance points at its own entries.
|
||||
static const Ipv4AllowEntry OTHER[] = {{htonl(0x0A000000), htonl(0xFF000000)}};
|
||||
Ipv4Allow first;
|
||||
Ipv4Allow second;
|
||||
first.set(ENTRIES, std::size(ENTRIES));
|
||||
second.set(OTHER, std::size(OTHER));
|
||||
EXPECT_TRUE(first.allows(htonl(0xC0A8AF14)));
|
||||
EXPECT_FALSE(second.allows(htonl(0xC0A8AF14)));
|
||||
EXPECT_TRUE(second.allows(htonl(0x0A00002A)));
|
||||
EXPECT_FALSE(first.allows(htonl(0x0A00002A)));
|
||||
}
|
||||
|
||||
} // namespace esphome::socket::testing
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user