2 Unix SMB/CIFS implementation.
4 Copyright (C) David Mulder 2017
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "param/param.h"
22 #include "param/loadparm.h"
23 #include "torture/smbtorture.h"
24 #include "lib/util/mkdir_p.h"
25 #include "dsdb/samdb/samdb.h"
26 #include "auth/session.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "torture/gpo/proto.h"
30 #include "lib/util/samba_util.h"
31 #include "util/tevent_ntstatus.h"
35 struct torture_suite
*gpo_apply_suite(TALLOC_CTX
*ctx
)
37 struct torture_suite
*suite
= torture_suite_create(ctx
, "apply");
39 torture_suite_add_simple_test(suite
, "gpo_param_from_gpo",
40 torture_gpo_system_access_policies
);
42 suite
->description
= talloc_strdup(suite
, "Group Policy apply tests");
47 static int exec_wait(struct torture_context
*tctx
, const char **gpo_update_cmd
)
51 struct tevent_req
*req
;
53 req
= samba_runcmd_send(tctx
,
55 timeval_current_ofs(100, 0),
58 "gpo_reload_cmd", NULL
);
63 if (!tevent_req_poll_ntstatus(req
, tctx
->ev
, &status
)) {
66 if (samba_runcmd_recv(req
, &ret
) != 0) {
72 static int unix2nttime(const char *sval
)
74 return (strtoll(sval
, NULL
, 10) * -1 / 60 / 60 / 24 / 10000000);
77 #define GPODIR "addom.samba.example.com/Policies/"\
78 "{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/"\
80 #define GPOFILE "GptTmpl.inf"
81 #define GPTTMPL "[System Access]\n\
82 MinimumPasswordAge = %d\n\
83 MaximumPasswordAge = %d\n\
84 MinimumPasswordLength = %d\n\
85 PasswordComplexity = %d\n\
87 #define GPTINI "addom.samba.example.com/Policies/"\
88 "{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI"
90 bool torture_gpo_system_access_policies(struct torture_context
*tctx
)
92 TALLOC_CTX
*ctx
= talloc_new(tctx
);
94 const char *sysvol_path
= NULL
, *gpo_dir
= NULL
;
95 const char *gpo_file
= NULL
, *gpt_file
= NULL
;
96 struct ldb_context
*samdb
= NULL
;
97 struct ldb_result
*result
;
98 const char *attrs
[] = {
106 const char **gpo_update_cmd
;
107 const char **gpo_unapply_cmd
;
108 const char **gpo_update_force_cmd
;
109 int minpwdcases
[] = { 0, 1, 998 };
110 int maxpwdcases
[] = { 0, 1, 999 };
111 int pwdlencases
[] = { 0, 1, 14 };
112 int pwdpropcases
[] = { 0, 1, 1 };
113 struct ldb_message
*old_message
= NULL
;
115 int gpo_update_len
= 0;
117 sysvol_path
= lpcfg_path(lpcfg_service(tctx
->lp_ctx
, "sysvol"),
118 lpcfg_default_service(tctx
->lp_ctx
), tctx
);
119 torture_assert(tctx
, sysvol_path
, "Failed to fetch the sysvol path");
121 /* Ensure the sysvol path exists */
122 gpo_dir
= talloc_asprintf(ctx
, "%s/%s", sysvol_path
, GPODIR
);
123 mkdir_p(gpo_dir
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
124 gpo_file
= talloc_asprintf(ctx
, "%s/%s", gpo_dir
, GPOFILE
);
126 /* Get the gpo update command */
127 gpo_update_cmd
= lpcfg_gpo_update_command(tctx
->lp_ctx
);
128 torture_assert(tctx
, gpo_update_cmd
&& gpo_update_cmd
[0],
129 "Failed to fetch the gpo update command");
131 /* Open and read the samba db and store the initial password settings */
132 samdb
= samdb_connect(ctx
,
135 system_session(tctx
->lp_ctx
),
138 torture_assert(tctx
, samdb
, "Failed to connect to the samdb");
140 ret
= ldb_search(samdb
, ctx
, &result
, ldb_get_default_basedn(samdb
),
141 LDB_SCOPE_BASE
, attrs
, NULL
);
142 torture_assert(tctx
, ret
== LDB_SUCCESS
&& result
->count
== 1,
143 "Searching the samdb failed");
145 old_message
= result
->msgs
[0];
147 for (i
= 0; i
< 3; i
++) {
148 /* Write out the sysvol */
149 if ( (fp
= fopen(gpo_file
, "w")) ) {
150 fputs(talloc_asprintf(ctx
, GPTTMPL
, minpwdcases
[i
],
151 maxpwdcases
[i
], pwdlencases
[i
],
152 pwdpropcases
[i
]), fp
);
156 /* Update the version in the GPT.INI */
157 gpt_file
= talloc_asprintf(ctx
, "%s/%s", sysvol_path
, GPTINI
);
158 if ( (fp
= fopen(gpt_file
, "r")) ) {
160 while (fgets(line
, 256, fp
)) {
161 if (strncasecmp(line
, "Version=", 8) == 0) {
168 if ( (fp
= fopen(gpt_file
, "w")) ) {
169 char *data
= talloc_asprintf(ctx
,
170 "[General]\nVersion=%d\n",
176 /* Run the gpo update command */
177 ret
= exec_wait(tctx
, gpo_update_cmd
);
179 torture_assert(tctx
, ret
== 0,
180 "Failed to execute the gpo update command");
181 ret
= ldb_search(samdb
, ctx
, &result
,
182 ldb_get_default_basedn(samdb
),
183 LDB_SCOPE_BASE
, attrs
, NULL
);
184 torture_assert(tctx
, ret
== LDB_SUCCESS
&& result
->count
== 1,
185 "Searching the samdb failed");
188 torture_assert_int_equal(tctx
, unix2nttime(
189 ldb_msg_find_attr_as_string(
192 "")), minpwdcases
[i
],
193 "The minPwdAge was not applied");
196 torture_assert_int_equal(tctx
, unix2nttime(
197 ldb_msg_find_attr_as_string(
200 "")), maxpwdcases
[i
],
201 "The maxPwdAge was not applied");
204 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
209 "The minPwdLength was not applied");
212 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
217 "The pwdProperties were not applied");
220 /* Reset settings, then verify a reapply doesn't force them back */
221 for (i
= 0; i
< old_message
->num_elements
; i
++) {
222 old_message
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
224 ret
= ldb_modify(samdb
, old_message
);
225 torture_assert(tctx
, ret
== 0, "Failed to reset password settings.");
227 ret
= exec_wait(tctx
, gpo_update_cmd
);
228 torture_assert(tctx
, ret
== 0,
229 "Failed to execute the gpo update command");
231 /* Validate that the apply did nothing (without --force param) */
232 ret
= ldb_search(samdb
, ctx
, &result
, ldb_get_default_basedn(samdb
),
233 LDB_SCOPE_BASE
, attrs
, NULL
);
234 torture_assert(tctx
, ret
== LDB_SUCCESS
&& result
->count
== 1,
235 "Searching the samdb failed");
237 torture_assert_int_equal(tctx
, unix2nttime(ldb_msg_find_attr_as_string(
241 unix2nttime(ldb_msg_find_attr_as_string(old_message
,
245 "The minPwdAge was re-applied");
247 torture_assert_int_equal(tctx
, unix2nttime(ldb_msg_find_attr_as_string(
251 unix2nttime(ldb_msg_find_attr_as_string(old_message
,
255 "The maxPwdAge was re-applied");
257 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
261 ldb_msg_find_attr_as_int(
265 "The minPwdLength was re-applied");
267 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
271 ldb_msg_find_attr_as_int(
275 "The pwdProperties were re-applied");
277 for (itr
= gpo_update_cmd
; *itr
!= NULL
; itr
++) {
281 /* Run gpupdate --force and verify settings are re-applied */
282 gpo_update_force_cmd
= talloc_array(ctx
, const char*, gpo_update_len
+2);
283 for (i
= 0; i
< gpo_update_len
; i
++) {
284 gpo_update_force_cmd
[i
] = talloc_strdup(gpo_update_force_cmd
,
287 gpo_update_force_cmd
[i
] = talloc_asprintf(gpo_update_force_cmd
,
289 gpo_update_force_cmd
[i
+1] = NULL
;
290 ret
= exec_wait(tctx
, gpo_update_force_cmd
);
291 torture_assert(tctx
, ret
== 0,
292 "Failed to execute the gpupdate --force command");
294 ret
= ldb_search(samdb
, ctx
, &result
,
295 ldb_get_default_basedn(samdb
),
296 LDB_SCOPE_BASE
, attrs
, NULL
);
297 torture_assert(tctx
, ret
== LDB_SUCCESS
&& result
->count
== 1,
298 "Searching the samdb failed");
301 torture_assert_int_equal(tctx
, unix2nttime(
302 ldb_msg_find_attr_as_string(
305 "")), minpwdcases
[2],
306 "The minPwdAge was not applied");
309 torture_assert_int_equal(tctx
, unix2nttime(
310 ldb_msg_find_attr_as_string(
313 "")), maxpwdcases
[2],
314 "The maxPwdAge was not applied");
317 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
322 "The minPwdLength was not applied");
325 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
330 "The pwdProperties were not applied");
332 /* Unapply the settings and verify they are removed */
333 gpo_unapply_cmd
= talloc_array(ctx
, const char*, gpo_update_len
+2);
334 for (i
= 0; i
< gpo_update_len
; i
++) {
335 gpo_unapply_cmd
[i
] = talloc_strdup(gpo_unapply_cmd
,
338 gpo_unapply_cmd
[i
] = talloc_asprintf(gpo_unapply_cmd
, "--unapply");
339 gpo_unapply_cmd
[i
+1] = NULL
;
340 ret
= exec_wait(tctx
, gpo_unapply_cmd
);
341 torture_assert(tctx
, ret
== 0,
342 "Failed to execute the gpo unapply command");
343 ret
= ldb_search(samdb
, ctx
, &result
, ldb_get_default_basedn(samdb
),
344 LDB_SCOPE_BASE
, attrs
, NULL
);
345 torture_assert(tctx
, ret
== LDB_SUCCESS
&& result
->count
== 1,
346 "Searching the samdb failed");
348 torture_assert_int_equal(tctx
, unix2nttime(ldb_msg_find_attr_as_string(
352 unix2nttime(ldb_msg_find_attr_as_string(old_message
,
356 "The minPwdAge was not unapplied");
358 torture_assert_int_equal(tctx
, unix2nttime(ldb_msg_find_attr_as_string(
362 unix2nttime(ldb_msg_find_attr_as_string(old_message
,
366 "The maxPwdAge was not unapplied");
368 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
372 ldb_msg_find_attr_as_int(
376 "The minPwdLength was not unapplied");
378 torture_assert_int_equal(tctx
, ldb_msg_find_attr_as_int(
382 ldb_msg_find_attr_as_int(
386 "The pwdProperties were not unapplied");