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"
23 #define GP_EXT_NAME "scripts"
25 #define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
27 #define GP_SCRIPTS_INI "Scripts/scripts.ini"
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"
34 #define GP_SCRIPTS_SECTION_CMDLINE "cmdline"
35 #define GP_SCRIPTS_SECTION_PARAMETERS "parameters"
37 #define GP_SCRIPTS_REG_VAL_SCRIPT "Script"
38 #define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters"
39 #define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime"
41 static TALLOC_CTX
*ctx
= NULL
;
43 /****************************************************************
44 ****************************************************************/
46 static NTSTATUS
scripts_get_reg_config(TALLOC_CTX
*mem_ctx
,
47 struct gp_extension_reg_info
**reg_info
)
50 struct gp_extension_reg_info
*info
= NULL
;
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
},
60 info
= TALLOC_ZERO_P(mem_ctx
, struct gp_extension_reg_info
);
61 NT_STATUS_HAVE_NO_MEMORY(info
);
63 status
= gp_ext_info_add_entry(mem_ctx
, GP_EXT_NAME
,
66 NT_STATUS_NOT_OK_RETURN(status
);
73 /****************************************************************
74 ****************************************************************/
76 static NTSTATUS
generate_gp_registry_entry(TALLOC_CTX
*mem_ctx
,
81 enum gp_reg_action action
,
82 struct gp_registry_entry
**entry_out
)
84 struct gp_registry_entry
*entry
= NULL
;
85 struct registry_value
*data
= NULL
;
87 entry
= TALLOC_ZERO_P(mem_ctx
, struct gp_registry_entry
);
88 NT_STATUS_HAVE_NO_MEMORY(entry
);
90 data
= TALLOC_ZERO_P(mem_ctx
, struct registry_value
);
91 NT_STATUS_HAVE_NO_MEMORY(data
);
93 data
->type
= data_type
;
96 data
->v
.qword
= *(uint64_t *)data_p
;
99 data
->v
.sz
.str
= talloc_strdup(mem_ctx
, (char *)data_p
);
100 data
->v
.sz
.len
= strlen(data
->v
.sz
.str
);
103 return NT_STATUS_NOT_SUPPORTED
;
108 entry
->action
= action
;
109 entry
->value
= talloc_strdup(mem_ctx
, value
);
110 NT_STATUS_HAVE_NO_MEMORY(entry
->value
);
117 /****************************************************************
118 ****************************************************************/
120 static NTSTATUS
scripts_parse_ini_section(struct gp_inifile_context
*ini_ctx
,
123 struct gp_registry_entry
**entries
,
126 NTSTATUS status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
132 const char *key
= NULL
;
133 const char *script
= NULL
;
134 const char *count
= NULL
;
135 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
;
162 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
164 GP_SCRIPTS_REG_VAL_SCRIPT
,
167 GP_REG_ACTION_ADD_VALUE
,
169 NT_STATUS_NOT_OK_RETURN(status
);
170 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
174 return NT_STATUS_NO_MEMORY
;
178 struct gp_registry_entry
*entry
= NULL
;
179 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
181 GP_SCRIPTS_REG_VAL_PARAMETERS
,
184 GP_REG_ACTION_ADD_VALUE
,
186 NT_STATUS_NOT_OK_RETURN(status
);
187 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
191 return NT_STATUS_NO_MEMORY
;
195 struct gp_registry_entry
*entry
= NULL
;
196 status
= generate_gp_registry_entry(ini_ctx
->mem_ctx
,
198 GP_SCRIPTS_REG_VAL_EXECTIME
,
201 GP_REG_ACTION_ADD_VALUE
,
203 NT_STATUS_NOT_OK_RETURN(status
);
204 if (!add_gp_registry_entry_to_array(ini_ctx
->mem_ctx
,
208 return NT_STATUS_NO_MEMORY
;
211 status
= NT_STATUS_OK
;
218 /****************************************************************
219 ****************************************************************/
221 static WERROR
scripts_store_reg_gpovals(TALLOC_CTX
*mem_ctx
,
222 struct registry_key
*key
,
223 struct GROUP_POLICY_OBJECT
*gpo
)
228 return WERR_INVALID_PARAM
;
231 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "DisplayName",
233 W_ERROR_NOT_OK_RETURN(werr
);
235 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "FileSysPath",
237 W_ERROR_NOT_OK_RETURN(werr
);
239 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPO-ID",
241 W_ERROR_NOT_OK_RETURN(werr
);
243 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "GPOName",
245 W_ERROR_NOT_OK_RETURN(werr
);
247 werr
= gp_store_reg_val_sz(mem_ctx
, key
, "SOM-ID",
249 W_ERROR_NOT_OK_RETURN(werr
);
254 /****************************************************************
255 ****************************************************************/
257 static WERROR
scripts_apply(TALLOC_CTX
*mem_ctx
,
258 const struct nt_user_token
*token
,
259 struct registry_key
*root_key
,
262 struct GROUP_POLICY_OBJECT
*gpo
,
263 struct gp_registry_entry
*entries
,
266 struct gp_registry_context
*reg_ctx
= NULL
;
269 const char *keystr
= NULL
;
272 if (num_entries
== 0) {
277 if (flags
& GPO_INFO_FLAG_MACHINE
) {
278 struct nt_user_token
*tmp_token
;
280 tmp_token
= registry_create_system_token(mem_ctx
);
281 W_ERROR_HAVE_NO_MEMORY(tmp_token
);
283 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKLM
, REG_KEY_WRITE
,
287 werr
= gp_init_reg_ctx(mem_ctx
, KEY_HKCU
, REG_KEY_WRITE
,
291 W_ERROR_NOT_OK_RETURN(werr
);
294 keystr
= talloc_asprintf(mem_ctx
, "%s\\%s\\%d", KEY_GP_SCRIPTS
,
296 W_ERROR_HAVE_NO_MEMORY(keystr
);
298 reg_deletekey_recursive(mem_ctx
, root_key
, keystr
);
300 werr
= gp_store_reg_subkey(mem_ctx
, keystr
,
301 root_key
, &root_key
);
302 if (!W_ERROR_IS_OK(werr
)) {
306 werr
= scripts_store_reg_gpovals(mem_ctx
, root_key
, gpo
);
307 if (!W_ERROR_IS_OK(werr
)) {
311 for (i
=0; i
<num_entries
; i
++) {
313 werr
= reg_apply_registry_entry(mem_ctx
, root_key
, reg_ctx
,
316 if (!W_ERROR_IS_OK(werr
)) {
317 DEBUG(0,("failed to apply registry: %s\n",
324 gp_free_reg_ctx(reg_ctx
);
328 /****************************************************************
329 ****************************************************************/
331 static NTSTATUS
scripts_process_group_policy(ADS_STRUCT
*ads
,
334 struct registry_key
*root_key
,
335 const struct nt_user_token
*token
,
336 struct GROUP_POLICY_OBJECT
*gpo
,
337 const char *extension_guid
,
338 const char *snapin_guid
)
343 char *unix_path
= NULL
;
344 struct gp_inifile_context
*ini_ctx
= NULL
;
345 struct gp_registry_entry
*entries
= NULL
;
346 size_t num_entries
= 0;
347 const char *list
[] = {
348 GP_SCRIPTS_INI_STARTUP
,
349 GP_SCRIPTS_INI_SHUTDOWN
,
350 GP_SCRIPTS_INI_LOGON
,
351 GP_SCRIPTS_INI_LOGOFF
354 debug_gpext_header(0, "scripts_process_group_policy", flags
, gpo
,
355 extension_guid
, snapin_guid
);
357 status
= gpo_get_unix_path(mem_ctx
, gpo
, &unix_path
);
358 NT_STATUS_NOT_OK_RETURN(status
);
360 status
= gp_inifile_init_context(mem_ctx
, flags
, unix_path
,
361 GP_SCRIPTS_INI
, &ini_ctx
);
362 NT_STATUS_NOT_OK_RETURN(status
);
364 for (i
= 0; i
< ARRAY_SIZE(list
); i
++) {
366 TALLOC_FREE(entries
);
369 status
= scripts_parse_ini_section(ini_ctx
, flags
, list
[i
],
370 &entries
, &num_entries
);
371 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
375 if (!NT_STATUS_IS_OK(status
)) {
379 dump_reg_entries(flags
, "READ", entries
, num_entries
);
381 werr
= scripts_apply(ini_ctx
->mem_ctx
, token
, root_key
,
382 flags
, list
[i
], gpo
, entries
, num_entries
);
383 if (!W_ERROR_IS_OK(werr
)) {
384 continue; /* FIXME: finally fix storing emtpy strings and REG_QWORD! */
385 TALLOC_FREE(ini_ctx
);
386 return werror_to_ntstatus(werr
);
390 TALLOC_FREE(ini_ctx
);
394 /****************************************************************
395 ****************************************************************/
397 static NTSTATUS
scripts_initialize(TALLOC_CTX
*mem_ctx
)
402 /****************************************************************
403 ****************************************************************/
405 static NTSTATUS
scripts_shutdown(void)
409 status
= unregister_gp_extension(GP_EXT_NAME
);
410 if (NT_STATUS_IS_OK(status
)) {
419 /****************************************************************
420 ****************************************************************/
422 static struct gp_extension_methods scripts_methods
= {
423 .initialize
= scripts_initialize
,
424 .process_group_policy
= scripts_process_group_policy
,
425 .get_reg_config
= scripts_get_reg_config
,
426 .shutdown
= scripts_shutdown
429 /****************************************************************
430 ****************************************************************/
432 NTSTATUS
gpext_scripts_init(void)
436 ctx
= talloc_init("gpext_scripts_init");
437 NT_STATUS_HAVE_NO_MEMORY(ctx
);
439 status
= register_gp_extension(ctx
, SMB_GPEXT_INTERFACE_VERSION
,
440 GP_EXT_NAME
, GP_EXT_GUID_SCRIPTS
,
442 if (!NT_STATUS_IS_OK(status
)) {