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 "Values from dhcp-options: false\n");
319}
320
321TEST(Dns, ToStringValuesFromDhcpOptions)
322{
324 config.parse_from_config("dhcp-option DNS6 1::1\n", nullptr);
325 config.update_map();
326 DnsOptionsParser dns(config, false);
327 ASSERT_EQ(dns.to_string(),
328 "DNS Servers:\n"
329 " Priority: 0\n"
330 " Addresses:\n"
331 " 1::1\n"
332 "Values from dhcp-options: true\n");
333}
334
335TEST(Dns, ToStringAllValuesSet)
336{
339 "dns search-domains dom1 dom2 dom3\n"
340 "dns server 10 address 1::1 1.1.1.1\n"
341 "dns server 10 resolve-domains rdom11 rdom12\n"
342 "dns server 10 transport DoT\n"
343 "dns server 10 sni snidom1\n"
344 "dns server 10 dnssec optional\n"
345 "dns server 20 address 2::2 2.2.2.2\n"
346 "dns server 20 resolve-domains rdom21 rdom22\n"
347 "dns server 20 transport DoH\n"
348 "dns server 20 sni snidom2\n"
349 "dns server 20 dnssec yes\n",
350 nullptr);
351 config.update_map();
352 DnsOptionsParser dns(config, false);
353 ASSERT_EQ(dns.to_string(),
354 "DNS Servers:\n"
355 " Priority: 10\n"
356 " Addresses:\n"
357 " 1::1\n"
358 " 1.1.1.1\n"
359 " Domains:\n"
360 " rdom11\n"
361 " rdom12\n"
362 " DNSSEC: Optional\n"
363 " Transport: TLS\n"
364 " SNI: snidom1\n"
365 " Priority: 20\n"
366 " Addresses:\n"
367 " 2::2\n"
368 " 2.2.2.2\n"
369 " Domains:\n"
370 " rdom21\n"
371 " rdom22\n"
372 " DNSSEC: Yes\n"
373 " Transport: HTTPS\n"
374 " SNI: snidom2\n"
375 "DNS Search Domains:\n"
376 " dom1\n"
377 " dom2\n"
378 " dom3\n"
379 "Values from dhcp-options: false\n");
380}
381
382TEST(Dns, JsonRoundtripMinValuesSet)
383{
385 config.parse_from_config("dns server 10 address 1::1\n", nullptr);
386 config.update_map();
387 DnsOptionsParser toJson(config, false);
388 Json::Value json = toJson.to_json();
389 Json::StreamWriterBuilder builder;
390 builder["indentation"] = " ";
391 ASSERT_EQ(Json::writeString(builder, json),
392 "{\n"
393 " \"from_dhcp_options\" : false,\n"
394 " \"servers\" : \n"
395 " {\n"
396 " \"10\" : \n"
397 " {\n"
398 " \"addresses\" : \n"
399 " [\n"
400 " {\n"
401 " \"address\" : \"1::1\"\n"
402 " }\n"
403 " ]\n"
404 " }\n"
405 " }\n"
406 "}");
407
408 DnsOptions fromJson;
409 fromJson.from_json(json, "json test");
410 ASSERT_EQ(fromJson.to_string(),
411 "DNS Servers:\n"
412 " Priority: 10\n"
413 " Addresses:\n"
414 " 1::1\n"
415 "Values from dhcp-options: false\n");
416}
417
418TEST(Dns, JsonRoundtripValuesFromDhcpOption)
419{
421 config.parse_from_config("dhcp-option DNS6 1::1\n", nullptr);
422 config.update_map();
423 DnsOptionsParser toJson(config, false);
424 Json::Value json = toJson.to_json();
425 Json::StreamWriterBuilder builder;
426 builder["indentation"] = " ";
427 ASSERT_EQ(Json::writeString(builder, json),
428 "{\n"
429 " \"from_dhcp_options\" : true,\n"
430 " \"servers\" : \n"
431 " {\n"
432 " \"0\" : \n"
433 " {\n"
434 " \"addresses\" : \n"
435 " [\n"
436 " {\n"
437 " \"address\" : \"1::1\"\n"
438 " }\n"
439 " ]\n"
440 " }\n"
441 " }\n"
442 "}");
443
444 DnsOptions fromJson;
445 fromJson.from_json(json, "json test");
446 ASSERT_EQ(fromJson.to_string(),
447 "DNS Servers:\n"
448 " Priority: 0\n"
449 " Addresses:\n"
450 " 1::1\n"
451 "Values from dhcp-options: true\n");
452}
453
454TEST(Dns, JsonRoundtripAllValuesSet)
455{
458 "dns search-domains dom1 dom2 dom3\n"
459 "dns server 10 address 1::1 1.1.1.1\n"
460 "dns server 10 resolve-domains rdom11 rdom12\n"
461 "dns server 10 transport DoT\n"
462 "dns server 10 sni snidom1\n"
463 "dns server 10 dnssec optional\n"
464 "dns server 20 address [2::2]:5353 2.2.2.2:5353\n"
465 "dns server 20 resolve-domains rdom21 rdom22\n"
466 "dns server 20 transport DoH\n"
467 "dns server 20 sni snidom2\n"
468 "dns server 20 dnssec yes\n",
469 nullptr);
470 config.update_map();
471 DnsOptionsParser toJson(config, false);
472 Json::Value json = toJson.to_json();
473 Json::StreamWriterBuilder builder;
474 builder["indentation"] = " ";
475 ASSERT_EQ(Json::writeString(builder, json),
476 "{\n"
477 " \"from_dhcp_options\" : false,\n"
478 " \"search_domains\" : \n"
479 " [\n"
480 " \"dom1\",\n"
481 " \"dom2\",\n"
482 " \"dom3\"\n"
483 " ],\n"
484 " \"servers\" : \n"
485 " {\n"
486 " \"10\" : \n"
487 " {\n"
488 " \"addresses\" : \n"
489 " [\n"
490 " {\n"
491 " \"address\" : \"1::1\"\n"
492 " },\n"
493 " {\n"
494 " \"address\" : \"1.1.1.1\"\n"
495 " }\n"
496 " ],\n"
497 " \"dnssec\" : \"Optional\",\n"
498 " \"domains\" : \n"
499 " [\n"
500 " \"rdom11\",\n"
501 " \"rdom12\"\n"
502 " ],\n"
503 " \"sni\" : \"snidom1\",\n"
504 " \"transport\" : \"TLS\"\n"
505 " },\n"
506 " \"20\" : \n"
507 " {\n"
508 " \"addresses\" : \n"
509 " [\n"
510 " {\n"
511 " \"address\" : \"2::2\",\n"
512 " \"port\" : 5353\n"
513 " },\n"
514 " {\n"
515 " \"address\" : \"2.2.2.2\",\n"
516 " \"port\" : 5353\n"
517 " }\n"
518 " ],\n"
519 " \"dnssec\" : \"Yes\",\n"
520 " \"domains\" : \n"
521 " [\n"
522 " \"rdom21\",\n"
523 " \"rdom22\"\n"
524 " ],\n"
525 " \"sni\" : \"snidom2\",\n"
526 " \"transport\" : \"HTTPS\"\n"
527 " }\n"
528 " }\n"
529 "}");
530
531 DnsOptions fromJson;
532 fromJson.from_json(json, "json test");
533 ASSERT_EQ(fromJson.to_string(),
534 "DNS Servers:\n"
535 " Priority: 10\n"
536 " Addresses:\n"
537 " 1::1\n"
538 " 1.1.1.1\n"
539 " Domains:\n"
540 " rdom11\n"
541 " rdom12\n"
542 " DNSSEC: Optional\n"
543 " Transport: TLS\n"
544 " SNI: snidom1\n"
545 " Priority: 20\n"
546 " Addresses:\n"
547 " 2::2 5353\n"
548 " 2.2.2.2 5353\n"
549 " Domains:\n"
550 " rdom21\n"
551 " rdom22\n"
552 " DNSSEC: Yes\n"
553 " Transport: HTTPS\n"
554 " SNI: snidom2\n"
555 "DNS Search Domains:\n"
556 " dom1\n"
557 " dom2\n"
558 " dom3\n"
559 "Values from dhcp-options: false\n");
560}
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[]