[Patches] export SAMBA_CPS_{ACCOUNT,USER_PRINCIPAL,FULL}_NAME to check password script

Stefan Metzmacher metze at samba.org
Wed Feb 6 20:37:08 UTC 2019


Hi,

when the check password script is executed in the AD DC it won't get any
information of the user and only the new password on stdin.

In the NT4 DC is may get '%u' substituted with the account name.

As the check password script is executed with /bin/sh -c
and on the AD DC also as root (without substituting %u),
Andrew asked to avoid adding %u.

The easiest solution (that won't break existing setups)
we come up with is to export environment variables:
SAMBA_CPS_ACCOUNT_NAME (always)
SAMBA_CPS_USER_PRINCIPAL_NAME (if available)
SAMBA_CPS_FULL_NAME (if available)

As a side effect this patchset also fixes the check password script
tests on FreeBSD (with less 'sed' features).

Please review and push:-)

See https://gitlab.com/samba-team/samba/merge_requests/203

Thanks!
metze
-------------- next part --------------
From d33057b14d6075b2c6fa1558f1a61d0016228ca7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 Feb 2019 12:58:57 +0100
Subject: [PATCH 1/9] lib/util: add samba_runcmd_export_stdin() helper function

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 lib/util/samba_util.h  |  1 +
 lib/util/util_runcmd.c | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index 7b96a595d437..1cd1235f8f11 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -649,6 +649,7 @@ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
 				     int stderr_log_level,
 				     const char * const *argv0, ...);
 int samba_runcmd_recv(struct tevent_req *req, int *perrno);
+int samba_runcmd_export_stdin(struct tevent_req *req);
 
 #ifdef DEVELOPER
 void samba_start_debugger(void);
diff --git a/lib/util/util_runcmd.c b/lib/util/util_runcmd.c
index 42d84a895bf2..78ac77f49467 100644
--- a/lib/util/util_runcmd.c
+++ b/lib/util/util_runcmd.c
@@ -49,6 +49,17 @@ static void samba_runcmd_cleanup_fn(struct tevent_req *req,
 	}
 }
 
+int samba_runcmd_export_stdin(struct tevent_req *req)
+{
+	struct samba_runcmd_state *state = tevent_req_data(req,
+					   struct samba_runcmd_state);
+	int ret = state->fd_stdin;
+
+	state->fd_stdin = -1;
+
+	return ret;
+}
+
 static void samba_runcmd_io_handler(struct tevent_context *ev,
 				    struct tevent_fd *fde,
 				    uint16_t flags,
-- 
2.17.1


From d45036c285093c6dbb3ed34509cb90a84d6c5b24 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 Feb 2019 13:00:13 +0100
Subject: [PATCH 2/9] s4:dsdb:util: make use of samba_runcmd_export_stdin()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source4/dsdb/common/util.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index d173a75ebb7d..3ac21d0e43ce 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -45,7 +45,6 @@
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/irpc.h"
 #include "libds/common/flag_mapping.h"
-#include "../lib/util/util_runcmd.h"
 #include "lib/util/access.h"
 #include "lib/util/util_str_hex.h"
 #include "libcli/util/ntstatus.h"
@@ -2112,7 +2111,7 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
 		int error = 0;
 		struct tevent_context *event_ctx = NULL;
 		struct tevent_req *req = NULL;
-		struct samba_runcmd_state *run_cmd = NULL;
+		int cps_stdin = -1;
 		const char * const cmd[4] = {
 			"/bin/sh", "-c",
 			password_script,
@@ -2133,15 +2132,24 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
 		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) {
+		if (req == NULL) {
 			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;
+		cps_stdin = samba_runcmd_export_stdin(req);
+
+		if (write(cps_stdin, utf8_pw, utf8_len) != utf8_len) {
+			close(cps_stdin);
+			cps_stdin = -1;
+			TALLOC_FREE(password_script);
+			TALLOC_FREE(event_ctx);
+			return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR;
+		}
+
+		close(cps_stdin);
+		cps_stdin = -1;
 
 		if (!tevent_req_poll(req, event_ctx)) {
 			TALLOC_FREE(password_script);
-- 
2.17.1


From fbc884c23584da72059f2d0ae18de11850100ff2 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 Feb 2019 13:09:37 +0100
Subject: [PATCH 3/9] lib/util: inline lib/util/util_runcmd.h again

samba_runcmd_state should not be exposed!

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 lib/util/util_runcmd.c | 16 +++++++++++++++-
 lib/util/util_runcmd.h | 37 -------------------------------------
 2 files changed, 15 insertions(+), 38 deletions(-)
 delete mode 100644 lib/util/util_runcmd.h

diff --git a/lib/util/util_runcmd.c b/lib/util/util_runcmd.c
index 78ac77f49467..3bb4cd83f68c 100644
--- a/lib/util/util_runcmd.c
+++ b/lib/util/util_runcmd.c
@@ -27,11 +27,25 @@
 
 #include "includes.h"
 #include "system/filesys.h"
+#include <tevent.h>
 #include "../lib/util/tevent_unix.h"
-#include "../lib/util/util_runcmd.h"
 #include "../lib/util/tfork.h"
 #include "../lib/util/sys_rw.h"
 
+struct samba_runcmd_state {
+	int stdout_log_level;
+	int stderr_log_level;
+	struct tevent_fd *fde_stdout;
+	struct tevent_fd *fde_stderr;
+	struct tevent_fd *fde_status;
+	int fd_stdin, fd_stdout, fd_stderr, fd_status;
+	char *arg0;
+	pid_t pid;
+	struct tfork *tfork;
+	char buf[1024];
+	uint16_t buf_used;
+};
+
 static void samba_runcmd_cleanup_fn(struct tevent_req *req,
 				    enum tevent_req_state req_state)
 {
diff --git a/lib/util/util_runcmd.h b/lib/util/util_runcmd.h
deleted file mode 100644
index 55329615a251..000000000000
--- a/lib/util/util_runcmd.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-   Unix SMB/CIFS implementation.
-
-   run a child command
-
-   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
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <tevent.h>
-
-struct samba_runcmd_state {
-	int stdout_log_level;
-	int stderr_log_level;
-	struct tevent_fd *fde_stdout;
-	struct tevent_fd *fde_stderr;
-	struct tevent_fd *fde_status;
-	int fd_stdin, fd_stdout, fd_stderr, fd_status;
-	char *arg0;
-	pid_t pid;
-	struct tfork *tfork;
-	char buf[1024];
-	uint16_t buf_used;
-};
-- 
2.17.1


From f5fd1afbcd924b8bcae14c228c155b34cbe63a33 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 5 Feb 2019 15:30:36 +0100
Subject: [PATCH 4/9] selftest: make check password script more portable

We should not rely on Linux specific sed options.

grep -q also works on FreeBSD (tested on FreeBSD 12).

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 selftest/checkpassword_arg1.sh | 15 +++++++++++++++
 selftest/target/Samba4.pm      |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100755 selftest/checkpassword_arg1.sh

diff --git a/selftest/checkpassword_arg1.sh b/selftest/checkpassword_arg1.sh
new file mode 100755
index 000000000000..9cb28ef198cf
--- /dev/null
+++ b/selftest/checkpassword_arg1.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+
+set -e
+set -u
+
+INVALIDPW="$1"
+NEWPW=`cat -`
+
+echo -n "${NEWPW}" | grep -q "^${INVALIDPW}\$" && {
+	echo "Found invalid password" >&1
+	exit 1
+}
+
+exit 0
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 33c66848c562..d8e066f6f447 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -2173,7 +2173,7 @@ sub provision_chgdcpass($$)
 	# (and also removes the default AD complexity checks)
 	my $unacceptable_password = "widk3Dsle32jxdBdskldsk55klASKQ";
 	my $extra_smb_conf = "
-	check password script = sed -e '/$unacceptable_password/{;q1}; /$unacceptable_password/!{q0}'
+	check password script = $self->{srcdir}/selftest/checkpassword_arg1.sh ${unacceptable_password}
 	allow dcerpc auth level connect:lsarpc = yes
 	dcesrv:max auth states = 8
 ";
-- 
2.17.1


From 98dd79fe7d09500fa054f0f14473e5a08a9f3566 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 22 Jan 2019 10:31:52 +0100
Subject: [PATCH 5/9] tests/user_check_password_script: add a test do disallow
 the username as password

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 .../samba_tool/user_check_password_script.py  | 34 ++++++++++++++-----
 selftest/checkpassword_arg1.sh                |  6 ++++
 .../knownfail.d/user_check_password_script    |  1 +
 3 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 selftest/knownfail.d/user_check_password_script

diff --git a/python/samba/tests/samba_tool/user_check_password_script.py b/python/samba/tests/samba_tool/user_check_password_script.py
index aaf791aff9ef..06afbade6bd5 100644
--- a/python/samba/tests/samba_tool/user_check_password_script.py
+++ b/python/samba/tests/samba_tool/user_check_password_script.py
@@ -42,20 +42,16 @@ class UserCheckPwdTestCase(SambaToolCmdTest):
         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]
+    def _test_checkpassword(self, user, bad_password, good_password, desc):
 
         (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.")
+        self.assertCmdFail(result, "Should fail adding a user with %s password." % desc)
         (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, out, err, "Should delete user with bad password.")
+        self.assertCmdSuccess(result, out, err, "Should delete user with %s password." % desc)
 
         (result, out, err) = self.runsubcmd("user", "add", user["name"], good_password,
                                             "-H", "ldap://%s" % os.environ["DC_SERVER"],
@@ -67,7 +63,7 @@ class UserCheckPwdTestCase(SambaToolCmdTest):
                                             "--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.")
+        self.assertCmdFail(result, "Should fail setting a user's password to a %s password." % desc)
 
         (result, out, err) = self.runsubcmd("user", "setpassword", user["name"],
                                             "--newpassword=%s" % good_password,
@@ -81,7 +77,7 @@ class UserCheckPwdTestCase(SambaToolCmdTest):
                                             "--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.")
+        self.assertCmdFail(result, "A user setting their own password to a %s password should fail." % desc)
 
         (result, out, err) = self.runsubcmd("user", "password",
                                             "--newpassword=%s" % good_password + 'XYZ',
@@ -89,6 +85,26 @@ class UserCheckPwdTestCase(SambaToolCmdTest):
                                             "-U%s%%%s" % (user["name"], good_password))
         self.assertCmdSuccess(result, out, err, "A user setting their own password to a good one should succeed.")
 
+    def test_checkpassword_unacceptable(self):
+        # Add
+        user = self._randomUser()
+        bad_password = os.environ["UNACCEPTABLE_PASSWORD"]
+        good_password = bad_password[:-1]
+        return self._test_checkpassword(user,
+                                        bad_password,
+                                        good_password,
+                                        "unacceptable")
+
+    def test_checkpassword_username(self):
+        # Add
+        user = self._randomUser()
+        bad_password = user["name"]
+        good_password = bad_password[:-1]
+        return self._test_checkpassword(user,
+                                        bad_password,
+                                        good_password,
+                                        "username")
+
     def _randomUser(self, base={}):
         """create a user with random attribute values, you can specify base attributes"""
         user = {
diff --git a/selftest/checkpassword_arg1.sh b/selftest/checkpassword_arg1.sh
index 9cb28ef198cf..8bb2aad972b1 100755
--- a/selftest/checkpassword_arg1.sh
+++ b/selftest/checkpassword_arg1.sh
@@ -4,6 +4,7 @@
 set -e
 set -u
 
+ACCOUNT_NAME="${SAMBA_CPS_ACCOUNT_NAME-}"
 INVALIDPW="$1"
 NEWPW=`cat -`
 
@@ -12,4 +13,9 @@ echo -n "${NEWPW}" | grep -q "^${INVALIDPW}\$" && {
 	exit 1
 }
 
+echo -n "${NEWPW}" | grep -q "^${ACCOUNT_NAME}\$" && {
+	echo "Password includes ACCOUNT_NAME" >&1
+	exit 1
+}
+
 exit 0
diff --git a/selftest/knownfail.d/user_check_password_script b/selftest/knownfail.d/user_check_password_script
new file mode 100644
index 000000000000..7d6e0823a651
--- /dev/null
+++ b/selftest/knownfail.d/user_check_password_script
@@ -0,0 +1 @@
+^samba.tests.samba_tool.user_check_password_script.*samba.tests.samba_tool.user_check_password_script.UserCheckPwdTestCase.test_checkpassword_username
-- 
2.17.1


From ac1e216d0d7e0f1e3fe7c4103b8562a9d22256e8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 22 Jan 2019 11:33:23 +0100
Subject: [PATCH 6/9] s4:dsdb:util: export
 SAMBA_CPS_{ACCOUNT,USER_PRINCIPAL,FULL}_NAME for check password script

This allows the check password script to reject the username and other
things.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 .../knownfail.d/user_check_password_script    |  1 -
 source4/dsdb/common/util.c                    | 19 +++++++++++++++++++
 .../dsdb/samdb/ldb_modules/password_hash.c    |  7 +++++++
 source4/rpc_server/samr/dcesrv_samr.c         |  9 +++++++++
 4 files changed, 35 insertions(+), 1 deletion(-)
 delete mode 100644 selftest/knownfail.d/user_check_password_script

diff --git a/selftest/knownfail.d/user_check_password_script b/selftest/knownfail.d/user_check_password_script
deleted file mode 100644
index 7d6e0823a651..000000000000
--- a/selftest/knownfail.d/user_check_password_script
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.samba_tool.user_check_password_script.*samba.tests.samba_tool.user_check_password_script.UserCheckPwdTestCase.test_checkpassword_username
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 3ac21d0e43ce..4b63504009cb 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -2083,6 +2083,9 @@ static void pwd_timeout_debug(struct tevent_context *unused1,
  */
 enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
 						struct loadparm_context *lp_ctx,
+						const char *account_name,
+						const char *user_principal_name,
+						const char *full_name,
 						const DATA_BLOB *utf8_blob,
 						const uint32_t pwdProperties,
 						const uint32_t minPwdLength)
@@ -2129,9 +2132,25 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx,
 				 tevent_timeval_current_ofs(1, 0),
 				 pwd_timeout_debug, NULL);
 
+		setenv("SAMBA_CPS_ACCOUNT_NAME", account_name, 1);
+		if (user_principal_name != NULL) {
+			setenv("SAMBA_CPS_USER_PRINCIPAL_NAME",
+			       user_principal_name, 1);
+		} else {
+			unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
+		}
+		if (full_name != NULL) {
+			setenv("SAMBA_CPS_FULL_NAME", full_name, 1);
+		} else {
+			unsetenv("SAMBA_CPS_FULL_NAME");
+		}
+
 		req = samba_runcmd_send(event_ctx, event_ctx,
 					tevent_timeval_current_ofs(10, 0),
 					100, 100, cmd, NULL);
+		unsetenv("SAMBA_CPS_ACCOUNT_NAME");
+		unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
+		unsetenv("SAMBA_CPS_FULL_NAME");
 		if (req == NULL) {
 			TALLOC_FREE(password_script);
 			TALLOC_FREE(event_ctx);
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 5f5710330044..51fd70b7c1db 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -130,6 +130,7 @@ struct setup_password_fields_io {
 		NTTIME pwdLastSet;
 		const char *sAMAccountName;
 		const char *user_principal_name;
+		const char *displayName; /* full name */
 		bool is_krbtgt;
 		uint32_t restrictions;
 		struct dom_sid *account_sid;
@@ -2716,6 +2717,9 @@ static int check_password_restrictions(struct setup_password_fields_io *io, WERR
 	if (io->n.cleartext_utf8 != NULL) {
 		enum samr_ValidationStatus vstat;
 		vstat = samdb_check_password(io->ac, lp_ctx,
+					     io->u.sAMAccountName,
+					     io->u.user_principal_name,
+					     io->u.displayName,
 					     io->n.cleartext_utf8,
 					     io->ac->status->domain_data.pwdProperties,
 					     io->ac->status->domain_data.minPwdLength);
@@ -3191,6 +3195,8 @@ static int setup_io(struct ph_context *ac,
 								      "sAMAccountName", NULL);
 	io->u.user_principal_name	= ldb_msg_find_attr_as_string(info_msg,
 								      "userPrincipalName", NULL);
+	io->u.displayName		= ldb_msg_find_attr_as_string(info_msg,
+								      "displayName", NULL);
 
 	/* Ensure it has an objectSID too */
 	io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
@@ -4707,6 +4713,7 @@ static int password_hash_mod_search_self(struct ph_context *ac)
 					      "sAMAccountName",
 					      "objectSid",
 					      "userPrincipalName",
+					      "displayName",
 					      "supplementalCredentials",
 					      "lmPwdHistory",
 					      "ntPwdHistory",
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 51fed4da62b3..84400284f42c 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -4871,6 +4871,7 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
 {
 	struct samr_GetDomPwInfo r2;
 	struct samr_PwInfo pwInfo;
+	const char *account = NULL;
 	DATA_BLOB password;
 	enum samr_ValidationStatus res;
 	NTSTATUS status;
@@ -4905,20 +4906,28 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
 		return NT_STATUS_NOT_SUPPORTED;
 	break;
 	case NetValidatePasswordChange:
+		account = r->in.req->req2.account.string;
 		password = data_blob_const(r->in.req->req2.password.string,
 					   r->in.req->req2.password.length);
 		res = samdb_check_password(mem_ctx,
 					   dce_call->conn->dce_ctx->lp_ctx,
+					   account,
+					   NULL, /* userPrincipalName */
+					   NULL, /* displayName/full_name */
 					   &password,
 					   pwInfo.password_properties,
 					   pwInfo.min_password_length);
 		(*r->out.rep)->ctr2.status = res;
 	break;
 	case NetValidatePasswordReset:
+		account = r->in.req->req3.account.string;
 		password = data_blob_const(r->in.req->req3.password.string,
 					   r->in.req->req3.password.length);
 		res = samdb_check_password(mem_ctx,
 					   dce_call->conn->dce_ctx->lp_ctx,
+					   account,
+					   NULL, /* userPrincipalName */
+					   NULL, /* displayName/full_name */
 					   &password,
 					   pwInfo.password_properties,
 					   pwInfo.min_password_length);
-- 
2.17.1


From 5c90725d5002c6e366e7a5e3a5c1978b76fbdf48 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 5 Feb 2019 16:15:15 +0100
Subject: [PATCH 7/9] selftest: require SAMBA_CPS_ACCOUNT_NAME in
 checkpassword_arg1.sh

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 selftest/checkpassword_arg1.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/selftest/checkpassword_arg1.sh b/selftest/checkpassword_arg1.sh
index 8bb2aad972b1..42e1b5e7df5a 100755
--- a/selftest/checkpassword_arg1.sh
+++ b/selftest/checkpassword_arg1.sh
@@ -4,7 +4,7 @@
 set -e
 set -u
 
-ACCOUNT_NAME="${SAMBA_CPS_ACCOUNT_NAME-}"
+ACCOUNT_NAME="${SAMBA_CPS_ACCOUNT_NAME}"
 INVALIDPW="$1"
 NEWPW=`cat -`
 
-- 
2.17.1


From cef73f49e56bddec5afa8c13f4361886341e0cc7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 2 Feb 2019 13:19:31 +0100
Subject: [PATCH 8/9] s3:srv_samr_chgpasswd: export
 SAMBA_CPS_{ACCOUNT,USER_PRINCIPAL,FULL}_NAME for check password script

This is keep compatibility with the AD DC usage.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/rpc_server/samr/srv_samr_chgpasswd.c | 17 ++++++++++++++++-
 source3/rpc_server/samr/srv_samr_nt.c        |  2 ++
 source3/rpc_server/samr/srv_samr_util.h      |  1 +
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c
index 87a3f32ff134..4affedb45cb7 100644
--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c
+++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c
@@ -941,6 +941,7 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext)
 ************************************************************/
 
 NTSTATUS check_password_complexity(const char *username,
+				   const char *fullname,
 				   const char *password,
 				   enum samPwdChangeReason *samr_reject_reason)
 {
@@ -960,7 +961,17 @@ NTSTATUS check_password_complexity(const char *username,
 		return NT_STATUS_PASSWORD_RESTRICTION;
 	}
 
+	setenv("SAMBA_CPS_ACCOUNT_NAME", username, 1);
+	unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
+	if (fullname != NULL) {
+		setenv("SAMBA_CPS_FULL_NAME", fullname, 1);
+	} else {
+		unsetenv("SAMBA_CPS_FULL_NAME");
+	}
 	check_ret = smbrunsecret(cmd, password);
+	unsetenv("SAMBA_CPS_ACCOUNT_NAME");
+	unsetenv("SAMBA_CPS_USER_PRINCIPAL_NAME");
+	unsetenv("SAMBA_CPS_FULL_NAME");
 	DEBUG(5,("check_password_complexity: check password script (%s) "
 		 "returned [%d]\n", cmd, check_ret));
 	TALLOC_FREE(cmd);
@@ -995,6 +1006,7 @@ static NTSTATUS change_oem_password(struct samu *hnd, const char *rhost,
 	TALLOC_CTX *tosctx = talloc_tos();
 	struct passwd *pass = NULL;
 	const char *username = pdb_get_username(hnd);
+	const char *fullname = pdb_get_fullname(hnd);
 	time_t can_change_time = pdb_get_pass_can_change_time(hnd);
 	NTSTATUS status;
 
@@ -1062,7 +1074,10 @@ static NTSTATUS change_oem_password(struct samu *hnd, const char *rhost,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	status = check_password_complexity(username, new_passwd, samr_reject_reason);
+	status = check_password_complexity(username,
+					   fullname,
+					   new_passwd,
+					   samr_reject_reason);
 	if (!NT_STATUS_IS_OK(status)) {
 		TALLOC_FREE(pass);
 		return status;
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
index 70a2efa4ca63..124d6d38cd70 100644
--- a/source3/rpc_server/samr/srv_samr_nt.c
+++ b/source3/rpc_server/samr/srv_samr_nt.c
@@ -6725,6 +6725,7 @@ static enum samr_ValidationStatus samr_ValidatePassword_Change(TALLOC_CTX *mem_c
 	}
 	if (dom_pw_info->password_properties & DOMAIN_PASSWORD_COMPLEX) {
 		status = check_password_complexity(req->account.string,
+						   NULL, /* full_name */
 						   req->password.string,
 						   NULL);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -6755,6 +6756,7 @@ static enum samr_ValidationStatus samr_ValidatePassword_Reset(TALLOC_CTX *mem_ct
 	}
 	if (dom_pw_info->password_properties & DOMAIN_PASSWORD_COMPLEX) {
 		status = check_password_complexity(req->account.string,
+						   NULL, /* full_name */
 						   req->password.string,
 						   NULL);
 		if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/rpc_server/samr/srv_samr_util.h b/source3/rpc_server/samr/srv_samr_util.h
index f992e2b90826..c0c4808f330e 100644
--- a/source3/rpc_server/samr/srv_samr_util.h
+++ b/source3/rpc_server/samr/srv_samr_util.h
@@ -75,5 +75,6 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
 			 const uchar old_nt_hash_encrypted[16],
 			 enum samPwdChangeReason *reject_reason);
 NTSTATUS check_password_complexity(const char *username,
+				   const char *fullname,
 				   const char *password,
 				   enum samPwdChangeReason *samr_reject_reason);
-- 
2.17.1


From e90f8f17d2425f3e9e9529e39e61a1faa320c434 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 4 Feb 2019 15:40:16 +0100
Subject: [PATCH 9/9] docs-xml/smbdotconf: document export of
 SAMBA_CPS_{ACCOUNT,USER_PRINCIPAL,FULL}_NAME for check password script

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 .../smbdotconf/security/checkpasswordscript.xml | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/docs-xml/smbdotconf/security/checkpasswordscript.xml b/docs-xml/smbdotconf/security/checkpasswordscript.xml
index 54f1096802b9..1e9031fda42b 100644
--- a/docs-xml/smbdotconf/security/checkpasswordscript.xml
+++ b/docs-xml/smbdotconf/security/checkpasswordscript.xml
@@ -15,6 +15,23 @@
     <citerefentry><refentrytitle>samba</refentrytitle> <manvolnum>8</manvolnum>
     </citerefentry> without any substitutions.</para>
 
+    <para>Note that starting with Samba 4.11 the following environment variables are exported to the script:</para>
+
+    <itemizedlist>
+	<listitem><para>
+	SAMBA_CPS_ACCOUNT_NAME is always present and contains the sAMAccountName of user,
+	the is the same as the %u substitutions in the none AD DC case.
+	</para></listitem>
+
+	<listitem><para>
+	SAMBA_CPS_USER_PRINCIPAL_NAME is optional in the AD DC case if the userPrincipalName is present.
+	</para></listitem>
+
+	<listitem><para>
+	SAMBA_CPS_FULL_NAME is optional if the displayName is present.
+	</para></listitem>
+    </itemizedlist>
+
     <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>
 
-- 
2.17.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190206/2736d8cc/signature.sig>


More information about the samba-technical mailing list