]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/test-proxy_protocol_cc.cc
Merge pull request #9073 from pieterlexis/runtime-dirs-virtual-hosting
[thirdparty/pdns.git] / pdns / test-proxy_protocol_cc.cc
CommitLineData
530e3e1a
PD
1#define BOOST_TEST_DYN_LINK
2#define BOOST_TEST_NO_MAIN
3#include <boost/test/unit_test.hpp>
4
5#include "iputils.hh"
6#include "proxy-protocol.hh"
7
8using namespace boost;
9using std::string;
10
11
12BOOST_AUTO_TEST_SUITE(test_proxy_protocol_cc)
13
14#define BINARY(s) (std::string(s, sizeof(s) - 1))
15
16#define PROXYMAGIC "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
17#define PROXYMAGICLEN sizeof(PROXYMAGIC)-1
18
19static string proxymagic(PROXYMAGIC, PROXYMAGICLEN);
20
21BOOST_AUTO_TEST_CASE(test_roundtrip) {
bde73d5b 22 std::vector<ProxyProtocolValue> values;
530e3e1a
PD
23 string proxyheader;
24
25 bool ptcp = true;
26 ComboAddress src("65.66.67.68:18762"); // 18762 = 0x494a = "IJ"
27 ComboAddress dest("69.70.71.72:19276"); // 19276 = 0x4b4c = "KL"
bde73d5b 28 proxyheader = makeProxyHeader(ptcp, src, dest, values);
530e3e1a
PD
29
30 BOOST_CHECK_EQUAL(proxyheader, BINARY(
31 PROXYMAGIC
32 "\x21" // version | command
33 "\x11" // ipv4=0x10 | TCP=0x1
34 "\x00\x0c" // 4 bytes IPv4 * 2 + 2 port numbers = 8 + 2 * 2 =12 = 0xc
35 "ABCD" // 65.66.67.68
36 "EFGH" // 69.70.71.72
37 "IJ" // src port
38 "KL" // dst port
39 ));
40
8c73c703 41 bool proxy;
530e3e1a
PD
42 bool ptcp2;
43 ComboAddress src2, dest2;
44
8c73c703 45 BOOST_CHECK_EQUAL(parseProxyHeader(proxyheader, proxy, src2, dest2, ptcp2, values), 28);
530e3e1a 46
8c73c703 47 BOOST_CHECK_EQUAL(proxy, true);
530e3e1a 48 BOOST_CHECK_EQUAL(ptcp2, true);
9a6a9e15
RG
49 BOOST_CHECK(src2 == src);
50 BOOST_CHECK(dest2 == dest);
51}
52
53BOOST_AUTO_TEST_CASE(test_local_proxy_header) {
54 auto payload = makeLocalProxyHeader();
55
56 BOOST_CHECK_EQUAL(payload, BINARY(
57 PROXYMAGIC
58 "\x20" // version | command
59 "\x00" // protocol family and address are set to 0
60 "\x00\x00" // no content
61 ));
62
63 bool proxy;
64 bool tcp = false;
65 ComboAddress src, dest;
66 std::vector<ProxyProtocolValue> values;
67
68 BOOST_CHECK_EQUAL(parseProxyHeader(payload, proxy, src, dest, tcp, values), 16);
69
70 BOOST_CHECK_EQUAL(proxy, false);
71 BOOST_CHECK_EQUAL(tcp, false);
72 BOOST_CHECK_EQUAL(values.size(), 0U);
73}
74
75BOOST_AUTO_TEST_CASE(test_tlv_values_content_len_signedness) {
76 std::string largeValue;
77 /* this value will make the content length parsing fail in case of signedness mistake */
78 largeValue.resize(65128, 'A');
79 const std::vector<ProxyProtocolValue> values = { { "foo", 0 }, { largeValue, 255 }};
80
81 const bool tcp = false;
82 const ComboAddress src("[2001:db8::1]:0");
83 const ComboAddress dest("[::1]:65535");
84 const auto payload = makeProxyHeader(tcp, src, dest, values);
85
86 bool proxy;
87 bool tcp2;
88 ComboAddress src2;
89 ComboAddress dest2;
90 std::vector<ProxyProtocolValue> parsedValues;
91
92 BOOST_CHECK_EQUAL(parseProxyHeader(payload, proxy, src2, dest2, tcp2, parsedValues), 16 + 36 + 6 + 65131);
93 BOOST_CHECK_EQUAL(proxy, true);
94 BOOST_CHECK_EQUAL(tcp2, tcp);
95 BOOST_CHECK(src2 == src);
96 BOOST_CHECK(dest2 == dest);
97 BOOST_REQUIRE_EQUAL(parsedValues.size(), values.size());
98 for (size_t idx = 0; idx < values.size(); idx++) {
99 BOOST_CHECK_EQUAL(parsedValues.at(idx).type, values.at(idx).type);
100 BOOST_CHECK_EQUAL(parsedValues.at(idx).content, values.at(idx).content);
101 }
102}
103
104BOOST_AUTO_TEST_CASE(test_tlv_values_length_signedness) {
105 std::string largeValue;
106 /* this value will make the TLV length parsing fail in case of signedness mistake */
107 largeValue.resize(65000, 'A');
108 const std::vector<ProxyProtocolValue> values = { { "foo", 0 }, { largeValue, 255 }};
109
110 const bool tcp = false;
111 const ComboAddress src("[2001:db8::1]:0");
112 const ComboAddress dest("[::1]:65535");
113 const auto payload = makeProxyHeader(tcp, src, dest, values);
114
115 bool proxy;
116 bool tcp2;
117 ComboAddress src2;
118 ComboAddress dest2;
119 std::vector<ProxyProtocolValue> parsedValues;
120
121 BOOST_CHECK_EQUAL(parseProxyHeader(payload, proxy, src2, dest2, tcp2, parsedValues), 16 + 36 + 6 + 65003);
122 BOOST_CHECK_EQUAL(proxy, true);
123 BOOST_CHECK_EQUAL(tcp2, tcp);
124 BOOST_CHECK(src2 == src);
125 BOOST_CHECK(dest2 == dest);
126 BOOST_REQUIRE_EQUAL(parsedValues.size(), values.size());
127 for (size_t idx = 0; idx < values.size(); idx++) {
128 BOOST_CHECK_EQUAL(parsedValues.at(idx).type, values.at(idx).type);
129 BOOST_CHECK_EQUAL(parsedValues.at(idx).content, values.at(idx).content);
130 }
131}
132
133BOOST_AUTO_TEST_CASE(test_parsing_invalid_headers) {
134 const std::vector<ProxyProtocolValue> noValues;
135
136 const bool tcp = false;
137 const ComboAddress src("[2001:db8::1]:0");
138 const ComboAddress dest("[::1]:65535");
139 const auto payload = makeProxyHeader(tcp, src, dest, noValues);
140
141 bool proxy;
142 bool tcp2;
143 ComboAddress src2;
144 ComboAddress dest2;
145 std::vector<ProxyProtocolValue> values;
146
147 {
148 /* just checking that everything works */
149 BOOST_CHECK_EQUAL(parseProxyHeader(payload, proxy, src2, dest2, tcp2, values), 52);
150 BOOST_CHECK_EQUAL(proxy, true);
151 BOOST_CHECK_EQUAL(tcp2, tcp);
152 BOOST_CHECK(src2 == src);
153 BOOST_CHECK(dest2 == dest);
154 BOOST_CHECK_EQUAL(values.size(), 0U);
155 }
156
157 {
158 /* too short (not even full header) */
159 std::string truncated = payload;
160 truncated.resize(15);
161 BOOST_CHECK_EQUAL(parseProxyHeader(truncated, proxy, src2, dest2, tcp2, values), -1);
162 }
163
164 {
165 /* too short (missing address part) */
166 std::string truncated = payload;
167 truncated.resize(/* full header */ 16 + /* two IPv6s + port */ 36 - /* truncation */ 1);
168 BOOST_CHECK_EQUAL(parseProxyHeader(truncated, proxy, src2, dest2, tcp2, values), -1);
169 }
170
171 {
172 /* too short (missing TLV) */
173 values = { { "foo", 0 }, { "bar", 255 }} ;
174 const auto payloadWithValues = makeProxyHeader(tcp, src, dest, values);
175
176 std::string truncated = payloadWithValues;
177 truncated.resize(/* full header */ 16 + /* two IPv6s + port */ 36 + /* TLV 1 */ 6 + /* TLV 2 */ 6 - /* truncation */ 2);
178 BOOST_CHECK_EQUAL(parseProxyHeader(truncated, proxy, src2, dest2, tcp2, values), -2);
179 }
180
181 {
182 /* invalid magic */
183 std::string invalid = payload;
184 invalid.at(4) = 42;
185 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
186 }
187
188 {
189 /* invalid version */
190 std::string invalid = payload;
191 invalid.at(12) = 0x10 | 0x01;
192 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
193 }
194
195 {
196 /* invalid command */
197 std::string invalid = payload;
198 invalid.at(12) = 0x20 | 0x02;
199 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
200 }
201
202 {
203 /* invalid family */
204 std::string invalid = payload;
205 invalid.at(13) = (0x04 << 4) | 0x01 /* STREAM */;
206 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
207 }
208
209 {
210 /* invalid address */
211 std::string invalid = payload;
212 invalid.at(13) = (0x02 /* AF_INET */ << 4) | 0x03;
213 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
214 }
215
216 {
217 /* TLV advertised len gets out of bounds */
218 values = { { "foo", 0 }, { "bar", 255 }} ;
219 const auto payloadWithValues = makeProxyHeader(tcp, src, dest, values);
220 std::string invalid = payloadWithValues;
221 /* full header (16) + two IPv6s + port (36) + TLV (6) TLV 2 (6) */
222 invalid.at(59) += 1;
223 BOOST_CHECK_EQUAL(parseProxyHeader(invalid, proxy, src2, dest2, tcp2, values), 0);
224 }
530e3e1a
PD
225}
226
227BOOST_AUTO_TEST_SUITE_END()