gpo: Test that unapply works
[nivanova/samba-autobuild/.git] / source4 / torture / gpo / apply.c
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
31 struct torture_suite *gpo_apply_suite(TALLOC_CTX *ctx)
32 {
33         struct torture_suite *suite = torture_suite_create(ctx, "apply");
34
35         torture_suite_add_simple_test(suite, "gpo_param_from_gpo",
36                                       torture_gpo_system_access_policies);
37
38         suite->description = talloc_strdup(suite, "Group Policy apply tests");
39
40         return suite;
41 }
42
43 static int exec_wait(char **cmd)
44 {
45         int ret;
46         pid_t pid = fork();
47         switch (pid) {
48                 case 0:
49                         execv(cmd[0], &(cmd[1]));
50                         ret = -1;
51                         break;
52                 case -1:
53                         ret = errno;
54                         break;
55                 default:
56                         if (waitpid(pid, &ret, 0) < 0)
57                                 ret = errno;
58                         break;
59         }
60         return ret;
61 }
62
63 static int unix2nttime(const char *sval)
64 {
65         return (strtoll(sval, NULL, 10) * -1 / 60 / 60 / 24 / 10000000);
66 }
67
68 #define GPODIR "addom.samba.example.com/Policies/"\
69                "{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/"\
70                "Windows NT/SecEdit"
71 #define GPOFILE "GptTmpl.inf"
72 #define GPTTMPL "[System Access]\n\
73 MinimumPasswordAge = %d\n\
74 MaximumPasswordAge = %d\n\
75 MinimumPasswordLength = %d\n\
76 PasswordComplexity = %d\n\
77 "
78 #define GPTINI "addom.samba.example.com/Policies/"\
79                "{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI"
80
81 bool torture_gpo_system_access_policies(struct torture_context *tctx)
82 {
83         TALLOC_CTX *ctx = talloc_new(tctx);
84         int ret, vers = 0, i;
85         const char *sysvol_path = NULL, *gpo_dir = NULL;
86         const char *gpo_file = NULL, *gpt_file = NULL;
87         struct ldb_context *samdb = NULL;
88         struct ldb_result *result;
89         const char *attrs[] = {
90                 "minPwdAge",
91                 "maxPwdAge",
92                 "minPwdLength",
93                 "pwdProperties",
94                 NULL
95         };
96         FILE *fp = NULL;
97         const char **gpo_update_cmd;
98         char **gpo_unapply_cmd;
99         int minpwdcases[] = { 0, 1, 998 };
100         int maxpwdcases[] = { 0, 1, 999 };
101         int pwdlencases[] = { 0, 1, 14 };
102         int pwdpropcases[] = { 0, 1, 1 };
103         struct ldb_message *old_message = NULL;
104         const char **itr;
105         int gpo_update_len = 0;
106
107         sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
108                                  lpcfg_default_service(tctx->lp_ctx), tctx);
109         torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");
110
111         /* Ensure the sysvol path exists */
112         gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
113         mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
114         gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);
115
116         /* Get the gpo update command */
117         gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
118         torture_assert(tctx, gpo_update_cmd && gpo_update_cmd[0],
119                        "Failed to fetch the gpo update command");
120
121         /* Open and read the samba db and store the initial password settings */
122         samdb = samdb_connect(ctx, tctx->ev, tctx->lp_ctx,
123                               system_session(tctx->lp_ctx), 0);
124         torture_assert(tctx, samdb, "Failed to connect to the samdb");
125
126         ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
127                          LDB_SCOPE_BASE, attrs, NULL);
128         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
129                        "Searching the samdb failed");
130
131         old_message = result->msgs[0];
132
133         for (i = 0; i < 3; i++) {
134                 /* Write out the sysvol */
135                 if ( (fp = fopen(gpo_file, "w")) ) {
136                         fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
137                                               maxpwdcases[i], pwdlencases[i],
138                                               pwdpropcases[i]), fp);
139                         fclose(fp);
140                 }
141
142                 /* Update the version in the GPT.INI */
143                 gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
144                 if ( (fp = fopen(gpt_file, "r")) ) {
145                         char line[256];
146                         while (fgets(line, 256, fp)) {
147                                 if (strncasecmp(line, "Version=", 8) == 0) {
148                                         vers = atoi(line+8);
149                                         break;
150                                 }
151                         }
152                         fclose(fp);
153                 }
154                 if ( (fp = fopen(gpt_file, "w")) ) {
155                         char *data = talloc_asprintf(ctx,
156                                                      "[General]\nVersion=%d\n",
157                                                      ++vers);
158                         fputs(data, fp);
159                         fclose(fp);
160                 }
161
162                 /* Run the gpo update command */
163                 ret = exec_wait(discard_const_p(char *, gpo_update_cmd));
164                 torture_assert(tctx, ret == 0,
165                                "Failed to execute the gpo update command");
166
167                 ret = ldb_search(samdb, ctx, &result,
168                                  ldb_get_default_basedn(samdb),
169                                  LDB_SCOPE_BASE, attrs, NULL);
170                 torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
171                                "Searching the samdb failed");
172
173                 /* minPwdAge */
174                 torture_assert_int_equal(tctx, unix2nttime(
175                                                 ldb_msg_find_attr_as_string(
176                                                         result->msgs[0],
177                                                         attrs[0],
178                                                         "")), minpwdcases[i],
179                                "The minPwdAge was not applied");
180
181                 /* maxPwdAge */
182                 torture_assert_int_equal(tctx, unix2nttime(
183                                                 ldb_msg_find_attr_as_string(
184                                                         result->msgs[0],
185                                                         attrs[1],
186                                                         "")), maxpwdcases[i],
187                                "The maxPwdAge was not applied");
188
189                 /* minPwdLength */
190                 torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
191                                                         result->msgs[0],
192                                                         attrs[2],
193                                                         -1),
194                                                pwdlencases[i],
195                                 "The minPwdLength was not applied");
196
197                 /* pwdProperties */
198                 torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
199                                                         result->msgs[0],
200                                                         attrs[3],
201                                                         -1),
202                                                pwdpropcases[i],
203                                "The pwdProperties were not applied");
204         }
205
206         /* Unapply the settings and verify they are removed */
207         for (itr = gpo_update_cmd; *itr != NULL; itr++) {
208                 gpo_update_len++;
209         }
210         gpo_unapply_cmd = talloc_array(ctx, char*, gpo_update_len+2);
211         for (i = 0; i < gpo_update_len; i++) {
212                 gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
213                                                    gpo_update_cmd[i]);
214         }
215         gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
216         gpo_unapply_cmd[i+1] = NULL;
217         ret = exec_wait(gpo_unapply_cmd);
218         torture_assert(tctx, ret == 0,
219                        "Failed to execute the gpo unapply command");
220         ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
221                          LDB_SCOPE_BASE, attrs, NULL);
222         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
223                        "Searching the samdb failed");
224         /* minPwdAge */
225         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
226                                                 result->msgs[0],
227                                                 attrs[0],
228                                                 "")),
229                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
230                                                                attrs[0],
231                                                                "")
232                                   ),
233                        "The minPwdAge was not unapplied");
234         /* maxPwdAge */
235         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
236                                                 result->msgs[0],
237                                                 attrs[1],
238                                                 "")),
239                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
240                                                                attrs[1],
241                                                                "")
242                                   ),
243                        "The maxPwdAge was not unapplied");
244         /* minPwdLength */
245         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
246                                                 result->msgs[0],
247                                                 attrs[2],
248                                                 -1),
249                                        ldb_msg_find_attr_as_int(
250                                                 old_message,
251                                                 attrs[2],
252                                                 -2),
253                         "The minPwdLength was not unapplied");
254         /* pwdProperties */
255         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
256                                                 result->msgs[0],
257                                                 attrs[3],
258                                                 -1),
259                                         ldb_msg_find_attr_as_int(
260                                                 old_message,
261                                                 attrs[3],
262                                                 -2),
263                         "The pwdProperties were not unapplied");
264
265         talloc_free(ctx);
266         return true;
267 }