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