[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Dec 10 03:57:03 UTC 2017


The branch, master has been updated
       via  2ab9847 Added smbc_SetLogCallback which lets third party code to capture libsmbclient logs
       via  d2b9f18 tests: make password valid in openldap provision test
       via  698d28e samba-tool: validate password early in `domain provision`
       via  704bbae source4 dsdb: Allow duplicate non local objectSIDs
       via  4d5da6c source4 dsdb modules: Add new module "unique_object_sids"
       via  2599f29 ldb ldb_index: Add an attriubute flag to require a unique value.
       via  0733286 tests dsdb: Add tests for optionally unique objectSID's
      from  b3d5072 s3:glock: Move sanity check in g_lock_parse()

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


- Log -----------------------------------------------------------------
commit 2ab9847f54da80352e6ce1f4281649a86558a822
Author: Puran Chand <pchand at vmware.com>
Date:   Wed Nov 29 13:41:05 2017 +0530

    Added smbc_SetLogCallback which lets third party code to capture libsmbclient logs
    
    Signed-off-by: Puran Chand <pchand at vmware.com>
    Reviewed-by: Garming Sam <garming at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Sun Dec 10 04:56:23 CET 2017 on sn-devel-144

commit d2b9f18a0d16e1f03a19229bed6e8ffa02744e63
Author: Jamie McClymont <jamiemcclymont at catalyst.net.nz>
Date:   Tue Dec 5 10:35:59 2017 +1300

    tests: make password valid in openldap provision test
    
    Test was using an invalid password, which causes test failure with early
    password validation patch
    
    Signed-off-by: Jamie McClymont <jamiemcclymont at catalyst.net.nz>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 698d28ee8cf4ff8258f2e6fe9b88d81f842584aa
Author: Jamie McClymont <jamiemcclymont at catalyst.net.nz>
Date:   Tue Nov 28 15:45:30 2017 +1300

    samba-tool: validate password early in `domain provision`
    
    Checks password against default quality and length standards when it is entered,
    allowing a second chance to enter one (if interactive), rather than running
    through the provisioning process and bailing on an exception
    
    Includes unit tests for the newly-added python wrapper of check_password_quality
    plus black-box tests for the checks in samba-tool.
    
    Breaks an openldap test which uses an invalid password.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9710
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12235
    
    Signed-off-by: Jamie McClymont <jamiemcclymont at catalyst.net.nz>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 704bbae25c07c08c051a66ae0a83fb5abda373f1
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Mon Nov 27 11:11:19 2017 +1300

    source4 dsdb: Allow duplicate non local objectSIDs
    
    Remove the unique constraint on the objectSID index, and enable the
    unique_object_sids module.
    
    This allows duplicate objectSIDs on foreign security principals, and
    disallows duplicates for local objectSIDs
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13004
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>

commit 4d5da6c72bd60064459170af1db00c7367f87fbe
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Mon Nov 27 11:09:49 2017 +1300

    source4 dsdb modules: Add new module "unique_object_sids"
    
    New module that sets the LDB_FLAG_INTERNAL_UNIQUE_VALUE on all local
    objectSIDS and ensure it is cleared for any foreign security principals.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13004
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>

commit 2599f291447ef2ec1c8a394dbe838126d43204c4
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue Nov 21 07:35:11 2017 +1300

    ldb ldb_index: Add an attriubute flag to require a unique value.
    
    Add attribute flag LDB_FLAG_INTERNAL_UNIQUE_VALUE, to request that the
    added attribute is unique on the index.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13004
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>

commit 073328673f0fb0a9797290f922ca8230e3f5fdf3
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Mon Nov 27 10:45:37 2017 +1300

    tests dsdb: Add tests for optionally unique objectSID's
    
    It is possible for foreign security principals to have duplicate object
    sids, this can be the result of:
     a replication race condition generating conflict resolution objects
     or the foreign security principal being deleted and then re-added on a
     join.
    
    Rather than remove unique check on all objectSIDs we wish to allow
    duplicate objectSIDs for foreign security principals.  But enforce the
    unique constraint for local objects.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13004
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>

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

Summary of changes:
 lib/ldb/include/ldb_module.h                       |   9 +
 lib/ldb/ldb_tdb/ldb_index.c                        |   3 +-
 lib/ldb/tests/ldb_mod_op_test.c                    | 326 +++++++++++++
 python/pyglue.c                                    |  17 +
 python/samba/__init__.py                           |   1 +
 python/samba/netcmd/domain.py                      |  28 +-
 python/samba/provision/__init__.py                 |   5 +-
 python/samba/tests/dsdb.py                         |  80 +++-
 python/samba/tests/password_quality.py             |  51 ++
 .../tests/samba_tool/provision_password_check.py   |  56 +++
 selftest/tests.py                                  |   1 +
 source3/include/libsmbclient.h                     |  13 +
 .../{smbclient-0.3.0.sigs => smbclient-0.3.1.sigs} |   1 +
 source3/libsmb/libsmb_setget.c                     |   8 +
 source3/libsmb/wscript                             |   2 +-
 source4/dsdb/samdb/ldb_modules/samba_dsdb.c        |   1 +
 .../ldb_modules/tests/test_unique_object_sids.c    | 513 +++++++++++++++++++++
 .../dsdb/samdb/ldb_modules/unique_object_sids.c    | 262 +++++++++++
 source4/dsdb/samdb/ldb_modules/wscript_build       |  11 +
 .../dsdb/samdb/ldb_modules/wscript_build_server    |   9 +
 source4/dsdb/schema/schema_init.c                  |   2 +-
 source4/selftest/tests.py                          |   6 +
 source4/setup/provision_basedn_modify.ldif         |   2 +-
 source4/setup/tests/blackbox_provision-backend.sh  |   2 +-
 source4/torture/libsmbclient/libsmbclient.c        |  22 +
 25 files changed, 1420 insertions(+), 11 deletions(-)
 create mode 100644 python/samba/tests/password_quality.py
 create mode 100644 python/samba/tests/samba_tool/provision_password_check.py
 copy source3/libsmb/ABI/{smbclient-0.3.0.sigs => smbclient-0.3.1.sigs} (99%)
 create mode 100644 source4/dsdb/samdb/ldb_modules/tests/test_unique_object_sids.c
 create mode 100644 source4/dsdb/samdb/ldb_modules/unique_object_sids.c


Changeset truncated at 500 lines:

diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index ffa6c2e..fd88c62 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -87,6 +87,15 @@ struct ldb_module;
 /* force single value checking on this attribute */
 #define LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK 0x80
 
+/*
+ * ensure that this value is unique on an index
+ * (despite the index not otherwise being configured as UNIQUE).
+ * For example, all words starting with 'a' must be unique, but duplicates of
+ * words starting with b are allowed.  This is specifically for Samba's
+ * objectSid index which is unique in the primary domain only.
+ */
+#define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100
+
 /* an extended match rule that always fails to match */
 #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1"
 
diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c
index c71e866..0afeae5 100644
--- a/lib/ldb/ldb_tdb/ldb_index.c
+++ b/lib/ldb/ldb_tdb/ldb_index.c
@@ -1761,7 +1761,8 @@ static int ltdb_index_add1(struct ldb_module *module,
 	 */
 	if (list->count > 0 &&
 	    ((a != NULL
-	      && (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX)) ||
+	      && (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX ||
+		 (el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX))) ||
 	     ldb_attr_cmp(el->name, LTDB_IDXDN) == 0)) {
 		/*
 		 * We do not want to print info about a possibly
diff --git a/lib/ldb/tests/ldb_mod_op_test.c b/lib/ldb/tests/ldb_mod_op_test.c
index 48ad20c..cf2288c 100644
--- a/lib/ldb/tests/ldb_mod_op_test.c
+++ b/lib/ldb/tests/ldb_mod_op_test.c
@@ -3009,7 +3009,317 @@ static void test_read_only(void **state)
 	TALLOC_FREE(tmp_ctx);
 }
 
+static bool unique_values = false;
+
+static int unique_index_test_module_add(
+	struct ldb_module *module,
+	struct ldb_request *req)
+{
+	if (unique_values) {
+		struct ldb_message *msg = discard_const(req->op.add.message);
+		struct ldb_message_element *el = NULL;
+		el = ldb_msg_find_element(msg, "cn");
+		if (el != NULL) {
+			el->flags |= LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX;
+		}
+	}
+
+	return ldb_next_request(module, req);
+}
+
+static int unique_index_test_module_init(struct ldb_module *module)
+{
+	return ldb_next_init(module);
+}
+
+static const struct ldb_module_ops ldb_unique_index_test_module_ops = {
+	.name		= "unique_index_test",
+	.init_context	= unique_index_test_module_init,
+	.add		= unique_index_test_module_add,
+};
+
+static int ldb_unique_index_test_setup(void **state)
+{
+	int ret;
+	struct ldb_ldif *ldif;
+	struct ldbtest_ctx *ldb_test_ctx;
+	const char *attrs_ldif =  \
+		"dn: @ATTRIBUTES\n"
+		"cn: UNIQUE_INDEX\n"
+		"\n";
+	const char *index_ldif =  \
+		"dn: @INDEXLIST\n"
+		"@IDXATTR: cn\n"
+		"\n";
+	const char *options[] = {"modules:unique_index_test"};
+
+
+	ret = ldb_register_module(&ldb_unique_index_test_module_ops);
+	assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS);
+	ldbtest_noconn_setup((void **) &ldb_test_ctx);
+
+
+	ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options);
+	assert_int_equal(ret, 0);
+
+	while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) {
+		ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
+		ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+        unique_values = true;
+
+	*state = ldb_test_ctx;
+	return 0;
+}
+
+static int ldb_unique_index_test_teardown(void **state)
+{
+	int ret;
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+	struct ldb_dn *del_dn;
+
+	del_dn = ldb_dn_new_fmt(ldb_test_ctx,
+				ldb_test_ctx->ldb,
+				"@INDEXLIST");
+	assert_non_null(del_dn);
+
+	ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
+	if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	assert_dn_doesnt_exist(ldb_test_ctx,
+			       "@INDEXLIST");
+
+	TALLOC_FREE(del_dn);
+
+	del_dn = ldb_dn_new_fmt(ldb_test_ctx,
+				ldb_test_ctx->ldb,
+				"@ATTRIBUTES");
+	assert_non_null(del_dn);
+
+	ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
+	if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	assert_dn_doesnt_exist(ldb_test_ctx,
+			       "@ATTRIBUTES");
+
+	ldbtest_teardown((void **) &ldb_test_ctx);
+	return 0;
+}
+
+
+static void test_ldb_add_unique_value_to_unique_index(void **state)
+{
+	int ret;
+	struct ldb_message *msg;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+	msg = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg);
+
+	msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test");
+	assert_non_null(msg->dn);
+
+	ret = ldb_msg_add_string(msg, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	talloc_free(tmp_ctx);
+}
+
+static int ldb_non_unique_index_test_setup(void **state)
+{
+	int ret;
+	struct ldb_ldif *ldif;
+	struct ldbtest_ctx *ldb_test_ctx;
+	const char *index_ldif =  \
+		"dn: @INDEXLIST\n"
+		"@IDXATTR: cn\n"
+		"\n";
+	const char *options[] = {"modules:unique_index_test"};
 
+
+	ret = ldb_register_module(&ldb_unique_index_test_module_ops);
+	assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS);
+	ldbtest_noconn_setup((void **) &ldb_test_ctx);
+
+
+	ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options);
+	assert_int_equal(ret, 0);
+
+	while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
+		ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+        unique_values = true;
+
+	*state = ldb_test_ctx;
+	return 0;
+}
+
+static int ldb_non_unique_index_test_teardown(void **state)
+{
+	int ret;
+	struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
+			struct ldbtest_ctx);
+	struct ldb_dn *del_dn;
+
+	del_dn = ldb_dn_new_fmt(ldb_test_ctx,
+				ldb_test_ctx->ldb,
+				"@INDEXLIST");
+	assert_non_null(del_dn);
+
+	ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
+	if (ret != LDB_ERR_NO_SUCH_OBJECT) {
+		assert_int_equal(ret, LDB_SUCCESS);
+	}
+
+	assert_dn_doesnt_exist(ldb_test_ctx,
+			       "@INDEXLIST");
+
+	TALLOC_FREE(del_dn);
+
+	ldbtest_teardown((void **) &ldb_test_ctx);
+	return 0;
+}
+
+static void test_ldb_add_duplicate_value_to_unique_index(void **state)
+{
+	int ret;
+	struct ldb_message *msg01;
+	struct ldb_message *msg02;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+	msg01 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
+	assert_non_null(msg01->dn);
+
+	ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg01);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	msg02 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
+	assert_non_null(msg02->dn);
+
+	ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg02);
+	assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
+	talloc_free(tmp_ctx);
+}
+
+static void test_ldb_add_to_index_duplicates_allowed(void **state)
+{
+	int ret;
+	struct ldb_message *msg01;
+	struct ldb_message *msg02;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+
+        unique_values = false;
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+
+	msg01 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
+	assert_non_null(msg01->dn);
+
+	ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg01);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	msg02 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
+	assert_non_null(msg02->dn);
+
+	ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg02);
+	assert_int_equal(ret, LDB_SUCCESS);
+	talloc_free(tmp_ctx);
+}
+
+static void test_ldb_add_to_index_unique_values_required(void **state)
+{
+	int ret;
+	struct ldb_message *msg01;
+	struct ldb_message *msg02;
+	struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+							struct ldbtest_ctx);
+	TALLOC_CTX *tmp_ctx;
+
+        unique_values = true;
+
+	tmp_ctx = talloc_new(test_ctx);
+	assert_non_null(tmp_ctx);
+
+
+	msg01 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
+	assert_non_null(msg01->dn);
+
+	ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg01);
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	msg02 = ldb_msg_new(tmp_ctx);
+	assert_non_null(msg01);
+
+	msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
+	assert_non_null(msg02->dn);
+
+	ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
+	assert_int_equal(ret, LDB_SUCCESS);
+
+	ret = ldb_add(test_ctx->ldb, msg02);
+	assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
+	talloc_free(tmp_ctx);
+}
 int main(int argc, const char **argv)
 {
 	const struct CMUnitTest tests[] = {
@@ -3133,6 +3443,22 @@ int main(int argc, const char **argv)
 		cmocka_unit_test_setup_teardown(test_read_only,
 						ldb_read_only_setup,
 						ldb_read_only_teardown),
+		cmocka_unit_test_setup_teardown(
+			test_ldb_add_unique_value_to_unique_index,
+			ldb_unique_index_test_setup,
+			ldb_unique_index_test_teardown),
+		cmocka_unit_test_setup_teardown(
+			test_ldb_add_duplicate_value_to_unique_index,
+			ldb_unique_index_test_setup,
+			ldb_unique_index_test_teardown),
+		cmocka_unit_test_setup_teardown(
+			test_ldb_add_to_index_duplicates_allowed,
+			ldb_non_unique_index_test_setup,
+			ldb_non_unique_index_test_teardown),
+		cmocka_unit_test_setup_teardown(
+			test_ldb_add_to_index_unique_values_required,
+			ldb_non_unique_index_test_setup,
+			ldb_non_unique_index_test_teardown),
 	};
 
 	return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/python/pyglue.c b/python/pyglue.c
index 07cde49..d928b4c 100644
--- a/python/pyglue.c
+++ b/python/pyglue.c
@@ -78,6 +78,17 @@ static PyObject *py_generate_random_machine_password(PyObject *self, PyObject *a
 	return ret;
 }
 
+static PyObject *py_check_password_quality(PyObject *self, PyObject *args)
+{
+	char *pass;
+
+	if (!PyArg_ParseTuple(args, "s", &pass)) {
+		return NULL;
+	}
+
+	return PyBool_FromLong(check_password_quality(pass));
+}
+
 static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
 {
 	time_t t;
@@ -296,6 +307,12 @@ static PyMethodDef py_misc_methods[] = {
 		"(based on random utf16 characters converted to utf8 or "
 		"random ascii characters if 'unix charset' is not 'utf8')"
 		"with a length >= min (at least 14) and <= max (at most 255)." },
+	{ "check_password_quality", (PyCFunction)py_check_password_quality,
+		METH_VARARGS, "check_password_quality(pass) -> bool\n"
+		"Check password quality against Samba's check_password_quality,"
+		"the implementation of Microsoft's rules:"
+		"http://msdn.microsoft.com/en-us/subscriptions/cc786468%28v=ws.10%29.aspx"
+	},
 	{ "unix2nttime", (PyCFunction)py_unix2nttime, METH_VARARGS,
 		"unix2nttime(timestamp) -> nttime" },
 	{ "nttime2unix", (PyCFunction)py_nttime2unix, METH_VARARGS,
diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 6f79b3c..6ba7c99 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -388,6 +388,7 @@ nttime2unix = _glue.nttime2unix
 unix2nttime = _glue.unix2nttime
 generate_random_password = _glue.generate_random_password
 generate_random_machine_password = _glue.generate_random_machine_password
+check_password_quality = _glue.check_password_quality
 strcasecmp_m = _glue.strcasecmp_m
 strstr_m = _glue.strstr_m
 is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built
diff --git a/python/samba/netcmd/domain.py b/python/samba/netcmd/domain.py
index e3a0e49..f54b404 100644
--- a/python/samba/netcmd/domain.py
+++ b/python/samba/netcmd/domain.py
@@ -84,7 +84,8 @@ from samba.dsdb import (
 
 from samba.provision import (
     provision,
-    ProvisioningError
+    ProvisioningError,
+    DEFAULT_MIN_PWD_LENGTH
     )
 
 from samba.provision.common import (
@@ -370,8 +371,9 @@ class cmd_domain_provision(Command):
 
             while True:
                 adminpassplain = getpass("Administrator password: ")
-                if not adminpassplain:
-                    self.errf.write("Invalid administrator password.\n")
+                issue = self._adminpass_issue(adminpassplain)
+                if issue:
+                    self.errf.write("%s.\n" % issue)
                 else:
                     adminpassverify = getpass("Retype password: ")
                     if not adminpassplain == adminpassverify:
@@ -387,7 +389,11 @@ class cmd_domain_provision(Command):
             if domain is None:
                 raise CommandError("No domain set!")
 
-        if not adminpass:
+        if adminpass:
+            issue = self._adminpass_issue(adminpass)
+            if issue:
+                raise CommandError(issue)
+        else:
             self.logger.info("Administrator password will be set randomly!")
 
         if function_level == "2000":
@@ -501,6 +507,20 @@ class cmd_domain_provision(Command):
 
         self.logger.warning("No nameserver found in %s" % RESOLV_CONF)
 
+    def _adminpass_issue(self, adminpass):
+        """Returns error string for a bad administrator password,
+        or None if acceptable"""
+
+        if len(adminpass.decode('utf-8')) < DEFAULT_MIN_PWD_LENGTH:
+            return "Administrator password does not meet the default minimum" \
+                " password length requirement (%d characters)" \
+                % DEFAULT_MIN_PWD_LENGTH
+        elif not samba.check_password_quality(adminpass):
+            return "Administrator password does not meet the default" \
+                " quality standards"
+        else:
+            return None
+
 
 class cmd_domain_dcpromo(Command):
     """Promote an existing domain member or NT4 PDC to an AD DC."""
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index 07c2479..ad14305 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -127,6 +127,8 @@ DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04FB984F9"
 DEFAULTSITE = "Default-First-Site-Name"
 LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN"
 
+DEFAULT_MIN_PWD_LENGTH = 7
+
 
 class ProvisionPaths(object):
 
@@ -1309,7 +1311,8 @@ def fill_samdb(samdb, lp, names, logger, policyguid,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list