/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- scripts_get_reg_config
- generate_gp_registry_entry
- scripts_parse_ini_section
- scripts_store_reg_gpovals
- scripts_apply
- scripts_process_group_policy
- scripts_initialize
- scripts_shutdown
- gpext_scripts_init
1 /*
2 * Unix SMB/CIFS implementation.
3 * Group Policy Support
4 * Copyright (C) Guenther Deschner 2007
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 "libgpo/gpo_ini.h"
22
23 #define GP_EXT_NAME "scripts"
24
25 #define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
26
27 #define GP_SCRIPTS_INI "Scripts/scripts.ini"
28
29 #define GP_SCRIPTS_INI_STARTUP "Startup"
30 #define GP_SCRIPTS_INI_SHUTDOWN "Shutdown"
31 #define GP_SCRIPTS_INI_LOGON "Logon"
32 #define GP_SCRIPTS_INI_LOGOFF "Logoff"
33
34 #define GP_SCRIPTS_SECTION_CMDLINE "cmdline"
35 #define GP_SCRIPTS_SECTION_PARAMETERS "parameters"
36
37 #define GP_SCRIPTS_REG_VAL_SCRIPT "Script"
38 #define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters"
39 #define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime"
40
41 static TALLOC_CTX *ctx = NULL;
42
43 /****************************************************************
44 ****************************************************************/
45
46 static NTSTATUS scripts_get_reg_config(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
47 struct gp_extension_reg_info **reg_info)
48 {
49 NTSTATUS status;
50 struct gp_extension_reg_info *info = NULL;
51
52 struct gp_extension_reg_table table[] = {
53 { "ProcessGroupPolicy", REG_SZ, "scripts_process_group_policy" },
54 { "NoGPOListChanges", REG_DWORD, "1" },
55 { "NoSlowLink", REG_DWORD, "1" },
56 { "NotifyLinkTransition", REG_DWORD, "1" },
57 { NULL, REG_NONE, NULL },
58 };
59
60 info = TALLOC_ZERO_P(mem_ctx, struct gp_extension_reg_info);
61 NT_STATUS_HAVE_NO_MEMORY(info);
62
63 status = gp_ext_info_add_entry(mem_ctx, GP_EXT_NAME,
64 GP_EXT_GUID_SCRIPTS,
65 table, info);
66 NT_STATUS_NOT_OK_RETURN(status);
67
68 *reg_info = info;
69
70 return NT_STATUS_OK;
71 }
72
73 /****************************************************************
74 ****************************************************************/
75
76 static NTSTATUS generate_gp_registry_entry(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
77 const char *key,
78 const char *value,
79 uint32_t data_type,
80 const void *data_p,
81 enum gp_reg_action action,
82 struct gp_registry_entry **entry_out)
83 {
84 struct gp_registry_entry *entry = NULL;
85 struct registry_value *data = NULL;
86
87 entry = TALLOC_ZERO_P(mem_ctx, struct gp_registry_entry);
88 NT_STATUS_HAVE_NO_MEMORY(entry);
89
90 data = TALLOC_ZERO_P(mem_ctx, struct registry_value);
91 NT_STATUS_HAVE_NO_MEMORY(data);
92
93 data->type = data_type;
94 switch (data->type) {
95 case REG_QWORD:
96 data->v.qword = *(uint64_t *)data_p;
97 break;
98 case REG_SZ:
99 data->v.sz.str = talloc_strdup(mem_ctx, (char *)data_p);
100 data->v.sz.len = strlen(data->v.sz.str);
101 break;
102 default:
103 return NT_STATUS_NOT_SUPPORTED;
104 }
105
106 entry->key = key;
107 entry->data = data;
108 entry->action = action;
109 entry->value = talloc_strdup(mem_ctx, value);
110 NT_STATUS_HAVE_NO_MEMORY(entry->value);
111
112 *entry_out = entry;
113
114 return NT_STATUS_OK;
115 }
116
117 /****************************************************************
118 ****************************************************************/
119
120 static NTSTATUS scripts_parse_ini_section(struct gp_inifile_context *ini_ctx,
/* [<][>][^][v][top][bottom][index][help] */
121 uint32_t flags,
122 const char *section,
123 struct gp_registry_entry **entries,
124 size_t *num_entries)
125 {
126 NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
127 int i = 0;
128
129 while (1) {
130
131 const char *key = NULL;
132 const char *script = NULL;
133 const char *count = NULL;
134 const char *parameters = NULL;
135
136 count = talloc_asprintf(ini_ctx->mem_ctx, "%d", i);
137 NT_STATUS_HAVE_NO_MEMORY(count);
138
139 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
140 section, count,
141 GP_SCRIPTS_SECTION_CMDLINE);
142 NT_STATUS_HAVE_NO_MEMORY(key);
143
144 script = iniparser_getstring(ini_ctx->dict, key, NULL);
145 if (!script) {
146 break;
147 }
148
149 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
150 section, count,
151 GP_SCRIPTS_SECTION_PARAMETERS);
152 NT_STATUS_HAVE_NO_MEMORY(key);
153
154 parameters = iniparser_getstring(ini_ctx->dict, key, NULL);
155
156 {
157 struct gp_registry_entry *entry = NULL;
158 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
159 count,
160 GP_SCRIPTS_REG_VAL_SCRIPT,
161 REG_SZ,
162 script,
163 GP_REG_ACTION_ADD_VALUE,
164 &entry);
165 NT_STATUS_NOT_OK_RETURN(status);
166 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
167 entry,
168 entries,
169 num_entries)) {
170 return NT_STATUS_NO_MEMORY;
171 }
172 }
173 {
174 struct gp_registry_entry *entry = NULL;
175 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
176 count,
177 GP_SCRIPTS_REG_VAL_PARAMETERS,
178 REG_SZ,
179 parameters,
180 GP_REG_ACTION_ADD_VALUE,
181 &entry);
182 NT_STATUS_NOT_OK_RETURN(status);
183 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
184 entry,
185 entries,
186 num_entries)) {
187 return NT_STATUS_NO_MEMORY;
188 }
189 }
190 {
191 struct gp_registry_entry *entry = NULL;
192 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
193 count,
194 GP_SCRIPTS_REG_VAL_EXECTIME,
195 REG_QWORD,
196 0,
197 GP_REG_ACTION_ADD_VALUE,
198 &entry);
199 NT_STATUS_NOT_OK_RETURN(status);
200 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
201 entry,
202 entries,
203 num_entries)) {
204 return NT_STATUS_NO_MEMORY;
205 }
206 }
207 status = NT_STATUS_OK;
208 i++;
209 }
210
211 return status;
212 }
213
214 /****************************************************************
215 ****************************************************************/
216
217 static WERROR scripts_store_reg_gpovals(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
218 struct registry_key *key,
219 struct GROUP_POLICY_OBJECT *gpo)
220 {
221 WERROR werr;
222
223 if (!key || !gpo) {
224 return WERR_INVALID_PARAM;
225 }
226
227 werr = gp_store_reg_val_sz(mem_ctx, key, "DisplayName",
228 gpo->display_name);
229 W_ERROR_NOT_OK_RETURN(werr);
230
231 werr = gp_store_reg_val_sz(mem_ctx, key, "FileSysPath",
232 gpo->file_sys_path);
233 W_ERROR_NOT_OK_RETURN(werr);
234
235 werr = gp_store_reg_val_sz(mem_ctx, key, "GPO-ID",
236 gpo->ds_path);
237 W_ERROR_NOT_OK_RETURN(werr);
238
239 werr = gp_store_reg_val_sz(mem_ctx, key, "GPOName",
240 gpo->name);
241 W_ERROR_NOT_OK_RETURN(werr);
242
243 werr = gp_store_reg_val_sz(mem_ctx, key, "SOM-ID",
244 gpo->link);
245 W_ERROR_NOT_OK_RETURN(werr);
246
247 return werr;
248 }
249
250 /****************************************************************
251 ****************************************************************/
252
253 static WERROR scripts_apply(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
254 const struct nt_user_token *token,
255 struct registry_key *root_key,
256 uint32_t flags,
257 const char *section,
258 struct GROUP_POLICY_OBJECT *gpo,
259 struct gp_registry_entry *entries,
260 size_t num_entries)
261 {
262 struct gp_registry_context *reg_ctx = NULL;
263 WERROR werr;
264 size_t i;
265 const char *keystr = NULL;
266 int count = 0;
267
268 if (num_entries == 0) {
269 return WERR_OK;
270 }
271
272 #if 0
273 if (flags & GPO_INFO_FLAG_MACHINE) {
274 struct nt_user_token *tmp_token;
275
276 tmp_token = registry_create_system_token(mem_ctx);
277 W_ERROR_HAVE_NO_MEMORY(tmp_token);
278
279 werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
280 tmp_token,
281 ®_ctx);
282 } else {
283 werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
284 token,
285 ®_ctx);
286 }
287 W_ERROR_NOT_OK_RETURN(werr);
288 #endif
289
290 keystr = talloc_asprintf(mem_ctx, "%s\\%s\\%d", KEY_GP_SCRIPTS,
291 section, count++);
292 W_ERROR_HAVE_NO_MEMORY(keystr);
293
294 reg_deletekey_recursive(mem_ctx, root_key, keystr);
295
296 werr = gp_store_reg_subkey(mem_ctx, keystr,
297 root_key, &root_key);
298 if (!W_ERROR_IS_OK(werr)) {
299 goto done;
300 }
301
302 werr = scripts_store_reg_gpovals(mem_ctx, root_key, gpo);
303 if (!W_ERROR_IS_OK(werr)) {
304 goto done;
305 }
306
307 for (i=0; i<num_entries; i++) {
308
309 werr = reg_apply_registry_entry(mem_ctx, root_key, reg_ctx,
310 &(entries)[i],
311 token, flags);
312 if (!W_ERROR_IS_OK(werr)) {
313 DEBUG(0,("failed to apply registry: %s\n",
314 win_errstr(werr)));
315 goto done;
316 }
317 }
318
319 done:
320 gp_free_reg_ctx(reg_ctx);
321 return werr;
322 }
323
324 /****************************************************************
325 ****************************************************************/
326
327 static NTSTATUS scripts_process_group_policy(ADS_STRUCT *ads,
/* [<][>][^][v][top][bottom][index][help] */
328 TALLOC_CTX *mem_ctx,
329 uint32_t flags,
330 struct registry_key *root_key,
331 const struct nt_user_token *token,
332 struct GROUP_POLICY_OBJECT *gpo,
333 const char *extension_guid,
334 const char *snapin_guid)
335 {
336 NTSTATUS status;
337 WERROR werr;
338 int i = 0;
339 char *unix_path = NULL;
340 struct gp_inifile_context *ini_ctx = NULL;
341 struct gp_registry_entry *entries = NULL;
342 size_t num_entries = 0;
343 const char *list[] = {
344 GP_SCRIPTS_INI_STARTUP,
345 GP_SCRIPTS_INI_SHUTDOWN,
346 GP_SCRIPTS_INI_LOGON,
347 GP_SCRIPTS_INI_LOGOFF
348 };
349
350 debug_gpext_header(0, "scripts_process_group_policy", flags, gpo,
351 extension_guid, snapin_guid);
352
353 status = gpo_get_unix_path(mem_ctx, gpo, &unix_path);
354 NT_STATUS_NOT_OK_RETURN(status);
355
356 status = gp_inifile_init_context(mem_ctx, flags, unix_path,
357 GP_SCRIPTS_INI, &ini_ctx);
358 NT_STATUS_NOT_OK_RETURN(status);
359
360 for (i = 0; i < ARRAY_SIZE(list); i++) {
361
362 TALLOC_FREE(entries);
363 num_entries = 0;
364
365 status = scripts_parse_ini_section(ini_ctx, flags, list[i],
366 &entries, &num_entries);
367 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
368 continue;
369 }
370
371 if (!NT_STATUS_IS_OK(status)) {
372 return status;
373 }
374
375 dump_reg_entries(flags, "READ", entries, num_entries);
376
377 werr = scripts_apply(ini_ctx->mem_ctx, token, root_key,
378 flags, list[i], gpo, entries, num_entries);
379 if (!W_ERROR_IS_OK(werr)) {
380 continue; /* FIXME: finally fix storing emtpy strings and REG_QWORD! */
381 TALLOC_FREE(ini_ctx);
382 return werror_to_ntstatus(werr);
383 }
384 }
385
386 TALLOC_FREE(ini_ctx);
387 return NT_STATUS_OK;
388 }
389
390 /****************************************************************
391 ****************************************************************/
392
393 static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx)
/* [<][>][^][v][top][bottom][index][help] */
394 {
395 return NT_STATUS_OK;
396 }
397
398 /****************************************************************
399 ****************************************************************/
400
401 static NTSTATUS scripts_shutdown(void)
/* [<][>][^][v][top][bottom][index][help] */
402 {
403 NTSTATUS status;
404
405 status = unregister_gp_extension(GP_EXT_NAME);
406 if (NT_STATUS_IS_OK(status)) {
407 return status;
408 }
409
410 TALLOC_FREE(ctx);
411
412 return NT_STATUS_OK;
413 }
414
415 /****************************************************************
416 ****************************************************************/
417
418 static struct gp_extension_methods scripts_methods = {
419 .initialize = scripts_initialize,
420 .process_group_policy = scripts_process_group_policy,
421 .get_reg_config = scripts_get_reg_config,
422 .shutdown = scripts_shutdown
423 };
424
425 /****************************************************************
426 ****************************************************************/
427
428 NTSTATUS gpext_scripts_init(void)
/* [<][>][^][v][top][bottom][index][help] */
429 {
430 NTSTATUS status;
431
432 ctx = talloc_init("gpext_scripts_init");
433 NT_STATUS_HAVE_NO_MEMORY(ctx);
434
435 status = register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
436 GP_EXT_NAME, GP_EXT_GUID_SCRIPTS,
437 &scripts_methods);
438 if (!NT_STATUS_IS_OK(status)) {
439 TALLOC_FREE(ctx);
440 }
441
442 return status;
443 }