Exemple #1
0
    def operation_79(self, op):
        if self.update_exists(op):
            return
        self.raise_if_not_fix(op)

        ace = "(OA;CIIO;WP;ea1b7b93-5e48-46d5-bc6c-4df4fda78a35;bf967a86-0de6-11d0-a285-00aa003049e2;PS)"

        res = self.samdb.search(expression="(objectClass=samDomain)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])
        for msg in res:
            existing_sd = ndr_unpack(security.descriptor,
                                     msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        res = self.samdb.search(expression="(objectClass=domainDNS)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])
        for msg in res:
            existing_sd = ndr_unpack(security.descriptor,
                                     msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        if self.add_update_container:
            self.update_add(op)
Exemple #2
0
    def operation_81(self, op):
        if self.update_exists(op):
            return
        self.raise_if_not_fix(op)

        ace = "(OA;CIOI;RPWP;3f78c3e5-f79a-46bd-a0b8-9d18116ddc79;;PS)"

        res = self.samdb.search(expression="(objectClass=samDomain)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])
        for msg in res:
            existing_sd = ndr_unpack(security.descriptor,
                                     msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        res = self.samdb.search(expression="(objectClass=domainDNS)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])

        for msg in res:
            existing_sd = ndr_unpack(security.descriptor,
                                     msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        if self.add_update_container:
            self.update_add(op)
Exemple #3
0
    def test_dirsync_deleted_items(self):
        """Check that dirsync returnd deleted objects too"""
        # Let's create an OU
        ouname="OU=testou3,%s" % self.base_dn
        self.ouname = ouname
        self.ldb_admin.create_ou(ouname)
        res = self.ldb_admin.search(self.base_dn,
                                    expression="(&(objectClass=organizationalUnit)(!(isDeleted=*)))",
                                    controls=["dirsync:1:0:1"])
        guid = None
        for e in res:
            if str(e["name"]) == "testou3":
                guid = str(ndr_unpack(misc.GUID,e.get("objectGUID")[0]))

        ctl = str(res.controls[0]).split(":")
        ctl[1] = "1"
        ctl[2] = "0"
        ctl[3] = "10000"
        control1 = str(":".join(ctl))

        # So now delete the object and check that
        # we can see the object but deleted when admin
        delete_force(self.ldb_admin, ouname)

        res = self.ldb_admin.search(self.base_dn,
                                    expression="(objectClass=organizationalUnit)",
                                    controls=[control1])
        self.assertEqual(len(res), 1)
        guid2 = str(ndr_unpack(misc.GUID,res[0].get("objectGUID")[0]))
        self.assertEqual(guid2, guid)
        self.assertTrue(res[0].get("isDeleted"))
        self.assertTrue(res[0].get("name") != None)
Exemple #4
0
    def setUp(self):
        super(DynamicTokenTest, self).setUp()
        self.admin_ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)

        self.base_dn = self.admin_ldb.domain_dn()

        self.test_user = "******"
        self.test_user_pass = "******"
        self.admin_ldb.newuser(self.test_user, self.test_user_pass)
        self.test_group0 = "tokengroups_group0"
        self.admin_ldb.newgroup(self.test_group0, grouptype=dsdb.GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)
        res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group0, self.base_dn),
                                    attrs=["objectSid"], scope=ldb.SCOPE_BASE)
        self.test_group0_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0])

        self.admin_ldb.add_remove_group_members(self.test_group0, [self.test_user],
                                       add_members_operation=True)

        self.test_group1 = "tokengroups_group1"
        self.admin_ldb.newgroup(self.test_group1, grouptype=dsdb.GTYPE_SECURITY_GLOBAL_GROUP)
        res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group1, self.base_dn),
                                    attrs=["objectSid"], scope=ldb.SCOPE_BASE)
        self.test_group1_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0])

        self.admin_ldb.add_remove_group_members(self.test_group1, [self.test_user],
                                       add_members_operation=True)

        self.test_group2 = "tokengroups_group2"
        self.admin_ldb.newgroup(self.test_group2, grouptype=dsdb.GTYPE_SECURITY_UNIVERSAL_GROUP)

        res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (self.test_group2, self.base_dn),
                                    attrs=["objectSid"], scope=ldb.SCOPE_BASE)
        self.test_group2_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0])

        self.admin_ldb.add_remove_group_members(self.test_group2, [self.test_user],
                                       add_members_operation=True)

        self.ldb = self.get_ldb_connection(self.test_user, self.test_user_pass)

        res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"])
        self.assertEquals(len(res), 1)

        self.user_sid_dn = "<SID=%s>" % str(ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0]))

        res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=[])
        self.assertEquals(len(res), 1)

        self.test_user_dn = res[0].dn

        session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS |
                               AUTH_SESSION_INFO_AUTHENTICATED |
                               AUTH_SESSION_INFO_SIMPLE_PRIVILEGES)
        session = samba.auth.user_session(self.ldb, lp_ctx=lp, dn=self.user_sid_dn,
                                          session_info_flags=session_info_flags)

        token = session.security_token
        self.user_sids = []
        for s in token.sids:
            self.user_sids.append(str(s))
Exemple #5
0
 def _get_identifier(self, ldb_conn, dn):
     res = ldb_conn.search(dn, scope=ldb.SCOPE_BASE,
             attrs=["objectGUID", "objectSid"])
     id = drsuapi.DsReplicaObjectIdentifier()
     id.guid = ndr_unpack(misc.GUID, res[0]['objectGUID'][0])
     if "objectSid" in res[0]:
         id.sid = ndr_unpack(security.dom_sid, res[0]['objectSid'][0])
     id.dn = str(res[0].dn)
     return id
Exemple #6
0
    def _check_ctr6(self, ctr6, expected_dns=[], expected_links=[],
                    dn_ordered=True, links_ordered=True,
                    more_data=False, nc_object_count=0,
                    nc_linked_attributes_count=0, drs_error=0):
        """
        Check that a ctr6 matches the specified parameters.
        """
        self.assertEqual(ctr6.object_count, len(expected_dns))
        self.assertEqual(ctr6.linked_attributes_count, len(expected_links))
        self.assertEqual(ctr6.more_data, more_data)
        self.assertEqual(ctr6.nc_object_count, nc_object_count)
        self.assertEqual(ctr6.nc_linked_attributes_count, nc_linked_attributes_count)
        self.assertEqual(ctr6.drs_error[0], drs_error)

        ctr6_dns = []
        next_object = ctr6.first_object
        for i in range(0, ctr6.object_count):
            ctr6_dns.append(next_object.object.identifier.dn)
            next_object = next_object.next_object
        self.assertEqual(next_object, None)

        i = 0
        for dn in expected_dns:
            # Expect them back in the exact same order as specified.
            if dn_ordered:
                self.assertNotEqual(ctr6_dns[i], None)
                self.assertEqual(ctr6_dns[i], dn)
                i = i + 1
            # Don't care what order
            else:
                self.assertTrue(dn in ctr6_dns, "Couldn't find DN '%s' anywhere in ctr6 response." % dn)

        ctr6_links = []
        expected_links.sort()
        lidx = 0
        for lidx in range(0, ctr6.linked_attributes_count):
            l = ctr6.linked_attributes[lidx]
            try:
                target = ndr_unpack(drsuapi.DsReplicaObjectIdentifier3,
                                    l.value.blob)
            except:
                target = ndr_unpack(drsuapi.DsReplicaObjectIdentifier3Binary,
                                    l.value.blob)
            al = AbstractLink(l.attid, l.flags,
                              l.identifier.guid,
                              target.guid)
            ctr6_links.append(al)

        lidx = 0
        for el in expected_links:
            if links_ordered:
                self.assertEqual(el, ctr6_links[lidx])
                lidx += 1
            else:
                self.assertTrue(el in ctr6_links, "Couldn't find link '%s' anywhere in ctr6 response." % el)
    def test_userPassword_cleartext_sha256(self):
        self.add_user(clear_text=True,
                      options=[("password hash userPassword schemes",
                                "CryptSHA256:rounds=100")])

        sc = self.get_supplemental_creds()

        # Check that we got all the expected supplemental credentials
        # And they are in the expected order.
        size = len(sc.sub.packages)
        self.assertEquals(6, size)

        (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
        self.assertEquals(1, pos)
        self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)

        (pos, package) = get_package(sc, "Primary:Kerberos")
        self.assertEquals(2, pos)
        self.assertEquals("Primary:Kerberos", package.name)

        (pos, wd_package) = get_package(sc, "Primary:WDigest")
        self.assertEquals(3, pos)
        self.assertEquals("Primary:WDigest", wd_package.name)

        (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT")
        self.assertEquals(4, pos)
        self.assertEquals("Primary:CLEARTEXT", ct_package.name)

        (pos, package) = get_package(sc, "Packages")
        self.assertEquals(5, pos)
        self.assertEquals("Packages", package.name)

        (pos, up_package) = get_package(sc, "Primary:userPassword")
        self.assertEquals(6, pos)
        self.assertEquals("Primary:userPassword", up_package.name)

        # Check that the WDigest values are correct.
        #
        digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
                             binascii.a2b_hex(wd_package.data))
        self.check_wdigests(digests)

        # Check the clear text  value is correct.
        ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
                        binascii.a2b_hex(ct_package.data))
        self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)

        # Check that the userPassword hashes are computed correctly
        #
        up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
                        binascii.a2b_hex(up_package.data))
        self.checkUserPassword(up, [("{CRYPT}", "5",100 )])
        self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
    def test_userPassword_multiple_hashes_rounds_specified(self):
        self.add_user(options=[(
            "password hash userPassword schemes",
            "CryptSHA512:rounds=5120 CryptSHA256:rounds=2560 CryptSHA512:rounds=5122")])

        sc = self.get_supplemental_creds()

        # Check that we got all the expected supplemental credentials
        # And they are in the expected order.
        size = len(sc.sub.packages)
        self.assertEquals(6, size)

        (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
        self.assertEquals(1, pos)
        self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)

        (pos, package) = get_package(sc, "Primary:Kerberos")
        self.assertEquals(2, pos)
        self.assertEquals("Primary:Kerberos", package.name)

        (pos, wp_package) = get_package(sc, "Primary:WDigest")
        self.assertEquals(3, pos)
        self.assertEquals("Primary:WDigest", wp_package.name)

        (pos, up_package) = get_package(sc, "Primary:userPassword")
        self.assertEquals(4, pos)
        self.assertEquals("Primary:userPassword", up_package.name)

        (pos, package) = get_package(sc, "Packages")
        self.assertEquals(5, pos)
        self.assertEquals("Packages", package.name)

        (pos, package) = get_package(sc, "Primary:SambaGPG")
        self.assertEquals(6, pos)
        self.assertEquals("Primary:SambaGPG", package.name)

        # Check that the WDigest values are correct.
        #
        digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
                             binascii.a2b_hex(wp_package.data))
        self.check_wdigests(digests)

        # Check that the userPassword hashes are computed correctly
        # Expect three hashes to be calculated
        up = ndr_unpack(drsblobs.package_PrimaryUserPasswordBlob,
                        binascii.a2b_hex(up_package.data))
        self.checkUserPassword(up, [
            ("{CRYPT}", "6", 5120),
            ("{CRYPT}", "5", 2560),
            ("{CRYPT}", "6", 5122)
        ])
        self.checkNtHash(USER_PASS, up.current_nt_hash.hash)
Exemple #9
0
    def test_cname(self):
        s1 = self.start_toy_server(dns_servers[0], 53, 'forwarder1')

        ad = contact_real_server(server_ip, 53)
        name = "resolve.cname"
        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []

        q = self.make_name_question(name, dns.DNS_QTYPE_CNAME,
                                    dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_OK)
            self.assertEqual(len(data.answers), 1)
            self.assertEqual('forwarder1', data.answers[0].rdata)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #10
0
    def test_modify_nonreplicated_reps_attributes(self):
        # some timestamp ones
        dn = self.base_dn

        m = ldb.Message()
        m.dn = ldb.Dn(self.samdb, dn)
        attr = 'repsFrom'

        res = self.samdb.search(dn, scope=ldb.SCOPE_BASE,
                                attrs=['repsFrom'])
        rep = ndr_unpack(drsblobs.repsFromToBlob, res[0]['repsFrom'][0],
                         allow_remaining=True)
        rep.ctr.result_last_attempt = -1
        value = ndr_pack(rep)

        m[attr] = ldb.MessageElement(value,
                                     ldb.FLAG_MOD_REPLACE,
                                     attr)
        try:
            self.samdb.modify(m)
            self.fail("Failed to fail to modify %s %s" % (dn, attr))
        except ldb.LdbError as e3:
            (ecode, emsg) = e3.args
            if ecode != ldb.ERR_REFERRAL:
                self.fail("Failed to REFER when trying to modify %s %s" %
                          (dn, attr))
            else:
                m = re.search(r'(ldap://[^>]+)>', emsg)
                if m is None:
                    self.fail("referral seems not to refer to anything")
                address = m.group(1)

                if address.lower().startswith(self.samdb.domain_dns_name()):
                    self.fail("referral address did not give a specific DC")
Exemple #11
0
    def test_array_from_ndr(self):
        rmd = drsblobs.replPropertyMetaDataBlob()

        rmd.version = 1
        rmd.ctr = drsblobs.replPropertyMetaDataCtr1()
        rmd.ctr.count = 3

        rmd1 = drsblobs.replPropertyMetaData1()
        rmd1.attid = 1
        rmd1.version = 2

        rmd2 = drsblobs.replPropertyMetaData1()
        rmd2.attid = 2
        rmd2.version = 2

        rmd3 = drsblobs.replPropertyMetaData1()
        rmd3.attid = 3
        rmd3.version = 2

        rmd.ctr.array = [rmd1, rmd2, rmd3]

        packed = ndr_pack(rmd)
        gc.collect()

        rmd_unpacked = ndr_unpack(drsblobs.replPropertyMetaDataBlob, packed)
        self.assertIsNotNone(rmd_unpacked)
        self.assertEqual(rmd_unpacked.version, 1)
        self.assertIsNotNone(rmd_unpacked.ctr)
        self.assertEqual(rmd_unpacked.ctr.count, 3)
        self.assertEqual(len(rmd_unpacked.ctr.array), rmd_unpacked.ctr.count)
        self.assertIsNotNone(rmd_unpacked.ctr.array[0])
        self.assertEqual(rmd_unpacked.ctr.array[0].attid, 1)

        self.assertEqual(rmd.ctr.array[0].attid,
                         rmd_unpacked.ctr.array[0].attid)
    def _check_metadata(self, metadata, expected):
        repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(metadata[0]))

        repl_array = []
        for o in repl.ctr.array:
            repl_array.append((o.attid, o.version))
        repl_set = set(repl_array)

        expected_set = set(expected)
        self.assertEqual(len(repl_set), len(expected),
                         "Unexpected metadata, missing from expected (%s), extra (%s)), repl: \n%s" % (
                         str(expected_set.difference(repl_set)),
                         str(repl_set.difference(expected_set)),
                         ndr_print(repl)))

        i = 0
        for o in repl.ctr.array:
            e = expected[i]
            (attid, version) = e
            self.assertEquals(attid, o.attid,
                              "(LDAP) Wrong attid "
                              "for expected value %d, wanted 0x%08x got 0x%08x, "
                              "repl: \n%s"
                              % (i, attid, o.attid, ndr_print(repl)))
            # Allow version to be skipped when it does not matter
            if version is not None:
                self.assertEquals(o.version, version,
                                  "(LDAP) Wrong version for expected value %d, "
                                  "attid 0x%08x, "
                                  "wanted %d got %d, repl: \n%s"
                                  % (i, o.attid,
                                     version, o.version, ndr_print(repl)))
            i = i + 1
Exemple #13
0
    def dns_transaction_tcp(self, packet, host,
                            dump=False, timeout=None):
        "send a DNS query and read the reply, also return the raw packet"
        s = None
        if timeout is None:
            timeout = self.timeout
        try:
            send_packet = ndr.ndr_pack(packet)
            if dump:
                print(self.hexdump(send_packet))
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
            s.settimeout(timeout)
            s.connect((host, 53))
            tcp_packet = struct.pack('!H', len(send_packet))
            tcp_packet += send_packet
            s.sendall(tcp_packet)

            recv_packet = s.recv(0xffff + 2, 0)
            if dump:
                print(self.hexdump(recv_packet))
            response = ndr.ndr_unpack(dns.name_packet, recv_packet[2:])

        finally:
            if s is not None:
                s.close()

        # unpacking and packing again should produce same bytestream
        my_packet = ndr.ndr_pack(response)
        self.assertEquals(my_packet, recv_packet[2:])

        return (response, recv_packet[2:])
Exemple #14
0
    def test_cname_forwarding_with_server_down(self):
        if len(dns_servers) < 2:
            print "Ignoring test_cname_forwarding_with_server_down"
            return
        s2 = self.start_toy_server(dns_servers[1], 53, 'forwarder2')

        name1 = 'resolve1.cname.%s' % self.get_dns_domain()
        name2 = 'resolve2.cname.%s' % self.get_dns_domain()
        self.make_cname_update(name1, name2)
        self.make_cname_update(name2, "dsfsfds.dsfsdfs")

        ad = contact_real_server(server_ip, 53)

        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []
        q = self.make_name_question(name1, dns.DNS_QTYPE_A,
                                    dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_OK)
            self.assertEqual('forwarder2', data.answers[-1].rdata)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #15
0
    def test_double_forwarder_both_slow(self):
        if len(dns_servers) < 2:
            print "Ignoring test_double_forwarder_both_slow"
            return
        s1 = self.start_toy_server(dns_servers[0], 53, 'forwarder1')
        s2 = self.start_toy_server(dns_servers[1], 53, 'forwarder2')
        s1.send('timeout 1.5', 0)
        s2.send('timeout 1.5', 0)
        ad = contact_real_server(server_ip, 53)
        name = "dsfsfds.dsfsdfs"
        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []

        q = self.make_name_question(name, dns.DNS_QTYPE_CNAME,
                                    dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_OK)
            self.assertEqual('forwarder1', data.answers[0].rdata)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #16
0
    def test_no_flag_recursive_forwarder(self):
        ad = contact_real_server(server_ip, 53)

        name = "dsfsfds.dsfsdfs"
        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []

        q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        send_packet = ndr.ndr_pack(p)

        self.finish_name_packet(p, questions)
        # Leave off the recursive flag
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_NXDOMAIN)
            self.assertEqual(data.ancount, 0)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #17
0
    def test_no_active_forwarder(self):
        ad = contact_real_server(server_ip, 53)

        name = "dsfsfds.dsfsdfs"
        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []

        q = self.make_name_question(name, dns.DNS_QTYPE_TXT, dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        send_packet = ndr.ndr_pack(p)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_SERVFAIL)
            self.assertEqual(data.ancount, 0)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
    def setUp(self):
        super(UserAccountControlTests, self).setUp()
        self.admin_creds = creds
        self.admin_samdb = SamDB(url=ldaphost,
                                 session_info=system_session(),
                                 credentials=self.admin_creds, lp=lp)
        self.domain_sid = security.dom_sid(self.admin_samdb.get_domain_sid())
        self.base_dn = self.admin_samdb.domain_dn()

        self.unpriv_user = "******"
        self.unpriv_user_pw = "samba123@"
        self.unpriv_creds = self.get_creds(self.unpriv_user, self.unpriv_user_pw)

        delete_force(self.admin_samdb, "CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn))
        delete_force(self.admin_samdb, "OU=test_computer_ou1,%s" % (self.base_dn))
        delete_force(self.admin_samdb, "CN=%s,CN=Users,%s" % (self.unpriv_user, self.base_dn))

        self.admin_samdb.newuser(self.unpriv_user, self.unpriv_user_pw)
        res = self.admin_samdb.search("CN=%s,CN=Users,%s" % (self.unpriv_user, self.admin_samdb.domain_dn()),
                                      scope=SCOPE_BASE,
                                      attrs=["objectSid"])
        self.assertEqual(1, len(res))

        self.unpriv_user_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
        self.unpriv_user_dn = res[0].dn

        self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp)

        self.samr = samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, self.unpriv_creds)
        self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
        self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)

        self.sd_utils = sd_utils.SDUtils(self.admin_samdb)

        self.admin_samdb.create_ou("OU=test_computer_ou1," + self.base_dn)
        self.unpriv_user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn)
        mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid)

        old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn)

        self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod)

        self.add_computer_ldap("testcomputer-t")

        self.sd_utils.modify_sd_on_dn("OU=test_computer_ou1," + self.base_dn, old_sd)

        self.computernames = ["testcomputer-0"]

        # Get the SD of the template account, then force it to match
        # what we expect for SeMachineAccountPrivilege accounts, so we
        # can confirm we created the accounts correctly
        self.sd_reference_cc = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn))

        self.sd_reference_modify = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn))
        for ace in self.sd_reference_modify.dacl.aces:
            if ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED and ace.trustee == self.unpriv_user_sid:
                ace.access_mask = ace.access_mask | security.SEC_ADS_SELF_WRITE | security.SEC_ADS_WRITE_PROP

        # Now reconnect without domain admin rights
        self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp)
Exemple #19
0
 def read_descriptor(self, samdb, object_dn):
     res = samdb.search(base=object_dn, scope=SCOPE_BASE,
             attrs=["nTSecurityDescriptor"])
     # we should theoretically always have an SD
     assert(len(res) == 1)
     desc = res[0]["nTSecurityDescriptor"][0]
     return ndr_unpack(security.descriptor, desc)
Exemple #20
0
def findprovisionrange(samdb, basedn):
    """ Find ranges of usn grouped by invocation id and then by timestamp
        rouned at 1 minute

        :param samdb: An LDB object pointing to the samdb
        :param basedn: The DN of the forest

        :return: A two level dictionary with invoication id as the
                first level, timestamp as the second one and then
                max, min, and number as subkeys, representing respectivily
                the maximum usn for the range, the minimum usn and the number
                of object with usn in this range.
    """
    nb_obj = 0
    hash_id = {}

    res = samdb.search(
        base=basedn,
        expression="objectClass=*",
        scope=ldb.SCOPE_SUBTREE,
        attrs=["replPropertyMetaData"],
        controls=["search_options:1:2"],
    )

    for e in res:
        nb_obj = nb_obj + 1
        obj = ndr_unpack(drsblobs.replPropertyMetaDataBlob, str(e["replPropertyMetaData"])).ctr

        for o in obj.array:
            # like a timestamp but with the resolution of 1 minute
            minutestamp = _glue.nttime2unix(o.originating_change_time) / 60
            hash_ts = hash_id.get(str(o.originating_invocation_id))

            if hash_ts is None:
                ob = {}
                ob["min"] = o.originating_usn
                ob["max"] = o.originating_usn
                ob["num"] = 1
                ob["list"] = [str(e.dn)]
                hash_ts = {}
            else:
                ob = hash_ts.get(minutestamp)
                if ob is None:
                    ob = {}
                    ob["min"] = o.originating_usn
                    ob["max"] = o.originating_usn
                    ob["num"] = 1
                    ob["list"] = [str(e.dn)]
                else:
                    if ob["min"] > o.originating_usn:
                        ob["min"] = o.originating_usn
                    if ob["max"] < o.originating_usn:
                        ob["max"] = o.originating_usn
                    if not (str(e.dn) in ob["list"]):
                        ob["num"] = ob["num"] + 1
                        ob["list"].append(str(e.dn))
            hash_ts[minutestamp] = ob
            hash_id[str(o.originating_invocation_id)] = hash_ts

    return (hash_id, nb_obj)
Exemple #21
0
    def test_default_supplementalCredentials(self):
        self.add_user()

        sc = self.get_supplemental_creds()

        # Check that we got all the expected supplemental credentials
        # And they are in the expected order.
        size = len(sc.sub.packages)
        self.assertEquals(3, size)

        (pos, package) = get_package(sc, "Primary:Kerberos")
        self.assertEquals(1, pos)
        self.assertEquals("Primary:Kerberos", package.name)

        (pos, package) = get_package(sc, "Packages")
        self.assertEquals(2, pos)
        self.assertEquals("Packages", package.name)

        (pos, package) = get_package(sc, "Primary:WDigest")
        self.assertEquals(3, pos)
        self.assertEquals("Primary:WDigest", package.name)

        # Check that the WDigest values are correct.
        #
        digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
                             binascii.a2b_hex(package.data))
        self.check_wdigests(digests)
Exemple #22
0
    def test_cleanup_multi_srv_record(self):
        """
        Test dns cleanup command for multi-valued SRV record.

        Steps:
        - Add 2 A records host1 and host2
        - Add a SRV record srv1 and points to both host1 and host2
        - Run cleanup command for host1
        - Check records for srv1, data for host1 should be gone and host2 is kept.
        """

        hosts = ['host1', 'host2']  # A record names
        srv_name = 'srv1'

        # add A records
        for host in hosts:
            self.runsubcmd("dns", "add", os.environ["SERVER"], self.zone,
                           host, "A", self.testip, self.creds_string)

            # the above A record points to this host
            dnshostname = '{}.{}'.format(host, self.zone.lower())

            # add a SRV record points to above host
            srv_record = "{} 65530 65530 65530".format(dnshostname)
            self.runsubcmd("dns", "add", os.environ["SERVER"], self.zone,
                           srv_name, "SRV", srv_record, self.creds_string)

        records = self.samdb.search(
            base="DC=DomainDnsZones,{}".format(self.samdb.get_default_basedn()),
            scope=ldb.SCOPE_SUBTREE,
            expression="(&(objectClass=dnsNode)(name={}))".format(srv_name),
            attrs=['dnsRecord'])
        # should have 2 records here
        self.assertEqual(len(records[0]['dnsRecord']), 2)

        # cleanup record for dns host1
        dnshostname1 = 'host1.{}'.format(self.zone.lower())
        self.runsubcmd("dns", "cleanup", os.environ["SERVER"],
                       dnshostname1, self.creds_string)

        records = self.samdb.search(
            base="DC=DomainDnsZones,{}".format(self.samdb.get_default_basedn()),
            scope=ldb.SCOPE_SUBTREE,
            expression="(&(objectClass=dnsNode)(name={}))".format(srv_name),
            attrs=['dnsRecord', 'dNSTombstoned'])

        # dnsRecord for host1 should be deleted
        self.assertEqual(len(records[0]['dnsRecord']), 1)

        # unpack data
        dns_record_bin = records[0]['dnsRecord'][0]
        dns_record_obj = ndr_unpack(dnsp.DnssrvRpcRecord, dns_record_bin)

        # dnsRecord for host2 is still there and is the only one
        dnshostname2 = 'host2.{}'.format(self.zone.lower())
        self.assertEqual(dns_record_obj.data.nameTarget, dnshostname2)

        # assert that the record isn't spuriously tombstoned
        self.assertTrue('dNSTombstoned' not in records[0] or
                        str(record['dNSTombstoned']) == 'FALSE')
Exemple #23
0
    def run(self, gpo, H=None, sambaopts=None, credopts=None, versionopts=None):

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)

        self.url = dc_url(self.lp, self.creds, H)

        samdb_connect(self)

        try:
            msg = get_gpo_info(self.samdb, gpo)[0]
        except Exception:
            raise CommandError("GPO '%s' does not exist" % gpo)

        try:
            secdesc_ndr = msg['nTSecurityDescriptor'][0]
            secdesc = ndr_unpack(security.descriptor, secdesc_ndr)
            secdesc_sddl = secdesc.as_sddl()
        except Exception:
            secdesc_sddl = "<hidden>"

        self.outf.write("GPO          : %s\n" % msg['name'][0])
        self.outf.write("display name : %s\n" % msg['displayName'][0])
        self.outf.write("path         : %s\n" % msg['gPCFileSysPath'][0])
        self.outf.write("dn           : %s\n" % msg.dn)
        self.outf.write("version      : %s\n" % attr_default(msg, 'versionNumber', '0'))
        self.outf.write("flags        : %s\n" % gpo_flags_string(int(attr_default(msg, 'flags', 0))))
        self.outf.write("ACL          : %s\n" % secdesc_sddl)
        self.outf.write("\n")
Exemple #24
0
def getntacl(lp, file, backend=None, eadbfile=None, direct_db_access=True):
    if direct_db_access:
        (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile)
        if dbname is not None:
            try:
                attribute = backend_obj.wrap_getxattr(dbname, file,
                                                      xattr.XATTR_NTACL_NAME)
            except Exception:
                # FIXME: Don't catch all exceptions, just those related to opening
                # xattrdb
                print "Fail to open %s" % dbname
                attribute = samba.xattr_native.wrap_getxattr(file,
                                                             xattr.XATTR_NTACL_NAME)
        else:
            attribute = samba.xattr_native.wrap_getxattr(file,
                                                         xattr.XATTR_NTACL_NAME)
        ntacl = ndr_unpack(xattr.NTACL, attribute)
        if ntacl.version == 1:
            return ntacl.info
        elif ntacl.version == 2:
            return ntacl.info.sd
        elif ntacl.version == 3:
            return ntacl.info.sd
        elif ntacl.version == 4:
            return ntacl.info.sd
    else:
        return smbd.get_nt_acl(file, security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_SACL)
Exemple #25
0
    def _samdb_fetch_pfm_and_schi(self):
        """Fetch prefixMap and schemaInfo stored in SamDB using LDB connection"""
        samdb = self.ldb_dc1
        res = samdb.search(base=samdb.get_schema_basedn(), scope=SCOPE_BASE,
                           attrs=["prefixMap", "schemaInfo"])

        pfm = ndr_unpack(drsblobs.prefixMapBlob,
                         str(res[0]['prefixMap']))

        schi = drsuapi.DsReplicaOIDMapping()
        schi.id_prefix = 0

        if 'schemaInfo' in res[0]:
            schi.oid.length = len(map(ord, str(res[0]['schemaInfo'])))
            schi.oid.binary_oid = map(ord, str(res[0]['schemaInfo']))
        else:
            schema_info = drsblobs.schemaInfoBlob()
            schema_info.revision = 0
            schema_info.marker = 0xFF
            schema_info.invocation_id = misc.GUID(samdb.get_invocation_id())
            schi.oid.length = len(map(ord, ndr_pack(schema_info)))
            schi.oid.binary_oid = map(ord, ndr_pack(schema_info))

        pfm.ctr.mappings = pfm.ctr.mappings + [schi]
        pfm.ctr.num_mappings += 1
        return pfm.ctr
    def _open_samr_user(self, res):
        self.assertTrue("objectSid" in res[0])

        (domain_sid, rid) = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]).split()
        self.assertEquals(self.domain_sid, domain_sid)

        return self.samr.OpenUser(self.samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, rid)
Exemple #27
0
    def get_attribute_replmetadata_version(self, dn, att):
        """Get the version field trom the replPropertyMetaData for
        the given field

        :param dn: The on which we want to get the version
        :param att: The name of the attribute
        :return: The value of the version field in the replPropertyMetaData
            for the given attribute. None if the attribute is not replicated
        """

        res = self.search(expression="distinguishedName=%s" % dn,
                            scope=ldb.SCOPE_SUBTREE,
                            controls=["search_options:1:2"],
                            attrs=["replPropertyMetaData"])
        if len(res) == 0:
            return None

        repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
                            str(res[0]["replPropertyMetaData"]))
        ctr = repl.ctr
        if len(self.hash_oid_name.keys()) == 0:
            self._populate_oid_attid()
        for o in ctr.array:
            # Search for Description
            att_oid = self.get_oid_from_attid(o.attid)
            if self.hash_oid_name.has_key(att_oid) and\
               att.lower() == self.hash_oid_name[att_oid].lower():
                return o.version
        return None
Exemple #28
0
 def decode(self):
     keys = []
     krb = ndr_unpack(drsblobs.package_PrimaryKerberosBlob, self._raw)
     assert krb.version == 4
     for key in krb.ctr.keys:
         keys.append({'type': key.keytype, 'value': key.value, 'salt': krb.ctr.salt.string})
     self.keys = keys
Exemple #29
0
    def check_rootdse(self):
        '''check the @ROOTDSE special object'''
        dn = ldb.Dn(self.samdb, '@ROOTDSE')
        if self.verbose:
            self.report("Checking object %s" % dn)
        res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE)
        if len(res) != 1:
            self.report("Object %s disappeared during check" % dn)
            return 1
        obj = res[0]
        error_count = 0

        # check that the dsServiceName is in GUID form
        if not 'dsServiceName' in obj:
            self.report('ERROR: dsServiceName missing in @ROOTDSE')
            return error_count+1

        if not obj['dsServiceName'][0].startswith('<GUID='):
            self.report('ERROR: dsServiceName not in GUID form in @ROOTDSE')
            error_count += 1
            if not self.confirm('Change dsServiceName to GUID form?'):
                return error_count
            res = self.samdb.search(base=ldb.Dn(self.samdb, obj['dsServiceName'][0]),
                                    scope=ldb.SCOPE_BASE, attrs=['objectGUID'])
            guid_str = str(ndr_unpack(misc.GUID, res[0]['objectGUID'][0]))
            m = ldb.Message()
            m.dn = dn
            m['dsServiceName'] = ldb.MessageElement("<GUID=%s>" % guid_str,
                                                    ldb.FLAG_MOD_REPLACE, 'dsServiceName')
            if self.do_modify(m, [], "Failed to change dsServiceName to GUID form", validate=False):
                self.report("Changed dsServiceName to GUID form")
        return error_count
    def test_supplementalCredentials_cleartext(self):
        self.add_user(clear_text=True)
        if not self.lp.get("password hash gpg key ids"):
            self.skipTest("No password hash gpg key ids, " +
                          "Primary:SambaGPG will not be generated");

        sc = self.get_supplemental_creds()

        # Check that we got all the expected supplemental credentials
        # And they are in the expected order.
        size = len(sc.sub.packages)
        self.assertEquals(6, size)
        (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
        self.assertEquals(1, pos)
        self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)

        (pos, package) = get_package(sc, "Primary:Kerberos")
        self.assertEquals(2, pos)
        self.assertEquals("Primary:Kerberos", package.name)

        (pos, wd_package) = get_package(sc, "Primary:WDigest")
        self.assertEquals(3, pos)
        self.assertEquals("Primary:WDigest", wd_package.name)

        (pos, ct_package) = get_package(sc, "Primary:CLEARTEXT")
        self.assertEquals(4, pos)
        self.assertEquals("Primary:CLEARTEXT", ct_package.name)

        (pos, package) = get_package(sc, "Packages")
        self.assertEquals(5, pos)
        self.assertEquals("Packages", package.name)

        (pos, package) = get_package(sc, "Primary:SambaGPG")
        self.assertEquals(6, pos)
        self.assertEquals("Primary:SambaGPG", package.name)

        # Check that the WDigest values are correct.
        #
        digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
                             binascii.a2b_hex(wd_package.data))
        self.check_wdigests(digests)

        # Check the clear text  value is correct.
        ct = ndr_unpack(drsblobs.package_PrimaryCLEARTEXTBlob,
                        binascii.a2b_hex(ct_package.data))
        self.assertEquals(USER_PASS.encode('utf-16-le'), ct.cleartext)
    def test_encrypted_secrets(self):
        """Test that secret attributes are stored encrypted on disk"""
        basedn = self.ldb.domain_dn()
        backend_filename = "%s.ldb" % basedn.upper()
        backend_subpath = os.path.join("sam.ldb.d", backend_filename)
        backend_path = self.lp.private_path(backend_subpath)
        backenddb = ldb.Ldb("ldb://" + backend_path,
                            flags=ldb.FLG_DONT_CREATE_DB)

        dn = "CN=Administrator,CN=Users,%s" % basedn

        res = backenddb.search(scope=ldb.SCOPE_BASE,
                               base=dn,
                               attrs=["unicodePwd"])
        self.assertIs(True, len(res) > 0)
        obj = res[0]
        blob = obj["unicodePwd"][0]
        self.assertTrue(len(blob) > 30)
        # Now verify that the header contains the correct magic value.
        encrypted = ndr_unpack(drsblobs.EncryptedSecret, blob)
        magic = 0xca5caded
        self.assertEqual(magic, encrypted.header.magic)
Exemple #32
0
    def get_record_from_db(self, zone_name, record_name):
        zones = self.samdb.search(base="DC=DomainDnsZones,%s" %
                                  self.samdb.get_default_basedn(),
                                  scope=ldb.SCOPE_SUBTREE,
                                  expression="(objectClass=dnsZone)",
                                  attrs=["cn"])

        for zone in zones:
            if zone_name in str(zone.dn):
                zone_dn = zone.dn
                break

        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]))
Exemple #33
0
    def operation_129(self, op):
        if self.update_exists(op):
            return
        self.raise_if_not_fix(op)

        ace = "(OA;CIOI;RPWP;3f78c3e5-f79a-46bd-a0b8-9d18116ddc79;;PS)"

        schema_dn = ldb.Dn(self.samdb, "CN=Sam-Domain,%s" % str(self.schema_dn))
        self.insert_ace_into_string(schema_dn, ace,
                                    attr='defaultSecurityDescriptor')

        res = self.samdb.search(expression="(objectClass=samDomain)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])
        for msg in res:
            existing_sd = ndr_unpack(security.descriptor, msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        if self.add_update_container:
            self.update_add(op)
Exemple #34
0
    def test_tokenGroupsGlobalAndUniversal_manual(self):
        # Manually run the tokenGroups algorithm from MS-ADTS 3.1.1.4.5.19 and MS-DRSR 4.1.8.3
        # and compare the result

        # The variable names come from MS-ADTS May 15, 2014

        S = set()
        S.add(self.test_user_dn.get_casefold())

        self.filtered_closure(S, GTYPE_SECURITY_GLOBAL_GROUP)

        T = set()
        # Not really a SID, we do this on DNs...
        for sid in S:
            X = set()
            X.add(sid)
            self.filtered_closure(X, GTYPE_SECURITY_UNIVERSAL_GROUP)

            T = T.union(X)

        T.remove(self.test_user_dn.get_casefold())

        tokenGroupsSet = set()

        res = self.ldb.search(self.user_sid_dn, scope=ldb.SCOPE_BASE, attrs=["tokenGroupsGlobalAndUniversal"])
        self.assertEquals(len(res), 1)

        dn_tokengroups = []
        for sid in res[0]['tokenGroupsGlobalAndUniversal']:
            sid = ndr_unpack(samba.dcerpc.security.dom_sid, sid)
            res3 = self.admin_ldb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE,
                                         attrs=[])
            tokenGroupsSet.add(res3[0].dn.get_casefold())

        if len(T.difference(tokenGroupsSet)):
            self.fail(msg="additional calculated: %s" % T.difference(tokenGroupsSet))

        if len(tokenGroupsSet.difference(T)):
            self.fail(msg="additional tokenGroupsGlobalAndUniversal: %s" % tokenGroupsSet.difference(T))
Exemple #35
0
def decrypt_supplementalCredentials(connector, spl_crypt):
    assert len(spl_crypt) >= 20

    confounder = spl_crypt[0:16]
    enc_buffer = spl_crypt[16:]

    m5 = hashlib.md5()
    m5.update(connector.drs.user_session_key)
    m5.update(confounder)
    enc_key = m5.digest()

    rc4 = Crypto.Cipher.ARC4.new(enc_key)
    plain_buffer = rc4.decrypt(enc_buffer)

    (crc32_v) = struct.unpack("<L", plain_buffer[0:4])
    attr_val = plain_buffer[4:]
    crc32_c = binascii.crc32(attr_val) & 0xffffffff
    assert int(
        crc32_v[0]) == int(crc32_c), "CRC32 0x%08X != 0x%08X" % (crc32_v[0],
                                                                 crc32_c)

    return ndr_unpack(drsblobs.supplementalCredentialsBlob, attr_val)
 def _expected_user_del_attributes(self, username, _guid, _sid):
     guid = ndr_unpack(misc.GUID, _guid)
     dn = "CN=%s\\0ADEL:%s,CN=Deleted Objects,%s" % (username, guid, self.base_dn)
     cn = "%s\nDEL:%s" % (username, guid)
     return {'dn': dn,
             'objectClass': '**',
             'cn': cn,
             'distinguishedName': dn,
             'isDeleted': 'TRUE',
             'isRecycled': 'TRUE',
             'instanceType': '4',
             'whenCreated': '**',
             'whenChanged': '**',
             'uSNCreated': '**',
             'uSNChanged': '**',
             'name': cn,
             'objectGUID': _guid,
             'userAccountControl': '546',
             'objectSid': _sid,
             'sAMAccountName': username,
             'lastKnownParent': 'CN=Users,%s' % self.base_dn,
             }
Exemple #37
0
 def dns_transaction_tcp(self,
                         packet,
                         host=os.getenv('SERVER_IP'),
                         dump=False):
     "send a DNS query and read the reply"
     s = None
     try:
         send_packet = ndr.ndr_pack(packet)
         if dump:
             print self.hexdump(send_packet)
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
         s.connect((host, 53))
         tcp_packet = struct.pack('!H', len(send_packet))
         tcp_packet += send_packet
         s.send(tcp_packet, 0)
         recv_packet = s.recv(0xffff + 2, 0)
         if dump:
             print self.hexdump(recv_packet)
         return ndr.ndr_unpack(dns.name_packet, recv_packet[2:])
     finally:
         if s is not None:
             s.close()
Exemple #38
0
    def test_single_forwarder_not_actually_there(self):
        ad = contact_real_server(server_ip, 53)
        name = "dsfsfds.dsfsdfs"
        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []

        q = self.make_name_question(name, dns.DNS_QTYPE_CNAME,
                                    dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_SERVFAIL)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #39
0
 def dns_transaction_udp(self,
                         packet,
                         host=server_ip,
                         dump=False,
                         timeout=timeout):
     "send a DNS query and read the reply"
     s = None
     try:
         send_packet = ndr.ndr_pack(packet)
         if dump:
             print(self.hexdump(send_packet))
         s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
         s.settimeout(timeout)
         s.connect((host, 53))
         s.send(send_packet, 0)
         recv_packet = s.recv(2048, 0)
         if dump:
             print(self.hexdump(recv_packet))
         return ndr.ndr_unpack(dns.name_packet, recv_packet)
     finally:
         if s is not None:
             s.close()
Exemple #40
0
    def test_dn_tokenGroups(self):
        print("Getting tokenGroups from user DN")
        res = self.ldb.search(self.user_sid_dn,
                              scope=ldb.SCOPE_BASE,
                              attrs=["tokenGroups"])
        self.assertEquals(len(res), 1)

        dn_tokengroups = []
        for sid in res[0]['tokenGroups']:
            dn_tokengroups.append(
                str(ndr_unpack(samba.dcerpc.security.dom_sid, sid)))

        sidset1 = set(dn_tokengroups)
        sidset2 = set(self.user_sids)
        if len(sidset1.difference(sidset2)):
            print("token sids don't match")
            print("tokengroups: %s" % tokengroups)
            print("calculated : %s" % sids)
            print("difference : %s" % sidset1.difference(sidset2))
            self.fail(
                msg="calculated groups don't match against user DN tokenGroups"
            )
Exemple #41
0
    def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None):
        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp, fallback_machine=True)

        try:
            samdb = SamDB(url=H, session_info=system_session(),
                          credentials=creds, lp=lp)

            search_filter = "(&(objectClass=group)(samaccountname=%s))" % groupname
            res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
                               expression=(search_filter),
                               attrs=["objectSid"])

            if (len(res) != 1):
                return

            group_dn = res[0].get('dn', idx=0)
            object_sid = res[0].get('objectSid', idx=0)

            object_sid = ndr_unpack(security.dom_sid, object_sid)
            (group_dom_sid, rid) = object_sid.split()

            search_filter = "(|(primaryGroupID=%s)(memberOf=%s))" % (rid, group_dn)
            res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
                               expression=(search_filter),
                               attrs=["samAccountName", "cn"])

            if (len(res) == 0):
                return

            for msg in res:
                member_name = msg.get("samAccountName", idx=0)
                if member_name is None:
                    member_name = msg.get("cn", idx=0)
                self.outf.write("%s\n" % member_name)

        except Exception as e:
            raise CommandError('Failed to list members of "%s" group ' % groupname, e)
Exemple #42
0
    def _test_pac_align_with_args(self, length):
        samdb = self.get_samdb()

        account_name = self.base_name + 'a' * (length - len(self.base_name))
        creds, _ = self.create_account(samdb, account_name)

        tgt = self.get_tgt(creds, expect_pac=True)

        pac_data = self.get_ticket_pac(tgt)
        self.assertIsNotNone(pac_data)

        self.assertEqual(0, len(pac_data) & 7)

        pac = ndr_unpack(krb5pac.PAC_DATA_RAW, pac_data)
        for pac_buffer in pac.buffers:
            buffer_type = pac_buffer.type
            buffer_size = pac_buffer.ndr_size

            with self.subTest(buffer_type=buffer_type):
                if buffer_type == krb5pac.PAC_TYPE_LOGON_NAME:
                    self.assertEqual(length * 2 + 10, buffer_size)
                elif buffer_type == krb5pac.PAC_TYPE_REQUESTER_SID:
                    self.assertEqual(28, buffer_size)
                elif buffer_type in {
                        krb5pac.PAC_TYPE_SRV_CHECKSUM,
                        krb5pac.PAC_TYPE_KDC_CHECKSUM,
                        krb5pac.PAC_TYPE_TICKET_CHECKSUM
                }:
                    self.assertEqual(
                        0, buffer_size & 3, f'buffer type was: {buffer_type}, '
                        f'buffer size was: {buffer_size}')
                else:
                    self.assertEqual(
                        0, buffer_size & 7, f'buffer type was: {buffer_type}, '
                        f'buffer size was: {buffer_size}')

                rounded_len = (buffer_size + 7) & ~7
                self.assertEqual(rounded_len, len(pac_buffer.info.remaining))
Exemple #43
0
    def setUp(self):
        super(StaticTokenTest, self).setUp()
        self.ldb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp)
        self.base_dn = self.ldb.domain_dn()

        res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"])
        self.assertEquals(len(res), 1)

        self.user_sid_dn = "<SID=%s>" % str(ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["tokenGroups"][0]))

        session_info_flags = (AUTH_SESSION_INFO_DEFAULT_GROUPS |
                              AUTH_SESSION_INFO_AUTHENTICATED |
                              AUTH_SESSION_INFO_SIMPLE_PRIVILEGES)
        if creds.get_kerberos_state() == DONT_USE_KERBEROS:
            session_info_flags |= AUTH_SESSION_INFO_NTLM

        session = samba.auth.user_session(self.ldb, lp_ctx=lp, dn=self.user_sid_dn,
                                          session_info_flags=session_info_flags)

        token = session.security_token
        self.user_sids = []
        for s in token.sids:
            self.user_sids.append(str(s))
Exemple #44
0
    def operation_88(self, op):
        if self.update_exists(op):
            return
        self.raise_if_not_fix(op)

        ace = "(OA;CIIO;WP;ea1b7b93-5e48-46d5-bc6c-4df4fda78a35;bf967a86-0de6-11d0-a285-00aa003049e2;PS)"

        schema_dn = ldb.Dn(self.samdb, "CN=Sam-Domain,%s" % str(self.schema_dn))

        self.insert_ace_into_string(schema_dn, ace,
                                    attr="defaultSecurityDescriptor")

        res = self.samdb.search(expression="(objectClass=samDomain)",
                                attrs=["nTSecurityDescriptor"],
                                controls=["search_options:1:2"])
        for msg in res:
            existing_sd = ndr_unpack(security.descriptor, msg["nTSecurityDescriptor"][0])
            existing_sddl = existing_sd.as_sddl(self.domain_sid)

            self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        if self.add_update_container:
            self.update_add(op)
Exemple #45
0
 def test_twoatt_replpropertymetadata(self):
     res = self.samdb.search(expression="cn=Administrator",
                             scope=ldb.SCOPE_SUBTREE,
                             attrs=["replPropertyMetaData", "uSNChanged"])
     repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
                       str(res[0]["replPropertyMetaData"]))
     ctr = repl.ctr
     for o in ctr.array:
         # Search for Description
         if o.attid == 13:
             old_version = o.version
             o.version = o.version + 1
             o.local_usn = long(str(res[0]["uSNChanged"])) + 1
     replBlob = ndr_pack(repl)
     msg = ldb.Message()
     msg.dn = res[0].dn
     msg["replPropertyMetaData"] = ldb.MessageElement(
         replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
     msg["description"] = ldb.MessageElement("new val",
                                             ldb.FLAG_MOD_REPLACE,
                                             "description")
     self.assertRaises(ldb.LdbError, self.samdb.modify, msg,
                       ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
Exemple #46
0
    def test_default_supplementalCredentials(self):
        self.add_user()
        if not self.lp.get("password hash gpg key ids"):
            self.skipTest("No password hash gpg key ids, " +
                          "Primary:SambaGPG will not be generated")

        sc = self.get_supplemental_creds()

        # Check that we got all the expected supplemental credentials
        # And they are in the expected order.
        size = len(sc.sub.packages)
        self.assertEquals(5, size)
        (pos, package) = get_package(sc, "Primary:Kerberos-Newer-Keys")
        self.assertEquals(1, pos)
        self.assertEquals("Primary:Kerberos-Newer-Keys", package.name)

        (pos, package) = get_package(sc, "Primary:Kerberos")
        self.assertEquals(2, pos)
        self.assertEquals("Primary:Kerberos", package.name)

        (pos, wd_package) = get_package(sc, "Primary:WDigest")
        self.assertEquals(3, pos)
        self.assertEquals("Primary:WDigest", wd_package.name)

        (pos, package) = get_package(sc, "Packages")
        self.assertEquals(4, pos)
        self.assertEquals("Packages", package.name)

        (pos, package) = get_package(sc, "Primary:SambaGPG")
        self.assertEquals(5, pos)
        self.assertEquals("Primary:SambaGPG", package.name)

        # Check that the WDigest values are correct.
        #
        digests = ndr_unpack(drsblobs.package_PrimaryWDigestBlob,
                             binascii.a2b_hex(wd_package.data))
        self.check_wdigests(digests)
Exemple #47
0
    def check_rootdse(self):
        '''check the @ROOTDSE special object'''
        dn = ldb.Dn(self.samdb, '@ROOTDSE')
        if self.verbose:
            self.report("Checking object %s" % dn)
        res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE)
        if len(res) != 1:
            self.report("Object %s disappeared during check" % dn)
            return 1
        obj = res[0]
        error_count = 0

        # check that the dsServiceName is in GUID form
        if not 'dsServiceName' in obj:
            self.report('ERROR: dsServiceName missing in @ROOTDSE')
            return error_count + 1

        if not obj['dsServiceName'][0].startswith('<GUID='):
            self.report('ERROR: dsServiceName not in GUID form in @ROOTDSE')
            error_count += 1
            if not self.confirm('Change dsServiceName to GUID form?'):
                return error_count
            res = self.samdb.search(base=ldb.Dn(self.samdb,
                                                obj['dsServiceName'][0]),
                                    scope=ldb.SCOPE_BASE,
                                    attrs=['objectGUID'])
            guid_str = str(ndr_unpack(misc.GUID, res[0]['objectGUID'][0]))
            m = ldb.Message()
            m.dn = dn
            m['dsServiceName'] = ldb.MessageElement("<GUID=%s>" % guid_str,
                                                    ldb.FLAG_MOD_REPLACE,
                                                    'dsServiceName')
            if self.do_modify(m, [],
                              "Failed to change dsServiceName to GUID form",
                              validate=False):
                self.report("Changed dsServiceName to GUID form")
        return error_count
Exemple #48
0
    def test_cname_forwarding_with_lots_of_cnames(self):
        name3 = 'resolve3.cname.%s' % self.get_dns_domain()
        s1 = self.start_toy_server(dns_servers[0], 53, name3)

        name1 = 'resolve1.cname.%s' % self.get_dns_domain()
        name2 = 'resolve2.cname.%s' % self.get_dns_domain()
        self.make_cname_update(name1, name2)
        self.make_cname_update(name3, name1)
        self.make_cname_update(name2, "dsfsfds.dsfsdfs")

        ad = contact_real_server(server_ip, 53)

        p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
        questions = []
        q = self.make_name_question(name1, dns.DNS_QTYPE_A,
                                    dns.DNS_QCLASS_IN)
        questions.append(q)

        self.finish_name_packet(p, questions)
        p.operation |= dns.DNS_FLAG_RECURSION_DESIRED
        send_packet = ndr.ndr_pack(p)

        ad.send(send_packet, 0)
        ad.settimeout(timeout)
        try:
            data = ad.recv(0xffff + 2, 0)
            data = ndr.ndr_unpack(dns.name_packet, data)
            # This should cause a loop in Windows
            # (which is restricted by a 20 CNAME limit)
            #
            # The reason it doesn't here is because forwarded CNAME have no
            # additional processing in the internal DNS server.
            self.assert_dns_rcode_equals(data, dns.DNS_RCODE_OK)
            self.assertEqual(name3, data.answers[-1].rdata)
        except socket.timeout:
            self.fail("DNS server is too slow (timeout %s)" % timeout)
Exemple #49
0
    def operation_80(self, op):
        if self.update_exists(op):
            return
        self.raise_if_not_fix(op)

        ace = "(OA;;CR;3e0f7e18-2c7a-4c10-ba82-4d926db99a3e;;%s-522)" % str(
            self.domain_sid)

        res = self.samdb.search(
            base=self.domain_dn,
            scope=ldb.SCOPE_BASE,
            attrs=["nTSecurityDescriptor"],
            controls=["search_options:1:2",
                      "sd_flags:1:%d" % SECINFO_DACL])
        msg = res[0]

        existing_sd = ndr_unpack(security.descriptor,
                                 msg["nTSecurityDescriptor"][0])
        existing_sddl = existing_sd.as_sddl(self.domain_sid)

        self.insert_ace_into_dacl(msg.dn, existing_sddl, ace)

        if self.add_update_container:
            self.update_add(op)
Exemple #50
0
    def _find_dns_record(self, name, ip_address):
        name = name.rstrip('$')  # computername
        records = self.samdb.search(
            base="DC=DomainDnsZones,{0}".format(
                self.samdb.get_default_basedn()),
            scope=ldb.SCOPE_SUBTREE,
            expression="(&(objectClass=dnsNode)(name={0}))".format(name),
            attrs=['dnsRecord', 'dNSTombstoned'])

        # unpack data and compare
        for record in records:
            if 'dNSTombstoned' in record and str(
                    record['dNSTombstoned']) == 'TRUE':
                # if a record is dNSTombstoned, ignore it.
                continue
            for dns_record_bin in record['dnsRecord']:
                dns_record_obj = ndr_unpack(dnsp.DnssrvRpcRecord,
                                            dns_record_bin)
                ip = str(dns_record_obj.data)

                if str(ip) == str(ip_address):
                    return True

        return False
Exemple #51
0
def getntacl(lp,
             file,
             backend=None,
             eadbfile=None,
             direct_db_access=True,
             service=None,
             session_info=None):
    if direct_db_access:
        (backend_obj, dbname) = checkset_backend(lp, backend, eadbfile)
        if dbname is not None:
            try:
                attribute = backend_obj.wrap_getxattr(dbname, file,
                                                      xattr.XATTR_NTACL_NAME)
            except Exception:
                # FIXME: Don't catch all exceptions, just those related to opening
                # xattrdb
                print("Fail to open %s" % dbname)
                attribute = samba.xattr_native.wrap_getxattr(
                    file, xattr.XATTR_NTACL_NAME)
        else:
            attribute = samba.xattr_native.wrap_getxattr(
                file, xattr.XATTR_NTACL_NAME)
        ntacl = ndr_unpack(xattr.NTACL, attribute)
        if ntacl.version == 1:
            return ntacl.info
        elif ntacl.version == 2:
            return ntacl.info.sd
        elif ntacl.version == 3:
            return ntacl.info.sd
        elif ntacl.version == 4:
            return ntacl.info.sd
    else:
        return smbd.get_nt_acl(file,
                               SECURITY_SECINFO_FLAGS,
                               service=service,
                               session_info=session_info)
Exemple #52
0
    def test_rootDSE_tokenGroups(self):
        """Testing rootDSE tokengroups against internal calculation"""
        if not url.startswith("ldap"):
            self.fail(msg="This test is only valid on ldap")

        res = self.ldb.search("", scope=ldb.SCOPE_BASE, attrs=["tokenGroups"])
        self.assertEquals(len(res), 1)

        print("Getting tokenGroups from rootDSE")
        tokengroups = []
        for sid in res[0]['tokenGroups']:
            tokengroups.append(
                str(ndr_unpack(samba.dcerpc.security.dom_sid, sid)))

        sidset1 = set(tokengroups)
        sidset2 = set(self.user_sids)
        if len(sidset1.difference(sidset2)):
            print("token sids don't match")
            print("tokengroups: %s" % tokengroups)
            print("calculated : %s" % self.user_sids)
            print("difference : %s" % sidset1.difference(sidset2))
            self.fail(
                msg="calculated groups don't match against rootDSE tokenGroups"
            )
Exemple #53
0
    def run(self,
            gpo,
            H=None,
            sambaopts=None,
            credopts=None,
            versionopts=None):

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)

        self.url = dc_url(self.lp, self.creds, H)

        samdb_connect(self)

        try:
            msg = get_gpo_info(self.samdb, gpo)[0]
        except Exception:
            raise CommandError("GPO '%s' does not exist" % gpo)

        try:
            secdesc_ndr = msg['nTSecurityDescriptor'][0]
            secdesc = ndr_unpack(security.descriptor, secdesc_ndr)
            secdesc_sddl = secdesc.as_sddl()
        except Exception:
            secdesc_sddl = "<hidden>"

        self.outf.write("GPO          : %s\n" % msg['name'][0])
        self.outf.write("display name : %s\n" % msg['displayName'][0])
        self.outf.write("path         : %s\n" % msg['gPCFileSysPath'][0])
        self.outf.write("dn           : %s\n" % msg.dn)
        self.outf.write("version      : %s\n" %
                        attr_default(msg, 'versionNumber', '0'))
        self.outf.write("flags        : %s\n" %
                        gpo_flags_string(int(attr_default(msg, 'flags', 0))))
        self.outf.write("ACL          : %s\n" % secdesc_sddl)
        self.outf.write("\n")
Exemple #54
0
    def test_samr_GetGroupsForUser_nomember(self):
        # Confirm that we get the correct results against SAMR also
        if not url.startswith("ldap://"):
            self.fail(msg="This test is only valid on ldap (so we an find the hostname and use SAMR)")
        host = url.split("://")[1]

        test_user = "******"
        self.admin_ldb.newuser(test_user, self.test_user_pass)
        res = self.admin_ldb.search(base="cn=%s,cn=users,%s" % (test_user, self.base_dn),
                                    attrs=["objectSid"], scope=ldb.SCOPE_BASE)
        user_sid = ndr_unpack(samba.dcerpc.security.dom_sid, res[0]["objectSid"][0])

        (domain_sid, user_rid) = user_sid.split()
        samr_conn = samba.dcerpc.samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, creds)
        samr_handle = samr_conn.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
        samr_domain = samr_conn.OpenDomain(samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED,
                                           domain_sid)
        user_handle = samr_conn.OpenUser(samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, user_rid)
        rids = samr_conn.GetGroupsForUser(user_handle)
        user_info = samr_conn.QueryUserInfo(user_handle, 1)
        delete_force(self.admin_ldb, "CN=%s,%s,%s" %
                     (test_user, "cn=users", self.base_dn))
        self.assertEqual(len(rids.rids), 1)
        self.assertEqual(rids.rids[0].rid, user_info.primary_gid)
Exemple #55
0
    def test_dn_tokenGroups(self):
        print("Getting tokenGroups from user DN")
        res = self.ldb.search(self.user_sid_dn,
                              scope=ldb.SCOPE_BASE,
                              attrs=["tokenGroups"])
        self.assertEquals(len(res), 1)

        dn_tokengroups = []
        for sid in res[0]['tokenGroups']:
            dn_tokengroups.append(
                str(ndr_unpack(samba.dcerpc.security.dom_sid, sid)))

        sidset1 = set(dn_tokengroups)
        sidset2 = set(self.user_sids)

        # The SIDs on the DN do not include the NTLM authentication SID
        sidset2.discard(samba.dcerpc.security.SID_NT_NTLM_AUTHENTICATION)

        if len(sidset1.difference(sidset2)):
            print("token sids don't match")
            print("difference : %s" % sidset1.difference(sidset2))
            self.fail(
                msg="calculated groups don't match against user DN tokenGroups"
            )
Exemple #56
0
    def test_sort_behaviour_single_object(self):
        """Testing sorting behaviour on single objects"""

        user1_dn = "cn=test_user1,%s" % self.ou
        user2_dn = "cn=test_user2,%s" % self.ou
        user3_dn = "cn=test_user3,%s" % self.ou
        group_dn = "cn=test_group,%s" % self.ou

        self.ldb_dc1.add({"dn": user1_dn, "objectclass": "user"})
        self.ldb_dc1.add({"dn": user2_dn, "objectclass": "user"})
        self.ldb_dc1.add({"dn": user3_dn, "objectclass": "user"})
        self.ldb_dc1.add({"dn": group_dn, "objectclass": "group"})

        u1_guid = misc.GUID(
            self.ldb_dc1.search(base=user1_dn,
                                attrs=["objectGUID"])[0]['objectGUID'][0])
        u2_guid = misc.GUID(
            self.ldb_dc1.search(base=user2_dn,
                                attrs=["objectGUID"])[0]['objectGUID'][0])
        u3_guid = misc.GUID(
            self.ldb_dc1.search(base=user3_dn,
                                attrs=["objectGUID"])[0]['objectGUID'][0])
        g_guid = misc.GUID(
            self.ldb_dc1.search(base=group_dn,
                                attrs=["objectGUID"])[0]['objectGUID'][0])

        self.add_linked_attribute(group_dn, user1_dn, attr='member')
        self.add_linked_attribute(group_dn, user2_dn, attr='member')
        self.add_linked_attribute(group_dn, user3_dn, attr='member')
        self.add_linked_attribute(group_dn, user1_dn, attr='managedby')
        self.add_linked_attribute(group_dn, user2_dn, attr='nonSecurityMember')
        self.add_linked_attribute(group_dn, user3_dn, attr='nonSecurityMember')

        set_inactive = AbstractLink(
            drsuapi.DRSUAPI_ATTID_nonSecurityMember,
            drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE, g_guid, u3_guid)

        expected_links = set([
            set_inactive,
            AbstractLink(drsuapi.DRSUAPI_ATTID_member,
                         drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE,
                         g_guid, u1_guid),
            AbstractLink(drsuapi.DRSUAPI_ATTID_member,
                         drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE,
                         g_guid, u2_guid),
            AbstractLink(drsuapi.DRSUAPI_ATTID_member,
                         drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE,
                         g_guid, u3_guid),
            AbstractLink(drsuapi.DRSUAPI_ATTID_managedBy,
                         drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE,
                         g_guid, u1_guid),
            AbstractLink(drsuapi.DRSUAPI_ATTID_nonSecurityMember,
                         drsuapi.DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE,
                         g_guid, u2_guid),
        ])

        dc_guid_1 = self.ldb_dc1.get_invocation_id()

        drs, drs_handle = self._ds_bind(self.dnsname_dc1)

        req8 = self._exop_req8(dest_dsa=None,
                               invocation_id=dc_guid_1,
                               nc_dn_str=group_dn,
                               exop=drsuapi.DRSUAPI_EXOP_REPL_OBJ)

        (level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8)

        no_inactive = []
        for link in ctr.linked_attributes:
            target_guid = ndr_unpack(drsuapi.DsReplicaObjectIdentifier3,
                                     link.value.blob).guid
            no_inactive.append((link, target_guid))
            self.assertTrue(
                AbstractLink(link.attid, link.flags, link.identifier.guid,
                             target_guid) in expected_links)

        no_inactive.sort(cmp=_linked_attribute_compare)

        # assert the two arrays are the same
        self.assertEqual(len(expected_links), ctr.linked_attributes_count)
        self.assertEqual([x[0] for x in no_inactive], ctr.linked_attributes)

        self.remove_linked_attribute(group_dn,
                                     user3_dn,
                                     attr='nonSecurityMember')

        # Set the link inactive
        expected_links.remove(set_inactive)
        set_inactive.flags = 0
        expected_links.add(set_inactive)

        has_inactive = []
        (level, ctr) = drs.DsGetNCChanges(drs_handle, 8, req8)
        for link in ctr.linked_attributes:
            target_guid = ndr_unpack(drsuapi.DsReplicaObjectIdentifier3,
                                     link.value.blob).guid
            has_inactive.append((link, target_guid))
            self.assertTrue(
                AbstractLink(link.attid, link.flags, link.identifier.guid,
                             target_guid) in expected_links)

        has_inactive.sort(cmp=_linked_attribute_compare)

        # assert the two arrays are the same
        self.assertEqual(len(expected_links), ctr.linked_attributes_count)
        self.assertEqual([x[0] for x in has_inactive], ctr.linked_attributes)
Exemple #57
0
 def find_domain_sid(self):
     res = self.ldb.search(base=self.base_dn,
                           expression="(objectClass=*)",
                           scope=SCOPE_BASE)
     return ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
Exemple #58
0
 def sid(msg):
     sid = ndr_unpack(security.dom_sid, msg["objectSID"][0])
     (x, _) = sid.split()
     return x
def purge_computer_with_DC_objects(ucr, binddn, bindpw, computername):

    lp = LoadParm()
    lp.load('/etc/samba/smb.conf')

    samdb = SamDB(os.path.join(SAMBA_PRIVATE_DIR, "sam.ldb"),
                  session_info=system_session(lp),
                  lp=lp)

    backlink_attribute_list = [
        "serverReferenceBL", "frsComputerReferenceBL",
        "msDFSR-ComputerReferenceBL"
    ]
    msgs = samdb.search(
        base=ucr["samba4/ldap/base"],
        scope=samba.ldb.SCOPE_SUBTREE,
        expression="(&(objectClass=computer)(sAMAccountName=%s$))" %
        computername,
        attrs=backlink_attribute_list)
    if not msgs:
        print "Samba 4 computer account '%s' not found." % (computername, )
        sys.exit(1)

    answer = raw_input("Really remove %s from Samba 4? [y/N]: " % computername)
    if not answer.lower() in ('y', 'yes'):
        print "Ok, stopping as requested.\n"
        sys.exit(2)

    computer_obj = msgs[0]

    # Confirmation check
    answer = raw_input("If you are really sure type YES and hit enter: ")
    if not answer == 'YES':
        print "The answer was not 'YES', confirmation failed.\n"
        sys.exit(1)
    else:
        print "Ok, continuing as requested.\n"

    # Determine the NTDS_objectGUID
    NTDS_objectGUID = None
    if "serverReferenceBL" in computer_obj:
        msgs = samdb.search(base=computer_obj["serverReferenceBL"][0],
                            scope=samba.ldb.SCOPE_SUBTREE,
                            expression="(CN=NTDS Settings)",
                            attrs=["objectGUID"])
        if msgs and "objectGUID" in msgs[0]:
            NTDS_objectGUID = str(
                ndr_unpack(misc.GUID, msgs[0]["objectGUID"][0]))

    # Determine the Domain_GUID
    msgs = samdb.search(base=ucr["samba4/ldap/base"],
                        scope=samba.ldb.SCOPE_BASE,
                        attrs=["objectGUID"])
    if not msgs:
        print "Samba 4 Domain_GUID for base dn '%s' not found." % (
            ucr["samba4/ldap/base"], )
        sys.exit(1)
    Domain_GUID = str(ndr_unpack(misc.GUID, msgs[0]["objectGUID"][0]))

    # Build current site list
    msgs = samdb.search(base="CN=Configuration,%s" % ucr["samba4/ldap/base"],
                        scope=samba.ldb.SCOPE_SUBTREE,
                        expression="(objectClass=site)",
                        attrs=["cn"])
    site_list = [obj["cn"][0] for obj in msgs]

    # Remove Samba 4 DNS records
    purge_s4_dns_records(ucr, binddn, bindpw, computername, NTDS_objectGUID,
                         Domain_GUID, site_list)

    # remove objects from Samba 4 SAM database
    for backlink_attribute in backlink_attribute_list:
        if backlink_attribute in computer_obj:
            backlink_object = computer_obj[backlink_attribute][0]
            try:
                print "Removing %s from SAM database." % (backlink_object, )
                samdb.delete(backlink_object, ["tree_delete:0"])
            except:
                print >> sys.stderr, "Removal of Samba 4 %s objects %s from Samba 4 SAM database failed." % (
                    backlink_attribute,
                    backlink_object,
                )
                print traceback.format_exc()

    # Now delete the Samba 4 computer account and sub-objects
    # Cannot use tree_delete on isCriticalSystemObject, perform recursive delete like ldbdel code does it:
    msgs = samdb.search(base=computer_obj.dn,
                        scope=samba.ldb.SCOPE_SUBTREE,
                        attrs=["dn"])
    obj_dn_list = [obj.dn for obj in msgs]
    obj_dn_list.sort(key=len)
    obj_dn_list.reverse()
    for obj_dn in obj_dn_list:
        try:
            print "Removing %s from SAM database." % (obj_dn, )
            samdb.delete(obj_dn)
        except:
            print >> sys.stderr, "Removal of Samba 4 computer account object %s from Samba 4 SAM database failed." % (
                obj_dn, )
            print >> sys.stderr, traceback.format_exc()

    answer = raw_input("Really remove %s from UDM as well? [y/N]: " %
                       computername)
    if not answer.lower() in ('y', 'yes'):
        print "Ok, stopping as requested.\n"
        sys.exit(2)

    # Finally, for consistency remove S4 computer object from UDM
    purge_udm_computer(ucr, binddn, bindpw, computername)
Exemple #60
0
def rid(msg):
    sid = ndr_unpack(security.dom_sid, msg["objectSID"][0])
    (_, rid) = sid.split()
    return rid