]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[950-harden-deferred-unpack] Hardened deffered unpacking so it no longer throws 950-harden-deferred-unpack
authorFrancis Dupont <fdupont@isc.org>
Sat, 12 Oct 2019 20:46:39 +0000 (22:46 +0200)
committerFrancis Dupont <fdupont@isc.org>
Sat, 12 Oct 2019 20:46:39 +0000 (22:46 +0200)
src/bin/dhcp4/dhcp4_messages.cc
src/bin/dhcp4/dhcp4_messages.h
src/bin/dhcp4/dhcp4_messages.mes
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/vendor_opts_unittest.cc

index 807b8147da134ab3a4cc56877c7e8546a86cea7a..f3e3a0edbaf5b75ce767c33c3ca67c56fcea1657 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Wed Jul 10 2019 15:10
+// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Sat Oct 12 2019 22:27
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -100,6 +100,7 @@ extern const isc::log::MessageID DHCP4_PACKET_NAK_0002 = "DHCP4_PACKET_NAK_0002"
 extern const isc::log::MessageID DHCP4_PACKET_NAK_0003 = "DHCP4_PACKET_NAK_0003";
 extern const isc::log::MessageID DHCP4_PACKET_NAK_0004 = "DHCP4_PACKET_NAK_0004";
 extern const isc::log::MessageID DHCP4_PACKET_OPTIONS_SKIPPED = "DHCP4_PACKET_OPTIONS_SKIPPED";
+extern const isc::log::MessageID DHCP4_PACKET_OPTION_UNPACK_FAIL = "DHCP4_PACKET_OPTION_UNPACK_FAIL";
 extern const isc::log::MessageID DHCP4_PACKET_PACK = "DHCP4_PACKET_PACK";
 extern const isc::log::MessageID DHCP4_PACKET_PACK_FAIL = "DHCP4_PACKET_PACK_FAIL";
 extern const isc::log::MessageID DHCP4_PACKET_PROCESS_EXCEPTION = "DHCP4_PACKET_PROCESS_EXCEPTION";
@@ -236,7 +237,8 @@ const char* values[] = {
     "DHCP4_PACKET_NAK_0002", "%1: invalid address %2 requested by INIT-REBOOT",
     "DHCP4_PACKET_NAK_0003", "%1: failed to advertise a lease, client sent ciaddr %2, requested-ip-address %3",
     "DHCP4_PACKET_NAK_0004", "%1: failed to grant a lease, client sent ciaddr %2, requested-ip-address %3",
-    "DHCP4_PACKET_OPTIONS_SKIPPED", "An error upacking an option, caused subsequent options to be skipped: %1",
+    "DHCP4_PACKET_OPTIONS_SKIPPED", "An error unpacking an option, caused subsequent options to be skipped: %1",
+    "DHCP4_PACKET_OPTION_UNPACK_FAIL", "An error unpacking the option %1: %2",
     "DHCP4_PACKET_PACK", "%1: preparing on-wire format of the packet to be sent",
     "DHCP4_PACKET_PACK_FAIL", "%1: preparing on-wire-format of the packet to be sent failed %2",
     "DHCP4_PACKET_PROCESS_EXCEPTION", "exception occurred during packet processing",
index f58ca25bbe951cda870d194037855ed075dce38f..c62bd16d5abefda662b9af554153eb1bcb9dbf33 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Wed Jul 10 2019 15:10
+// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Sat Oct 12 2019 22:27
 
 #ifndef DHCP4_MESSAGES_H
 #define DHCP4_MESSAGES_H
@@ -101,6 +101,7 @@ extern const isc::log::MessageID DHCP4_PACKET_NAK_0002;
 extern const isc::log::MessageID DHCP4_PACKET_NAK_0003;
 extern const isc::log::MessageID DHCP4_PACKET_NAK_0004;
 extern const isc::log::MessageID DHCP4_PACKET_OPTIONS_SKIPPED;
+extern const isc::log::MessageID DHCP4_PACKET_OPTION_UNPACK_FAIL;
 extern const isc::log::MessageID DHCP4_PACKET_PACK;
 extern const isc::log::MessageID DHCP4_PACKET_PACK_FAIL;
 extern const isc::log::MessageID DHCP4_PACKET_PROCESS_EXCEPTION;
index 7a0b1c19f2e18dbacf75897438fdacd7d2b5ee1f..888ca4fe1716c0e126ad9e197ae62ca21180ad85 100644 (file)
@@ -552,7 +552,12 @@ identification information. The second argument contains the IPv4 address
 in the ciaddr field. The third argument contains the IPv4 address in the
 requested-ip-address option (if present).
 
-% DHCP4_PACKET_OPTIONS_SKIPPED An error upacking an option, caused subsequent options to be skipped: %1
+% DHCP4_PACKET_OPTION_UNPACK_FAIL An error unpacking the option %1: %2
+A debug message issued when an option failed to unpack correctly, making it
+to be left unpacked in the packet. The first argument is the option code,
+the second the error.
+
+% DHCP4_PACKET_OPTIONS_SKIPPED An error unpacking an option, caused subsequent options to be skipped: %1
 A debug message issued when an option failed to unpack correctly, making it
 impossible to unpack the remaining options in the packet.  The server will
 server will still attempt to service the packet.
index 456c6d9d896dcd75aab209a4d52092b2d3ca4c5d..db5dffc5c6bdd10c55754e849b222e87f789fb17 100644 (file)
@@ -3572,14 +3572,28 @@ Dhcpv4Srv::deferredUnpack(Pkt4Ptr& query)
         OptionPtr opt = query->getOption(code);
         if (!opt) {
             // should not happen but do not crash anyway
+            LOG_DEBUG(bad_packet4_logger, DBG_DHCP4_DETAIL,
+                      DHCP4_PACKET_OPTION_UNPACK_FAIL)
+                .arg(code)
+                .arg("can't find the option in the query");
             continue;
         }
         const OptionBuffer buf = opt->getData();
+        try {
+            // Unpack the option
+            opt = def->optionFactory(Option::V4, code, buf);
+        } catch (const std::exception& e) {
+            // Failed to parse the option.
+            LOG_DEBUG(bad_packet4_logger, DBG_DHCP4_DETAIL,
+                      DHCP4_PACKET_OPTION_UNPACK_FAIL)
+                .arg(code)
+                .arg(e.what());
+            continue;
+        }
         while (query->delOption(code)) {
             // continue
         }
-        // Unpack the option and add it
-        opt = def->optionFactory(Option::V4, code, buf.cbegin(), buf.cend());
+        // Add the unpacked option.
         query->addOption(opt);
     }
 }
index 2f94205a71e28a57a23ca1d1587f2c5a9cc7503a..c13cabe889862fcbed26ca3188f7e0e4c796974c 100644 (file)
@@ -684,7 +684,7 @@ TEST_F(VendorOptsTest, option43FailRaw) {
     // The vendor-encapsulated-options has an incompatible data
     // so won't have the expected content. Here the processing
     // of suboptions tries to unpack the uitn32 foo suboption and
-    // raises an exception.
+    // raises an exception which is caught so the option stays unpacked.
     string config = "{ \"interfaces-config\": {"
         "    \"interfaces\": [ \"*\" ] }, "
         "\"subnet4\": [ "
@@ -742,7 +742,9 @@ TEST_F(VendorOptsTest, option43FailRaw) {
     query->addOption(prl);
 
     srv.classifyPacket(query);
-    EXPECT_THROW(srv.deferredUnpack(query), InvalidOptionValue);
+    EXPECT_NO_THROW(srv.deferredUnpack(query));
+    ASSERT_TRUE(query->getOption(vopt->getType()));
+    EXPECT_EQ(vopt, query->getOption(vopt->getType()));
 }
 
 // Verifies raw option 43 can be handled (global)
@@ -1321,7 +1323,7 @@ TEST_F(VendorOptsTest, clientOption43FailRaw) {
     // The vendor-encapsulated-options has an incompatible data
     // so won't have the expected content. Here the processing
     // of suboptions tries to unpack the uint32 foo suboption and
-    // raises an exception.
+    // raises an exception which is caught.
     string config = "{ \"interfaces-config\": {"
         "    \"interfaces\": [ \"*\" ] }, "
         "\"subnet4\": [ "
@@ -1346,9 +1348,9 @@ TEST_F(VendorOptsTest, clientOption43FailRaw) {
     client.addExtraOption(vopt);
 
     // Let's check whether the server is not able to process this packet
-    // and raises an exception so the response is empty.
+    // and raises an exception which is caught so the response is not empty.
     EXPECT_NO_THROW(client.doDiscover());
-    EXPECT_FALSE(client.getContext().response_);
+    EXPECT_TRUE(client.getContext().response_);
 }
 
 // Verifies raw option 43 sent by a client can be handled (global)