2 * Unix SMB/CIFS implementation.
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/>.
21 #include "../libgpo/gpo_ini.h"
22 #include "../libgpo/gpo.h"
23 #include "libgpo/gpo_proto.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 static TALLOC_CTX
*ctx
= NULL
;
49 /****************************************************************
50 ****************************************************************/
52 static NTSTATUS
scripts_get_reg_config(TALLOC_CTX
*mem_ctx
,
53 struct gp_extension_reg_info
**reg_info
)
56 struct gp_extension_reg_info
*info
= NULL
;
58 struct gp_extension_reg_table table
[] = {
59 { "ProcessGroupPolicy", REG_SZ
, "scripts_process_group_policy" },
60 { "NoGPOListChanges", REG_DWORD
, "1" },
61 { "NoSlowLink", REG_DWORD
, "1" },
62 { "NotifyLinkTransition", REG_DWORD
, "1" },
63 { NULL
, REG_NONE
, NULL
},
66 info
= talloc_zero(mem_ctx
, struct gp_extension_reg_info
);
67 NT_STATUS_HAVE_NO_MEMORY(info
);
69 status
= gpext_info_add_entry(mem_ctx
, GP_EXT_NAME
,
72 NT_STATUS_NOT_OK_RETURN(status
);
79 /****************************************************************
80 ****************************************************************/
82 static NTSTATUS
generate_gp_registry_entry(TALLOC_CTX
*mem_ctx
,
87 enum gp_reg_action action
,
88 struct gp_registry_entry
**entry_out
)
90 struct gp_registry_entry
*entry
= NULL
;
91 struct registry_value
*data
= NULL
;
93 entry
= talloc_zero(mem_ctx
, struct gp_registry_entry
);
94 NT_STATUS_HAVE_NO_MEMORY(entry
);
96 data
= talloc_zero(mem_ctx
, struct registry_value
);
97 NT_STATUS_HAVE_NO_MEMORY(data
);
99 data
->type
= data_type
;
100 switch (data
->type
) {
102 data
->data
= data_blob_talloc(mem_ctx
, NULL
, 8);
103 SBVAL(data
->data
.data
, 0, *(uint64_t *)data_p
);
106 if (!push_reg_sz(mem_ctx
, &data
->data
, (const char *)data_p
)) {
107 return NT_STATUS_NO_MEMORY
;
111 return NT_STATUS_NOT_SUPPORTED
;
116 entry
->action
= action
;
117 entry
->value
= talloc_strdup(mem_ctx
, value
);
118 NT_STATUS_HAVE_NO_MEMORY(entry
->value
);
125 /****************************************************************
126 ****************************************************************/
128 static NTSTATUS
scripts_parse_ini_section(struct gp_inifile_context
*ini_ctx
,
131 struct gp_registry_entry
**entries
,
134 NTSTATUS status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
140 const char *key
= NULL
;
142 const char *count
= NULL
;
143 char *parameters
= NULL
;
145 count
= talloc_asprintf(ini_ctx
->mem_ctx
, "%d", i
);
146 NT_STATUS_HAVE_NO_MEMORY(count
);
148 key
= talloc_asprintf(ini_ctx
->mem_ctx
, "%s:%s%s",
150 GP_SCRIPTS_SECTION_CMDLINE
);
151 NT_STATUS_HAVE_NO_MEMORY(key
);
153 result
= gp_inifile_getstring(ini_ctx
, key
, &script
);
154 if (!NT_STATUS_IS_OK(result
)) {
158 key
= talloc_asprintf(ini_ctx
->mem_ctx
, "%s:%s%s",
160 GP_SCRIPTS_SECTION_PARAMETERS
);
161 NT_STATUS_HAVE_NO_MEMORY(key
);
163 result
= gp_inifile_getstring(ini_ctx
, key
, ¶meters
);
164 if (!NT_STATUS_IS_OK(result
)) {
169 struct gp_registry_entry
*entry
= NULL
;
170 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
172 GP_SCRIPTS_REG_VAL_SCRIPT
,
175 GP_REG_ACTION_ADD_VALUE
,
177 NT_STATUS_NOT_OK_RETURN(status
);
178 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
182 return NT_STATUS_NO_MEMORY
;
186 struct gp_registry_entry
*entry
= NULL
;
187 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
189 GP_SCRIPTS_REG_VAL_PARAMETERS
,
192 GP_REG_ACTION_ADD_VALUE
,
194 NT_STATUS_NOT_OK_RETURN(status
);
195 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
199 return NT_STATUS_NO_MEMORY
;
203 struct gp_registry_entry
*entry
= NULL
;
204 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
206 GP_SCRIPTS_REG_VAL_EXECTIME
,
209 GP_REG_ACTION_ADD_VALUE
,
211 NT_STATUS_NOT_OK_RETURN(status
);
212 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
216 return NT_STATUS_NO_MEMORY
;
219 status
= NT_STATUS_OK
;
226 /****************************************************************
227 ****************************************************************/
229 static WERROR
scripts_store_reg_gpovals(TALLOC_CTX
*mem_ctx
,
230 struct registry_key
*key
,
231 const struct GROUP_POLICY_OBJECT
*gpo
)
236 return WERR_INVALID_PARAM
;
239 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "DisplayName",
241 W_ERROR_NOT_OK_RETURN(werr
);
243 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "FileSysPath",
245 W_ERROR_NOT_OK_RETURN(werr
);
247 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPO-ID",
249 W_ERROR_NOT_OK_RETURN(werr
);
251 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPOName",
253 W_ERROR_NOT_OK_RETURN(werr
);
255 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "SOM-ID",
257 W_ERROR_NOT_OK_RETURN(werr
);
262 /****************************************************************
263 ****************************************************************/
265 static WERROR
scripts_apply(TALLOC_CTX
*mem_ctx
,
266 const struct security_token
*token
,
267 struct registry_key
*root_key
,
270 const struct GROUP_POLICY_OBJECT
*gpo
,
271 struct gp_registry_entry
*entries
,
274 struct gp_registry_context
*reg_ctx
= NULL
;
277 const char *keystr
= NULL
;
280 if (num_entries
== 0) {
285 if (flags
& GPO_INFO_FLAG_MACHINE
) {
286 struct security_token
*tmp_token
;
288 tmp_token
= registry_create_system_token(mem_ctx
);
289 W_ERROR_HAVE_NO_MEMORY(tmp_token
);
291 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKLM
, REG_KEY_WRITE
,
295 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKCU
, REG_KEY_WRITE
,
299 W_ERROR_NOT_OK_RETURN(werr
);
302 keystr
= talloc_asprintf(mem_ctx
, "%s\\%s\\%d", KEY_GP_SCRIPTS
,
304 W_ERROR_HAVE_NO_MEMORY(keystr
);
306 reg_deletekey_recursive(root_key
, keystr
);
308 werr
= gp_store_reg_subkey(mem_ctx
, keystr
,
309 root_key
, &root_key
);
310 if (!W_ERROR_IS_OK(werr
)) {
314 werr
= scripts_store_reg_gpovals(mem_ctx
, root_key
, gpo
);
315 if (!W_ERROR_IS_OK(werr
)) {
319 for (i
=0; i
<num_entries
; i
++) {
321 werr
= reg_apply_registry_entry(mem_ctx
, root_key
, reg_ctx
,
324 if (!W_ERROR_IS_OK(werr
)) {
325 DEBUG(0,("failed to apply registry: %s\n",
332 gp_free_reg_ctx(reg_ctx
);
336 /****************************************************************
337 ****************************************************************/
339 static NTSTATUS
scripts_process_group_policy(TALLOC_CTX
*mem_ctx
,
341 struct registry_key
*root_key
,
342 const struct security_token
*token
,
343 const struct GROUP_POLICY_OBJECT
*deleted_gpo_list
,
344 const struct GROUP_POLICY_OBJECT
*changed_gpo_list
)
349 char *unix_path
= NULL
;
350 struct gp_inifile_context
*ini_ctx
= NULL
;
351 struct gp_registry_entry
*entries
= NULL
;
352 size_t num_entries
= 0;
353 const char *list
[] = {
354 GP_SCRIPTS_INI_STARTUP
,
355 GP_SCRIPTS_INI_SHUTDOWN
,
356 GP_SCRIPTS_INI_LOGON
,
357 GP_SCRIPTS_INI_LOGOFF
359 const struct GROUP_POLICY_OBJECT
*gpo
;
360 char *gpo_cache_path
= cache_path(GPO_CACHE_DIR
);
361 if (gpo_cache_path
== NULL
) {
362 return NT_STATUS_NO_MEMORY
;
365 /* implementation of the policy callback function, see
366 * http://msdn.microsoft.com/en-us/library/aa373494%28v=vs.85%29.aspx
367 * for details - gd */
369 /* for now do not process the list of deleted group policies
371 for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) {
376 for (gpo
= changed_gpo_list
; gpo
; gpo
= gpo
->next
) {
378 gpext_debug_header(0, "scripts_process_group_policy", flags
,
379 gpo
, GP_EXT_GUID_SCRIPTS
, NULL
);
381 status
= gpo_get_unix_path(mem_ctx
, gpo_cache_path
,
383 if (!NT_STATUS_IS_OK(status
)) {
384 goto err_cache_path_free
;
387 status
= gp_inifile_init_context(mem_ctx
, flags
, unix_path
,
388 GP_SCRIPTS_INI
, &ini_ctx
);
389 if (!NT_STATUS_IS_OK(status
)) {
390 goto err_cache_path_free
;
393 for (i
= 0; i
< ARRAY_SIZE(list
); i
++) {
395 TALLOC_FREE(entries
);
398 status
= scripts_parse_ini_section(ini_ctx
, flags
, list
[i
],
399 &entries
, &num_entries
);
400 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
404 if (!NT_STATUS_IS_OK(status
)) {
405 TALLOC_FREE(ini_ctx
);
406 goto err_cache_path_free
;
409 dump_reg_entries(flags
, "READ", entries
, num_entries
);
411 werr
= scripts_apply(ini_ctx
->mem_ctx
, token
, root_key
,
412 flags
, list
[i
], gpo
, entries
, num_entries
);
413 if (!W_ERROR_IS_OK(werr
)) {
414 continue; /* FIXME: finally fix storing emtpy strings and REG_QWORD! */
418 TALLOC_FREE(ini_ctx
);
420 status
= NT_STATUS_OK
;
423 talloc_free(gpo_cache_path
);
427 /****************************************************************
428 ****************************************************************/
430 static NTSTATUS
scripts_initialize(TALLOC_CTX
*mem_ctx
)
435 /****************************************************************
436 ****************************************************************/
438 static NTSTATUS
scripts_shutdown(void)
442 status
= gpext_unregister_gp_extension(GP_EXT_NAME
);
443 if (NT_STATUS_IS_OK(status
)) {
452 /****************************************************************
453 ****************************************************************/
455 static struct gp_extension_methods scripts_methods
= {
456 .initialize
= scripts_initialize
,
457 .process_group_policy
= scripts_process_group_policy
,
458 .get_reg_config
= scripts_get_reg_config
,
459 .shutdown
= scripts_shutdown
462 /****************************************************************
463 ****************************************************************/
465 NTSTATUS
gpext_scripts_init(void)
469 ctx
= talloc_init("gpext_scripts_init");
470 NT_STATUS_HAVE_NO_MEMORY(ctx
);
472 status
= gpext_register_gp_extension(ctx
, SMB_GPEXT_INTERFACE_VERSION
,
473 GP_EXT_NAME
, GP_EXT_GUID_SCRIPTS
,
475 if (!NT_STATUS_IS_OK(status
)) {