]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix computation of the final proxy protocol payload size 12025/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 29 Sep 2022 07:52:32 +0000 (09:52 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 29 Sep 2022 07:52:32 +0000 (09:52 +0200)
pdns/proxy-protocol.cc
pdns/test-proxy_protocol_cc.cc

index a68f094c902ec7820821b2d1857c55218b41a06b..9bf48adcc343a17e2def24b92b42cc3bba3f21d1 100644 (file)
@@ -32,7 +32,7 @@ static const string proxymagic(PROXYMAGIC, PROXYMAGICLEN);
 static void makeSimpleHeader(uint8_t command, uint8_t protocol, uint16_t contentLen, size_t additionalSize, std::string& out)
 {
   const uint8_t versioncommand = (0x20 | command);
-  const size_t totalSize = proxymagic.size() + sizeof(versioncommand) + sizeof(protocol) + sizeof(contentLen) + contentLen + additionalSize;
+  const size_t totalSize = proxymagic.size() + sizeof(versioncommand) + sizeof(protocol) + sizeof(contentLen) + additionalSize;
   if (out.capacity() < totalSize) {
     out.reserve(totalSize);
   }
@@ -75,14 +75,15 @@ std::string makeProxyHeader(bool tcp, const ComboAddress& source, const ComboAdd
     }
   }
 
-  size_t total = (addrSize * 2) + sizeof(sourcePort) + sizeof(destinationPort) + valuesSize;
-  if (total > std::numeric_limits<uint16_t>::max()) {
-    throw std::runtime_error("The size of a proxy protocol header is limited to " + std::to_string(std::numeric_limits<uint16_t>::max()) + ", trying to send one of size " + std::to_string(total));
+  /* size of the data that will come _after_ the minimal proxy protocol header */
+  size_t additionalDataSize = (addrSize * 2) + sizeof(sourcePort) + sizeof(destinationPort) + valuesSize;
+  if (additionalDataSize > std::numeric_limits<uint16_t>::max()) {
+    throw std::runtime_error("The size of a proxy protocol header is limited to " + std::to_string(std::numeric_limits<uint16_t>::max()) + ", trying to send one of size " + std::to_string(additionalDataSize));
   }
 
-  const uint16_t contentlen = htons(static_cast<uint16_t>(total));
+  const uint16_t contentlen = htons(static_cast<uint16_t>(additionalDataSize));
   std::string ret;
-  makeSimpleHeader(command, protocol, contentlen, total, ret);
+  makeSimpleHeader(command, protocol, contentlen, additionalDataSize, ret);
 
   // We already established source and destination sin_family equivalence
   if (source.isIPv4()) {
index e61f9787618e69303a520645ee135af190dfa797..6a672c4dac01ba6cfbda4fd0421d529907b6762c 100644 (file)
@@ -101,6 +101,18 @@ BOOST_AUTO_TEST_CASE(test_tlv_values_content_len_signedness) {
   }
 }
 
+BOOST_AUTO_TEST_CASE(test_payload_too_large) {
+  const bool tcp = false;
+  const ComboAddress src("[2001:db8::1]:0");
+  const ComboAddress dest("[::1]:65535");
+  std::string largeValue;
+  /* this value is larger than the maximum size for a TLV */
+  largeValue.resize(65536, 'A');
+  const std::vector<ProxyProtocolValue> values = {{ largeValue, 255 }};
+
+  BOOST_CHECK_THROW(makeProxyHeader(tcp, src, dest, values), std::runtime_error);
+}
+
 BOOST_AUTO_TEST_CASE(test_tlv_values_length_signedness) {
   std::string largeValue;
   /* this value will make the TLV length parsing fail in case of signedness mistake */