// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. #pragma allow_unsafe_buffers #endif #include "net/dns/dns_response.h" #include <algorithm> #include <memory> #include <optional> #include <string> #include <string_view> #include <vector> #include "base/check.h" #include "base/containers/span.h" #include "base/containers/span_writer.h" #include "base/time/time.h" #include "net/base/io_buffer.h" #include "net/dns/dns_names_util.h" #include "net/dns/dns_query.h" #include "net/dns/dns_test_util.h" #include "net/dns/public/dns_protocol.h" #include "net/dns/record_rdata.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { namespace { TEST(DnsRecordParserTest, Constructor) { … } TEST(DnsRecordParserTest, ReadName) { … } TEST(DnsRecordParserTest, ReadNameFail) { … } // Returns an RFC 1034 style domain name with a length of |name_len|. // Also writes the expected dotted string representation into |dotted_str|, // which must be non-null. std::vector<uint8_t> BuildRfc1034Name(const size_t name_len, std::string* dotted_str) { … } TEST(DnsRecordParserTest, ReadNameGoodLength) { … } // Tests against incorrect name length validation, which is anti-pattern #3 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, ReadNameTooLongFail) { … } // Tests against incorrect name compression pointer validation, which is anti- // pattern #6 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectsNamesWithLoops) { … } // Tests against incorrect name compression pointer validation, which is anti- // pattern #6 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectsNamesPointingOutsideData) { … } TEST(DnsRecordParserTest, ParsesValidPointer) { … } // Per RFC 1035, section 4.1.4, the first 2 bits of a DNS name label determine // if it is a length label (if the bytes are 00) or a pointer label (if the // bytes are 11). It is a common DNS parsing bug to treat 01 or 10 as pointer // labels, but these are reserved and invalid. Such labels should always result // in DnsRecordParser rejecting the name. // // Tests against incorrect name compression pointer validation, which is anti- // pattern #6 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectsNamesWithInvalidLabelTypeAsPointer) { … } // Per RFC 1035, section 4.1.4, the first 2 bits of a DNS name label determine // if it is a length label (if the bytes are 00) or a pointer label (if the // bytes are 11). Such labels should always result in DnsRecordParser rejecting // the name. // // Tests against incorrect name compression pointer validation, which is anti- // pattern #6 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectsNamesWithInvalidLabelTypeAsLength) { … } TEST(DnsRecordParserTest, ReadRecord) { … } TEST(DnsRecordParserTest, ReadsRecordWithLongName) { … } // Tests against incorrect name length validation, which is anti-pattern #3 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectRecordWithTooLongName) { … } // Test that a record cannot be parsed with a name extending past the end of the // data. // Tests against incorrect name length validation, which is anti-pattern #3 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectRecordWithNonendedName) { … } // Test that a record cannot be parsed with a name without final null // termination. Parsing should assume the name has not ended and find the first // byte of the TYPE field instead, making the remainder of the record // unparsable. // Tests against incorrect name null termination, which is anti-pattern #4 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsRecordParserTest, RejectRecordNameMissingNullTermination) { … } // Test that no more records can be parsed once the claimed number of records // have been parsed. TEST(DnsRecordParserTest, RejectReadingTooManyRecords) { … } // Test that no more records can be parsed once the end of the buffer is // reached, even if more records are claimed. TEST(DnsRecordParserTest, RejectReadingPastEnd) { … } TEST(DnsResponseTest, InitParse) { … } TEST(DnsResponseTest, InitParseInvalidFlags) { … } TEST(DnsResponseTest, InitParseRejectsResponseWithoutQuestions) { … } TEST(DnsResponseTest, InitParseRejectsResponseWithTooManyQuestions) { … } TEST(DnsResponseTest, InitParseWithoutQuery) { … } TEST(DnsResponseTest, InitParseWithoutQueryNoQuestions) { … } TEST(DnsResponseTest, InitParseWithoutQueryInvalidFlags) { … } TEST(DnsResponseTest, InitParseWithoutQueryTwoQuestions) { … } TEST(DnsResponseTest, InitParseWithoutQueryPacketTooShort) { … } TEST(DnsResponseTest, InitParseAllowsQuestionWithLongName) { … } // Tests against incorrect name length validation, which is anti-pattern #3 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsResponseTest, InitParseRejectsQuestionWithTooLongName) { … } // Test that `InitParse[...]()` rejects a response with a question name // extending past the end of the response. // Tests against incorrect name length validation, which is anti-pattern #3 from // the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsResponseTest, InitParseRejectsQuestionWithNonendedName) { … } // Test that `InitParse[...]()` rejects responses that do not contain at least // the claimed number of questions. // Tests against incorrect record count field validation, which is anti-pattern // #5 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsResponseTest, InitParseRejectsResponseWithMissingQuestions) { … } // Test that a parsed DnsResponse only allows parsing the number of records // claimed in the response header. // Tests against incorrect record count field validation, which is anti-pattern // #5 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsResponseTest, ParserLimitedToNumClaimedRecords) { … } // Test that a parsed DnsResponse does not allow parsing past the end of the // input, even if more records are claimed in the response header. // Tests against incorrect record count field validation, which is anti-pattern // #5 from the "NAME:WRECK" report: // https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/ TEST(DnsResponseTest, ParserLimitedToBufferSize) { … } TEST(DnsResponseWriteTest, SingleARecordAnswer) { … } TEST(DnsResponseWriteTest, SingleARecordAnswerWithFinalDotInName) { … } TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) { … } TEST(DnsResponseWriteTest, SingleAnswerWithQuestionConstructedFromSizeInflatedQuery) { … } TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) { … } TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestionAndNsecAdditionalRecord) { … } TEST(DnsResponseWriteTest, TwoAnswersWithAAndQuadARecords) { … } TEST(DnsResponseWriteTest, AnswerWithAuthorityRecord) { … } TEST(DnsResponseWriteTest, AnswerWithRcode) { … } // CNAME answers are always allowed for any question. TEST(DnsResponseWriteTest, AAAAQuestionAndCnameAnswer) { … } TEST(DnsResponseWriteTest, WrittenResponseCanBeParsed) { … } TEST(DnsResponseWriteTest, CreateEmptyNoDataResponse) { … } } // namespace } // namespace net