From c8cf0a60804f2ae77619d77f1c0c5ff527cc2ca7 Mon Sep 17 00:00:00 2001 From: Harald Alvestrand Date: Mon, 12 Apr 2021 14:44:17 +0000 Subject: [PATCH] Remove MDNS message implementation No customers have been identified. Bug: chromium:1197965 Change-Id: Ia3063d0909c718ffb8e824225c8c60180551115a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214963 Reviewed-by: Taylor Commit-Queue: Harald Alvestrand Cr-Commit-Position: refs/heads/master@{#33700} --- p2p/BUILD.gn | 3 - p2p/base/mdns_message.cc | 396 -------------------- p2p/base/mdns_message.h | 206 ----------- p2p/base/mdns_message_unittest.cc | 571 ----------------------------- test/fuzzers/BUILD.gn | 9 - test/fuzzers/mdns_parser_fuzzer.cc | 27 -- 6 files changed, 1212 deletions(-) delete mode 100644 p2p/base/mdns_message.cc delete mode 100644 p2p/base/mdns_message.h delete mode 100644 p2p/base/mdns_message_unittest.cc delete mode 100644 test/fuzzers/mdns_parser_fuzzer.cc diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn index 84832a3bbf..244bc39092 100644 --- a/p2p/BUILD.gn +++ b/p2p/BUILD.gn @@ -45,8 +45,6 @@ rtc_library("rtc_p2p") { "base/ice_credentials_iterator.h", "base/ice_transport_internal.cc", "base/ice_transport_internal.h", - "base/mdns_message.cc", - "base/mdns_message.h", "base/p2p_constants.cc", "base/p2p_constants.h", "base/p2p_transport_channel.cc", @@ -215,7 +213,6 @@ if (rtc_include_tests) { "base/basic_async_resolver_factory_unittest.cc", "base/dtls_transport_unittest.cc", "base/ice_credentials_iterator_unittest.cc", - "base/mdns_message_unittest.cc", "base/p2p_transport_channel_unittest.cc", "base/port_allocator_unittest.cc", "base/port_unittest.cc", diff --git a/p2p/base/mdns_message.cc b/p2p/base/mdns_message.cc deleted file mode 100644 index 1aa996c4a8..0000000000 --- a/p2p/base/mdns_message.cc +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2018 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "p2p/base/mdns_message.h" - -#include "rtc_base/logging.h" -#include "rtc_base/net_helpers.h" -#include "rtc_base/string_encode.h" - -namespace webrtc { - -namespace { -// RFC 1035, Section 4.1.1. -// -// QR bit. -constexpr uint16_t kMdnsFlagMaskQueryOrResponse = 0x8000; -// AA bit. -constexpr uint16_t kMdnsFlagMaskAuthoritative = 0x0400; -// RFC 1035, Section 4.1.2, QCLASS and RFC 6762, Section 18.12, repurposing of -// top bit of QCLASS as the unicast response bit. -constexpr uint16_t kMdnsQClassMaskUnicastResponse = 0x8000; -constexpr size_t kMdnsHeaderSizeBytes = 12; - -bool ReadDomainName(MessageBufferReader* buf, std::string* name) { - size_t name_start_pos = buf->CurrentOffset(); - uint8_t label_length; - if (!buf->ReadUInt8(&label_length)) { - return false; - } - // RFC 1035, Section 4.1.4. - // - // If the first two bits of the length octet are ones, the name is compressed - // and the rest six bits with the next octet denotes its position in the - // message by the offset from the start of the message. - auto is_pointer = [](uint8_t octet) { - return (octet & 0x80) && (octet & 0x40); - }; - while (label_length && !is_pointer(label_length)) { - // RFC 1035, Section 2.3.1, labels are restricted to 63 octets or less. - if (label_length > 63) { - return false; - } - std::string label; - if (!buf->ReadString(&label, label_length)) { - return false; - } - (*name) += label + "."; - if (!buf->ReadUInt8(&label_length)) { - return false; - } - } - if (is_pointer(label_length)) { - uint8_t next_octet; - if (!buf->ReadUInt8(&next_octet)) { - return false; - } - size_t pos_jump_to = ((label_length & 0x3f) << 8) | next_octet; - // A legitimate pointer only refers to a prior occurrence of the same name, - // and we should only move strictly backward to a prior name field after the - // header. - if (pos_jump_to >= name_start_pos || pos_jump_to < kMdnsHeaderSizeBytes) { - return false; - } - MessageBufferReader new_buf(buf->MessageData(), buf->MessageLength()); - if (!new_buf.Consume(pos_jump_to)) { - return false; - } - return ReadDomainName(&new_buf, name); - } - return true; -} - -void WriteDomainName(rtc::ByteBufferWriter* buf, const std::string& name) { - std::vector labels; - rtc::tokenize(name, '.', &labels); - for (const auto& label : labels) { - buf->WriteUInt8(label.length()); - buf->WriteString(label); - } - buf->WriteUInt8(0); -} - -} // namespace - -void MdnsHeader::SetQueryOrResponse(bool is_query) { - if (is_query) { - flags &= ~kMdnsFlagMaskQueryOrResponse; - } else { - flags |= kMdnsFlagMaskQueryOrResponse; - } -} - -void MdnsHeader::SetAuthoritative(bool is_authoritative) { - if (is_authoritative) { - flags |= kMdnsFlagMaskAuthoritative; - } else { - flags &= ~kMdnsFlagMaskAuthoritative; - } -} - -bool MdnsHeader::IsAuthoritative() const { - return flags & kMdnsFlagMaskAuthoritative; -} - -bool MdnsHeader::Read(MessageBufferReader* buf) { - if (!buf->ReadUInt16(&id) || !buf->ReadUInt16(&flags) || - !buf->ReadUInt16(&qdcount) || !buf->ReadUInt16(&ancount) || - !buf->ReadUInt16(&nscount) || !buf->ReadUInt16(&arcount)) { - RTC_LOG(LS_ERROR) << "Invalid mDNS header."; - return false; - } - return true; -} - -void MdnsHeader::Write(rtc::ByteBufferWriter* buf) const { - buf->WriteUInt16(id); - buf->WriteUInt16(flags); - buf->WriteUInt16(qdcount); - buf->WriteUInt16(ancount); - buf->WriteUInt16(nscount); - buf->WriteUInt16(arcount); -} - -bool MdnsHeader::IsQuery() const { - return !(flags & kMdnsFlagMaskQueryOrResponse); -} - -MdnsSectionEntry::MdnsSectionEntry() = default; -MdnsSectionEntry::~MdnsSectionEntry() = default; -MdnsSectionEntry::MdnsSectionEntry(const MdnsSectionEntry& other) = default; - -void MdnsSectionEntry::SetType(SectionEntryType type) { - switch (type) { - case SectionEntryType::kA: - type_ = 1; - return; - case SectionEntryType::kAAAA: - type_ = 28; - return; - default: - RTC_NOTREACHED(); - } -} - -SectionEntryType MdnsSectionEntry::GetType() const { - switch (type_) { - case 1: - return SectionEntryType::kA; - case 28: - return SectionEntryType::kAAAA; - default: - return SectionEntryType::kUnsupported; - } -} - -void MdnsSectionEntry::SetClass(SectionEntryClass cls) { - switch (cls) { - case SectionEntryClass::kIN: - class_ = 1; - return; - default: - RTC_NOTREACHED(); - } -} - -SectionEntryClass MdnsSectionEntry::GetClass() const { - switch (class_) { - case 1: - return SectionEntryClass::kIN; - default: - return SectionEntryClass::kUnsupported; - } -} - -MdnsQuestion::MdnsQuestion() = default; -MdnsQuestion::MdnsQuestion(const MdnsQuestion& other) = default; -MdnsQuestion::~MdnsQuestion() = default; - -bool MdnsQuestion::Read(MessageBufferReader* buf) { - if (!ReadDomainName(buf, &name_)) { - RTC_LOG(LS_ERROR) << "Invalid name."; - return false; - } - if (!buf->ReadUInt16(&type_) || !buf->ReadUInt16(&class_)) { - RTC_LOG(LS_ERROR) << "Invalid type and class."; - return false; - } - return true; -} - -bool MdnsQuestion::Write(rtc::ByteBufferWriter* buf) const { - WriteDomainName(buf, name_); - buf->WriteUInt16(type_); - buf->WriteUInt16(class_); - return true; -} - -void MdnsQuestion::SetUnicastResponse(bool should_unicast) { - if (should_unicast) { - class_ |= kMdnsQClassMaskUnicastResponse; - } else { - class_ &= ~kMdnsQClassMaskUnicastResponse; - } -} - -bool MdnsQuestion::ShouldUnicastResponse() const { - return class_ & kMdnsQClassMaskUnicastResponse; -} - -MdnsResourceRecord::MdnsResourceRecord() = default; -MdnsResourceRecord::MdnsResourceRecord(const MdnsResourceRecord& other) = - default; -MdnsResourceRecord::~MdnsResourceRecord() = default; - -bool MdnsResourceRecord::Read(MessageBufferReader* buf) { - if (!ReadDomainName(buf, &name_)) { - return false; - } - if (!buf->ReadUInt16(&type_) || !buf->ReadUInt16(&class_) || - !buf->ReadUInt32(&ttl_seconds_) || !buf->ReadUInt16(&rdlength_)) { - return false; - } - - switch (GetType()) { - case SectionEntryType::kA: - return ReadARData(buf); - case SectionEntryType::kAAAA: - return ReadQuadARData(buf); - case SectionEntryType::kUnsupported: - return false; - default: - RTC_NOTREACHED(); - } - return false; -} -bool MdnsResourceRecord::ReadARData(MessageBufferReader* buf) { - // A RDATA contains a 32-bit IPv4 address. - return buf->ReadString(&rdata_, 4); -} - -bool MdnsResourceRecord::ReadQuadARData(MessageBufferReader* buf) { - // AAAA RDATA contains a 128-bit IPv6 address. - return buf->ReadString(&rdata_, 16); -} - -bool MdnsResourceRecord::Write(rtc::ByteBufferWriter* buf) const { - WriteDomainName(buf, name_); - buf->WriteUInt16(type_); - buf->WriteUInt16(class_); - buf->WriteUInt32(ttl_seconds_); - buf->WriteUInt16(rdlength_); - switch (GetType()) { - case SectionEntryType::kA: - WriteARData(buf); - return true; - case SectionEntryType::kAAAA: - WriteQuadARData(buf); - return true; - case SectionEntryType::kUnsupported: - return false; - default: - RTC_NOTREACHED(); - } - return true; -} - -void MdnsResourceRecord::WriteARData(rtc::ByteBufferWriter* buf) const { - buf->WriteString(rdata_); -} - -void MdnsResourceRecord::WriteQuadARData(rtc::ByteBufferWriter* buf) const { - buf->WriteString(rdata_); -} - -bool MdnsResourceRecord::SetIPAddressInRecordData( - const rtc::IPAddress& address) { - int af = address.family(); - if (af != AF_INET && af != AF_INET6) { - return false; - } - char out[16] = {0}; - if (!rtc::inet_pton(af, address.ToString().c_str(), out)) { - return false; - } - rdlength_ = (af == AF_INET) ? 4 : 16; - rdata_ = std::string(out, rdlength_); - return true; -} - -bool MdnsResourceRecord::GetIPAddressFromRecordData( - rtc::IPAddress* address) const { - if (GetType() != SectionEntryType::kA && - GetType() != SectionEntryType::kAAAA) { - return false; - } - if (rdata_.size() != 4 && rdata_.size() != 16) { - return false; - } - char out[INET6_ADDRSTRLEN] = {0}; - int af = (GetType() == SectionEntryType::kA) ? AF_INET : AF_INET6; - if (!rtc::inet_ntop(af, rdata_.data(), out, sizeof(out))) { - return false; - } - return rtc::IPFromString(std::string(out), address); -} - -MdnsMessage::MdnsMessage() = default; -MdnsMessage::~MdnsMessage() = default; - -bool MdnsMessage::Read(MessageBufferReader* buf) { - RTC_DCHECK_EQ(0u, buf->CurrentOffset()); - if (!header_.Read(buf)) { - return false; - } - - auto read_question = [&buf](std::vector* section, - uint16_t count) { - section->resize(count); - for (auto& question : (*section)) { - if (!question.Read(buf)) { - return false; - } - } - return true; - }; - auto read_rr = [&buf](std::vector* section, - uint16_t count) { - section->resize(count); - for (auto& rr : (*section)) { - if (!rr.Read(buf)) { - return false; - } - } - return true; - }; - - if (!read_question(&question_section_, header_.qdcount) || - !read_rr(&answer_section_, header_.ancount) || - !read_rr(&authority_section_, header_.nscount) || - !read_rr(&additional_section_, header_.arcount)) { - return false; - } - return true; -} - -bool MdnsMessage::Write(rtc::ByteBufferWriter* buf) const { - header_.Write(buf); - - auto write_rr = [&buf](const std::vector& section) { - for (const auto& rr : section) { - if (!rr.Write(buf)) { - return false; - } - } - return true; - }; - - for (const auto& question : question_section_) { - if (!question.Write(buf)) { - return false; - } - } - if (!write_rr(answer_section_) || !write_rr(authority_section_) || - !write_rr(additional_section_)) { - return false; - } - - return true; -} - -bool MdnsMessage::ShouldUnicastResponse() const { - bool should_unicast = false; - for (const auto& question : question_section_) { - should_unicast |= question.ShouldUnicastResponse(); - } - return should_unicast; -} - -void MdnsMessage::AddQuestion(const MdnsQuestion& question) { - question_section_.push_back(question); - header_.qdcount = question_section_.size(); -} - -void MdnsMessage::AddAnswerRecord(const MdnsResourceRecord& answer) { - answer_section_.push_back(answer); - header_.ancount = answer_section_.size(); -} - -} // namespace webrtc diff --git a/p2p/base/mdns_message.h b/p2p/base/mdns_message.h deleted file mode 100644 index 79be5219e4..0000000000 --- a/p2p/base/mdns_message.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2018 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef P2P_BASE_MDNS_MESSAGE_H_ -#define P2P_BASE_MDNS_MESSAGE_H_ - -// This file contains classes to read and write mDNSs message defined in RFC -// 6762 and RFC 1025 (DNS messages). Note that it is recommended by RFC 6762 to -// use the name compression scheme defined in RFC 1035 whenever possible. We -// currently only implement the capability of reading compressed names in mDNS -// messages in MdnsMessage::Read(); however, the MdnsMessage::Write() does not -// support name compression yet. -// -// Fuzzer tests (test/fuzzers/mdns_parser_fuzzer.cc) MUST always be performed -// after changes made to this file. - -#include - -#include -#include - -#include "rtc_base/byte_buffer.h" -#include "rtc_base/ip_address.h" -#include "rtc_base/message_buffer_reader.h" - -namespace webrtc { - -// We use "section entry" to denote either a question or a resource record. -// -// RFC 1035 Section 3.2.2. -enum class SectionEntryType { - kA, - kAAAA, - // Only the above types are processed in the current implementation. - kUnsupported, -}; - -// RFC 1035 Section 3.2.4. -enum class SectionEntryClass { - kIN, - kUnsupported, -}; - -// RFC 1035, Section 4.1.1. -class MdnsHeader final { - public: - bool Read(MessageBufferReader* buf); - void Write(rtc::ByteBufferWriter* buf) const; - - void SetQueryOrResponse(bool is_query); - bool IsQuery() const; - void SetAuthoritative(bool is_authoritative); - bool IsAuthoritative() const; - - uint16_t id = 0; - uint16_t flags = 0; - // Number of entries in the question section. - uint16_t qdcount = 0; - // Number of resource records in the answer section. - uint16_t ancount = 0; - // Number of name server resource records in the authority records section. - uint16_t nscount = 0; - // Number of resource records in the additional records section. - uint16_t arcount = 0; -}; - -// Entries in each section after the header share a common structure. Note that -// this is not a concept defined in RFC 1035. -class MdnsSectionEntry { - public: - MdnsSectionEntry(); - MdnsSectionEntry(const MdnsSectionEntry& other); - virtual ~MdnsSectionEntry(); - virtual bool Read(MessageBufferReader* buf) = 0; - virtual bool Write(rtc::ByteBufferWriter* buf) const = 0; - - void SetName(const std::string& name) { name_ = name; } - // Returns the fully qualified domain name in the section entry, i.e., QNAME - // in a question or NAME in a resource record. - std::string GetName() const { return name_; } - - void SetType(SectionEntryType type); - SectionEntryType GetType() const; - void SetClass(SectionEntryClass cls); - SectionEntryClass GetClass() const; - - protected: - std::string name_; // Fully qualified domain name. - uint16_t type_ = 0; - uint16_t class_ = 0; -}; - -// RFC 1035, Section 4.1.2. -class MdnsQuestion final : public MdnsSectionEntry { - public: - MdnsQuestion(); - MdnsQuestion(const MdnsQuestion& other); - ~MdnsQuestion() override; - - bool Read(MessageBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - void SetUnicastResponse(bool should_unicast); - bool ShouldUnicastResponse() const; -}; - -// RFC 1035, Section 4.1.3. -class MdnsResourceRecord final : public MdnsSectionEntry { - public: - MdnsResourceRecord(); - MdnsResourceRecord(const MdnsResourceRecord& other); - ~MdnsResourceRecord() override; - - bool Read(MessageBufferReader* buf) override; - bool Write(rtc::ByteBufferWriter* buf) const override; - - void SetTtlSeconds(uint32_t ttl_seconds) { ttl_seconds_ = ttl_seconds; } - uint32_t GetTtlSeconds() const { return ttl_seconds_; } - // Returns true if |address| is in the address family AF_INET or AF_INET6 and - // |address| has a valid IPv4 or IPv6 address; false otherwise. - bool SetIPAddressInRecordData(const rtc::IPAddress& address); - // Returns true if the record is of type A or AAAA and the record has a valid - // IPv4 or IPv6 address; false otherwise. Stores the valid IP in |address|. - bool GetIPAddressFromRecordData(rtc::IPAddress* address) const; - - private: - // The list of methods reading and writing rdata can grow as we support more - // types of rdata. - bool ReadARData(MessageBufferReader* buf); - void WriteARData(rtc::ByteBufferWriter* buf) const; - - bool ReadQuadARData(MessageBufferReader* buf); - void WriteQuadARData(rtc::ByteBufferWriter* buf) const; - - uint32_t ttl_seconds_ = 0; - uint16_t rdlength_ = 0; - std::string rdata_; -}; - -class MdnsMessage final { - public: - // RFC 1035, Section 4.1. - enum class Section { kQuestion, kAnswer, kAuthority, kAdditional }; - - MdnsMessage(); - ~MdnsMessage(); - // Reads the mDNS message in |buf| and populates the corresponding fields in - // MdnsMessage. - bool Read(MessageBufferReader* buf); - // Write an mDNS message to |buf| based on the fields in MdnsMessage. - // - // TODO(qingsi): Implement name compression when writing mDNS messages. - bool Write(rtc::ByteBufferWriter* buf) const; - - void SetId(uint16_t id) { header_.id = id; } - uint16_t GetId() const { return header_.id; } - - void SetQueryOrResponse(bool is_query) { - header_.SetQueryOrResponse(is_query); - } - bool IsQuery() const { return header_.IsQuery(); } - - void SetAuthoritative(bool is_authoritative) { - header_.SetAuthoritative(is_authoritative); - } - bool IsAuthoritative() const { return header_.IsAuthoritative(); } - - // Returns true if the message is a query and the unicast response is - // preferred. False otherwise. - bool ShouldUnicastResponse() const; - - void AddQuestion(const MdnsQuestion& question); - // TODO(qingsi): Implement AddXRecord for name server and additional records. - void AddAnswerRecord(const MdnsResourceRecord& answer); - - const std::vector& question_section() const { - return question_section_; - } - const std::vector& answer_section() const { - return answer_section_; - } - const std::vector& authority_section() const { - return authority_section_; - } - const std::vector& additional_section() const { - return additional_section_; - } - - private: - MdnsHeader header_; - std::vector question_section_; - std::vector answer_section_; - std::vector authority_section_; - std::vector additional_section_; -}; - -} // namespace webrtc - -#endif // P2P_BASE_MDNS_MESSAGE_H_ diff --git a/p2p/base/mdns_message_unittest.cc b/p2p/base/mdns_message_unittest.cc deleted file mode 100644 index 2f1f74d8e3..0000000000 --- a/p2p/base/mdns_message_unittest.cc +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright 2018 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "p2p/base/mdns_message.h" - -#include -#include -#include - -#include "rtc_base/byte_buffer.h" -#include "rtc_base/gunit.h" -#include "rtc_base/ip_address.h" -#include "rtc_base/socket_address.h" -#include "test/gmock.h" - -#define ReadMdnsMessage(X, Y) ReadMdnsMessageTestCase(X, Y, sizeof(Y)) -#define WriteMdnsMessageAndCompare(X, Y) \ - WriteMdnsMessageAndCompareWithTestCast(X, Y, sizeof(Y)) - -using ::testing::ElementsAre; -using ::testing::Pair; -using ::testing::UnorderedElementsAre; - -namespace webrtc { - -namespace { - -const uint8_t kSingleQuestionForIPv4AddrWithUnicastResponse[] = { - 0x12, 0x34, // ID - 0x00, 0x00, // flags - 0x00, 0x01, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x80, 0x01, // class IN, unicast response -}; - -const uint8_t kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse[] = { - 0x12, 0x34, // ID - 0x00, 0x00, // flags - 0x00, 0x02, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x34, // webrtc4 - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response - 0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x36, // webrtc6 - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN, multicast response -}; - -const uint8_t - kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponseAndNameCompression[] = { - 0x12, 0x34, // ID - 0x00, 0x00, // flags - 0x00, 0x02, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x03, 0x77, 0x77, 0x77, // www - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response - 0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns - 0xc0, 0x10, // offset 16, webrtc.org. - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN, multicast response -}; - -const uint8_t kThreeQuestionsWithTwoPointersToTheSameNameSuffix[] = { - 0x12, 0x34, // ID - 0x00, 0x00, // flags - 0x00, 0x03, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x03, 0x77, 0x77, 0x77, // www - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response - 0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns - 0xc0, 0x10, // offset 16, webrtc.org. - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN, multicast response - 0xc0, 0x10, // offset 16, webrtc.org. - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response -}; - -const uint8_t kThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer[] = - { - 0x12, 0x34, // ID - 0x00, 0x00, // flags - 0x00, 0x03, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x03, 0x77, 0x77, 0x77, // www - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response - 0x04, 0x6d, 0x64, 0x6e, 0x73, // mdns - 0xc0, 0x10, // offset 16, webrtc.org. - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN, multicast response - 0x03, 0x77, 0x77, 0x77, // www - 0xc0, 0x20, // offset 32, mdns.webrtc.org. - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN, multicast response -}; - -const uint8_t kCorruptedQuestionWithNameCompression1[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x01, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0xc0, 0x0c, // offset 12, - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN -}; - -const uint8_t kCorruptedQuestionWithNameCompression2[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x01, // number of questions - 0x00, 0x00, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x01, 0x77, // w - 0xc0, 0x0c, // offset 12, - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN -}; - -const uint8_t kSingleAuthoritativeAnswerWithIPv4Addr[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x00, // number of questions - 0x00, 0x01, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds - 0x00, 0x04, // rdlength, 32 bits - 0xC0, 0xA8, 0x00, 0x01, // 192.168.0.1 -}; - -const uint8_t kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x00, // number of questions - 0x00, 0x02, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x34, // webrtc4 - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds - 0x00, 0x04, // rdlength, 32 bits - 0xC0, 0xA8, 0x00, 0x01, // 192.168.0.1 - 0x07, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, 0x36, // webrtc6 - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds - 0x00, 0x10, // rdlength, 128 bits - 0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -}; - -const uint8_t kTwoAuthoritativeAnswersWithIPv4AndIPv6AddrWithNameCompression[] = - { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x00, // number of questions - 0x00, 0x02, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x03, 0x77, 0x77, 0x77, // www - 0x06, 0x77, 0x65, 0x62, 0x72, 0x74, 0x63, // webrtc - 0x03, 0x6f, 0x72, 0x67, // org - 0x00, // null label - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds - 0x00, 0x04, // rdlength, 32 bits - 0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1 - 0xc0, 0x10, // offset 16, webrtc.org. - 0x00, 0x1C, // type AAAA Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x78, // TTL, 120 seconds - 0x00, 0x10, // rdlength, 128 bits - 0xfd, 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x01, // fd12:3456:789a:1::1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -}; - -const uint8_t kCorruptedAnswerWithNameCompression1[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x00, // number of questions - 0x00, 0x01, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0xc0, 0x0c, // offset 12, - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds - 0x00, 0x04, // rdlength, 32 bits - 0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1 -}; - -const uint8_t kCorruptedAnswerWithNameCompression2[] = { - 0x12, 0x34, // ID - 0x84, 0x00, // flags - 0x00, 0x00, // number of questions - 0x00, 0x01, // number of answer rr - 0x00, 0x00, // number of name server rr - 0x00, 0x00, // number of additional rr - 0x01, 0x77, // w - 0xc0, 0x0c, // offset 12, - 0x00, 0x01, // type A Record - 0x00, 0x01, // class IN - 0x00, 0x00, 0x00, 0x3c, // TTL, 60 seconds - 0x00, 0x04, // rdlength, 32 bits - 0xc0, 0xA8, 0x00, 0x01, // 192.168.0.1 -}; - -bool ReadMdnsMessageTestCase(MdnsMessage* msg, - const uint8_t* testcase, - size_t size) { - MessageBufferReader buf(reinterpret_cast(testcase), size); - return msg->Read(&buf); -} - -void WriteMdnsMessageAndCompareWithTestCast(MdnsMessage* msg, - const uint8_t* testcase, - size_t size) { - rtc::ByteBufferWriter out; - EXPECT_TRUE(msg->Write(&out)); - EXPECT_EQ(size, out.Length()); - int len = static_cast(out.Length()); - rtc::ByteBufferReader read_buf(out); - std::string bytes; - read_buf.ReadString(&bytes, len); - std::string testcase_bytes(reinterpret_cast(testcase), size); - EXPECT_EQ(testcase_bytes, bytes); -} - -bool GetQueriedNames(MdnsMessage* msg, std::set* names) { - if (!msg->IsQuery() || msg->question_section().empty()) { - return false; - } - for (const auto& question : msg->question_section()) { - names->insert(question.GetName()); - } - return true; -} - -bool GetResolution(MdnsMessage* msg, - std::map* names) { - if (msg->IsQuery() || msg->answer_section().empty()) { - return false; - } - for (const auto& answer : msg->answer_section()) { - rtc::IPAddress resolved_addr; - if (!answer.GetIPAddressFromRecordData(&resolved_addr)) { - return false; - } - (*names)[answer.GetName()] = resolved_addr; - } - return true; -} - -} // namespace - -TEST(MdnsMessageTest, ReadSingleQuestionForIPv4Address) { - MdnsMessage msg; - ASSERT_TRUE( - ReadMdnsMessage(&msg, kSingleQuestionForIPv4AddrWithUnicastResponse)); - EXPECT_TRUE(msg.IsQuery()); - EXPECT_EQ(0x1234, msg.GetId()); - ASSERT_EQ(1u, msg.question_section().size()); - EXPECT_EQ(0u, msg.answer_section().size()); - EXPECT_EQ(0u, msg.authority_section().size()); - EXPECT_EQ(0u, msg.additional_section().size()); - EXPECT_TRUE(msg.ShouldUnicastResponse()); - - const auto& question = msg.question_section()[0]; - EXPECT_EQ(SectionEntryType::kA, question.GetType()); - - std::set queried_names; - EXPECT_TRUE(GetQueriedNames(&msg, &queried_names)); - EXPECT_THAT(queried_names, ElementsAre("webrtc.org.")); -} - -TEST(MdnsMessageTest, ReadTwoQuestionsForIPv4AndIPv6Addr) { - MdnsMessage msg; - ASSERT_TRUE(ReadMdnsMessage( - &msg, kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse)); - EXPECT_TRUE(msg.IsQuery()); - EXPECT_EQ(0x1234, msg.GetId()); - ASSERT_EQ(2u, msg.question_section().size()); - EXPECT_EQ(0u, msg.answer_section().size()); - EXPECT_EQ(0u, msg.authority_section().size()); - EXPECT_EQ(0u, msg.additional_section().size()); - - const auto& question1 = msg.question_section()[0]; - const auto& question2 = msg.question_section()[1]; - EXPECT_EQ(SectionEntryType::kA, question1.GetType()); - EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType()); - - std::set queried_names; - EXPECT_TRUE(GetQueriedNames(&msg, &queried_names)); - EXPECT_THAT(queried_names, - UnorderedElementsAre("webrtc4.org.", "webrtc6.org.")); -} - -TEST(MdnsMessageTest, ReadTwoQuestionsForIPv4AndIPv6AddrWithNameCompression) { - MdnsMessage msg; - ASSERT_TRUE(ReadMdnsMessage( - &msg, - kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponseAndNameCompression)); - - ASSERT_EQ(2u, msg.question_section().size()); - const auto& question1 = msg.question_section()[0]; - const auto& question2 = msg.question_section()[1]; - EXPECT_EQ(SectionEntryType::kA, question1.GetType()); - EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType()); - - std::set queried_names; - EXPECT_TRUE(GetQueriedNames(&msg, &queried_names)); - EXPECT_THAT(queried_names, - UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org.")); -} - -TEST(MdnsMessageTest, ReadThreeQuestionsWithTwoPointersToTheSameNameSuffix) { - MdnsMessage msg; - ASSERT_TRUE( - ReadMdnsMessage(&msg, kThreeQuestionsWithTwoPointersToTheSameNameSuffix)); - - ASSERT_EQ(3u, msg.question_section().size()); - const auto& question1 = msg.question_section()[0]; - const auto& question2 = msg.question_section()[1]; - const auto& question3 = msg.question_section()[2]; - EXPECT_EQ(SectionEntryType::kA, question1.GetType()); - EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType()); - EXPECT_EQ(SectionEntryType::kA, question3.GetType()); - - std::set queried_names; - EXPECT_TRUE(GetQueriedNames(&msg, &queried_names)); - EXPECT_THAT(queried_names, - UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org.", - "webrtc.org.")); -} - -TEST(MdnsMessageTest, - ReadThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer) { - MdnsMessage msg; - ASSERT_TRUE(ReadMdnsMessage( - &msg, kThreeQuestionsWithPointerToNameSuffixContainingAnotherPointer)); - - ASSERT_EQ(3u, msg.question_section().size()); - const auto& question1 = msg.question_section()[0]; - const auto& question2 = msg.question_section()[1]; - const auto& question3 = msg.question_section()[2]; - EXPECT_EQ(SectionEntryType::kA, question1.GetType()); - EXPECT_EQ(SectionEntryType::kAAAA, question2.GetType()); - EXPECT_EQ(SectionEntryType::kA, question3.GetType()); - - std::set queried_names; - EXPECT_TRUE(GetQueriedNames(&msg, &queried_names)); - EXPECT_THAT(queried_names, - UnorderedElementsAre("www.webrtc.org.", "mdns.webrtc.org.", - "www.mdns.webrtc.org.")); -} - -TEST(MdnsMessageTest, - ReadQuestionWithCorruptedPointerInNameCompressionShouldFail) { - MdnsMessage msg; - EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedQuestionWithNameCompression1)); - EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedQuestionWithNameCompression2)); -} - -TEST(MdnsMessageTest, ReadSingleAnswerForIPv4Addr) { - MdnsMessage msg; - ASSERT_TRUE(ReadMdnsMessage(&msg, kSingleAuthoritativeAnswerWithIPv4Addr)); - EXPECT_FALSE(msg.IsQuery()); - EXPECT_TRUE(msg.IsAuthoritative()); - EXPECT_EQ(0x1234, msg.GetId()); - EXPECT_EQ(0u, msg.question_section().size()); - ASSERT_EQ(1u, msg.answer_section().size()); - EXPECT_EQ(0u, msg.authority_section().size()); - EXPECT_EQ(0u, msg.additional_section().size()); - - const auto& answer = msg.answer_section()[0]; - EXPECT_EQ(SectionEntryType::kA, answer.GetType()); - EXPECT_EQ(120u, answer.GetTtlSeconds()); - - std::map resolution; - EXPECT_TRUE(GetResolution(&msg, &resolution)); - rtc::IPAddress expected_addr(rtc::SocketAddress("192.168.0.1", 0).ipaddr()); - EXPECT_THAT(resolution, ElementsAre(Pair("webrtc.org.", expected_addr))); -} - -TEST(MdnsMessageTest, ReadTwoAnswersForIPv4AndIPv6Addr) { - MdnsMessage msg; - ASSERT_TRUE( - ReadMdnsMessage(&msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr)); - EXPECT_FALSE(msg.IsQuery()); - EXPECT_TRUE(msg.IsAuthoritative()); - EXPECT_EQ(0x1234, msg.GetId()); - EXPECT_EQ(0u, msg.question_section().size()); - ASSERT_EQ(2u, msg.answer_section().size()); - EXPECT_EQ(0u, msg.authority_section().size()); - EXPECT_EQ(0u, msg.additional_section().size()); - - const auto& answer1 = msg.answer_section()[0]; - const auto& answer2 = msg.answer_section()[1]; - EXPECT_EQ(SectionEntryType::kA, answer1.GetType()); - EXPECT_EQ(SectionEntryType::kAAAA, answer2.GetType()); - EXPECT_EQ(60u, answer1.GetTtlSeconds()); - EXPECT_EQ(120u, answer2.GetTtlSeconds()); - - std::map resolution; - EXPECT_TRUE(GetResolution(&msg, &resolution)); - rtc::IPAddress expected_addr_ipv4( - rtc::SocketAddress("192.168.0.1", 0).ipaddr()); - rtc::IPAddress expected_addr_ipv6( - rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr()); - EXPECT_THAT(resolution, - UnorderedElementsAre(Pair("webrtc4.org.", expected_addr_ipv4), - Pair("webrtc6.org.", expected_addr_ipv6))); -} - -TEST(MdnsMessageTest, ReadTwoAnswersForIPv4AndIPv6AddrWithNameCompression) { - MdnsMessage msg; - ASSERT_TRUE(ReadMdnsMessage( - &msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6AddrWithNameCompression)); - - std::map resolution; - EXPECT_TRUE(GetResolution(&msg, &resolution)); - rtc::IPAddress expected_addr_ipv4( - rtc::SocketAddress("192.168.0.1", 0).ipaddr()); - rtc::IPAddress expected_addr_ipv6( - rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr()); - EXPECT_THAT(resolution, - UnorderedElementsAre(Pair("www.webrtc.org.", expected_addr_ipv4), - Pair("webrtc.org.", expected_addr_ipv6))); -} - -TEST(MdnsMessageTest, - ReadAnswerWithCorruptedPointerInNameCompressionShouldFail) { - MdnsMessage msg; - EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedAnswerWithNameCompression1)); - EXPECT_FALSE(ReadMdnsMessage(&msg, kCorruptedAnswerWithNameCompression2)); -} - -TEST(MdnsMessageTest, WriteSingleQuestionForIPv4Addr) { - MdnsMessage msg; - msg.SetId(0x1234); - msg.SetQueryOrResponse(true); - - MdnsQuestion question; - question.SetName("webrtc.org."); - question.SetType(SectionEntryType::kA); - question.SetClass(SectionEntryClass::kIN); - question.SetUnicastResponse(true); - msg.AddQuestion(question); - - WriteMdnsMessageAndCompare(&msg, - kSingleQuestionForIPv4AddrWithUnicastResponse); -} - -TEST(MdnsMessageTest, WriteTwoQuestionsForIPv4AndIPv6Addr) { - MdnsMessage msg; - msg.SetId(0x1234); - msg.SetQueryOrResponse(true); - - MdnsQuestion question1; - question1.SetName("webrtc4.org."); - question1.SetType(SectionEntryType::kA); - question1.SetClass(SectionEntryClass::kIN); - msg.AddQuestion(question1); - - MdnsQuestion question2; - question2.SetName("webrtc6.org."); - question2.SetType(SectionEntryType::kAAAA); - question2.SetClass(SectionEntryClass::kIN); - msg.AddQuestion(question2); - - WriteMdnsMessageAndCompare( - &msg, kTwoQuestionsForIPv4AndIPv6AddrWithMulticastResponse); -} - -TEST(MdnsMessageTest, WriteSingleAnswerToIPv4Addr) { - MdnsMessage msg; - msg.SetId(0x1234); - msg.SetQueryOrResponse(false); - msg.SetAuthoritative(true); - - MdnsResourceRecord answer; - answer.SetName("webrtc.org."); - answer.SetType(SectionEntryType::kA); - answer.SetClass(SectionEntryClass::kIN); - EXPECT_TRUE(answer.SetIPAddressInRecordData( - rtc::SocketAddress("192.168.0.1", 0).ipaddr())); - answer.SetTtlSeconds(120); - msg.AddAnswerRecord(answer); - - WriteMdnsMessageAndCompare(&msg, kSingleAuthoritativeAnswerWithIPv4Addr); -} - -TEST(MdnsMessageTest, WriteTwoAnswersToIPv4AndIPv6Addr) { - MdnsMessage msg; - msg.SetId(0x1234); - msg.SetQueryOrResponse(false); - msg.SetAuthoritative(true); - - MdnsResourceRecord answer1; - answer1.SetName("webrtc4.org."); - answer1.SetType(SectionEntryType::kA); - answer1.SetClass(SectionEntryClass::kIN); - answer1.SetIPAddressInRecordData( - rtc::SocketAddress("192.168.0.1", 0).ipaddr()); - answer1.SetTtlSeconds(60); - msg.AddAnswerRecord(answer1); - - MdnsResourceRecord answer2; - answer2.SetName("webrtc6.org."); - answer2.SetType(SectionEntryType::kAAAA); - answer2.SetClass(SectionEntryClass::kIN); - answer2.SetIPAddressInRecordData( - rtc::SocketAddress("fd12:3456:789a:1::1", 0).ipaddr()); - answer2.SetTtlSeconds(120); - msg.AddAnswerRecord(answer2); - - WriteMdnsMessageAndCompare(&msg, kTwoAuthoritativeAnswersWithIPv4AndIPv6Addr); -} - -} // namespace webrtc diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn index e08ba3cd99..9395c7a8f1 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -443,15 +443,6 @@ webrtc_fuzzer_test("stun_validator_fuzzer") { dict = "corpora/stun.tokens" } -webrtc_fuzzer_test("mdns_parser_fuzzer") { - sources = [ "mdns_parser_fuzzer.cc" ] - deps = [ - "../../p2p:rtc_p2p", - "../../rtc_base:rtc_base_approved", - ] - seed_corpus = "corpora/mdns-corpus" -} - webrtc_fuzzer_test("pseudotcp_parser_fuzzer") { sources = [ "pseudotcp_parser_fuzzer.cc" ] deps = [ diff --git a/test/fuzzers/mdns_parser_fuzzer.cc b/test/fuzzers/mdns_parser_fuzzer.cc deleted file mode 100644 index 451742327f..0000000000 --- a/test/fuzzers/mdns_parser_fuzzer.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include -#include - -#include - -#include "p2p/base/mdns_message.h" -#include "rtc_base/message_buffer_reader.h" - -namespace webrtc { - -void FuzzOneInput(const uint8_t* data, size_t size) { - MessageBufferReader buf(reinterpret_cast(data), size); - auto mdns_msg = std::make_unique(); - mdns_msg->Read(&buf); -} - -} // namespace webrtc