2 * Unix SMB/CIFS implementation.
3 * Group Policy Object Support
4 * Copyright (C) Guenther Deschner 2005
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 2 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, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /****************************************************************
26 parse the raw extension string into a GP_EXT structure
27 ****************************************************************/
29 ADS_STATUS
ads_parse_gp_ext(TALLOC_CTX
*mem_ctx
,
30 const char *extension_raw
,
31 struct GP_EXT
*gp_ext
)
34 char **ext_strings
= NULL
;
37 DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw
));
39 ext_list
= str_list_make_talloc(mem_ctx
, extension_raw
, "]");
40 if (ext_list
== NULL
) {
44 for (i
= 0; ext_list
[i
] != NULL
; i
++) {
50 if (gp_ext
->num_exts
) {
51 gp_ext
->extensions
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, gp_ext
->num_exts
);
52 gp_ext
->extensions_guid
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, gp_ext
->num_exts
);
53 gp_ext
->snapins
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, gp_ext
->num_exts
);
54 gp_ext
->snapins_guid
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, gp_ext
->num_exts
);
56 gp_ext
->extensions
= NULL
;
57 gp_ext
->extensions_guid
= NULL
;
58 gp_ext
->snapins
= NULL
;
59 gp_ext
->snapins_guid
= NULL
;
62 if (gp_ext
->extensions
== NULL
|| gp_ext
->extensions_guid
== NULL
||
63 gp_ext
->snapins
== NULL
|| gp_ext
->snapins_guid
== NULL
||
64 gp_ext
->gp_extension
== NULL
) {
68 gp_ext
->gp_extension
= talloc_strdup(mem_ctx
, extension_raw
);
70 for (i
= 0; ext_list
[i
] != NULL
; i
++) {
75 DEBUGADD(10,("extension #%d\n", i
));
83 ext_strings
= str_list_make_talloc(mem_ctx
, p
, "}");
84 if (ext_strings
== NULL
) {
88 for (k
= 0; ext_strings
[k
] != NULL
; k
++) {
98 gp_ext
->extensions
[i
] = talloc_strdup(mem_ctx
, cse_gpo_guid_string_to_name(q
));
99 gp_ext
->extensions_guid
[i
] = talloc_strdup(mem_ctx
, q
);
101 /* we might have no name for the guid */
102 if (gp_ext
->extensions_guid
[i
] == NULL
) {
106 for (k
= 1; ext_strings
[k
] != NULL
; k
++) {
108 char *m
= ext_strings
[k
];
114 /* FIXME: theoretically there could be more than one snapin per extension */
115 gp_ext
->snapins
[i
] = talloc_strdup(mem_ctx
, cse_snapin_gpo_guid_string_to_name(m
));
116 gp_ext
->snapins_guid
[i
] = talloc_strdup(mem_ctx
, m
);
118 /* we might have no name for the guid */
119 if (gp_ext
->snapins_guid
[i
] == NULL
) {
126 str_list_free_talloc(mem_ctx
, &ext_list
);
129 str_list_free_talloc(mem_ctx
, &ext_strings
);
132 return ADS_ERROR(LDAP_SUCCESS
);
136 str_list_free_talloc(mem_ctx
, &ext_list
);
139 str_list_free_talloc(mem_ctx
, &ext_strings
);
142 return ADS_ERROR(LDAP_NO_MEMORY
);
145 /****************************************************************
146 parse the raw link string into a GP_LINK structure
147 ****************************************************************/
149 ADS_STATUS
ads_parse_gplink(TALLOC_CTX
*mem_ctx
,
150 const char *gp_link_raw
,
152 struct GP_LINK
*gp_link
)
157 DEBUG(10,("ads_parse_gplink: gPLink: %s\n", gp_link_raw
));
159 link_list
= str_list_make_talloc(mem_ctx
, gp_link_raw
, "]");
160 if (link_list
== NULL
) {
164 for (i
= 0; link_list
[i
] != NULL
; i
++) {
168 gp_link
->gp_opts
= options
;
169 gp_link
->num_links
= i
;
171 if (gp_link
->num_links
) {
172 gp_link
->link_names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, gp_link
->num_links
);
173 gp_link
->link_opts
= TALLOC_ZERO_ARRAY(mem_ctx
, uint32
, gp_link
->num_links
);
175 gp_link
->link_names
= NULL
;
176 gp_link
->link_opts
= NULL
;
179 gp_link
->gp_link
= talloc_strdup(mem_ctx
, gp_link_raw
);
181 if (gp_link
->link_names
== NULL
|| gp_link
->link_opts
== NULL
|| gp_link
->gp_link
== NULL
) {
185 for (i
= 0; link_list
[i
] != NULL
; i
++) {
189 DEBUGADD(10,("ads_parse_gplink: processing link #%d\n", i
));
202 gp_link
->link_names
[i
] = talloc_strdup(mem_ctx
, q
);
203 if (gp_link
->link_names
[i
] == NULL
) {
206 gp_link
->link_names
[i
][PTR_DIFF(p
, q
)] = 0;
208 gp_link
->link_opts
[i
] = atoi(p
+ 1);
210 DEBUGADD(10,("ads_parse_gplink: link: %s\n", gp_link
->link_names
[i
]));
211 DEBUGADD(10,("ads_parse_gplink: opt: %d\n", gp_link
->link_opts
[i
]));
216 str_list_free_talloc(mem_ctx
, &link_list
);
219 return ADS_ERROR(LDAP_SUCCESS
);
223 str_list_free_talloc(mem_ctx
, &link_list
);
226 return ADS_ERROR(LDAP_NO_MEMORY
);
229 /****************************************************************
230 helper call to get a GP_LINK structure from a linkdn
231 ****************************************************************/
233 ADS_STATUS
ads_get_gpo_link(ADS_STRUCT
*ads
,
236 struct GP_LINK
*gp_link_struct
)
239 const char *attrs
[] = {"gPLink", "gPOptions", NULL
};
240 LDAPMessage
*res
= NULL
;
244 ZERO_STRUCTP(gp_link_struct
);
246 status
= ads_search_dn(ads
, &res
, link_dn
, attrs
);
247 if (!ADS_ERR_OK(status
)) {
248 DEBUG(10,("ads_get_gpo_link: search failed with %s\n", ads_errstr(status
)));
252 if (ads_count_replies(ads
, res
) != 1) {
253 DEBUG(10,("ads_get_gpo_link: no result\n"));
254 ads_msgfree(ads
, res
);
255 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
258 gp_link
= ads_pull_string(ads
, mem_ctx
, res
, "gPLink");
259 if (gp_link
== NULL
) {
260 DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
261 ads_msgfree(ads
, res
);
262 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE
);
265 /* perfectly leggal to have no options */
266 if (!ads_pull_uint32(ads
, res
, "gPOptions", &gp_options
)) {
267 DEBUG(10,("ads_get_gpo_link: no 'gPOptions' attribute found\n"));
271 ads_msgfree(ads
, res
);
273 return ads_parse_gplink(mem_ctx
, gp_link
, gp_options
, gp_link_struct
);
276 /****************************************************************
277 helper call to add a gp link
278 ****************************************************************/
280 ADS_STATUS
ads_add_gpo_link(ADS_STRUCT
*ads
,
287 const char *attrs
[] = {"gPLink", NULL
};
288 LDAPMessage
*res
= NULL
;
289 const char *gp_link
, *gp_link_new
;
292 /* although ADS allows to set anything here, we better check here if
293 * the gpo_dn is sane */
295 if (!strnequal(gpo_dn
, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
296 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
299 status
= ads_search_dn(ads
, &res
, link_dn
, attrs
);
300 if (!ADS_ERR_OK(status
)) {
301 DEBUG(10,("ads_add_gpo_link: search failed with %s\n", ads_errstr(status
)));
305 if (ads_count_replies(ads
, res
) != 1) {
306 DEBUG(10,("ads_add_gpo_link: no result\n"));
307 ads_msgfree(ads
, res
);
308 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
311 gp_link
= ads_pull_string(ads
, mem_ctx
, res
, "gPLink");
312 if (gp_link
== NULL
) {
313 gp_link_new
= talloc_asprintf(mem_ctx
, "[%s;%d]", gpo_dn
, gpo_opt
);
315 gp_link_new
= talloc_asprintf(mem_ctx
, "%s[%s;%d]", gp_link
, gpo_dn
, gpo_opt
);
318 ads_msgfree(ads
, res
);
319 ADS_ERROR_HAVE_NO_MEMORY(gp_link_new
);
321 mods
= ads_init_mods(mem_ctx
);
322 ADS_ERROR_HAVE_NO_MEMORY(mods
);
324 status
= ads_mod_str(mem_ctx
, &mods
, "gPLink", gp_link_new
);
325 if (!ADS_ERR_OK(status
)) {
329 return ads_gen_mod(ads
, link_dn
, mods
);
332 /****************************************************************
333 helper call to delete add a gp link
334 ****************************************************************/
336 /* untested & broken */
337 ADS_STATUS
ads_delete_gpo_link(ADS_STRUCT
*ads
,
343 const char *attrs
[] = {"gPLink", NULL
};
344 LDAPMessage
*res
= NULL
;
345 const char *gp_link
, *gp_link_new
= NULL
;
348 /* check for a sane gpo_dn */
349 if (gpo_dn
[0] != '[') {
350 DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
351 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
354 if (gpo_dn
[strlen(gpo_dn
)] != ']') {
355 DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
356 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
359 status
= ads_search_dn(ads
, &res
, link_dn
, attrs
);
360 if (!ADS_ERR_OK(status
)) {
361 DEBUG(10,("ads_delete_gpo_link: search failed with %s\n", ads_errstr(status
)));
365 if (ads_count_replies(ads
, res
) != 1) {
366 DEBUG(10,("ads_delete_gpo_link: no result\n"));
367 ads_msgfree(ads
, res
);
368 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
371 gp_link
= ads_pull_string(ads
, mem_ctx
, res
, "gPLink");
372 if (gp_link
== NULL
) {
373 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE
);
376 /* find link to delete */
377 /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt); */
379 ads_msgfree(ads
, res
);
380 ADS_ERROR_HAVE_NO_MEMORY(gp_link_new
);
382 mods
= ads_init_mods(mem_ctx
);
383 ADS_ERROR_HAVE_NO_MEMORY(mods
);
385 status
= ads_mod_str(mem_ctx
, &mods
, "gPLink", gp_link_new
);
386 if (!ADS_ERR_OK(status
)) {
390 return ads_gen_mod(ads
, link_dn
, mods
);
393 /****************************************************************
394 parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
395 ****************************************************************/
397 ADS_STATUS
ads_parse_gpo(ADS_STRUCT
*ads
,
401 struct GROUP_POLICY_OBJECT
*gpo
)
405 ADS_ERROR_HAVE_NO_MEMORY(res
);
408 gpo
->ds_path
= talloc_strdup(mem_ctx
, gpo_dn
);
410 gpo
->ds_path
= ads_get_dn(ads
, res
);
413 ADS_ERROR_HAVE_NO_MEMORY(gpo
->ds_path
);
415 if (!ads_pull_uint32(ads
, res
, "versionNumber", &gpo
->version
)) {
416 return ADS_ERROR(LDAP_NO_MEMORY
);
420 if (!ads_pull_uint32(ads
, res
, "flags", &gpo
->options
)) {
421 return ADS_ERROR(LDAP_NO_MEMORY
);
424 gpo
->file_sys_path
= ads_pull_string(ads
, mem_ctx
, res
, "gPCFileSysPath");
425 ADS_ERROR_HAVE_NO_MEMORY(gpo
->file_sys_path
);
427 gpo
->display_name
= ads_pull_string(ads
, mem_ctx
, res
, "displayName");
428 ADS_ERROR_HAVE_NO_MEMORY(gpo
->display_name
);
430 gpo
->name
= ads_pull_string(ads
, mem_ctx
, res
, "name");
431 ADS_ERROR_HAVE_NO_MEMORY(gpo
->name
);
433 /* ???, this is optional to have and what does it depend on, the 'flags' ?) */
434 gpo
->machine_extensions
= ads_pull_string(ads
, mem_ctx
, res
, "gPCMachineExtensionNames");
435 gpo
->user_extensions
= ads_pull_string(ads
, mem_ctx
, res
, "gPCUserExtensionNames");
437 ads_pull_sd(ads
, mem_ctx
, res
, "ntSecurityDescriptor", &gpo
->security_descriptor
);
438 ADS_ERROR_HAVE_NO_MEMORY(gpo
->security_descriptor
);
440 return ADS_ERROR(LDAP_SUCCESS
);
443 /****************************************************************
444 get a GROUP_POLICY_OBJECT structure based on different input paramters
445 ****************************************************************/
447 ADS_STATUS
ads_get_gpo(ADS_STRUCT
*ads
,
450 const char *display_name
,
451 const char *guid_name
,
452 struct GROUP_POLICY_OBJECT
*gpo
)
455 LDAPMessage
*res
= NULL
;
458 const char *attrs
[] = { "cn", "displayName", "flags", "gPCFileSysPath",
459 "gPCFunctionalityVersion", "gPCMachineExtensionNames",
460 "gPCUserExtensionNames", "gPCWQLFilter", "name",
461 "versionNumber", "ntSecurityDescriptor", NULL
};
462 uint32 sd_flags
= DACL_SECURITY_INFORMATION
;
466 if (!gpo_dn
&& !display_name
&& !guid_name
) {
467 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
472 if (strnequal(gpo_dn
, "LDAP://", strlen("LDAP://")) != 0) {
473 gpo_dn
= gpo_dn
+ strlen("LDAP://");
476 status
= ads_search_retry_dn_sd_flags(ads
, &res
,
480 } else if (display_name
|| guid_name
) {
482 filter
= talloc_asprintf(mem_ctx
,
483 "(&(objectclass=groupPolicyContainer)(%s=%s))",
484 display_name
? "displayName" : "name",
485 display_name
? display_name
: guid_name
);
486 ADS_ERROR_HAVE_NO_MEMORY(filter
);
488 status
= ads_do_search_all_sd_flags(ads
, ads
->config
.bind_path
,
489 LDAP_SCOPE_SUBTREE
, filter
,
490 attrs
, sd_flags
, &res
);
493 if (!ADS_ERR_OK(status
)) {
494 DEBUG(10,("ads_get_gpo: search failed with %s\n", ads_errstr(status
)));
498 if (ads_count_replies(ads
, res
) != 1) {
499 DEBUG(10,("ads_get_gpo: no result\n"));
500 ads_msgfree(ads
, res
);
501 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
504 dn
= ads_get_dn(ads
, res
);
506 ads_msgfree(ads
, res
);
507 return ADS_ERROR(LDAP_NO_MEMORY
);
510 status
= ads_parse_gpo(ads
, mem_ctx
, res
, dn
, gpo
);
511 ads_msgfree(ads
, res
);
512 ads_memfree(ads
, dn
);
517 /****************************************************************
518 add a gplink to the GROUP_POLICY_OBJECT linked list
519 ****************************************************************/
521 ADS_STATUS
add_gplink_to_gpo_list(ADS_STRUCT
*ads
,
523 struct GROUP_POLICY_OBJECT
**gpo_list
,
525 struct GP_LINK
*gp_link
,
526 enum GPO_LINK_TYPE link_type
,
527 BOOL only_add_forced_gpos
,
528 struct GPO_SID_TOKEN
*token
)
533 for (i
= 0; i
< gp_link
->num_links
; i
++) {
535 struct GROUP_POLICY_OBJECT
*new_gpo
= NULL
;
537 if (gp_link
->link_opts
[i
] & GPO_LINK_OPT_DISABLED
) {
538 DEBUG(10,("skipping disabled GPO\n"));
542 if (only_add_forced_gpos
) {
544 if (! (gp_link
->link_opts
[i
] & GPO_LINK_OPT_ENFORCED
)) {
545 DEBUG(10,("skipping nonenforced GPO link because GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
548 DEBUG(10,("adding enforced GPO link although the GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
552 new_gpo
= TALLOC_P(mem_ctx
, struct GROUP_POLICY_OBJECT
);
553 ADS_ERROR_HAVE_NO_MEMORY(new_gpo
);
555 ZERO_STRUCTP(new_gpo
);
557 status
= ads_get_gpo(ads
, mem_ctx
, gp_link
->link_names
[i
], NULL
, NULL
, new_gpo
);
558 if (!ADS_ERR_OK(status
)) {
562 new_gpo
->link
= link_dn
;
563 new_gpo
->link_type
= link_type
;
565 DLIST_ADD(*gpo_list
, new_gpo
);
567 DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s to GPO list\n",
568 i
, gp_link
->link_names
[i
]));
571 return ADS_ERROR(LDAP_SUCCESS
);
574 /****************************************************************
575 ****************************************************************/
577 ADS_STATUS
ads_get_gpo_sid_token(ADS_STRUCT
*ads
,
580 struct GPO_SID_TOKEN
**token
)
584 DOM_SID primary_group_sid
;
585 DOM_SID
*ad_token_sids
;
586 size_t num_ad_token_sids
= 0;
588 size_t num_token_sids
= 0;
589 struct GPO_SID_TOKEN
*new_token
= NULL
;
592 new_token
= TALLOC_ZERO_P(mem_ctx
, struct GPO_SID_TOKEN
);
593 ADS_ERROR_HAVE_NO_MEMORY(new_token
);
595 status
= ads_get_tokensids(ads
, mem_ctx
, dn
,
596 &object_sid
, &primary_group_sid
,
597 &ad_token_sids
, &num_ad_token_sids
);
598 if (!ADS_ERR_OK(status
)) {
602 new_token
->object_sid
= object_sid
;
603 new_token
->primary_group_sid
= primary_group_sid
;
605 token_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, 1);
606 ADS_ERROR_HAVE_NO_MEMORY(token_sids
);
608 for (i
= 0; i
< num_ad_token_sids
; i
++) {
610 if (sid_check_is_in_builtin(&ad_token_sids
[i
])) {
614 if (!add_sid_to_array_unique(mem_ctx
, &ad_token_sids
[i
],
615 &token_sids
, &num_token_sids
)) {
616 return ADS_ERROR(LDAP_NO_MEMORY
);
620 /* Add S-1-5-11 to token */
621 if (!add_sid_to_array_unique(mem_ctx
, &global_sid_Authenticated_Users
,
622 &token_sids
, &num_token_sids
)) {
623 return ADS_ERROR(LDAP_NO_MEMORY
);
627 new_token
->token_sids
= token_sids
;
628 new_token
->num_token_sids
= num_token_sids
;
632 return ADS_ERROR_LDAP(LDAP_SUCCESS
);
636 /****************************************************************
637 get the full list of GROUP_POLICY_OBJECTs for a given dn
638 ****************************************************************/
640 ADS_STATUS
ads_get_gpo_list(ADS_STRUCT
*ads
,
644 struct GROUP_POLICY_OBJECT
**gpo_list
)
646 /* (L)ocal (S)ite (D)omain (O)rganizational(U)nit */
649 struct GP_LINK gp_link
;
650 struct GPO_SID_TOKEN
*token
= NULL
;
651 const char *parent_dn
, *site_dn
, *tmp_dn
;
652 BOOL add_only_forced_gpos
= False
;
654 ZERO_STRUCTP(gpo_list
);
656 DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn
));
658 status
= ads_get_gpo_sid_token(ads
, mem_ctx
, dn
, &token
);
659 if (!ADS_ERR_OK(status
)) {
668 /* are site GPOs valid for users as well ??? */
669 if (flags
& GPO_LIST_FLAG_MACHINE
) {
671 status
= ads_site_dn_for_machine(ads
, mem_ctx
, ads
->config
.ldap_server_name
, &site_dn
);
672 if (!ADS_ERR_OK(status
)) {
676 DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n", site_dn
));
678 status
= ads_get_gpo_link(ads
, mem_ctx
, site_dn
, &gp_link
);
679 if (ADS_ERR_OK(status
)) {
681 if (DEBUGLEVEL
>= 100) {
682 dump_gplink(ads
, mem_ctx
, &gp_link
);
685 status
= add_gplink_to_gpo_list(ads
, mem_ctx
, gpo_list
,
686 site_dn
, &gp_link
, GP_LINK_SITE
,
687 add_only_forced_gpos
,
689 if (!ADS_ERR_OK(status
)) {
693 if (flags
& GPO_LIST_FLAG_SITEONLY
) {
694 return ADS_ERROR(LDAP_SUCCESS
);
697 /* inheritance can't be blocked at the site level */
703 while ( (parent_dn
= ads_parent_dn(tmp_dn
)) &&
704 (!strequal(parent_dn
, ads_parent_dn(ads
->config
.bind_path
))) ) {
708 /* An account can just be a member of one domain */
709 if (strncmp(parent_dn
, "DC=", strlen("DC=")) == 0) {
711 DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n", parent_dn
));
713 status
= ads_get_gpo_link(ads
, mem_ctx
, parent_dn
, &gp_link
);
714 if (ADS_ERR_OK(status
)) {
716 if (DEBUGLEVEL
>= 100) {
717 dump_gplink(ads
, mem_ctx
, &gp_link
);
720 /* block inheritance from now on */
721 if (gp_link
.gp_opts
& GPOPTIONS_BLOCK_INHERITANCE
) {
722 add_only_forced_gpos
= True
;
725 status
= add_gplink_to_gpo_list(ads
, mem_ctx
,
727 &gp_link
, GP_LINK_DOMAIN
,
728 add_only_forced_gpos
,
730 if (!ADS_ERR_OK(status
)) {
742 while ( (parent_dn
= ads_parent_dn(tmp_dn
)) &&
743 (!strequal(parent_dn
, ads_parent_dn(ads
->config
.bind_path
))) ) {
746 /* (O)rganizational(U)nit */
748 /* An account can be a member of more OUs */
749 if (strncmp(parent_dn
, "OU=", strlen("OU=")) == 0) {
751 DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n", parent_dn
));
753 status
= ads_get_gpo_link(ads
, mem_ctx
, parent_dn
, &gp_link
);
754 if (ADS_ERR_OK(status
)) {
756 if (DEBUGLEVEL
>= 100) {
757 dump_gplink(ads
, mem_ctx
, &gp_link
);
760 /* block inheritance from now on */
761 if (gp_link
.gp_opts
& GPOPTIONS_BLOCK_INHERITANCE
) {
762 add_only_forced_gpos
= True
;
765 status
= add_gplink_to_gpo_list(ads
, mem_ctx
,
767 &gp_link
, GP_LINK_OU
,
768 add_only_forced_gpos
,
770 if (!ADS_ERR_OK(status
)) {
780 return ADS_ERROR(LDAP_SUCCESS
);
783 #endif /* HAVE_LDAP */