diff --git pdns/dnswriter.cc pdns/dnswriter.cc index fc02ebef7..b7a1dbeea 100644 --- pdns/dnswriter.cc +++ pdns/dnswriter.cc @@ -196,12 +196,16 @@ template void GenericDNSPacketWriter::xfrUnquote { if(text.empty()) { d_content.push_back(0); return; } - if(lenField) + if (lenField) { + if (text.length() > 255) { + throw runtime_error("invalid unquoted text length"); + } d_content.push_back(text.length()); + } d_content.insert(d_content.end(), text.c_str(), text.c_str() + text.length()); } static constexpr bool l_verbose=false; @@ -408,15 +412,18 @@ template void GenericDNSPacketWriter::xfrSvcPara xfr16BitInt(m); } break; case SvcParam::alpn: { - uint16_t totalSize = param.getALPN().size(); // All 1 octet size headers for each value + size_t totalSize = param.getALPN().size(); // All 1 octet size headers for each value for (auto const &a : param.getALPN()) { totalSize += a.length(); } - xfr16BitInt(totalSize); + if (totalSize > std::numeric_limits::max()) { + throw runtime_error("invalid total length of alpn parameters"); + } + xfr16BitInt(static_cast(totalSize)); for (auto const &a : param.getALPN()) { xfrUnquotedText(a, true); // will add the 1-byte length field } break; } diff --git pdns/rcpgenerator.cc pdns/rcpgenerator.cc index 75d6e77de..4597c2881 100644 --- pdns/rcpgenerator.cc +++ pdns/rcpgenerator.cc @@ -433,18 +433,26 @@ void RecordTextReader::xfrSvcParamKeyVals(set& val) // NOLINT(readabil len = v.at(spos); spos += 1; if (len == 0) { throw RecordTextException("ALPN values cannot be empty strings"); } + if (len > 255) { + throw RecordTextException("Length of ALPN value goes over 255"); + } if (len > v.length() - spos) { throw RecordTextException("Length of ALPN value goes over total length of alpn SVC Param"); } value.push_back(v.substr(spos, len)); spos += len; } } else { xfrSVCBValueList(value); + for (const auto& item : value) { + if (item.length() > 255) { + throw RecordTextException("Length of SVC ALPN value goes over 255"); + } + } } if (value.empty()) { throw RecordTextException("value is required for SVC Param " + k); } for (const auto &alpn_value : value) { diff --git pdns/test-dnsrecords_cc.cc pdns/test-dnsrecords_cc.cc index bbe176155..72ee3788e 100644 --- pdns/test-dnsrecords_cc.cc +++ pdns/test-dnsrecords_cc.cc @@ -221,10 +221,11 @@ BOOST_AUTO_TEST_CASE(test_record_types) { // Service mode (CASE_S(QType::SVCB, "1 .", "\x00\x01\x00")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. mandatory=alpn", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x00\x00\x02\x00\x01")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. no-default-alpn", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x02\x00\x00")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. alpn=h3,h2", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x01\x00\x06\x02h3\x02h2")) + (BROKEN_CASE_S(QType::SVCB, "1 foo.powerdns.org. alpn=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x01\x00\x06\x02h3\x02h2")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. port=53", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x03\x00\x02\x00\x35")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. ipv4hint=192.0.2.53,192.0.2.2", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x04\x00\x08\xc0\x00\x02\x35\xc0\x00\x02\x02")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. ech=\"aGVsbG8=\"", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x05\x00\x05hello")) (CASE_L(QType::SVCB, "1 foo.powerdns.org. ech=aGVsbG8=", "1 foo.powerdns.org. ech=\"aGVsbG8=\"", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x05\x00\x05hello")) (CASE_S(QType::SVCB, "1 foo.powerdns.org. ipv6hint=2001:db8::1,2001:db8::53:1", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x06\x00\x20\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x53\x00\x01"))