lib: gpo: Fixes issue with GPOPTIONS_BLOCK_INHERITANCE.
[gd/samba-autobuild/.git] / libgpo / gpo_ldap.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  Group Policy Object Support
4  *  Copyright (C) Guenther Deschner 2005,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.h"
22 #include "auth.h"
23 #include "../libcli/security/security.h"
24
25 /****************************************************************
26  parse the raw extension string into a GP_EXT structure
27 ****************************************************************/
28
29 bool ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
30                       const char *extension_raw,
31                       struct GP_EXT **gp_ext)
32 {
33         bool ret = false;
34         struct GP_EXT *ext = NULL;
35         char **ext_list = NULL;
36         char **ext_strings = NULL;
37         int i;
38
39         if (!extension_raw) {
40                 goto parse_error;
41         }
42
43         DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
44
45         ext = talloc_zero(mem_ctx, struct GP_EXT);
46         if (!ext) {
47                 goto parse_error;
48         }
49
50         ext_list = str_list_make(mem_ctx, extension_raw, "]");
51         if (!ext_list) {
52                 goto parse_error;
53         }
54
55         for (i = 0; ext_list[i] != NULL; i++) {
56                 /* no op */
57         }
58
59         ext->num_exts = i;
60
61         if (ext->num_exts) {
62                 ext->extensions         = talloc_zero_array(mem_ctx, char *,
63                                                             ext->num_exts);
64                 ext->extensions_guid    = talloc_zero_array(mem_ctx, char *,
65                                                             ext->num_exts);
66                 ext->snapins            = talloc_zero_array(mem_ctx, char *,
67                                                             ext->num_exts);
68                 ext->snapins_guid       = talloc_zero_array(mem_ctx, char *,
69                                                             ext->num_exts);
70         }
71
72         ext->gp_extension = talloc_strdup(mem_ctx, extension_raw);
73
74         if (!ext->extensions || !ext->extensions_guid ||
75             !ext->snapins || !ext->snapins_guid ||
76             !ext->gp_extension) {
77                 goto parse_error;
78         }
79
80         for (i = 0; ext_list[i] != NULL; i++) {
81
82                 int k;
83                 char *p, *q;
84
85                 DEBUGADD(10,("extension #%d\n", i));
86
87                 p = ext_list[i];
88
89                 if (p[0] == '[') {
90                         p++;
91                 }
92
93                 ext_strings = str_list_make(mem_ctx, p, "}");
94                 if (ext_strings == NULL) {
95                         goto parse_error;
96                 }
97
98                 for (k = 0; ext_strings[k] != NULL; k++) {
99                         /* no op */
100                 }
101
102                 q = ext_strings[0];
103
104                 if (q[0] == '{') {
105                         q++;
106                 }
107
108                 ext->extensions[i] = talloc_strdup(mem_ctx,
109                                            cse_gpo_guid_string_to_name(q));
110                 ext->extensions_guid[i] = talloc_strdup(mem_ctx, q);
111
112                 /* we might have no name for the guid */
113                 if (ext->extensions_guid[i] == NULL) {
114                         goto parse_error;
115                 }
116
117                 for (k = 1; ext_strings[k] != NULL; k++) {
118
119                         char *m = ext_strings[k];
120
121                         if (m[0] == '{') {
122                                 m++;
123                         }
124
125                         /* FIXME: theoretically there could be more than one
126                          * snapin per extension */
127                         ext->snapins[i] = talloc_strdup(mem_ctx,
128                                 cse_snapin_gpo_guid_string_to_name(m));
129                         ext->snapins_guid[i] = talloc_strdup(mem_ctx, m);
130
131                         /* we might have no name for the guid */
132                         if (ext->snapins_guid[i] == NULL) {
133                                 goto parse_error;
134                         }
135                 }
136         }
137
138         *gp_ext = ext;
139
140         ret = true;
141
142  parse_error:
143         talloc_free(ext_list);
144         talloc_free(ext_strings);
145
146         return ret;
147 }
148
149 #ifdef HAVE_LDAP
150
151 /****************************************************************
152  parse the raw link string into a GP_LINK structure
153 ****************************************************************/
154
155 static ADS_STATUS gpo_parse_gplink(TALLOC_CTX *mem_ctx,
156                                    const char *gp_link_raw,
157                                    uint32_t options,
158                                    struct GP_LINK *gp_link)
159 {
160         ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
161         char **link_list;
162         int i;
163
164         ZERO_STRUCTP(gp_link);
165
166         DEBUG(10,("gpo_parse_gplink: gPLink: %s\n", gp_link_raw));
167
168         link_list = str_list_make_v3(mem_ctx, gp_link_raw, "]");
169         if (!link_list) {
170                 goto parse_error;
171         }
172
173         for (i = 0; link_list[i] != NULL; i++) {
174                 /* no op */
175         }
176
177         gp_link->gp_opts = options;
178         gp_link->num_links = i;
179
180         if (gp_link->num_links) {
181                 gp_link->link_names = talloc_zero_array(mem_ctx, char *,
182                                                         gp_link->num_links);
183                 gp_link->link_opts = talloc_zero_array(mem_ctx, uint32_t,
184                                                        gp_link->num_links);
185         }
186
187         gp_link->gp_link = talloc_strdup(mem_ctx, gp_link_raw);
188
189         if (!gp_link->link_names || !gp_link->link_opts || !gp_link->gp_link) {
190                 goto parse_error;
191         }
192
193         for (i = 0; link_list[i] != NULL; i++) {
194
195                 char *p, *q;
196
197                 DEBUGADD(10,("gpo_parse_gplink: processing link #%d\n", i));
198
199                 q = link_list[i];
200                 if (q[0] == '[') {
201                         q++;
202                 };
203
204                 p = strchr(q, ';');
205
206                 if (p == NULL) {
207                         goto parse_error;
208                 }
209
210                 gp_link->link_names[i] = talloc_strdup(mem_ctx, q);
211                 if (gp_link->link_names[i] == NULL) {
212                         goto parse_error;
213                 }
214                 gp_link->link_names[i][PTR_DIFF(p, q)] = 0;
215
216                 gp_link->link_opts[i] = atoi(p + 1);
217
218                 DEBUGADD(10,("gpo_parse_gplink: link: %s\n",
219                         gp_link->link_names[i]));
220                 DEBUGADD(10,("gpo_parse_gplink: opt: %d\n",
221                         gp_link->link_opts[i]));
222
223         }
224
225         status = ADS_SUCCESS;
226
227  parse_error:
228         talloc_free(link_list);
229
230         return status;
231 }
232
233 /****************************************************************
234  helper call to get a GP_LINK structure from a linkdn
235 ****************************************************************/
236
237 ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
238                             TALLOC_CTX *mem_ctx,
239                             const char *link_dn,
240                             struct GP_LINK *gp_link_struct)
241 {
242         ADS_STATUS status;
243         const char *attrs[] = {"gPLink", "gPOptions", NULL};
244         LDAPMessage *res = NULL;
245         const char *gp_link;
246         uint32_t gp_options;
247
248         ZERO_STRUCTP(gp_link_struct);
249
250         status = ads_search_dn(ads, &res, link_dn, attrs);
251         if (!ADS_ERR_OK(status)) {
252                 DEBUG(10,("ads_get_gpo_link: search failed with %s\n",
253                         ads_errstr(status)));
254                 return status;
255         }
256
257         if (ads_count_replies(ads, res) != 1) {
258                 DEBUG(10,("ads_get_gpo_link: no result\n"));
259                 ads_msgfree(ads, res);
260                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
261         }
262
263         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
264         if (gp_link == NULL) {
265                 DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
266                 ads_msgfree(ads, res);
267                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
268         }
269
270         /* perfectly legal to have no options */
271         if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
272                 DEBUG(10,("ads_get_gpo_link: "
273                         "no 'gPOptions' attribute found\n"));
274                 gp_options = 0;
275         }
276
277         ads_msgfree(ads, res);
278
279         return gpo_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
280 }
281
282 /****************************************************************
283  helper call to add a gp link
284 ****************************************************************/
285
286 ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
287                             TALLOC_CTX *mem_ctx,
288                             const char *link_dn,
289                             const char *gpo_dn,
290                             uint32_t gpo_opt)
291 {
292         ADS_STATUS status;
293         const char *attrs[] = {"gPLink", NULL};
294         LDAPMessage *res = NULL;
295         const char *gp_link, *gp_link_new;
296         ADS_MODLIST mods;
297
298         /* although ADS allows one to set anything here, we better check here if
299          * the gpo_dn is sane */
300
301         if (!strnequal(gpo_dn, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
302                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
303         }
304
305         status = ads_search_dn(ads, &res, link_dn, attrs);
306         if (!ADS_ERR_OK(status)) {
307                 DEBUG(10,("ads_add_gpo_link: search failed with %s\n",
308                         ads_errstr(status)));
309                 return status;
310         }
311
312         if (ads_count_replies(ads, res) != 1) {
313                 DEBUG(10,("ads_add_gpo_link: no result\n"));
314                 ads_msgfree(ads, res);
315                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
316         }
317
318         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
319         if (gp_link == NULL) {
320                 gp_link_new = talloc_asprintf(mem_ctx, "[%s;%d]",
321                         gpo_dn, gpo_opt);
322         } else {
323                 gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]",
324                         gp_link, gpo_dn, gpo_opt);
325         }
326
327         ads_msgfree(ads, res);
328         ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
329
330         mods = ads_init_mods(mem_ctx);
331         ADS_ERROR_HAVE_NO_MEMORY(mods);
332
333         status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
334         if (!ADS_ERR_OK(status)) {
335                 return status;
336         }
337
338         return ads_gen_mod(ads, link_dn, mods);
339 }
340
341 /****************************************************************
342  helper call to delete add a gp link
343 ****************************************************************/
344
345 /* untested & broken */
346 ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
347                                TALLOC_CTX *mem_ctx,
348                                const char *link_dn,
349                                const char *gpo_dn)
350 {
351         ADS_STATUS status;
352         const char *attrs[] = {"gPLink", NULL};
353         LDAPMessage *res = NULL;
354         const char *gp_link, *gp_link_new = NULL;
355         ADS_MODLIST mods;
356
357         /* check for a sane gpo_dn */
358         if (gpo_dn[0] != '[') {
359                 DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
360                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
361         }
362
363         if (gpo_dn[strlen(gpo_dn)] != ']') {
364                 DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
365                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
366         }
367
368         status = ads_search_dn(ads, &res, link_dn, attrs);
369         if (!ADS_ERR_OK(status)) {
370                 DEBUG(10,("ads_delete_gpo_link: search failed with %s\n",
371                         ads_errstr(status)));
372                 return status;
373         }
374
375         if (ads_count_replies(ads, res) != 1) {
376                 DEBUG(10,("ads_delete_gpo_link: no result\n"));
377                 ads_msgfree(ads, res);
378                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
379         }
380
381         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
382         if (gp_link == NULL) {
383                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
384         }
385
386         /* find link to delete */
387         /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link,
388                                          gpo_dn, gpo_opt); */
389
390         ads_msgfree(ads, res);
391         ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
392
393         mods = ads_init_mods(mem_ctx);
394         ADS_ERROR_HAVE_NO_MEMORY(mods);
395
396         status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
397         if (!ADS_ERR_OK(status)) {
398                 return status;
399         }
400
401         return ads_gen_mod(ads, link_dn, mods);
402 }
403
404 /****************************************************************
405  parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
406 ****************************************************************/
407
408  ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
409                           TALLOC_CTX *mem_ctx,
410                           LDAPMessage *res,
411                           const char *gpo_dn,
412                           struct GROUP_POLICY_OBJECT *gpo)
413 {
414         ZERO_STRUCTP(gpo);
415
416         ADS_ERROR_HAVE_NO_MEMORY(res);
417
418         if (gpo_dn) {
419                 gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
420         } else {
421                 gpo->ds_path = ads_get_dn(ads, mem_ctx, res);
422         }
423
424         ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
425
426         if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
427                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
428         }
429
430         if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
431                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
432         }
433
434         gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res,
435                 "gPCFileSysPath");
436         if (gpo->file_sys_path == NULL) {
437                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
438         }
439
440         gpo->display_name = ads_pull_string(ads, mem_ctx, res,
441                 "displayName");
442         if (gpo->display_name == NULL) {
443                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
444         }
445
446         gpo->name = ads_pull_string(ads, mem_ctx, res,
447                 "name");
448         if (gpo->name == NULL) {
449                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
450         }
451
452         gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res,
453                 "gPCMachineExtensionNames");
454         gpo->user_extensions = ads_pull_string(ads, mem_ctx, res,
455                 "gPCUserExtensionNames");
456
457         ads_pull_sd(ads, mem_ctx, res, "ntSecurityDescriptor",
458                 &gpo->security_descriptor);
459         if (gpo->security_descriptor == NULL) {
460                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
461         }
462
463         return ADS_ERROR(LDAP_SUCCESS);
464 }
465
466 /****************************************************************
467  get a GROUP_POLICY_OBJECT structure based on different input parameters
468 ****************************************************************/
469
470 ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
471                        TALLOC_CTX *mem_ctx,
472                        const char *gpo_dn,
473                        const char *display_name,
474                        const char *guid_name,
475                        struct GROUP_POLICY_OBJECT *gpo)
476 {
477         ADS_STATUS status;
478         LDAPMessage *res = NULL;
479         char *dn;
480         const char *filter;
481         const char *attrs[] = {
482                 "cn",
483                 "displayName",
484                 "flags",
485                 "gPCFileSysPath",
486                 "gPCFunctionalityVersion",
487                 "gPCMachineExtensionNames",
488                 "gPCUserExtensionNames",
489                 "gPCWQLFilter",
490                 "name",
491                 "ntSecurityDescriptor",
492                 "versionNumber",
493                 NULL};
494         uint32_t sd_flags = SECINFO_DACL;
495
496         ZERO_STRUCTP(gpo);
497
498         if (!gpo_dn && !display_name && !guid_name) {
499                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
500         }
501
502         if (gpo_dn) {
503
504                 if (strnequal(gpo_dn, "LDAP://", strlen("LDAP://")) != 0) {
505                         gpo_dn = gpo_dn + strlen("LDAP://");
506                 }
507
508                 status = ads_search_retry_dn_sd_flags(ads, &res,
509                                                       sd_flags,
510                                                       gpo_dn, attrs);
511
512         } else if (display_name || guid_name) {
513
514                 filter = talloc_asprintf(mem_ctx,
515                                  "(&(objectclass=groupPolicyContainer)(%s=%s))",
516                                  display_name ? "displayName" : "name",
517                                  display_name ? display_name : guid_name);
518                 ADS_ERROR_HAVE_NO_MEMORY(filter);
519
520                 status = ads_do_search_all_sd_flags(ads, ads->config.bind_path,
521                                                     LDAP_SCOPE_SUBTREE, filter,
522                                                     attrs, sd_flags, &res);
523         }
524
525         if (!ADS_ERR_OK(status)) {
526                 DEBUG(10,("ads_get_gpo: search failed with %s\n",
527                         ads_errstr(status)));
528                 return status;
529         }
530
531         if (ads_count_replies(ads, res) != 1) {
532                 DEBUG(10,("ads_get_gpo: no result\n"));
533                 ads_msgfree(ads, res);
534                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
535         }
536
537         dn = ads_get_dn(ads, mem_ctx, res);
538         if (dn == NULL) {
539                 ads_msgfree(ads, res);
540                 return ADS_ERROR(LDAP_NO_MEMORY);
541         }
542
543         status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
544         ads_msgfree(ads, res);
545         TALLOC_FREE(dn);
546
547         return status;
548 }
549
550 /****************************************************************
551  add a gplink to the GROUP_POLICY_OBJECT linked list
552 ****************************************************************/
553
554 static ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
555                                          TALLOC_CTX *mem_ctx,
556                                          struct GROUP_POLICY_OBJECT **gpo_list,
557                                          const char *link_dn,
558                                          struct GP_LINK *gp_link,
559                                          enum GPO_LINK_TYPE link_type,
560                                          bool only_add_forced_gpos,
561                                          const struct security_token *token)
562 {
563         ADS_STATUS status;
564         uint32_t count;
565
566         /*
567          * Note: DLIST_ADD pushes to the front,
568          * so loop from last to first to get the
569          * order right.
570          */
571         for (count = gp_link->num_links; count > 0; count--) {
572                 /* NB. Index into arrays is one less than counter. */
573                 uint32_t i = count - 1;
574                 struct GROUP_POLICY_OBJECT *new_gpo = NULL;
575
576                 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
577                         DEBUG(10,("skipping disabled GPO\n"));
578                         continue;
579                 }
580
581                 if (only_add_forced_gpos) {
582
583                         if (!(gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED)) {
584                                 DEBUG(10,("skipping nonenforced GPO link "
585                                         "because GPOPTIONS_BLOCK_INHERITANCE "
586                                         "has been set\n"));
587                                 continue;
588                         } else {
589                                 DEBUG(10,("adding enforced GPO link although "
590                                         "the GPOPTIONS_BLOCK_INHERITANCE "
591                                         "has been set\n"));
592                         }
593                 }
594
595                 new_gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
596                 ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
597
598                 status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i],
599                                      NULL, NULL, new_gpo);
600                 if (!ADS_ERR_OK(status)) {
601                         DEBUG(10,("failed to get gpo: %s\n",
602                                 gp_link->link_names[i]));
603                         if ((status.error_type == ENUM_ADS_ERROR_LDAP) &&
604                             (status.err.rc == LDAP_NO_SUCH_ATTRIBUTE)) {
605                                 DEBUG(10,("skipping empty gpo: %s\n",
606                                         gp_link->link_names[i]));
607                                 talloc_free(new_gpo);
608                                 continue;
609                         }
610                         return status;
611                 }
612
613                 status = ADS_ERROR_NT(gpo_apply_security_filtering(new_gpo,
614                                                                    token));
615                 if (!ADS_ERR_OK(status)) {
616                         DEBUG(10,("skipping GPO \"%s\" as object "
617                                 "has no access to it\n",
618                                 new_gpo->display_name));
619                         talloc_free(new_gpo);
620                         continue;
621                 }
622
623                 new_gpo->link = link_dn;
624                 new_gpo->link_type = link_type;
625
626                 DLIST_ADD(*gpo_list, new_gpo);
627
628                 DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s "
629                         "to GPO list\n", i, gp_link->link_names[i]));
630         }
631
632         return ADS_ERROR(LDAP_SUCCESS);
633 }
634
635 /****************************************************************
636 ****************************************************************/
637
638 ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
639                              TALLOC_CTX *mem_ctx,
640                              const char *dn,
641                              struct security_token **token)
642 {
643         ADS_STATUS status;
644         struct dom_sid object_sid;
645         struct dom_sid primary_group_sid;
646         struct dom_sid *ad_token_sids;
647         size_t num_ad_token_sids = 0;
648         struct dom_sid *token_sids;
649         uint32_t num_token_sids = 0;
650         struct security_token *new_token = NULL;
651         int i;
652
653         status = ads_get_tokensids(ads, mem_ctx, dn,
654                                    &object_sid, &primary_group_sid,
655                                    &ad_token_sids, &num_ad_token_sids);
656         if (!ADS_ERR_OK(status)) {
657                 return status;
658         }
659
660         token_sids = talloc_array(mem_ctx, struct dom_sid, 1);
661         ADS_ERROR_HAVE_NO_MEMORY(token_sids);
662
663         status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
664                                                       &primary_group_sid,
665                                                       &token_sids,
666                                                       &num_token_sids));
667         if (!ADS_ERR_OK(status)) {
668                 return status;
669         }
670
671         for (i = 0; i < num_ad_token_sids; i++) {
672
673                 if (sid_check_is_in_builtin(&ad_token_sids[i])) {
674                         continue;
675                 }
676
677                 status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
678                                                               &ad_token_sids[i],
679                                                               &token_sids,
680                                                               &num_token_sids));
681                 if (!ADS_ERR_OK(status)) {
682                         return status;
683                 }
684         }
685
686         new_token = create_local_nt_token(mem_ctx, &object_sid, false,
687                                           num_token_sids, token_sids);
688         ADS_ERROR_HAVE_NO_MEMORY(new_token);
689
690         *token = new_token;
691
692         security_token_debug(DBGC_CLASS, 5, *token);
693
694         return ADS_ERROR_LDAP(LDAP_SUCCESS);
695 }
696
697 /****************************************************************
698 ****************************************************************/
699
700 static ADS_STATUS add_local_policy_to_gpo_list(TALLOC_CTX *mem_ctx,
701                                                struct GROUP_POLICY_OBJECT **gpo_list,
702                                                enum GPO_LINK_TYPE link_type)
703 {
704         struct GROUP_POLICY_OBJECT *gpo = NULL;
705
706         ADS_ERROR_HAVE_NO_MEMORY(gpo_list);
707
708         gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
709         ADS_ERROR_HAVE_NO_MEMORY(gpo);
710
711         gpo->name = talloc_strdup(mem_ctx, "Local Policy");
712         ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
713
714         gpo->display_name = talloc_strdup(mem_ctx, "Local Policy");
715         ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
716
717         gpo->link_type = link_type;
718
719         DLIST_ADD(*gpo_list, gpo);
720
721         return ADS_ERROR_NT(NT_STATUS_OK);
722 }
723
724 /****************************************************************
725  get the full list of GROUP_POLICY_OBJECTs for a given dn
726 ****************************************************************/
727
728 ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
729                             TALLOC_CTX *mem_ctx,
730                             const char *dn,
731                             uint32_t flags,
732                             const struct security_token *token,
733                             struct GROUP_POLICY_OBJECT **gpo_list)
734 {
735         /*
736          * Push GPOs to gpo_list so that the traversal order of the list matches
737          * the order of application:
738          * (L)ocal (S)ite (D)omain (O)rganizational(U)nit
739          * Within domains and OUs: parent-to-child.
740          * Since GPOs are pushed to the front of gpo_list, GPOs have to be
741          * pushed in the opposite order of application (OUs first, local last,
742          * child-to-parent).
743          */
744
745         ADS_STATUS status;
746         struct GP_LINK gp_link;
747         const char *parent_dn, *site_dn, *tmp_dn;
748         bool add_only_forced_gpos = false;
749
750         ZERO_STRUCTP(gpo_list);
751
752         if (!dn) {
753                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
754         }
755
756         if (!ads_set_sasl_wrap_flags(ads, ADS_AUTH_SASL_SIGN)) {
757                 return ADS_ERROR(LDAP_INVALID_CREDENTIALS);
758         }
759
760         DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
761
762         tmp_dn = dn;
763
764         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
765                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
766
767
768                 /* (O)rganizational(U)nit */
769
770                 /* An account can be a member of more OUs */
771                 if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
772
773                         DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n",
774                                 parent_dn));
775
776                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
777                                                   &gp_link);
778                         if (ADS_ERR_OK(status)) {
779
780                                 if (DEBUGLEVEL >= 100) {
781                                         dump_gplink(&gp_link);
782                                 }
783
784                                 status = add_gplink_to_gpo_list(ads,
785                                                         mem_ctx,
786                                                         gpo_list,
787                                                         parent_dn,
788                                                         &gp_link,
789                                                         GP_LINK_OU,
790                                                         add_only_forced_gpos,
791                                                         token);
792                                 if (!ADS_ERR_OK(status)) {
793                                         return status;
794                                 }
795
796                                 /* block inheritance from now on */
797                                 if (gp_link.gp_opts &
798                                     GPOPTIONS_BLOCK_INHERITANCE) {
799                                         add_only_forced_gpos = true;
800                                 }
801                         }
802                 }
803
804                 tmp_dn = parent_dn;
805
806         }
807
808         /* reset dn again */
809         tmp_dn = dn;
810
811         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
812                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
813
814                 /* (D)omain */
815
816                 /* An account can just be a member of one domain */
817                 if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
818
819                         DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n",
820                                 parent_dn));
821
822                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
823                                                   &gp_link);
824                         if (ADS_ERR_OK(status)) {
825
826                                 if (DEBUGLEVEL >= 100) {
827                                         dump_gplink(&gp_link);
828                                 }
829
830                                 status = add_gplink_to_gpo_list(ads,
831                                                         mem_ctx,
832                                                         gpo_list,
833                                                         parent_dn,
834                                                         &gp_link,
835                                                         GP_LINK_DOMAIN,
836                                                         add_only_forced_gpos,
837                                                         token);
838                                 if (!ADS_ERR_OK(status)) {
839                                         return status;
840                                 }
841
842                                 /* block inheritance from now on */
843                                 if (gp_link.gp_opts &
844                                     GPOPTIONS_BLOCK_INHERITANCE) {
845                                         add_only_forced_gpos = true;
846                                 }
847                         }
848                 }
849
850                 tmp_dn = parent_dn;
851         }
852
853         /* (S)ite */
854
855         /* are site GPOs valid for users as well ??? */
856         if (flags & GPO_LIST_FLAG_MACHINE) {
857
858                 status = ads_site_dn_for_machine(ads, mem_ctx,
859                                                  ads->config.ldap_server_name,
860                                                  &site_dn);
861                 if (!ADS_ERR_OK(status)) {
862                         return status;
863                 }
864
865                 DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n",
866                         site_dn));
867
868                 status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
869                 if (ADS_ERR_OK(status)) {
870
871                         if (DEBUGLEVEL >= 100) {
872                                 dump_gplink(&gp_link);
873                         }
874
875                         status = add_gplink_to_gpo_list(ads, mem_ctx, gpo_list,
876                                                         site_dn, &gp_link,
877                                                         GP_LINK_SITE,
878                                                         add_only_forced_gpos,
879                                                         token);
880                         if (!ADS_ERR_OK(status)) {
881                                 return status;
882                         }
883
884                         if (flags & GPO_LIST_FLAG_SITEONLY) {
885                                 return ADS_ERROR(LDAP_SUCCESS);
886                         }
887
888                         /* inheritance can't be blocked at the site level */
889                 }
890         }
891
892         /* (L)ocal */
893         status = add_local_policy_to_gpo_list(mem_ctx, gpo_list,
894                                               GP_LINK_LOCAL);
895         if (!ADS_ERR_OK(status)) {
896                 return status;
897         }
898
899         return ADS_ERROR(LDAP_SUCCESS);
900 }
901
902 #endif /* HAVE_LDAP */