bootstrap/config.py: adjust package list to align current ci image
[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 = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
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                                          struct GROUP_POLICY_OBJECT **forced_gpo_list,
558                                          const char *link_dn,
559                                          struct GP_LINK *gp_link,
560                                          enum GPO_LINK_TYPE link_type,
561                                          bool only_add_forced_gpos,
562                                          const struct security_token *token)
563 {
564         ADS_STATUS status;
565         uint32_t count;
566
567         /*
568          * Note: DLIST_ADD pushes to the front,
569          * so loop from last to first to get the
570          * order right.
571          */
572         for (count = gp_link->num_links; count > 0; count--) {
573                 /* NB. Index into arrays is one less than counter. */
574                 uint32_t i = count - 1;
575                 struct GROUP_POLICY_OBJECT **target_list = NULL;
576                 struct GROUP_POLICY_OBJECT *new_gpo = NULL;
577                 bool is_forced =
578                         (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) != 0;
579
580                 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
581                         DEBUG(10,("skipping disabled GPO\n"));
582                         continue;
583                 }
584
585                 if (only_add_forced_gpos) {
586
587                         if (!is_forced) {
588                                 DEBUG(10,("skipping nonenforced GPO link "
589                                         "because GPOPTIONS_BLOCK_INHERITANCE "
590                                         "has been set\n"));
591                                 continue;
592                         } else {
593                                 DEBUG(10,("adding enforced GPO link although "
594                                         "the GPOPTIONS_BLOCK_INHERITANCE "
595                                         "has been set\n"));
596                         }
597                 }
598
599                 new_gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
600                 ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
601
602                 status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i],
603                                      NULL, NULL, new_gpo);
604                 if (!ADS_ERR_OK(status)) {
605                         DEBUG(10,("failed to get gpo: %s\n",
606                                 gp_link->link_names[i]));
607                         if ((status.error_type == ENUM_ADS_ERROR_LDAP) &&
608                             (status.err.rc == LDAP_NO_SUCH_ATTRIBUTE)) {
609                                 DEBUG(10,("skipping empty gpo: %s\n",
610                                         gp_link->link_names[i]));
611                                 talloc_free(new_gpo);
612                                 continue;
613                         }
614                         return status;
615                 }
616
617                 status = ADS_ERROR_NT(gpo_apply_security_filtering(new_gpo,
618                                                                    token));
619                 if (!ADS_ERR_OK(status)) {
620                         DEBUG(10,("skipping GPO \"%s\" as object "
621                                 "has no access to it\n",
622                                 new_gpo->display_name));
623                         talloc_free(new_gpo);
624                         continue;
625                 }
626
627                 new_gpo->link = link_dn;
628                 new_gpo->link_type = link_type;
629
630                 target_list = is_forced ? forced_gpo_list : gpo_list;
631                 DLIST_ADD(*target_list, new_gpo);
632
633                 DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s "
634                         "to GPO list\n", i, gp_link->link_names[i]));
635         }
636
637         return ADS_ERROR(LDAP_SUCCESS);
638 }
639
640 /****************************************************************
641 ****************************************************************/
642
643 ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
644                              TALLOC_CTX *mem_ctx,
645                              const char *dn,
646                              struct security_token **token)
647 {
648         ADS_STATUS status;
649         struct dom_sid object_sid;
650         struct dom_sid primary_group_sid;
651         struct dom_sid *ad_token_sids;
652         size_t num_ad_token_sids = 0;
653         struct dom_sid *token_sids;
654         uint32_t num_token_sids = 0;
655         struct security_token *new_token = NULL;
656         int i;
657
658         status = ads_get_tokensids(ads, mem_ctx, dn,
659                                    &object_sid, &primary_group_sid,
660                                    &ad_token_sids, &num_ad_token_sids);
661         if (!ADS_ERR_OK(status)) {
662                 return status;
663         }
664
665         token_sids = talloc_array(mem_ctx, struct dom_sid, 1);
666         ADS_ERROR_HAVE_NO_MEMORY(token_sids);
667
668         status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
669                                                       &primary_group_sid,
670                                                       &token_sids,
671                                                       &num_token_sids));
672         if (!ADS_ERR_OK(status)) {
673                 return status;
674         }
675
676         for (i = 0; i < num_ad_token_sids; i++) {
677
678                 if (sid_check_is_in_builtin(&ad_token_sids[i])) {
679                         continue;
680                 }
681
682                 status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
683                                                               &ad_token_sids[i],
684                                                               &token_sids,
685                                                               &num_token_sids));
686                 if (!ADS_ERR_OK(status)) {
687                         return status;
688                 }
689         }
690
691         status = ADS_ERROR_NT(create_local_nt_token(mem_ctx, 
692                                           &object_sid, false,
693                                           num_token_sids, token_sids, &new_token));
694         if (!ADS_ERR_OK(status)) {
695                 return status;
696         }
697         
698         *token = new_token;
699
700         security_token_debug(DBGC_CLASS, 5, *token);
701
702         return ADS_ERROR_LDAP(LDAP_SUCCESS);
703 }
704
705 /****************************************************************
706 ****************************************************************/
707
708 static ADS_STATUS add_local_policy_to_gpo_list(TALLOC_CTX *mem_ctx,
709                                                struct GROUP_POLICY_OBJECT **gpo_list,
710                                                enum GPO_LINK_TYPE link_type)
711 {
712         struct GROUP_POLICY_OBJECT *gpo = NULL;
713
714         ADS_ERROR_HAVE_NO_MEMORY(gpo_list);
715
716         gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
717         ADS_ERROR_HAVE_NO_MEMORY(gpo);
718
719         gpo->name = talloc_strdup(mem_ctx, "Local Policy");
720         ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
721
722         gpo->display_name = talloc_strdup(mem_ctx, "Local Policy");
723         ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
724
725         gpo->link_type = link_type;
726
727         DLIST_ADD(*gpo_list, gpo);
728
729         return ADS_ERROR_NT(NT_STATUS_OK);
730 }
731
732 /****************************************************************
733  Get the full list of GROUP_POLICY_OBJECTs for a given dn.
734 ****************************************************************/
735
736 static ADS_STATUS ads_get_gpo_list_internal(ADS_STRUCT *ads,
737                             TALLOC_CTX *mem_ctx,
738                             const char *dn,
739                             uint32_t flags,
740                             const struct security_token *token,
741                             struct GROUP_POLICY_OBJECT **gpo_list,
742                             struct GROUP_POLICY_OBJECT **forced_gpo_list)
743 {
744         /*
745          * Push GPOs to gpo_list so that the traversal order of the list matches
746          * the order of application:
747          * (L)ocal (S)ite (D)omain (O)rganizational(U)nit
748          * For different domains and OUs: parent-to-child.
749          * Within same level of domains and OUs: Link order.
750          * Since GPOs are pushed to the front of gpo_list, GPOs have to be
751          * pushed in the opposite order of application (OUs first, local last,
752          * child-to-parent).
753          * Forced GPOs are appended in the end since they override all others.
754          */
755
756         ADS_STATUS status;
757         struct GP_LINK gp_link;
758         const char *parent_dn, *site_dn, *tmp_dn;
759         bool add_only_forced_gpos = false;
760
761         ZERO_STRUCTP(gpo_list);
762         ZERO_STRUCTP(forced_gpo_list);
763
764         if (!dn) {
765                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
766         }
767
768         if (!ads_set_sasl_wrap_flags(ads, ADS_AUTH_SASL_SIGN)) {
769                 return ADS_ERROR(LDAP_INVALID_CREDENTIALS);
770         }
771
772         DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
773
774         tmp_dn = dn;
775
776         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
777                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
778
779
780                 /* (O)rganizational(U)nit */
781
782                 /* An account can be a member of more OUs */
783                 if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
784
785                         DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n",
786                                 parent_dn));
787
788                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
789                                                   &gp_link);
790                         if (ADS_ERR_OK(status)) {
791
792                                 if (DEBUGLEVEL >= 100) {
793                                         dump_gplink(&gp_link);
794                                 }
795
796                                 status = add_gplink_to_gpo_list(ads,
797                                                         mem_ctx,
798                                                         gpo_list,
799                                                         forced_gpo_list,
800                                                         parent_dn,
801                                                         &gp_link,
802                                                         GP_LINK_OU,
803                                                         add_only_forced_gpos,
804                                                         token);
805                                 if (!ADS_ERR_OK(status)) {
806                                         return status;
807                                 }
808
809                                 /* block inheritance from now on */
810                                 if (gp_link.gp_opts &
811                                     GPOPTIONS_BLOCK_INHERITANCE) {
812                                         add_only_forced_gpos = true;
813                                 }
814                         }
815                 }
816
817                 tmp_dn = parent_dn;
818
819         }
820
821         /* reset dn again */
822         tmp_dn = dn;
823
824         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
825                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
826
827                 /* (D)omain */
828
829                 /* An account can just be a member of one domain */
830                 if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
831
832                         DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n",
833                                 parent_dn));
834
835                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
836                                                   &gp_link);
837                         if (ADS_ERR_OK(status)) {
838
839                                 if (DEBUGLEVEL >= 100) {
840                                         dump_gplink(&gp_link);
841                                 }
842
843                                 status = add_gplink_to_gpo_list(ads,
844                                                         mem_ctx,
845                                                         gpo_list,
846                                                         forced_gpo_list,
847                                                         parent_dn,
848                                                         &gp_link,
849                                                         GP_LINK_DOMAIN,
850                                                         add_only_forced_gpos,
851                                                         token);
852                                 if (!ADS_ERR_OK(status)) {
853                                         return status;
854                                 }
855
856                                 /* block inheritance from now on */
857                                 if (gp_link.gp_opts &
858                                     GPOPTIONS_BLOCK_INHERITANCE) {
859                                         add_only_forced_gpos = true;
860                                 }
861                         }
862                 }
863
864                 tmp_dn = parent_dn;
865         }
866
867         /* (S)ite */
868
869         /* are site GPOs valid for users as well ??? */
870         if (flags & GPO_LIST_FLAG_MACHINE) {
871
872                 status = ads_site_dn_for_machine(ads, mem_ctx,
873                                                  ads->config.ldap_server_name,
874                                                  &site_dn);
875                 if (!ADS_ERR_OK(status)) {
876                         return status;
877                 }
878
879                 DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n",
880                         site_dn));
881
882                 status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
883                 if (ADS_ERR_OK(status)) {
884
885                         if (DEBUGLEVEL >= 100) {
886                                 dump_gplink(&gp_link);
887                         }
888
889                         status = add_gplink_to_gpo_list(ads,
890                                                         mem_ctx,
891                                                         gpo_list,
892                                                         forced_gpo_list,
893                                                         site_dn,
894                                                         &gp_link,
895                                                         GP_LINK_SITE,
896                                                         add_only_forced_gpos,
897                                                         token);
898                         if (!ADS_ERR_OK(status)) {
899                                 return status;
900                         }
901
902                         if (flags & GPO_LIST_FLAG_SITEONLY) {
903                                 return ADS_ERROR(LDAP_SUCCESS);
904                         }
905
906                         /* inheritance can't be blocked at the site level */
907                 }
908         }
909
910         /* (L)ocal */
911         status = add_local_policy_to_gpo_list(mem_ctx, gpo_list,
912                                               GP_LINK_LOCAL);
913         if (!ADS_ERR_OK(status)) {
914                 return status;
915         }
916
917         return ADS_ERROR(LDAP_SUCCESS);
918 }
919
920 /****************************************************************
921  Get the full list of GROUP_POLICY_OBJECTs for a given dn, wrapper
922  around ads_get_gpo_list_internal() that ensures correct ordering.
923 ****************************************************************/
924
925 ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
926                             TALLOC_CTX *mem_ctx,
927                             const char *dn,
928                             uint32_t flags,
929                             const struct security_token *token,
930                             struct GROUP_POLICY_OBJECT **gpo_list)
931 {
932         struct GROUP_POLICY_OBJECT *forced_gpo_list = NULL;
933         ADS_STATUS status;
934
935         status = ads_get_gpo_list_internal(ads,
936                                            mem_ctx,
937                                            dn,
938                                            flags,
939                                            token,
940                                            gpo_list,
941                                            &forced_gpo_list);
942         if (!ADS_ERR_OK(status)) {
943                 return status;
944         }
945         /*
946          * Append |forced_gpo_list| at the end of |gpo_list|,
947          * so that forced GPOs are applied on top of non enforced GPOs.
948          */
949         DLIST_CONCATENATE(*gpo_list, forced_gpo_list);
950
951         return ADS_ERROR(LDAP_SUCCESS);
952 }
953
954 #endif /* HAVE_LDAP */