record_rdata.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. // Copyright (c) 2013 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/record_rdata.h"
  5. #include <algorithm>
  6. #include <numeric>
  7. #include <utility>
  8. #include "base/big_endian.h"
  9. #include "base/logging.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "base/rand_util.h"
  12. #include "base/strings/string_piece.h"
  13. #include "net/base/ip_address.h"
  14. #include "net/dns/dns_response.h"
  15. #include "net/dns/public/dns_protocol.h"
  16. namespace net {
  17. static const size_t kSrvRecordMinimumSize = 6;
  18. // The simplest INTEGRITY record is a U16-length-prefixed nonce (containing zero
  19. // bytes) followed by its SHA256 digest.
  20. static constexpr size_t kIntegrityMinimumSize =
  21. sizeof(uint16_t) + IntegrityRecordRdata::kDigestLen;
  22. // Minimal HTTPS rdata is 2 octets priority + 1 octet empty name.
  23. static constexpr size_t kHttpsRdataMinimumSize = 3;
  24. bool RecordRdata::HasValidSize(const base::StringPiece& data, uint16_t type) {
  25. switch (type) {
  26. case dns_protocol::kTypeSRV:
  27. return data.size() >= kSrvRecordMinimumSize;
  28. case dns_protocol::kTypeA:
  29. return data.size() == IPAddress::kIPv4AddressSize;
  30. case dns_protocol::kTypeAAAA:
  31. return data.size() == IPAddress::kIPv6AddressSize;
  32. case dns_protocol::kExperimentalTypeIntegrity:
  33. return data.size() >= kIntegrityMinimumSize;
  34. case dns_protocol::kTypeHttps:
  35. return data.size() >= kHttpsRdataMinimumSize;
  36. case dns_protocol::kTypeCNAME:
  37. case dns_protocol::kTypePTR:
  38. case dns_protocol::kTypeTXT:
  39. case dns_protocol::kTypeNSEC:
  40. case dns_protocol::kTypeOPT:
  41. case dns_protocol::kTypeSOA:
  42. return true;
  43. default:
  44. VLOG(1) << "Unrecognized RDATA type.";
  45. return true;
  46. }
  47. }
  48. SrvRecordRdata::SrvRecordRdata() = default;
  49. SrvRecordRdata::~SrvRecordRdata() = default;
  50. // static
  51. std::unique_ptr<SrvRecordRdata> SrvRecordRdata::Create(
  52. const base::StringPiece& data,
  53. const DnsRecordParser& parser) {
  54. if (!HasValidSize(data, kType))
  55. return nullptr;
  56. auto rdata = base::WrapUnique(new SrvRecordRdata());
  57. auto reader = base::BigEndianReader::FromStringPiece(data);
  58. // 2 bytes for priority, 2 bytes for weight, 2 bytes for port.
  59. reader.ReadU16(&rdata->priority_);
  60. reader.ReadU16(&rdata->weight_);
  61. reader.ReadU16(&rdata->port_);
  62. if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(),
  63. &rdata->target_))
  64. return nullptr;
  65. return rdata;
  66. }
  67. uint16_t SrvRecordRdata::Type() const {
  68. return SrvRecordRdata::kType;
  69. }
  70. bool SrvRecordRdata::IsEqual(const RecordRdata* other) const {
  71. if (other->Type() != Type()) return false;
  72. const SrvRecordRdata* srv_other = static_cast<const SrvRecordRdata*>(other);
  73. return weight_ == srv_other->weight_ &&
  74. port_ == srv_other->port_ &&
  75. priority_ == srv_other->priority_ &&
  76. target_ == srv_other->target_;
  77. }
  78. ARecordRdata::ARecordRdata() = default;
  79. ARecordRdata::~ARecordRdata() = default;
  80. // static
  81. std::unique_ptr<ARecordRdata> ARecordRdata::Create(
  82. const base::StringPiece& data,
  83. const DnsRecordParser& parser) {
  84. if (!HasValidSize(data, kType))
  85. return nullptr;
  86. auto rdata = base::WrapUnique(new ARecordRdata());
  87. rdata->address_ =
  88. IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
  89. return rdata;
  90. }
  91. uint16_t ARecordRdata::Type() const {
  92. return ARecordRdata::kType;
  93. }
  94. bool ARecordRdata::IsEqual(const RecordRdata* other) const {
  95. if (other->Type() != Type()) return false;
  96. const ARecordRdata* a_other = static_cast<const ARecordRdata*>(other);
  97. return address_ == a_other->address_;
  98. }
  99. AAAARecordRdata::AAAARecordRdata() = default;
  100. AAAARecordRdata::~AAAARecordRdata() = default;
  101. // static
  102. std::unique_ptr<AAAARecordRdata> AAAARecordRdata::Create(
  103. const base::StringPiece& data,
  104. const DnsRecordParser& parser) {
  105. if (!HasValidSize(data, kType))
  106. return nullptr;
  107. auto rdata = base::WrapUnique(new AAAARecordRdata());
  108. rdata->address_ =
  109. IPAddress(reinterpret_cast<const uint8_t*>(data.data()), data.length());
  110. return rdata;
  111. }
  112. uint16_t AAAARecordRdata::Type() const {
  113. return AAAARecordRdata::kType;
  114. }
  115. bool AAAARecordRdata::IsEqual(const RecordRdata* other) const {
  116. if (other->Type() != Type()) return false;
  117. const AAAARecordRdata* a_other = static_cast<const AAAARecordRdata*>(other);
  118. return address_ == a_other->address_;
  119. }
  120. CnameRecordRdata::CnameRecordRdata() = default;
  121. CnameRecordRdata::~CnameRecordRdata() = default;
  122. // static
  123. std::unique_ptr<CnameRecordRdata> CnameRecordRdata::Create(
  124. const base::StringPiece& data,
  125. const DnsRecordParser& parser) {
  126. auto rdata = base::WrapUnique(new CnameRecordRdata());
  127. if (!parser.ReadName(data.begin(), &rdata->cname_))
  128. return nullptr;
  129. return rdata;
  130. }
  131. uint16_t CnameRecordRdata::Type() const {
  132. return CnameRecordRdata::kType;
  133. }
  134. bool CnameRecordRdata::IsEqual(const RecordRdata* other) const {
  135. if (other->Type() != Type()) return false;
  136. const CnameRecordRdata* cname_other =
  137. static_cast<const CnameRecordRdata*>(other);
  138. return cname_ == cname_other->cname_;
  139. }
  140. PtrRecordRdata::PtrRecordRdata() = default;
  141. PtrRecordRdata::~PtrRecordRdata() = default;
  142. // static
  143. std::unique_ptr<PtrRecordRdata> PtrRecordRdata::Create(
  144. const base::StringPiece& data,
  145. const DnsRecordParser& parser) {
  146. auto rdata = base::WrapUnique(new PtrRecordRdata());
  147. if (!parser.ReadName(data.begin(), &rdata->ptrdomain_))
  148. return nullptr;
  149. return rdata;
  150. }
  151. uint16_t PtrRecordRdata::Type() const {
  152. return PtrRecordRdata::kType;
  153. }
  154. bool PtrRecordRdata::IsEqual(const RecordRdata* other) const {
  155. if (other->Type() != Type()) return false;
  156. const PtrRecordRdata* ptr_other = static_cast<const PtrRecordRdata*>(other);
  157. return ptrdomain_ == ptr_other->ptrdomain_;
  158. }
  159. TxtRecordRdata::TxtRecordRdata() = default;
  160. TxtRecordRdata::~TxtRecordRdata() = default;
  161. // static
  162. std::unique_ptr<TxtRecordRdata> TxtRecordRdata::Create(
  163. const base::StringPiece& data,
  164. const DnsRecordParser& parser) {
  165. auto rdata = base::WrapUnique(new TxtRecordRdata());
  166. for (size_t i = 0; i < data.size(); ) {
  167. uint8_t length = data[i];
  168. if (i + length >= data.size())
  169. return nullptr;
  170. rdata->texts_.push_back(std::string(data.substr(i + 1, length)));
  171. // Move to the next string.
  172. i += length + 1;
  173. }
  174. return rdata;
  175. }
  176. uint16_t TxtRecordRdata::Type() const {
  177. return TxtRecordRdata::kType;
  178. }
  179. bool TxtRecordRdata::IsEqual(const RecordRdata* other) const {
  180. if (other->Type() != Type()) return false;
  181. const TxtRecordRdata* txt_other = static_cast<const TxtRecordRdata*>(other);
  182. return texts_ == txt_other->texts_;
  183. }
  184. NsecRecordRdata::NsecRecordRdata() = default;
  185. NsecRecordRdata::~NsecRecordRdata() = default;
  186. // static
  187. std::unique_ptr<NsecRecordRdata> NsecRecordRdata::Create(
  188. const base::StringPiece& data,
  189. const DnsRecordParser& parser) {
  190. auto rdata = base::WrapUnique(new NsecRecordRdata());
  191. // Read the "next domain". This part for the NSEC record format is
  192. // ignored for mDNS, since it has no semantic meaning.
  193. unsigned next_domain_length = parser.ReadName(data.data(), nullptr);
  194. // If we did not succeed in getting the next domain or the data length
  195. // is too short for reading the bitmap header, return.
  196. if (next_domain_length == 0 || data.length() < next_domain_length + 2)
  197. return nullptr;
  198. struct BitmapHeader {
  199. uint8_t block_number; // The block number should be zero.
  200. uint8_t length; // Bitmap length in bytes. Between 1 and 32.
  201. };
  202. const BitmapHeader* header = reinterpret_cast<const BitmapHeader*>(
  203. data.data() + next_domain_length);
  204. // The block number must be zero in mDns-specific NSEC records. The bitmap
  205. // length must be between 1 and 32.
  206. if (header->block_number != 0 || header->length == 0 || header->length > 32)
  207. return nullptr;
  208. base::StringPiece bitmap_data = data.substr(next_domain_length + 2);
  209. // Since we may only have one block, the data length must be exactly equal to
  210. // the domain length plus bitmap size.
  211. if (bitmap_data.length() != header->length)
  212. return nullptr;
  213. rdata->bitmap_.insert(rdata->bitmap_.begin(),
  214. bitmap_data.begin(),
  215. bitmap_data.end());
  216. return rdata;
  217. }
  218. uint16_t NsecRecordRdata::Type() const {
  219. return NsecRecordRdata::kType;
  220. }
  221. bool NsecRecordRdata::IsEqual(const RecordRdata* other) const {
  222. if (other->Type() != Type())
  223. return false;
  224. const NsecRecordRdata* nsec_other =
  225. static_cast<const NsecRecordRdata*>(other);
  226. return bitmap_ == nsec_other->bitmap_;
  227. }
  228. bool NsecRecordRdata::GetBit(unsigned i) const {
  229. unsigned byte_num = i/8;
  230. if (bitmap_.size() < byte_num + 1)
  231. return false;
  232. unsigned bit_num = 7 - i % 8;
  233. return (bitmap_[byte_num] & (1 << bit_num)) != 0;
  234. }
  235. IntegrityRecordRdata::IntegrityRecordRdata(Nonce nonce)
  236. : nonce_(std::move(nonce)), digest_(Hash(nonce_)), is_intact_(true) {}
  237. IntegrityRecordRdata::IntegrityRecordRdata(Nonce nonce,
  238. Digest digest,
  239. size_t rdata_len)
  240. : nonce_(std::move(nonce)),
  241. digest_(digest),
  242. is_intact_(rdata_len == LengthForSerialization(nonce_) &&
  243. Hash(nonce_) == digest_) {}
  244. IntegrityRecordRdata::IntegrityRecordRdata(IntegrityRecordRdata&&) = default;
  245. IntegrityRecordRdata::IntegrityRecordRdata(const IntegrityRecordRdata&) =
  246. default;
  247. IntegrityRecordRdata::~IntegrityRecordRdata() = default;
  248. bool IntegrityRecordRdata::IsEqual(const RecordRdata* other) const {
  249. if (other->Type() != Type())
  250. return false;
  251. const IntegrityRecordRdata* integrity_other =
  252. static_cast<const IntegrityRecordRdata*>(other);
  253. return is_intact_ && integrity_other->is_intact_ &&
  254. nonce_ == integrity_other->nonce_ &&
  255. digest_ == integrity_other->digest_;
  256. }
  257. uint16_t IntegrityRecordRdata::Type() const {
  258. return kType;
  259. }
  260. // static
  261. std::unique_ptr<IntegrityRecordRdata> IntegrityRecordRdata::Create(
  262. const base::StringPiece& data) {
  263. auto reader = base::BigEndianReader::FromStringPiece(data);
  264. // Parse a U16-prefixed |Nonce| followed by a |Digest|.
  265. base::StringPiece parsed_nonce, parsed_digest;
  266. // Note that even if this parse fails, we still want to create a record.
  267. bool parse_success = reader.ReadU16LengthPrefixed(&parsed_nonce) &&
  268. reader.ReadPiece(&parsed_digest, kDigestLen);
  269. const std::string kZeroDigest = std::string(kDigestLen, 0);
  270. if (!parse_success) {
  271. parsed_nonce = base::StringPiece();
  272. parsed_digest = base::StringPiece(kZeroDigest);
  273. }
  274. Digest digest_copy{};
  275. CHECK_EQ(parsed_digest.size(), digest_copy.size());
  276. std::copy_n(parsed_digest.begin(), parsed_digest.size(), digest_copy.begin());
  277. auto record = base::WrapUnique(
  278. new IntegrityRecordRdata(Nonce(parsed_nonce.begin(), parsed_nonce.end()),
  279. digest_copy, data.size()));
  280. // A failed parse implies |!IsIntact()|, though the converse is not true. The
  281. // record may be considered not intact if there were trailing bytes in |data|
  282. // or if |parsed_digest| is not the hash of |parsed_nonce|.
  283. if (!parse_success)
  284. DCHECK(!record->IsIntact());
  285. return record;
  286. }
  287. // static
  288. IntegrityRecordRdata IntegrityRecordRdata::Random() {
  289. constexpr uint16_t kMinNonceLen = 32;
  290. constexpr uint16_t kMaxNonceLen = 512;
  291. // Construct random nonce.
  292. const uint16_t nonce_len = base::RandInt(kMinNonceLen, kMaxNonceLen);
  293. Nonce nonce(nonce_len);
  294. base::RandBytes(nonce.data(), nonce.size());
  295. return IntegrityRecordRdata(std::move(nonce));
  296. }
  297. absl::optional<std::vector<uint8_t>> IntegrityRecordRdata::Serialize() const {
  298. if (!is_intact_) {
  299. return absl::nullopt;
  300. }
  301. // Create backing buffer and writer.
  302. std::vector<uint8_t> serialized(LengthForSerialization(nonce_));
  303. base::BigEndianWriter writer(reinterpret_cast<char*>(serialized.data()),
  304. serialized.size());
  305. // Writes will only fail if the buffer is too small. We are asserting here
  306. // that our buffer is exactly the right size, which is expected to always be
  307. // true if |is_intact_|.
  308. CHECK(writer.WriteU16(nonce_.size()));
  309. CHECK(writer.WriteBytes(nonce_.data(), nonce_.size()));
  310. CHECK(writer.WriteBytes(digest_.data(), digest_.size()));
  311. CHECK_EQ(writer.remaining(), 0u);
  312. return serialized;
  313. }
  314. // static
  315. IntegrityRecordRdata::Digest IntegrityRecordRdata::Hash(const Nonce& nonce) {
  316. Digest digest{};
  317. SHA256(nonce.data(), nonce.size(), digest.data());
  318. return digest;
  319. }
  320. // static
  321. size_t IntegrityRecordRdata::LengthForSerialization(const Nonce& nonce) {
  322. // A serialized INTEGRITY record consists of a U16-prefixed |nonce_|, followed
  323. // by the bytes of |digest_|.
  324. return sizeof(uint16_t) + nonce.size() + kDigestLen;
  325. }
  326. } // namespace net