https_record_rdata.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/dns/https_record_rdata.h"
  5. #include <stdint.h>
  6. #include <algorithm>
  7. #include <map>
  8. #include <memory>
  9. #include <set>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/big_endian.h"
  14. #include "base/check.h"
  15. #include "base/dcheck_is_on.h"
  16. #include "base/immediate_crash.h"
  17. #include "base/memory/ptr_util.h"
  18. #include "base/strings/string_piece.h"
  19. #include "net/base/ip_address.h"
  20. #include "net/dns/dns_util.h"
  21. #include "net/dns/public/dns_protocol.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. namespace net {
  24. namespace {
  25. bool ReadNextServiceParam(absl::optional<uint16_t> last_key,
  26. base::BigEndianReader& reader,
  27. uint16_t* out_param_key,
  28. base::StringPiece* out_param_value) {
  29. DCHECK(out_param_key);
  30. DCHECK(out_param_value);
  31. uint16_t key;
  32. if (!reader.ReadU16(&key))
  33. return false;
  34. if (last_key.has_value() && last_key.value() >= key)
  35. return false;
  36. base::StringPiece value;
  37. if (!reader.ReadU16LengthPrefixed(&value))
  38. return false;
  39. *out_param_key = key;
  40. *out_param_value = value;
  41. return true;
  42. }
  43. bool ParseMandatoryKeys(base::StringPiece param_value,
  44. std::set<uint16_t>* out_parsed) {
  45. DCHECK(out_parsed);
  46. auto reader = base::BigEndianReader::FromStringPiece(param_value);
  47. std::set<uint16_t> mandatory_keys;
  48. // Do/while to require at least one key.
  49. do {
  50. uint16_t key;
  51. if (!reader.ReadU16(&key))
  52. return false;
  53. // Mandatory key itself is disallowed from its list.
  54. if (key == dns_protocol::kHttpsServiceParamKeyMandatory)
  55. return false;
  56. // Keys required to be listed in ascending order.
  57. if (!mandatory_keys.empty() && key <= *mandatory_keys.rbegin())
  58. return false;
  59. CHECK(mandatory_keys.insert(key).second);
  60. } while (reader.remaining() > 0);
  61. *out_parsed = std::move(mandatory_keys);
  62. return true;
  63. }
  64. bool ParseAlpnIds(base::StringPiece param_value,
  65. std::vector<std::string>* out_parsed) {
  66. DCHECK(out_parsed);
  67. auto reader = base::BigEndianReader::FromStringPiece(param_value);
  68. std::vector<std::string> alpn_ids;
  69. // Do/while to require at least one ID.
  70. do {
  71. base::StringPiece alpn_id;
  72. if (!reader.ReadU8LengthPrefixed(&alpn_id))
  73. return false;
  74. if (alpn_id.size() < 1)
  75. return false;
  76. DCHECK_LE(alpn_id.size(), 255u);
  77. alpn_ids.emplace_back(alpn_id.data(), alpn_id.size());
  78. } while (reader.remaining() > 0);
  79. *out_parsed = std::move(alpn_ids);
  80. return true;
  81. }
  82. template <size_t ADDRESS_SIZE>
  83. bool ParseIpAddresses(base::StringPiece param_value,
  84. std::vector<IPAddress>* out_addresses) {
  85. DCHECK(out_addresses);
  86. auto reader = base::BigEndianReader::FromStringPiece(param_value);
  87. std::vector<IPAddress> addresses;
  88. uint8_t addr_bytes[ADDRESS_SIZE];
  89. do {
  90. if (!reader.ReadBytes(addr_bytes, ADDRESS_SIZE))
  91. return false;
  92. addresses.emplace_back(addr_bytes);
  93. DCHECK(addresses.back().IsValid());
  94. } while (reader.remaining() > 0);
  95. *out_addresses = std::move(addresses);
  96. return true;
  97. }
  98. } // namespace
  99. // static
  100. std::unique_ptr<HttpsRecordRdata> HttpsRecordRdata::Parse(
  101. base::StringPiece data) {
  102. if (!HasValidSize(data, kType))
  103. return nullptr;
  104. auto reader = base::BigEndianReader::FromStringPiece(data);
  105. uint16_t priority;
  106. CHECK(reader.ReadU16(&priority));
  107. if (priority == 0) {
  108. return AliasFormHttpsRecordRdata::Parse(data);
  109. }
  110. return ServiceFormHttpsRecordRdata::Parse(data);
  111. }
  112. HttpsRecordRdata::~HttpsRecordRdata() = default;
  113. bool HttpsRecordRdata::IsEqual(const RecordRdata* other) const {
  114. DCHECK(other);
  115. if (other->Type() != kType)
  116. return false;
  117. const HttpsRecordRdata* https = static_cast<const HttpsRecordRdata*>(other);
  118. return IsEqual(https);
  119. }
  120. uint16_t HttpsRecordRdata::Type() const {
  121. return kType;
  122. }
  123. AliasFormHttpsRecordRdata* HttpsRecordRdata::AsAliasForm() {
  124. CHECK(IsAlias());
  125. return static_cast<AliasFormHttpsRecordRdata*>(this);
  126. }
  127. const AliasFormHttpsRecordRdata* HttpsRecordRdata::AsAliasForm() const {
  128. return const_cast<HttpsRecordRdata*>(this)->AsAliasForm();
  129. }
  130. ServiceFormHttpsRecordRdata* HttpsRecordRdata::AsServiceForm() {
  131. CHECK(!IsAlias());
  132. return static_cast<ServiceFormHttpsRecordRdata*>(this);
  133. }
  134. const ServiceFormHttpsRecordRdata* HttpsRecordRdata::AsServiceForm() const {
  135. return const_cast<HttpsRecordRdata*>(this)->AsServiceForm();
  136. }
  137. AliasFormHttpsRecordRdata::AliasFormHttpsRecordRdata(std::string alias_name)
  138. : alias_name_(std::move(alias_name)) {}
  139. // static
  140. std::unique_ptr<AliasFormHttpsRecordRdata> AliasFormHttpsRecordRdata::Parse(
  141. base::StringPiece data) {
  142. auto reader = base::BigEndianReader::FromStringPiece(data);
  143. uint16_t priority;
  144. if (!reader.ReadU16(&priority))
  145. return nullptr;
  146. if (priority != 0)
  147. return nullptr;
  148. absl::optional<std::string> alias_name =
  149. DnsDomainToString(reader, true /* require_complete */);
  150. if (!alias_name.has_value())
  151. return nullptr;
  152. // Ignore any params.
  153. absl::optional<uint16_t> last_param_key;
  154. while (reader.remaining() > 0) {
  155. uint16_t param_key;
  156. base::StringPiece param_value;
  157. if (!ReadNextServiceParam(last_param_key, reader, &param_key, &param_value))
  158. return nullptr;
  159. last_param_key = param_key;
  160. }
  161. return std::make_unique<AliasFormHttpsRecordRdata>(
  162. std::move(alias_name).value());
  163. }
  164. bool AliasFormHttpsRecordRdata::IsEqual(const HttpsRecordRdata* other) const {
  165. DCHECK(other);
  166. if (!other->IsAlias())
  167. return false;
  168. const AliasFormHttpsRecordRdata* alias = other->AsAliasForm();
  169. return alias_name_ == alias->alias_name_;
  170. }
  171. bool AliasFormHttpsRecordRdata::IsAlias() const {
  172. return true;
  173. }
  174. // static
  175. constexpr uint16_t ServiceFormHttpsRecordRdata::kSupportedKeys[];
  176. ServiceFormHttpsRecordRdata::ServiceFormHttpsRecordRdata(
  177. HttpsRecordPriority priority,
  178. std::string service_name,
  179. std::set<uint16_t> mandatory_keys,
  180. std::vector<std::string> alpn_ids,
  181. bool default_alpn,
  182. absl::optional<uint16_t> port,
  183. std::vector<IPAddress> ipv4_hint,
  184. std::string ech_config,
  185. std::vector<IPAddress> ipv6_hint,
  186. std::map<uint16_t, std::string> unparsed_params)
  187. : priority_(priority),
  188. service_name_(std::move(service_name)),
  189. mandatory_keys_(std::move(mandatory_keys)),
  190. alpn_ids_(std::move(alpn_ids)),
  191. default_alpn_(default_alpn),
  192. port_(port),
  193. ipv4_hint_(std::move(ipv4_hint)),
  194. ech_config_(std::move(ech_config)),
  195. ipv6_hint_(std::move(ipv6_hint)),
  196. unparsed_params_(std::move(unparsed_params)) {
  197. DCHECK_NE(priority_, 0);
  198. DCHECK(mandatory_keys_.find(dns_protocol::kHttpsServiceParamKeyMandatory) ==
  199. mandatory_keys_.end());
  200. #if DCHECK_IS_ON()
  201. for (const IPAddress& address : ipv4_hint_) {
  202. DCHECK(address.IsIPv4());
  203. }
  204. for (const IPAddress& address : ipv6_hint_) {
  205. DCHECK(address.IsIPv6());
  206. }
  207. for (const auto& unparsed_param : unparsed_params_) {
  208. DCHECK(!IsSupportedKey(unparsed_param.first));
  209. }
  210. #endif // DCHECK_IS_ON()
  211. }
  212. ServiceFormHttpsRecordRdata::~ServiceFormHttpsRecordRdata() = default;
  213. bool ServiceFormHttpsRecordRdata::IsEqual(const HttpsRecordRdata* other) const {
  214. DCHECK(other);
  215. if (other->IsAlias())
  216. return false;
  217. const ServiceFormHttpsRecordRdata* service = other->AsServiceForm();
  218. return priority_ == service->priority_ &&
  219. service_name_ == service->service_name_ &&
  220. mandatory_keys_ == service->mandatory_keys_ &&
  221. alpn_ids_ == service->alpn_ids_ &&
  222. default_alpn_ == service->default_alpn_ && port_ == service->port_ &&
  223. ipv4_hint_ == service->ipv4_hint_ &&
  224. ech_config_ == service->ech_config_ &&
  225. ipv6_hint_ == service->ipv6_hint_;
  226. }
  227. bool ServiceFormHttpsRecordRdata::IsAlias() const {
  228. return false;
  229. }
  230. // static
  231. std::unique_ptr<ServiceFormHttpsRecordRdata> ServiceFormHttpsRecordRdata::Parse(
  232. base::StringPiece data) {
  233. auto reader = base::BigEndianReader::FromStringPiece(data);
  234. uint16_t priority;
  235. if (!reader.ReadU16(&priority))
  236. return nullptr;
  237. if (priority == 0)
  238. return nullptr;
  239. absl::optional<std::string> service_name =
  240. DnsDomainToString(reader, true /* require_complete */);
  241. if (!service_name.has_value())
  242. return nullptr;
  243. if (reader.remaining() == 0) {
  244. return std::make_unique<ServiceFormHttpsRecordRdata>(
  245. HttpsRecordPriority{priority}, std::move(service_name).value(),
  246. std::set<uint16_t>() /* mandatory_keys */,
  247. std::vector<std::string>() /* alpn_ids */, true /* default_alpn */,
  248. absl::nullopt /* port */, std::vector<IPAddress>() /* ipv4_hint */,
  249. std::string() /* ech_config */,
  250. std::vector<IPAddress>() /* ipv6_hint */,
  251. std::map<uint16_t, std::string>() /* unparsed_params */);
  252. }
  253. uint16_t param_key = 0;
  254. base::StringPiece param_value;
  255. if (!ReadNextServiceParam(absl::nullopt /* last_key */, reader, &param_key,
  256. &param_value))
  257. return nullptr;
  258. // Assume keys less than Mandatory are not possible.
  259. DCHECK_GE(param_key, dns_protocol::kHttpsServiceParamKeyMandatory);
  260. std::set<uint16_t> mandatory_keys;
  261. if (param_key == dns_protocol::kHttpsServiceParamKeyMandatory) {
  262. DCHECK(IsSupportedKey(param_key));
  263. if (!ParseMandatoryKeys(param_value, &mandatory_keys))
  264. return nullptr;
  265. if (reader.remaining() > 0 &&
  266. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  267. return nullptr;
  268. }
  269. }
  270. std::vector<std::string> alpn_ids;
  271. if (param_key == dns_protocol::kHttpsServiceParamKeyAlpn) {
  272. DCHECK(IsSupportedKey(param_key));
  273. if (!ParseAlpnIds(param_value, &alpn_ids))
  274. return nullptr;
  275. if (reader.remaining() > 0 &&
  276. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  277. return nullptr;
  278. }
  279. }
  280. bool default_alpn = true;
  281. if (param_key == dns_protocol::kHttpsServiceParamKeyNoDefaultAlpn) {
  282. DCHECK(IsSupportedKey(param_key));
  283. if (!param_value.empty())
  284. return nullptr;
  285. default_alpn = false;
  286. if (reader.remaining() > 0 &&
  287. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  288. return nullptr;
  289. }
  290. }
  291. absl::optional<uint16_t> port;
  292. if (param_key == dns_protocol::kHttpsServiceParamKeyPort) {
  293. DCHECK(IsSupportedKey(param_key));
  294. if (param_value.size() != 2)
  295. return nullptr;
  296. uint16_t port_val;
  297. base::ReadBigEndian(reinterpret_cast<const uint8_t*>(param_value.data()),
  298. &port_val);
  299. port = port_val;
  300. if (reader.remaining() > 0 &&
  301. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  302. return nullptr;
  303. }
  304. }
  305. std::vector<IPAddress> ipv4_hint;
  306. if (param_key == dns_protocol::kHttpsServiceParamKeyIpv4Hint) {
  307. DCHECK(IsSupportedKey(param_key));
  308. if (!ParseIpAddresses<IPAddress::kIPv4AddressSize>(param_value, &ipv4_hint))
  309. return nullptr;
  310. if (reader.remaining() > 0 &&
  311. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  312. return nullptr;
  313. }
  314. }
  315. std::string ech_config;
  316. if (param_key == dns_protocol::kHttpsServiceParamKeyEchConfig) {
  317. DCHECK(IsSupportedKey(param_key));
  318. ech_config = std::string(param_value.data(), param_value.size());
  319. if (reader.remaining() > 0 &&
  320. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  321. return nullptr;
  322. }
  323. }
  324. std::vector<IPAddress> ipv6_hint;
  325. if (param_key == dns_protocol::kHttpsServiceParamKeyIpv6Hint) {
  326. DCHECK(IsSupportedKey(param_key));
  327. if (!ParseIpAddresses<IPAddress::kIPv6AddressSize>(param_value, &ipv6_hint))
  328. return nullptr;
  329. if (reader.remaining() > 0 &&
  330. !ReadNextServiceParam(param_key, reader, &param_key, &param_value)) {
  331. return nullptr;
  332. }
  333. }
  334. // Note that if parsing has already reached the end of the rdata, `param_key`
  335. // is still set for whatever param was read last.
  336. std::map<uint16_t, std::string> unparsed_params;
  337. if (param_key > dns_protocol::kHttpsServiceParamKeyIpv6Hint) {
  338. for (;;) {
  339. DCHECK(!IsSupportedKey(param_key));
  340. CHECK(unparsed_params
  341. .emplace(param_key, static_cast<std::string>(param_value))
  342. .second);
  343. if (reader.remaining() == 0)
  344. break;
  345. if (!ReadNextServiceParam(param_key, reader, &param_key, &param_value))
  346. return nullptr;
  347. }
  348. }
  349. return std::make_unique<ServiceFormHttpsRecordRdata>(
  350. HttpsRecordPriority{priority}, std::move(service_name).value(),
  351. std::move(mandatory_keys), std::move(alpn_ids), default_alpn, port,
  352. std::move(ipv4_hint), std::move(ech_config), std::move(ipv6_hint),
  353. std::move(unparsed_params));
  354. }
  355. bool ServiceFormHttpsRecordRdata::IsCompatible() const {
  356. std::set<uint16_t> supported_keys(std::begin(kSupportedKeys),
  357. std::end(kSupportedKeys));
  358. for (uint16_t mandatory_key : mandatory_keys_) {
  359. DCHECK_NE(mandatory_key, dns_protocol::kHttpsServiceParamKeyMandatory);
  360. if (supported_keys.find(mandatory_key) == supported_keys.end())
  361. return false;
  362. }
  363. #if DCHECK_IS_ON()
  364. for (const auto& unparsed_param : unparsed_params_) {
  365. DCHECK(mandatory_keys_.find(unparsed_param.first) == mandatory_keys_.end());
  366. }
  367. #endif // DCHECK_IS_ON()
  368. return true;
  369. }
  370. // static
  371. bool ServiceFormHttpsRecordRdata::IsSupportedKey(uint16_t key) {
  372. #if DCHECK_IS_ON()
  373. return std::find(std::begin(kSupportedKeys), std::end(kSupportedKeys), key) !=
  374. std::end(kSupportedKeys);
  375. #else
  376. // Only intended for DCHECKs.
  377. IMMEDIATE_CRASH();
  378. #endif // DCHECK_IS_ON()
  379. }
  380. } // namespace net