1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/public/dns_over_https_server_config.h"
6
7 #include <string>
8
9 #include "base/json/json_reader.h"
10 #include "net/base/ip_address.h"
11 #include "net/dns/public/dns_over_https_config.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace net {
16 namespace {
17
18 const IPAddress ip1(192, 0, 2, 1);
19 const IPAddress ip2(0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
20 const IPAddress ip3(192, 0, 2, 2);
21 const IPAddress ip4(0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2);
22 const DnsOverHttpsServerConfig::Endpoints endpoints{{ip1, ip2}, {ip3, ip4}};
23
TEST(DnsOverHttpsServerConfigTest,ValidWithGet)24 TEST(DnsOverHttpsServerConfigTest, ValidWithGet) {
25 auto parsed = DnsOverHttpsServerConfig::FromString(
26 "https://dnsserver.example.net/dns-query{?dns}");
27 EXPECT_THAT(parsed, testing::Optional(testing::Property(
28 &DnsOverHttpsServerConfig::use_post, false)));
29
30 parsed = DnsOverHttpsServerConfig::FromString(
31 "https://dnsserver.example.net/dns-query{?dns,extra}");
32 EXPECT_THAT(parsed, testing::Optional(testing::Property(
33 &DnsOverHttpsServerConfig::use_post, false)));
34
35 parsed = DnsOverHttpsServerConfig::FromString(
36 "https://query:{dns}@dnsserver.example.net");
37 EXPECT_THAT(parsed, testing::Optional(testing::Property(
38 &DnsOverHttpsServerConfig::use_post, false)));
39
40 parsed = DnsOverHttpsServerConfig::FromString(
41 "https://dnsserver.example.net{/dns}");
42 EXPECT_THAT(parsed, testing::Optional(testing::Property(
43 &DnsOverHttpsServerConfig::use_post, false)));
44 }
45
TEST(DnsOverHttpsServerConfigTest,ValidWithPost)46 TEST(DnsOverHttpsServerConfigTest, ValidWithPost) {
47 auto parsed = DnsOverHttpsServerConfig::FromString(
48 "https://dnsserver.example.net/dns-query{?query}");
49 EXPECT_THAT(parsed, testing::Optional(testing::Property(
50 &DnsOverHttpsServerConfig::use_post, true)));
51
52 parsed = DnsOverHttpsServerConfig::FromString(
53 "https://dnsserver.example.net/dns-query");
54 EXPECT_THAT(parsed, testing::Optional(testing::Property(
55 &DnsOverHttpsServerConfig::use_post, true)));
56 }
57
TEST(DnsOverHttpsServerConfigTest,Invalid)58 TEST(DnsOverHttpsServerConfigTest, Invalid) {
59 // Invalid template format
60 EXPECT_FALSE(DnsOverHttpsServerConfig::FromString(
61 "https://dnsserver.example.net/dns-query{{?dns}}"));
62 // Must be HTTPS
63 EXPECT_FALSE(DnsOverHttpsServerConfig::FromString(
64 "http://dnsserver.example.net/dns-query"));
65 EXPECT_FALSE(DnsOverHttpsServerConfig::FromString(
66 "http://dnsserver.example.net/dns-query{?dns}"));
67 // Template must expand to a valid URL
68 EXPECT_FALSE(DnsOverHttpsServerConfig::FromString("https://{?dns}"));
69 // The hostname must not contain the dns variable
70 EXPECT_FALSE(
71 DnsOverHttpsServerConfig::FromString("https://{dns}.dnsserver.net"));
72 }
73
TEST(DnsOverHttpsServerConfigTest,Empty)74 TEST(DnsOverHttpsServerConfigTest, Empty) {
75 EXPECT_FALSE(net::DnsOverHttpsServerConfig::FromString(""));
76 }
77
TEST(DnsOverHttpsServerConfigTest,Simple)78 TEST(DnsOverHttpsServerConfigTest, Simple) {
79 auto parsed = DnsOverHttpsServerConfig::FromString(
80 "https://dnsserver.example.net/dns-query{?dns}");
81 EXPECT_THAT(parsed, testing::Optional(testing::Property(
82 &DnsOverHttpsServerConfig::IsSimple, true)));
83 }
84
TEST(DnsOverHttpsServerConfigTest,ToValueSimple)85 TEST(DnsOverHttpsServerConfigTest, ToValueSimple) {
86 auto parsed = DnsOverHttpsServerConfig::FromString(
87 "https://dnsserver.example.net/dns-query{?dns}");
88 ASSERT_TRUE(parsed);
89
90 base::Value expected = *base::JSONReader::Read(R"(
91 {
92 "template": "https://dnsserver.example.net/dns-query{?dns}"
93 }
94 )");
95 EXPECT_EQ(expected.GetDict(), parsed->ToValue());
96 }
97
TEST(DnsOverHttpsServerConfigTest,ToValueWithEndpoints)98 TEST(DnsOverHttpsServerConfigTest, ToValueWithEndpoints) {
99 auto parsed = DnsOverHttpsServerConfig::FromString(
100 "https://dnsserver.example.net/dns-query{?dns}", endpoints);
101 ASSERT_TRUE(parsed);
102
103 EXPECT_THAT(parsed, testing::Optional(testing::Property(
104 &DnsOverHttpsServerConfig::IsSimple, false)));
105 EXPECT_THAT(parsed, testing::Optional(testing::Property(
106 &DnsOverHttpsServerConfig::endpoints, endpoints)));
107
108 base::Value expected = *base::JSONReader::Read(
109 R"({
110 "template": "https://dnsserver.example.net/dns-query{?dns}",
111 "endpoints": [{
112 "ips": ["192.0.2.1", "2001:db8::1"]
113 }, {
114 "ips": ["192.0.2.2", "2001:db8::2"]
115 }]
116 })");
117 EXPECT_EQ(expected.GetDict(), parsed->ToValue());
118 }
119
TEST(DnsOverHttpsServerConfigTest,FromValueSimple)120 TEST(DnsOverHttpsServerConfigTest, FromValueSimple) {
121 base::Value input = *base::JSONReader::Read(R"(
122 {
123 "template": "https://dnsserver.example.net/dns-query{?dns}"
124 }
125 )");
126
127 auto parsed =
128 DnsOverHttpsServerConfig::FromValue(std::move(input).TakeDict());
129
130 auto expected = DnsOverHttpsServerConfig::FromString(
131 "https://dnsserver.example.net/dns-query{?dns}");
132 EXPECT_EQ(expected, parsed);
133 }
134
TEST(DnsOverHttpsServerConfigTest,FromValueWithEndpoints)135 TEST(DnsOverHttpsServerConfigTest, FromValueWithEndpoints) {
136 base::Value input = *base::JSONReader::Read(R"(
137 {
138 "template": "https://dnsserver.example.net/dns-query{?dns}",
139 "endpoints": [{
140 "ips": ["192.0.2.1", "2001:db8::1"]
141 }, {
142 "ips": ["192.0.2.2", "2001:db8::2"]
143 }]
144 }
145 )");
146
147 auto parsed =
148 DnsOverHttpsServerConfig::FromValue(std::move(input).TakeDict());
149
150 auto expected = DnsOverHttpsServerConfig::FromString(
151 "https://dnsserver.example.net/dns-query{?dns}", endpoints);
152 EXPECT_EQ(expected, parsed);
153 }
154
TEST(DnsOverHttpsServerConfigTest,FromValueWithUnknownKey)155 TEST(DnsOverHttpsServerConfigTest, FromValueWithUnknownKey) {
156 base::Value input = *base::JSONReader::Read(R"(
157 {
158 "template": "https://dnsserver.example.net/dns-query{?dns}",
159 "unknown key": "value is ignored"
160 }
161 )");
162
163 auto parsed =
164 DnsOverHttpsServerConfig::FromValue(std::move(input).TakeDict());
165
166 auto expected = DnsOverHttpsServerConfig::FromString(
167 "https://dnsserver.example.net/dns-query{?dns}");
168 EXPECT_EQ(expected, parsed);
169 }
170
TEST(DnsOverHttpsServerConfigTest,FromValueInvalid)171 TEST(DnsOverHttpsServerConfigTest, FromValueInvalid) {
172 // Empty dict
173 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(base::Value::Dict()));
174
175 // Wrong scheme
176 base::StringPiece input = R"(
177 {
178 "template": "http://dnsserver.example.net/dns-query{?dns}"
179 }
180 )";
181 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
182 std::move(base::JSONReader::Read(input)->GetDict())));
183
184 // Wrong template type
185 input = R"({"template": 12345})";
186 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
187 std::move(base::JSONReader::Read(input)->GetDict())));
188
189 // Wrong endpoints type
190 input = R"(
191 {
192 "template": "https://dnsserver.example.net/dns-query{?dns}",
193 "endpoints": {
194 "ips": ["192.0.2.1", "2001:db8::1"]
195 }
196 }
197 )";
198 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
199 std::move(base::JSONReader::Read(input)->GetDict())));
200
201 // Wrong "ips" type
202 input = R"(
203 {
204 "template": "https://dnsserver.example.net/dns-query{?dns}",
205 "endpoints": [{
206 "ips": "192.0.2.1"
207 }]
208 }
209 )";
210 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
211 std::move(base::JSONReader::Read(input)->GetDict())));
212
213 // Wrong IP type
214 input = R"(
215 {
216 "template": "https://dnsserver.example.net/dns-query{?dns}",
217 "endpoints": [{
218 "ips": ["2001:db8::1", 192.021]
219 }]
220 }
221 )";
222 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
223 std::move(base::JSONReader::Read(input)->GetDict())));
224
225 // Bad IP address
226 input = R"(
227 {
228 "template": "https://dnsserver.example.net/dns-query{?dns}",
229 "endpoints": [{
230 "ips": ["2001:db8::1", "256.257.258.259"]
231 }]
232 }
233 )";
234 EXPECT_FALSE(DnsOverHttpsServerConfig::FromValue(
235 std::move(base::JSONReader::Read(input)->GetDict())));
236 }
237
238 } // namespace
239 } // namespace net
240