CVE-2019-14861: s4-rpc/dnsserver: Confirm sort behaviour in dcesrv_DnssrvEnumRecords
authorAndrew Bartlett <abartlet@samba.org>
Tue, 29 Oct 2019 04:25:28 +0000 (17:25 +1300)
committerKarolin Seeger <kseeger@samba.org>
Tue, 3 Dec 2019 11:50:18 +0000 (12:50 +0100)
The sort behaviour for child records is not correct in Samba so
we add a flapping entry.

(patch differs from master patch due to addtional flapping entry
for python2)

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14138

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/dcerpc/dnsserver.py
selftest/flapping.d/dnsserver [new file with mode: 0644]

index 0da9614d0666faae14097e3447e3b5fc5b7811b9..b2dffc924cb4c51f50a264d8ae4a8741006ab7b1 100644 (file)
@@ -156,6 +156,107 @@ class DnsserverTests(RpcInterfaceTestCase):
                                    None)
         super(DnsserverTests, self).tearDown()
 
+    def test_enum_is_sorted(self):
+        """
+        Confirm the zone is sorted
+        """
+
+        record_str = "192.168.50.50"
+        record_type_str = "A"
+        self.add_record(self.custom_zone, "atestrecord-1", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-2", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-3", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-4", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-0", record_type_str, record_str)
+
+        # This becomes an extra A on the zone itself by server-side magic
+        self.add_record(self.custom_zone, self.custom_zone, record_type_str, record_str)
+
+        _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                                 0,
+                                                 self.server,
+                                                 self.custom_zone,
+                                                 "@",
+                                                 None,
+                                                 self.record_type_int(record_type_str),
+                                                 dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA,
+                                                 None,
+                                                 None)
+
+        self.assertEqual(len(result.rec), 6)
+        self.assertEqual(result.rec[0].dnsNodeName.str, "")
+        self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0")
+        self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1")
+        self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2")
+        self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3")
+        self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4")
+
+    def test_enum_is_sorted_children_prefix_first(self):
+        """
+        Confirm the zone returns the selected prefix first but no more
+        as Samba is flappy for the full sort
+        """
+
+        record_str = "192.168.50.50"
+        record_type_str = "A"
+        self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str)
+
+        # Not expected to be returned
+        self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str)
+
+        _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                                 0,
+                                                 self.server,
+                                                 self.custom_zone,
+                                                 "a.b",
+                                                 None,
+                                                 self.record_type_int(record_type_str),
+                                                 dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA,
+                                                 None,
+                                                 None)
+
+        self.assertEqual(len(result.rec), 6)
+        self.assertEqual(result.rec[0].dnsNodeName.str, "")
+
+    def test_enum_is_sorted_children(self):
+        """
+        Confirm the zone is sorted
+        """
+
+        record_str = "192.168.50.50"
+        record_type_str = "A"
+        self.add_record(self.custom_zone, "atestrecord-1.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-2.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-3.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-4.a.b", record_type_str, record_str)
+        self.add_record(self.custom_zone, "atestrecord-0.a.b", record_type_str, record_str)
+
+        # Not expected to be returned
+        self.add_record(self.custom_zone, "atestrecord-0.b.b", record_type_str, record_str)
+
+        _, result = self.conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                                 0,
+                                                 self.server,
+                                                 self.custom_zone,
+                                                 "a.b",
+                                                 None,
+                                                 self.record_type_int(record_type_str),
+                                                 dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA,
+                                                 None,
+                                                 None)
+
+        self.assertEqual(len(result.rec), 6)
+        self.assertEqual(result.rec[0].dnsNodeName.str, "")
+        self.assertEqual(result.rec[1].dnsNodeName.str, "atestrecord-0")
+        self.assertEqual(result.rec[2].dnsNodeName.str, "atestrecord-1")
+        self.assertEqual(result.rec[3].dnsNodeName.str, "atestrecord-2")
+        self.assertEqual(result.rec[4].dnsNodeName.str, "atestrecord-3")
+        self.assertEqual(result.rec[5].dnsNodeName.str, "atestrecord-4")
+
     # This test fails against Samba (but passes against Windows),
     # because Samba does not return the record when we enum records.
     # Records can be given DNS_RANK_NONE when the zone they are in
diff --git a/selftest/flapping.d/dnsserver b/selftest/flapping.d/dnsserver
new file mode 100644 (file)
index 0000000..bf2dc99
--- /dev/null
@@ -0,0 +1,3 @@
+# This is not stable in samba due to a bug
+^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_enum_is_sorted_children
+^samba.tests.dcerpc.dnsserver.python2.samba.tests.dcerpc.dnsserver.DnsserverTests.test_enum_is_sorted_children