source: vendor/current/source3/libgpo/gpext/scripts.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 12.4 KB
Line 
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#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"
28
29#define GP_EXT_NAME "scripts"
30
31#define KEY_GP_SCRIPTS "Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
32
33#define GP_SCRIPTS_INI "Scripts/scripts.ini"
34
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"
39
40#define GP_SCRIPTS_SECTION_CMDLINE "cmdline"
41#define GP_SCRIPTS_SECTION_PARAMETERS "parameters"
42
43#define GP_SCRIPTS_REG_VAL_SCRIPT "Script"
44#define GP_SCRIPTS_REG_VAL_PARAMETERS "Parameters"
45#define GP_SCRIPTS_REG_VAL_EXECTIME "ExecTime"
46
47static TALLOC_CTX *ctx = NULL;
48
49/****************************************************************
50****************************************************************/
51
52static NTSTATUS scripts_get_reg_config(TALLOC_CTX *mem_ctx,
53 struct gp_extension_reg_info **reg_info)
54{
55 NTSTATUS status;
56 struct gp_extension_reg_info *info = NULL;
57
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 },
64 };
65
66 info = talloc_zero(mem_ctx, struct gp_extension_reg_info);
67 NT_STATUS_HAVE_NO_MEMORY(info);
68
69 status = gpext_info_add_entry(mem_ctx, GP_EXT_NAME,
70 GP_EXT_GUID_SCRIPTS,
71 table, info);
72 NT_STATUS_NOT_OK_RETURN(status);
73
74 *reg_info = info;
75
76 return NT_STATUS_OK;
77}
78
79/****************************************************************
80****************************************************************/
81
82static NTSTATUS generate_gp_registry_entry(TALLOC_CTX *mem_ctx,
83 const char *key,
84 const char *value,
85 uint32_t data_type,
86 const void *data_p,
87 enum gp_reg_action action,
88 struct gp_registry_entry **entry_out)
89{
90 struct gp_registry_entry *entry = NULL;
91 struct registry_value *data = NULL;
92
93 entry = talloc_zero(mem_ctx, struct gp_registry_entry);
94 NT_STATUS_HAVE_NO_MEMORY(entry);
95
96 data = talloc_zero(mem_ctx, struct registry_value);
97 NT_STATUS_HAVE_NO_MEMORY(data);
98
99 data->type = data_type;
100 switch (data->type) {
101 case REG_QWORD:
102 data->data = data_blob_talloc(mem_ctx, NULL, 8);
103 SBVAL(data->data.data, 0, *(uint64_t *)data_p);
104 break;
105 case REG_SZ:
106 if (!push_reg_sz(mem_ctx, &data->data, (const char *)data_p)) {
107 return NT_STATUS_NO_MEMORY;
108 }
109 break;
110 default:
111 return NT_STATUS_NOT_SUPPORTED;
112 }
113
114 entry->key = key;
115 entry->data = data;
116 entry->action = action;
117 entry->value = talloc_strdup(mem_ctx, value);
118 NT_STATUS_HAVE_NO_MEMORY(entry->value);
119
120 *entry_out = entry;
121
122 return NT_STATUS_OK;
123}
124
125/****************************************************************
126****************************************************************/
127
128static NTSTATUS scripts_parse_ini_section(struct gp_inifile_context *ini_ctx,
129 uint32_t flags,
130 const char *section,
131 struct gp_registry_entry **entries,
132 size_t *num_entries)
133{
134 NTSTATUS status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
135 NTSTATUS result;
136 int i = 0;
137
138 while (1) {
139
140 const char *key = NULL;
141 char *script = NULL;
142 const char *count = NULL;
143 char *parameters = NULL;
144
145 count = talloc_asprintf(ini_ctx->mem_ctx, "%d", i);
146 NT_STATUS_HAVE_NO_MEMORY(count);
147
148 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
149 section, count,
150 GP_SCRIPTS_SECTION_CMDLINE);
151 NT_STATUS_HAVE_NO_MEMORY(key);
152
153 result = gp_inifile_getstring(ini_ctx, key, &script);
154 if (!NT_STATUS_IS_OK(result)) {
155 break;
156 }
157
158 key = talloc_asprintf(ini_ctx->mem_ctx, "%s:%s%s",
159 section, count,
160 GP_SCRIPTS_SECTION_PARAMETERS);
161 NT_STATUS_HAVE_NO_MEMORY(key);
162
163 result = gp_inifile_getstring(ini_ctx, key, &parameters);
164 if (!NT_STATUS_IS_OK(result)) {
165 break;
166 }
167
168 {
169 struct gp_registry_entry *entry = NULL;
170 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
171 count,
172 GP_SCRIPTS_REG_VAL_SCRIPT,
173 REG_SZ,
174 script,
175 GP_REG_ACTION_ADD_VALUE,
176 &entry);
177 NT_STATUS_NOT_OK_RETURN(status);
178 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
179 entry,
180 entries,
181 num_entries)) {
182 return NT_STATUS_NO_MEMORY;
183 }
184 }
185 {
186 struct gp_registry_entry *entry = NULL;
187 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
188 count,
189 GP_SCRIPTS_REG_VAL_PARAMETERS,
190 REG_SZ,
191 parameters,
192 GP_REG_ACTION_ADD_VALUE,
193 &entry);
194 NT_STATUS_NOT_OK_RETURN(status);
195 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
196 entry,
197 entries,
198 num_entries)) {
199 return NT_STATUS_NO_MEMORY;
200 }
201 }
202 {
203 struct gp_registry_entry *entry = NULL;
204 status = generate_gp_registry_entry(ini_ctx->mem_ctx,
205 count,
206 GP_SCRIPTS_REG_VAL_EXECTIME,
207 REG_QWORD,
208 0,
209 GP_REG_ACTION_ADD_VALUE,
210 &entry);
211 NT_STATUS_NOT_OK_RETURN(status);
212 if (!add_gp_registry_entry_to_array(ini_ctx->mem_ctx,
213 entry,
214 entries,
215 num_entries)) {
216 return NT_STATUS_NO_MEMORY;
217 }
218 }
219 status = NT_STATUS_OK;
220 i++;
221 }
222
223 return status;
224}
225
226/****************************************************************
227****************************************************************/
228
229static WERROR scripts_store_reg_gpovals(TALLOC_CTX *mem_ctx,
230 struct registry_key *key,
231 const struct GROUP_POLICY_OBJECT *gpo)
232{
233 WERROR werr;
234
235 if (!key || !gpo) {
236 return WERR_INVALID_PARAM;
237 }
238
239 werr = gp_store_reg_val_sz(mem_ctx, key, "DisplayName",
240 gpo->display_name);
241 W_ERROR_NOT_OK_RETURN(werr);
242
243 werr = gp_store_reg_val_sz(mem_ctx, key, "FileSysPath",
244 gpo->file_sys_path);
245 W_ERROR_NOT_OK_RETURN(werr);
246
247 werr = gp_store_reg_val_sz(mem_ctx, key, "GPO-ID",
248 gpo->ds_path);
249 W_ERROR_NOT_OK_RETURN(werr);
250
251 werr = gp_store_reg_val_sz(mem_ctx, key, "GPOName",
252 gpo->name);
253 W_ERROR_NOT_OK_RETURN(werr);
254
255 werr = gp_store_reg_val_sz(mem_ctx, key, "SOM-ID",
256 gpo->link);
257 W_ERROR_NOT_OK_RETURN(werr);
258
259 return werr;
260}
261
262/****************************************************************
263****************************************************************/
264
265static WERROR scripts_apply(TALLOC_CTX *mem_ctx,
266 const struct security_token *token,
267 struct registry_key *root_key,
268 uint32_t flags,
269 const char *section,
270 const struct GROUP_POLICY_OBJECT *gpo,
271 struct gp_registry_entry *entries,
272 size_t num_entries)
273{
274 struct gp_registry_context *reg_ctx = NULL;
275 WERROR werr;
276 size_t i;
277 const char *keystr = NULL;
278 int count = 0;
279
280 if (num_entries == 0) {
281 return WERR_OK;
282 }
283
284#if 0
285 if (flags & GPO_INFO_FLAG_MACHINE) {
286 struct security_token *tmp_token;
287
288 tmp_token = registry_create_system_token(mem_ctx);
289 W_ERROR_HAVE_NO_MEMORY(tmp_token);
290
291 werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
292 tmp_token,
293 &reg_ctx);
294 } else {
295 werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
296 token,
297 &reg_ctx);
298 }
299 W_ERROR_NOT_OK_RETURN(werr);
300#endif
301
302 keystr = talloc_asprintf(mem_ctx, "%s\\%s\\%d", KEY_GP_SCRIPTS,
303 section, count++);
304 W_ERROR_HAVE_NO_MEMORY(keystr);
305
306 reg_deletekey_recursive(root_key, keystr);
307
308 werr = gp_store_reg_subkey(mem_ctx, keystr,
309 root_key, &root_key);
310 if (!W_ERROR_IS_OK(werr)) {
311 goto done;
312 }
313
314 werr = scripts_store_reg_gpovals(mem_ctx, root_key, gpo);
315 if (!W_ERROR_IS_OK(werr)) {
316 goto done;
317 }
318
319 for (i=0; i<num_entries; i++) {
320
321 werr = reg_apply_registry_entry(mem_ctx, root_key, reg_ctx,
322 &(entries)[i],
323 token, flags);
324 if (!W_ERROR_IS_OK(werr)) {
325 DEBUG(0,("failed to apply registry: %s\n",
326 win_errstr(werr)));
327 goto done;
328 }
329 }
330
331 done:
332 gp_free_reg_ctx(reg_ctx);
333 return werr;
334}
335
336/****************************************************************
337****************************************************************/
338
339static NTSTATUS scripts_process_group_policy(TALLOC_CTX *mem_ctx,
340 uint32_t flags,
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)
345{
346 NTSTATUS status;
347 WERROR werr;
348 int i = 0;
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
358 };
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;
363 }
364
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 */
368
369 /* for now do not process the list of deleted group policies
370
371 for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) {
372 }
373
374 */
375
376 for (gpo = changed_gpo_list; gpo; gpo = gpo->next) {
377
378 gpext_debug_header(0, "scripts_process_group_policy", flags,
379 gpo, GP_EXT_GUID_SCRIPTS, NULL);
380
381 status = gpo_get_unix_path(mem_ctx, gpo_cache_path,
382 gpo, &unix_path);
383 if (!NT_STATUS_IS_OK(status)) {
384 goto err_cache_path_free;
385 }
386
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;
391 }
392
393 for (i = 0; i < ARRAY_SIZE(list); i++) {
394
395 TALLOC_FREE(entries);
396 num_entries = 0;
397
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)) {
401 continue;
402 }
403
404 if (!NT_STATUS_IS_OK(status)) {
405 TALLOC_FREE(ini_ctx);
406 goto err_cache_path_free;
407 }
408
409 dump_reg_entries(flags, "READ", entries, num_entries);
410
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! */
415 }
416 }
417
418 TALLOC_FREE(ini_ctx);
419 }
420 status = NT_STATUS_OK;
421
422err_cache_path_free:
423 talloc_free(gpo_cache_path);
424 return status;
425}
426
427/****************************************************************
428****************************************************************/
429
430static NTSTATUS scripts_initialize(TALLOC_CTX *mem_ctx)
431{
432 return NT_STATUS_OK;
433}
434
435/****************************************************************
436****************************************************************/
437
438static NTSTATUS scripts_shutdown(void)
439{
440 NTSTATUS status;
441
442 status = gpext_unregister_gp_extension(GP_EXT_NAME);
443 if (NT_STATUS_IS_OK(status)) {
444 return status;
445 }
446
447 TALLOC_FREE(ctx);
448
449 return NT_STATUS_OK;
450}
451
452/****************************************************************
453****************************************************************/
454
455static 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
460};
461
462/****************************************************************
463****************************************************************/
464
465NTSTATUS gpext_scripts_init(void)
466{
467 NTSTATUS status;
468
469 ctx = talloc_init("gpext_scripts_init");
470 NT_STATUS_HAVE_NO_MEMORY(ctx);
471
472 status = gpext_register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
473 GP_EXT_NAME, GP_EXT_GUID_SCRIPTS,
474 &scripts_methods);
475 if (!NT_STATUS_IS_OK(status)) {
476 TALLOC_FREE(ctx);
477 }
478
479 return status;
480}
Note: See TracBrowser for help on using the repository browser.