Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Group Policy Support
4 : * Copyright (C) Guenther Deschner 2007-2008
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.h"
22 : #include "../libgpo/gpext/gpext.h"
23 : #include "librpc/gen_ndr/ndr_misc.h"
24 : #include "lib/util/dlinklist.h"
25 : #include "../libcli/registry/util_reg.h"
26 : #include "libgpo/gpo_proto.h"
27 : #include "registry.h"
28 : #include "registry/reg_api.h"
29 : #include "lib/util/util_paths.h"
30 : #include "lib/util/string_wrappers.h"
31 :
32 : static struct gp_extension *extensions = NULL;
33 :
34 : /****************************************************************
35 : ****************************************************************/
36 :
37 0 : struct gp_extension *gpext_get_gp_extension_list(void)
38 : {
39 0 : return extensions;
40 : }
41 :
42 : /****************************************************************
43 : ****************************************************************/
44 :
45 :
46 : struct gp_extension_reg_table gpext_reg_vals[] = {
47 : {
48 : .val = "DllName",
49 : .type = REG_EXPAND_SZ,
50 : },
51 : {
52 : .val = "ProcessGroupPolicy",
53 : .type = REG_SZ,
54 : },
55 : {
56 : .val = "NoMachinePolicy",
57 : .type = REG_DWORD,
58 : },
59 : {
60 : .val = "NoUserPolicy",
61 : .type = REG_DWORD,
62 : },
63 : {
64 : .val = "NoSlowLink",
65 : .type = REG_DWORD,
66 : },
67 : {
68 : .val = "NoBackgroundPolicy",
69 : .type = REG_DWORD,
70 : },
71 : {
72 : .val = "NoGPOListChanges",
73 : .type = REG_DWORD,
74 : },
75 : {
76 : .val = "PerUserLocalSettings",
77 : .type = REG_DWORD,
78 : },
79 : {
80 : .val = "RequiresSuccessfulRegistry",
81 : .type = REG_DWORD,
82 : },
83 : {
84 : .val = "EnableAsynchronousProcessing",
85 : .type = REG_DWORD,
86 : },
87 : {
88 : .val = "ExtensionDebugLevel",
89 : .type = REG_DWORD,
90 : },
91 : /* new */
92 : {
93 : .val = "GenerateGroupPolicy", /* not supported on w2k */
94 : .type = REG_SZ,
95 : },
96 : {
97 : .val = "NotifyLinkTransition",
98 : .type = REG_DWORD,
99 : },
100 : {
101 : .val = "ProcessGroupPolicyEx", /* not supported on w2k */
102 : .type = REG_SZ,
103 : },
104 : {
105 : .val = "ExtensionEventSource", /* not supported on w2k */
106 : .type = REG_MULTI_SZ,
107 : },
108 : {
109 : .val = "MaxNoGPOListChangesInterval",
110 : .type = REG_DWORD,
111 : },
112 : { .type = REG_NONE }
113 : };
114 :
115 : /****************************************************************
116 : ****************************************************************/
117 :
118 0 : static struct gp_extension *get_extension_by_name(struct gp_extension *be,
119 : const char *name)
120 : {
121 0 : struct gp_extension *b;
122 :
123 0 : for (b = be; b; b = b->next) {
124 0 : if (strequal(b->name, name)) {
125 0 : return b;
126 : }
127 : }
128 :
129 0 : return NULL;
130 : }
131 :
132 : /****************************************************************
133 : ****************************************************************/
134 :
135 0 : static struct gp_extension_methods *get_methods_by_name(struct gp_extension *be,
136 : const char *name)
137 : {
138 0 : struct gp_extension *b;
139 :
140 0 : for (b = be; b; b = b->next) {
141 0 : if (strequal(b->name, name)) {
142 0 : return b->methods;
143 : }
144 : }
145 :
146 0 : return NULL;
147 : }
148 :
149 : /****************************************************************
150 : ****************************************************************/
151 :
152 0 : NTSTATUS gpext_unregister_gp_extension(const char *name)
153 : {
154 0 : struct gp_extension *ext;
155 :
156 0 : ext = get_extension_by_name(extensions, name);
157 0 : if (!ext) {
158 0 : return NT_STATUS_OK;
159 : }
160 :
161 0 : DLIST_REMOVE(extensions, ext);
162 0 : talloc_free(ext);
163 :
164 0 : DEBUG(2,("Successfully removed GP extension '%s'\n", name));
165 :
166 0 : return NT_STATUS_OK;
167 : }
168 :
169 : /****************************************************************
170 : ****************************************************************/
171 :
172 0 : NTSTATUS gpext_register_gp_extension(TALLOC_CTX *gpext_ctx,
173 : int version,
174 : const char *name,
175 : const char *guid,
176 : struct gp_extension_methods *methods)
177 : {
178 0 : struct gp_extension_methods *test;
179 0 : struct gp_extension *entry;
180 0 : NTSTATUS status;
181 :
182 0 : if (!gpext_ctx) {
183 0 : return NT_STATUS_INTERNAL_DB_ERROR;
184 : }
185 :
186 0 : if ((version != SMB_GPEXT_INTERFACE_VERSION)) {
187 0 : DEBUG(0,("Failed to register gp extension.\n"
188 : "The module was compiled against "
189 : "SMB_GPEXT_INTERFACE_VERSION %d,\n"
190 : "current SMB_GPEXT_INTERFACE_VERSION is %d.\n"
191 : "Please recompile against the current "
192 : "version of samba!\n",
193 : version, SMB_GPEXT_INTERFACE_VERSION));
194 0 : return NT_STATUS_OBJECT_TYPE_MISMATCH;
195 : }
196 :
197 0 : if (!guid || !name || !name[0] || !methods) {
198 0 : DEBUG(0,("Called with NULL pointer or empty name!\n"));
199 0 : return NT_STATUS_INVALID_PARAMETER;
200 : }
201 :
202 0 : test = get_methods_by_name(extensions, name);
203 0 : if (test) {
204 0 : DEBUG(0,("GP extension module %s already registered!\n",
205 : name));
206 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
207 : }
208 :
209 0 : entry = talloc_zero(gpext_ctx, struct gp_extension);
210 0 : NT_STATUS_HAVE_NO_MEMORY(entry);
211 :
212 0 : entry->name = talloc_strdup(gpext_ctx, name);
213 0 : NT_STATUS_HAVE_NO_MEMORY(entry->name);
214 :
215 0 : entry->guid = talloc_zero(gpext_ctx, struct GUID);
216 0 : NT_STATUS_HAVE_NO_MEMORY(entry->guid);
217 0 : status = GUID_from_string(guid, entry->guid);
218 0 : NT_STATUS_NOT_OK_RETURN(status);
219 :
220 0 : entry->methods = methods;
221 0 : DLIST_ADD(extensions, entry);
222 :
223 0 : DEBUG(2,("Successfully added GP extension '%s' %s\n",
224 : name, GUID_string2(gpext_ctx, entry->guid)));
225 :
226 0 : return NT_STATUS_OK;
227 : }
228 :
229 : /****************************************************************
230 : ****************************************************************/
231 :
232 0 : static NTSTATUS gp_extension_init_module(TALLOC_CTX *mem_ctx,
233 : const char *name,
234 : struct gp_extension **gpext)
235 : {
236 0 : NTSTATUS status;
237 0 : struct gp_extension *ext = NULL;
238 :
239 0 : ext = talloc_zero(mem_ctx, struct gp_extension);
240 0 : NT_STATUS_HAVE_NO_MEMORY(gpext);
241 :
242 0 : ext->methods = get_methods_by_name(extensions, name);
243 0 : if (!ext->methods) {
244 :
245 0 : status = smb_probe_module(SAMBA_SUBSYSTEM_GPEXT,
246 : name);
247 0 : if (!NT_STATUS_IS_OK(status)) {
248 0 : return status;
249 : }
250 :
251 0 : ext->methods = get_methods_by_name(extensions, name);
252 0 : if (!ext->methods) {
253 0 : return NT_STATUS_DLL_INIT_FAILED;
254 : }
255 : }
256 :
257 0 : *gpext = ext;
258 :
259 0 : return NT_STATUS_OK;
260 : }
261 :
262 : /****************************************************************
263 : ****************************************************************/
264 :
265 0 : static bool add_gp_extension_reg_entry_to_array(TALLOC_CTX *mem_ctx,
266 : struct gp_extension_reg_entry *entry,
267 : struct gp_extension_reg_entry **entries,
268 : size_t *num)
269 : {
270 0 : *entries = talloc_realloc(mem_ctx, *entries,
271 : struct gp_extension_reg_entry,
272 : (*num)+1);
273 0 : if (*entries == NULL) {
274 0 : *num = 0;
275 0 : return false;
276 : }
277 :
278 0 : (*entries)[*num].value = entry->value;
279 0 : (*entries)[*num].data = entry->data;
280 :
281 0 : *num += 1;
282 0 : return true;
283 : }
284 :
285 : /****************************************************************
286 : ****************************************************************/
287 :
288 0 : static bool add_gp_extension_reg_info_entry_to_array(TALLOC_CTX *mem_ctx,
289 : struct gp_extension_reg_info_entry *entry,
290 : struct gp_extension_reg_info_entry **entries,
291 : size_t *num)
292 : {
293 0 : *entries = talloc_realloc(mem_ctx, *entries,
294 : struct gp_extension_reg_info_entry,
295 : (*num)+1);
296 0 : if (*entries == NULL) {
297 0 : *num = 0;
298 0 : return false;
299 : }
300 :
301 0 : (*entries)[*num].guid = entry->guid;
302 0 : (*entries)[*num].num_entries = entry->num_entries;
303 0 : (*entries)[*num].entries = entry->entries;
304 :
305 0 : *num += 1;
306 0 : return true;
307 : }
308 :
309 : /****************************************************************
310 : ****************************************************************/
311 :
312 0 : static NTSTATUS gp_ext_info_add_reg(TALLOC_CTX *mem_ctx,
313 : struct gp_extension_reg_info_entry *entry,
314 : const char *value,
315 : enum winreg_Type type,
316 : const char *data_s)
317 : {
318 0 : struct gp_extension_reg_entry *reg_entry = NULL;
319 0 : struct registry_value *data = NULL;
320 :
321 0 : reg_entry = talloc_zero(mem_ctx, struct gp_extension_reg_entry);
322 0 : NT_STATUS_HAVE_NO_MEMORY(reg_entry);
323 :
324 0 : data = talloc_zero(mem_ctx, struct registry_value);
325 0 : NT_STATUS_HAVE_NO_MEMORY(data);
326 :
327 0 : data->type = type;
328 :
329 0 : switch (type) {
330 0 : case REG_SZ:
331 : case REG_EXPAND_SZ:
332 0 : if (!push_reg_sz(mem_ctx, &data->data, data_s)) {
333 0 : return NT_STATUS_NO_MEMORY;
334 : }
335 0 : break;
336 0 : case REG_DWORD: {
337 0 : uint32_t v = atoi(data_s);
338 0 : data->data = data_blob_talloc(mem_ctx, NULL, 4);
339 0 : SIVAL(data->data.data, 0, v);
340 0 : break;
341 : }
342 0 : default:
343 0 : return NT_STATUS_NOT_SUPPORTED;
344 : }
345 :
346 0 : reg_entry->value = value;
347 0 : reg_entry->data = data;
348 :
349 0 : if (!add_gp_extension_reg_entry_to_array(mem_ctx, reg_entry,
350 : &entry->entries,
351 : &entry->num_entries)) {
352 0 : return NT_STATUS_NO_MEMORY;
353 : }
354 :
355 0 : return NT_STATUS_OK;
356 : }
357 :
358 : /****************************************************************
359 : ****************************************************************/
360 :
361 0 : static NTSTATUS gp_ext_info_add_reg_table(TALLOC_CTX *mem_ctx,
362 : const char *module,
363 : struct gp_extension_reg_info_entry *entry,
364 : struct gp_extension_reg_table *table)
365 : {
366 0 : NTSTATUS status;
367 0 : const char *module_name = NULL;
368 0 : int i;
369 :
370 0 : module_name = talloc_asprintf(mem_ctx, "%s.%s", module, shlib_ext());
371 0 : NT_STATUS_HAVE_NO_MEMORY(module_name);
372 :
373 0 : status = gp_ext_info_add_reg(mem_ctx, entry,
374 : "DllName", REG_EXPAND_SZ, module_name);
375 0 : NT_STATUS_NOT_OK_RETURN(status);
376 :
377 0 : for (i=0; table[i].val; i++) {
378 0 : status = gp_ext_info_add_reg(mem_ctx, entry,
379 0 : table[i].val,
380 0 : table[i].type,
381 0 : table[i].data);
382 0 : NT_STATUS_NOT_OK_RETURN(status);
383 : }
384 :
385 0 : return status;
386 : }
387 :
388 : /****************************************************************
389 : ****************************************************************/
390 :
391 0 : NTSTATUS gpext_info_add_entry(TALLOC_CTX *mem_ctx,
392 : const char *module,
393 : const char *ext_guid,
394 : struct gp_extension_reg_table *table,
395 : struct gp_extension_reg_info *info)
396 : {
397 0 : NTSTATUS status;
398 0 : struct gp_extension_reg_info_entry *entry = NULL;
399 :
400 0 : entry = talloc_zero(mem_ctx, struct gp_extension_reg_info_entry);
401 0 : NT_STATUS_HAVE_NO_MEMORY(entry);
402 :
403 0 : status = GUID_from_string(ext_guid, &entry->guid);
404 0 : NT_STATUS_NOT_OK_RETURN(status);
405 :
406 0 : status = gp_ext_info_add_reg_table(mem_ctx, module, entry, table);
407 0 : NT_STATUS_NOT_OK_RETURN(status);
408 :
409 0 : if (!add_gp_extension_reg_info_entry_to_array(mem_ctx, entry,
410 : &info->entries,
411 : &info->num_entries)) {
412 0 : return NT_STATUS_NO_MEMORY;
413 : }
414 :
415 0 : return NT_STATUS_OK;
416 : }
417 :
418 : /****************************************************************
419 : ****************************************************************/
420 :
421 0 : static bool gp_extension_reg_info_verify_entry(struct gp_extension_reg_entry *entry)
422 : {
423 0 : int i;
424 :
425 0 : for (i=0; gpext_reg_vals[i].val; i++) {
426 :
427 0 : if ((strequal(entry->value, gpext_reg_vals[i].val)) &&
428 0 : (entry->data->type == gpext_reg_vals[i].type)) {
429 0 : return true;
430 : }
431 : }
432 :
433 0 : return false;
434 : }
435 :
436 : /****************************************************************
437 : ****************************************************************/
438 :
439 0 : static bool gp_extension_reg_info_verify(struct gp_extension_reg_info_entry *entry)
440 : {
441 0 : int i;
442 :
443 0 : for (i=0; i < entry->num_entries; i++) {
444 0 : if (!gp_extension_reg_info_verify_entry(&entry->entries[i])) {
445 0 : return false;
446 : }
447 : }
448 :
449 0 : return true;
450 : }
451 :
452 : /****************************************************************
453 : ****************************************************************/
454 :
455 0 : static WERROR gp_extension_store_reg_vals(TALLOC_CTX *mem_ctx,
456 : struct registry_key *key,
457 : struct gp_extension_reg_info_entry *entry)
458 : {
459 0 : WERROR werr = WERR_OK;
460 0 : size_t i;
461 :
462 0 : for (i=0; i < entry->num_entries; i++) {
463 :
464 0 : werr = reg_setvalue(key,
465 0 : entry->entries[i].value,
466 0 : entry->entries[i].data);
467 0 : W_ERROR_NOT_OK_RETURN(werr);
468 : }
469 :
470 0 : return werr;
471 : }
472 :
473 : /****************************************************************
474 : ****************************************************************/
475 :
476 0 : static WERROR gp_extension_store_reg_entry(TALLOC_CTX *mem_ctx,
477 : struct gp_registry_context *reg_ctx,
478 : struct gp_extension_reg_info_entry *entry)
479 : {
480 0 : WERROR werr;
481 0 : struct registry_key *key = NULL;
482 0 : const char *subkeyname = NULL;
483 :
484 0 : if (!gp_extension_reg_info_verify(entry)) {
485 0 : return WERR_INVALID_PARAMETER;
486 : }
487 :
488 0 : subkeyname = GUID_string2(mem_ctx, &entry->guid);
489 0 : W_ERROR_HAVE_NO_MEMORY(subkeyname);
490 :
491 0 : if (!strupper_m(discard_const_p(char, subkeyname))) {
492 0 : return WERR_INVALID_PARAMETER;
493 : }
494 :
495 0 : werr = gp_store_reg_subkey(mem_ctx,
496 : subkeyname,
497 : reg_ctx->curr_key,
498 : &key);
499 0 : W_ERROR_NOT_OK_RETURN(werr);
500 :
501 0 : werr = gp_extension_store_reg_vals(mem_ctx,
502 : key,
503 : entry);
504 0 : W_ERROR_NOT_OK_RETURN(werr);
505 :
506 0 : return werr;
507 : }
508 :
509 : /****************************************************************
510 : ****************************************************************/
511 :
512 0 : static WERROR gp_extension_store_reg(TALLOC_CTX *mem_ctx,
513 : struct gp_registry_context *reg_ctx,
514 : struct gp_extension_reg_info *info)
515 : {
516 0 : WERROR werr = WERR_OK;
517 0 : int i;
518 :
519 0 : if (!info) {
520 0 : return WERR_OK;
521 : }
522 :
523 0 : for (i=0; i < info->num_entries; i++) {
524 0 : werr = gp_extension_store_reg_entry(mem_ctx,
525 : reg_ctx,
526 0 : &info->entries[i]);
527 0 : W_ERROR_NOT_OK_RETURN(werr);
528 : }
529 :
530 0 : return werr;
531 : }
532 :
533 : /****************************************************************
534 : ****************************************************************/
535 :
536 0 : static NTSTATUS gp_glob_ext_list(TALLOC_CTX *mem_ctx,
537 : const char ***ext_list,
538 : size_t *ext_list_len)
539 : {
540 0 : DIR *dir = NULL;
541 0 : struct dirent *dirent = NULL;
542 :
543 0 : dir = opendir(modules_path(talloc_tos(),
544 : SAMBA_SUBSYSTEM_GPEXT));
545 0 : if (!dir) {
546 0 : return map_nt_error_from_unix_common(errno);
547 : }
548 :
549 0 : while ((dirent = readdir(dir))) {
550 :
551 0 : fstring name; /* forgive me... */
552 0 : char *p;
553 :
554 0 : if ((strequal(dirent->d_name, ".")) ||
555 0 : (strequal(dirent->d_name, ".."))) {
556 0 : continue;
557 : }
558 :
559 0 : p = strrchr(dirent->d_name, '.');
560 0 : if (!p) {
561 0 : closedir(dir);
562 0 : return NT_STATUS_NO_MEMORY;
563 : }
564 :
565 0 : if (!strcsequal(p+1, shlib_ext())) {
566 0 : DEBUG(10,("gp_glob_ext_list: not a *.so file: %s\n",
567 : dirent->d_name));
568 0 : continue;
569 : }
570 :
571 0 : fstrcpy(name, dirent->d_name);
572 0 : name[PTR_DIFF(p, dirent->d_name)] = 0;
573 :
574 0 : if (!add_string_to_array(mem_ctx, name, ext_list,
575 : ext_list_len)) {
576 0 : closedir(dir);
577 0 : return NT_STATUS_NO_MEMORY;
578 : }
579 : }
580 :
581 0 : closedir(dir);
582 :
583 0 : return NT_STATUS_OK;
584 : }
585 :
586 : /****************************************************************
587 : ****************************************************************/
588 :
589 0 : NTSTATUS gpext_shutdown_gp_extensions(void)
590 : {
591 0 : struct gp_extension *ext = NULL;
592 :
593 0 : for (ext = extensions; ext; ext = ext->next) {
594 0 : if (ext->methods && ext->methods->shutdown) {
595 0 : ext->methods->shutdown();
596 : }
597 : }
598 :
599 0 : return NT_STATUS_OK;
600 : }
601 :
602 : /****************************************************************
603 : ****************************************************************/
604 :
605 0 : NTSTATUS gpext_init_gp_extensions(TALLOC_CTX *mem_ctx)
606 : {
607 0 : NTSTATUS status;
608 0 : WERROR werr;
609 0 : int i = 0;
610 0 : const char **ext_array = NULL;
611 0 : size_t ext_array_len = 0;
612 0 : struct gp_extension *gpext = NULL;
613 0 : struct gp_registry_context *reg_ctx = NULL;
614 :
615 0 : if (gpext_get_gp_extension_list()) {
616 0 : return NT_STATUS_OK;
617 : }
618 :
619 0 : status = gp_glob_ext_list(mem_ctx, &ext_array, &ext_array_len);
620 0 : NT_STATUS_NOT_OK_RETURN(status);
621 :
622 0 : for (i=0; i<ext_array_len; i++) {
623 :
624 0 : struct gp_extension_reg_info *info = NULL;
625 :
626 0 : status = gp_extension_init_module(mem_ctx, ext_array[i],
627 : &gpext);
628 0 : if (!NT_STATUS_IS_OK(status)) {
629 0 : goto out;
630 : }
631 :
632 0 : if (gpext->methods->get_reg_config) {
633 :
634 0 : status = gpext->methods->initialize(mem_ctx);
635 0 : if (!NT_STATUS_IS_OK(status)) {
636 0 : gpext->methods->shutdown();
637 0 : goto out;
638 : }
639 :
640 0 : status = gpext->methods->get_reg_config(mem_ctx,
641 : &info);
642 0 : if (!NT_STATUS_IS_OK(status)) {
643 0 : gpext->methods->shutdown();
644 0 : goto out;
645 : }
646 :
647 0 : if (!reg_ctx) {
648 0 : struct security_token *token;
649 :
650 0 : token = registry_create_system_token(mem_ctx);
651 0 : NT_STATUS_HAVE_NO_MEMORY(token);
652 :
653 0 : werr = gp_init_reg_ctx(mem_ctx,
654 : KEY_WINLOGON_GPEXT_PATH,
655 : REG_KEY_WRITE,
656 : token,
657 : ®_ctx);
658 0 : if (!W_ERROR_IS_OK(werr)) {
659 0 : status = werror_to_ntstatus(werr);
660 0 : gpext->methods->shutdown();
661 0 : goto out;
662 : }
663 : }
664 :
665 0 : werr = gp_extension_store_reg(mem_ctx, reg_ctx, info);
666 0 : if (!W_ERROR_IS_OK(werr)) {
667 0 : DEBUG(1,("gp_extension_store_reg failed: %s\n",
668 : win_errstr(werr)));
669 0 : TALLOC_FREE(info);
670 0 : gpext->methods->shutdown();
671 0 : status = werror_to_ntstatus(werr);
672 0 : goto out;
673 : }
674 0 : TALLOC_FREE(info);
675 : }
676 :
677 : }
678 :
679 0 : out:
680 0 : TALLOC_FREE(reg_ctx);
681 :
682 0 : return status;
683 : }
684 :
685 : /****************************************************************
686 : ****************************************************************/
687 :
688 0 : NTSTATUS gpext_free_gp_extensions(void)
689 : {
690 0 : struct gp_extension *ext, *ext_next = NULL;
691 :
692 0 : for (ext = extensions; ext; ext = ext_next) {
693 0 : ext_next = ext->next;
694 0 : DLIST_REMOVE(extensions, ext);
695 0 : TALLOC_FREE(ext);
696 : }
697 :
698 0 : extensions = NULL;
699 :
700 0 : return NT_STATUS_OK;
701 : }
702 :
703 : /****************************************************************
704 : ****************************************************************/
705 :
706 0 : void gpext_debug_header(int lvl,
707 : const char *name,
708 : uint32_t flags,
709 : const struct GROUP_POLICY_OBJECT *gpo,
710 : const char *extension_guid,
711 : const char *snapin_guid)
712 : {
713 0 : char *flags_str = NULL;
714 :
715 0 : DEBUG(lvl,("%s\n", name));
716 0 : DEBUGADD(lvl,("\tgpo: %s (%s)\n", gpo->name,
717 : gpo->display_name));
718 0 : DEBUGADD(lvl,("\tcse extension: %s (%s)\n", extension_guid,
719 : cse_gpo_guid_string_to_name(extension_guid)));
720 0 : DEBUGADD(lvl,("\tgplink: %s\n", gpo->link));
721 0 : DEBUGADD(lvl,("\tsnapin: %s (%s)\n", snapin_guid,
722 : cse_snapin_gpo_guid_string_to_name(snapin_guid)));
723 :
724 0 : flags_str = gpo_flag_str(NULL, flags);
725 0 : DEBUGADD(lvl,("\tflags: 0x%08x %s\n", flags, flags_str));
726 0 : TALLOC_FREE(flags_str);
727 0 : }
728 :
729 : /****************************************************************
730 : ****************************************************************/
731 :
732 0 : static NTSTATUS gpext_check_gpo_for_gpext_presence(TALLOC_CTX *mem_ctx,
733 : uint32_t flags,
734 : const struct GROUP_POLICY_OBJECT *gpo,
735 : const struct GUID *guid,
736 : bool *gpext_guid_present)
737 : {
738 0 : struct GP_EXT *gp_ext = NULL;
739 0 : int i;
740 0 : bool ok;
741 :
742 0 : *gpext_guid_present = false;
743 :
744 :
745 0 : if (gpo->link_type == GP_LINK_LOCAL) {
746 0 : return NT_STATUS_OK;
747 : }
748 :
749 0 : ok = gpo_get_gp_ext_from_gpo(mem_ctx, flags, gpo, &gp_ext);
750 0 : if (!ok) {
751 0 : return NT_STATUS_INVALID_PARAMETER;
752 : }
753 :
754 0 : if (gp_ext == NULL) {
755 0 : return NT_STATUS_OK;
756 : }
757 :
758 0 : for (i = 0; i < gp_ext->num_exts; i++) {
759 0 : struct GUID guid2;
760 0 : NTSTATUS status;
761 :
762 0 : status = GUID_from_string(gp_ext->extensions_guid[i], &guid2);
763 0 : if (!NT_STATUS_IS_OK(status)) {
764 0 : return status;
765 : }
766 0 : if (GUID_equal(guid, &guid2)) {
767 0 : *gpext_guid_present = true;
768 0 : return NT_STATUS_OK;
769 : }
770 : }
771 :
772 0 : return NT_STATUS_OK;
773 : }
774 :
775 : /****************************************************************
776 : ****************************************************************/
777 :
778 0 : NTSTATUS gpext_process_extension(TALLOC_CTX *mem_ctx,
779 : uint32_t flags,
780 : const struct security_token *token,
781 : struct registry_key *root_key,
782 : const struct GROUP_POLICY_OBJECT *deleted_gpo_list,
783 : const struct GROUP_POLICY_OBJECT *changed_gpo_list,
784 : const char *extension_guid_filter)
785 : {
786 0 : NTSTATUS status;
787 0 : struct gp_extension *ext = NULL;
788 0 : const struct GROUP_POLICY_OBJECT *gpo;
789 0 : struct GUID extension_guid_filter_guid;
790 :
791 0 : status = gpext_init_gp_extensions(mem_ctx);
792 0 : if (!NT_STATUS_IS_OK(status)) {
793 0 : DEBUG(1,("gpext_init_gp_extensions failed: %s\n",
794 : nt_errstr(status)));
795 0 : return status;
796 : }
797 :
798 0 : if (extension_guid_filter) {
799 0 : status = GUID_from_string(extension_guid_filter,
800 : &extension_guid_filter_guid);
801 0 : if (!NT_STATUS_IS_OK(status)) {
802 0 : return status;
803 : }
804 : }
805 :
806 0 : for (ext = extensions; ext; ext = ext->next) {
807 :
808 0 : struct GROUP_POLICY_OBJECT *deleted_gpo_list_filtered = NULL;
809 0 : struct GROUP_POLICY_OBJECT *changed_gpo_list_filtered = NULL;
810 :
811 0 : if (extension_guid_filter) {
812 0 : if (!GUID_equal(&extension_guid_filter_guid, ext->guid)) {
813 0 : continue;
814 : }
815 : }
816 :
817 0 : for (gpo = deleted_gpo_list; gpo; gpo = gpo->next) {
818 :
819 0 : bool is_present = false;
820 :
821 0 : status = gpext_check_gpo_for_gpext_presence(mem_ctx,
822 : flags,
823 : gpo,
824 0 : ext->guid,
825 : &is_present);
826 0 : if (!NT_STATUS_IS_OK(status)) {
827 0 : return status;
828 : }
829 :
830 0 : if (is_present) {
831 0 : struct GROUP_POLICY_OBJECT *new_gpo;
832 :
833 0 : status = gpo_copy(mem_ctx, gpo, &new_gpo);
834 0 : if (!NT_STATUS_IS_OK(status)) {
835 0 : return status;
836 : }
837 :
838 0 : DLIST_ADD(deleted_gpo_list_filtered, new_gpo);
839 : }
840 : }
841 :
842 0 : for (gpo = changed_gpo_list; gpo; gpo = gpo->next) {
843 :
844 0 : bool is_present = false;
845 :
846 0 : status = gpext_check_gpo_for_gpext_presence(mem_ctx,
847 : flags,
848 : gpo,
849 0 : ext->guid,
850 : &is_present);
851 0 : if (!NT_STATUS_IS_OK(status)) {
852 0 : return status;
853 : }
854 :
855 0 : if (is_present) {
856 0 : struct GROUP_POLICY_OBJECT *new_gpo;
857 :
858 0 : status = gpo_copy(mem_ctx, gpo, &new_gpo);
859 0 : if (!NT_STATUS_IS_OK(status)) {
860 0 : return status;
861 : }
862 :
863 0 : DLIST_ADD(changed_gpo_list_filtered, new_gpo);
864 : }
865 : }
866 :
867 0 : status = ext->methods->initialize(mem_ctx);
868 0 : NT_STATUS_NOT_OK_RETURN(status);
869 :
870 0 : status = ext->methods->process_group_policy(mem_ctx,
871 : flags,
872 : root_key,
873 : token,
874 : deleted_gpo_list_filtered,
875 : changed_gpo_list_filtered);
876 0 : if (!NT_STATUS_IS_OK(status)) {
877 0 : ext->methods->shutdown();
878 : }
879 : }
880 :
881 0 : return status;
882 : }
|