1 /*
2    Unix SMB/CIFS implementation.
3 
4    Winbind ADS backend functions
5 
6    Copyright (C) Andrew Tridgell 2001
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
8    Copyright (C) Gerald (Jerry) Carter 2004
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "includes.h"
25 #include "winbindd.h"
26 #include "winbindd_ads.h"
27 #include "libsmb/namequery.h"
28 #include "rpc_client/rpc_client.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "../libds/common/flags.h"
31 #include "ads.h"
32 #include "../libcli/ldap/ldap_ndr.h"
33 #include "../libcli/security/security.h"
34 #include "../libds/common/flag_mapping.h"
35 #include "libsmb/samlogon_cache.h"
36 #include "passdb.h"
37 
38 #ifdef HAVE_ADS
39 
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_WINBIND
42 
43 extern struct winbindd_methods reconnect_methods;
44 extern struct winbindd_methods msrpc_methods;
45 
46 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
47 
48 /**
49  * Check if cached connection can be reused. If the connection cannot
50  * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
51  */
ads_cached_connection_reuse(ADS_STRUCT ** adsp)52 static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
53 {
54 
55 	ADS_STRUCT *ads = *adsp;
56 
57 	if (ads != NULL) {
58 		time_t expire;
59 		time_t now = time(NULL);
60 
61 		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
62 
63 		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
64 			  "is now %d)\n", (uint32_t)expire - (uint32_t)now,
65 			  (uint32_t) expire, (uint32_t) now));
66 
67 		if ( ads->config.realm && (expire > now)) {
68 			return;
69 		} else {
70 			/* we own this ADS_STRUCT so make sure it goes away */
71 			DEBUG(7,("Deleting expired krb5 credential cache\n"));
72 			ads->is_mine = True;
73 			ads_destroy( &ads );
74 			ads_kdestroy(WINBIND_CCACHE_NAME);
75 			*adsp = NULL;
76 		}
77 	}
78 }
79 
80 /**
81  * @brief Establish a connection to a DC
82  *
83  * @param[out]   adsp             ADS_STRUCT that will be created
84  * @param[in]    target_realm     Realm of domain to connect to
85  * @param[in]    target_dom_name  'workgroup' name of domain to connect to
86  * @param[in]    ldap_server      DNS name of server to connect to
87  * @param[in]    password         Our machine acount secret
88  * @param[in]    auth_realm       Realm of local domain for creating krb token
89  * @param[in]    renewable        Renewable ticket time
90  *
91  * @return ADS_STATUS
92  */
ads_cached_connection_connect(ADS_STRUCT ** adsp,const char * target_realm,const char * target_dom_name,const char * ldap_server,char * password,char * auth_realm,time_t renewable)93 static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
94 						const char *target_realm,
95 						const char *target_dom_name,
96 						const char *ldap_server,
97 						char *password,
98 						char *auth_realm,
99 						time_t renewable)
100 {
101 	ADS_STRUCT *ads;
102 	ADS_STATUS status;
103 	struct sockaddr_storage dc_ss;
104 	fstring dc_name;
105 
106 	if (auth_realm == NULL) {
107 		return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
108 	}
109 
110 	/* we don't want this to affect the users ccache */
111 	setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
112 
113 	ads = ads_init(target_realm,
114 		       target_dom_name,
115 		       ldap_server,
116 		       ADS_SASL_SEAL);
117 	if (!ads) {
118 		DEBUG(1,("ads_init for domain %s failed\n", target_dom_name));
119 		return ADS_ERROR(LDAP_NO_MEMORY);
120 	}
121 
122 	SAFE_FREE(ads->auth.password);
123 	SAFE_FREE(ads->auth.realm);
124 
125 	ads->auth.renewable = renewable;
126 	ads->auth.password = password;
127 
128 	ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
129 
130 	ads->auth.realm = SMB_STRDUP(auth_realm);
131 	if (!strupper_m(ads->auth.realm)) {
132 		ads_destroy(&ads);
133 		return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
134 	}
135 
136 	/* Setup the server affinity cache.  We don't reaally care
137 	   about the name.  Just setup affinity and the KRB5_CONFIG
138 	   file. */
139 	get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
140 
141 	status = ads_connect(ads);
142 	if (!ADS_ERR_OK(status)) {
143 		DEBUG(1,("ads_connect for domain %s failed: %s\n",
144 			 target_dom_name, ads_errstr(status)));
145 		ads_destroy(&ads);
146 		return status;
147 	}
148 
149 	/* set the flag that says we don't own the memory even
150 	   though we do so that ads_destroy() won't destroy the
151 	   structure we pass back by reference */
152 
153 	ads->is_mine = False;
154 
155 	*adsp = ads;
156 
157 	return status;
158 }
159 
ads_idmap_cached_connection(ADS_STRUCT ** adsp,const char * dom_name)160 ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
161 {
162 	char *ldap_server, *realm, *password;
163 	struct winbindd_domain *wb_dom;
164 	ADS_STATUS status;
165 
166 	if (IS_AD_DC) {
167 		/*
168 		 * Make sure we never try to use LDAP against
169 		 * a trusted domain as AD DC.
170 		 */
171 		return ADS_ERROR_NT(NT_STATUS_REQUEST_NOT_ACCEPTED);
172 	}
173 
174 	ads_cached_connection_reuse(adsp);
175 	if (*adsp != NULL) {
176 		return ADS_SUCCESS;
177 	}
178 
179 	/*
180 	 * At this point we only have the NetBIOS domain name.
181 	 * Check if we can get server nam and realm from SAF cache
182 	 * and the domain list.
183 	 */
184 	ldap_server = saf_fetch(talloc_tos(), dom_name);
185 	DEBUG(10, ("ldap_server from saf cache: '%s'\n",
186 		   ldap_server ? ldap_server : ""));
187 
188 	wb_dom = find_domain_from_name(dom_name);
189 	if (wb_dom == NULL) {
190 		DEBUG(10, ("could not find domain '%s'\n", dom_name));
191 		return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
192 	}
193 
194 	DEBUG(10, ("find_domain_from_name found realm '%s' for "
195 			  " domain '%s'\n", wb_dom->alt_name, dom_name));
196 
197 	if (!get_trust_pw_clear(dom_name, &password, NULL, NULL)) {
198 		TALLOC_FREE(ldap_server);
199 		return ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
200 	}
201 
202 	if (IS_DC) {
203 		SMB_ASSERT(wb_dom->alt_name != NULL);
204 		realm = SMB_STRDUP(wb_dom->alt_name);
205 	} else {
206 		struct winbindd_domain *our_domain = wb_dom;
207 
208 		/* always give preference to the alt_name in our
209 		   primary domain if possible */
210 
211 		if (!wb_dom->primary) {
212 			our_domain = find_our_domain();
213 		}
214 
215 		if (our_domain->alt_name != NULL) {
216 			realm = SMB_STRDUP(our_domain->alt_name);
217 		} else {
218 			realm = SMB_STRDUP(lp_realm());
219 		}
220 	}
221 
222 	status = ads_cached_connection_connect(
223 		adsp,			/* Returns ads struct. */
224 		wb_dom->alt_name,	/* realm to connect to. */
225 		dom_name,		/* 'workgroup' name for ads_init */
226 		ldap_server,		/* DNS name to connect to. */
227 		password,		/* password for auth realm. */
228 		realm,			/* realm used for krb5 ticket. */
229 		0);			/* renewable ticket time. */
230 
231 	SAFE_FREE(realm);
232 	TALLOC_FREE(ldap_server);
233 
234 	return status;
235 }
236 
237 /*
238   return our ads connections structure for a domain. We keep the connection
239   open to make things faster
240 */
ads_cached_connection(struct winbindd_domain * domain)241 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
242 {
243 	ADS_STATUS status;
244 	char *password, *realm;
245 
246 	if (IS_AD_DC) {
247 		/*
248 		 * Make sure we never try to use LDAP against
249 		 * a trusted domain as AD DC.
250 		 */
251 		return NULL;
252 	}
253 
254 	DEBUG(10,("ads_cached_connection\n"));
255 	ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
256 
257 	if (domain->private_data) {
258 		return (ADS_STRUCT *)domain->private_data;
259 	}
260 
261 	/* the machine acct password might have change - fetch it every time */
262 
263 	if (!get_trust_pw_clear(domain->name, &password, NULL, NULL)) {
264 		return NULL;
265 	}
266 
267 	if ( IS_DC ) {
268 		SMB_ASSERT(domain->alt_name != NULL);
269 		realm = SMB_STRDUP(domain->alt_name);
270 	}
271 	else {
272 		struct winbindd_domain *our_domain = domain;
273 
274 
275 		/* always give preference to the alt_name in our
276 		   primary domain if possible */
277 
278 		if ( !domain->primary )
279 			our_domain = find_our_domain();
280 
281 		if (our_domain->alt_name != NULL) {
282 			realm = SMB_STRDUP( our_domain->alt_name );
283 		}
284 		else
285 			realm = SMB_STRDUP( lp_realm() );
286 	}
287 
288 	status = ads_cached_connection_connect(
289 					(ADS_STRUCT **)&domain->private_data,
290 					domain->alt_name,
291 					domain->name, NULL,
292 					password, realm,
293 					WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
294 	SAFE_FREE(realm);
295 
296 	if (!ADS_ERR_OK(status)) {
297 		/* if we get ECONNREFUSED then it might be a NT4
298                    server, fall back to MSRPC */
299 		if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
300 		    status.err.rc == ECONNREFUSED) {
301 			/* 'reconnect_methods' is the MS-RPC backend. */
302 			DEBUG(1,("Trying MSRPC methods\n"));
303 			domain->backend = &reconnect_methods;
304 		}
305 		return NULL;
306 	}
307 
308 	return (ADS_STRUCT *)domain->private_data;
309 }
310 
311 /* Query display info for a realm. This is the basic user list fn */
query_user_list(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t ** prids)312 static NTSTATUS query_user_list(struct winbindd_domain *domain,
313 			       TALLOC_CTX *mem_ctx,
314 			       uint32_t **prids)
315 {
316 	ADS_STRUCT *ads = NULL;
317 	const char *attrs[] = { "sAMAccountType", "objectSid", NULL };
318 	int count;
319 	uint32_t *rids = NULL;
320 	ADS_STATUS rc;
321 	LDAPMessage *res = NULL;
322 	LDAPMessage *msg = NULL;
323 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
324 
325 	DEBUG(3,("ads: query_user_list\n"));
326 
327 	if ( !winbindd_can_contact_domain( domain ) ) {
328 		DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
329 			  domain->name));
330 		return NT_STATUS_OK;
331 	}
332 
333 	ads = ads_cached_connection(domain);
334 
335 	if (!ads) {
336 		domain->last_status = NT_STATUS_SERVER_DISABLED;
337 		goto done;
338 	}
339 
340 	rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
341 	if (!ADS_ERR_OK(rc)) {
342 		DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
343 		status = ads_ntstatus(rc);
344 		goto done;
345 	} else if (!res) {
346 		DEBUG(1,("query_user_list ads_search returned NULL res\n"));
347 		goto done;
348 	}
349 
350 	count = ads_count_replies(ads, res);
351 	if (count == 0) {
352 		DEBUG(1,("query_user_list: No users found\n"));
353 		goto done;
354 	}
355 
356 	rids = talloc_zero_array(mem_ctx, uint32_t, count);
357 	if (rids == NULL) {
358 		status = NT_STATUS_NO_MEMORY;
359 		goto done;
360 	}
361 
362 	count = 0;
363 
364 	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
365 		struct dom_sid user_sid;
366 		uint32_t atype;
367 		bool ok;
368 
369 		ok = ads_pull_uint32(ads, msg, "sAMAccountType", &atype);
370 		if (!ok) {
371 			DBG_INFO("Object lacks sAMAccountType attribute\n");
372 			continue;
373 		}
374 		if (ds_atype_map(atype) != SID_NAME_USER) {
375 			DBG_INFO("Not a user account? atype=0x%x\n", atype);
376 			continue;
377 		}
378 
379 		if (!ads_pull_sid(ads, msg, "objectSid", &user_sid)) {
380 			char *dn = ads_get_dn(ads, talloc_tos(), msg);
381 			DBG_INFO("No sid for %s !?\n", dn);
382 			TALLOC_FREE(dn);
383 			continue;
384 		}
385 
386 		if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
387 			struct dom_sid_buf sidstr, domstr;
388 			DBG_WARNING("Got sid %s in domain %s\n",
389 				    dom_sid_str_buf(&user_sid, &sidstr),
390 				    dom_sid_str_buf(&domain->sid, &domstr));
391 			continue;
392 		}
393 
394 		sid_split_rid(&user_sid, &rids[count]);
395 		count += 1;
396 	}
397 
398 	rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
399 	if (prids != NULL) {
400 		*prids = rids;
401 	}
402 
403 	status = NT_STATUS_OK;
404 
405 	DBG_NOTICE("ads query_user_list gave %d entries\n", count);
406 
407 done:
408 	ads_msgfree(ads, res);
409 	return status;
410 }
411 
412 /* list all domain groups */
enum_dom_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * num_entries,struct wb_acct_info ** info)413 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
414 				TALLOC_CTX *mem_ctx,
415 				uint32_t *num_entries,
416 				struct wb_acct_info **info)
417 {
418 	ADS_STRUCT *ads = NULL;
419 	const char *attrs[] = {"userPrincipalName", "sAMAccountName",
420 			       "name", "objectSid", NULL};
421 	int i, count;
422 	ADS_STATUS rc;
423 	LDAPMessage *res = NULL;
424 	LDAPMessage *msg = NULL;
425 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
426 	const char *filter;
427 	bool enum_dom_local_groups = False;
428 
429 	*num_entries = 0;
430 
431 	DEBUG(3,("ads: enum_dom_groups\n"));
432 
433 	if ( !winbindd_can_contact_domain( domain ) ) {
434 		DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
435 			  domain->name));
436 		return NT_STATUS_OK;
437 	}
438 
439 	/* only grab domain local groups for our domain */
440 	if ( domain->active_directory && strequal(lp_realm(), domain->alt_name)  ) {
441 		enum_dom_local_groups = True;
442 	}
443 
444 	/* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
445 	 * rollup-fixes:
446 	 *
447 	 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
448 	 * default value, it MUST be absent. In case of extensible matching the
449 	 * "dnattr" boolean defaults to FALSE and so it must be only be present
450 	 * when set to TRUE.
451 	 *
452 	 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
453 	 * filter using bitwise matching rule then the buggy AD fails to decode
454 	 * the extensible match. As a workaround set it to TRUE and thereby add
455 	 * the dnAttributes "dn" field to cope with those older AD versions.
456 	 * It should not harm and won't put any additional load on the AD since
457 	 * none of the dn components have a bitmask-attribute.
458 	 *
459 	 * Thanks to Ralf Haferkamp for input and testing - Guenther */
460 
461 	filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
462 				 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
463 				 ADS_LDAP_MATCHING_RULE_BIT_AND,
464 				 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
465 
466 	if (filter == NULL) {
467 		status = NT_STATUS_NO_MEMORY;
468 		goto done;
469 	}
470 
471 	ads = ads_cached_connection(domain);
472 
473 	if (!ads) {
474 		domain->last_status = NT_STATUS_SERVER_DISABLED;
475 		goto done;
476 	}
477 
478 	rc = ads_search_retry(ads, &res, filter, attrs);
479 	if (!ADS_ERR_OK(rc)) {
480 		status = ads_ntstatus(rc);
481 		DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
482 		goto done;
483 	} else if (!res) {
484 		DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
485 		goto done;
486 	}
487 
488 	count = ads_count_replies(ads, res);
489 	if (count == 0) {
490 		DEBUG(1,("enum_dom_groups: No groups found\n"));
491 		goto done;
492 	}
493 
494 	(*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
495 	if (!*info) {
496 		status = NT_STATUS_NO_MEMORY;
497 		goto done;
498 	}
499 
500 	i = 0;
501 
502 	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
503 		char *name, *gecos;
504 		struct dom_sid sid;
505 		uint32_t rid;
506 
507 		name = ads_pull_username(ads, (*info), msg);
508 		gecos = ads_pull_string(ads, (*info), msg, "name");
509 		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
510 			DEBUG(1,("No sid for %s !?\n", name));
511 			continue;
512 		}
513 
514 		if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
515 			DEBUG(1,("No rid for %s !?\n", name));
516 			continue;
517 		}
518 
519 		(*info)[i].acct_name = name;
520 		(*info)[i].acct_desc = gecos;
521 		(*info)[i].rid = rid;
522 		i++;
523 	}
524 
525 	(*num_entries) = i;
526 
527 	status = NT_STATUS_OK;
528 
529 	DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
530 
531 done:
532 	if (res)
533 		ads_msgfree(ads, res);
534 
535 	return status;
536 }
537 
538 /* list all domain local groups */
enum_local_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * num_entries,struct wb_acct_info ** info)539 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
540 				TALLOC_CTX *mem_ctx,
541 				uint32_t *num_entries,
542 				struct wb_acct_info **info)
543 {
544 	/*
545 	 * This is a stub function only as we returned the domain
546 	 * local groups in enum_dom_groups() if the domain->native field
547 	 * was true.  This is a simple performance optimization when
548 	 * using LDAP.
549 	 *
550 	 * if we ever need to enumerate domain local groups separately,
551 	 * then this optimization in enum_dom_groups() will need
552 	 * to be split out
553 	 */
554 	*num_entries = 0;
555 
556 	return NT_STATUS_OK;
557 }
558 
559 /* convert a single name to a sid in a domain - use rpc methods */
name_to_sid(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * domain_name,const char * name,uint32_t flags,const char ** pdom_name,struct dom_sid * sid,enum lsa_SidType * type)560 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
561 			    TALLOC_CTX *mem_ctx,
562 			    const char *domain_name,
563 			    const char *name,
564 			    uint32_t flags,
565 			    const char **pdom_name,
566 			    struct dom_sid *sid,
567 			    enum lsa_SidType *type)
568 {
569 	return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
570 					 flags, pdom_name, sid, type);
571 }
572 
573 /* convert a domain SID to a user or group name - use rpc methods */
sid_to_name(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,char ** domain_name,char ** name,enum lsa_SidType * type)574 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
575 			    TALLOC_CTX *mem_ctx,
576 			    const struct dom_sid *sid,
577 			    char **domain_name,
578 			    char **name,
579 			    enum lsa_SidType *type)
580 {
581 	return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
582 					 domain_name, name, type);
583 }
584 
585 /* convert a list of rids to names - use rpc methods */
rids_to_names(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,uint32_t * rids,size_t num_rids,char ** domain_name,char *** names,enum lsa_SidType ** types)586 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
587 			      TALLOC_CTX *mem_ctx,
588 			      const struct dom_sid *sid,
589 			      uint32_t *rids,
590 			      size_t num_rids,
591 			      char **domain_name,
592 			      char ***names,
593 			      enum lsa_SidType **types)
594 {
595 	return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
596 					   rids, num_rids,
597 					   domain_name, names, types);
598 }
599 
600 /* Lookup groups a user is a member of - alternate method, for when
601    tokenGroups are not available. */
lookup_usergroups_member(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * user_dn,struct dom_sid * primary_group,uint32_t * p_num_groups,struct dom_sid ** user_sids)602 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
603 					 TALLOC_CTX *mem_ctx,
604 					 const char *user_dn,
605 					 struct dom_sid *primary_group,
606 					 uint32_t *p_num_groups, struct dom_sid **user_sids)
607 {
608 	ADS_STATUS rc;
609 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
610 	int count;
611 	LDAPMessage *res = NULL;
612 	LDAPMessage *msg = NULL;
613 	char *ldap_exp;
614 	ADS_STRUCT *ads;
615 	const char *group_attrs[] = {"objectSid", NULL};
616 	char *escaped_dn;
617 	uint32_t num_groups = 0;
618 
619 	DEBUG(3,("ads: lookup_usergroups_member\n"));
620 
621 	if ( !winbindd_can_contact_domain( domain ) ) {
622 		DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
623 			  domain->name));
624 		return NT_STATUS_OK;
625 	}
626 
627 	ads = ads_cached_connection(domain);
628 
629 	if (!ads) {
630 		domain->last_status = NT_STATUS_SERVER_DISABLED;
631 		goto done;
632 	}
633 
634 	if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
635 		status = NT_STATUS_NO_MEMORY;
636 		goto done;
637 	}
638 
639 	ldap_exp = talloc_asprintf(mem_ctx,
640 		"(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
641 		escaped_dn,
642 		ADS_LDAP_MATCHING_RULE_BIT_AND,
643 		GROUP_TYPE_SECURITY_ENABLED);
644 	if (!ldap_exp) {
645 		DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
646 		TALLOC_FREE(escaped_dn);
647 		status = NT_STATUS_NO_MEMORY;
648 		goto done;
649 	}
650 
651 	TALLOC_FREE(escaped_dn);
652 
653 	rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
654 
655 	if (!ADS_ERR_OK(rc)) {
656 		DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
657 		return ads_ntstatus(rc);
658 	} else if (!res) {
659 		DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
660 		return NT_STATUS_INTERNAL_ERROR;
661 	}
662 
663 
664 	count = ads_count_replies(ads, res);
665 
666 	*user_sids = NULL;
667 	num_groups = 0;
668 
669 	/* always add the primary group to the sid array */
670 	status = add_sid_to_array(mem_ctx, primary_group, user_sids,
671 				  &num_groups);
672 	if (!NT_STATUS_IS_OK(status)) {
673 		goto done;
674 	}
675 
676 	if (count > 0) {
677 		for (msg = ads_first_entry(ads, res); msg;
678 		     msg = ads_next_entry(ads, msg)) {
679 			struct dom_sid group_sid;
680 
681 			if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
682 				DEBUG(1,("No sid for this group ?!?\n"));
683 				continue;
684 			}
685 
686 			/* ignore Builtin groups from ADS - Guenther */
687 			if (sid_check_is_in_builtin(&group_sid)) {
688 				continue;
689 			}
690 
691 			status = add_sid_to_array(mem_ctx, &group_sid,
692 						  user_sids, &num_groups);
693 			if (!NT_STATUS_IS_OK(status)) {
694 				goto done;
695 			}
696 		}
697 
698 	}
699 
700 	*p_num_groups = num_groups;
701 	status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
702 
703 	DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
704 done:
705 	if (res)
706 		ads_msgfree(ads, res);
707 
708 	return status;
709 }
710 
711 /* Lookup groups a user is a member of - alternate method, for when
712    tokenGroups are not available. */
lookup_usergroups_memberof(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * user_dn,struct dom_sid * primary_group,uint32_t * p_num_groups,struct dom_sid ** user_sids)713 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
714 					   TALLOC_CTX *mem_ctx,
715 					   const char *user_dn,
716 					   struct dom_sid *primary_group,
717 					   uint32_t *p_num_groups,
718 					   struct dom_sid **user_sids)
719 {
720 	ADS_STATUS rc;
721 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
722 	ADS_STRUCT *ads;
723 	const char *attrs[] = {"memberOf", NULL};
724 	uint32_t num_groups = 0;
725 	struct dom_sid *group_sids = NULL;
726 	size_t i;
727 	char **strings = NULL;
728 	size_t num_strings = 0, num_sids = 0;
729 
730 
731 	DEBUG(3,("ads: lookup_usergroups_memberof\n"));
732 
733 	if ( !winbindd_can_contact_domain( domain ) ) {
734 		DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
735 			  "domain %s\n", domain->name));
736 		return NT_STATUS_OK;
737 	}
738 
739 	ads = ads_cached_connection(domain);
740 
741 	if (!ads) {
742 		domain->last_status = NT_STATUS_SERVER_DISABLED;
743 		return NT_STATUS_UNSUCCESSFUL;
744 	}
745 
746 	rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
747 						 ADS_EXTENDED_DN_HEX_STRING,
748 						 &strings, &num_strings);
749 
750 	if (!ADS_ERR_OK(rc)) {
751 		DEBUG(1,("lookup_usergroups_memberof ads_search "
752 			"member=%s: %s\n", user_dn, ads_errstr(rc)));
753 		return ads_ntstatus(rc);
754 	}
755 
756 	*user_sids = NULL;
757 	num_groups = 0;
758 
759 	/* always add the primary group to the sid array */
760 	status = add_sid_to_array(mem_ctx, primary_group, user_sids,
761 				  &num_groups);
762 	if (!NT_STATUS_IS_OK(status)) {
763 		goto done;
764 	}
765 
766 	group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
767 	if (!group_sids) {
768 		status = NT_STATUS_NO_MEMORY;
769 		goto done;
770 	}
771 
772 	for (i=0; i<num_strings; i++) {
773 		rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
774 						  ADS_EXTENDED_DN_HEX_STRING,
775 						  &(group_sids)[i]);
776 		if (!ADS_ERR_OK(rc)) {
777 			/* ignore members without SIDs */
778 			if (NT_STATUS_EQUAL(ads_ntstatus(rc),
779 			    NT_STATUS_NOT_FOUND)) {
780 				continue;
781 			}
782 			else {
783 				status = ads_ntstatus(rc);
784 				goto done;
785 			}
786 		}
787 		num_sids++;
788 	}
789 
790 	if (i == 0) {
791 		DEBUG(1,("No memberOf for this user?!?\n"));
792 		status = NT_STATUS_NO_MEMORY;
793 		goto done;
794 	}
795 
796 	for (i=0; i<num_sids; i++) {
797 
798 		/* ignore Builtin groups from ADS - Guenther */
799 		if (sid_check_is_in_builtin(&group_sids[i])) {
800 			continue;
801 		}
802 
803 		status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
804 					  &num_groups);
805 		if (!NT_STATUS_IS_OK(status)) {
806 			goto done;
807 		}
808 
809 	}
810 
811 	*p_num_groups = num_groups;
812 	status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
813 
814 	DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
815 		user_dn));
816 
817 done:
818 	TALLOC_FREE(strings);
819 	TALLOC_FREE(group_sids);
820 
821 	return status;
822 }
823 
824 
825 /* Lookup groups a user is a member of. */
lookup_usergroups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,uint32_t * p_num_groups,struct dom_sid ** user_sids)826 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
827 				  TALLOC_CTX *mem_ctx,
828 				  const struct dom_sid *sid,
829 				  uint32_t *p_num_groups, struct dom_sid **user_sids)
830 {
831 	ADS_STRUCT *ads = NULL;
832 	const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
833 	ADS_STATUS rc;
834 	int count;
835 	LDAPMessage *msg = NULL;
836 	char *user_dn = NULL;
837 	struct dom_sid *sids;
838 	int i;
839 	struct dom_sid primary_group;
840 	uint32_t primary_group_rid;
841 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
842 	uint32_t num_groups = 0;
843 	struct dom_sid_buf buf;
844 
845 	DEBUG(3,("ads: lookup_usergroups\n"));
846 	*p_num_groups = 0;
847 
848 	status = lookup_usergroups_cached(mem_ctx, sid,
849 					  p_num_groups, user_sids);
850 	if (NT_STATUS_IS_OK(status)) {
851 		return NT_STATUS_OK;
852 	}
853 
854 	if ( !winbindd_can_contact_domain( domain ) ) {
855 		DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
856 			  domain->name));
857 
858 		/* Tell the cache manager not to remember this one */
859 
860 		return NT_STATUS_SYNCHRONIZATION_REQUIRED;
861 	}
862 
863 	ads = ads_cached_connection(domain);
864 
865 	if (!ads) {
866 		domain->last_status = NT_STATUS_SERVER_DISABLED;
867 		status = NT_STATUS_SERVER_DISABLED;
868 		goto done;
869 	}
870 
871 	rc = ads_search_retry_sid(ads, &msg, sid, attrs);
872 
873 	if (!ADS_ERR_OK(rc)) {
874 		status = ads_ntstatus(rc);
875 		DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
876 			  "%s\n",
877 			  dom_sid_str_buf(sid, &buf),
878 			  ads_errstr(rc)));
879 		goto done;
880 	}
881 
882 	count = ads_count_replies(ads, msg);
883 	if (count != 1) {
884 		status = NT_STATUS_UNSUCCESSFUL;
885 		DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
886 			 "invalid number of results (count=%d)\n",
887 			 dom_sid_str_buf(sid, &buf),
888 			 count));
889 		goto done;
890 	}
891 
892 	if (!msg) {
893 		DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
894 			 dom_sid_str_buf(sid, &buf)));
895 		status = NT_STATUS_UNSUCCESSFUL;
896 		goto done;
897 	}
898 
899 	user_dn = ads_get_dn(ads, mem_ctx, msg);
900 	if (user_dn == NULL) {
901 		status = NT_STATUS_NO_MEMORY;
902 		goto done;
903 	}
904 
905 	if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
906 		DEBUG(1,("%s: No primary group for sid=%s !?\n",
907 			 domain->name,
908 			 dom_sid_str_buf(sid, &buf)));
909 		goto done;
910 	}
911 
912 	sid_compose(&primary_group, &domain->sid, primary_group_rid);
913 
914 	count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
915 
916 	/* there must always be at least one group in the token,
917 	   unless we are talking to a buggy Win2k server */
918 
919 	/* actually this only happens when the machine account has no read
920 	 * permissions on the tokenGroup attribute - gd */
921 
922 	if (count == 0) {
923 
924 		/* no tokenGroups */
925 
926 		/* lookup what groups this user is a member of by DN search on
927 		 * "memberOf" */
928 
929 		status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
930 						    &primary_group,
931 						    &num_groups, user_sids);
932 		*p_num_groups = num_groups;
933 		if (NT_STATUS_IS_OK(status)) {
934 			goto done;
935 		}
936 
937 		/* lookup what groups this user is a member of by DN search on
938 		 * "member" */
939 
940 		status = lookup_usergroups_member(domain, mem_ctx, user_dn,
941 						  &primary_group,
942 						  &num_groups, user_sids);
943 		*p_num_groups = num_groups;
944 		goto done;
945 	}
946 
947 	*user_sids = NULL;
948 	num_groups = 0;
949 
950 	status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
951 				  &num_groups);
952 	if (!NT_STATUS_IS_OK(status)) {
953 		goto done;
954 	}
955 
956 	for (i=0;i<count;i++) {
957 
958 		/* ignore Builtin groups from ADS - Guenther */
959 		if (sid_check_is_in_builtin(&sids[i])) {
960 			continue;
961 		}
962 
963 		status = add_sid_to_array_unique(mem_ctx, &sids[i],
964 						 user_sids, &num_groups);
965 		if (!NT_STATUS_IS_OK(status)) {
966 			goto done;
967 		}
968 	}
969 
970 	*p_num_groups = (uint32_t)num_groups;
971 	status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
972 
973 	DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
974 		 dom_sid_str_buf(sid, &buf)));
975 done:
976 	TALLOC_FREE(user_dn);
977 	ads_msgfree(ads, msg);
978 	return status;
979 }
980 
981 /* Lookup aliases a user is member of - use rpc methods */
lookup_useraliases(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t num_sids,const struct dom_sid * sids,uint32_t * num_aliases,uint32_t ** alias_rids)982 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
983 				   TALLOC_CTX *mem_ctx,
984 				   uint32_t num_sids, const struct dom_sid *sids,
985 				   uint32_t *num_aliases, uint32_t **alias_rids)
986 {
987 	return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
988 						num_aliases, alias_rids);
989 }
990 
add_primary_group_members(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,uint32_t rid,char *** all_members,size_t * num_all_members)991 static NTSTATUS add_primary_group_members(
992 	ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
993 	char ***all_members, size_t *num_all_members)
994 {
995 	char *filter;
996 	NTSTATUS status = NT_STATUS_NO_MEMORY;
997 	ADS_STATUS rc;
998 	const char *attrs[] = { "dn", NULL };
999 	LDAPMessage *res = NULL;
1000 	LDAPMessage *msg;
1001 	char **members;
1002 	size_t num_members;
1003 	ads_control args;
1004 
1005 	filter = talloc_asprintf(
1006 		mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
1007 		(unsigned)rid);
1008 	if (filter == NULL) {
1009 		goto done;
1010 	}
1011 
1012 	args.control = ADS_EXTENDED_DN_OID;
1013 	args.val = ADS_EXTENDED_DN_HEX_STRING;
1014 	args.critical = True;
1015 
1016 	rc = ads_do_search_all_args(ads, ads->config.bind_path,
1017 				    LDAP_SCOPE_SUBTREE, filter, attrs, &args,
1018 				    &res);
1019 
1020 	if (!ADS_ERR_OK(rc)) {
1021 		status = ads_ntstatus(rc);
1022 		DEBUG(1,("%s: ads_search: %s\n", __func__, ads_errstr(rc)));
1023 		goto done;
1024 	}
1025 	if (res == NULL) {
1026 		DEBUG(1,("%s: ads_search returned NULL res\n", __func__));
1027 		goto done;
1028 	}
1029 
1030 	num_members = ads_count_replies(ads, res);
1031 
1032 	DEBUG(10, ("%s: Got %ju primary group members\n", __func__,
1033 		   (uintmax_t)num_members));
1034 
1035 	if (num_members == 0) {
1036 		status = NT_STATUS_OK;
1037 		goto done;
1038 	}
1039 
1040 	members = talloc_realloc(mem_ctx, *all_members, char *,
1041 				 *num_all_members + num_members);
1042 	if (members == NULL) {
1043 		DEBUG(1, ("%s: talloc_realloc failed\n", __func__));
1044 		goto done;
1045 	}
1046 	*all_members = members;
1047 
1048 	for (msg = ads_first_entry(ads, res); msg != NULL;
1049 	     msg = ads_next_entry(ads, msg)) {
1050 		char *dn;
1051 
1052 		dn = ads_get_dn(ads, members, msg);
1053 		if (dn == NULL) {
1054 			DEBUG(1, ("%s: ads_get_dn failed\n", __func__));
1055 			continue;
1056 		}
1057 
1058 		members[*num_all_members] = dn;
1059 		*num_all_members += 1;
1060 	}
1061 
1062 	status = NT_STATUS_OK;
1063 done:
1064 	if (res != NULL) {
1065 		ads_msgfree(ads, res);
1066 	}
1067 	TALLOC_FREE(filter);
1068 	return status;
1069 }
1070 
1071 /*
1072   find the members of a group, given a group rid and domain
1073  */
lookup_groupmem(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * group_sid,enum lsa_SidType type,uint32_t * num_names,struct dom_sid ** sid_mem,char *** names,uint32_t ** name_types)1074 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
1075 				TALLOC_CTX *mem_ctx,
1076 				const struct dom_sid *group_sid,
1077 				enum lsa_SidType type,
1078 				uint32_t *num_names,
1079 				struct dom_sid **sid_mem, char ***names,
1080 				uint32_t **name_types)
1081 {
1082 	ADS_STATUS rc;
1083 	ADS_STRUCT *ads = NULL;
1084 	char *ldap_exp;
1085 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1086 	char *sidbinstr;
1087 	char **members = NULL;
1088 	size_t i;
1089 	size_t num_members = 0;
1090 	ads_control args;
1091 	struct dom_sid *sid_mem_nocache = NULL;
1092 	char **names_nocache = NULL;
1093 	enum lsa_SidType *name_types_nocache = NULL;
1094 	char **domains_nocache = NULL;     /* only needed for rpccli_lsa_lookup_sids */
1095 	uint32_t num_nocache = 0;
1096 	TALLOC_CTX *tmp_ctx = NULL;
1097 	uint32_t rid;
1098 	struct dom_sid_buf buf;
1099 
1100 	DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1101 		  dom_sid_str_buf(group_sid, &buf)));
1102 
1103 	*num_names = 0;
1104 
1105 	tmp_ctx = talloc_new(mem_ctx);
1106 	if (!tmp_ctx) {
1107 		DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1108 		status = NT_STATUS_NO_MEMORY;
1109 		goto done;
1110 	}
1111 
1112 	if (!sid_peek_rid(group_sid, &rid)) {
1113 		DEBUG(1, ("%s: sid_peek_rid failed\n", __func__));
1114 		status = NT_STATUS_INVALID_PARAMETER;
1115 		goto done;
1116 	}
1117 
1118 	if ( !winbindd_can_contact_domain( domain ) ) {
1119 		DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1120 			  domain->name));
1121 		return NT_STATUS_OK;
1122 	}
1123 
1124 	ads = ads_cached_connection(domain);
1125 
1126 	if (!ads) {
1127 		domain->last_status = NT_STATUS_SERVER_DISABLED;
1128 		goto done;
1129 	}
1130 
1131 	if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1132 		status = NT_STATUS_NO_MEMORY;
1133 		goto done;
1134 	}
1135 
1136 	/* search for all members of the group */
1137 	ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1138 	TALLOC_FREE(sidbinstr);
1139 	if (ldap_exp == NULL) {
1140 		DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1141 		status = NT_STATUS_NO_MEMORY;
1142 		goto done;
1143 	}
1144 
1145 	args.control = ADS_EXTENDED_DN_OID;
1146 	args.val = ADS_EXTENDED_DN_HEX_STRING;
1147 	args.critical = True;
1148 
1149 	rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1150 			       ldap_exp, &args, "member", &members, &num_members);
1151 
1152 	if (!ADS_ERR_OK(rc)) {
1153 		DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1154 		status = NT_STATUS_UNSUCCESSFUL;
1155 		goto done;
1156 	}
1157 
1158 	DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1159 
1160 	status = add_primary_group_members(ads, mem_ctx, rid,
1161 					   &members, &num_members);
1162 	if (!NT_STATUS_IS_OK(status)) {
1163 		DEBUG(10, ("%s: add_primary_group_members failed: %s\n",
1164 			   __func__, nt_errstr(status)));
1165 		goto done;
1166 	}
1167 
1168 	DEBUG(10, ("%s: Got %d sids after adding primary group members\n",
1169 		   __func__, (int)num_members));
1170 
1171 	/* Now that we have a list of sids, we need to get the
1172 	 * lists of names and name_types belonging to these sids.
1173 	 * even though conceptually not quite clean,  we use the
1174 	 * RPC call lsa_lookup_sids for this since it can handle a
1175 	 * list of sids. ldap calls can just resolve one sid at a time.
1176 	 *
1177 	 * At this stage, the sids are still hidden in the exetended dn
1178 	 * member output format. We actually do a little better than
1179 	 * stated above: In extracting the sids from the member strings,
1180 	 * we try to resolve as many sids as possible from the
1181 	 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1182 
1183 	if (num_members) {
1184 		(*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
1185 		(*names) = talloc_zero_array(mem_ctx, char *, num_members);
1186 		(*name_types) = talloc_zero_array(mem_ctx, uint32_t, num_members);
1187 		(sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
1188 
1189 		if ((members == NULL) || (*sid_mem == NULL) ||
1190 		    (*names == NULL) || (*name_types == NULL) ||
1191 		    (sid_mem_nocache == NULL))
1192 		{
1193 			DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1194 			status = NT_STATUS_NO_MEMORY;
1195 			goto done;
1196 		}
1197 	}
1198 	else {
1199 		(*sid_mem) = NULL;
1200 		(*names) = NULL;
1201 		(*name_types) = NULL;
1202 	}
1203 
1204 	for (i=0; i<num_members; i++) {
1205 		enum lsa_SidType name_type;
1206 		char *name, *domain_name;
1207 		struct dom_sid sid;
1208 
1209 	        rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1210 		    &sid);
1211 		if (!ADS_ERR_OK(rc)) {
1212 			if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1213 			    NT_STATUS_NOT_FOUND)) {
1214 				/* Group members can be objects, like Exchange
1215 				 * Public Folders, that don't have a SID.  Skip
1216 				 * them. */
1217 				continue;
1218 			}
1219 			else {
1220 				status = ads_ntstatus(rc);
1221 				goto done;
1222 			}
1223 		}
1224 		if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1225 		    &name_type)) {
1226 			DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1227 				  "cache\n",
1228 				  dom_sid_str_buf(&sid, &buf)));
1229 			sid_copy(&(*sid_mem)[*num_names], &sid);
1230 			(*names)[*num_names] = fill_domain_username_talloc(
1231 							*names,
1232 							domain_name,
1233 							name,
1234 							true);
1235 
1236 			(*name_types)[*num_names] = name_type;
1237 			(*num_names)++;
1238 		}
1239 		else {
1240 			DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1241 				   "cache\n",
1242 				   dom_sid_str_buf(&sid, &buf)));
1243 			sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1244 			num_nocache++;
1245 		}
1246 	}
1247 
1248 	DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1249 		  "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1250 
1251 	/* handle sids not resolved from cache by lsa_lookup_sids */
1252 	if (num_nocache > 0) {
1253 
1254 		status = winbindd_lookup_sids(tmp_ctx,
1255 					      domain,
1256 					      num_nocache,
1257 					      sid_mem_nocache,
1258 					      &domains_nocache,
1259 					      &names_nocache,
1260 					      &name_types_nocache);
1261 
1262 		if (!(NT_STATUS_IS_OK(status) ||
1263 		      NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1264 		      NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1265 		{
1266 			DEBUG(1, ("lsa_lookupsids call failed with %s "
1267 				  "- retrying...\n", nt_errstr(status)));
1268 
1269 			status = winbindd_lookup_sids(tmp_ctx,
1270 						      domain,
1271 						      num_nocache,
1272 						      sid_mem_nocache,
1273 						      &domains_nocache,
1274 						      &names_nocache,
1275 						      &name_types_nocache);
1276 		}
1277 
1278 		if (NT_STATUS_IS_OK(status) ||
1279 		    NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
1280 		{
1281 			/* Copy the entries over from the "_nocache" arrays
1282 			 * to the result arrays, skipping the gaps the
1283 			 * lookup_sids call left. */
1284 			for (i=0; i < num_nocache; i++) {
1285 				if (((names_nocache)[i] != NULL) &&
1286 				    ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
1287 				{
1288 					sid_copy(&(*sid_mem)[*num_names],
1289 						 &sid_mem_nocache[i]);
1290 					(*names)[*num_names] =
1291 						fill_domain_username_talloc(
1292 							*names,
1293 							domains_nocache[i],
1294 							names_nocache[i],
1295 							true);
1296 					(*name_types)[*num_names] = name_types_nocache[i];
1297 					(*num_names)++;
1298 				}
1299 			}
1300 		}
1301 		else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1302 			DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
1303 				   "not map any SIDs at all.\n"));
1304 			/* Don't handle this as an error here.
1305 			 * There is nothing left to do with respect to the
1306 			 * overall result... */
1307 		}
1308 		else if (!NT_STATUS_IS_OK(status)) {
1309 			DEBUG(10, ("lookup_groupmem: Error looking up %d "
1310 				   "sids via rpc_lsa_lookup_sids: %s\n",
1311 				   (int)num_members, nt_errstr(status)));
1312 			goto done;
1313 		}
1314 	}
1315 
1316 	status = NT_STATUS_OK;
1317 	DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1318 		 dom_sid_str_buf(group_sid, &buf)));
1319 
1320 done:
1321 
1322 	TALLOC_FREE(tmp_ctx);
1323 
1324 	return status;
1325 }
1326 
1327 /* find the sequence number for a domain */
sequence_number(struct winbindd_domain * domain,uint32_t * seq)1328 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
1329 {
1330 	ADS_STRUCT *ads = NULL;
1331 	ADS_STATUS rc;
1332 
1333 	DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
1334 
1335 	if ( !winbindd_can_contact_domain( domain ) ) {
1336 		DEBUG(10,("sequence: No incoming trust for domain %s\n",
1337 			  domain->name));
1338 		*seq = time(NULL);
1339 		return NT_STATUS_OK;
1340 	}
1341 
1342 	if (IS_AD_DC) {
1343 		DEBUG(10,("sequence: Avoid LDAP connection for domain %s\n",
1344 			  domain->name));
1345 		*seq = time(NULL);
1346 		return NT_STATUS_OK;
1347 	}
1348 
1349 	*seq = DOM_SEQUENCE_NONE;
1350 
1351 	ads = ads_cached_connection(domain);
1352 
1353 	if (!ads) {
1354 		domain->last_status = NT_STATUS_SERVER_DISABLED;
1355 		return NT_STATUS_UNSUCCESSFUL;
1356 	}
1357 
1358 	rc = ads_USN(ads, seq);
1359 
1360 	if (!ADS_ERR_OK(rc)) {
1361 
1362 		/* its a dead connection, destroy it */
1363 
1364 		if (domain->private_data) {
1365 			ads = (ADS_STRUCT *)domain->private_data;
1366 			ads->is_mine = True;
1367 			ads_destroy(&ads);
1368 			ads_kdestroy(WINBIND_CCACHE_NAME);
1369 			domain->private_data = NULL;
1370 		}
1371 	}
1372 	return ads_ntstatus(rc);
1373 }
1374 
1375 /* find the lockout policy of a domain - use rpc methods */
lockout_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo12 * policy)1376 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1377 			       TALLOC_CTX *mem_ctx,
1378 			       struct samr_DomInfo12 *policy)
1379 {
1380 	return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
1381 }
1382 
1383 /* find the password policy of a domain - use rpc methods */
password_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo1 * policy)1384 static NTSTATUS password_policy(struct winbindd_domain *domain,
1385 				TALLOC_CTX *mem_ctx,
1386 				struct samr_DomInfo1 *policy)
1387 {
1388 	return msrpc_methods.password_policy(domain, mem_ctx, policy);
1389 }
1390 
1391 /* get a list of trusted domains */
trusted_domains(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct netr_DomainTrustList * trusts)1392 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1393 				TALLOC_CTX *mem_ctx,
1394 				struct netr_DomainTrustList *trusts)
1395 {
1396 	NTSTATUS 		result = NT_STATUS_UNSUCCESSFUL;
1397 	WERROR werr;
1398 	uint32_t		i;
1399 	uint32_t		flags;
1400 	struct rpc_pipe_client *cli;
1401 	int ret_count;
1402 	struct dcerpc_binding_handle *b;
1403 
1404 	DEBUG(3,("ads: trusted_domains\n"));
1405 
1406 	ZERO_STRUCTP(trusts);
1407 
1408 	/* If this is our primary domain or a root in our forest,
1409 	   query for all trusts.  If not, then just look for domain
1410 	   trusts in the target forest */
1411 
1412 	if (domain->primary || domain_is_forest_root(domain)) {
1413 		flags = NETR_TRUST_FLAG_OUTBOUND |
1414 			NETR_TRUST_FLAG_INBOUND |
1415 			NETR_TRUST_FLAG_IN_FOREST;
1416 	} else {
1417 		flags = NETR_TRUST_FLAG_IN_FOREST;
1418 	}
1419 
1420 	result = cm_connect_netlogon(domain, &cli);
1421 
1422 	if (!NT_STATUS_IS_OK(result)) {
1423 		DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1424 			  "for PIPE_NETLOGON (%s)\n",
1425 			  domain->name, nt_errstr(result)));
1426 		return NT_STATUS_UNSUCCESSFUL;
1427 	}
1428 
1429 	b = cli->binding_handle;
1430 
1431 	result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1432 						      cli->desthost,
1433 						      flags,
1434 						      trusts,
1435 						      &werr);
1436 	if (!NT_STATUS_IS_OK(result)) {
1437 		return result;
1438 	}
1439 
1440 	if (!W_ERROR_IS_OK(werr)) {
1441 		return werror_to_ntstatus(werr);
1442 	}
1443 	if (trusts->count == 0) {
1444 		return NT_STATUS_OK;
1445 	}
1446 
1447 	/* Copy across names and sids */
1448 
1449 	ret_count = 0;
1450 	for (i = 0; i < trusts->count; i++) {
1451 		struct netr_DomainTrust *trust = &trusts->array[i];
1452 		struct winbindd_domain d;
1453 
1454 		ZERO_STRUCT(d);
1455 
1456 		/*
1457 		 * drop external trusts if this is not our primary
1458 		 * domain.  This means that the returned number of
1459 		 * domains may be less that the ones actually trusted
1460 		 * by the DC.
1461 		 */
1462 
1463 		if ((trust->trust_attributes
1464 		     & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1465 		    !domain->primary )
1466 		{
1467 			DEBUG(10,("trusted_domains: Skipping external trusted "
1468 				  "domain %s because it is outside of our "
1469 				  "primary domain\n",
1470 				  trust->netbios_name));
1471 			continue;
1472 		}
1473 
1474 		/* add to the trusted domain cache */
1475 
1476 		d.name = discard_const_p(char, trust->netbios_name);
1477 		d.alt_name = discard_const_p(char, trust->dns_name);
1478 
1479 		if (trust->sid) {
1480 			sid_copy(&d.sid, trust->sid);
1481 		} else {
1482 			sid_copy(&d.sid, &global_sid_NULL);
1483 		}
1484 
1485 		if ( domain->primary ) {
1486 			DEBUG(10,("trusted_domains(ads):  Searching "
1487 				  "trusted domain list of %s and storing "
1488 				  "trust flags for domain %s\n",
1489 				  domain->name, d.alt_name));
1490 
1491 			d.domain_flags = trust->trust_flags;
1492 			d.domain_type = trust->trust_type;
1493 			d.domain_trust_attribs = trust->trust_attributes;
1494 
1495 			wcache_tdc_add_domain( &d );
1496 			ret_count++;
1497 		} else if (domain_is_forest_root(domain)) {
1498 			/* Check if we already have this record. If
1499 			 * we are following our forest root that is not
1500 			 * our primary domain, we want to keep trust
1501 			 * flags from the perspective of our primary
1502 			 * domain not our forest root. */
1503 			struct winbindd_tdc_domain *exist = NULL;
1504 
1505 			exist = wcache_tdc_fetch_domain(
1506 				talloc_tos(), trust->netbios_name);
1507 			if (!exist) {
1508 				DEBUG(10,("trusted_domains(ads):  Searching "
1509 					  "trusted domain list of %s and "
1510 					  "storing trust flags for domain "
1511 					  "%s\n", domain->name, d.alt_name));
1512 				d.domain_flags = trust->trust_flags;
1513 				d.domain_type = trust->trust_type;
1514 				d.domain_trust_attribs =
1515 					trust->trust_attributes;
1516 
1517 				wcache_tdc_add_domain( &d );
1518 				ret_count++;
1519 			}
1520 			TALLOC_FREE(exist);
1521 		} else {
1522 			/* This gets a little tricky.  If we are
1523 			   following a transitive forest trust, then
1524 			   innerit the flags, type, and attribs from
1525 			   the domain we queried to make sure we don't
1526 			   record the view of the trust from the wrong
1527 			   side.  Always view it from the side of our
1528 			   primary domain.   --jerry */
1529 			struct winbindd_tdc_domain *parent = NULL;
1530 
1531 			DEBUG(10,("trusted_domains(ads):  Searching "
1532 				  "trusted domain list of %s and inheriting "
1533 				  "trust flags for domain %s\n",
1534 				  domain->name, d.alt_name));
1535 
1536 			parent = wcache_tdc_fetch_domain(talloc_tos(),
1537 							 domain->name);
1538 			if (parent) {
1539 				d.domain_flags = parent->trust_flags;
1540 				d.domain_type  = parent->trust_type;
1541 				d.domain_trust_attribs = parent->trust_attribs;
1542 			} else {
1543 				d.domain_flags = domain->domain_flags;
1544 				d.domain_type  = domain->domain_type;
1545 				d.domain_trust_attribs =
1546 					domain->domain_trust_attribs;
1547 			}
1548 			TALLOC_FREE(parent);
1549 
1550 			/*
1551 			 * We need to pass the modified properties
1552 			 * to the caller.
1553 			 */
1554 			trust->trust_flags = d.domain_flags;
1555 			trust->trust_type = d.domain_type;
1556 			trust->trust_attributes = d.domain_trust_attribs;
1557 
1558 			wcache_tdc_add_domain( &d );
1559 			ret_count++;
1560 		}
1561 	}
1562 	return result;
1563 }
1564 
1565 /* the ADS backend methods are exposed via this structure */
1566 struct winbindd_methods ads_methods = {
1567 	True,
1568 	query_user_list,
1569 	enum_dom_groups,
1570 	enum_local_groups,
1571 	name_to_sid,
1572 	sid_to_name,
1573 	rids_to_names,
1574 	lookup_usergroups,
1575 	lookup_useraliases,
1576 	lookup_groupmem,
1577 	sequence_number,
1578 	lockout_policy,
1579 	password_policy,
1580 	trusted_domains,
1581 };
1582 
1583 #endif
1584