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 964 : struct torture_suite *gpo_apply_suite(TALLOC_CTX *ctx)
36 : {
37 964 : struct torture_suite *suite = torture_suite_create(ctx, "apply");
38 :
39 964 : torture_suite_add_simple_test(suite, "gpo_param_from_gpo",
40 : torture_gpo_system_access_policies);
41 :
42 964 : suite->description = talloc_strdup(suite, "Group Policy apply tests");
43 :
44 964 : return suite;
45 : }
46 :
47 0 : static int exec_wait(struct torture_context *tctx, const char **gpo_update_cmd)
48 : {
49 : NTSTATUS status;
50 0 : int ret = 0;
51 : struct tevent_req *req;
52 :
53 0 : 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 0 : if (req == NULL) {
60 0 : return -1;
61 : }
62 :
63 0 : if (!tevent_req_poll_ntstatus(req, tctx->ev, &status)) {
64 0 : return -1;
65 : }
66 0 : if (samba_runcmd_recv(req, &ret) != 0) {
67 0 : return -1;
68 : }
69 0 : return ret;
70 : }
71 :
72 0 : static int unix2nttime(const char *sval)
73 : {
74 0 : 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 0 : bool torture_gpo_system_access_policies(struct torture_context *tctx)
91 : {
92 0 : TALLOC_CTX *ctx = talloc_new(tctx);
93 0 : int ret, vers = 0, i;
94 0 : const char *sysvol_path = NULL, *gpo_dir = NULL;
95 0 : const char *gpo_file = NULL, *gpt_file = NULL;
96 0 : struct ldb_context *samdb = NULL;
97 : struct ldb_result *result;
98 0 : const char *attrs[] = {
99 : "minPwdAge",
100 : "maxPwdAge",
101 : "minPwdLength",
102 : "pwdProperties",
103 : NULL
104 : };
105 0 : FILE *fp = NULL;
106 : const char **gpo_update_cmd;
107 : const char **gpo_unapply_cmd;
108 : const char **gpo_update_force_cmd;
109 0 : int minpwdcases[] = { 0, 1, 998 };
110 0 : int maxpwdcases[] = { 0, 1, 999 };
111 0 : int pwdlencases[] = { 0, 1, 14 };
112 0 : int pwdpropcases[] = { 0, 1, 1 };
113 0 : struct ldb_message *old_message = NULL;
114 : const char **itr;
115 0 : int gpo_update_len = 0;
116 :
117 0 : sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
118 : lpcfg_default_service(tctx->lp_ctx), tctx);
119 0 : torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");
120 :
121 : /* Ensure the sysvol path exists */
122 0 : gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
123 0 : mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
124 0 : gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);
125 :
126 : /* Get the gpo update command */
127 0 : gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
128 0 : 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 0 : samdb = samdb_connect(ctx,
133 : tctx->ev,
134 : tctx->lp_ctx,
135 : system_session(tctx->lp_ctx),
136 : NULL,
137 : 0);
138 0 : torture_assert(tctx, samdb, "Failed to connect to the samdb");
139 :
140 0 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
141 : LDB_SCOPE_BASE, attrs, NULL);
142 0 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
143 : "Searching the samdb failed");
144 :
145 0 : old_message = result->msgs[0];
146 :
147 0 : for (i = 0; i < 3; i++) {
148 : /* Write out the sysvol */
149 0 : if ( (fp = fopen(gpo_file, "w")) ) {
150 0 : fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
151 : maxpwdcases[i], pwdlencases[i],
152 : pwdpropcases[i]), fp);
153 0 : fclose(fp);
154 : }
155 :
156 : /* Update the version in the GPT.INI */
157 0 : gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
158 0 : if ( (fp = fopen(gpt_file, "r")) ) {
159 : char line[256];
160 0 : while (fgets(line, 256, fp)) {
161 0 : if (strncasecmp(line, "Version=", 8) == 0) {
162 0 : vers = atoi(line+8);
163 0 : break;
164 : }
165 : }
166 0 : fclose(fp);
167 : }
168 0 : if ( (fp = fopen(gpt_file, "w")) ) {
169 0 : char *data = talloc_asprintf(ctx,
170 : "[General]\nVersion=%d\n",
171 : ++vers);
172 0 : fputs(data, fp);
173 0 : fclose(fp);
174 : }
175 :
176 : /* Run the gpo update command */
177 0 : ret = exec_wait(tctx, gpo_update_cmd);
178 :
179 0 : torture_assert(tctx, ret == 0,
180 : "Failed to execute the gpo update command");
181 0 : ret = ldb_search(samdb, ctx, &result,
182 : ldb_get_default_basedn(samdb),
183 : LDB_SCOPE_BASE, attrs, NULL);
184 0 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
185 : "Searching the samdb failed");
186 :
187 : /* minPwdAge */
188 0 : 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 0 : 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 0 : 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 0 : 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 0 : for (i = 0; i < old_message->num_elements; i++) {
222 0 : old_message->elements[i].flags = LDB_FLAG_MOD_REPLACE;
223 : }
224 0 : ret = ldb_modify(samdb, old_message);
225 0 : torture_assert(tctx, ret == 0, "Failed to reset password settings.");
226 :
227 0 : ret = exec_wait(tctx, gpo_update_cmd);
228 0 : 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 0 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
233 : LDB_SCOPE_BASE, attrs, NULL);
234 0 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
235 : "Searching the samdb failed");
236 : /* minPwdAge */
237 0 : 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 0 : 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 0 : 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 0 : 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 0 : for (itr = gpo_update_cmd; *itr != NULL; itr++) {
278 0 : gpo_update_len++;
279 : }
280 :
281 : /* Run gpupdate --force and verify settings are re-applied */
282 0 : gpo_update_force_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
283 0 : for (i = 0; i < gpo_update_len; i++) {
284 0 : gpo_update_force_cmd[i] = talloc_strdup(gpo_update_force_cmd,
285 0 : gpo_update_cmd[i]);
286 : }
287 0 : gpo_update_force_cmd[i] = talloc_asprintf(gpo_update_force_cmd,
288 : "--force");
289 0 : gpo_update_force_cmd[i+1] = NULL;
290 0 : ret = exec_wait(tctx, gpo_update_force_cmd);
291 0 : torture_assert(tctx, ret == 0,
292 : "Failed to execute the gpupdate --force command");
293 :
294 0 : ret = ldb_search(samdb, ctx, &result,
295 : ldb_get_default_basedn(samdb),
296 : LDB_SCOPE_BASE, attrs, NULL);
297 0 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
298 : "Searching the samdb failed");
299 :
300 : /* minPwdAge */
301 0 : 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 0 : 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 0 : 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 0 : 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 0 : gpo_unapply_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
334 0 : for (i = 0; i < gpo_update_len; i++) {
335 0 : gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
336 0 : gpo_update_cmd[i]);
337 : }
338 0 : gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
339 0 : gpo_unapply_cmd[i+1] = NULL;
340 0 : ret = exec_wait(tctx, gpo_unapply_cmd);
341 0 : torture_assert(tctx, ret == 0,
342 : "Failed to execute the gpo unapply command");
343 0 : ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
344 : LDB_SCOPE_BASE, attrs, NULL);
345 0 : torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
346 : "Searching the samdb failed");
347 : /* minPwdAge */
348 0 : 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 0 : 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 0 : 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 0 : 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 0 : talloc_free(ctx);
389 0 : return true;
390 : }
|