OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_psid_cookie.cpp
Go to the documentation of this file.
1#include "test_common.hpp"
2
4
5using namespace openvpn;
6
7
8TEST(psid_cookie, setup)
9{
11
12 ASSERT_TRUE(true);
13}
14
15// The following uland_addr46 type is a userland adaptation of an unpublished
16// ovpn_addr46 type from James Yonan's kernel work. The main idea is to create
17// a reliably hashable representation of an IP address, be it IPv4 or IPv6
18/* Discriminated union for IPv4/v6 addresses that should replace
19 ovpn_addr. The advantage of this approach over ovpn_addr is
20 better alignment/packing and potential use as an rhashtable key. */
22 /* IPv4 */
23 struct
24 {
25 /* treat as IPv4-mapped IPv6 addresses */
26 uint64_t a4_pre64; /* 0 */
27 uint32_t a4_pre32; /* htonl(0xFFFF) */
28 struct in_addr a4; /* the IPv4 address */
29 };
30
31 /* IPv6 */
32 struct in6_addr a6;
33 uint64_t a6_64[2];
34};
35
37{
38 public:
40 {
41 prng.rand_fill(addrport_);
42 }
43 const unsigned char *get_abstract_cli_addrport(size_t &slab_size) const override
44 {
45 slab_size = slab_size_;
46 return addrport_.c;
47 }
48 // unused for these tests
49 const void *get_impl_info() const override
50 {
51 return nullptr;
52 }
53
54 virtual ~ClientAddressMock() = default;
55
56 private:
57 // the detail here is not used; the slab is just randomly filled with data for the
58 // hmac; this segment is here to show the motivation for slab_size_
59 static constexpr size_t slab_size_ = sizeof(union uland_addr46) + sizeof(std::uint16_t);
60 union {
61 unsigned char c[slab_size_];
62 struct
63 {
64 union uland_addr46 oaddr46;
65 std::uint16_t port;
66 } s;
68};
69
70class PsidCookieTest : public testing::Test
71{
72 openvpn_io::io_context dummy_io_context;
76
77 protected:
79 : dummy_io_context(1), pcfg(new ProtoContext::ProtoConfig())
80 {
81 std::string tls_key_fn = UNITTEST_SOURCE_DIR "/input/psid_cookie_tls.key";
82 pcfg->tls_auth_key.parse_from_file(tls_key_fn);
84 pcfg->set_tls_auth_digest(CryptoAlgs::lookup("SHA256"));
85 pcfg->now = &now;
86 pcfg->handshake_window = Time::Duration::seconds(60);
87 pcfg->key_direction = 0;
88 pcfg->rng.reset(new SSLLib::RandomAPI());
89 pcfg->prng.reset(new MTRand(2020303));
90
92 spf->proto_context_config = pcfg;
93
95 }
96
98 {
99 now = setting;
100 return setting;
101 }
102
103 Time advance_clock(uint64_t binary_ms)
104 {
105 now += Time::Duration::binary_ms(binary_ms);
106 return now;
107 }
108
109 void SetUp() override
110 {
111 }
112
113 void TearDown() override
114 {
115 }
116
117 std::unique_ptr<PsidCookieImpl> pcookie_impl;
118};
119
120
122{
123 PsidCookieImpl *pci_dut = pcookie_impl.get();
124 ASSERT_NE(pci_dut, nullptr);
125
126 // check test clock's equivalence to the PsidCookieImpl clock
127 Time start(set_clock(Time::now()));
128 EXPECT_TRUE(start == *pci_dut->now_);
129
130 // spot check other aspects of successful pci_dut creation
131 EXPECT_TRUE(pci_dut->pcfg_.tls_auth_key.defined());
132 EXPECT_FALSE(pci_dut->not_tls_auth_mode_);
133}
134
136{
137 PsidCookieImpl &pci_dut(*pcookie_impl.get());
138 ClientAddressMock cli_addr(*pci_dut.pcfg_.prng);
139 ProtoSessionID cli_psid;
140 ProtoSessionID srv_psid;
141 // interval duplicates the computation in calculate_session_id_hmac()
142 uint64_t interval = (pci_dut.pcfg_.handshake_window.raw() + 1) / 2;
143 bool hmac_ok;
144
145 cli_psid.randomize(*pci_dut.pcfg_.rng);
146
147 set_clock(Time::now());
148 srv_psid = pci_dut.calculate_session_id_hmac(cli_psid, cli_addr, 0);
149
150 // server is in the same interval in which it offered the hmac
151 hmac_ok = pci_dut.check_session_id_hmac(srv_psid, cli_psid, cli_addr);
152 EXPECT_TRUE(hmac_ok);
153
154 advance_clock(interval);
155 // server is in the next interval after which it offered the hmac
156 hmac_ok = pci_dut.check_session_id_hmac(srv_psid, cli_psid, cli_addr);
157 EXPECT_TRUE(hmac_ok);
158
159 advance_clock(interval);
160 // server is two intervals after which it offered the hmac
161 hmac_ok = pci_dut.check_session_id_hmac(srv_psid, cli_psid, cli_addr);
162 EXPECT_FALSE(hmac_ok);
163}
static constexpr size_t slab_size_
ClientAddressMock(RandomAPI &prng)
union ClientAddressMock::@121 addrport_
const unsigned char * get_abstract_cli_addrport(size_t &slab_size) const override
virtual ~ClientAddressMock()=default
const void * get_impl_info() const override
void SetUp() override
Time advance_clock(uint64_t binary_ms)
Time set_clock(Time setting)
ProtoContext::ProtoConfig::Ptr pcfg
ServerProto::Factory::Ptr spf
openvpn_io::io_context dummy_io_context
std::unique_ptr< PsidCookieImpl > pcookie_impl
void TearDown() override
OpenVPNStaticKey tls_auth_key
leave this undefined to disable tls_auth
Definition proto.hpp:398
StrongRandomAPI::Ptr rng
Definition proto.hpp:358
void randomize(StrongRandomAPI &rng)
Definition psid.hpp:52
Interface to communicate the server's address semantics.
Implements the PsidCookie interface.
bool check_session_id_hmac(const ProtoSessionID &srv_psid, const ProtoSessionID &cli_psid, const PsidCookieAddrInfoBase &pcaib)
const ProtoContext::ProtoConfig & pcfg_
ProtoSessionID calculate_session_id_hmac(const ProtoSessionID &cli_psid, const PsidCookieAddrInfoBase &pcaib, unsigned int offset)
Calculate the psid cookie, the ProtoSessionID hmac.
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
Abstract base class for random number generators.
Definition randapi.hpp:39
void rand_fill(T &obj)
Fill a data object with random bytes.
Definition randapi.hpp:75
static TimeType now()
Definition time.hpp:305
Type lookup(const std::string &name)
uint64_t a6_64[2]
struct in6_addr a6
struct in_addr a4