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 <bobcampb...@catalyst.net.nz> Date: Tue Jun 28 10:34:04 2016 +1200 password_hash: Make an error message clearer Signed-off-by: Bob Campbell <bobcampb...@catalyst.net.nz> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Garming Sam <garm...@samba.org> Autobuild-Date(master): Tue Jul 5 03:47:52 CEST 2016 on sn-devel-144 commit 2840ebc76fba061dc4476cc425c888cf7e981cf0 Author: Garming Sam <garm...@catalyst.net.nz> Date: Mon Jun 13 15:42:25 2016 +1200 typo: mandetory -> mandatory Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 1a2427d97e871069214e4d65c308bf70ec2a1f47 Author: Garming Sam <garm...@catalyst.net.nz> Date: Tue May 31 09:54:26 2016 +1200 typo: componemt => component Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fa7212afe79cbb4b782ccae9413c8587191659d8 Author: Garming Sam <garm...@catalyst.net.nz> Date: Thu Feb 18 14:17:01 2016 +1300 tevent: typo in documentation Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 73152561df1f6da991057ce066fe30de117ebc20 Author: Garming Sam <garm...@catalyst.net.nz> Date: Fri Jan 22 13:55:34 2016 +1300 param: fix a typo emtpy -> empty Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 21295155cc285843f4e145efb5ef11344109db88 Author: Bob Campbell <bobcampb...@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 <bobcampb...@catalyst.net.nz> Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ef0cbc556017b1ac3a6893add54890ff03670233 Author: Bob Campbell <bobcampb...@catalyst.net.nz> Date: Mon Jun 13 15:42:46 2016 +1200 selftest: add check password script test Pair-programmed-with: Garming Sam <garm...@catalyst.net.nz> Signed-off-by: Bob Campbell <bobcampb...@catalyst.net.nz> Signed-off-by: Garming Sam <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 878fa6ef7de420ed7f28e95113bb76bf50879553 Author: Garming Sam <garm...@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 <garm...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@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 <k...@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 <sda...@linux.vnet.ibm.com> 2011 +# Copyright (C) Andrew Bartlett <abart...@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