[PATCH 22/23] gpo: Add gpo tests

David Mulder dmulder at suse.com
Fri Mar 10 16:09:29 UTC 2017


Lays down a sysvol gpttmpl.inf with password policies, then runs the samba_gpoupdate command. Verifies policies are applied to the samdb.

Signed-off-by: David Mulder <dmulder at suse.com>
---
 python/samba/gpclass.py           |   5 +-
 selftest/target/Samba4.pm         |   1 +
 source4/selftest/tests.py         |   4 +
 source4/torture/gpo/apply.c       | 189 ++++++++++++++++++++++++++++++++++++++
 source4/torture/gpo/gpo.c         |  36 ++++++++
 source4/torture/gpo/wscript_build |  14 +++
 source4/torture/wscript_build     |   1 +
 7 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 source4/torture/gpo/apply.c
 create mode 100644 source4/torture/gpo/gpo.c
 create mode 100644 source4/torture/gpo/wscript_build

diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index c8f8c79..81580d9 100755
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -134,7 +134,10 @@ class gp_sec_ext(gp_ext):
         ret = False
         inftable = self.populate_inf()
 
-        policy = conn.loadfile(path.replace('/', '\\')).decode('utf-16')
+        try:
+            policy = conn.loadfile(path.replace('/', '\\')).decode('utf-16')
+        except ValueError:
+            policy = conn.loadfile(path.replace('/', '\\')) # Handle ascii files created by linux
         current_section = None
         LOG = open(attr_log, "a")
         LOG.write(str(path.split('/')[2]) + '\n')
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index dacdab4..681c199 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -582,6 +582,7 @@ sub provision_raw_step1($$)
 	rndc command = true
 	dns update command = $ctx->{samba_dnsupdate}
 	spn update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_spnupdate -s $ctx->{smb_conf}
+	gpo update command = $ENV{SRCDIR_ABS}/source4/scripting/bin/samba_gpoupdate -s $ctx->{smb_conf}
 	dreplsrv:periodic_startup_interval = 0
 	dsdb:schema update allowed = yes
 
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 93635d9..7231c6a 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -237,6 +237,10 @@ for env in ["ad_dc_ntvfs", "nt4_dc"]:
 plantestsuite("samba.blackbox.pdbtest.s4winbind(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_pdbtest.sh"), '$SERVER', "$PREFIX", "pdbtest3", smbclient4, '$SMB_CONF_PATH', configuration + " --option='authmethods=samba4:winbind'"])
 plantestsuite("samba.blackbox.pdbtest.s4winbind_wbclient(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_pdbtest.sh"), '$SERVER', "$PREFIX", "pdbtest4", smbclient4, '$SMB_CONF_PATH', configuration + " --option='authmethods=samba4:winbind_wbclient'"])
 
+gpo = smbtorture4_testsuites("gpo.")
+for t in gpo:
+    plansmbtorture4testsuite(t, 'ad_dc:local', ['//$SERVER/sysvol', '-U$USERNAME%$PASSWORD'])
+
 transports = ["ncacn_np", "ncacn_ip_tcp"]
 
 #Kerberos varies between functional levels, so it is important to check this on all of them
diff --git a/source4/torture/gpo/apply.c b/source4/torture/gpo/apply.c
new file mode 100644
index 0000000..a9944ab0
--- /dev/null
+++ b/source4/torture/gpo/apply.c
@@ -0,0 +1,189 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) David Mulder 2017
+   
+   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 "includes.h"
+#include "param/param.h"
+#include "param/loadparm.h"
+#include "torture/smbtorture.h"
+#include "lib/util/mkdir_p.h"
+#include "dsdb/samdb/samdb.h"
+#include "auth/session.h"
+#include "lib/ldb/include/ldb.h"
+#include "torture/gpo/proto.h"
+
+struct torture_suite *gpo_apply_suite(TALLOC_CTX *ctx)
+{
+	struct torture_suite *suite = torture_suite_create(ctx, "apply");
+
+	torture_suite_add_simple_test(suite, "gpo_param_from_gpo", torture_gpo_system_access_policies);
+
+	suite->description = talloc_strdup(suite, "Group Policy apply tests");
+
+	return suite;
+}
+
+static char* convert_param(struct torture_context *tctx, struct parm_struct *parm, void *parm_ptr)
+{
+	switch (parm->type) {
+		case P_CHAR:
+			return talloc_asprintf(tctx, "%c", *(char *)parm_ptr);
+		case P_STRING:
+		case P_USTRING:
+			return talloc_strdup(tctx, *(char **)parm_ptr);;
+		case P_CMDLIST:
+		case P_LIST:
+		{
+			int j, len = 0;
+			const char **strlist = *(const char ***)parm_ptr;
+			char *result = NULL;
+
+			if (strlist == NULL)
+				return NULL;
+
+			for (j = 0; strlist[j]; j++) {
+				int len_chunk = strlen(strlist[j])+1;
+				result = talloc_realloc(tctx, result, char, len+len_chunk);
+				memcpy(result+len, strlist[j], len_chunk);
+				len += len_chunk;
+				result[len-1] = ' ';
+			}
+			result[len-1] = '\0'; // Terminate the string
+			return result;
+		}
+		case P_BOOL:
+		case P_BOOLREV:
+		case P_INTEGER:
+		case P_OCTAL:
+		case P_BYTES:
+		case P_ENUM:
+		default:
+			return NULL; // TODO: implement the other types if needed
+	}
+	return NULL;
+}
+
+static const char* lp_get_param(struct torture_context *tctx, const char *service_name, const char *param_name)
+{
+	struct parm_struct *parm = NULL;
+	struct loadparm_service *service;
+	void *parm_ptr = NULL;
+
+	if (service_name) {
+		service = lpcfg_service(tctx->lp_ctx, service_name);
+		torture_assert(tctx, service, talloc_asprintf(tctx, "Failed to find %s", service_name));
+		parm = lpcfg_parm_struct(tctx->lp_ctx, param_name);
+		torture_assert(tctx, parm, talloc_asprintf(tctx, "Failed to find %s %s", service_name, param_name));
+		parm_ptr = lpcfg_parm_ptr(tctx->lp_ctx, service, parm);
+		torture_assert(tctx, parm_ptr, talloc_asprintf(tctx, "Failed to find %s %s", service_name, param_name));
+	} else {
+		parm = lpcfg_parm_struct(tctx->lp_ctx, param_name);
+		torture_assert(tctx, parm, talloc_asprintf(tctx, "Failed to find %s", param_name));
+		parm_ptr = lpcfg_parm_ptr(tctx->lp_ctx, NULL, parm);
+		torture_assert(tctx, parm, talloc_asprintf(tctx, "Failed to find %s", param_name));
+	}
+	return convert_param(tctx, parm, parm_ptr);
+}
+
+#define GPODIR "addom.samba.example.com/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/Windows NT/SecEdit"
+#define GPOFILE "GptTmpl.inf"
+#define GPTTMPL "[System Access]\n\
+MinimumPasswordAge = 2\n\
+MaximumPasswordAge = 37\n\
+MinimumPasswordLength = 11\n\
+PasswordComplexity = 2\n\
+"
+#define GPTINI "addom.samba.example.com/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI"
+
+bool torture_gpo_system_access_policies(struct torture_context *tctx)
+{
+	int ret, vers = 0;
+	const char *gpo_update_cmd = NULL, *sysvol_path = NULL, *gpo_dir = NULL, *gpo_file = NULL, *gpt_file = NULL;
+	struct ldb_context *samdb = NULL;
+	struct ldb_result *result;
+	const char *attrs[] = {
+		"minPwdAge",
+		"maxPwdAge",
+		"minPwdLength",
+		"pwdProperties",
+		NULL
+	};
+	const struct ldb_val *val;
+	FILE *fp = NULL;
+
+	sysvol_path = lp_get_param(tctx, "sysvol", "path");
+	torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");
+	gpo_update_cmd = lp_get_param(tctx, NULL, "gpo update command");
+	torture_assert(tctx, gpo_update_cmd, "Failed to fetch the gpo update command");
+
+	/* Write out the sysvol */
+	gpo_dir = talloc_asprintf(tctx, "%s/%s", sysvol_path, GPODIR);
+	mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+	gpo_file = talloc_asprintf(tctx, "%s/%s", gpo_dir, GPOFILE);
+	if ( (fp = fopen(gpo_file, "w")) ) {
+		fputs(GPTTMPL, fp);
+		fclose(fp);
+	}
+
+	/* Update the version in the GPT.INI */
+	gpt_file = talloc_asprintf(tctx, "%s/%s", sysvol_path, GPTINI);
+	if ( (fp = fopen(gpt_file, "r")) ) {
+		char line[256];
+		while (fgets(line, 256, fp)) {
+			if (strncasecmp(line, "Version=", 8) == 0) {
+				vers = atoi(line+8);
+				break;
+			}
+		}
+		fclose(fp);
+	}
+	if ( (fp = fopen(gpt_file, "w")) ) {
+		char *data = talloc_asprintf(tctx, "[General]\nVersion=%d\n", ++vers);
+		fputs(data, fp);
+		fclose(fp);
+	}
+
+	/* Run the gpo update command */
+	system(gpo_update_cmd);
+
+	/* Open and read the samba db and verify the settings applied */
+	samdb = samdb_connect(tctx, tctx->ev, tctx->lp_ctx, system_session(tctx->lp_ctx), 0);
+	torture_assert(tctx, samdb, "Failed to connect to the samdb");
+
+	ret = ldb_search(samdb, tctx, &result, ldb_get_default_basedn(samdb), LDB_SCOPE_BASE, attrs, NULL);
+	torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1, "Searching the samdb failed");
+
+	/* minPwdAge */
+	val = ldb_msg_find_ldb_val(result->msgs[0], attrs[0]);
+	torture_assert(tctx, strcmp((char*)val->data, "-1728000000000") == 0, "The minPwdAge was not applied");
+
+	/* maxPwdAge */
+	val = ldb_msg_find_ldb_val(result->msgs[0], attrs[1]);
+	torture_assert(tctx, strcmp((char*)val->data, "-31968000000000") == 0, "The maxPwdAge was not applied");
+
+	/* minPwdLength */
+	val = ldb_msg_find_ldb_val(result->msgs[0], attrs[2]);
+	torture_assert(tctx, atoi((char*)val->data) == 11, "The minPwdLength was not applied");
+
+	/* pwdProperties */
+	val = ldb_msg_find_ldb_val(result->msgs[0], attrs[3]);
+	torture_assert(tctx, atoi((char*)val->data) == 2, "The pwdProperties were not applied");
+
+	return true;
+}
+
diff --git a/source4/torture/gpo/gpo.c b/source4/torture/gpo/gpo.c
new file mode 100644
index 0000000..ded4404
--- /dev/null
+++ b/source4/torture/gpo/gpo.c
@@ -0,0 +1,36 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) David Mulder 2017
+   
+   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 "includes.h"
+#include "torture/smbtorture.h"
+#include "torture/gpo/proto.h"
+
+NTSTATUS torture_gpo_init(void)
+{
+    struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "gpo");
+
+    torture_suite_add_suite(suite, gpo_apply_suite(suite));
+
+    suite->description = talloc_strdup(suite, "Group Policy tests");
+
+    torture_register_suite(suite);
+
+    return NT_STATUS_OK;
+}
+
diff --git a/source4/torture/gpo/wscript_build b/source4/torture/gpo/wscript_build
new file mode 100644
index 0000000..c92bbf7
--- /dev/null
+++ b/source4/torture/gpo/wscript_build
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+bld.SAMBA_MODULE('TORTURE_GPO',
+	source='''
+        gpo.c
+        apply.c
+        ''',
+	subsystem='smbtorture',
+	deps='torture mkdir_p',
+	internal_module=True,
+	autoproto='proto.h',
+	init_function='torture_gpo_init'
+	)
+
diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build
index c065eaa..b235baa 100644
--- a/source4/torture/wscript_build
+++ b/source4/torture/wscript_build
@@ -31,6 +31,7 @@ bld.RECURSE('smb2')
 bld.RECURSE('winbind')
 bld.RECURSE('libnetapi')
 bld.RECURSE('libsmbclient')
+bld.RECURSE('gpo')
 
 ntvfs_specific = dict(source='', deps='')
 
-- 
2.10.2




More information about the samba-technical mailing list