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 
ads_parse_gp_ext(TALLOC_CTX * mem_ctx,const char * extension_raw,struct GP_EXT ** gp_ext)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 
gpo_parse_gplink(TALLOC_CTX * mem_ctx,const char * gp_link_raw,uint32_t options,struct GP_LINK * gp_link)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 
ads_get_gpo_link(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * link_dn,struct GP_LINK * gp_link_struct)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 
ads_add_gpo_link(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * link_dn,const char * gpo_dn,uint32_t gpo_opt)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 */
ads_delete_gpo_link(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * link_dn,const char * gpo_dn)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 
ads_parse_gpo(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,LDAPMessage * res,const char * gpo_dn,struct GROUP_POLICY_OBJECT * gpo)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 
ads_get_gpo(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * gpo_dn,const char * display_name,const char * guid_name,struct GROUP_POLICY_OBJECT * gpo)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 
add_gplink_to_gpo_list(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,struct GROUP_POLICY_OBJECT ** gpo_list,struct GROUP_POLICY_OBJECT ** forced_gpo_list,const char * link_dn,struct GP_LINK * gp_link,enum GPO_LINK_TYPE link_type,bool only_add_forced_gpos,const struct security_token * token)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 
ads_get_sid_token(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * dn,struct security_token ** token)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 
add_local_policy_to_gpo_list(TALLOC_CTX * mem_ctx,struct GROUP_POLICY_OBJECT ** gpo_list,enum GPO_LINK_TYPE link_type)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 
ads_get_gpo_list_internal(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * dn,uint32_t flags,const struct security_token * token,struct GROUP_POLICY_OBJECT ** gpo_list,struct GROUP_POLICY_OBJECT ** forced_gpo_list)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 
ads_get_gpo_list(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,const char * dn,uint32_t flags,const struct security_token * token,struct GROUP_POLICY_OBJECT ** gpo_list)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 */
957