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