OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_dns.cpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13#include "test_common.hpp"
14
15#include <json/value.h>
17
18using namespace openvpn;
19
20TEST(Dns, Options)
21{
23
25 "dns server 1 address 1.1.1.1\n"
26 "dns search-domains domain0 domain1\n"
27 "dns server -2 address [2.2.2.2]:5353\n"
28 "dns server -2 resolve-domains rdom0\n"
29 "dns server 1 address [1::1]:5353\n"
30 "dns search-domains domain2\n"
31 "dns server -2 resolve-domains rdom1\n"
32 "dns server -2 dnssec optional\n"
33 "dns server -2 transport DoT\n"
34 "dns server -2 sni hostname\n"
35 "dns server 3 address 3::3 3.2.1.0:4242 [3:3::3:3]:3333\n"
36 "dns server 3 dnssec no\n"
37 "dns server 3 transport DoH\n",
38 nullptr);
39 config.update_map();
40
41 DnsOptionsParser dns(config, false);
42
43 ASSERT_EQ(dns.search_domains.size(), 3u);
44 ASSERT_EQ(dns.search_domains[0].to_string(), "domain0");
45 ASSERT_EQ(dns.search_domains[1].to_string(), "domain1");
46 ASSERT_EQ(dns.search_domains[2].to_string(), "domain2");
47
48 ASSERT_EQ(dns.servers.size(), 3u);
49
50 int i = 1;
51 for (const auto &keyval : dns.servers)
52 {
53 auto priority = keyval.first;
54 auto &server = keyval.second;
55
56 if (priority == -2)
57 {
58 ASSERT_EQ(i, 1);
59
60 ASSERT_TRUE(server.addresses.size() == 1u);
61 ASSERT_EQ(server.addresses[0].address, "2.2.2.2");
62 ASSERT_EQ(server.addresses[0].port, 5353u);
63
64 ASSERT_EQ(server.domains.size(), 2u);
65 ASSERT_EQ(server.domains[0].to_string(), "rdom0");
66 ASSERT_EQ(server.domains[1].to_string(), "rdom1");
67
68 ASSERT_EQ(server.dnssec, DnsServer::Security::Optional);
69
70 ASSERT_EQ(server.transport, DnsServer::Transport::TLS);
71 ASSERT_EQ(server.sni, "hostname");
72 }
73 else if (priority == 1)
74 {
75 ASSERT_EQ(i, 2);
76
77 ASSERT_TRUE(server.addresses.size() == 2u);
78 ASSERT_EQ(server.addresses[0].address, "1.1.1.1");
79 ASSERT_EQ(server.addresses[0].port, 0u);
80
81 ASSERT_EQ(server.addresses[1].address, "1::1");
82 ASSERT_EQ(server.addresses[1].port, 5353u);
83
84 ASSERT_EQ(server.domains.size(), 0u);
85
86 ASSERT_EQ(server.dnssec, DnsServer::Security::Unset);
87
88 ASSERT_EQ(server.transport, DnsServer::Transport::Unset);
89 ASSERT_TRUE(server.sni.empty());
90 }
91 else if (priority == 3)
92 {
93 ASSERT_EQ(i, 3);
94
95 ASSERT_TRUE(server.addresses.size() == 3u);
96 ASSERT_EQ(server.addresses[0].address, "3::3");
97 ASSERT_EQ(server.addresses[0].port, 0u);
98
99 ASSERT_EQ(server.addresses[1].address, "3.2.1.0");
100 ASSERT_EQ(server.addresses[1].port, 4242u);
101
102 ASSERT_EQ(server.addresses[2].address, "3:3::3:3");
103 ASSERT_EQ(server.addresses[2].port, 3333u);
104
105 ASSERT_EQ(server.domains.size(), 0u);
106
107 ASSERT_EQ(server.dnssec, DnsServer::Security::No);
108
109 ASSERT_EQ(server.transport, DnsServer::Transport::HTTPS);
110 ASSERT_TRUE(server.sni.empty());
111 }
112
113 i++;
114 }
115}
116
117TEST(Dns, OptionsMerger)
118{
119 OptionList pushed;
121 DnsOptionsMerger merger;
122
123 pushed.parse_from_config("dns server 1 address ::1", nullptr);
124 config.parse_from_config("dns server 1 address 1.1.1.1\n"
125 "dns server -2 address 2.2.2.2\n",
126 nullptr);
127 pushed.update_map();
128 config.update_map();
129
130 merger.merge(pushed, config);
131 ASSERT_EQ(config.size(), 2u);
132 ASSERT_EQ(pushed.size(), 2u);
133 ASSERT_EQ(pushed[0].ref(4), "::1");
134 ASSERT_EQ(pushed[1].ref(4), "2.2.2.2");
135}
136
137TEST(Dns, ServerNoAddress)
138{
140 config.parse_from_config("dns server 0 resolve-domains dom0\n", nullptr);
141 config.update_map();
143 option_error,
144 "dns server 0 does not have an address assigned");
145}
146
147TEST(Dns, ServerEightAddresses)
148{
150 config.parse_from_config("dns server 0 address 1::1 2::2 3::3 4::4 5::5 6::6 7::7 8::8\n", nullptr);
151 config.update_map();
152 DnsOptionsParser dns(config, false);
153 ASSERT_EQ(dns.servers.size(), 1u);
154 ASSERT_EQ(dns.servers[0].addresses.size(), 8u);
155}
156
157TEST(Dns, ServerTooManyAddresses)
158{
160 config.parse_from_config("dns server 0 address 1::1 2::2 3::3 4::4 5::5 6::6 7::7 8::8 9::9\n", nullptr);
161 config.update_map();
163 option_error,
164 "dns server 0 option 'address' unknown or too many parameters");
165}
166
167TEST(Dns, ServerInvalidAddress)
168{
170 config.parse_from_config("dns server 0 address 1.1.1.1 foobar\n", nullptr);
171 config.update_map();
173 option_error,
174 "dns server 0 invalid address: foobar");
175}
176
177TEST(Dns, ServerInvalidDnssec)
178{
179 {
181 config.parse_from_config("dns server 0 dnssec foo\n", nullptr);
182 config.update_map();
184 option_error,
185 "dns server 0 dnssec setting 'foo' invalid");
186 }
187 {
189 config.parse_from_config("dns server 0 dnssec yes no\n", nullptr);
190 config.update_map();
192 option_error,
193 "dns server 0 option 'dnssec' unknown or too many parameters");
194 }
195}
196
197TEST(Dns, ServerInvalidTransport)
198{
199 {
201 config.parse_from_config("dns server 0 transport avian-carrier\n", nullptr);
202 config.update_map();
204 option_error,
205 "dns server 0 transport 'avian-carrier' invalid");
206 }
207 {
209 config.parse_from_config("dns server 0 transport DoT D'oh\n", nullptr);
210 config.update_map();
212 option_error,
213 "dns server 0 option 'transport' unknown or too many parameters");
214 }
215}
216
217TEST(Dns, dhcp_options)
218{
221 "dhcp-option DNS 1.1.1.1\n"
222 "dhcp-option DNS6 1::1\n"
223 "dhcp-option DOMAIN domain0\n"
224 "dhcp-option DOMAIN-SEARCH domain1\n"
225 "dhcp-option ADAPTER_DOMAIN_SUFFIX adsX\n"
226 "dhcp-option ADAPTER_DOMAIN_SUFFIX ads\n",
227 nullptr);
228 config.update_map();
229
230 DnsOptionsParser dns(config, false);
231
232 ASSERT_TRUE(dns.from_dhcp_options);
233
234 ASSERT_EQ(dns.search_domains.size(), 3u);
235 ASSERT_EQ(dns.search_domains[0].to_string(), "ads");
236 ASSERT_EQ(dns.search_domains[1].to_string(), "domain0");
237 ASSERT_EQ(dns.search_domains[2].to_string(), "domain1");
238
239 ASSERT_EQ(dns.servers.size(), 1u);
240 ASSERT_TRUE(dns.servers[0].addresses.size() == 2u);
241 ASSERT_EQ(dns.servers[0].addresses[0].address, "1.1.1.1");
242 ASSERT_EQ(dns.servers[0].addresses[0].port, 0u);
243
244 ASSERT_EQ(dns.servers[0].addresses[1].address, "1::1");
245 ASSERT_EQ(dns.servers[0].addresses[1].port, 0u);
246}
247
248TEST(Dns, dhcp_options_with_split_domains)
249{
252 "dhcp-option DNS 1.1.1.1\n"
253 "dhcp-option DNS6 1::1\n"
254 "dhcp-option DOMAIN domain0\n"
255 "dhcp-option DOMAIN-SEARCH domain1\n"
256 "dhcp-option ADAPTER_DOMAIN_SUFFIX adsX\n"
257 "dhcp-option ADAPTER_DOMAIN_SUFFIX ads\n",
258 nullptr);
259 config.update_map();
260
261 DnsOptionsParser dns(config, true);
262
263 ASSERT_TRUE(dns.from_dhcp_options);
264
265 ASSERT_EQ(dns.search_domains.size(), 1u);
266 ASSERT_EQ(dns.search_domains[0].to_string(), "ads");
267
268 ASSERT_EQ(dns.servers.size(), 1u);
269
270 ASSERT_TRUE(dns.servers[0].addresses.size() == 2u);
271 ASSERT_EQ(dns.servers[0].addresses[0].address, "1.1.1.1");
272 ASSERT_EQ(dns.servers[0].addresses[0].port, 0u);
273 ASSERT_EQ(dns.servers[0].addresses[1].address, "1::1");
274 ASSERT_EQ(dns.servers[0].addresses[1].port, 0u);
275
276 ASSERT_TRUE(dns.servers[0].domains.size() == 2u);
277 ASSERT_EQ(dns.servers[0].domains[0].domain, "domain0");
278 ASSERT_EQ(dns.servers[0].domains[1].domain, "domain1");
279}
280
281TEST(Dns, dhcp_options_ignored)
282{
285 "dhcp-option DNS 1.1.1.1\n"
286 "dhcp-option DNS6 1::1\n"
287 "dhcp-option DOMAIN domain0\n"
288 "dhcp-option DOMAIN-SEARCH domain1\n"
289 "dhcp-option ADAPTER_DOMAIN_SUFFIX adsX\n"
290 "dns server 123 address 123::123\n"
291 "dhcp-option ADAPTER_DOMAIN_SUFFIX ads\n",
292 nullptr);
293 config.update_map();
294
295 DnsOptionsParser dns(config, true);
296
297 ASSERT_FALSE(dns.from_dhcp_options);
298 ASSERT_TRUE(dns.search_domains.empty());
299 ASSERT_EQ(dns.servers.size(), 1u);
300
301 ASSERT_TRUE(dns.servers[123].domains.empty());
302 ASSERT_TRUE(dns.servers[123].addresses.size() == 1u);
303 ASSERT_EQ(dns.servers[123].addresses[0].address, "123::123");
304 ASSERT_EQ(dns.servers[123].addresses[0].port, 0u);
305}
306
307TEST(Dns, ToStringMinValuesSet)
308{
310 config.parse_from_config("dns server 10 address 1::1\n", nullptr);
311 config.update_map();
312 DnsOptionsParser dns(config, false);
313 ASSERT_EQ(dns.to_string(),
314 "DNS Servers:\n"
315 " Priority: 10\n"
316 " Addresses:\n"
317 " 1::1\n");
318}
319
320TEST(Dns, ToStringAllValuesSet)
321{
324 "dns search-domains dom1 dom2 dom3\n"
325 "dns server 10 address 1::1 1.1.1.1\n"
326 "dns server 10 resolve-domains rdom11 rdom12\n"
327 "dns server 10 transport DoT\n"
328 "dns server 10 sni snidom1\n"
329 "dns server 10 dnssec optional\n"
330 "dns server 20 address 2::2 2.2.2.2\n"
331 "dns server 20 resolve-domains rdom21 rdom22\n"
332 "dns server 20 transport DoH\n"
333 "dns server 20 sni snidom2\n"
334 "dns server 20 dnssec yes\n",
335 nullptr);
336 config.update_map();
337 DnsOptionsParser dns(config, false);
338 ASSERT_EQ(dns.to_string(),
339 "DNS Servers:\n"
340 " Priority: 10\n"
341 " Addresses:\n"
342 " 1::1\n"
343 " 1.1.1.1\n"
344 " Domains:\n"
345 " rdom11\n"
346 " rdom12\n"
347 " DNSSEC: Optional\n"
348 " Transport: TLS\n"
349 " SNI: snidom1\n"
350 " Priority: 20\n"
351 " Addresses:\n"
352 " 2::2\n"
353 " 2.2.2.2\n"
354 " Domains:\n"
355 " rdom21\n"
356 " rdom22\n"
357 " DNSSEC: Yes\n"
358 " Transport: HTTPS\n"
359 " SNI: snidom2\n"
360 "DNS Search Domains:\n"
361 " dom1\n"
362 " dom2\n"
363 " dom3\n");
364}
365
366TEST(Dns, JsonRoundtripMinValuesSet)
367{
369 config.parse_from_config("dns server 10 address 1::1\n", nullptr);
370 config.update_map();
371 DnsOptionsParser toJson(config, false);
372 Json::Value json = toJson.to_json();
373 Json::StreamWriterBuilder builder;
374 builder["indentation"] = " ";
375 ASSERT_EQ(Json::writeString(builder, json),
376 "{\n"
377 " \"servers\" : \n"
378 " {\n"
379 " \"10\" : \n"
380 " {\n"
381 " \"addresses\" : \n"
382 " [\n"
383 " {\n"
384 " \"address\" : \"1::1\"\n"
385 " }\n"
386 " ]\n"
387 " }\n"
388 " }\n"
389 "}");
390
391 DnsOptions fromJson;
392 fromJson.from_json(json, "json test");
393 ASSERT_EQ(fromJson.to_string(),
394 "DNS Servers:\n"
395 " Priority: 10\n"
396 " Addresses:\n"
397 " 1::1\n");
398}
399
400TEST(Dns, JsonRoundtripAllValuesSet)
401{
404 "dns search-domains dom1 dom2 dom3\n"
405 "dns server 10 address 1::1 1.1.1.1\n"
406 "dns server 10 resolve-domains rdom11 rdom12\n"
407 "dns server 10 transport DoT\n"
408 "dns server 10 sni snidom1\n"
409 "dns server 10 dnssec optional\n"
410 "dns server 20 address [2::2]:5353 2.2.2.2:5353\n"
411 "dns server 20 resolve-domains rdom21 rdom22\n"
412 "dns server 20 transport DoH\n"
413 "dns server 20 sni snidom2\n"
414 "dns server 20 dnssec yes\n",
415 nullptr);
416 config.update_map();
417 DnsOptionsParser toJson(config, false);
418 Json::Value json = toJson.to_json();
419 Json::StreamWriterBuilder builder;
420 builder["indentation"] = " ";
421 ASSERT_EQ(Json::writeString(builder, json),
422 "{\n"
423 " \"search_domains\" : \n"
424 " [\n"
425 " \"dom1\",\n"
426 " \"dom2\",\n"
427 " \"dom3\"\n"
428 " ],\n"
429 " \"servers\" : \n"
430 " {\n"
431 " \"10\" : \n"
432 " {\n"
433 " \"addresses\" : \n"
434 " [\n"
435 " {\n"
436 " \"address\" : \"1::1\"\n"
437 " },\n"
438 " {\n"
439 " \"address\" : \"1.1.1.1\"\n"
440 " }\n"
441 " ],\n"
442 " \"dnssec\" : \"Optional\",\n"
443 " \"domains\" : \n"
444 " [\n"
445 " \"rdom11\",\n"
446 " \"rdom12\"\n"
447 " ],\n"
448 " \"sni\" : \"snidom1\",\n"
449 " \"transport\" : \"TLS\"\n"
450 " },\n"
451 " \"20\" : \n"
452 " {\n"
453 " \"addresses\" : \n"
454 " [\n"
455 " {\n"
456 " \"address\" : \"2::2\",\n"
457 " \"port\" : 5353\n"
458 " },\n"
459 " {\n"
460 " \"address\" : \"2.2.2.2\",\n"
461 " \"port\" : 5353\n"
462 " }\n"
463 " ],\n"
464 " \"dnssec\" : \"Yes\",\n"
465 " \"domains\" : \n"
466 " [\n"
467 " \"rdom21\",\n"
468 " \"rdom22\"\n"
469 " ],\n"
470 " \"sni\" : \"snidom2\",\n"
471 " \"transport\" : \"HTTPS\"\n"
472 " }\n"
473 " }\n"
474 "}");
475
476 DnsOptions fromJson;
477 fromJson.from_json(json, "json test");
478 ASSERT_EQ(fromJson.to_string(),
479 "DNS Servers:\n"
480 " Priority: 10\n"
481 " Addresses:\n"
482 " 1::1\n"
483 " 1.1.1.1\n"
484 " Domains:\n"
485 " rdom11\n"
486 " rdom12\n"
487 " DNSSEC: Optional\n"
488 " Transport: TLS\n"
489 " SNI: snidom1\n"
490 " Priority: 20\n"
491 " Addresses:\n"
492 " 2::2 5353\n"
493 " 2.2.2.2 5353\n"
494 " Domains:\n"
495 " rdom21\n"
496 " rdom22\n"
497 " DNSSEC: Yes\n"
498 " Transport: HTTPS\n"
499 " SNI: snidom2\n"
500 "DNS Search Domains:\n"
501 " dom1\n"
502 " dom2\n"
503 " dom3\n");
504}
void parse_from_config(const std::string &str, Limits *lim)
Definition options.hpp:985
void merge(OptionList &pushed, const OptionList &config) const override
Definition dns.hpp:338
All DNS options set with the –dns or –dhcp-option directive.
std::map< int, DnsServer > servers
void from_json(const Json::Value &root, const std::string &title)
std::vector< DnsDomain > search_domains
std::string to_string() const
Json::Value to_json() const
TEST(Dns, Options)
Definition test_dns.cpp:20
#define JY_EXPECT_THROW
static const char config[]