1 // Copyright 2020 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/https_record_rdata.h"
6
7 #include <map>
8 #include <memory>
9 #include <optional>
10 #include <string>
11 #include <string_view>
12 #include <vector>
13
14 #include "net/base/ip_address.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19 namespace {
20
TEST(HttpsRecordRdataTest,ParsesAlias)21 TEST(HttpsRecordRdataTest, ParsesAlias) {
22 const char kRdata[] =
23 // Priority: 0 for alias record
24 "\000\000"
25 // Alias name: chromium.org
26 "\010chromium\003org\000";
27
28 std::unique_ptr<HttpsRecordRdata> rdata =
29 HttpsRecordRdata::Parse(std::string_view(kRdata, sizeof(kRdata) - 1));
30 ASSERT_TRUE(rdata);
31
32 AliasFormHttpsRecordRdata expected("chromium.org");
33 EXPECT_TRUE(rdata->IsEqual(&expected));
34
35 EXPECT_TRUE(rdata->IsAlias());
36 AliasFormHttpsRecordRdata* alias_rdata = rdata->AsAliasForm();
37 ASSERT_TRUE(alias_rdata);
38 EXPECT_EQ(alias_rdata->alias_name(), "chromium.org");
39 }
40
TEST(HttpsRecordRdataTest,ParseAliasWithEmptyName)41 TEST(HttpsRecordRdataTest, ParseAliasWithEmptyName) {
42 const char kRdata[] =
43 // Priority: 0 for alias record
44 "\000\000"
45 // Alias name: ""
46 "\000";
47
48 std::unique_ptr<HttpsRecordRdata> rdata =
49 HttpsRecordRdata::Parse(std::string_view(kRdata, sizeof(kRdata) - 1));
50 ASSERT_TRUE(rdata);
51
52 AliasFormHttpsRecordRdata expected("");
53 EXPECT_TRUE(rdata->IsEqual(&expected));
54
55 EXPECT_TRUE(rdata->IsAlias());
56 AliasFormHttpsRecordRdata* alias_rdata = rdata->AsAliasForm();
57 ASSERT_TRUE(alias_rdata);
58 EXPECT_TRUE(alias_rdata->alias_name().empty());
59 }
60
TEST(HttpsRecordRdataTest,IgnoreAliasParams)61 TEST(HttpsRecordRdataTest, IgnoreAliasParams) {
62 const char kRdata[] =
63 // Priority: 0 for alias record
64 "\000\000"
65 // Alias name: chromium.org
66 "\010chromium\003org\000"
67 // no-default-alpn
68 "\000\002\000\000";
69
70 std::unique_ptr<HttpsRecordRdata> rdata =
71 HttpsRecordRdata::Parse(std::string_view(kRdata, sizeof(kRdata) - 1));
72 ASSERT_TRUE(rdata);
73
74 AliasFormHttpsRecordRdata expected("chromium.org");
75 EXPECT_TRUE(rdata->IsEqual(&expected));
76
77 EXPECT_TRUE(rdata->IsAlias());
78 AliasFormHttpsRecordRdata* alias_rdata = rdata->AsAliasForm();
79 ASSERT_TRUE(alias_rdata);
80 EXPECT_EQ(alias_rdata->alias_name(), "chromium.org");
81 }
82
TEST(HttpsRecordRdataTest,ParsesService)83 TEST(HttpsRecordRdataTest, ParsesService) {
84 const char kRdata[] =
85 // Priority: 1
86 "\000\001"
87 // Service name: chromium.org
88 "\010chromium\003org\000"
89 // mandatory=alpn,no-default-alpn,port,ipv4hint,echconfig,ipv6hint
90 "\000\000\000\014\000\001\000\002\000\003\000\004\000\005\000\006"
91 // alpn=foo,bar
92 "\000\001\000\010\003foo\003bar"
93 // no-default-alpn
94 "\000\002\000\000"
95 // port=46
96 "\000\003\000\002\000\056"
97 // ipv4hint=8.8.8.8
98 "\000\004\000\004\010\010\010\010"
99 // echconfig=hello
100 "\000\005\000\005hello"
101 // ipv6hint=2001:4860:4860::8888
102 "\000\006\000\020\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00"
103 "\x88\x88"
104 // Unknown key7=foo
105 "\000\007\000\003foo";
106
107 std::unique_ptr<HttpsRecordRdata> rdata =
108 HttpsRecordRdata::Parse(std::string_view(kRdata, sizeof(kRdata) - 1));
109 ASSERT_TRUE(rdata);
110
111 IPAddress expected_ipv6;
112 ASSERT_TRUE(expected_ipv6.AssignFromIPLiteral("2001:4860:4860::8888"));
113 ServiceFormHttpsRecordRdata expected(
114 1 /* priority */, "chromium.org", std::set<uint16_t>({1, 2, 3, 4, 5, 6}),
115 std::vector<std::string>({"foo", "bar"}) /* alpn_ids */,
116 false /* default_alpn */, std::optional<uint16_t>(46) /* port */,
117 std::vector<IPAddress>({IPAddress(8, 8, 8, 8)}) /* ipv4_hint */,
118 "hello" /* ech_config */,
119 std::vector<IPAddress>({expected_ipv6}) /* ipv6_hint */,
120 std::map<uint16_t, std::string>({{7, "foo"}}) /* unparsed_params */);
121 EXPECT_TRUE(rdata->IsEqual(&expected));
122
123 EXPECT_FALSE(rdata->IsAlias());
124 ServiceFormHttpsRecordRdata* service_rdata = rdata->AsServiceForm();
125 ASSERT_TRUE(service_rdata);
126 EXPECT_EQ(service_rdata->priority(), 1);
127 EXPECT_EQ(service_rdata->service_name(), "chromium.org");
128 EXPECT_THAT(service_rdata->mandatory_keys(),
129 testing::ElementsAre(1, 2, 3, 4, 5, 6));
130 EXPECT_THAT(service_rdata->alpn_ids(), testing::ElementsAre("foo", "bar"));
131 EXPECT_FALSE(service_rdata->default_alpn());
132 EXPECT_THAT(service_rdata->port(), testing::Optional(46));
133 EXPECT_THAT(service_rdata->ipv4_hint(),
134 testing::ElementsAre(IPAddress(8, 8, 8, 8)));
135 EXPECT_EQ(service_rdata->ech_config(), "hello");
136 EXPECT_THAT(service_rdata->ipv6_hint(), testing::ElementsAre(expected_ipv6));
137 EXPECT_THAT(service_rdata->unparsed_params(),
138 testing::ElementsAre(testing::Pair(7, "foo")));
139 EXPECT_TRUE(service_rdata->IsCompatible());
140 }
141
TEST(HttpsRecordRdataTest,RejectCorruptRdata)142 TEST(HttpsRecordRdataTest, RejectCorruptRdata) {
143 const char kRdata[] =
144 // Priority: 5
145 "\000\005"
146 // Service name: chromium.org
147 "\010chromium\003org\000"
148 // Malformed alpn
149 "\000\001\000\005hi";
150
151 std::unique_ptr<HttpsRecordRdata> rdata =
152 HttpsRecordRdata::Parse(std::string_view(kRdata, sizeof(kRdata) - 1));
153 EXPECT_FALSE(rdata);
154 }
155
TEST(HttpsRecordRdataTest,AliasIsEqualRejectsWrongType)156 TEST(HttpsRecordRdataTest, AliasIsEqualRejectsWrongType) {
157 AliasFormHttpsRecordRdata alias("alias.name.test");
158 ServiceFormHttpsRecordRdata service(
159 1u /* priority */, "service.name.test", {} /* mandatory_keys */,
160 {} /* alpn_ids */, true /* default_alpn */, std::nullopt /* port */,
161 {} /* ipv4_hint */, "" /* ech_config */, {} /* ipv6_hint */,
162 {} /* unparsed_params */);
163
164 EXPECT_TRUE(alias.IsEqual(&alias));
165 EXPECT_FALSE(alias.IsEqual(&service));
166 }
167
TEST(HttpsRecordRdataTest,ServiceIsEqualRejectsWrongType)168 TEST(HttpsRecordRdataTest, ServiceIsEqualRejectsWrongType) {
169 AliasFormHttpsRecordRdata alias("alias.name.test");
170 ServiceFormHttpsRecordRdata service(
171 1u /* priority */, "service.name.test", {} /* mandatory_keys */,
172 {} /* alpn_ids */, true /* default_alpn */, std::nullopt /* port */,
173 {} /* ipv4_hint */, "" /* ech_config */, {} /* ipv6_hint */,
174 {} /* unparsed_params */);
175
176 EXPECT_FALSE(service.IsEqual(&alias));
177 EXPECT_TRUE(service.IsEqual(&service));
178 }
179
180 } // namespace
181 } // namespace net
182