[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-154-g5fb6530

Matthias Dieter Wallnöfer mdw at samba.org
Thu Sep 10 07:44:50 MDT 2009


The branch, master has been updated
       via  5fb653029529d8cc30dbeb498f7f6d152d17ce17 (commit)
       via  e3a2a22451b3f2b7294da0e6d1f1f6e6d4a33368 (commit)
       via  67a8a8c9e652d0f1aa5a1c593177bd75bc4af284 (commit)
       via  ebdb9da78e4ab66a633145d668ef4f777120f9c2 (commit)
       via  3cbcaa139ca490b1b457f6a623f1a3680cae9a04 (commit)
       via  4b68cfe15dcb62930ddda8c43d5d52deaa4d6501 (commit)
       via  0206b1d6f979dab29c70ada10153578ce45b774a (commit)
       via  5f6ebc34832d85319bda184955a9e56120340927 (commit)
       via  e71383eed7e012c86c957949ba8d1979219e6b60 (commit)
       via  02c30fee2126241186df2d1e009ac8d9c2b96078 (commit)
       via  aae07390e2b84d8b1d41eb65d31f9621a22a17aa (commit)
      from  27beb7fc7efde5c26917357e6a53e61e4cd7e04a (commit)

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


- Log -----------------------------------------------------------------
commit 5fb653029529d8cc30dbeb498f7f6d152d17ce17
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Mon Sep 7 07:52:37 2009 -0500

    s4:srvsvc: Fix logic on error checking.

commit e3a2a22451b3f2b7294da0e6d1f1f6e6d4a33368
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Tue Sep 8 06:01:18 2009 -0500

    s4:pwsettings: Added blackbox tests.
    
    The added tests include basic validation that the script runs and accepts all
    custom arguments.  The tests also verify changes to the password complexity,
    minimum password length, and minimum password length settings.

commit 67a8a8c9e652d0f1aa5a1c593177bd75bc4af284
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Tue Sep 8 16:01:26 2009 -0500

    testprogs:subunit.sh: Add function for expected failures.
    
    The testit_expect_failure() function is like the testit() function, with
    reversed error detection logic.  This reversal only affects the pass/fail logic
    and logging - the original return code from the command is still returned to the
    calling script.

commit ebdb9da78e4ab66a633145d668ef4f777120f9c2
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Tue Sep 8 02:34:56 2009 -0500

    s4:pwsettings: Show default values in help messages.

commit 3cbcaa139ca490b1b457f6a623f1a3680cae9a04
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Tue Sep 8 02:34:30 2009 -0500

    s4:pwsettings: Add 'default' option for password complexity.

commit 4b68cfe15dcb62930ddda8c43d5d52deaa4d6501
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Mon Sep 7 03:38:33 2009 -0500

    s4:pwsettings: Added validation.
    
    Validate that each field is within its allowed range.  Also validate that the
    maximum password age is greater than the minimum password length (if the maximum
    password age is set).
    
    I could not find these values documented anywhere in the WSPP docs.  I used the
    values shown in the W2K8 GPMC, as it appears that the GPMC actuaally performs
    the validation of values.

commit 0206b1d6f979dab29c70ada10153578ce45b774a
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Mon Sep 7 02:04:55 2009 -0500

    s4:pwsettings: Don't assume a value for pwdProperties.
    
    If we cannot retrieve the value, do not assume a particular value.  The fact
    that we could not retrieve the value indicates a larger problem that we don't
    want to make worse bypossibly clearing bit fields in the pwdProperties
    attribute.

commit 5f6ebc34832d85319bda184955a9e56120340927
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Mon Sep 7 01:47:35 2009 -0500

    s4:pwsettings: Run all updates as a single modify() operation.
    
    This ensures that all changes are made, or none are made.  It also makes it
    possible to do validation as we go and abort in case of an error, while always
    leaving things in a consistent state.

commit e71383eed7e012c86c957949ba8d1979219e6b60
Author: Andrew Kroeger <andrew at id10ts.net>
Date:   Mon Sep 7 01:05:11 2009 -0500

    s4:pwsettings: Added --quiet option.
    
    Also changed all non-error status output to use the message() function, which
    respects the --quiet option.

commit 02c30fee2126241186df2d1e009ac8d9c2b96078
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Thu Sep 10 00:59:50 2009 +0200

    s4:netlogon - Put the "supported encryption types" more back in the "LogonGetDomainInfo" call
    
    They're needed only at the end.

commit aae07390e2b84d8b1d41eb65d31f9621a22a17aa
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Thu Sep 10 00:46:51 2009 +0200

    Revert "s4: Let the "setpassword" script finally use the "samdb_set_password" routine"
    
    This reverts commit fdd62e9699b181a140292689fcd88a559bc26211.
    
    abartlet and I agreed that this isn't the right way to enforce the password
    policies. Sooner or later we've to control them anyway on the directory level.

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

Summary of changes:
 source4/rpc_server/netlogon/dcerpc_netlogon.c |   14 ++--
 source4/rpc_server/srvsvc/dcesrv_srvsvc.c     |   12 ++--
 source4/scripting/python/pyglue.c             |   65 +--------------
 source4/scripting/python/samba/samdb.py       |   14 ++--
 source4/setup/pwsettings                      |  113 ++++++++++++++-----------
 source4/setup/tests/blackbox_setpassword.sh   |    2 +
 testprogs/blackbox/subunit.sh                 |   15 ++++
 testprogs/blackbox/test_passwords.sh          |   28 ++++++
 8 files changed, 130 insertions(+), 133 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index e349df0..4ec6b74 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -1129,9 +1129,9 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 	struct netr_DomainInformation *domain_info;
 	struct netr_LsaPolicyInformation *lsa_policy_info;
 	struct netr_OsVersionInfoEx *os_version;
+	uint32_t default_supported_enc_types =
+		ENC_CRC32|ENC_RSA_MD5|ENC_RC4_HMAC_MD5;
 	int ret1, ret2, i;
-	uint32_t client_supported_enc;
-	uint32_t default_supported_enc = ENC_CRC32|ENC_RSA_MD5|ENC_RC4_HMAC_MD5;
 	NTSTATUS status;
 
 	status = dcesrv_netr_creds_server_step_check(dce_call,
@@ -1178,9 +1178,6 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 							"dNSHostName",
 							NULL);
 
-		client_supported_enc = samdb_search_int64(sam_ctx, mem_ctx, default_supported_enc,
-						       workstation_dn,	"msDS-SupportedEncryptionTypes", 
-						       NULL);
 		/* Gets host informations and put them in our directory */
 		new_msg = ldb_msg_new(mem_ctx);
 		NT_STATUS_HAVE_NO_MEMORY(new_msg);
@@ -1314,6 +1311,12 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 			&domain_info->trusted_domains[i], true, true);
 		NT_STATUS_NOT_OK_RETURN(status);
 
+		/* Sets the supported encryption types */
+		domain_info->supported_enc_types = samdb_search_uint(
+			sam_ctx, mem_ctx,
+			default_supported_enc_types, workstation_dn,
+			"msDS-SupportedEncryptionTypes", NULL);
+
 		/* Other host domain informations */
 
 		lsa_policy_info = talloc(mem_ctx,
@@ -1326,7 +1329,6 @@ static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_cal
 		domain_info->dns_hostname.string = old_dns_hostname;
 		domain_info->workstation_flags =
 			r->in.query->workstation_info->workstation_flags;
-		domain_info->supported_enc_types = client_supported_enc;
 
 		r->out.info->domain_info = domain_info;
 	break;
diff --git a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c
index f33c49a..be804ba 100644
--- a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c
+++ b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c
@@ -1246,7 +1246,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					0,
 					0,
 					NULL);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
@@ -1263,7 +1263,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					0,
 					0,
 					NULL);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
@@ -1280,7 +1280,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					r->in.info->info2->max_users,
 					0,
 					NULL);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
@@ -1297,7 +1297,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					0,
 					r->in.info->info501->csc_policy,
 					NULL);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
@@ -1314,7 +1314,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					r->in.info->info502->max_users,
 					0,
 					r->in.info->info502->sd_buf.sd);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
@@ -1331,7 +1331,7 @@ static WERROR dcesrv_srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call,
 					0,
 					0,
 					NULL);
-		if (W_ERROR_EQUAL(status, WERR_OK)) {
+		if (!W_ERROR_EQUAL(status, WERR_OK)) {
 			return status;
 		}
 		break;
diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c
index 3e6233b..42c04c1 100644
--- a/source4/scripting/python/pyglue.c
+++ b/source4/scripting/python/pyglue.c
@@ -220,69 +220,13 @@ static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
 	if (!sid) {
 		PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
 		return NULL;
-	}
-
+	} 
 	retstr = dom_sid_string(NULL, sid);
 	ret = PyString_FromString(retstr);
 	talloc_free(retstr);
-
 	return ret;
 }
 
-static PyObject *py_samdb_set_password(PyLdbObject *self, PyObject *args,
-	PyObject *kwargs)
-{
-	PyObject *py_sam, *py_user_dn, *py_dom_dn, *py_mod, *py_user_change;
-	char *new_password;
-	bool user_change;
-	DATA_BLOB new_pwd_blob;
-	struct ldb_context *sam_ctx;
-	struct ldb_dn *user_dn, *dom_dn;
-	struct ldb_message *mod;
-	TALLOC_CTX *mem_ctx;
-	NTSTATUS status;
-	const char * const kwnames[] = { "samdb", "user_dn", "dom_dn", "mod",
-		"new_password", "user_change", NULL };
-
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOOOsO",
-		  discard_const_p(char *, kwnames),
-		  &py_sam, &py_user_dn, &py_dom_dn, &py_mod, &new_password,
-		  &py_user_change))
-		return NULL;
-
-	sam_ctx = PyLdb_AsLdbContext(py_sam);
-
-	mem_ctx = talloc_new(NULL);
-	if (mem_ctx == NULL) {
-		PyErr_NoMemory();
-	}
-
-	if (!PyObject_AsDn(mem_ctx, py_user_dn, sam_ctx, &user_dn)) {
-		PyErr_SetString(PyExc_RuntimeError, "user_dn invalid!");
-		return NULL;
-	}
-
-	if (!PyObject_AsDn(mem_ctx, py_dom_dn, sam_ctx, &dom_dn)) {
-		PyErr_SetString(PyExc_RuntimeError, "dom_dn invalid!");
-		return NULL;
-	}
-
-	mod = PyLdbMessage_AsMessage(py_mod);
-
-	user_change = PyInt_AsLong(py_user_change);
-
-	new_pwd_blob.data = (uint8_t *) new_password;
-	new_pwd_blob.length = strlen((char *) new_pwd_blob.data);
-
-	status = samdb_set_password(sam_ctx, mem_ctx, user_dn, dom_dn, mod,
-		&new_pwd_blob, NULL, NULL, user_change, NULL, NULL);
-
-	talloc_free(mem_ctx);
-
-	PyErr_NTSTATUS_IS_ERR_RAISE(status);
-	Py_RETURN_NONE;
-}
-
 static PyObject *py_ldb_register_samba_handlers(PyObject *self, PyObject *args)
 {
 	PyObject *py_ldb;
@@ -496,8 +440,7 @@ static PyObject *py_dom_sid_to_rid(PyLdbObject *self, PyObject *args)
 
 	sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid));
 
-	status = dom_sid_split_rid(NULL, (const struct dom_sid *)sid, NULL,
-		&rid);
+	status = dom_sid_split_rid(NULL, sid, NULL, &rid);
 	if (!NT_STATUS_IS_OK(status)) {
 		PyErr_SetString(PyExc_RuntimeError, "dom_sid_split_rid failed");
 		return NULL;
@@ -527,10 +470,6 @@ static PyMethodDef py_misc_methods[] = {
 	{ "samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid, METH_VARARGS,
 		"samdb_get_domain_sid(samdb)\n"
 		"Get SID of domain in use." },
-	{ "samdb_set_password", (PyCFunction)py_samdb_set_password,
-		METH_VARARGS|METH_KEYWORDS,
-		"samdb_set_password(samdb, user_dn, dom_dn, mod, new_password, user_change)\n"
-		"Set the password of a user" },
 	{ "ldb_register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers, METH_VARARGS,
 		"ldb_register_samba_handlers(ldb)\n"
 		"Register Samba-specific LDB modules and schemas." },
diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py
index 3f4252b..a58d6c5 100644
--- a/source4/scripting/python/samba/samdb.py
+++ b/source4/scripting/python/samba/samdb.py
@@ -161,14 +161,14 @@ pwdLastSet: 0
             assert(len(res) == 1)
             user_dn = res[0].dn
 
-            mod = ldb.Message()
-            mod.dn = user_dn
-
-            glue.samdb_set_password(samdb=self, user_dn=str(user_dn),
-                        dom_dn=self.domain_dn(), mod=mod, new_password=password,
-                        user_change=False)
+            setpw = """
+dn: %s
+changetype: modify
+replace: userPassword
+userPassword:: %s
+""" % (user_dn, base64.b64encode(password))
 
-            self.modify(mod)
+            self.modify_ldif(setpw)
 
             if force_password_change_at_next_login:
                 self.force_password_change_at_next_login(user_dn)
diff --git a/source4/setup/pwsettings b/source4/setup/pwsettings
index f26bcf7..cd9c07d 100755
--- a/source4/setup/pwsettings
+++ b/source4/setup/pwsettings
@@ -6,6 +6,7 @@
 #
 #	Copyright Jelmer Vernooij 2008
 #	Copyright Matthias Dieter Wallnoefer 2009
+#	Copyright Andrew Kroeger 2009
 #	Released under the GNU GPL version 3 or later
 #
 import os, sys
@@ -27,17 +28,18 @@ parser.add_option_group(sambaopts)
 parser.add_option_group(options.VersionOptions(parser))
 credopts = options.CredentialsOptions(parser)
 parser.add_option_group(credopts)
+parser.add_option("--quiet", help="Be quiet", action="store_true")
 parser.add_option("-H", help="LDB URL for database or target server", type=str)
 parser.add_option("--complexity",
-  help="The password complexity (on | off). Default is 'on'", type=str)
+  help="The password complexity (on | off | default). Default is 'on'", type=str)
 parser.add_option("--history-length",
-  help="The password history length (<integer> | default)", type=str)
+  help="The password history length (<integer> | default).  Default is 24.", type=str)
 parser.add_option("--min-pwd-length",
-  help="The minimum password length (<integer> | default)", type=str)
+  help="The minimum password length (<integer> | default).  Default is 7.", type=str)
 parser.add_option("--min-pwd-age",
-  help="The minimum password age (<integer in days> | default)", type=str)
+  help="The minimum password age (<integer in days> | default).  Default is 0.", type=str)
 parser.add_option("--max-pwd-age",
-  help="The maximum password age (<integer in days> | default)", type=str)
+  help="The maximum password age (<integer in days> | default).  Default is 43.", type=str)
 
 opts, args = parser.parse_args()
 
@@ -82,57 +84,54 @@ except:
 		print "So no settings can be displayed!"
 		sys.exit(1)
 	else:
-		pwd_props = 0
-		print "WARNING: Assuming previous password properties 0 (used for password complexity setting)"
+		print "ERROR: Could not retrieve password properties (used for password complexity setting)"
+		sys.exit(1)
 
 if args[0] == "show":
-	print "Password informations for domain '" + domain_dn + "'"
-	print ""
+	message("Password informations for domain '" + domain_dn + "'")
+	message("")
 	if pwd_props & DOMAIN_PASSWORD_COMPLEX != 0:
-		print "Password complexity: on"
+		message("Password complexity: on")
 	else:
-		print "Password complexity: off"
-	print "Password history length: " + str(pwd_hist_len)
-	print "Minimum password length: " + str(min_pwd_len)
-	print "Minimum password age (days): " + str(min_pwd_age)
-	print "Maximum password age (days): " + str(max_pwd_age)
+		message("Password complexity: off")
+	message("Password history length: " + str(pwd_hist_len))
+	message("Minimum password length: " + str(min_pwd_len))
+	message("Minimum password age (days): " + str(min_pwd_age))
+	message("Maximum password age (days): " + str(max_pwd_age))
 
 elif args[0] == "set":
+
+	msgs = []
+	m = ldb.Message()
+	m.dn = ldb.Dn(samdb, domain_dn)
+
 	if opts.complexity is not None:
-		if opts.complexity == "on":
+		if opts.complexity == "on" or opts.complexity == "default":
 			pwd_props = pwd_props | DOMAIN_PASSWORD_COMPLEX
-
-			m = ldb.Message()
-			m.dn = ldb.Dn(samdb, domain_dn)
-			m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
-			  ldb.FLAG_MOD_REPLACE, "pwdProperties")
-			samdb.modify(m)
-			print "Password complexity activated!"
+			msgs.append("Password complexity activated!")
 		elif opts.complexity == "off":
 			pwd_props = pwd_props & (~DOMAIN_PASSWORD_COMPLEX)
-
-			m = ldb.Message()
-			m.dn = ldb.Dn(samdb, domain_dn)
-			m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
-			  ldb.FLAG_MOD_REPLACE, "pwdProperties")
-			samdb.modify(m)
-			print "Password complexity deactivated!"
+			msgs.append("Password complexity deactivated!")
 		else:
 			print "ERROR: Wrong argument '" + opts.complexity + "'!"
 			sys.exit(1)
 
+		m["pwdProperties"] = ldb.MessageElement(str(pwd_props),
+		  ldb.FLAG_MOD_REPLACE, "pwdProperties")
+
 	if opts.history_length is not None:
 		if opts.history_length == "default":
 			pwd_hist_len = 24
 		else:
 			pwd_hist_len = int(opts.history_length)
 
-		m = ldb.Message()
-		m.dn = ldb.Dn(samdb, domain_dn)
+		if pwd_hist_len < 0 or pwd_hist_len > 24:
+			print "ERROR: Password history length must be in the range of 0 to 24!"
+			sys.exit(1)
+
 		m["pwdHistoryLength"] = ldb.MessageElement(str(pwd_hist_len),
 		  ldb.FLAG_MOD_REPLACE, "pwdHistoryLength")
-		samdb.modify(m)
-		print "Password history length changed!"
+		msgs.append("Password history length changed!")
 
 	if opts.min_pwd_length is not None:
 		if opts.min_pwd_length == "default":
@@ -140,45 +139,57 @@ elif args[0] == "set":
 		else:
 			min_pwd_len = int(opts.min_pwd_length)
 
-		m = ldb.Message()
-		m.dn = ldb.Dn(samdb, domain_dn)
+		if min_pwd_len < 0 or min_pwd_len > 14:
+			print "ERROR: Minimum password length must be in the range of 0 to 14!"
+			sys.exit(1)
+
 		m["minPwdLength"] = ldb.MessageElement(str(min_pwd_len),
 		  ldb.FLAG_MOD_REPLACE, "minPwdLength")
-		samdb.modify(m)
-		print "Minimum password length changed!"
+		msgs.append("Minimum password length changed!")
 
 	if opts.min_pwd_age is not None:
 		if opts.min_pwd_age == "default":
 			min_pwd_age = 0
 		else:
 			min_pwd_age = int(opts.min_pwd_age)
+
+		if min_pwd_age < 0 or min_pwd_age > 998:
+			print "ERROR: Minimum password age must be in the range of 0 to 998!"
+			sys.exit(1)
+
 		# days -> ticks
-		min_pwd_age = -int(min_pwd_age * (24 * 60 * 60 * 1e7))
+		min_pwd_age_ticks = -int(min_pwd_age * (24 * 60 * 60 * 1e7))
 
-		m = ldb.Message()
-		m.dn = ldb.Dn(samdb, domain_dn)
-		m["minPwdAge"] = ldb.MessageElement(str(min_pwd_age),
+		m["minPwdAge"] = ldb.MessageElement(str(min_pwd_age_ticks),
 		  ldb.FLAG_MOD_REPLACE, "minPwdAge")
-		samdb.modify(m)
-		print "Minimum password age changed!"
+		msgs.append("Minimum password age changed!")
 
 	if opts.max_pwd_age is not None:
 		if opts.max_pwd_age == "default":
 			max_pwd_age = 43
 		else:
 			max_pwd_age = int(opts.max_pwd_age)
+
+		if max_pwd_age < 0 or max_pwd_age > 999:
+			print "ERROR: Maximum password age must be in the range of 0 to 999!"
+			sys.exit(1)
+
 		# days -> ticks
-		max_pwd_age = -int(max_pwd_age * (24 * 60 * 60 * 1e7))
+		max_pwd_age_ticks = -int(max_pwd_age * (24 * 60 * 60 * 1e7))
 
-		m = ldb.Message()
-		m.dn = ldb.Dn(samdb, domain_dn)
-		m["maxPwdAge"] = ldb.MessageElement(str(max_pwd_age),
+		m["maxPwdAge"] = ldb.MessageElement(str(max_pwd_age_ticks),
 		  ldb.FLAG_MOD_REPLACE, "maxPwdAge")
-		samdb.modify(m)
-		print "Maximum password age changed!"
+		msgs.append("Maximum password age changed!")
+
+	if max_pwd_age > 0 and min_pwd_age >= max_pwd_age:
+		print "ERROR: Maximum password age (%d) must be greater than minimum password age (%d)!" % (max_pwd_age, min_pwd_age)
+		sys.exit(1)
+
+	samdb.modify(m)
 
-	print "All changes applied successfully!"
+	msgs.append("All changes applied successfully!")
 
+	message("\n".join(msgs))
 else:
 	print "ERROR: Wrong argument '" + args[0] + "'!"
 	sys.exit(1)
diff --git a/source4/setup/tests/blackbox_setpassword.sh b/source4/setup/tests/blackbox_setpassword.sh
index 70061f6..77b41a2 100755
--- a/source4/setup/tests/blackbox_setpassword.sh
+++ b/source4/setup/tests/blackbox_setpassword.sh
@@ -20,4 +20,6 @@ testit "setpassword" $PYTHON ./setup/setpassword --configfile=$PREFIX/simple-dc/
 
 testit "setpassword" $PYTHON ./setup/setpassword --configfile=$PREFIX/simple-dc/etc/smb.conf testuser --newpassword=testpass --must-change-at-next-login
 
+testit "pwsettings" $PYTHON ./setup/pwsettings --quiet set --configfile=$PREFIX/simple-dc/etc/smb.conf --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default
+
 exit $failed
diff --git a/testprogs/blackbox/subunit.sh b/testprogs/blackbox/subunit.sh
index cee8cf6..e16aee7 100755
--- a/testprogs/blackbox/subunit.sh
+++ b/testprogs/blackbox/subunit.sh
@@ -65,3 +65,18 @@ testit () {
 	fi
 	return $status
 }
+
+testit_expect_failure () {
+	name="$1"
+	shift
+	cmdline="$*"
+	subunit_start_test "$name"
+	output=`$cmdline 2>&1`
+	status=$?
+	if [ x$status = x0 ]; then
+		echo "$output" | subunit_fail_test "$name"
+	else
+		subunit_pass_test "$name"
+	fi
+	return $status
+}
diff --git a/testprogs/blackbox/test_passwords.sh b/testprogs/blackbox/test_passwords.sh
index c42969f..09799f6 100755
--- a/testprogs/blackbox/test_passwords.sh
+++ b/testprogs/blackbox/test_passwords.sh
@@ -112,9 +112,37 @@ expect Success
 EOF
 
 testit "change user password with kpasswd (after must change flag set)" $rkpty ./tmpkpasswdscript $samba4kpasswd nettestuser@$REALM || failed=`expr $failed + 1`
+USERPASS=$NEWUSERPASS
 
 test_smbclient "Test login with user kerberos" 'ls' -k yes -Unettestuser@$REALM%$NEWUSERPASS || failed=`expr $failed + 1`
 
+testit "reset password policies" $VALGRIND $PYTHON ./setup/pwsettings set --configfile=$PREFIX/dc/etc/smb.conf --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1`
+
+NEWUSERPASS=abcdefg
+testit_expect_failure "try to set a non-complex password (command should not succeed)" $VALGRIND $net password change -W$DOMAIN -U$DOMAIN\\nettestuser%$USERPASS -k no $NEWUSERPASS $@ && failed=`expr $failed + 1`
+
+testit "allow non-complex passwords" $VALGRIND $PYTHON ./setup/pwsettings set --configfile=$PREFIX/dc/etc/smb.conf --complexity=off || failed=`expr $failed + 1`
+
+testit "try to set a non-complex password (command should succeed)" $VALGRIND $net password change -W$DOMAIN -U$DOMAIN\\nettestuser%$USERPASS -k no $NEWUSERPASS $@ || failed=`expr $failed + 1`
+USERPASS=$NEWUSERPASS
+
+test_smbclient "test login with non-complex password" 'ls' -k no -Unettestuser@$REALM%$USERPASS || failed=`expr $failed + 1`
+
+NEWUSERPASS=abc
+testit_expect_failure "try to set a short password (command should not succeed)" $VALGRIND $net password change -W$DOMAIN -U$DOMAIN\\nettestuser%$USERPASS -k no $NEWUSERPASS $@ && failed=`expr $failed + 1`
+
+testit "allow short passwords (length 1)" $VALGRIND $PYTHON ./setup/pwsettings set --configfile=$PREFIX/dc/etc/smb.conf --min-pwd-length=1 || failed=`expr $failed + 1`
+
+testit "try to set a short password (command should succeed)" $VALGRIND $net password change -W$DOMAIN -U$DOMAIN\\nettestuser%$USERPASS -k no $NEWUSERPASS $@ || failed=`expr $failed + 1`
+USERPASS=$NEWUSERPASS
+
+testit "require minimum password age of 1 day" $VALGRIND $PYTHON ./setup/pwsettings set --configfile=$PREFIX/dc/etc/smb.conf --min-pwd-age=1 || failed=`expr $failed + 1`
+
+NEWUSERPASS=testPaSS at 08%
+testit_expect_failure "try to change password too quickly (command should not succeed)" $VALGRIND $net password change -W$DOMAIN -U$DOMAIN\\nettestuser%$USERPASS -k no $NEWUSERPASS $@ && failed=`expr $failed + 1`
+
+testit "reset password policies" $VALGRIND $PYTHON ./setup/pwsettings set --configfile=$PREFIX/dc/etc/smb.conf --complexity=default --history-length=default --min-pwd-length=default --min-pwd-age=default --max-pwd-age=default || failed=`expr $failed + 1`
+
 testit "del user" $VALGRIND $net user delete nettestuser -U"$USERNAME%$PASSWORD" -k no $@ || failed=`expr $failed + 1`
 
 rm -f tmpccfile tmppassfile tmpuserpassfile tmpuserccache tmpkpasswdscript


-- 
Samba Shared Repository


More information about the samba-cvs mailing list