Spelling fixes s/emtpy/empty/
[Samba.git] / source3 / libgpo / gpext / scripts.c
blobfe0f1393aa9afb0ea1914c9dc433edd48061da06
1 /*
2 * Unix SMB/CIFS implementation.
3 * Group Policy Support
4 * Copyright (C) Guenther Deschner 2007
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/>.
20 #include "includes.h"
21 #include "../libgpo/gpo_ini.h"
22 #include "../libgpo/gpo.h"
23 #include "libgpo/gpo_proto.h"
24 #include "registry.h"
25 #include "registry/reg_api.h"
26 #include "../libcli/registry/util_reg.h"
27 #include "libgpo/gpext/gpext.h"
29 #define GP_EXT_NAME "scripts"
31 #define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
33 #define GP_SCRIPTS_INI "Scripts/scripts.ini"
35 #define GP_SCRIPTS_INI_STARTUP "Startup"
36 #define GP_SCRIPTS_INI_SHUTDOWN "Shutdown"
37 #define GP_SCRIPTS_INI_LOGON "Logon"
38 #define GP_SCRIPTS_INI_LOGOFF "Logoff"
40 #define GP_SCRIPTS_SECTION_CMDLINE "cmdline"
41 #define GP_SCRIPTS_SECTION_PARAMETERS "parameters"
43 #define GP_SCRIPTS_REG_VAL_SCRIPT "Script"
44 #define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters"
45 #define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime"
47 NTSTATUS gpext_scripts_init(TALLOC_CTX *mem_ctx);
49 static TALLOC_CTX *ctx = NULL;
51 /****************************************************************
52 ****************************************************************/
54 static NTSTATUS scripts_get_reg_config(TALLOC_CTX *mem_ctx,
55 struct gp_extension_reg_info **reg_info)
57 NTSTATUS status;
58 struct gp_extension_reg_info *info = NULL;
60 struct gp_extension_reg_table table[] = {
61 { "ProcessGroupPolicy", REG_SZ, "scripts_process_group_policy" },
62 { "NoGPOListChanges", REG_DWORD, "1" },
63 { "NoSlowLink", REG_DWORD, "1" },
64 { "NotifyLinkTransition", REG_DWORD, "1" },
65 { NULL, REG_NONE, NULL },
68 info = talloc_zero(mem_ctx, struct gp_extension_reg_info);
69 NT_STATUS_HAVE_NO_MEMORY(info);
71 status = gpext_info_add_entry(mem_ctx, GP_EXT_NAME,
72 GP_EXT_GUID_SCRIPTS,
73 table, info);
74 NT_STATUS_NOT_OK_RETURN(status);
76 *reg_info = info;
78 return NT_STATUS_OK;
81 /****************************************************************
82 ****************************************************************/
84 static NTSTATUS generate_gp_registry_entry(TALLOC_CTX *mem_ctx,
85 const char *key,
86 const char *value,
87 uint32_t data_type,
88 DATA_BLOB *blob,
89 enum gp_reg_action action,
90 struct gp_registry_entry **entry_out)
92 struct gp_registry_entry *entry = NULL;
93 struct registry_value *data = NULL;
95 entry = talloc_zero(mem_ctx, struct gp_registry_entry);
96 NT_STATUS_HAVE_NO_MEMORY(entry);
98 data = talloc_zero(mem_ctx, struct registry_value);
99 NT_STATUS_HAVE_NO_MEMORY(data);
101 data->type = data_type;
102 data->data = *blob;
104 entry->key = key;
105 entry->data = data;
106 entry->action = action;
107 entry->value = talloc_strdup(mem_ctx, value);
108 NT_STATUS_HAVE_NO_MEMORY(entry->value);
110 *entry_out = entry;
112 return NT_STATUS_OK;
115 /****************************************************************
116 ****************************************************************/
118 static NTSTATUS scripts_parse_ini_section(struct gp_inifile_context *ini_ctx,
119 uint32_t flags,
120 const char *section,
121 struct gp_registry_entry **entries,
122 size_t *num_entries)
124 NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
125 NTSTATUS result;
126 int i = 0;
128 while (1) {
130 const char *key = NULL;
131 const char *script = NULL;
132 const char *count = NULL;
133 const char *parameters = NULL;
134 DATA_BLOB blob;
135 bool ok;
137 count = talloc_asprintf(ini_ctx->mem_ctx, "%d", i);
138 NT_STATUS_HAVE_NO_MEMORY(count);
140 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
141 section, count,
142 GP_SCRIPTS_SECTION_CMDLINE);
143 NT_STATUS_HAVE_NO_MEMORY(key);
145 result = gp_inifile_getstring(ini_ctx, key, &script);
146 if (!NT_STATUS_IS_OK(result)) {
147 break;
150 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
151 section, count,
152 GP_SCRIPTS_SECTION_PARAMETERS);
153 NT_STATUS_HAVE_NO_MEMORY(key);
155 result = gp_inifile_getstring(ini_ctx, key, &parameters);
156 if (!NT_STATUS_IS_OK(result)) {
157 break;
161 struct gp_registry_entry *entry = NULL;
163 ok = push_reg_sz(ini_ctx->mem_ctx, &blob, script);
164 if (!ok) {
165 return NT_STATUS_NO_MEMORY;
168 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
169 count,
170 GP_SCRIPTS_REG_VAL_SCRIPT,
171 REG_SZ,
172 &blob,
173 GP_REG_ACTION_ADD_VALUE,
174 &entry);
175 NT_STATUS_NOT_OK_RETURN(status);
176 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
177 entry,
178 entries,
179 num_entries)) {
180 return NT_STATUS_NO_MEMORY;
184 struct gp_registry_entry *entry = NULL;
186 ok = push_reg_sz(ini_ctx->mem_ctx, &blob, parameters);
187 if (!ok) {
188 return NT_STATUS_NO_MEMORY;
191 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
192 count,
193 GP_SCRIPTS_REG_VAL_PARAMETERS,
194 REG_SZ,
195 &blob,
196 GP_REG_ACTION_ADD_VALUE,
197 &entry);
198 NT_STATUS_NOT_OK_RETURN(status);
199 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
200 entry,
201 entries,
202 num_entries)) {
203 return NT_STATUS_NO_MEMORY;
207 struct gp_registry_entry *entry = NULL;
209 blob = data_blob_talloc_zero(ini_ctx->mem_ctx, 8);
211 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
212 count,
213 GP_SCRIPTS_REG_VAL_EXECTIME,
214 REG_QWORD,
215 &blob,
216 GP_REG_ACTION_ADD_VALUE,
217 &entry);
218 NT_STATUS_NOT_OK_RETURN(status);
219 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
220 entry,
221 entries,
222 num_entries)) {
223 return NT_STATUS_NO_MEMORY;
226 status = NT_STATUS_OK;
227 i++;
230 return status;
233 /****************************************************************
234 ****************************************************************/
236 static WERROR scripts_store_reg_gpovals(TALLOC_CTX *mem_ctx,
237 struct registry_key *key,
238 const struct GROUP_POLICY_OBJECT *gpo)
240 WERROR werr;
242 if (!key || !gpo) {
243 return WERR_INVALID_PARAMETER;
246 werr = gp_store_reg_val_sz(mem_ctx, key, "DisplayName",
247 gpo->display_name);
248 W_ERROR_NOT_OK_RETURN(werr);
250 werr = gp_store_reg_val_sz(mem_ctx, key, "FileSysPath",
251 gpo->file_sys_path);
252 W_ERROR_NOT_OK_RETURN(werr);
254 werr = gp_store_reg_val_sz(mem_ctx, key, "GPO-ID",
255 gpo->ds_path);
256 W_ERROR_NOT_OK_RETURN(werr);
258 werr = gp_store_reg_val_sz(mem_ctx, key, "GPOName",
259 gpo->name);
260 W_ERROR_NOT_OK_RETURN(werr);
262 werr = gp_store_reg_val_sz(mem_ctx, key, "SOM-ID",
263 gpo->link);
264 W_ERROR_NOT_OK_RETURN(werr);
266 return werr;
269 /****************************************************************
270 ****************************************************************/
272 static WERROR scripts_apply(TALLOC_CTX *mem_ctx,
273 const struct security_token *token,
274 struct registry_key *root_key,
275 uint32_t flags,
276 const char *section,
277 const struct GROUP_POLICY_OBJECT *gpo,
278 struct gp_registry_entry *entries,
279 size_t num_entries)
281 struct gp_registry_context *reg_ctx = NULL;
282 WERROR werr;
283 size_t i;
284 const char *keystr = NULL;
285 int count = 0;
287 if (num_entries == 0) {
288 return WERR_OK;
291 #if 0
292 if (flags & GPO_INFO_FLAG_MACHINE) {
293 struct security_token *tmp_token;
295 tmp_token = registry_create_system_token(mem_ctx);
296 W_ERROR_HAVE_NO_MEMORY(tmp_token);
298 werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
299 tmp_token,
300 &reg_ctx);
301 } else {
302 werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
303 token,
304 &reg_ctx);
306 W_ERROR_NOT_OK_RETURN(werr);
307 #endif
309 keystr = talloc_asprintf(mem_ctx, "%s\\%s\\%d", KEY_GP_SCRIPTS,
310 section, count++);
311 W_ERROR_HAVE_NO_MEMORY(keystr);
313 reg_deletekey_recursive(root_key, keystr);
315 werr = gp_store_reg_subkey(mem_ctx, keystr,
316 root_key, &root_key);
317 if (!W_ERROR_IS_OK(werr)) {
318 goto done;
321 werr = scripts_store_reg_gpovals(mem_ctx, root_key, gpo);
322 if (!W_ERROR_IS_OK(werr)) {
323 goto done;
326 for (i=0; i<num_entries; i++) {
328 werr = reg_apply_registry_entry(mem_ctx, root_key, reg_ctx,
329 &(entries)[i],
330 token, flags);
331 if (!W_ERROR_IS_OK(werr)) {
332 DEBUG(0,("failed to apply registry: %s\n",
333 win_errstr(werr)));
334 goto done;
338 done:
339 gp_free_reg_ctx(reg_ctx);
340 return werr;
343 /****************************************************************
344 ****************************************************************/
346 static NTSTATUS scripts_process_group_policy(TALLOC_CTX *mem_ctx,
347 uint32_t flags,
348 struct registry_key *root_key,
349 const struct security_token *token,
350 const struct GROUP_POLICY_OBJECT *deleted_gpo_list,
351 const struct GROUP_POLICY_OBJECT *changed_gpo_list)
353 NTSTATUS status;
354 WERROR werr;
355 int i = 0;
356 char *unix_path = NULL;
357 struct gp_inifile_context *ini_ctx = NULL;
358 struct gp_registry_entry *entries = NULL;
359 size_t num_entries = 0;
360 const char *list[] = {
361 GP_SCRIPTS_INI_STARTUP,
362 GP_SCRIPTS_INI_SHUTDOWN,
363 GP_SCRIPTS_INI_LOGON,
364 GP_SCRIPTS_INI_LOGOFF
366 const struct GROUP_POLICY_OBJECT *gpo;
367 char *gpo_cache_path = cache_path(talloc_tos(), GPO_CACHE_DIR);
368 if (gpo_cache_path == NULL) {
369 return NT_STATUS_NO_MEMORY;
372 /* implementation of the policy callback function, see
373 * http://msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx
374 * for details - gd */
376 /* for now do not process the list of deleted group policies
378 for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) {
383 for (gpo = changed_gpo_list; gpo; gpo = gpo->next) {
385 gpext_debug_header(0, "scripts_process_group_policy", flags,
386 gpo, GP_EXT_GUID_SCRIPTS, NULL);
388 status = gpo_get_unix_path(mem_ctx, gpo_cache_path,
389 gpo, &unix_path);
390 if (!NT_STATUS_IS_OK(status)) {
391 goto err_cache_path_free;
394 status = gp_inifile_init_context(mem_ctx, flags, unix_path,
395 GP_SCRIPTS_INI, &ini_ctx);
396 if (!NT_STATUS_IS_OK(status)) {
397 goto err_cache_path_free;
400 for (i = 0; i < ARRAY_SIZE(list); i++) {
402 TALLOC_FREE(entries);
403 num_entries = 0;
405 status = scripts_parse_ini_section(ini_ctx, flags, list[i],
406 &entries, &num_entries);
407 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
408 continue;
411 if (!NT_STATUS_IS_OK(status)) {
412 TALLOC_FREE(ini_ctx);
413 goto err_cache_path_free;
416 dump_reg_entries(flags, "READ", entries, num_entries);
418 werr = scripts_apply(ini_ctx->mem_ctx, token, root_key,
419 flags, list[i], gpo, entries, num_entries);
420 if (!W_ERROR_IS_OK(werr)) {
421 continue; /* FIXME: finally fix storing empty strings and REG_QWORD! */
425 TALLOC_FREE(ini_ctx);
427 status = NT_STATUS_OK;
429 err_cache_path_free:
430 talloc_free(gpo_cache_path);
431 return status;
434 /****************************************************************
435 ****************************************************************/
437 static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx)
439 return NT_STATUS_OK;
442 /****************************************************************
443 ****************************************************************/
445 static NTSTATUS scripts_shutdown(void)
447 NTSTATUS status;
449 status = gpext_unregister_gp_extension(GP_EXT_NAME);
450 if (NT_STATUS_IS_OK(status)) {
451 return status;
454 TALLOC_FREE(ctx);
456 return NT_STATUS_OK;
459 /****************************************************************
460 ****************************************************************/
462 static struct gp_extension_methods scripts_methods = {
463 .initialize = scripts_initialize,
464 .process_group_policy = scripts_process_group_policy,
465 .get_reg_config = scripts_get_reg_config,
466 .shutdown = scripts_shutdown
469 /****************************************************************
470 ****************************************************************/
472 NTSTATUS gpext_scripts_init(TALLOC_CTX *mem_ctx)
474 NTSTATUS status;
476 ctx = talloc_init("gpext_scripts_init");
477 NT_STATUS_HAVE_NO_MEMORY(ctx);
479 status = gpext_register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
480 GP_EXT_NAME, GP_EXT_GUID_SCRIPTS,
481 &scripts_methods);
482 if (!NT_STATUS_IS_OK(status)) {
483 TALLOC_FREE(ctx);
486 return status;