Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) David Mulder 2017
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
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"
29 : #include <unistd.h>
30 : #include "lib/util/samba_util.h"
31 : #include "util/tevent_ntstatus.h"
32 :
33 : #undef strncasecmp
34 :
35 2354 : struct torture_suite *gpo_apply_suite(TALLOC_CTX *ctx)
36 : {
37 2354 : struct torture_suite *suite = torture_suite_create(ctx, "apply");
38 :
39 2354 : torture_suite_add_simple_test(suite, "gpo_param_from_gpo",
40 : torture_gpo_system_access_policies);
41 :
42 2354 : suite->description = talloc_strdup(suite, "Group Policy apply tests");
43 :
44 2354 : return suite;
45 : }
46 :
47 12 : static int exec_wait(struct torture_context *tctx, const char **gpo_update_cmd)
48 : {
49 0 : NTSTATUS status;
50 12 : int ret = 0;
51 0 : struct tevent_req *req;
52 :
53 12 : req = samba_runcmd_send(tctx,
54 : tctx->ev,
55 : timeval_current_ofs(100, 0),
56 : 2, 0,
57 : gpo_update_cmd,
58 : "gpo_reload_cmd", NULL);
59 12 : if (req == NULL) {
60 0 : return -1;
61 : }
62 :
63 12 : if (!tevent_req_poll_ntstatus(req, tctx->ev, &status)) {
64 0 : return -1;
65 : }
66 12 : if (samba_runcmd_recv(req, &ret) != 0) {
67 0 : return -1;
68 : }
69 12 : return ret;
70 : }
71 :
72 32 : static int unix2nttime(const char *sval)
73 : {
74 32 : return (strtoll(sval, NULL, 10) * -1 / 60 / 60 / 24 / 10000000);
75 : }
76 :
77 : #define GPODIR "addom.samba.example.com/Policies/"\
78 : "{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/"\
79 : "Windows NT/SecEdit"
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\
86 : "
87 : #define GPTINI "addom.samba.example.com/Policies/"\
88 : "{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI"
89 :
90 2 : bool torture_gpo_system_access_policies(struct torture_context *tctx)
91 : {
92 2 : TALLOC_CTX *ctx = talloc_new(tctx);
93 2 : int ret, vers = 0, i;
94 2 : const char *sysvol_path = NULL, *gpo_dir = NULL;
95 2 : const char *gpo_file = NULL, *gpt_file = NULL;
96 2 : struct ldb_context *samdb = NULL;
97 0 : struct ldb_result *result;
98 2 : const char *attrs[] = {
99 : "minPwdAge",
100 : "maxPwdAge",
101 : "minPwdLength",
102 : "pwdProperties",
103 : NULL
104 : };
105 2 : FILE *fp = NULL;
106 0 : const char **gpo_update_cmd;
107 0 : const char **gpo_unapply_cmd;
108 0 : const char **gpo_update_force_cmd;
109 2 : int minpwdcases[] = { 0, 1, 998 };
110 2 : int maxpwdcases[] = { 0, 1, 999 };
111 2 : int pwdlencases[] = { 0, 1, 14 };
112 2 : int pwdpropcases[] = { 0, 1, 1 };
113 2 : struct ldb_message *old_message = NULL;
114 0 : const char **itr;
115 2 : int gpo_update_len = 0;
116 :
117 2 : sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
118 : lpcfg_default_service(tctx->lp_ctx), tctx);
119 2 : torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");
120 :
121 : /* Ensure the sysvol path exists */
122 2 : gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
123 2 : mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
124 2 : gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);
125 :
126 : /* Get the gpo update command */
127 2 : gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
128 2 : torture_assert(tctx, gpo_update_cmd && gpo_update_cmd[0],
129 : "Failed to fetch the gpo update command");
130 :
131 : /* Open and read the samba db and store the initial password settings */
132 2 : samdb = samdb_connect(ctx,
133 : tctx->ev,
134 : tctx->lp_ctx,
135 : system_session(tctx->lp_ctx),
136 : NULL,
137 : 0);
138 2 : torture_assert(tctx, samdb, "Failed to connect to the samdb");
139 :
140 2 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
141 : LDB_SCOPE_BASE, attrs, NULL);
142 2 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
143 : "Searching the samdb failed");
144 :
145 2 : old_message = result->msgs[0];
146 :
147 8 : for (i = 0; i < 3; i++) {
148 : /* Write out the sysvol */
149 6 : if ( (fp = fopen(gpo_file, "w")) ) {
150 6 : fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
151 : maxpwdcases[i], pwdlencases[i],
152 : pwdpropcases[i]), fp);
153 6 : fclose(fp);
154 : }
155 :
156 : /* Update the version in the GPT.INI */
157 6 : gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
158 6 : if ( (fp = fopen(gpt_file, "r")) ) {
159 : char line[256];
160 12 : while (fgets(line, 256, fp)) {
161 12 : if (strncasecmp(line, "Version=", 8) == 0) {
162 6 : vers = atoi(line+8);
163 6 : break;
164 : }
165 : }
166 6 : fclose(fp);
167 : }
168 6 : if ( (fp = fopen(gpt_file, "w")) ) {
169 6 : char *data = talloc_asprintf(ctx,
170 : "[General]\nVersion=%d\n",
171 : ++vers);
172 6 : fputs(data, fp);
173 6 : fclose(fp);
174 : }
175 :
176 : /* Run the gpo update command */
177 6 : ret = exec_wait(tctx, gpo_update_cmd);
178 :
179 6 : torture_assert(tctx, ret == 0,
180 : "Failed to execute the gpo update command");
181 6 : ret = ldb_search(samdb, ctx, &result,
182 : ldb_get_default_basedn(samdb),
183 : LDB_SCOPE_BASE, attrs, NULL);
184 6 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
185 : "Searching the samdb failed");
186 :
187 : /* minPwdAge */
188 6 : torture_assert_int_equal(tctx, unix2nttime(
189 : ldb_msg_find_attr_as_string(
190 : result->msgs[0],
191 : attrs[0],
192 : "")), minpwdcases[i],
193 : "The minPwdAge was not applied");
194 :
195 : /* maxPwdAge */
196 6 : torture_assert_int_equal(tctx, unix2nttime(
197 : ldb_msg_find_attr_as_string(
198 : result->msgs[0],
199 : attrs[1],
200 : "")), maxpwdcases[i],
201 : "The maxPwdAge was not applied");
202 :
203 : /* minPwdLength */
204 6 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
205 : result->msgs[0],
206 : attrs[2],
207 : -1),
208 : pwdlencases[i],
209 : "The minPwdLength was not applied");
210 :
211 : /* pwdProperties */
212 6 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
213 : result->msgs[0],
214 : attrs[3],
215 : -1),
216 : pwdpropcases[i],
217 : "The pwdProperties were not applied");
218 : }
219 :
220 : /* Reset settings, then verify a reapply doesn't force them back */
221 10 : for (i = 0; i < old_message->num_elements; i++) {
222 8 : old_message->elements[i].flags = LDB_FLAG_MOD_REPLACE;
223 : }
224 2 : ret = ldb_modify(samdb, old_message);
225 2 : torture_assert(tctx, ret == 0, "Failed to reset password settings.");
226 :
227 2 : ret = exec_wait(tctx, gpo_update_cmd);
228 2 : torture_assert(tctx, ret == 0,
229 : "Failed to execute the gpo update command");
230 :
231 : /* Validate that the apply did nothing (without --force param) */
232 2 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
233 : LDB_SCOPE_BASE, attrs, NULL);
234 2 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
235 : "Searching the samdb failed");
236 : /* minPwdAge */
237 2 : torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
238 : result->msgs[0],
239 : attrs[0],
240 : "")),
241 : unix2nttime(ldb_msg_find_attr_as_string(old_message,
242 : attrs[0],
243 : "")
244 : ),
245 : "The minPwdAge was re-applied");
246 : /* maxPwdAge */
247 2 : torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
248 : result->msgs[0],
249 : attrs[1],
250 : "")),
251 : unix2nttime(ldb_msg_find_attr_as_string(old_message,
252 : attrs[1],
253 : "")
254 : ),
255 : "The maxPwdAge was re-applied");
256 : /* minPwdLength */
257 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
258 : result->msgs[0],
259 : attrs[2],
260 : -1),
261 : ldb_msg_find_attr_as_int(
262 : old_message,
263 : attrs[2],
264 : -2),
265 : "The minPwdLength was re-applied");
266 : /* pwdProperties */
267 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
268 : result->msgs[0],
269 : attrs[3],
270 : -1),
271 : ldb_msg_find_attr_as_int(
272 : old_message,
273 : attrs[3],
274 : -2),
275 : "The pwdProperties were re-applied");
276 :
277 12 : for (itr = gpo_update_cmd; *itr != NULL; itr++) {
278 10 : gpo_update_len++;
279 : }
280 :
281 : /* Run gpupdate --force and verify settings are re-applied */
282 2 : gpo_update_force_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
283 12 : for (i = 0; i < gpo_update_len; i++) {
284 10 : gpo_update_force_cmd[i] = talloc_strdup(gpo_update_force_cmd,
285 10 : gpo_update_cmd[i]);
286 : }
287 2 : gpo_update_force_cmd[i] = talloc_asprintf(gpo_update_force_cmd,
288 : "--force");
289 2 : gpo_update_force_cmd[i+1] = NULL;
290 2 : ret = exec_wait(tctx, gpo_update_force_cmd);
291 2 : torture_assert(tctx, ret == 0,
292 : "Failed to execute the gpupdate --force command");
293 :
294 2 : ret = ldb_search(samdb, ctx, &result,
295 : ldb_get_default_basedn(samdb),
296 : LDB_SCOPE_BASE, attrs, NULL);
297 2 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
298 : "Searching the samdb failed");
299 :
300 : /* minPwdAge */
301 2 : torture_assert_int_equal(tctx, unix2nttime(
302 : ldb_msg_find_attr_as_string(
303 : result->msgs[0],
304 : attrs[0],
305 : "")), minpwdcases[2],
306 : "The minPwdAge was not applied");
307 :
308 : /* maxPwdAge */
309 2 : torture_assert_int_equal(tctx, unix2nttime(
310 : ldb_msg_find_attr_as_string(
311 : result->msgs[0],
312 : attrs[1],
313 : "")), maxpwdcases[2],
314 : "The maxPwdAge was not applied");
315 :
316 : /* minPwdLength */
317 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
318 : result->msgs[0],
319 : attrs[2],
320 : -1),
321 : pwdlencases[2],
322 : "The minPwdLength was not applied");
323 :
324 : /* pwdProperties */
325 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
326 : result->msgs[0],
327 : attrs[3],
328 : -1),
329 : pwdpropcases[2],
330 : "The pwdProperties were not applied");
331 :
332 : /* Unapply the settings and verify they are removed */
333 2 : gpo_unapply_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
334 12 : for (i = 0; i < gpo_update_len; i++) {
335 10 : gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
336 10 : gpo_update_cmd[i]);
337 : }
338 2 : gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
339 2 : gpo_unapply_cmd[i+1] = NULL;
340 2 : ret = exec_wait(tctx, gpo_unapply_cmd);
341 2 : torture_assert(tctx, ret == 0,
342 : "Failed to execute the gpo unapply command");
343 2 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
344 : LDB_SCOPE_BASE, attrs, NULL);
345 2 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
346 : "Searching the samdb failed");
347 : /* minPwdAge */
348 2 : torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
349 : result->msgs[0],
350 : attrs[0],
351 : "")),
352 : unix2nttime(ldb_msg_find_attr_as_string(old_message,
353 : attrs[0],
354 : "")
355 : ),
356 : "The minPwdAge was not unapplied");
357 : /* maxPwdAge */
358 2 : torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
359 : result->msgs[0],
360 : attrs[1],
361 : "")),
362 : unix2nttime(ldb_msg_find_attr_as_string(old_message,
363 : attrs[1],
364 : "")
365 : ),
366 : "The maxPwdAge was not unapplied");
367 : /* minPwdLength */
368 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
369 : result->msgs[0],
370 : attrs[2],
371 : -1),
372 : ldb_msg_find_attr_as_int(
373 : old_message,
374 : attrs[2],
375 : -2),
376 : "The minPwdLength was not unapplied");
377 : /* pwdProperties */
378 2 : torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
379 : result->msgs[0],
380 : attrs[3],
381 : -1),
382 : ldb_msg_find_attr_as_int(
383 : old_message,
384 : attrs[3],
385 : -2),
386 : "The pwdProperties were not unapplied");
387 :
388 2 : talloc_free(ctx);
389 2 : return true;
390 : }
|