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 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
)
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
,
74 NT_STATUS_NOT_OK_RETURN(status
);
81 /****************************************************************
82 ****************************************************************/
84 static NTSTATUS
generate_gp_registry_entry(TALLOC_CTX
*mem_ctx
,
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
;
106 entry
->action
= action
;
107 entry
->value
= talloc_strdup(mem_ctx
, value
);
108 NT_STATUS_HAVE_NO_MEMORY(entry
->value
);
115 /****************************************************************
116 ****************************************************************/
118 static NTSTATUS
scripts_parse_ini_section(struct gp_inifile_context
*ini_ctx
,
121 struct gp_registry_entry
**entries
,
124 NTSTATUS status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
130 const char *key
= NULL
;
131 const char *script
= NULL
;
132 const char *count
= NULL
;
133 const char *parameters
= NULL
;
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",
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
)) {
150 key
= talloc_asprintf(ini_ctx
->mem_ctx
, "%s:%s%s",
152 GP_SCRIPTS_SECTION_PARAMETERS
);
153 NT_STATUS_HAVE_NO_MEMORY(key
);
155 result
= gp_inifile_getstring(ini_ctx
, key
, ¶meters
);
156 if (!NT_STATUS_IS_OK(result
)) {
161 struct gp_registry_entry
*entry
= NULL
;
163 ok
= push_reg_sz(ini_ctx
->mem_ctx
, &blob
, script
);
165 return NT_STATUS_NO_MEMORY
;
168 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
170 GP_SCRIPTS_REG_VAL_SCRIPT
,
173 GP_REG_ACTION_ADD_VALUE
,
175 NT_STATUS_NOT_OK_RETURN(status
);
176 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
180 return NT_STATUS_NO_MEMORY
;
184 struct gp_registry_entry
*entry
= NULL
;
186 ok
= push_reg_sz(ini_ctx
->mem_ctx
, &blob
, parameters
);
188 return NT_STATUS_NO_MEMORY
;
191 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
193 GP_SCRIPTS_REG_VAL_PARAMETERS
,
196 GP_REG_ACTION_ADD_VALUE
,
198 NT_STATUS_NOT_OK_RETURN(status
);
199 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
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
,
213 GP_SCRIPTS_REG_VAL_EXECTIME
,
216 GP_REG_ACTION_ADD_VALUE
,
218 NT_STATUS_NOT_OK_RETURN(status
);
219 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
223 return NT_STATUS_NO_MEMORY
;
226 status
= NT_STATUS_OK
;
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
)
243 return WERR_INVALID_PARAMETER
;
246 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "DisplayName",
248 W_ERROR_NOT_OK_RETURN(werr
);
250 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "FileSysPath",
252 W_ERROR_NOT_OK_RETURN(werr
);
254 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPO-ID",
256 W_ERROR_NOT_OK_RETURN(werr
);
258 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPOName",
260 W_ERROR_NOT_OK_RETURN(werr
);
262 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "SOM-ID",
264 W_ERROR_NOT_OK_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
,
277 const struct GROUP_POLICY_OBJECT
*gpo
,
278 struct gp_registry_entry
*entries
,
281 struct gp_registry_context
*reg_ctx
= NULL
;
284 const char *keystr
= NULL
;
287 if (num_entries
== 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
,
302 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKCU
, REG_KEY_WRITE
,
306 W_ERROR_NOT_OK_RETURN(werr
);
309 keystr
= talloc_asprintf(mem_ctx
, "%s\\%s\\%d", KEY_GP_SCRIPTS
,
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
)) {
321 werr
= scripts_store_reg_gpovals(mem_ctx
, root_key
, gpo
);
322 if (!W_ERROR_IS_OK(werr
)) {
326 for (i
=0; i
<num_entries
; i
++) {
328 werr
= reg_apply_registry_entry(mem_ctx
, root_key
, reg_ctx
,
331 if (!W_ERROR_IS_OK(werr
)) {
332 DEBUG(0,("failed to apply registry: %s\n",
339 gp_free_reg_ctx(reg_ctx
);
343 /****************************************************************
344 ****************************************************************/
346 static NTSTATUS
scripts_process_group_policy(TALLOC_CTX
*mem_ctx
,
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
)
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
,
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
);
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
)) {
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
;
430 talloc_free(gpo_cache_path
);
434 /****************************************************************
435 ****************************************************************/
437 static NTSTATUS
scripts_initialize(TALLOC_CTX
*mem_ctx
)
442 /****************************************************************
443 ****************************************************************/
445 static NTSTATUS
scripts_shutdown(void)
449 status
= gpext_unregister_gp_extension(GP_EXT_NAME
);
450 if (NT_STATUS_IS_OK(status
)) {
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
)
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
,
482 if (!NT_STATUS_IS_OK(status
)) {