heimdal_build: Support using system hdb and kdc libraries.
[Samba.git] / libgpo / gpo_ldap.c
blobe6b9609bab20c56b0cb7755f7394bcdbf0873dd5
1 /*
2 * Unix SMB/CIFS implementation.
3 * Group Policy Object Support
4 * Copyright (C) Guenther Deschner 2005,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/>.
20 #include "includes.h"
21 #include "libgpo/gpo.h"
22 #if _SAMBA_BUILD_ == 4
23 #include "libgpo/gpo_s4.h"
24 #include "source4/libgpo/ads_convenience.h"
25 #endif
26 #include "../libcli/security/security.h"
28 /****************************************************************
29 parse the raw extension string into a GP_EXT structure
30 ****************************************************************/
32 bool ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
33 const char *extension_raw,
34 struct GP_EXT **gp_ext)
36 bool ret = false;
37 struct GP_EXT *ext = NULL;
38 char **ext_list = NULL;
39 char **ext_strings = NULL;
40 int i;
42 if (!extension_raw) {
43 goto parse_error;
46 DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
48 ext = talloc_zero(mem_ctx, struct GP_EXT);
49 if (!ext) {
50 goto parse_error;
53 ext_list = str_list_make(mem_ctx, extension_raw, "]");
54 if (!ext_list) {
55 goto parse_error;
58 for (i = 0; ext_list[i] != NULL; i++) {
59 /* no op */
62 ext->num_exts = i;
64 if (ext->num_exts) {
65 ext->extensions = talloc_zero_array(mem_ctx, char *,
66 ext->num_exts);
67 ext->extensions_guid = talloc_zero_array(mem_ctx, char *,
68 ext->num_exts);
69 ext->snapins = talloc_zero_array(mem_ctx, char *,
70 ext->num_exts);
71 ext->snapins_guid = talloc_zero_array(mem_ctx, char *,
72 ext->num_exts);
75 ext->gp_extension = talloc_strdup(mem_ctx, extension_raw);
77 if (!ext->extensions || !ext->extensions_guid ||
78 !ext->snapins || !ext->snapins_guid ||
79 !ext->gp_extension) {
80 goto parse_error;
83 for (i = 0; ext_list[i] != NULL; i++) {
85 int k;
86 char *p, *q;
88 DEBUGADD(10,("extension #%d\n", i));
90 p = ext_list[i];
92 if (p[0] == '[') {
93 p++;
96 ext_strings = str_list_make(mem_ctx, p, "}");
97 if (ext_strings == NULL) {
98 goto parse_error;
101 for (k = 0; ext_strings[k] != NULL; k++) {
102 /* no op */
105 q = ext_strings[0];
107 if (q[0] == '{') {
108 q++;
111 ext->extensions[i] = talloc_strdup(mem_ctx,
112 cse_gpo_guid_string_to_name(q));
113 ext->extensions_guid[i] = talloc_strdup(mem_ctx, q);
115 /* we might have no name for the guid */
116 if (ext->extensions_guid[i] == NULL) {
117 goto parse_error;
120 for (k = 1; ext_strings[k] != NULL; k++) {
122 char *m = ext_strings[k];
124 if (m[0] == '{') {
125 m++;
128 /* FIXME: theoretically there could be more than one
129 * snapin per extension */
130 ext->snapins[i] = talloc_strdup(mem_ctx,
131 cse_snapin_gpo_guid_string_to_name(m));
132 ext->snapins_guid[i] = talloc_strdup(mem_ctx, m);
134 /* we might have no name for the guid */
135 if (ext->snapins_guid[i] == NULL) {
136 goto parse_error;
141 *gp_ext = ext;
143 ret = true;
145 parse_error:
146 talloc_free(ext_list);
147 talloc_free(ext_strings);
149 return ret;
152 #ifdef HAVE_LDAP
154 /****************************************************************
155 parse the raw link string into a GP_LINK structure
156 ****************************************************************/
158 static ADS_STATUS gpo_parse_gplink(TALLOC_CTX *mem_ctx,
159 const char *gp_link_raw,
160 uint32_t options,
161 struct GP_LINK *gp_link)
163 ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
164 char **link_list;
165 int i;
167 ZERO_STRUCTP(gp_link);
169 DEBUG(10,("gpo_parse_gplink: gPLink: %s\n", gp_link_raw));
171 link_list = str_list_make_v3(mem_ctx, gp_link_raw, "]");
172 if (!link_list) {
173 goto parse_error;
176 for (i = 0; link_list[i] != NULL; i++) {
177 /* no op */
180 gp_link->gp_opts = options;
181 gp_link->num_links = i;
183 if (gp_link->num_links) {
184 gp_link->link_names = talloc_zero_array(mem_ctx, char *,
185 gp_link->num_links);
186 gp_link->link_opts = talloc_zero_array(mem_ctx, uint32_t,
187 gp_link->num_links);
190 gp_link->gp_link = talloc_strdup(mem_ctx, gp_link_raw);
192 if (!gp_link->link_names || !gp_link->link_opts || !gp_link->gp_link) {
193 goto parse_error;
196 for (i = 0; link_list[i] != NULL; i++) {
198 char *p, *q;
200 DEBUGADD(10,("gpo_parse_gplink: processing link #%d\n", i));
202 q = link_list[i];
203 if (q[0] == '[') {
204 q++;
207 p = strchr(q, ';');
209 if (p == NULL) {
210 goto parse_error;
213 gp_link->link_names[i] = talloc_strdup(mem_ctx, q);
214 if (gp_link->link_names[i] == NULL) {
215 goto parse_error;
217 gp_link->link_names[i][PTR_DIFF(p, q)] = 0;
219 gp_link->link_opts[i] = atoi(p + 1);
221 DEBUGADD(10,("gpo_parse_gplink: link: %s\n",
222 gp_link->link_names[i]));
223 DEBUGADD(10,("gpo_parse_gplink: opt: %d\n",
224 gp_link->link_opts[i]));
228 status = ADS_SUCCESS;
230 parse_error:
231 talloc_free(link_list);
233 return status;
236 /****************************************************************
237 helper call to get a GP_LINK structure from a linkdn
238 ****************************************************************/
240 ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
241 TALLOC_CTX *mem_ctx,
242 const char *link_dn,
243 struct GP_LINK *gp_link_struct)
245 ADS_STATUS status;
246 const char *attrs[] = {"gPLink", "gPOptions", NULL};
247 LDAPMessage *res = NULL;
248 const char *gp_link;
249 uint32_t gp_options;
251 ZERO_STRUCTP(gp_link_struct);
253 status = ads_search_dn(ads, &res, link_dn, attrs);
254 if (!ADS_ERR_OK(status)) {
255 DEBUG(10,("ads_get_gpo_link: search failed with %s\n",
256 ads_errstr(status)));
257 return status;
260 if (ads_count_replies(ads, res) != 1) {
261 DEBUG(10,("ads_get_gpo_link: no result\n"));
262 ads_msgfree(ads, res);
263 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
266 gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
267 if (gp_link == NULL) {
268 DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
269 ads_msgfree(ads, res);
270 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
273 /* perfectly legal to have no options */
274 if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
275 DEBUG(10,("ads_get_gpo_link: "
276 "no 'gPOptions' attribute found\n"));
277 gp_options = 0;
280 ads_msgfree(ads, res);
282 return gpo_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
285 /****************************************************************
286 helper call to add a gp link
287 ****************************************************************/
289 ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
290 TALLOC_CTX *mem_ctx,
291 const char *link_dn,
292 const char *gpo_dn,
293 uint32_t gpo_opt)
295 ADS_STATUS status;
296 const char *attrs[] = {"gPLink", NULL};
297 LDAPMessage *res = NULL;
298 const char *gp_link, *gp_link_new;
299 ADS_MODLIST mods;
301 /* although ADS allows to set anything here, we better check here if
302 * the gpo_dn is sane */
304 if (!strnequal(gpo_dn, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
305 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
308 status = ads_search_dn(ads, &res, link_dn, attrs);
309 if (!ADS_ERR_OK(status)) {
310 DEBUG(10,("ads_add_gpo_link: search failed with %s\n",
311 ads_errstr(status)));
312 return status;
315 if (ads_count_replies(ads, res) != 1) {
316 DEBUG(10,("ads_add_gpo_link: no result\n"));
317 ads_msgfree(ads, res);
318 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
321 gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
322 if (gp_link == NULL) {
323 gp_link_new = talloc_asprintf(mem_ctx, "[%s;%d]",
324 gpo_dn, gpo_opt);
325 } else {
326 gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]",
327 gp_link, gpo_dn, gpo_opt);
330 ads_msgfree(ads, res);
331 ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
333 mods = ads_init_mods(mem_ctx);
334 ADS_ERROR_HAVE_NO_MEMORY(mods);
336 status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
337 if (!ADS_ERR_OK(status)) {
338 return status;
341 return ads_gen_mod(ads, link_dn, mods);
344 /****************************************************************
345 helper call to delete add a gp link
346 ****************************************************************/
348 /* untested & broken */
349 ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
350 TALLOC_CTX *mem_ctx,
351 const char *link_dn,
352 const char *gpo_dn)
354 ADS_STATUS status;
355 const char *attrs[] = {"gPLink", NULL};
356 LDAPMessage *res = NULL;
357 const char *gp_link, *gp_link_new = NULL;
358 ADS_MODLIST mods;
360 /* check for a sane gpo_dn */
361 if (gpo_dn[0] != '[') {
362 DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
363 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
366 if (gpo_dn[strlen(gpo_dn)] != ']') {
367 DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
368 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
371 status = ads_search_dn(ads, &res, link_dn, attrs);
372 if (!ADS_ERR_OK(status)) {
373 DEBUG(10,("ads_delete_gpo_link: search failed with %s\n",
374 ads_errstr(status)));
375 return status;
378 if (ads_count_replies(ads, res) != 1) {
379 DEBUG(10,("ads_delete_gpo_link: no result\n"));
380 ads_msgfree(ads, res);
381 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
384 gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
385 if (gp_link == NULL) {
386 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
389 /* find link to delete */
390 /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link,
391 gpo_dn, gpo_opt); */
393 ads_msgfree(ads, res);
394 ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
396 mods = ads_init_mods(mem_ctx);
397 ADS_ERROR_HAVE_NO_MEMORY(mods);
399 status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
400 if (!ADS_ERR_OK(status)) {
401 return status;
404 return ads_gen_mod(ads, link_dn, mods);
407 /****************************************************************
408 parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
409 ****************************************************************/
411 ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
412 TALLOC_CTX *mem_ctx,
413 LDAPMessage *res,
414 const char *gpo_dn,
415 struct GROUP_POLICY_OBJECT *gpo)
417 ZERO_STRUCTP(gpo);
419 ADS_ERROR_HAVE_NO_MEMORY(res);
421 if (gpo_dn) {
422 gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
423 } else {
424 gpo->ds_path = ads_get_dn(ads, mem_ctx, res);
427 ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
429 if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
430 return ADS_ERROR(LDAP_NO_MEMORY);
433 if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
434 return ADS_ERROR(LDAP_NO_MEMORY);
437 gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res,
438 "gPCFileSysPath");
439 ADS_ERROR_HAVE_NO_MEMORY(gpo->file_sys_path);
441 gpo->display_name = ads_pull_string(ads, mem_ctx, res,
442 "displayName");
443 ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
445 gpo->name = ads_pull_string(ads, mem_ctx, res,
446 "name");
447 ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
449 gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res,
450 "gPCMachineExtensionNames");
451 gpo->user_extensions = ads_pull_string(ads, mem_ctx, res,
452 "gPCUserExtensionNames");
454 ads_pull_sd(ads, mem_ctx, res, "ntSecurityDescriptor",
455 &gpo->security_descriptor);
456 ADS_ERROR_HAVE_NO_MEMORY(gpo->security_descriptor);
458 return ADS_ERROR(LDAP_SUCCESS);
461 /****************************************************************
462 get a GROUP_POLICY_OBJECT structure based on different input parameters
463 ****************************************************************/
465 ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
466 TALLOC_CTX *mem_ctx,
467 const char *gpo_dn,
468 const char *display_name,
469 const char *guid_name,
470 struct GROUP_POLICY_OBJECT *gpo)
472 ADS_STATUS status;
473 LDAPMessage *res = NULL;
474 char *dn;
475 const char *filter;
476 const char *attrs[] = {
477 "cn",
478 "displayName",
479 "flags",
480 "gPCFileSysPath",
481 "gPCFunctionalityVersion",
482 "gPCMachineExtensionNames",
483 "gPCUserExtensionNames",
484 "gPCWQLFilter",
485 "name",
486 "ntSecurityDescriptor",
487 "versionNumber",
488 NULL};
489 uint32_t sd_flags = SECINFO_DACL;
491 ZERO_STRUCTP(gpo);
493 if (!gpo_dn && !display_name && !guid_name) {
494 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
497 if (gpo_dn) {
499 if (strnequal(gpo_dn, "LDAP://", strlen("LDAP://")) != 0) {
500 gpo_dn = gpo_dn + strlen("LDAP://");
503 status = ads_search_retry_dn_sd_flags(ads, &res,
504 sd_flags,
505 gpo_dn, attrs);
507 } else if (display_name || guid_name) {
509 filter = talloc_asprintf(mem_ctx,
510 "(&(objectclass=groupPolicyContainer)(%s=%s))",
511 display_name ? "displayName" : "name",
512 display_name ? display_name : guid_name);
513 ADS_ERROR_HAVE_NO_MEMORY(filter);
515 status = ads_do_search_all_sd_flags(ads, ads->config.bind_path,
516 LDAP_SCOPE_SUBTREE, filter,
517 attrs, sd_flags, &res);
520 if (!ADS_ERR_OK(status)) {
521 DEBUG(10,("ads_get_gpo: search failed with %s\n",
522 ads_errstr(status)));
523 return status;
526 if (ads_count_replies(ads, res) != 1) {
527 DEBUG(10,("ads_get_gpo: no result\n"));
528 ads_msgfree(ads, res);
529 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
532 dn = ads_get_dn(ads, mem_ctx, res);
533 if (dn == NULL) {
534 ads_msgfree(ads, res);
535 return ADS_ERROR(LDAP_NO_MEMORY);
538 status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
539 ads_msgfree(ads, res);
540 TALLOC_FREE(dn);
542 return status;
545 /****************************************************************
546 add a gplink to the GROUP_POLICY_OBJECT linked list
547 ****************************************************************/
549 static ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
550 TALLOC_CTX *mem_ctx,
551 struct GROUP_POLICY_OBJECT **gpo_list,
552 const char *link_dn,
553 struct GP_LINK *gp_link,
554 enum GPO_LINK_TYPE link_type,
555 bool only_add_forced_gpos,
556 const struct security_token *token)
558 ADS_STATUS status;
559 int i;
561 for (i = 0; i < gp_link->num_links; i++) {
563 struct GROUP_POLICY_OBJECT *new_gpo = NULL;
565 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
566 DEBUG(10,("skipping disabled GPO\n"));
567 continue;
570 if (only_add_forced_gpos) {
572 if (!(gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED)) {
573 DEBUG(10,("skipping nonenforced GPO link "
574 "because GPOPTIONS_BLOCK_INHERITANCE "
575 "has been set\n"));
576 continue;
577 } else {
578 DEBUG(10,("adding enforced GPO link although "
579 "the GPOPTIONS_BLOCK_INHERITANCE "
580 "has been set\n"));
584 new_gpo = TALLOC_ZERO_P(mem_ctx, struct GROUP_POLICY_OBJECT);
585 ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
587 status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i],
588 NULL, NULL, new_gpo);
589 if (!ADS_ERR_OK(status)) {
590 DEBUG(10,("failed to get gpo: %s\n",
591 gp_link->link_names[i]));
592 return status;
595 status = ADS_ERROR_NT(gpo_apply_security_filtering(new_gpo,
596 token));
597 if (!ADS_ERR_OK(status)) {
598 DEBUG(10,("skipping GPO \"%s\" as object "
599 "has no access to it\n",
600 new_gpo->display_name));
601 talloc_free(new_gpo);
602 continue;
605 new_gpo->link = link_dn;
606 new_gpo->link_type = link_type;
608 DLIST_ADD(*gpo_list, new_gpo);
610 DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s "
611 "to GPO list\n", i, gp_link->link_names[i]));
614 return ADS_ERROR(LDAP_SUCCESS);
617 /****************************************************************
618 ****************************************************************/
620 ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
621 TALLOC_CTX *mem_ctx,
622 const char *dn,
623 struct security_token **token)
625 ADS_STATUS status;
626 struct dom_sid object_sid;
627 struct dom_sid primary_group_sid;
628 struct dom_sid *ad_token_sids;
629 size_t num_ad_token_sids = 0;
630 struct dom_sid *token_sids;
631 uint32_t num_token_sids = 0;
632 struct security_token *new_token = NULL;
633 int i;
635 status = ads_get_tokensids(ads, mem_ctx, dn,
636 &object_sid, &primary_group_sid,
637 &ad_token_sids, &num_ad_token_sids);
638 if (!ADS_ERR_OK(status)) {
639 return status;
642 token_sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, 1);
643 ADS_ERROR_HAVE_NO_MEMORY(token_sids);
645 status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
646 &primary_group_sid,
647 &token_sids,
648 &num_token_sids));
649 if (!ADS_ERR_OK(status)) {
650 return status;
653 for (i = 0; i < num_ad_token_sids; i++) {
655 if (sid_check_is_in_builtin(&ad_token_sids[i])) {
656 continue;
659 status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
660 &ad_token_sids[i],
661 &token_sids,
662 &num_token_sids));
663 if (!ADS_ERR_OK(status)) {
664 return status;
668 new_token = create_local_nt_token(mem_ctx, &object_sid, false,
669 num_token_sids, token_sids);
670 ADS_ERROR_HAVE_NO_MEMORY(new_token);
672 *token = new_token;
674 security_token_debug(DBGC_CLASS, 5, *token);
676 return ADS_ERROR_LDAP(LDAP_SUCCESS);
679 /****************************************************************
680 ****************************************************************/
682 static ADS_STATUS add_local_policy_to_gpo_list(TALLOC_CTX *mem_ctx,
683 struct GROUP_POLICY_OBJECT **gpo_list,
684 enum GPO_LINK_TYPE link_type)
686 struct GROUP_POLICY_OBJECT *gpo = NULL;
688 ADS_ERROR_HAVE_NO_MEMORY(gpo_list);
690 gpo = TALLOC_ZERO_P(mem_ctx, struct GROUP_POLICY_OBJECT);
691 ADS_ERROR_HAVE_NO_MEMORY(gpo);
693 gpo->name = talloc_strdup(mem_ctx, "Local Policy");
694 ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
696 gpo->display_name = talloc_strdup(mem_ctx, "Local Policy");
697 ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
699 gpo->link_type = link_type;
701 DLIST_ADD(*gpo_list, gpo);
703 return ADS_ERROR_NT(NT_STATUS_OK);
706 /****************************************************************
707 get the full list of GROUP_POLICY_OBJECTs for a given dn
708 ****************************************************************/
710 ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
711 TALLOC_CTX *mem_ctx,
712 const char *dn,
713 uint32_t flags,
714 const struct security_token *token,
715 struct GROUP_POLICY_OBJECT **gpo_list)
717 /* (L)ocal (S)ite (D)omain (O)rganizational(U)nit */
719 ADS_STATUS status;
720 struct GP_LINK gp_link;
721 const char *parent_dn, *site_dn, *tmp_dn;
722 bool add_only_forced_gpos = false;
724 ZERO_STRUCTP(gpo_list);
726 if (!dn) {
727 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
730 if (!ads_set_sasl_wrap_flags(ads, ADS_AUTH_SASL_SIGN)) {
731 return ADS_ERROR(LDAP_INVALID_CREDENTIALS);
734 DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
736 /* (L)ocal */
737 status = add_local_policy_to_gpo_list(mem_ctx, gpo_list,
738 GP_LINK_LOCAL);
739 if (!ADS_ERR_OK(status)) {
740 return status;
743 /* (S)ite */
745 /* are site GPOs valid for users as well ??? */
746 if (flags & GPO_LIST_FLAG_MACHINE) {
748 status = ads_site_dn_for_machine(ads, mem_ctx,
749 ads->config.ldap_server_name,
750 &site_dn);
751 if (!ADS_ERR_OK(status)) {
752 return status;
755 DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n",
756 site_dn));
758 status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
759 if (ADS_ERR_OK(status)) {
761 if (DEBUGLEVEL >= 100) {
762 dump_gplink(ads, mem_ctx, &gp_link);
765 status = add_gplink_to_gpo_list(ads, mem_ctx, gpo_list,
766 site_dn, &gp_link,
767 GP_LINK_SITE,
768 add_only_forced_gpos,
769 token);
770 if (!ADS_ERR_OK(status)) {
771 return status;
774 if (flags & GPO_LIST_FLAG_SITEONLY) {
775 return ADS_ERROR(LDAP_SUCCESS);
778 /* inheritance can't be blocked at the site level */
782 tmp_dn = dn;
784 while ((parent_dn = ads_parent_dn(tmp_dn)) &&
785 (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
787 /* (D)omain */
789 /* An account can just be a member of one domain */
790 if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
792 DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n",
793 parent_dn));
795 status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
796 &gp_link);
797 if (ADS_ERR_OK(status)) {
799 if (DEBUGLEVEL >= 100) {
800 dump_gplink(ads, mem_ctx, &gp_link);
803 /* block inheritance from now on */
804 if (gp_link.gp_opts &
805 GPOPTIONS_BLOCK_INHERITANCE) {
806 add_only_forced_gpos = true;
809 status = add_gplink_to_gpo_list(ads,
810 mem_ctx,
811 gpo_list,
812 parent_dn,
813 &gp_link,
814 GP_LINK_DOMAIN,
815 add_only_forced_gpos,
816 token);
817 if (!ADS_ERR_OK(status)) {
818 return status;
823 tmp_dn = parent_dn;
826 /* reset dn again */
827 tmp_dn = dn;
829 while ((parent_dn = ads_parent_dn(tmp_dn)) &&
830 (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
833 /* (O)rganizational(U)nit */
835 /* An account can be a member of more OUs */
836 if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
838 DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n",
839 parent_dn));
841 status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
842 &gp_link);
843 if (ADS_ERR_OK(status)) {
845 if (DEBUGLEVEL >= 100) {
846 dump_gplink(ads, mem_ctx, &gp_link);
849 /* block inheritance from now on */
850 if (gp_link.gp_opts &
851 GPOPTIONS_BLOCK_INHERITANCE) {
852 add_only_forced_gpos = true;
855 status = add_gplink_to_gpo_list(ads,
856 mem_ctx,
857 gpo_list,
858 parent_dn,
859 &gp_link,
860 GP_LINK_OU,
861 add_only_forced_gpos,
862 token);
863 if (!ADS_ERR_OK(status)) {
864 return status;
869 tmp_dn = parent_dn;
873 return ADS_ERROR(LDAP_SUCCESS);
876 #endif /* HAVE_LDAP */