[SCM] Samba Shared Repository - branch master updated

Garming Sam garming at samba.org
Tue Jul 5 01:48:03 UTC 2016


The branch, master has been updated
       via  965361a password_hash: Make an error message clearer
       via  2840ebc typo: mandetory -> mandatory
       via  1a2427d typo: componemt => component
       via  fa7212a tevent: typo in documentation
       via  7315256 param: fix a typo emtpy -> empty
       via  2129515 check_password_script: Add a DEBUG message for timeouts
       via  ef0cbc5 selftest: add check password script test
       via  878fa6e check-password-script: Allow AD to execute these scripts
      from  5a0d1b7 ctdb-tests: Link to ctdb-ipalloc instead of using ctdbd_test.c

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


- Log -----------------------------------------------------------------
commit 965361aa929ab6798e03e71d3800027a32896c7d
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Tue Jun 28 10:34:04 2016 +1200

    password_hash: Make an error message clearer
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Garming Sam <garming at samba.org>
    Autobuild-Date(master): Tue Jul  5 03:47:52 CEST 2016 on sn-devel-144

commit 2840ebc76fba061dc4476cc425c888cf7e981cf0
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Jun 13 15:42:25 2016 +1200

    typo: mandetory -> mandatory
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1a2427d97e871069214e4d65c308bf70ec2a1f47
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue May 31 09:54:26 2016 +1200

    typo: componemt => component
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fa7212afe79cbb4b782ccae9413c8587191659d8
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Thu Feb 18 14:17:01 2016 +1300

    tevent: typo in documentation
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 73152561df1f6da991057ce066fe30de117ebc20
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Fri Jan 22 13:55:34 2016 +1300

    param: fix a typo emtpy -> empty
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 21295155cc285843f4e145efb5ef11344109db88
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Tue Jun 28 10:33:24 2016 +1200

    check_password_script: Add a DEBUG message for timeouts
    
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ef0cbc556017b1ac3a6893add54890ff03670233
Author: Bob Campbell <bobcampbell at catalyst.net.nz>
Date:   Mon Jun 13 15:42:46 2016 +1200

    selftest: add check password script test
    
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Bob Campbell <bobcampbell at catalyst.net.nz>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 878fa6ef7de420ed7f28e95113bb76bf50879553
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Fri Apr 1 10:10:57 2016 +1300

    check-password-script: Allow AD to execute these scripts
    
    In contrast to source3, this is run as root and without substitution.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 auth/gensec/gensec.c                               |  6 +-
 .../smbdotconf/security/checkpasswordscript.xml    |  6 +-
 lib/param/loadparm.c                               |  8 +-
 lib/tevent/tevent.h                                |  2 +-
 lib/util/util_runcmd.c                             | 14 +---
 .../echo_server.h => lib/util/util_runcmd.h        | 28 ++++---
 librpc/ndr/ndr_dns.c                               |  2 +-
 .../tests/samba_tool/user_check_password_script.py | 97 ++++++++++++++++++++++
 selftest/selftest.pl                               |  1 +
 selftest/target/Samba4.pm                          |  6 +-
 source4/dsdb/common/util.c                         | 84 ++++++++++++++++++-
 source4/dsdb/samdb/ldb_modules/password_hash.c     | 12 +--
 source4/dsdb/wscript_build                         |  2 +-
 source4/rpc_server/samr/dcesrv_samr.c              |  8 +-
 source4/selftest/tests.py                          |  1 +
 15 files changed, 231 insertions(+), 46 deletions(-)
 copy source4/echo_server/echo_server.h => lib/util/util_runcmd.h (68%)
 create mode 100644 python/samba/tests/samba_tool/user_check_password_script.py


Changeset truncated at 500 lines:

diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c
index 2a8bba8..3f3c31b 100644
--- a/auth/gensec/gensec.c
+++ b/auth/gensec/gensec.c
@@ -244,7 +244,7 @@ static NTSTATUS gensec_verify_dcerpc_auth_level(struct gensec_security *gensec_s
 	switch (gensec_security->dcerpc_auth_level) {
 	case DCERPC_AUTH_LEVEL_INTEGRITY:
 		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
+			DEBUG(0,("Did not manage to negotiate mandatory feature "
 				 "SIGN for dcerpc auth_level %u\n",
 				 gensec_security->dcerpc_auth_level));
 			return NT_STATUS_ACCESS_DENIED;
@@ -252,13 +252,13 @@ static NTSTATUS gensec_verify_dcerpc_auth_level(struct gensec_security *gensec_s
 		break;
 	case DCERPC_AUTH_LEVEL_PRIVACY:
 		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
+			DEBUG(0,("Did not manage to negotiate mandatory feature "
 				 "SIGN for dcerpc auth_level %u\n",
 				 gensec_security->dcerpc_auth_level));
 			return NT_STATUS_ACCESS_DENIED;
 		}
 		if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
-			DEBUG(0,("Did not manage to negotiate mandetory feature "
+			DEBUG(0,("Did not manage to negotiate mandatory feature "
 				 "SEAL for dcerpc auth_level %u\n",
 				 gensec_security->dcerpc_auth_level));
 			return NT_STATUS_ACCESS_DENIED;
diff --git a/docs-xml/smbdotconf/security/checkpasswordscript.xml b/docs-xml/smbdotconf/security/checkpasswordscript.xml
index e2079c2..54f1096 100644
--- a/docs-xml/smbdotconf/security/checkpasswordscript.xml
+++ b/docs-xml/smbdotconf/security/checkpasswordscript.xml
@@ -5,12 +5,16 @@
 <description>
     <para>The name of a program that can be used to check password
     complexity. The password is sent to the program's standard input.</para>
- 
+
     <para>The program must return 0 on a good password, or any other value
     if the password is bad.
     In case the password is considered weak (the program does not return 0) the
     user will be notified and the password change will fail.</para>
 
+    <para>In Samba AD, this script will be run <emphasis>AS ROOT</emphasis> by
+    <citerefentry><refentrytitle>samba</refentrytitle> <manvolnum>8</manvolnum>
+    </citerefentry> without any substitutions.</para>
+
     <para>Note: In the example directory is a sample program called <command moreinfo="none">crackcheck</command>
     that uses cracklib to check the password quality.</para>
 
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 73d4204..19ee7eb 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -549,7 +549,7 @@ bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
 
 
 /* this is used to prevent lots of mallocs of size 1 */
-static const char lpcfg_string_emtpy[] = "";
+static const char lpcfg_string_empty[] = "";
 
 /**
  Free a string value.
@@ -559,7 +559,7 @@ void lpcfg_string_free(char **s)
 	if (s == NULL) {
 		return;
 	}
-	if (*s == lpcfg_string_emtpy) {
+	if (*s == lpcfg_string_empty) {
 		*s = NULL;
 		return;
 	}
@@ -575,7 +575,7 @@ bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 	lpcfg_string_free(dest);
 
 	if ((src == NULL) || (*src == '\0')) {
-		*dest = discard_const_p(char, lpcfg_string_emtpy);
+		*dest = discard_const_p(char, lpcfg_string_empty);
 		return true;
 	}
 
@@ -597,7 +597,7 @@ bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 	lpcfg_string_free(dest);
 
 	if ((src == NULL) || (*src == '\0')) {
-		*dest = discard_const_p(char, lpcfg_string_emtpy);
+		*dest = discard_const_p(char, lpcfg_string_empty);
 		return true;
 	}
 
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index cc6b15e..1c1271b 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -1369,7 +1369,7 @@ bool tevent_wakeup_recv(struct tevent_req *req);
 /* @} */
 
 /**
- * @defgroup tevent_helpers The tevent helper functiions
+ * @defgroup tevent_helpers The tevent helper functions
  * @ingroup tevent
  *
  * @todo description
diff --git a/lib/util/util_runcmd.c b/lib/util/util_runcmd.c
index 02de77e..9264cbb 100644
--- a/lib/util/util_runcmd.c
+++ b/lib/util/util_runcmd.c
@@ -27,20 +27,8 @@
 
 #include "includes.h"
 #include "system/filesys.h"
-#include <tevent.h>
 #include "../lib/util/tevent_unix.h"
-
-struct samba_runcmd_state {
-	int stdout_log_level;
-	int stderr_log_level;
-	struct tevent_fd *fde_stdout;
-	struct tevent_fd *fde_stderr;
-	int fd_stdin, fd_stdout, fd_stderr;
-	char *arg0;
-	pid_t pid;
-	char buf[1024];
-	uint16_t buf_used;
-};
+#include "../lib/util/util_runcmd.h"
 
 static int samba_runcmd_state_destructor(struct samba_runcmd_state *state)
 {
diff --git a/source4/echo_server/echo_server.h b/lib/util/util_runcmd.h
similarity index 68%
copy from source4/echo_server/echo_server.h
copy to lib/util/util_runcmd.h
index 3c3e1ae..26fdbc6 100644
--- a/source4/echo_server/echo_server.h
+++ b/lib/util/util_runcmd.h
@@ -1,9 +1,9 @@
 /*
    Unix SMB/CIFS implementation.
 
-   Echo structures, server service example
+   run a child command
 
-   Copyright (C) 2010 Kai Blin  <kai at samba.org>
+   Copyright (C) Andrew Tridgell 2010
 
    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
@@ -17,17 +17,19 @@
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __ECHO_SERVER_H__
-#define __ECHO_SERVER_H__
 
-struct task_server;
+*/
 
-struct echo_server {
-        struct task_server *task;
+#include <tevent.h>
+
+struct samba_runcmd_state {
+	int stdout_log_level;
+	int stderr_log_level;
+	struct tevent_fd *fde_stdout;
+	struct tevent_fd *fde_stderr;
+	int fd_stdin, fd_stdout, fd_stderr;
+	char *arg0;
+	pid_t pid;
+	char buf[1024];
+	uint16_t buf_used;
 };
-
-#define ECHO_SERVICE_PORT 7
-
-#endif /*__ECHO_SERVER_H__*/
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
index 7e6286a..4e4c556 100644
--- a/librpc/ndr/ndr_dns.c
+++ b/librpc/ndr/ndr_dns.c
@@ -212,7 +212,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
 						(unsigned char)complen, s);
 		NDR_ERR_HAVE_NO_MEMORY(compname);
 
-		/* remember the current componemt + the rest of the string
+		/* remember the current component + the rest of the string
 		 * so it can be reused later
 		 */
 		if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) {
diff --git a/python/samba/tests/samba_tool/user_check_password_script.py b/python/samba/tests/samba_tool/user_check_password_script.py
new file mode 100644
index 0000000..5d4fbae
--- /dev/null
+++ b/python/samba/tests/samba_tool/user_check_password_script.py
@@ -0,0 +1,97 @@
+# Unix SMB/CIFS implementation.
+# Copyright (C) Sean Dague <sdague at linux.vnet.ibm.com> 2011
+# Copyright (C) Andrew Bartlett <abartlet at samba.org> 2016
+#
+# 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/>.
+#
+
+import os
+import time
+import ldb
+from samba.tests.samba_tool.base import SambaToolCmdTest
+from samba import (
+        nttime2unix,
+        dsdb
+        )
+
+class UserCheckPwdTestCase(SambaToolCmdTest):
+    """Tests for samba-tool user subcommands"""
+    users = []
+    samdb = None
+
+    def setUp(self):
+        super(UserCheckPwdTestCase, self).setUp()
+        self.samdb = self.getSamDB("-H", "ldap://%s" % os.environ["DC_SERVER"],
+            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.old_min_pwd_age = self.samdb.get_minPwdAge()
+        self.samdb.set_minPwdAge("0")
+
+    def tearDown(self):
+        super(UserCheckPwdTestCase, self).tearDown()
+        self.samdb.set_minPwdAge(self.old_min_pwd_age)
+
+    def test_checkpassword(self):
+        # Add
+        user = self._randomUser()
+        bad_password = os.environ["UNACCEPTABLE_PASSWORD"]
+        good_password = bad_password[:-1]
+
+        (result, out, err) = self.runsubcmd("user", "add", user["name"], bad_password,
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.assertCmdFail(result, "Should fail adding a user with bad password.")
+        (result, out, err) = self.runsubcmd("user", "delete", user["name"],
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.assertCmdSuccess(result, "Should delete user with bad password.")
+
+        (result, out, err) = self.runsubcmd("user", "add", user["name"], good_password,
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.assertCmdSuccess(result, "Should succeed adding a user with good password.")
+
+        # Set password
+        (result, out, err) = self.runsubcmd("user", "setpassword", user["name"],
+                                            "--newpassword=%s" % bad_password,
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.assertCmdFail(result, "Should fail setting a user's password to a bad one.")
+
+        (result, out, err) = self.runsubcmd("user", "setpassword", user["name"],
+                                            "--newpassword=%s" % good_password,
+                                            "-H", "ldap://%s" % os.environ["DC_SERVER"],
+                                            "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
+        self.assertCmdSuccess(result, "Should succeed setting a user's password to a good one.")
+
+        # Password=
+
+        (result, out, err) = self.runsubcmd("user", "password",
+                                            "--newpassword=%s" % bad_password,
+                                            "--ipaddress", os.environ["DC_SERVER_IP"],
+                                            "-U%s%%%s" % (user["name"], good_password))
+        self.assertCmdFail(result, "A user setting their own password to a bad one should fail.")
+
+        (result, out, err) = self.runsubcmd("user", "password",
+                                            "--newpassword=%s" % good_password + 'XYZ',
+                                            "--ipaddress", os.environ["DC_SERVER_IP"],
+                                            "-U%s%%%s" % (user["name"], good_password))
+        self.assertCmdSuccess(result, "A user setting their own password to a good one should succeed.")
+
+    def _randomUser(self, base={}):
+        """create a user with random attribute values, you can specify base attributes"""
+        user = {
+            "name": self.randomName(),
+        }
+        user.update(base)
+        return user
diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index 528aa9c..1ab932b 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -836,6 +836,7 @@ my @exported_envvars = (
 	"DNS_FORWARDER1",
 	"DNS_FORWARDER2",
 	"RESOLV_CONF",
+	"UNACCEPTABLE_PASSWORD",
 
 	# nss_wrapper
 	"NSS_WRAPPER_PASSWD",
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 693e623..731ad1f 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1761,6 +1761,9 @@ sub provision_chgdcpass($$)
 
 	print "PROVISIONING CHGDCPASS...\n";
 	my $extra_provision_options = undef;
+	# This environment disallows the use of this password
+	# (and also removes the default AD complexity checks)
+	my $unacceptable_password = "widk3Dsle32jxdBdskldsk55klASKQ";
 	push (@{$extra_provision_options}, "--dns-backend=BIND9_DLZ");
 	my $ret = $self->provision($prefix,
 				   "domain controller",
@@ -1771,7 +1774,7 @@ sub provision_chgdcpass($$)
 				   "chgDCpass1",
 				   undef,
 				   undef,
-				   "",
+				   "check password script = sed -e '/$unacceptable_password/{;q1}; /$unacceptable_password/!{q0}'\n",
 				   "",
 				   $extra_provision_options);
 	unless (defined $ret) {
@@ -1797,6 +1800,7 @@ sub provision_chgdcpass($$)
 	$ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
 	$ret->{DC_USERNAME} = $ret->{USERNAME};
 	$ret->{DC_PASSWORD} = $ret->{PASSWORD};
+	$ret->{UNACCEPTABLE_PASSWORD} = $unacceptable_password;
 
 	return $ret;
 }
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 69f0f63..1c546d7 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -44,6 +44,7 @@
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/irpc.h"
 #include "libds/common/flag_mapping.h"
+#include "../lib/util/util_runcmd.h"
 
 /*
   search the sam for the specified attributes in a specific domain, filter on
@@ -1980,6 +1981,15 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 	return ret;
 }
 
+static void pwd_timeout_debug(struct tevent_context *unused1,
+			      struct tevent_timer *unused2,
+			      struct timeval unused3,
+			      void *unused4)
+{
+	DEBUG(0, ("WARNING: check_password_complexity: password script "
+		  "took more than 1 second to run\n"));
+}
+
 
 /*
  * Performs checks on a user password (plaintext UNIX format - attribute
@@ -1988,12 +1998,15 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
  *
  * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
  */
-enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *utf8_blob,
+enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
+						struct loadparm_context *lp_ctx,
+						const DATA_BLOB *utf8_blob,
 						const uint32_t pwdProperties,
 						const uint32_t minPwdLength)
 {
 	const char *utf8_pw = (const char *)utf8_blob->data;
 	size_t utf8_len = strlen_m(utf8_pw);
+	char *password_script = NULL;
 
 	/* checks if the "minPwdLength" property is satisfied */
 	if (minPwdLength > utf8_len) {
@@ -2009,6 +2022,75 @@ enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *utf8_blob,
 		return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
 	}
 
+	password_script = lpcfg_check_password_script(lp_ctx, mem_ctx);
+	if (password_script != NULL && *password_script != '\0') {
+		int check_ret = 0;
+		int error = 0;
+		struct tevent_context *event_ctx = NULL;
+		struct tevent_req *req = NULL;
+		struct samba_runcmd_state *run_cmd = NULL;
+		const char * const cmd[4] = {
+			"/bin/sh", "-c",
+			password_script,
+			NULL
+		};
+
+		event_ctx = tevent_context_init(mem_ctx);
+		if (event_ctx == NULL) {
+			TALLOC_FREE(password_script);
+			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+		}
+
+		/* Gives a warning after 1 second, terminates after 10 */
+		tevent_add_timer(event_ctx, event_ctx,
+				 tevent_timeval_current_ofs(1, 0),
+				 pwd_timeout_debug, NULL);
+
+		req = samba_runcmd_send(event_ctx, event_ctx,
+					tevent_timeval_current_ofs(10, 0),
+					100, 100, cmd, NULL);
+		run_cmd = tevent_req_data(req, struct samba_runcmd_state);
+		if (write(run_cmd->fd_stdin, utf8_pw, utf8_len) != utf8_len) {
+			TALLOC_FREE(password_script);
+			TALLOC_FREE(event_ctx);
+			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+		}
+
+		close(run_cmd->fd_stdin);
+		run_cmd->fd_stdin = -1;
+
+		if (!tevent_req_poll(req, event_ctx)) {
+			TALLOC_FREE(password_script);
+			TALLOC_FREE(event_ctx);
+			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+		}
+
+		check_ret = samba_runcmd_recv(req, &error);
+		TALLOC_FREE(event_ctx);
+
+		if (error == ETIMEDOUT) {
+			DEBUG(0, ("check_password_complexity: check password script took too long!\n"));
+			TALLOC_FREE(password_script);
+			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+		} else {
+			DEBUG(5,("check_password_complexity: check password script (%s) "
+				 "returned [%d]\n", password_script, check_ret));
+
+			if (check_ret != 0) {
+				DEBUG(1,("check_password_complexity: "
+					 "check password script said new password is not good "
+					 "enough!\n"));
+				TALLOC_FREE(password_script);
+				return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
+			}
+		}
+
+		TALLOC_FREE(password_script);
+		return SAMR_VALIDATION_STATUS_SUCCESS;
+	}
+
+	TALLOC_FREE(password_script);
+
 	if (!check_password_quality(utf8_pw)) {
 		return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
 	}
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 76c63a6..c50a778 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -2106,10 +2106,11 @@ done:
 
 static int check_password_restrictions(struct setup_password_fields_io *io)
 {
-	struct ldb_context *ldb;
+	struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
 	int ret;
-
-	ldb = ldb_module_get_ctx(io->ac->module);
+	struct loadparm_context *lp_ctx =
+		lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+					 struct loadparm_context);
 
 	if (!io->ac->update_password) {
 		return LDB_SUCCESS;
@@ -2175,7 +2176,8 @@ static int check_password_restrictions(struct setup_password_fields_io *io)
 	 */
 	if (io->n.cleartext_utf8 != NULL) {
 		enum samr_ValidationStatus vstat;
-		vstat = samdb_check_password(io->n.cleartext_utf8,
+		vstat = samdb_check_password(io->ac, lp_ctx,
+					     io->n.cleartext_utf8,
 					     io->ac->status->domain_data.pwdProperties,
 					     io->ac->status->domain_data.minPwdLength);
 		switch (vstat) {
@@ -2208,7 +2210,7 @@ static int check_password_restrictions(struct setup_password_fields_io *io)
 			ret = LDB_ERR_CONSTRAINT_VIOLATION;
 			ldb_asprintf_errstring(ldb,
 				"%08X: %s - check_password_restrictions: "
-				"the password doesn't fit by a certain reason!",
+				"the password doesn't fit due to a miscellaneous restriction!",
 				W_ERROR_V(WERR_PASSWORD_RESTRICTION),
 				ldb_strerror(ret));
 			return ret;
diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build
index 28ca845..991f9d3 100755


-- 
Samba Shared Repository



More information about the samba-cvs mailing list