Example #1
0
    def post_setup(self):
        ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials)

        # delete default SASL mappings
        res = ldapi_db.search(expression="(!(cn=samba-admin mapping))", base="cn=mapping,cn=sasl,cn=config", scope=SCOPE_ONELEVEL, attrs=["dn"])
    
        # configure in-directory access control on Fedora DS via the aci attribute (over a direct ldapi:// socket)
        for i in range (0, len(res)):
            dn = str(res[i]["dn"])
            ldapi_db.delete(dn)
            
        aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn
        
        m = ldb.Message()
        m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci")

        m.dn = ldb.Dn(ldapi_db, self.names.domaindn)
        ldapi_db.modify(m)
            
        m.dn = ldb.Dn(ldapi_db, self.names.configdn)
        ldapi_db.modify(m)
            
        m.dn = ldb.Dn(ldapi_db, self.names.schemadn)
        ldapi_db.modify(m)
Example #2
0
    def post_setup(self):
        ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials)

        # delete default SASL mappings
        res = ldapi_db.search(expression="(!(cn=samba-admin mapping))", base="cn=mapping,cn=sasl,cn=config", scope=SCOPE_ONELEVEL, attrs=["dn"])
    
        # configure in-directory access control on Fedora DS via the aci attribute (over a direct ldapi:// socket)
        for i in range (0, len(res)):
            dn = str(res[i]["dn"])
            ldapi_db.delete(dn)
            
            aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn
        
            m = ldb.Message()
            m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci")

            m.dn = ldb.Dn(1, self.names.domaindn)
            ldapi_db.modify(m)
            
            m.dn = ldb.Dn(1, self.names.configdn)
            ldapi_db.modify(m)
            
            m.dn = ldb.Dn(1, self.names.schemadn)
            ldapi_db.modify(m)
Example #3
0
class MapTestCase(MapBaseTestCase):
    def setUp(self):
        super(MapTestCase, self).setUp()
        ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        ldb.set_opaque("skip_allocate_sids", "true")
        ldif = read_datafile("provision_samba3sam.ldif")
        ldb.add_ldif(self.samba4.subst(ldif))
        self.setup_modules(ldb, self.samba3, self.samba4)
        del ldb
        self.ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        self.ldb.set_opaque("skip_allocate_sids", "true")

    def test_map_search(self):
        """Running search tests on mapped data."""
        self.samba3.db.add({
            "dn": "sambaDomainName=TESTS," + self.samba3.basedn,
            "objectclass": ["sambaDomain", "top"],
            "sambaSID": "S-1-5-21-4231626423-2410014848-2360679739",
            "sambaNextRid": "2000",
            "sambaDomainName": "TESTS"
        })

        # Add a set of split records
        self.ldb.add_ldif("""
dn: """ + self.samba4.dn("cn=Domain Users") + """
objectClass: group
cn: Domain Users
objectSid: S-1-5-21-4231626423-2410014848-2360679739-513
""")

        # Add a set of split records
        self.ldb.add_ldif("""
dn: """ + self.samba4.dn("cn=X") + """
objectClass: user
cn: X
codePage: x
revision: x
dnsHostName: x
nextRid: y
lastLogon: x
description: x
objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052
""")

        self.ldb.add({
            "dn": self.samba4.dn("cn=Y"),
            "objectClass": "top",
            "cn": "Y",
            "codePage": "x",
            "revision": "x",
            "dnsHostName": "y",
            "nextRid": "y",
            "lastLogon": "y",
            "description": "x"
        })

        self.ldb.add({
            "dn": self.samba4.dn("cn=Z"),
            "objectClass": "top",
            "cn": "Z",
            "codePage": "x",
            "revision": "y",
            "dnsHostName": "z",
            "nextRid": "y",
            "lastLogon": "z",
            "description": "y"
        })

        # Add a set of remote records

        self.samba3.db.add({
            "dn":
            self.samba3.dn("cn=A"),
            "objectClass":
            "posixAccount",
            "cn":
            "A",
            "sambaNextRid":
            "x",
            "sambaBadPasswordCount":
            "x",
            "sambaLogonTime":
            "x",
            "description":
            "x",
            "sambaSID":
            "S-1-5-21-4231626423-2410014848-2360679739-1052",
            "sambaPrimaryGroupSID":
            "S-1-5-21-4231626423-2410014848-2360679739-512"
        })

        self.samba3.db.add({
            "dn": self.samba3.dn("cn=B"),
            "objectClass": "top",
            "cn": "B",
            "sambaNextRid": "x",
            "sambaBadPasswordCount": "x",
            "sambaLogonTime": "y",
            "description": "x"
        })

        self.samba3.db.add({
            "dn": self.samba3.dn("cn=C"),
            "objectClass": "top",
            "cn": "C",
            "sambaNextRid": "x",
            "sambaBadPasswordCount": "y",
            "sambaLogonTime": "z",
            "description": "y"
        })

        # Testing search by DN

        # Search remote record by local DN
        dn = self.samba4.dn("cn=A")
        res = self.ldb.search(dn,
                              scope=SCOPE_BASE,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")

        # Search remote record by remote DN
        dn = self.samba3.dn("cn=A")
        res = self.samba3.db.search(
            dn,
            scope=SCOPE_BASE,
            attrs=["dnsHostName", "lastLogon", "sambaLogonTime"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertTrue(not "lastLogon" in res[0])
        self.assertEquals(str(res[0]["sambaLogonTime"]), "x")

        # Search split record by local DN
        dn = self.samba4.dn("cn=X")
        res = self.ldb.search(dn,
                              scope=SCOPE_BASE,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")

        # Search split record by remote DN
        dn = self.samba3.dn("cn=X")
        res = self.samba3.db.search(
            dn,
            scope=SCOPE_BASE,
            attrs=["dnsHostName", "lastLogon", "sambaLogonTime"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertTrue(not "lastLogon" in res[0])
        self.assertEquals(str(res[0]["sambaLogonTime"]), "x")

        # Testing search by attribute

        # Search by ignored attribute
        res = self.ldb.search(expression="(revision=x)",
                              scope=SCOPE_DEFAULT,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by kept attribute
        res = self.ldb.search(expression="(description=y)",
                              scope=SCOPE_DEFAULT,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[1]["dnsHostName"]), "z")
        self.assertEquals(str(res[1]["lastLogon"]), "z")

        # Search by renamed attribute
        res = self.ldb.search(expression="(badPwdCount=x)",
                              scope=SCOPE_DEFAULT,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by converted attribute
        # TODO:
        #   Using the SID directly in the parse tree leads to conversion
        #   errors, letting the search fail with no results.
        #res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-1052)", scope=SCOPE_DEFAULT, attrs)
        res = self.ldb.search(expression="(objectSid=*)",
                              base=None,
                              scope=SCOPE_DEFAULT,
                              attrs=["dnsHostName", "lastLogon", "objectSid"])
        self.assertEquals(len(res), 4)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             res[1]["objectSid"])
        self.assertTrue("objectSid" in res[1])
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             res[0]["objectSid"])
        self.assertTrue("objectSid" in res[0])

        # Search by generated attribute
        # In most cases, this even works when the mapping is missing
        # a `convert_operator' by enumerating the remote db.
        res = self.ldb.search(
            expression="(primaryGroupID=512)",
            attrs=["dnsHostName", "lastLogon", "primaryGroupID"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[0]["primaryGroupID"]), "512")

        # Note that Xs "objectSid" seems to be fine in the previous search for
        # "objectSid"...
        #res = ldb.search(expression="(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs)
        #print len(res) + " results found"
        #for i in range(len(res)):
        #    for (obj in res[i]) {
        #        print obj + ": " + res[i][obj]
        #    }
        #    print "---"
        #

        # Search by remote name of renamed attribute */
        res = self.ldb.search(expression="(sambaBadPasswordCount=*)",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 0)

        # Search by objectClass
        attrs = ["dnsHostName", "lastLogon", "objectClass"]
        res = self.ldb.search(expression="(objectClass=user)", attrs=attrs)
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[0]["objectClass"][0]), "user")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertEquals(str(res[1]["objectClass"][0]), "user")

        # Prove that the objectClass is actually used for the search
        res = self.ldb.search(
            expression="(|(objectClass=user)(badPwdCount=x))", attrs=attrs)
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(res[0]["objectClass"][0], "user")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(set(res[1]["objectClass"]), set(["top"]))
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[2]["dnsHostName"]), "x")
        self.assertEquals(str(res[2]["lastLogon"]), "x")
        self.assertEquals(str(res[2]["objectClass"][0]), "user")

        # Testing search by parse tree

        # Search by conjunction of local attributes
        res = self.ldb.search(expression="(&(codePage=x)(revision=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by conjunction of remote attributes
        res = self.ldb.search(expression="(&(lastLogon=x)(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")

        # Search by conjunction of local and remote attribute
        res = self.ldb.search(expression="(&(codePage=x)(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by conjunction of local and remote attribute w/o match
        attrs = ["dnsHostName", "lastLogon"]
        res = self.ldb.search(expression="(&(codePage=x)(nextRid=x))",
                              attrs=attrs)
        self.assertEquals(len(res), 0)
        res = self.ldb.search(expression="(&(revision=x)(lastLogon=z))",
                              attrs=attrs)
        self.assertEquals(len(res), 0)

        # Search by disjunction of local attributes
        res = self.ldb.search(expression="(|(revision=x)(dnsHostName=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by disjunction of remote attributes
        res = self.ldb.search(expression="(|(badPwdCount=x)(lastLogon=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertFalse("dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertFalse("dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[2]["dnsHostName"]), "x")
        self.assertEquals(str(res[2]["lastLogon"]), "x")

        # Search by disjunction of local and remote attribute
        res = self.ldb.search(expression="(|(revision=x)(lastLogon=y))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
        self.assertFalse("dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "y")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[2]["dnsHostName"]), "y")
        self.assertEquals(str(res[2]["lastLogon"]), "y")

        # Search by disjunction of local and remote attribute w/o match
        res = self.ldb.search(expression="(|(codePage=y)(nextRid=z))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 0)

        # Search by negated local attribute
        res = self.ldb.search(expression="(!(revision=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated remote attribute
        res = self.ldb.search(expression="(!(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 4)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[1]["dnsHostName"]), "z")
        self.assertEquals(str(res[1]["lastLogon"]), "z")

        # Search by negated conjunction of local attributes
        res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated conjunction of remote attributes
        res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "y")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "z")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[2]["dnsHostName"]), "y")
        self.assertEquals(str(res[2]["lastLogon"]), "y")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated conjunction of local and remote attribute
        res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated disjunction of local attributes
        res = self.ldb.search(expression="(!(|(revision=x)(dnsHostName=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated disjunction of remote attributes
        res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 5)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[2]["dnsHostName"]), "z")
        self.assertEquals(str(res[2]["lastLogon"]), "z")

        # Search by negated disjunction of local and remote attribute
        res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 5)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "z")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[2]["dnsHostName"]), "z")
        self.assertEquals(str(res[2]["lastLogon"]), "z")

        # Search by complex parse tree
        res = self.ldb.search(
            expression=
            "(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))",
            attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 7)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[3]["dnsHostName"]), "x")
        self.assertEquals(str(res[3]["lastLogon"]), "x")
        self.assertEquals(str(res[4].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[4]["dnsHostName"]), "z")
        self.assertEquals(str(res[4]["lastLogon"]), "z")

        # Clean up
        dns = [
            self.samba4.dn("cn=%s" % n)
            for n in ["A", "B", "C", "X", "Y", "Z"]
        ]
        for dn in dns:
            self.ldb.delete(dn)

    def test_map_modify_local(self):
        """Modification of local records."""
        # Add local record
        dn = "cn=test,dc=idealx,dc=org"
        self.ldb.add({
            "dn": dn,
            "cn": "test",
            "foo": "bar",
            "revision": "1",
            "description": "test"
        })
        # Check it's there
        attrs = ["foo", "revision", "description"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["foo"]), "bar")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "test")
        # Check it's not in the local db
        res = self.samba4.db.search(expression="(cn=test)",
                                    scope=SCOPE_DEFAULT,
                                    attrs=attrs)
        self.assertEquals(len(res), 0)
        # Check it's not in the remote db
        res = self.samba3.db.search(expression="(cn=test)",
                                    scope=SCOPE_DEFAULT,
                                    attrs=attrs)
        self.assertEquals(len(res), 0)

        # Modify local record
        ldif = """
dn: """ + dn + """
replace: foo
foo: baz
replace: description
description: foo
"""
        self.ldb.modify_ldif(ldif)
        # Check in local db
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["foo"]), "baz")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "foo")

        # Rename local record
        dn2 = "cn=toast,dc=idealx,dc=org"
        self.ldb.rename(dn, dn2)
        # Check in local db
        res = self.ldb.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["foo"]), "baz")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "foo")

        # Delete local record
        self.ldb.delete(dn2)
        # Check it's gone
        res = self.ldb.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)

    def test_map_modify_remote_remote(self):
        """Modification of remote data of remote records"""
        # Add remote record
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.samba3.db.add({
            "dn": dn2,
            "cn": "test",
            "description": "foo",
            "sambaBadPasswordCount": "3",
            "sambaNextRid": "1001"
        })
        # Check it's there
        res = self.samba3.db.search(
            dn2,
            scope=SCOPE_BASE,
            attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        # Check in mapped db
        attrs = ["description", "badPwdCount", "nextRid"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs, expression="")
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["badPwdCount"]), "3")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 0)

        # Modify remote data of remote record
        ldif = """
dn: """ + dn + """
replace: description
description: test
replace: badPwdCount
badPwdCount: 4
"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        res = self.ldb.search(dn,
                              scope=SCOPE_BASE,
                              attrs=["description", "badPwdCount", "nextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in remote db
        res = self.samba3.db.search(
            dn2,
            scope=SCOPE_BASE,
            attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")

        # Rename remote record
        dn2 = self.samba4.dn("cn=toast")
        self.ldb.rename(dn, dn2)
        # Check in mapped db
        dn = dn2
        res = self.ldb.search(dn,
                              scope=SCOPE_BASE,
                              attrs=["description", "badPwdCount", "nextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in remote db
        dn2 = self.samba3.dn("cn=toast")
        res = self.samba3.db.search(
            dn2,
            scope=SCOPE_BASE,
            attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")

        # Delete remote record
        self.ldb.delete(dn)
        # Check in mapped db that it's removed
        res = self.ldb.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)

    def test_map_modify_remote_local(self):
        """Modification of local data of remote records"""
        # Add remote record (same as before)
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.samba3.db.add({
            "dn": dn2,
            "cn": "test",
            "description": "foo",
            "sambaBadPasswordCount": "3",
            "sambaNextRid": "1001"
        })

        # Modify local data of remote record
        ldif = """
dn: """ + dn + """
add: revision
revision: 1
replace: description
description: test

"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        attrs = ["revision", "description"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertTrue(not "revision" in res[0])
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertEquals(str(res[0]["revision"]), "1")

        # Delete (newly) split record
        self.ldb.delete(dn)

    def test_map_modify_split(self):
        """Testing modification of split records"""
        # Add split record
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.ldb.add({
            "dn": dn,
            "cn": "test",
            "description": "foo",
            "badPwdCount": "3",
            "nextRid": "1001",
            "revision": "1"
        })
        # Check it's there
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["badPwdCount"]), "3")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in remote db
        attrs = [
            "description", "sambaBadPasswordCount", "sambaNextRid", "revision"
        ]
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Modify of split record
        ldif = """
dn: """ + dn + """
replace: description
description: test
replace: badPwdCount
badPwdCount: 4
replace: revision
revision: 2
"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in remote db
        attrs = [
            "description", "sambaBadPasswordCount", "sambaNextRid", "revision"
        ]
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Rename split record
        dn2 = self.samba4.dn("cn=toast")
        self.ldb.rename(dn, dn2)
        # Check in mapped db
        dn = dn2
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in remote db
        dn2 = self.samba3.dn("cn=toast")
        res = self.samba3.db.search(dn2,
                                    scope=SCOPE_BASE,
                                    attrs=[
                                        "description", "sambaBadPasswordCount",
                                        "sambaNextRid", "revision"
                                    ])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Delete split record
        self.ldb.delete(dn)
        # Check in mapped db
        res = self.ldb.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
Example #4
0
class Samba3SamTestCase(MapBaseTestCase):
    def setUp(self):
        super(Samba3SamTestCase, self).setUp()
        ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        ldb.set_opaque("skip_allocate_sids", "true")
        self.samba3.setup_data("samba3.ldif")
        ldif = read_datafile("provision_samba3sam.ldif")
        ldb.add_ldif(self.samba4.subst(ldif))
        self.setup_modules(ldb, self.samba3, self.samba4)
        del ldb
        self.ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        self.ldb.set_opaque("skip_allocate_sids", "true")

    def test_search_non_mapped(self):
        """Looking up by non-mapped attribute"""
        msg = self.ldb.search(expression="(cn=Administrator)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(msg[0]["cn"], "Administrator")

    def test_search_non_mapped(self):
        """Looking up by mapped attribute"""
        msg = self.ldb.search(expression="(name=Backup Operators)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["name"]), "Backup Operators")

    def test_old_name_of_renamed(self):
        """Looking up by old name of renamed attribute"""
        msg = self.ldb.search(expression="(displayName=Backup Operators)")
        self.assertEquals(len(msg), 0)

    def test_mapped_containing_sid(self):
        """Looking up mapped entry containing SID"""
        msg = self.ldb.search(expression="(cn=Replicator)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0].dn),
                          "cn=Replicator,ou=Groups,dc=vernstok,dc=nl")
        self.assertTrue("objectSid" in msg[0])
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             msg[0]["objectSid"])
        oc = set(msg[0]["objectClass"])
        self.assertEquals(oc, set(["group"]))

    def test_search_by_objclass(self):
        """Looking up by objectClass"""
        msg = self.ldb.search(
            expression="(|(objectClass=user)(cn=Administrator))")
        self.assertEquals(
            set([str(m.dn) for m in msg]),
            set([
                "unixName=Administrator,ou=Users,dc=vernstok,dc=nl",
                "unixName=nobody,ou=Users,dc=vernstok,dc=nl"
            ]))

    def test_s3sam_modify(self):
        # Adding a record that will be fallbacked
        self.ldb.add({
            "dn": "cn=Foo",
            "foo": "bar",
            "blah": "Blie",
            "cn": "Foo",
            "showInAdvancedViewOnly": "TRUE"
        })

        # Checking for existence of record (local)
        # TODO: This record must be searched in the local database, which is
        # currently only supported for base searches
        # msg = ldb.search(expression="(cn=Foo)", ['foo','blah','cn','showInAdvancedViewOnly')]
        # TODO: Actually, this version should work as well but doesn't...
        #
        #
        msg = self.ldb.search(
            expression="(cn=Foo)",
            base="cn=Foo",
            scope=SCOPE_BASE,
            attrs=['foo', 'blah', 'cn', 'showInAdvancedViewOnly'])
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["showInAdvancedViewOnly"]), "TRUE")
        self.assertEquals(str(msg[0]["foo"]), "bar")
        self.assertEquals(str(msg[0]["blah"]), "Blie")

        # Adding record that will be mapped
        self.ldb.add({
            "dn": "cn=Niemand,cn=Users,dc=vernstok,dc=nl",
            "objectClass": "user",
            "unixName": "bin",
            "sambaUnicodePwd": "geheim",
            "cn": "Niemand"
        })

        # Checking for existence of record (remote)
        msg = self.ldb.search(
            expression="(unixName=bin)",
            attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd'])
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for existence of record (local && remote)
        msg = self.ldb.search(
            expression="(&(unixName=bin)(sambaUnicodePwd=geheim))",
            attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd'])
        self.assertEquals(len(msg), 1)  # TODO: should check with more records
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["unixName"]), "bin")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for existence of record (local || remote)
        msg = self.ldb.search(
            expression="(|(unixName=bin)(sambaUnicodePwd=geheim))",
            attrs=['unixName', 'cn', 'dn', 'sambaUnicodePwd'])
        #print "got %d replies" % len(msg)
        self.assertEquals(len(msg), 1)  # TODO: should check with more records
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["unixName"]), "bin")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for data in destination database
        msg = self.samba3.db.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["sambaSID"]),
                          "S-1-5-21-4231626423-2410014848-2360679739-2001")
        self.assertEquals(str(msg[0]["displayName"]), "Niemand")

        # Adding attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
add: description
description: Blah
""")

        # Checking whether changes are still there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["description"]), "Blah")

        # Modifying attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
replace: description
description: Blie
""")

        # Checking whether changes are still there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["description"]), "Blie")

        # Deleting attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
delete: description
""")

        # Checking whether changes are no longer there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertTrue(not "description" in msg[0])

        # Renaming record...
        self.ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl",
                        "cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Checking whether DN has changed...
        msg = self.ldb.search(expression="(cn=Niemand2)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0].dn),
                          "cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Deleting record...
        self.ldb.delete("cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Checking whether record is gone...
        msg = self.ldb.search(expression="(cn=Niemand2)")
        self.assertEquals(len(msg), 0)
Example #5
0
class MapTestCase(MapBaseTestCase):

    def setUp(self):
        super(MapTestCase, self).setUp()
        ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        ldb.set_opaque("skip_allocate_sids", "true");
        ldif = read_datafile("provision_samba3sam.ldif")
        ldb.add_ldif(self.samba4.subst(ldif))
        self.setup_modules(ldb, self.samba3, self.samba4)
        del ldb
        self.ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        self.ldb.set_opaque("skip_allocate_sids", "true");

    def test_map_search(self):
        """Running search tests on mapped data."""
        self.samba3.db.add({
            "dn": "sambaDomainName=TESTS," + self.samba3.basedn,
            "objectclass": ["sambaDomain", "top"],
            "sambaSID": "S-1-5-21-4231626423-2410014848-2360679739",
            "sambaNextRid": "2000",
            "sambaDomainName": "TESTS"
            })

        # Add a set of split records
        self.ldb.add_ldif("""
dn: """+ self.samba4.dn("cn=Domain Users") + """
objectClass: group
cn: Domain Users
objectSid: S-1-5-21-4231626423-2410014848-2360679739-513
""")

        # Add a set of split records
        self.ldb.add_ldif("""
dn: """+ self.samba4.dn("cn=X") + """
objectClass: user
cn: X
codePage: x
revision: x
dnsHostName: x
nextRid: y
lastLogon: x
description: x
objectSid: S-1-5-21-4231626423-2410014848-2360679739-1052
""")

        self.ldb.add({
            "dn": self.samba4.dn("cn=Y"),
            "objectClass": "top",
            "cn": "Y",
            "codePage": "x",
            "revision": "x",
            "dnsHostName": "y",
            "nextRid": "y",
            "lastLogon": "y",
            "description": "x"})

        self.ldb.add({
            "dn": self.samba4.dn("cn=Z"),
            "objectClass": "top",
            "cn": "Z",
            "codePage": "x",
            "revision": "y",
            "dnsHostName": "z",
            "nextRid": "y",
            "lastLogon": "z",
            "description": "y"})

        # Add a set of remote records

        self.samba3.db.add({
            "dn": self.samba3.dn("cn=A"),
            "objectClass": "posixAccount",
            "cn": "A",
            "sambaNextRid": "x",
            "sambaBadPasswordCount": "x",
            "sambaLogonTime": "x",
            "description": "x",
            "sambaSID": "S-1-5-21-4231626423-2410014848-2360679739-1052",
            "sambaPrimaryGroupSID": "S-1-5-21-4231626423-2410014848-2360679739-512"})

        self.samba3.db.add({
            "dn": self.samba3.dn("cn=B"),
            "objectClass": "top",
            "cn": "B",
            "sambaNextRid": "x",
            "sambaBadPasswordCount": "x",
            "sambaLogonTime": "y",
            "description": "x"})

        self.samba3.db.add({
            "dn": self.samba3.dn("cn=C"),
            "objectClass": "top",
            "cn": "C",
            "sambaNextRid": "x",
            "sambaBadPasswordCount": "y",
            "sambaLogonTime": "z",
            "description": "y"})

        # Testing search by DN

        # Search remote record by local DN
        dn = self.samba4.dn("cn=A")
        res = self.ldb.search(dn, scope=SCOPE_BASE,
                attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")

        # Search remote record by remote DN
        dn = self.samba3.dn("cn=A")
        res = self.samba3.db.search(dn, scope=SCOPE_BASE,
                attrs=["dnsHostName", "lastLogon", "sambaLogonTime"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertTrue(not "lastLogon" in res[0])
        self.assertEquals(str(res[0]["sambaLogonTime"]), "x")

        # Search split record by local DN
        dn = self.samba4.dn("cn=X")
        res = self.ldb.search(dn, scope=SCOPE_BASE,
                attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")

        # Search split record by remote DN
        dn = self.samba3.dn("cn=X")
        res = self.samba3.db.search(dn, scope=SCOPE_BASE,
                attrs=["dnsHostName", "lastLogon", "sambaLogonTime"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertTrue(not "lastLogon" in res[0])
        self.assertEquals(str(res[0]["sambaLogonTime"]), "x")

        # Testing search by attribute

        # Search by ignored attribute
        res = self.ldb.search(expression="(revision=x)", scope=SCOPE_DEFAULT,
                attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by kept attribute
        res = self.ldb.search(expression="(description=y)",
                scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[1]["dnsHostName"]), "z")
        self.assertEquals(str(res[1]["lastLogon"]), "z")

        # Search by renamed attribute
        res = self.ldb.search(expression="(badPwdCount=x)", scope=SCOPE_DEFAULT,
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by converted attribute
        # TODO:
        #   Using the SID directly in the parse tree leads to conversion
        #   errors, letting the search fail with no results.
        #res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-1052)", scope=SCOPE_DEFAULT, attrs)
        res = self.ldb.search(expression="(objectSid=*)", base=None, scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon", "objectSid"])
        self.assertEquals(len(res), 4)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             res[1]["objectSid"])
        self.assertTrue("objectSid" in res[1])
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             res[0]["objectSid"])
        self.assertTrue("objectSid" in res[0])

        # Search by generated attribute
        # In most cases, this even works when the mapping is missing
        # a `convert_operator' by enumerating the remote db.
        res = self.ldb.search(expression="(primaryGroupID=512)",
                           attrs=["dnsHostName", "lastLogon", "primaryGroupID"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[0]["primaryGroupID"]), "512")

        # Note that Xs "objectSid" seems to be fine in the previous search for
        # "objectSid"...
        #res = ldb.search(expression="(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs)
        #print len(res) + " results found"
        #for i in range(len(res)):
        #    for (obj in res[i]) {
        #        print obj + ": " + res[i][obj]
        #    }
        #    print "---"
        #

        # Search by remote name of renamed attribute */
        res = self.ldb.search(expression="(sambaBadPasswordCount=*)",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 0)

        # Search by objectClass
        attrs = ["dnsHostName", "lastLogon", "objectClass"]
        res = self.ldb.search(expression="(objectClass=user)", attrs=attrs)
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[0]["objectClass"][0]), "user")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertEquals(str(res[1]["objectClass"][0]), "user")

        # Prove that the objectClass is actually used for the search
        res = self.ldb.search(expression="(|(objectClass=user)(badPwdCount=x))",
                              attrs=attrs)
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(res[0]["objectClass"][0], "user")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(set(res[1]["objectClass"]), set(["top"]))
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[2]["dnsHostName"]), "x")
        self.assertEquals(str(res[2]["lastLogon"]), "x")
        self.assertEquals(str(res[2]["objectClass"][0]), "user")

        # Testing search by parse tree

        # Search by conjunction of local attributes
        res = self.ldb.search(expression="(&(codePage=x)(revision=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by conjunction of remote attributes
        res = self.ldb.search(expression="(&(lastLogon=x)(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")

        # Search by conjunction of local and remote attribute
        res = self.ldb.search(expression="(&(codePage=x)(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by conjunction of local and remote attribute w/o match
        attrs = ["dnsHostName", "lastLogon"]
        res = self.ldb.search(expression="(&(codePage=x)(nextRid=x))",
                              attrs=attrs)
        self.assertEquals(len(res), 0)
        res = self.ldb.search(expression="(&(revision=x)(lastLogon=z))",
                              attrs=attrs)
        self.assertEquals(len(res), 0)

        # Search by disjunction of local attributes
        res = self.ldb.search(expression="(|(revision=x)(dnsHostName=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 2)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[0]["dnsHostName"]), "x")
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")

        # Search by disjunction of remote attributes
        res = self.ldb.search(expression="(|(badPwdCount=x)(lastLogon=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertFalse("dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertFalse("dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[2]["dnsHostName"]), "x")
        self.assertEquals(str(res[2]["lastLogon"]), "x")

        # Search by disjunction of local and remote attribute
        res = self.ldb.search(expression="(|(revision=x)(lastLogon=y))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 3)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
        self.assertFalse("dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "y")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[1]["dnsHostName"]), "x")
        self.assertEquals(str(res[1]["lastLogon"]), "x")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[2]["dnsHostName"]), "y")
        self.assertEquals(str(res[2]["lastLogon"]), "y")

        # Search by disjunction of local and remote attribute w/o match
        res = self.ldb.search(expression="(|(codePage=y)(nextRid=z))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 0)

        # Search by negated local attribute
        res = self.ldb.search(expression="(!(revision=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated remote attribute
        res = self.ldb.search(expression="(!(description=x))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 4)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[1]["dnsHostName"]), "z")
        self.assertEquals(str(res[1]["lastLogon"]), "z")

        # Search by negated conjunction of local attributes
        res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated conjunction of remote attributes
        res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "y")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "z")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[2]["dnsHostName"]), "y")
        self.assertEquals(str(res[2]["lastLogon"]), "y")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated conjunction of local and remote attribute
        res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 6)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated disjunction of local attributes
        res = self.ldb.search(expression="(!(|(revision=x)(dnsHostName=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[3]["dnsHostName"]), "z")
        self.assertEquals(str(res[3]["lastLogon"]), "z")

        # Search by negated disjunction of remote attributes
        res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 5)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "z")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=Y"))
        self.assertEquals(str(res[1]["dnsHostName"]), "y")
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[2]["dnsHostName"]), "z")
        self.assertEquals(str(res[2]["lastLogon"]), "z")

        # Search by negated disjunction of local and remote attribute
        res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))",
                              attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 5)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "z")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[2]["dnsHostName"]), "z")
        self.assertEquals(str(res[2]["lastLogon"]), "z")

        # Search by complex parse tree
        res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=["dnsHostName", "lastLogon"])
        self.assertEquals(len(res), 7)
        res = sorted(res, key=attrgetter('dn'))
        self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A"))
        self.assertTrue(not "dnsHostName" in res[0])
        self.assertEquals(str(res[0]["lastLogon"]), "x")
        self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B"))
        self.assertTrue(not "dnsHostName" in res[1])
        self.assertEquals(str(res[1]["lastLogon"]), "y")
        self.assertEquals(str(res[2].dn), self.samba4.dn("cn=C"))
        self.assertTrue(not "dnsHostName" in res[2])
        self.assertEquals(str(res[2]["lastLogon"]), "z")
        self.assertEquals(str(res[3].dn), self.samba4.dn("cn=X"))
        self.assertEquals(str(res[3]["dnsHostName"]), "x")
        self.assertEquals(str(res[3]["lastLogon"]), "x")
        self.assertEquals(str(res[4].dn), self.samba4.dn("cn=Z"))
        self.assertEquals(str(res[4]["dnsHostName"]), "z")
        self.assertEquals(str(res[4]["lastLogon"]), "z")

        # Clean up
        dns = [self.samba4.dn("cn=%s" % n) for n in ["A","B","C","X","Y","Z"]]
        for dn in dns:
            self.ldb.delete(dn)

    def test_map_modify_local(self):
        """Modification of local records."""
        # Add local record
        dn = "cn=test,dc=idealx,dc=org"
        self.ldb.add({"dn": dn,
                 "cn": "test",
                 "foo": "bar",
                 "revision": "1",
                 "description": "test"})
        # Check it's there
        attrs = ["foo", "revision", "description"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["foo"]), "bar")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "test")
        # Check it's not in the local db
        res = self.samba4.db.search(expression="(cn=test)",
                                    scope=SCOPE_DEFAULT, attrs=attrs)
        self.assertEquals(len(res), 0)
        # Check it's not in the remote db
        res = self.samba3.db.search(expression="(cn=test)",
                                    scope=SCOPE_DEFAULT, attrs=attrs)
        self.assertEquals(len(res), 0)

        # Modify local record
        ldif = """
dn: """ + dn + """
replace: foo
foo: baz
replace: description
description: foo
"""
        self.ldb.modify_ldif(ldif)
        # Check in local db
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["foo"]), "baz")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "foo")

        # Rename local record
        dn2 = "cn=toast,dc=idealx,dc=org"
        self.ldb.rename(dn, dn2)
        # Check in local db
        res = self.ldb.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["foo"]), "baz")
        self.assertEquals(str(res[0]["revision"]), "1")
        self.assertEquals(str(res[0]["description"]), "foo")

        # Delete local record
        self.ldb.delete(dn2)
        # Check it's gone
        res = self.ldb.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)

    def test_map_modify_remote_remote(self):
        """Modification of remote data of remote records"""
        # Add remote record
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.samba3.db.add({"dn": dn2,
                   "cn": "test",
                   "description": "foo",
                   "sambaBadPasswordCount": "3",
                   "sambaNextRid": "1001"})
        # Check it's there
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE,
                attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        # Check in mapped db
        attrs = ["description", "badPwdCount", "nextRid"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs, expression="")
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["badPwdCount"]), "3")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 0)

        # Modify remote data of remote record
        ldif = """
dn: """ + dn + """
replace: description
description: test
replace: badPwdCount
badPwdCount: 4
"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        res = self.ldb.search(dn, scope=SCOPE_BASE,
                attrs=["description", "badPwdCount", "nextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE,
                attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")

        # Rename remote record
        dn2 = self.samba4.dn("cn=toast")
        self.ldb.rename(dn, dn2)
        # Check in mapped db
        dn = dn2
        res = self.ldb.search(dn, scope=SCOPE_BASE,
                attrs=["description", "badPwdCount", "nextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        # Check in remote db
        dn2 = self.samba3.dn("cn=toast")
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE,
                attrs=["description", "sambaBadPasswordCount", "sambaNextRid"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")

        # Delete remote record
        self.ldb.delete(dn)
        # Check in mapped db that it's removed
        res = self.ldb.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)

    def test_map_modify_remote_local(self):
        """Modification of local data of remote records"""
        # Add remote record (same as before)
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.samba3.db.add({"dn": dn2,
                   "cn": "test",
                   "description": "foo",
                   "sambaBadPasswordCount": "3",
                   "sambaNextRid": "1001"})

        # Modify local data of remote record
        ldif = """
dn: """ + dn + """
add: revision
revision: 1
replace: description
description: test

"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        attrs = ["revision", "description"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertTrue(not "revision" in res[0])
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertEquals(str(res[0]["revision"]), "1")

        # Delete (newly) split record
        self.ldb.delete(dn)

    def test_map_modify_split(self):
        """Testing modification of split records"""
        # Add split record
        dn = self.samba4.dn("cn=test")
        dn2 = self.samba3.dn("cn=test")
        self.ldb.add({
            "dn": dn,
            "cn": "test",
            "description": "foo",
            "badPwdCount": "3",
            "nextRid": "1001",
            "revision": "1"})
        # Check it's there
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["badPwdCount"]), "3")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "1")
        # Check in remote db
        attrs = ["description", "sambaBadPasswordCount", "sambaNextRid",
                 "revision"]
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "foo")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "3")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Modify of split record
        ldif = """
dn: """ + dn + """
replace: description
description: test
replace: badPwdCount
badPwdCount: 4
replace: revision
revision: 2
"""
        self.ldb.modify_ldif(ldif)
        # Check in mapped db
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in remote db
        attrs = ["description", "sambaBadPasswordCount", "sambaNextRid",
                 "revision"]
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Rename split record
        dn2 = self.samba4.dn("cn=toast")
        self.ldb.rename(dn, dn2)
        # Check in mapped db
        dn = dn2
        attrs = ["description", "badPwdCount", "nextRid", "revision"]
        res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["badPwdCount"]), "4")
        self.assertEquals(str(res[0]["nextRid"]), "1001")
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE, attrs=attrs)
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn)
        self.assertTrue(not "description" in res[0])
        self.assertTrue(not "badPwdCount" in res[0])
        self.assertTrue(not "nextRid" in res[0])
        self.assertEquals(str(res[0]["revision"]), "2")
        # Check in remote db
        dn2 = self.samba3.dn("cn=toast")
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE,
          attrs=["description", "sambaBadPasswordCount", "sambaNextRid",
                 "revision"])
        self.assertEquals(len(res), 1)
        self.assertEquals(str(res[0].dn), dn2)
        self.assertEquals(str(res[0]["description"]), "test")
        self.assertEquals(str(res[0]["sambaBadPasswordCount"]), "4")
        self.assertEquals(str(res[0]["sambaNextRid"]), "1001")
        self.assertTrue(not "revision" in res[0])

        # Delete split record
        self.ldb.delete(dn)
        # Check in mapped db
        res = self.ldb.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in local db
        res = self.samba4.db.search(dn, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
        # Check in remote db
        res = self.samba3.db.search(dn2, scope=SCOPE_BASE)
        self.assertEquals(len(res), 0)
Example #6
0
class Samba3SamTestCase(MapBaseTestCase):

    def setUp(self):
        super(Samba3SamTestCase, self).setUp()
        ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        ldb.set_opaque("skip_allocate_sids", "true");
        self.samba3.setup_data("samba3.ldif")
        ldif = read_datafile("provision_samba3sam.ldif")
        ldb.add_ldif(self.samba4.subst(ldif))
        self.setup_modules(ldb, self.samba3, self.samba4)
        del ldb
        self.ldb = Ldb(self.ldburl, lp=self.lp, session_info=system_session())
        self.ldb.set_opaque("skip_allocate_sids", "true");

    def test_search_non_mapped(self):
        """Looking up by non-mapped attribute"""
        msg = self.ldb.search(expression="(cn=Administrator)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(msg[0]["cn"], "Administrator")

    def test_search_non_mapped(self):
        """Looking up by mapped attribute"""
        msg = self.ldb.search(expression="(name=Backup Operators)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["name"]), "Backup Operators")

    def test_old_name_of_renamed(self):
        """Looking up by old name of renamed attribute"""
        msg = self.ldb.search(expression="(displayName=Backup Operators)")
        self.assertEquals(len(msg), 0)

    def test_mapped_containing_sid(self):
        """Looking up mapped entry containing SID"""
        msg = self.ldb.search(expression="(cn=Replicator)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0].dn),
                          "cn=Replicator,ou=Groups,dc=vernstok,dc=nl")
        self.assertTrue("objectSid" in msg[0])
        self.assertSidEquals("S-1-5-21-4231626423-2410014848-2360679739-1052",
                             msg[0]["objectSid"])
        oc = set(msg[0]["objectClass"])
        self.assertEquals(oc, set(["group"]))

    def test_search_by_objclass(self):
        """Looking up by objectClass"""
        msg = self.ldb.search(expression="(|(objectClass=user)(cn=Administrator))")
        self.assertEquals(set([str(m.dn) for m in msg]),
                set(["unixName=Administrator,ou=Users,dc=vernstok,dc=nl",
                     "unixName=nobody,ou=Users,dc=vernstok,dc=nl"]))

    def test_s3sam_modify(self):
        # Adding a record that will be fallbacked
        self.ldb.add({
            "dn": "cn=Foo",
            "foo": "bar",
            "blah": "Blie",
            "cn": "Foo",
            "showInAdvancedViewOnly": "TRUE"})

        # Checking for existence of record (local)
        # TODO: This record must be searched in the local database, which is
        # currently only supported for base searches
        # msg = ldb.search(expression="(cn=Foo)", ['foo','blah','cn','showInAdvancedViewOnly')]
        # TODO: Actually, this version should work as well but doesn't...
        #
        #
        msg = self.ldb.search(expression="(cn=Foo)", base="cn=Foo",
                scope=SCOPE_BASE,
                attrs=['foo','blah','cn','showInAdvancedViewOnly'])
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["showInAdvancedViewOnly"]), "TRUE")
        self.assertEquals(str(msg[0]["foo"]), "bar")
        self.assertEquals(str(msg[0]["blah"]), "Blie")

        # Adding record that will be mapped
        self.ldb.add({"dn": "cn=Niemand,cn=Users,dc=vernstok,dc=nl",
                 "objectClass": "user",
                 "unixName": "bin",
                 "sambaUnicodePwd": "geheim",
                 "cn": "Niemand"})

        # Checking for existence of record (remote)
        msg = self.ldb.search(expression="(unixName=bin)",
                              attrs=['unixName','cn','dn', 'sambaUnicodePwd'])
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for existence of record (local && remote)
        msg = self.ldb.search(expression="(&(unixName=bin)(sambaUnicodePwd=geheim))",
                         attrs=['unixName','cn','dn', 'sambaUnicodePwd'])
        self.assertEquals(len(msg), 1)           # TODO: should check with more records
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["unixName"]), "bin")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for existence of record (local || remote)
        msg = self.ldb.search(expression="(|(unixName=bin)(sambaUnicodePwd=geheim))",
                         attrs=['unixName','cn','dn', 'sambaUnicodePwd'])
        #print "got %d replies" % len(msg)
        self.assertEquals(len(msg), 1)        # TODO: should check with more records
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["unixName"]), "bin")
        self.assertEquals(str(msg[0]["sambaUnicodePwd"]), "geheim")

        # Checking for data in destination database
        msg = self.samba3.db.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["sambaSID"]),
                "S-1-5-21-4231626423-2410014848-2360679739-2001")
        self.assertEquals(str(msg[0]["displayName"]), "Niemand")

        # Adding attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
add: description
description: Blah
""")

        # Checking whether changes are still there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["cn"]), "Niemand")
        self.assertEquals(str(msg[0]["description"]), "Blah")

        # Modifying attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
replace: description
description: Blie
""")

        # Checking whether changes are still there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertEquals(str(msg[0]["description"]), "Blie")

        # Deleting attribute...
        self.ldb.modify_ldif("""
dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
changetype: modify
delete: description
""")

        # Checking whether changes are no longer there...
        msg = self.ldb.search(expression="(cn=Niemand)")
        self.assertTrue(len(msg) >= 1)
        self.assertTrue(not "description" in msg[0])

        # Renaming record...
        self.ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl",
                        "cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Checking whether DN has changed...
        msg = self.ldb.search(expression="(cn=Niemand2)")
        self.assertEquals(len(msg), 1)
        self.assertEquals(str(msg[0].dn),
                          "cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Deleting record...
        self.ldb.delete("cn=Niemand2,cn=Users,dc=vernstok,dc=nl")

        # Checking whether record is gone...
        msg = self.ldb.search(expression="(cn=Niemand2)")
        self.assertEquals(len(msg), 0)
Example #7
0
class LDAPBase(object):

    def __init__(self, host, creds, lp,
                 two=False, quiet=False, descriptor=False, sort_aces=False, verbose=False,
                 view="section", base="", scope="SUB",
                 outf=sys.stdout, errf=sys.stderr, skip_missing_dn=True):
        ldb_options = []
        samdb_url = host
        if "://" not in host:
            if os.path.isfile(host):
                samdb_url = "tdb://%s" % host
            else:
                samdb_url = "ldap://%s" % host
        # use 'paged_search' module when connecting remotely
        if samdb_url.lower().startswith("ldap://"):
            ldb_options = ["modules:paged_searches"]
        self.outf = outf
        self.errf = errf
        self.ldb = Ldb(url=samdb_url,
                       credentials=creds,
                       lp=lp,
                       options=ldb_options)
        self.search_base = base
        self.search_scope = scope
        self.two_domains = two
        self.quiet = quiet
        self.descriptor = descriptor
        self.sort_aces = sort_aces
        self.view = view
        self.verbose = verbose
        self.host = host
        self.skip_missing_dn = skip_missing_dn
        self.base_dn = str(self.ldb.get_default_basedn())
        self.root_dn = str(self.ldb.get_root_basedn())
        self.config_dn = str(self.ldb.get_config_basedn())
        self.schema_dn = str(self.ldb.get_schema_basedn())
        self.domain_netbios = self.find_netbios()
        self.server_names = self.find_servers()
        self.domain_name = re.sub("[Dd][Cc]=", "", self.base_dn).replace(",", ".")
        self.domain_sid = self.find_domain_sid()
        self.get_sid_map()
        #
        # Log some domain controller specific place-holers that are being used
        # when compare content of two DCs. Uncomment for DEBUG purposes.
        if self.two_domains and not self.quiet:
            self.outf.write("\n* Place-holders for %s:\n" % self.host)
            self.outf.write(4 * " " + "${DOMAIN_DN}      => %s\n" %
                            self.base_dn)
            self.outf.write(4 * " " + "${DOMAIN_NETBIOS} => %s\n" %
                            self.domain_netbios)
            self.outf.write(4 * " " + "${SERVER_NAME}     => %s\n" %
                            self.server_names)
            self.outf.write(4 * " " + "${DOMAIN_NAME}    => %s\n" %
                            self.domain_name)

    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])

    def find_servers(self):
        """
        """
        res = self.ldb.search(base="OU=Domain Controllers,%s" % self.base_dn,
                              scope=SCOPE_SUBTREE, expression="(objectClass=computer)", attrs=["cn"])
        assert len(res) > 0
        return [str(x["cn"][0]) for x in res]

    def find_netbios(self):
        res = self.ldb.search(base="CN=Partitions,%s" % self.config_dn,
                              scope=SCOPE_SUBTREE, attrs=["nETBIOSName"])
        assert len(res) > 0
        for x in res:
            if "nETBIOSName" in x:
                return x["nETBIOSName"][0]

    def object_exists(self, object_dn):
        res = None
        try:
            res = self.ldb.search(base=object_dn, scope=SCOPE_BASE)
        except LdbError as e2:
            (enum, estr) = e2.args
            if enum == ERR_NO_SUCH_OBJECT:
                return False
            raise
        return len(res) == 1

    def delete_force(self, object_dn):
        try:
            self.ldb.delete(object_dn)
        except Ldb.LdbError as e:
            assert "No such object" in str(e)

    def get_attribute_name(self, key):
        """ Returns the real attribute name
            It resolved ranged results e.g. member;range=0-1499
        """

        m = RE_RANGED_RESULT.match(key)
        if m is None:
            return key

        return m.group(1)

    def get_attribute_values(self, object_dn, key, vals):
        """ Returns list with all attribute values
            It resolved ranged results e.g. member;range=0-1499
        """

        m = RE_RANGED_RESULT.match(key)
        if m is None:
            # no range, just return the values
            return vals

        attr = m.group(1)
        hi = int(m.group(3))

        # get additional values in a loop
        # until we get a response with '*' at the end
        while True:

            n = "%s;range=%d-*" % (attr, hi + 1)
            res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=[n])
            assert len(res) == 1
            res = dict(res[0])
            del res["dn"]

            fm = None
            fvals = None

            for key in res:
                m = RE_RANGED_RESULT.match(key)

                if m is None:
                    continue

                if m.group(1) != attr:
                    continue

                fm = m
                fvals = list(res[key])
                break

            if fm is None:
                break

            vals.extend(fvals)
            if fm.group(3) == "*":
                # if we got "*" we're done
                break

            assert int(fm.group(2)) == hi + 1
            hi = int(fm.group(3))

        return vals

    def get_attributes(self, object_dn):
        """ Returns dict with all default visible attributes
        """
        res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=["*"])
        assert len(res) == 1
        res = dict(res[0])
        # 'Dn' element is not iterable and we have it as 'distinguishedName'
        del res["dn"]

        attributes = {}
        for key, vals in res.items():
            name = self.get_attribute_name(key)
            # sort vals and return a list, help to compare
            vals = sorted(vals)
            attributes[name] = self.get_attribute_values(object_dn, key, vals)

        return attributes

    def get_descriptor_sddl(self, object_dn):
        res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"])
        desc = res[0]["nTSecurityDescriptor"][0]
        desc = ndr_unpack(security.descriptor, desc)
        return desc.as_sddl(self.domain_sid)

    def guid_as_string(self, guid_blob):
        """ Translate binary representation of schemaIDGUID to standard string representation.
            @gid_blob: binary schemaIDGUID
        """
        blob = "%s" % guid_blob
        stops = [4, 2, 2, 2, 6]
        index = 0
        res = ""
        x = 0
        while x < len(stops):
            tmp = ""
            y = 0
            while y < stops[x]:
                c = hex(ord(blob[index])).replace("0x", "")
                c = [None, "0" + c, c][len(c)]
                if 2 * index < len(blob):
                    tmp = c + tmp
                else:
                    tmp += c
                index += 1
                y += 1
            res += tmp + " "
            x += 1
        assert index == len(blob)
        return res.strip().replace(" ", "-")

    def get_sid_map(self):
        """ Build dictionary that maps GUID to 'name' attribute found in Schema or Extended-Rights.
        """
        self.sid_map = {}
        res = self.ldb.search(base=self.base_dn,
                              expression="(objectSid=*)", scope=SCOPE_SUBTREE, attrs=["objectSid", "sAMAccountName"])
        for item in res:
            try:
                self.sid_map["%s" % ndr_unpack(security.dom_sid, item["objectSid"][0])] = str(item["sAMAccountName"][0])
            except KeyError:
                pass
Example #8
0
class LDAPBase(object):

    def __init__(self, host, creds, lp,
                 two=False, quiet=False, descriptor=False, sort_aces=False, verbose=False,
                 view="section", base="", scope="SUB",
                 outf=sys.stdout, errf=sys.stderr, skip_missing_dn=True):
        ldb_options = []
        samdb_url = host
        if not "://" in host:
            if os.path.isfile(host):
                samdb_url = "tdb://%s" % host
            else:
                samdb_url = "ldap://%s" % host
        # use 'paged_search' module when connecting remotely
        if samdb_url.lower().startswith("ldap://"):
            ldb_options = ["modules:paged_searches"]
        self.outf = outf
        self.errf = errf
        self.ldb = Ldb(url=samdb_url,
                       credentials=creds,
                       lp=lp,
                       options=ldb_options)
        self.search_base = base
        self.search_scope = scope
        self.two_domains = two
        self.quiet = quiet
        self.descriptor = descriptor
        self.sort_aces = sort_aces
        self.view = view
        self.verbose = verbose
        self.host = host
        self.skip_missing_dn = skip_missing_dn
        self.base_dn = str(self.ldb.get_default_basedn())
        self.root_dn = str(self.ldb.get_root_basedn())
        self.config_dn = str(self.ldb.get_config_basedn())
        self.schema_dn = str(self.ldb.get_schema_basedn())
        self.domain_netbios = self.find_netbios()
        self.server_names = self.find_servers()
        self.domain_name = re.sub("[Dd][Cc]=", "", self.base_dn).replace(",", ".")
        self.domain_sid = self.find_domain_sid()
        self.get_sid_map()
        #
        # Log some domain controller specific place-holers that are being used
        # when compare content of two DCs. Uncomment for DEBUG purposes.
        if self.two_domains and not self.quiet:
            self.outf.write("\n* Place-holders for %s:\n" % self.host)
            self.outf.write(4*" " + "${DOMAIN_DN}      => %s\n" %
                self.base_dn)
            self.outf.write(4*" " + "${DOMAIN_NETBIOS} => %s\n" %
                self.domain_netbios)
            self.outf.write(4*" " + "${SERVER_NAME}     => %s\n" %
                self.server_names)
            self.outf.write(4*" " + "${DOMAIN_NAME}    => %s\n" %
                self.domain_name)

    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])

    def find_servers(self):
        """
        """
        res = self.ldb.search(base="OU=Domain Controllers,%s" % self.base_dn,
                scope=SCOPE_SUBTREE, expression="(objectClass=computer)", attrs=["cn"])
        assert len(res) > 0
        srv = []
        for x in res:
            srv.append(x["cn"][0])
        return srv

    def find_netbios(self):
        res = self.ldb.search(base="CN=Partitions,%s" % self.config_dn,
                scope=SCOPE_SUBTREE, attrs=["nETBIOSName"])
        assert len(res) > 0
        for x in res:
            if "nETBIOSName" in x.keys():
                return x["nETBIOSName"][0]

    def object_exists(self, object_dn):
        res = None
        try:
            res = self.ldb.search(base=object_dn, scope=SCOPE_BASE)
        except LdbError as e:
            (enum, estr) = e.args
            if enum == ERR_NO_SUCH_OBJECT:
                return False
            raise
        return len(res) == 1

    def delete_force(self, object_dn):
        try:
            self.ldb.delete(object_dn)
        except Ldb.LdbError as e:
            assert "No such object" in str(e)

    def get_attribute_name(self, key):
        """ Returns the real attribute name
            It resolved ranged results e.g. member;range=0-1499
        """

        r = re.compile("^([^;]+);range=(\d+)-(\d+|\*)$")

        m = r.match(key)
        if m is None:
            return key

        return m.group(1)

    def get_attribute_values(self, object_dn, key, vals):
        """ Returns list with all attribute values
            It resolved ranged results e.g. member;range=0-1499
        """

        r = re.compile("^([^;]+);range=(\d+)-(\d+|\*)$")

        m = r.match(key)
        if m is None:
            # no range, just return the values
            return vals

        attr = m.group(1)
        hi = int(m.group(3))

        # get additional values in a loop
        # until we get a response with '*' at the end
        while True:

            n = "%s;range=%d-*" % (attr, hi + 1)
            res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=[n])
            assert len(res) == 1
            res = dict(res[0])
            del res["dn"]

            fm = None
            fvals = None

            for key in res.keys():
                m = r.match(key)

                if m is None:
                    continue

                if m.group(1) != attr:
                    continue

                fm = m
                fvals = list(res[key])
                break

            if fm is None:
                break

            vals.extend(fvals)
            if fm.group(3) == "*":
                # if we got "*" we're done
                break

            assert int(fm.group(2)) == hi + 1
            hi = int(fm.group(3))

        return vals

    def get_attributes(self, object_dn):
        """ Returns dict with all default visible attributes
        """
        res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=["*"])
        assert len(res) == 1
        res = dict(res[0])
        # 'Dn' element is not iterable and we have it as 'distinguishedName'
        del res["dn"]
        for key in res.keys():
            vals = list(res[key])
            del res[key]
            name = self.get_attribute_name(key)
            res[name] = self.get_attribute_values(object_dn, key, vals)

        return res

    def get_descriptor_sddl(self, object_dn):
        res = self.ldb.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"])
        desc = res[0]["nTSecurityDescriptor"][0]
        desc = ndr_unpack(security.descriptor, desc)
        return desc.as_sddl(self.domain_sid)

    def guid_as_string(self, guid_blob):
        """ Translate binary representation of schemaIDGUID to standard string representation.
            @gid_blob: binary schemaIDGUID
        """
        blob = "%s" % guid_blob
        stops = [4, 2, 2, 2, 6]
        index = 0
        res = ""
        x = 0
        while x < len(stops):
            tmp = ""
            y = 0
            while y < stops[x]:
                c = hex(ord(blob[index])).replace("0x", "")
                c = [None, "0" + c, c][len(c)]
                if 2 * index < len(blob):
                    tmp = c + tmp
                else:
                    tmp += c
                index += 1
                y += 1
            res += tmp + " "
            x += 1
        assert index == len(blob)
        return res.strip().replace(" ", "-")

    def get_sid_map(self):
        """ Build dictionary that maps GUID to 'name' attribute found in Schema or Extended-Rights.
        """
        self.sid_map = {}
        res = self.ldb.search(base=self.base_dn,
                              expression="(objectSid=*)", scope=SCOPE_SUBTREE, attrs=["objectSid", "sAMAccountName"])
        for item in res:
            try:
                self.sid_map["%s" % ndr_unpack(security.dom_sid, item["objectSid"][0])] = item["sAMAccountName"][0]
            except KeyError:
                pass