[SCM] Samba Shared Repository - branch master updated

Garming Sam garming at samba.org
Mon Dec 12 07:47:04 UTC 2016


The branch, master has been updated
       via  5f5ba89 tests/dns: Check you cannot add empty CNAME
       via  eacba34 dnsserver_common: Add name check in name2dn
       via  d571476 python/tests: expand samba-tool dns tests
       via  3799e78 python/tests: fix typo to use correct var
       via  4408df2 dnsserver: add dns name checking
       via  3ba40f6 tests/dnsserver: Check security descriptors
       via  30faba7 samba-tool/dns: remove use of dns_record_match from add and delete
       via  464da7d samba-tool/dns: reword error messages and make error catching specific
       via  64a3825 python/tests: expand tests for dns server over rpc
       via  b9c99a3 python/tests: add tests for samba-tool dns
       via  dba8dfe python/netcmd: print traceback through self.errf
      from  8be0a0d lib: Remove xfile

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 5f5ba893de53f624f04bbfd219aa8bf5ba595060
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Dec 7 16:42:38 2016 +1300

    tests/dns: Check you cannot add empty CNAME
    
    This exercises the dns_check_name case in the DNS server. Directly
    attempting to add an invalid name with leading . or double .. cannot be
    done due to ndr_pull_component forcing the check on the client side
    (leading to a CNAME name of NUL and unexpected data of the actual name).
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Pair-programmed-with: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Garming Sam <garming at samba.org>
    Autobuild-Date(master): Mon Dec 12 08:46:26 CET 2016 on sn-devel-144

commit eacba34a276397df4d5de09d741d0d7390e84020
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Dec 7 15:33:06 2016 +1300

    dnsserver_common: Add name check in name2dn
    
    Fills in the missing TODO. Note that this may also prevent deletion of
    existing corrupted records, but should be resolvable through RPC, or at
    worst LDAP.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit d57147621d5989e2a50278fbf02487aa979a1933
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Dec 7 15:00:25 2016 +1300

    python/tests: expand samba-tool dns tests
    
    These new tests concern collisions and lock in current Samba behaviour.
    
    They do not pass against Windows Server 2012R2. See dnsserver.py tests
    for the tests consistent with Windows behaviour.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3799e78a4b769327a6b303b5f8f0135c4ae8c253
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Dec 7 14:25:35 2016 +1300

    python/tests: fix typo to use correct var
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 4408df249349581654c5a77f4f8fa38bbae11b4f
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Tue Dec 6 15:34:23 2016 +1300

    dnsserver: add dns name checking
    
    This may also prevent deletion of existing corrupted records through
    DNS, but should be resolvable through RPC, or at worst LDAP.
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 3ba40f6eb194d773a2d369f6dc3472390fe248ea
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue Dec 6 11:00:17 2016 +1300

    tests/dnsserver: Check security descriptors
    
    These tests discover that there are some discrepancies between Windows and Samba.
    Although there are failures, they do not appear to be critical, however
    some of the SD differences will be important for 2012 support.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Pair-programmed-with: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 30faba750f235b9a5136746ae0b2393d013727fd
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Mon Nov 28 11:12:18 2016 +1300

    samba-tool/dns: remove use of dns_record_match from add and delete
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 464da7dc8d1d95e267b7c02889096a68dfddc596
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Fri Nov 25 16:29:31 2016 +1300

    samba-tool/dns: reword error messages and make error catching specific
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 64a382576542d35b4abd64ae78f54713d9d621f9
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Wed Nov 30 09:19:31 2016 +1300

    python/tests: expand tests for dns server over rpc
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit b9c99a3483d0de5508ec41698ae992764b2b9abe
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Mon Nov 21 16:22:46 2016 +1300

    python/tests: add tests for samba-tool dns
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit dba8dfe5240e2a2c3c2fc5cbc07e67796ce6bd3b
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Mon Nov 28 14:30:43 2016 +1300

    python/netcmd: print traceback through self.errf
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/netcmd/__init__.py          |   2 +-
 python/samba/netcmd/dns.py               | 115 ++--
 python/samba/tests/dcerpc/dnsserver.py   | 919 ++++++++++++++++++++++++++++---
 python/samba/tests/dns.py                |  11 +-
 python/samba/tests/samba_tool/dnscmd.py  | 661 ++++++++++++++++++++++
 selftest/knownfail                       |   3 +
 source4/dns_server/dnsserver_common.c    | 100 +++-
 source4/dns_server/dnsserver_common.h    |   4 +-
 source4/rpc_server/dnsserver/dnsdata.c   | 191 ++++++-
 source4/rpc_server/dnsserver/dnsdb.c     |  33 +-
 source4/rpc_server/dnsserver/dnsserver.h |   4 +-
 source4/rpc_server/wscript_build         |   2 +-
 source4/selftest/tests.py                |   1 +
 13 files changed, 1890 insertions(+), 156 deletions(-)
 create mode 100644 python/samba/tests/samba_tool/dnscmd.py


Changeset truncated at 500 lines:

diff --git a/python/samba/netcmd/__init__.py b/python/samba/netcmd/__init__.py
index 1debae8..e91bebd 100644
--- a/python/samba/netcmd/__init__.py
+++ b/python/samba/netcmd/__init__.py
@@ -120,7 +120,7 @@ class Command(object):
             force_traceback = True
 
         if force_traceback or samba.get_debug_level() >= 3:
-            traceback.print_tb(etraceback)
+            traceback.print_tb(etraceback, file=self.errf)
 
     def _create_parser(self, prog, epilog=None):
         parser = optparse.OptionParser(
diff --git a/python/samba/netcmd/dns.py b/python/samba/netcmd/dns.py
index 7cedffc..fe5a293 100644
--- a/python/samba/netcmd/dns.py
+++ b/python/samba/netcmd/dns.py
@@ -17,6 +17,7 @@
 #
 
 import samba.getopt as options
+from samba import WERRORError
 from struct import pack
 from socket import inet_ntoa
 from socket import inet_ntop
@@ -622,13 +623,16 @@ def dns_record_match(dns_conn, server, zone, name, record_type, data):
         buflen, res = dns_conn.DnssrvEnumRecords2(
             dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
             record_type, select_flags, None, None)
-    except RuntimeError, e:
-        return None
+    except WERRORError as e:
+        if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+            # Either the zone doesn't exist, or there were no records.
+            # We can't differentiate the two.
+            return None
+        raise e
 
     if not res or res.count == 0:
         return None
 
-    rec_match = None
     for rec in res.rec[0].records:
         if rec.wType != record_type:
             continue
@@ -678,10 +682,9 @@ def dns_record_match(dns_conn, server, zone, name, record_type, data):
                             (rec.data.str[i].str == urec.data.str[i].str)
 
         if found:
-            rec_match = rec
-            break
+            return rec
 
-    return rec_match
+    return None
 
 
 class cmd_serverinfo(Command):
@@ -892,9 +895,15 @@ class cmd_zonecreate(Command):
         name_and_param.pszNodeName = 'AllowUpdate'
         name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
 
-        res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
-                                        0, 'ResetDwordProperty', typeid,
-                                        name_and_param)
+        try:
+            res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
+                                            0, 'ResetDwordProperty', typeid,
+                                            name_and_param)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_ZONE_ALREADY_EXISTS':
+                self.outf.write('Zone already exists.')
+            raise e
+
         self.outf.write('Zone %s created successfully\n' % zone)
 
 
@@ -919,11 +928,17 @@ class cmd_zonedelete(Command):
         dns_conn = dns_connect(server, self.lp, self.creds)
 
         zone = zone.lower()
-        res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0, server, zone, 0, 'DeleteZoneFromDs',
-                                        dnsserver.DNSSRV_TYPEID_NULL,
-                                        None)
-        self.outf.write('Zone %s delete successfully\n' % zone)
+        try:
+            res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                            0, server, zone, 0, 'DeleteZoneFromDs',
+                                            dnsserver.DNSSRV_TYPEID_NULL,
+                                            None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist and so could not be deleted.')
+            raise e
+
+        self.outf.write('Zone %s deleted successfully\n' % zone)
 
 
 class cmd_query(Command):
@@ -993,9 +1008,15 @@ class cmd_query(Command):
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        buflen, res = dns_conn.DnssrvEnumRecords2(
+        try:
+            buflen, res = dns_conn.DnssrvEnumRecords2(
                 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
                 None, record_type, select_flags, None, None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Record or zone does not exist.')
+            raise e
+
         print_dnsrecords(self.outf, res)
 
 
@@ -1065,16 +1086,17 @@ class cmd_add_record(Command):
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
-                data)
-        if rec_match is not None:
-            raise CommandError('Record already exists')
-
         add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
         add_rec_buf.rec = rec
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                     0, server, zone, name, add_rec_buf, None)
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0, server, zone, name, add_rec_buf, None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be added.\n')
+            raise e
+
         self.outf.write('Record added successfully\n')
 
 
@@ -1119,7 +1141,7 @@ class cmd_update_record(Command):
         rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
                 olddata)
         if not rec_match:
-            raise CommandError('Record does not exist')
+            raise CommandError('Record or zone does not exist.')
 
         # Copy properties from existing record to new record
         rec.dwFlags = rec_match.dwFlags
@@ -1133,13 +1155,19 @@ class cmd_update_record(Command):
         del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
         del_rec_buf.rec = rec_match
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0,
-                                        server,
-                                        zone,
-                                        name,
-                                        add_rec_buf,
-                                        del_rec_buf)
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0,
+                                         server,
+                                         zone,
+                                         name,
+                                         add_rec_buf,
+                                         del_rec_buf)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be updated.\n')
+            raise e
+
         self.outf.write('Record updated successfully\n')
 
 
@@ -1173,25 +1201,28 @@ class cmd_delete_record(Command):
             raise CommandError('Deleting record of type %s is not supported' % rtype)
 
         record_type = dns_type_flag(rtype)
+        rec = data_to_dns_record(record_type, data)
 
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
-        if not rec_match:
-            raise CommandError('Record does not exist')
-
         del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
-        del_rec_buf.rec = rec_match
+        del_rec_buf.rec = rec
+
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0,
+                                         server,
+                                         zone,
+                                         name,
+                                         None,
+                                         del_rec_buf)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be deleted.\n')
+            raise e
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0,
-                                        server,
-                                        zone,
-                                        name,
-                                        None,
-                                        del_rec_buf)
         self.outf.write('Record deleted successfully\n')
 
 
diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py
index 7229877..9602066 100644
--- a/python/samba/tests/dcerpc/dnsserver.py
+++ b/python/samba/tests/dcerpc/dnsserver.py
@@ -17,20 +17,643 @@
 
 """Tests for samba.dcerpc.dnsserver"""
 
-from samba.dcerpc import dnsp, dnsserver
+import os
+import ldb
+
+from samba.auth import system_session
+from samba.samdb import SamDB
+from samba.ndr import ndr_unpack, ndr_pack
+from samba.dcerpc import dnsp, dnsserver, security
 from samba.tests import RpcInterfaceTestCase, env_get_var_value
-from samba.netcmd.dns import ARecord, NSRecord
+from samba.netcmd.dns import ARecord, AAAARecord, PTRRecord, CNameRecord, NSRecord, MXRecord, SRVRecord, TXTRecord
+from samba import sd_utils, descriptor
 
 class DnsserverTests(RpcInterfaceTestCase):
 
+    @classmethod
+    def setUpClass(cls):
+        good_dns = ["SAMDOM.EXAMPLE.COM",
+                    "1.EXAMPLE.COM",
+                    "%sEXAMPLE.COM" % ("1."*100),
+                    "EXAMPLE",
+                    "\n.COM",
+                    "!@#$%^&*()_",
+                    "HIGH\xFFBYTE",
+                    "@.EXAMPLE.COM",
+                    "."]
+        bad_dns = ["...",
+                   ".EXAMPLE.COM",
+                   ".EXAMPLE.",
+                   "",
+                   "SAMDOM..EXAMPLE.COM"]
+
+        good_mx = ["SAMDOM.EXAMPLE.COM 65535"]
+        bad_mx = []
+
+        good_srv = ["SAMDOM.EXAMPLE.COM 65535 65535 65535"]
+        bad_srv = []
+
+        for bad_dn in bad_dns:
+            bad_mx.append("%s 1" % bad_dn)
+            bad_srv.append("%s 0 0 0" % bad_dn)
+        for good_dn in good_dns:
+            good_mx.append("%s 1" % good_dn)
+            good_srv.append("%s 0 0 0" % good_dn)
+
+        cls.good_records = {
+            "A": ["192.168.0.1",
+                  "255.255.255.255"],
+            "AAAA": ["1234:5678:9ABC:DEF0:0000:0000:0000:0000",
+                     "0000:0000:0000:0000:0000:0000:0000:0000",
+                     "1234:5678:9ABC:DEF0:1234:5678:9ABC:DEF0",
+                     "1234:1234:1234::",
+                     "1234:1234:1234:1234:1234::",
+                     "1234:5678:9ABC:DEF0::",
+                     "0000:0000::0000",
+                     "1234::5678:9ABC:0000:0000:0000:0000",
+                     "::1",
+                     "::",
+                     "1:1:1:1:1:1:1:1"],
+            "PTR": good_dns,
+            "CNAME": good_dns,
+            "NS": good_dns,
+            "MX": good_mx,
+            "SRV": good_srv,
+            "TXT": ["text", "", "@#!", "\n"]
+        }
+
+        cls.bad_records = {
+            "A": ["192.168.0.500",
+                  "255.255.255.255/32"],
+            "AAAA": ["GGGG:1234:5678:9ABC:0000:0000:0000:0000",
+                     "0000:0000:0000:0000:0000:0000:0000:0000/1",
+                     "AAAA:AAAA:AAAA:AAAA:G000:0000:0000:1234",
+                     "1234:5678:9ABC:DEF0:1234:5678:9ABC:DEF0:1234",
+                     "1234:5678:9ABC:DEF0:1234:5678:9ABC",
+                     "1111::1111::1111"],
+            "PTR": bad_dns,
+            "CNAME": bad_dns,
+            "NS": bad_dns,
+            "MX": bad_mx,
+            "SRV": bad_srv
+        }
+
+        # Because we use uint16_t for these numbers, we can't
+        # actually create these records.
+        invalid_mx = ["SAMDOM.EXAMPLE.COM -1",
+                      "SAMDOM.EXAMPLE.COM 65536",
+                      "%s 1" % "A"*256]
+        invalid_srv = ["SAMDOM.EXAMPLE.COM 0 65536 0",
+                       "SAMDOM.EXAMPLE.COM 0 0 65536",
+                       "SAMDOM.EXAMPLE.COM 65536 0 0"]
+        cls.invalid_records = {
+            "MX": invalid_mx,
+            "SRV": invalid_srv
+        }
+
     def setUp(self):
         super(DnsserverTests, self).setUp()
-        self.server = env_get_var_value("SERVER_IP")
+        self.server = os.environ["DC_SERVER"]
         self.zone = env_get_var_value("REALM").lower()
         self.conn = dnsserver.dnsserver("ncacn_ip_tcp:%s[sign]" % (self.server),
                                         self.get_loadparm(),
                                         self.get_credentials())
 
+        self.samdb = SamDB(url="ldap://%s" % os.environ["DC_SERVER_IP"],
+                           lp = self.get_loadparm(),
+                           session_info=system_session(),
+                           credentials=self.get_credentials())
+
+
+        self.custom_zone = "zone"
+        zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
+        zone_create_info.pszZoneName = self.custom_zone
+        zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
+        zone_create_info.fAging = 0
+        zone_create_info.fDsIntegrated = 1
+        zone_create_info.fLoadExisting = 1
+        zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
+
+        self.conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                   0,
+                                   self.server,
+                                   None,
+                                   0,
+                                   'ZoneCreate',
+                                   dnsserver.DNSSRV_TYPEID_ZONE_CREATE,
+                                   zone_create_info)
+
+    def tearDown(self):
+        self.conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                   0,
+                                   self.server,
+                                   self.custom_zone,
+                                   0,
+                                   'DeleteZoneFromDs',
+                                   dnsserver.DNSSRV_TYPEID_NULL,
+                                   None)
+        super(DnsserverTests, self).tearDown()
+
+    # 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
+    # does not have DNS_ZONE_TYPE_PRIMARY. Since such records can be
+    # deleted, however, we do not consider this urgent to fix and
+    # so this test is a knownfail.
+    def test_rank_none(self):
+        """
+        See what happens when we set a record's rank to
+        DNS_RANK_NONE.
+        """
+
+        record_str = "192.168.50.50"
+        record_type_str = "A"
+        self.add_record(self.custom_zone, "testrecord", record_type_str, record_str)
+
+        dn, record = self.get_record_from_db(self.custom_zone, "testrecord")
+        record.rank = 0 # DNS_RANK_NONE
+        res = self.samdb.dns_replace_by_dn(dn, [record])
+        if res is not None:
+            self.fail("Unable to update dns record to have DNS_RANK_NONE.")
+
+        self.assert_num_records(self.custom_zone, "testrecord", record_type_str)
+        self.add_record(self.custom_zone, "testrecord", record_type_str, record_str, assertion=False)
+        self.delete_record(self.custom_zone, "testrecord", record_type_str, record_str)
+        self.assert_num_records(self.custom_zone, "testrecord", record_type_str, 0)
+
+    def test_dns_tombstoned(self):
+        """
+        See what happens when we set a record to be tombstoned.
+        """
+
+        record_str = "192.168.50.50"
+        record_type_str = "A"
+        self.add_record(self.custom_zone, "testrecord", record_type_str, record_str)
+
+        dn, record = self.get_record_from_db(self.custom_zone, "testrecord")
+        record.wType = dnsp.DNS_TYPE_TOMBSTONE
+        res = self.samdb.dns_replace_by_dn(dn, [record])
+        if res is not None:
+            self.fail("Unable to update dns record to be tombstoned.")
+
+        self.assert_num_records(self.custom_zone, "testrecord", record_type_str)
+        self.delete_record(self.custom_zone, "testrecord", record_type_str, record_str)
+        self.assert_num_records(self.custom_zone, "testrecord", record_type_str, 0)
+
+    def get_record_from_db(self, zone_name, record_name):
+        """
+        Returns (dn of record, record)
+        """
+
+        zones = self.samdb.search(base="DC=DomainDnsZones,%s" % self.samdb.get_default_basedn(), scope=ldb.SCOPE_SUBTREE,
+                                  expression="(objectClass=dnsZone)",
+                                  attrs=["cn"])
+
+        zone_dn = None
+        for zone in zones:
+            if zone_name in str(zone.dn):
+                zone_dn = zone.dn
+                break
+
+        if zone_dn is None:
+            raise AssertionError("Couldn't find zone '%s'." % zone_name)
+
+        records = self.samdb.search(base=zone_dn, scope=ldb.SCOPE_SUBTREE,
+                                    expression="(objectClass=dnsNode)",
+                                    attrs=["dnsRecord"])
+
+        for old_packed_record in records:
+            if record_name in str(old_packed_record.dn):
+                return (old_packed_record.dn, ndr_unpack(dnsp.DnssrvRpcRecord, old_packed_record["dnsRecord"][0]))
+
+    def test_duplicate_matching(self):
+        """
+        Make sure that records which should be distinct from each other or duplicate
+        to each other behave as expected.
+        """
+
+        distinct_dns = [("SAMDOM.EXAMPLE.COM",
+                         "SAMDOM.EXAMPLE.CO",
+                         "EXAMPLE.COM", "SAMDOM.EXAMPLE")]
+        duplicate_dns = [("SAMDOM.EXAMPLE.COM", "samdom.example.com", "SAMDOM.example.COM"),
+                         ("EXAMPLE.", "EXAMPLE")]
+
+        # Every tuple has entries which should be considered duplicate to one another.
+        duplicates = {
+            "AAAA": [("AAAA::", "aaaa::"),
+                     ("AAAA::", "AAAA:0000::"),
+                     ("AAAA::", "AAAA:0000:0000:0000:0000:0000:0000:0000"),
+                     ("AAAA::", "AAAA:0:0:0:0:0:0:0"),
+                     ("0123::", "123::"),
+                     ("::", "::0", "0000:0000:0000:0000:0000:0000:0000:0000")],
+        }
+
+        # Every tuple has entries which should be considered distinct from one another.
+        distinct = {
+            "A": [("192.168.1.0", "192.168.1.1", "192.168.2.0", "192.169.1.0", "193.168.1.0")],
+            "AAAA": [("AAAA::1234:5678:9ABC", "::AAAA:1234:5678:9ABC"),
+                     ("1000::", "::1000"),
+                     ("::1", "::11", "::1111"),
+                     ("1234::", "0234::")],
+            "SRV": [("SAMDOM.EXAMPLE.COM 1 1 1", "SAMDOM.EXAMPLE.COM 1 1 0", "SAMDOM.EXAMPLE.COM 1 0 1",
+                     "SAMDOM.EXAMPLE.COM 0 1 1", "SAMDOM.EXAMPLE.COM 2 1 0", "SAMDOM.EXAMPLE.COM 2 2 2")],
+            "MX": [("SAMDOM.EXAMPLE.COM 1", "SAMDOM.EXAMPLE.COM 0")],
+            "TXT": [("A RECORD", "B RECORD", "a record")]
+        }
+
+        for record_type_str in ("PTR", "CNAME", "NS"):
+            distinct[record_type_str] = distinct_dns
+            duplicates[record_type_str] = duplicate_dns
+
+        for record_type_str in duplicates:
+            for duplicate_tuple in duplicates[record_type_str]:
+                # Attempt to add duplicates and make sure that all after the first fails
+                self.add_record(self.custom_zone, "testrecord", record_type_str, duplicate_tuple[0])
+                for record in duplicate_tuple:
+                    self.add_record(self.custom_zone, "testrecord", record_type_str, record, assertion=False)
+                    self.assert_num_records(self.custom_zone, "testrecord", record_type_str)
+                self.delete_record(self.custom_zone, "testrecord", record_type_str, duplicate_tuple[0])
+
+                # Repeatedly: add the first duplicate, and attempt to remove all of the others, making sure this succeeds
+                for record in duplicate_tuple:
+                    self.add_record(self.custom_zone, "testrecord", record_type_str, duplicate_tuple[0])
+                    self.delete_record(self.custom_zone, "testrecord", record_type_str, record)
+
+        for record_type_str in distinct:
+            for distinct_tuple in distinct[record_type_str]:
+                # Attempt to add distinct and make sure that they all succeed within a tuple
+                i = 0
+                for record in distinct_tuple:
+                    i = i + 1
+                    try:
+                        self.add_record(self.custom_zone, "testrecord", record_type_str, record)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list