[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Mon Feb 19 22:48:02 UTC 2018


The branch, master has been updated
       via  7573b2a tests: Add tests for parsing LDAPv3 and LDAPv2 filter strings
       via  654b767 s3:tldap: Comment code for to LDAP escaping version
       via  c96dc78 s3:tldap: Fix parsing LDAPv2 escaped strings
       via  9c9c275 python/tests/sites: ensure we can't manipulate subnets as non-admin
       via  7b45dc6 subnet: Avoid a segfault when renaming subnet objects
      from  d35a22c Fix incorrect `ldbsearch` invocation

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


- Log -----------------------------------------------------------------
commit 7573b2a960c5bd32ac6d42b10bb46329ff7fa7b7
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Feb 19 12:08:26 2018 +0100

    tests: Add tests for parsing LDAPv3 and LDAPv2 filter strings
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Mon Feb 19 23:47:08 CET 2018 on sn-devel-144

commit 654b76739a72b8ecdf0542c0b9a566b82dcfb1e1
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Feb 19 12:29:55 2018 +0100

    s3:tldap: Comment code for to LDAP escaping version
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c96dc78aa680d3a1c1d53ea9b18a966025a93e16
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Jul 26 17:48:34 2017 +0200

    s3:tldap: Fix parsing LDAPv2 escaped strings
    
    Yes, this is outdated, but the missing 'break' produces a compiler
    warning.
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Simo Sorce <idra at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9c9c2754a950d6cd411d490fa7fb9fad5b194a01
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Feb 15 15:08:03 2018 +1300

    python/tests/sites: ensure we can't manipulate subnets as non-admin
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13031
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7b45dc6841ff534e7a0eb481aa4f4149a716824f
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Sep 20 14:55:11 2017 +1200

    subnet: Avoid a segfault when renaming subnet objects
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13031
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 python/samba/subnets.py                 |  33 ++++++++
 selftest/tests.py                       |   3 +
 source3/lib/test_tldap.c                |  62 +++++++++++++++
 source3/lib/tldap.c                     |   4 +
 source3/wscript_build                   |  10 +++
 source4/dsdb/samdb/ldb_modules/samldb.c |   8 +-
 source4/dsdb/tests/python/sites.py      | 133 +++++++++++++++++++++++++++++++-
 7 files changed, 248 insertions(+), 5 deletions(-)
 create mode 100644 source3/lib/test_tldap.c


Changeset truncated at 500 lines:

diff --git a/python/samba/subnets.py b/python/samba/subnets.py
index e859f06..72eeb0f 100644
--- a/python/samba/subnets.py
+++ b/python/samba/subnets.py
@@ -127,6 +127,39 @@ def delete_subnet(samdb, configDn, subnet_name):
 
     samdb.delete(dnsubnet)
 
+def rename_subnet(samdb, configDn, subnet_name, new_name):
+    """Rename a subnet.
+
+    :param samdb: A samdb connection
+    :param configDn: The DN of the configuration partition
+    :param subnet_name: Name of the subnet to rename
+    :param new_name: New name for the subnet
+    :return: None
+    :raise SubnetNotFound: if the subnet to be renamed does not exist.
+    :raise SubnetExists: if the subnet to be created already exists.
+    """
+    dnsubnet = ldb.Dn(samdb, "CN=Subnets,CN=Sites")
+    if dnsubnet.add_base(configDn) == False:
+        raise SubnetException("dnsubnet.add_base() failed")
+    if dnsubnet.add_child("CN=X") == False:
+        raise SubnetException("dnsubnet.add_child() failed")
+    dnsubnet.set_component(0, "CN", subnet_name)
+
+    newdnsubnet = ldb.Dn(samdb, str(dnsubnet))
+    newdnsubnet.set_component(0, "CN", new_name)
+    try:
+        samdb.rename(dnsubnet, newdnsubnet)
+    except LdbError as (enum, estr):
+        if enum == ldb.ERR_NO_SUCH_OBJECT:
+            raise SubnetNotFound('Subnet %s does not exist' % subnet)
+        elif enum == ldb.ERR_ENTRY_ALREADY_EXISTS:
+            raise SubnetAlreadyExists('A subnet with the CIDR %s already exists'
+                                      % new_name)
+        elif enum == ldb.ERR_INVALID_DN_SYNTAX:
+            raise SubnetInvalid("%s is not a valid subnet: %s" % (new_name,
+                                                                  estr))
+        else:
+            raise
 
 def set_subnet_site(samdb, configDn, subnet_name, site_name):
     """Assign a subnet to a site.
diff --git a/selftest/tests.py b/selftest/tests.py
index ec48b03..be1be45 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -180,3 +180,6 @@ if with_cmocka:
 
     plantestsuite("samba.unittests.smb1cli_session", "none",
                   [os.path.join(bindir(), "default/libcli/smb/test_smb1cli_session")])
+
+    plantestsuite("samba.unittests.tldap", "none",
+                  [os.path.join(bindir(), "default/source3/test_tldap")])
diff --git a/source3/lib/test_tldap.c b/source3/lib/test_tldap.c
new file mode 100644
index 0000000..a6c2f21
--- /dev/null
+++ b/source3/lib/test_tldap.c
@@ -0,0 +1,62 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Test suite for ldap client
+ *
+ * Copyright (C) 2018      Andreas Schneider <asn at samba.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "source3/lib/tldap.c"
+
+static void test_tldap_unescape_ldapv3(void **state)
+{
+	const char *unescaped_dn = "(&(objectclass=group)(cn=Samba*))";
+	char dn[] = "\\28&\\28objectclass=group\\29\\28cn=Samba\\2a\\29\\29";
+	size_t dnlen = sizeof(dn);
+	bool ok;
+
+	ok = tldap_unescape_inplace(dn, &dnlen);
+	assert_true(ok);
+
+	assert_string_equal(dn, unescaped_dn);
+}
+
+static void test_tldap_unescape_ldapv2(void **state)
+{
+	const char *unescaped_dn = "(&(objectclass=group)(cn=Samba*))";
+	char dn[] = "\\(&\\(objectclass=group\\)\\(cn=Samba\\*\\)\\)";
+	size_t dnlen = sizeof(dn);
+	bool ok;
+
+	ok = tldap_unescape_inplace(dn, &dnlen);
+	assert_true(ok);
+
+	assert_string_equal(dn, unescaped_dn);
+}
+
+int main(void) {
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(test_tldap_unescape_ldapv3),
+		cmocka_unit_test(test_tldap_unescape_ldapv2)
+	};
+
+	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+	return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c
index 40064fd..205a9cf 100644
--- a/source3/lib/tldap.c
+++ b/source3/lib/tldap.c
@@ -1280,6 +1280,7 @@ static bool tldap_unescape_inplace(char *value, size_t *val_len)
 			}
 			i++;
 
+			/* LDAPv3 escaped */
 			c = tldap_hex2char(&value[i]);
 			if (c >= 0 && c < 256) {
 				value[p] = c;
@@ -1288,6 +1289,7 @@ static bool tldap_unescape_inplace(char *value, size_t *val_len)
 				break;
 			}
 
+			/* LDAPv2 escaped */
 			switch (value[i]) {
 			case '(':
 			case ')':
@@ -1295,6 +1297,8 @@ static bool tldap_unescape_inplace(char *value, size_t *val_len)
 			case '\\':
 				value[p] = value[i];
 				p++;
+
+				break;
 			default:
 				/* invalid */
 				return false;
diff --git a/source3/wscript_build b/source3/wscript_build
index 76c5d6e..d5ac7a2 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -106,6 +106,16 @@ bld.SAMBA3_SUBSYSTEM('TLDAP',
                          samba3util
                          ''')
 
+bld.SAMBA3_BINARY('test_tldap',
+                  source='lib/test_tldap.c',
+                  deps='''
+                       asn1util
+                       LIBTSOCKET
+                       samba3util
+                       smbconf
+                       cmocka
+                       ''')
+
 # libpdb.so should not expose internal symbols that are only usable
 # to the statically linked modules that are merged into libpdb.
 # Note that we always filter these symbols out in libpdb, even
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 971048d..3e429e1 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -3351,13 +3351,13 @@ static int verify_cidr(const char *cidr)
 }
 
 
-static int samldb_verify_subnet(struct samldb_ctx *ac)
+static int samldb_verify_subnet(struct samldb_ctx *ac, struct ldb_dn *dn)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
 	const char *cidr = NULL;
 	const struct ldb_val *rdn_value = NULL;
 
-	rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
+	rdn_value = ldb_dn_get_rdn_val(dn);
 	if (rdn_value == NULL) {
 		ldb_set_errstring(ldb, "samldb: ldb_dn_get_rdn_val "
 				  "failed");
@@ -3588,7 +3588,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
 
 	if (samdb_find_attribute(ldb, ac->msg,
 				 "objectclass", "subnet") != NULL) {
-		ret = samldb_verify_subnet(ac);
+		ret = samldb_verify_subnet(ac, ac->msg->dn);
 		if (ret != LDB_SUCCESS) {
 			talloc_free(ac);
 			return ret;
@@ -3991,7 +3991,7 @@ static int check_rename_constraints(struct ldb_message *msg,
 
 	/* subnet objects */
 	if (samdb_find_attribute(ldb, msg, "objectclass", "subnet") != NULL) {
-		ret = samldb_verify_subnet(ac);
+		ret = samldb_verify_subnet(ac, newdn);
 		if (ret != LDB_SUCCESS) {
 			talloc_free(ac);
 			return ret;
diff --git a/source4/dsdb/tests/python/sites.py b/source4/dsdb/tests/python/sites.py
index a24f9b5..3bb53d9 100755
--- a/source4/dsdb/tests/python/sites.py
+++ b/source4/dsdb/tests/python/sites.py
@@ -30,9 +30,12 @@ from samba import sites
 from samba import subnets
 from samba.auth import system_session
 from samba.samdb import SamDB
+from samba import gensec
+from samba.credentials import Credentials, DONT_USE_KERBEROS
 import samba.tests
+from samba.tests import delete_force
 from samba.dcerpc import security
-from ldb import SCOPE_SUBTREE
+from ldb import SCOPE_SUBTREE, LdbError, ERR_INSUFFICIENT_ACCESS_RIGHTS
 
 parser = optparse.OptionParser("sites.py [options] <host>")
 sambaopts = options.SambaOptions(parser)
@@ -183,6 +186,134 @@ class SimpleSubnetTests(SitesBaseTests):
         self.assertRaises(subnets.SubnetNotFound,
                           subnets.delete_subnet, self.ldb, basedn, cidr)
 
+    def get_user_and_ldb(self, username, password, hostname=ldaphost):
+        """Get a connection for a temporarily user that will vanish as soon as
+        the test is over."""
+        user = self.ldb.newuser(username, password)
+        creds_tmp = Credentials()
+        creds_tmp.set_username(username)
+        creds_tmp.set_password(password)
+        creds_tmp.set_domain(creds.get_domain())
+        creds_tmp.set_realm(creds.get_realm())
+        creds_tmp.set_workstation(creds.get_workstation())
+        creds_tmp.set_gensec_features(creds_tmp.get_gensec_features()
+                                      | gensec.FEATURE_SEAL)
+        creds_tmp.set_kerberos_state(DONT_USE_KERBEROS)
+        ldb_target = SamDB(url=hostname, credentials=creds_tmp, lp=lp)
+        self.addCleanup(delete_force, self.ldb, self.get_user_dn(username))
+        return (user, ldb_target)
+
+    def test_rename_delete_good_subnet_to_good_subnet_other_user(self):
+        """Make sure that we can't rename or delete subnets when we aren't
+        admin."""
+        basedn = self.ldb.get_config_basedn()
+        cidr = "10.16.0.0/24"
+        new_cidr = "10.16.1.0/24"
+        subnets.create_subnet(self.ldb, basedn, cidr, self.sitename)
+        user, non_admin_ldb = self.get_user_and_ldb("notadmin", "samba123@")
+        try:
+            subnets.rename_subnet(non_admin_ldb, basedn, cidr, new_cidr)
+        except LdbError as e:
+            self.assertEqual(e.args[0], ERR_INSUFFICIENT_ACCESS_RIGHTS,
+                             ("subnet rename by non-admin failed "
+                              "in the wrong way: %s" % e))
+        else:
+            self.fail("subnet rename by non-admin succeeded: %s" % e)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % cidr)
+
+        self.assertEqual(len(ret), 1, ('Subnet %s destroyed or renamed '
+                                       'by non-admin' % cidr))
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression=('(&(objectclass=subnet)(cn=%s))'
+                                          % new_cidr))
+
+        self.assertEqual(len(ret), 0,
+                         'New subnet %s created by non-admin' % cidr)
+
+        try:
+            subnets.delete_subnet(non_admin_ldb, basedn, cidr)
+        except LdbError as e:
+            self.assertEqual(e.args[0], ERR_INSUFFICIENT_ACCESS_RIGHTS,
+                             ("subnet delete by non-admin failed "
+                              "in the wrong way: %s" % e))
+        else:
+            self.fail("subnet delete by non-admin succeeded: %s" % e)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % cidr)
+
+        self.assertEqual(len(ret), 1, 'Subnet %s deleted non-admin' % cidr)
+
+        subnets.delete_subnet(self.ldb, basedn, cidr)
+
+    def test_create_good_subnet_other_user(self):
+        """Make sure that we can't create subnets when we aren't admin."""
+        basedn = self.ldb.get_config_basedn()
+        cidr = "10.16.0.0/24"
+        user, non_admin_ldb = self.get_user_and_ldb("notadmin", "samba123@")
+        try:
+            subnets.create_subnet(non_admin_ldb, basedn, cidr, self.sitename)
+        except LdbError as e:
+            self.assertEqual(e.args[0], ERR_INSUFFICIENT_ACCESS_RIGHTS,
+                             ("subnet create by non-admin failed "
+                              "in the wrong way: %s" % e))
+        else:
+            subnets.delete_subnet(self.ldb, basedn, cidr)
+            self.fail("subnet create by non-admin succeeded: %s")
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % cidr)
+
+        self.assertEqual(len(ret), 0, 'New subnet %s created by non-admin' % cidr)
+
+    def test_rename_good_subnet_to_good_subnet(self):
+        """Make sure that we can rename subnets"""
+        basedn = self.ldb.get_config_basedn()
+        cidr = "10.16.0.0/24"
+        new_cidr = "10.16.1.0/24"
+
+        subnets.create_subnet(self.ldb, basedn, cidr, self.sitename)
+
+        subnets.rename_subnet(self.ldb, basedn, cidr, new_cidr)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % new_cidr)
+
+        self.assertEqual(len(ret), 1, 'Failed to rename subnet %s' % cidr)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % cidr)
+
+        self.assertEqual(len(ret), 0, 'Failed to remove old subnet during rename %s' % cidr)
+
+        subnets.delete_subnet(self.ldb, basedn, new_cidr)
+
+    def test_rename_good_subnet_to_bad_subnet(self):
+        """Make sure that the CIDR checking runs during rename"""
+        basedn = self.ldb.get_config_basedn()
+        cidr = "10.17.0.0/24"
+        bad_cidr = "10.11.12.0/14"
+
+        subnets.create_subnet(self.ldb, basedn, cidr, self.sitename)
+
+        self.assertRaises(subnets.SubnetInvalid, subnets.rename_subnet,
+                          self.ldb, basedn, cidr, bad_cidr)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % bad_cidr)
+
+        self.assertEqual(len(ret), 0, 'Failed to rename subnet %s' % cidr)
+
+        ret = self.ldb.search(base=basedn, scope=SCOPE_SUBTREE,
+                              expression='(&(objectclass=subnet)(cn=%s))' % cidr)
+
+        self.assertEqual(len(ret), 1, 'Failed to remove old subnet during rename %s' % cidr)
+
+        subnets.delete_subnet(self.ldb, basedn, cidr)
+
     def test_create_bad_ranges(self):
         """These CIDR ranges all have something wrong with them, and they
         should all fail."""


-- 
Samba Shared Repository



More information about the samba-cvs mailing list