s3-winbindd: Fix memory leak in ads_cached_connection().
[Samba.git] / source3 / winbindd / winbindd_ads.c
blob924bc83525bb4b9cf12cb43c10d57fe0cc53b22c
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind ADS backend functions
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
8 Copyright (C) Gerald (Jerry) Carter 2004
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.
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.
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/>.
24 #include "includes.h"
25 #include "winbindd.h"
26 #include "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "../libds/common/flags.h"
29 #include "ads.h"
30 #include "secrets.h"
31 #include "../libcli/ldap/ldap_ndr.h"
32 #include "../libcli/security/security.h"
33 #include "../libds/common/flag_mapping.h"
34 #include "passdb.h"
36 #ifdef HAVE_ADS
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_WINBIND
41 extern struct winbindd_methods reconnect_methods;
43 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
45 /**
46 * Check if cached connection can be reused. If the connection cannot
47 * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
49 static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
52 ADS_STRUCT *ads = *adsp;
54 if (ads != NULL) {
55 time_t expire;
56 time_t now = time(NULL);
58 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
60 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
61 "is now %d)\n", (uint32)expire - (uint32)now,
62 (uint32) expire, (uint32) now));
64 if ( ads->config.realm && (expire > now)) {
65 return;
66 } else {
67 /* we own this ADS_STRUCT so make sure it goes away */
68 DEBUG(7,("Deleting expired krb5 credential cache\n"));
69 ads->is_mine = True;
70 ads_destroy( &ads );
71 ads_kdestroy(WINBIND_CCACHE_NAME);
72 *adsp = NULL;
77 static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
78 const char *dom_name_alt,
79 const char *dom_name,
80 const char *ldap_server,
81 char *password,
82 char *realm,
83 time_t renewable)
85 ADS_STRUCT *ads;
86 ADS_STATUS status;
87 struct sockaddr_storage dc_ss;
88 fstring dc_name;
90 /* we don't want this to affect the users ccache */
91 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
93 ads = ads_init(dom_name_alt, dom_name, ldap_server);
94 if (!ads) {
95 DEBUG(1,("ads_init for domain %s failed\n", dom_name));
96 return ADS_ERROR(LDAP_NO_MEMORY);
99 SAFE_FREE(ads->auth.password);
100 SAFE_FREE(ads->auth.realm);
102 ads->auth.renewable = renewable;
103 ads->auth.password = password;
105 ads->auth.realm = SMB_STRDUP(realm);
106 if (!strupper_m(ads->auth.realm)) {
107 ads_destroy(&ads);
108 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
111 /* Setup the server affinity cache. We don't reaally care
112 about the name. Just setup affinity and the KRB5_CONFIG
113 file. */
114 get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
116 status = ads_connect(ads);
117 if (!ADS_ERR_OK(status)) {
118 DEBUG(1,("ads_connect for domain %s failed: %s\n",
119 dom_name, ads_errstr(status)));
120 ads_destroy(&ads);
121 return status;
124 /* set the flag that says we don't own the memory even
125 though we do so that ads_destroy() won't destroy the
126 structure we pass back by reference */
128 ads->is_mine = False;
130 *adsp = ads;
132 return status;
135 ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
137 char *ldap_server, *realm, *password;
138 struct winbindd_domain *wb_dom;
140 ads_cached_connection_reuse(adsp);
141 if (*adsp != NULL) {
142 return ADS_SUCCESS;
146 * At this point we only have the NetBIOS domain name.
147 * Check if we can get server nam and realm from SAF cache
148 * and the domain list.
150 ldap_server = saf_fetch(dom_name);
151 DEBUG(10, ("ldap_server from saf cache: '%s'\n",
152 ldap_server ? ldap_server : ""));
154 wb_dom = find_domain_from_name_noinit(dom_name);
155 if (wb_dom == NULL) {
156 DEBUG(10, ("could not find domain '%s'\n", dom_name));
157 realm = NULL;
158 } else {
159 DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
160 " domain '%s'\n", wb_dom->alt_name, dom_name));
161 realm = wb_dom->alt_name;
164 /* the machine acct password might have change - fetch it every time */
165 password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
166 realm = SMB_STRDUP(lp_realm());
168 return ads_cached_connection_connect(adsp, realm, dom_name, ldap_server,
169 password, realm, 0);
173 return our ads connections structure for a domain. We keep the connection
174 open to make things faster
176 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
178 ADS_STATUS status;
179 char *password, *realm;
181 DEBUG(10,("ads_cached_connection\n"));
182 ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
184 if (domain->private_data) {
185 return (ADS_STRUCT *)domain->private_data;
188 /* the machine acct password might have change - fetch it every time */
190 if ( IS_DC ) {
192 if ( !pdb_get_trusteddom_pw( domain->name, &password, NULL,
193 NULL ) ) {
194 return NULL;
196 realm = NULL;
198 else {
199 struct winbindd_domain *our_domain = domain;
202 password = secrets_fetch_machine_password(lp_workgroup(), NULL,
203 NULL);
204 /* always give preference to the alt_name in our
205 primary domain if possible */
207 if ( !domain->primary )
208 our_domain = find_our_domain();
210 if (our_domain->alt_name != NULL) {
211 realm = SMB_STRDUP( our_domain->alt_name );
213 else
214 realm = SMB_STRDUP( lp_realm() );
217 status = ads_cached_connection_connect(
218 (ADS_STRUCT **)&domain->private_data,
219 domain->alt_name,
220 domain->name, NULL,
221 password, realm,
222 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
223 SAFE_FREE(realm);
225 if (!ADS_ERR_OK(status)) {
226 /* if we get ECONNREFUSED then it might be a NT4
227 server, fall back to MSRPC */
228 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
229 status.err.rc == ECONNREFUSED) {
230 /* 'reconnect_methods' is the MS-RPC backend. */
231 DEBUG(1,("Trying MSRPC methods\n"));
232 domain->backend = &reconnect_methods;
234 return NULL;
237 return (ADS_STRUCT *)domain->private_data;
240 /* Query display info for a realm. This is the basic user list fn */
241 static NTSTATUS query_user_list(struct winbindd_domain *domain,
242 TALLOC_CTX *mem_ctx,
243 uint32 *num_entries,
244 struct wbint_userinfo **pinfo)
246 ADS_STRUCT *ads = NULL;
247 const char *attrs[] = { "*", NULL };
248 int i, count;
249 ADS_STATUS rc;
250 LDAPMessage *res = NULL;
251 LDAPMessage *msg = NULL;
252 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
254 *num_entries = 0;
256 DEBUG(3,("ads: query_user_list\n"));
258 if ( !winbindd_can_contact_domain( domain ) ) {
259 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
260 domain->name));
261 return NT_STATUS_OK;
264 ads = ads_cached_connection(domain);
266 if (!ads) {
267 domain->last_status = NT_STATUS_SERVER_DISABLED;
268 goto done;
271 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
272 if (!ADS_ERR_OK(rc)) {
273 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
274 status = ads_ntstatus(rc);
275 } else if (!res) {
276 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
278 goto done;
281 count = ads_count_replies(ads, res);
282 if (count == 0) {
283 DEBUG(1,("query_user_list: No users found\n"));
284 goto done;
287 (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
288 if (!*pinfo) {
289 status = NT_STATUS_NO_MEMORY;
290 goto done;
293 count = 0;
295 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
296 struct wbint_userinfo *info = &((*pinfo)[count]);
297 uint32 group;
298 uint32 atype;
300 if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
301 ds_atype_map(atype) != SID_NAME_USER) {
302 DEBUG(1,("Not a user account? atype=0x%x\n", atype));
303 continue;
306 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
307 info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
308 info->homedir = NULL;
309 info->shell = NULL;
310 info->primary_gid = (gid_t)-1;
312 if (!ads_pull_sid(ads, msg, "objectSid",
313 &info->user_sid)) {
314 DEBUG(1, ("No sid for %s !?\n", info->acct_name));
315 continue;
318 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
319 DEBUG(1, ("No primary group for %s !?\n",
320 info->acct_name));
321 continue;
323 sid_compose(&info->group_sid, &domain->sid, group);
325 count += 1;
328 (*num_entries) = count;
329 ads_msgfree(ads, res);
331 for (i=0; i<count; i++) {
332 struct wbint_userinfo *info = &((*pinfo)[i]);
333 const char *gecos = NULL;
334 gid_t primary_gid = (gid_t)-1;
336 status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
337 &info->homedir, &info->shell,
338 &gecos, &primary_gid);
339 if (!NT_STATUS_IS_OK(status)) {
341 * Deliberately ignore this error, there might be more
342 * users to fill
344 continue;
347 if (gecos != NULL) {
348 info->full_name = gecos;
350 info->primary_gid = primary_gid;
353 status = NT_STATUS_OK;
355 DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
357 done:
358 return status;
361 /* list all domain groups */
362 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
363 TALLOC_CTX *mem_ctx,
364 uint32 *num_entries,
365 struct wb_acct_info **info)
367 ADS_STRUCT *ads = NULL;
368 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
369 "name", "objectSid", NULL};
370 int i, count;
371 ADS_STATUS rc;
372 LDAPMessage *res = NULL;
373 LDAPMessage *msg = NULL;
374 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
375 const char *filter;
376 bool enum_dom_local_groups = False;
378 *num_entries = 0;
380 DEBUG(3,("ads: enum_dom_groups\n"));
382 if ( !winbindd_can_contact_domain( domain ) ) {
383 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
384 domain->name));
385 return NT_STATUS_OK;
388 /* only grab domain local groups for our domain */
389 if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
390 enum_dom_local_groups = True;
393 /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
394 * rollup-fixes:
396 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
397 * default value, it MUST be absent. In case of extensible matching the
398 * "dnattr" boolean defaults to FALSE and so it must be only be present
399 * when set to TRUE.
401 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
402 * filter using bitwise matching rule then the buggy AD fails to decode
403 * the extensible match. As a workaround set it to TRUE and thereby add
404 * the dnAttributes "dn" field to cope with those older AD versions.
405 * It should not harm and won't put any additional load on the AD since
406 * none of the dn components have a bitmask-attribute.
408 * Thanks to Ralf Haferkamp for input and testing - Guenther */
410 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
411 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
412 ADS_LDAP_MATCHING_RULE_BIT_AND,
413 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
415 if (filter == NULL) {
416 status = NT_STATUS_NO_MEMORY;
417 goto done;
420 ads = ads_cached_connection(domain);
422 if (!ads) {
423 domain->last_status = NT_STATUS_SERVER_DISABLED;
424 goto done;
427 rc = ads_search_retry(ads, &res, filter, attrs);
428 if (!ADS_ERR_OK(rc)) {
429 status = ads_ntstatus(rc);
430 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
431 goto done;
432 } else if (!res) {
433 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
434 goto done;
437 count = ads_count_replies(ads, res);
438 if (count == 0) {
439 DEBUG(1,("enum_dom_groups: No groups found\n"));
440 goto done;
443 (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
444 if (!*info) {
445 status = NT_STATUS_NO_MEMORY;
446 goto done;
449 i = 0;
451 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
452 char *name, *gecos;
453 struct dom_sid sid;
454 uint32 rid;
456 name = ads_pull_username(ads, mem_ctx, msg);
457 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
458 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
459 DEBUG(1,("No sid for %s !?\n", name));
460 continue;
463 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
464 DEBUG(1,("No rid for %s !?\n", name));
465 continue;
468 fstrcpy((*info)[i].acct_name, name);
469 fstrcpy((*info)[i].acct_desc, gecos);
470 (*info)[i].rid = rid;
471 i++;
474 (*num_entries) = i;
476 status = NT_STATUS_OK;
478 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
480 done:
481 if (res)
482 ads_msgfree(ads, res);
484 return status;
487 /* list all domain local groups */
488 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
489 TALLOC_CTX *mem_ctx,
490 uint32 *num_entries,
491 struct wb_acct_info **info)
494 * This is a stub function only as we returned the domain
495 * local groups in enum_dom_groups() if the domain->native field
496 * was true. This is a simple performance optimization when
497 * using LDAP.
499 * if we ever need to enumerate domain local groups separately,
500 * then this optimization in enum_dom_groups() will need
501 * to be split out
503 *num_entries = 0;
505 return NT_STATUS_OK;
508 /* convert a single name to a sid in a domain - use rpc methods */
509 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
510 TALLOC_CTX *mem_ctx,
511 const char *domain_name,
512 const char *name,
513 uint32_t flags,
514 struct dom_sid *sid,
515 enum lsa_SidType *type)
517 return reconnect_methods.name_to_sid(domain, mem_ctx,
518 domain_name, name, flags,
519 sid, type);
522 /* convert a domain SID to a user or group name - use rpc methods */
523 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
524 TALLOC_CTX *mem_ctx,
525 const struct dom_sid *sid,
526 char **domain_name,
527 char **name,
528 enum lsa_SidType *type)
530 return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
531 domain_name, name, type);
534 /* convert a list of rids to names - use rpc methods */
535 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
536 TALLOC_CTX *mem_ctx,
537 const struct dom_sid *sid,
538 uint32 *rids,
539 size_t num_rids,
540 char **domain_name,
541 char ***names,
542 enum lsa_SidType **types)
544 return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
545 rids, num_rids,
546 domain_name, names, types);
549 /* If you are looking for "dn_lookup": Yes, it used to be here!
550 * It has gone now since it was a major speed bottleneck in
551 * lookup_groupmem (its only use). It has been replaced by
552 * an rpc lookup sids call... R.I.P. */
554 /* Lookup user information from a rid */
555 static NTSTATUS query_user(struct winbindd_domain *domain,
556 TALLOC_CTX *mem_ctx,
557 const struct dom_sid *sid,
558 struct wbint_userinfo *info)
560 ADS_STRUCT *ads = NULL;
561 const char *attrs[] = { "*", NULL };
562 ADS_STATUS rc;
563 int count;
564 LDAPMessage *msg = NULL;
565 char *ldap_exp;
566 char *sidstr;
567 uint32 group_rid;
568 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
569 struct netr_SamInfo3 *user = NULL;
570 gid_t gid = -1;
571 int ret;
572 char *ads_name;
574 DEBUG(3,("ads: query_user\n"));
576 info->homedir = NULL;
577 info->shell = NULL;
579 /* try netsamlogon cache first */
581 if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
583 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
584 sid_string_dbg(sid)));
586 sid_compose(&info->user_sid, &domain->sid, user->base.rid);
587 sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);
589 info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
590 info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
592 nss_get_info_cached( domain, sid, mem_ctx,
593 &info->homedir, &info->shell, &info->full_name,
594 &gid );
595 info->primary_gid = gid;
597 TALLOC_FREE(user);
599 return NT_STATUS_OK;
602 if ( !winbindd_can_contact_domain(domain)) {
603 DEBUG(8,("query_user: No incoming trust from domain %s\n",
604 domain->name));
606 /* We still need to generate some basic information
607 about the user even if we cannot contact the
608 domain. Most of this stuff we can deduce. */
610 sid_copy( &info->user_sid, sid );
612 /* Assume "Domain Users" for the primary group */
614 sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );
616 /* Try to fill in what the nss_info backend can do */
618 nss_get_info_cached( domain, sid, mem_ctx,
619 &info->homedir, &info->shell, &info->full_name,
620 &gid);
621 info->primary_gid = gid;
623 return NT_STATUS_OK;
626 /* no cache...do the query */
628 if ( (ads = ads_cached_connection(domain)) == NULL ) {
629 domain->last_status = NT_STATUS_SERVER_DISABLED;
630 return NT_STATUS_SERVER_DISABLED;
633 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
635 ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
636 TALLOC_FREE(sidstr);
637 if (ret == -1) {
638 return NT_STATUS_NO_MEMORY;
640 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
641 SAFE_FREE(ldap_exp);
642 if (!ADS_ERR_OK(rc)) {
643 DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
644 sid_string_dbg(sid), ads_errstr(rc)));
645 return ads_ntstatus(rc);
646 } else if (!msg) {
647 DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n",
648 sid_string_dbg(sid)));
649 return NT_STATUS_INTERNAL_ERROR;
652 count = ads_count_replies(ads, msg);
653 if (count != 1) {
654 DEBUG(1,("query_user(sid=%s): Not found\n",
655 sid_string_dbg(sid)));
656 ads_msgfree(ads, msg);
657 return NT_STATUS_NO_SUCH_USER;
660 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
662 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
663 DEBUG(1,("No primary group for %s !?\n",
664 sid_string_dbg(sid)));
665 ads_msgfree(ads, msg);
666 return NT_STATUS_NO_SUCH_USER;
668 sid_copy(&info->user_sid, sid);
669 sid_compose(&info->group_sid, &domain->sid, group_rid);
672 * We have to fetch the "name" attribute before doing the
673 * nss_get_info_cached call. nss_get_info_cached might destroy
674 * the ads struct, potentially invalidating the ldap message.
676 ads_name = ads_pull_string(ads, mem_ctx, msg, "name");
678 ads_msgfree(ads, msg);
679 msg = NULL;
681 status = nss_get_info_cached( domain, sid, mem_ctx,
682 &info->homedir, &info->shell, &info->full_name,
683 &gid);
684 info->primary_gid = gid;
685 if (!NT_STATUS_IS_OK(status)) {
686 DEBUG(1, ("nss_get_info_cached failed: %s\n",
687 nt_errstr(status)));
688 return status;
691 if (info->full_name == NULL) {
692 info->full_name = ads_name;
693 } else {
694 TALLOC_FREE(ads_name);
697 status = NT_STATUS_OK;
699 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
700 return NT_STATUS_OK;
703 /* Lookup groups a user is a member of - alternate method, for when
704 tokenGroups are not available. */
705 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
706 TALLOC_CTX *mem_ctx,
707 const char *user_dn,
708 struct dom_sid *primary_group,
709 uint32_t *p_num_groups, struct dom_sid **user_sids)
711 ADS_STATUS rc;
712 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
713 int count;
714 LDAPMessage *res = NULL;
715 LDAPMessage *msg = NULL;
716 char *ldap_exp;
717 ADS_STRUCT *ads;
718 const char *group_attrs[] = {"objectSid", NULL};
719 char *escaped_dn;
720 uint32_t num_groups = 0;
722 DEBUG(3,("ads: lookup_usergroups_member\n"));
724 if ( !winbindd_can_contact_domain( domain ) ) {
725 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
726 domain->name));
727 return NT_STATUS_OK;
730 ads = ads_cached_connection(domain);
732 if (!ads) {
733 domain->last_status = NT_STATUS_SERVER_DISABLED;
734 goto done;
737 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
738 status = NT_STATUS_NO_MEMORY;
739 goto done;
742 ldap_exp = talloc_asprintf(mem_ctx,
743 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
744 escaped_dn,
745 ADS_LDAP_MATCHING_RULE_BIT_AND,
746 GROUP_TYPE_SECURITY_ENABLED);
747 if (!ldap_exp) {
748 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
749 TALLOC_FREE(escaped_dn);
750 status = NT_STATUS_NO_MEMORY;
751 goto done;
754 TALLOC_FREE(escaped_dn);
756 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
758 if (!ADS_ERR_OK(rc)) {
759 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
760 return ads_ntstatus(rc);
761 } else if (!res) {
762 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
763 return NT_STATUS_INTERNAL_ERROR;
767 count = ads_count_replies(ads, res);
769 *user_sids = NULL;
770 num_groups = 0;
772 /* always add the primary group to the sid array */
773 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
774 &num_groups);
775 if (!NT_STATUS_IS_OK(status)) {
776 goto done;
779 if (count > 0) {
780 for (msg = ads_first_entry(ads, res); msg;
781 msg = ads_next_entry(ads, msg)) {
782 struct dom_sid group_sid;
784 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
785 DEBUG(1,("No sid for this group ?!?\n"));
786 continue;
789 /* ignore Builtin groups from ADS - Guenther */
790 if (sid_check_is_in_builtin(&group_sid)) {
791 continue;
794 status = add_sid_to_array(mem_ctx, &group_sid,
795 user_sids, &num_groups);
796 if (!NT_STATUS_IS_OK(status)) {
797 goto done;
803 *p_num_groups = num_groups;
804 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
806 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
807 done:
808 if (res)
809 ads_msgfree(ads, res);
811 return status;
814 /* Lookup groups a user is a member of - alternate method, for when
815 tokenGroups are not available. */
816 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
817 TALLOC_CTX *mem_ctx,
818 const char *user_dn,
819 struct dom_sid *primary_group,
820 uint32_t *p_num_groups,
821 struct dom_sid **user_sids)
823 ADS_STATUS rc;
824 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
825 ADS_STRUCT *ads;
826 const char *attrs[] = {"memberOf", NULL};
827 uint32_t num_groups = 0;
828 struct dom_sid *group_sids = NULL;
829 int i;
830 char **strings = NULL;
831 size_t num_strings = 0, num_sids = 0;
834 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
836 if ( !winbindd_can_contact_domain( domain ) ) {
837 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
838 "domain %s\n", domain->name));
839 return NT_STATUS_OK;
842 ads = ads_cached_connection(domain);
844 if (!ads) {
845 domain->last_status = NT_STATUS_SERVER_DISABLED;
846 return NT_STATUS_UNSUCCESSFUL;
849 rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
850 ADS_EXTENDED_DN_HEX_STRING,
851 &strings, &num_strings);
853 if (!ADS_ERR_OK(rc)) {
854 DEBUG(1,("lookup_usergroups_memberof ads_search "
855 "member=%s: %s\n", user_dn, ads_errstr(rc)));
856 return ads_ntstatus(rc);
859 *user_sids = NULL;
860 num_groups = 0;
862 /* always add the primary group to the sid array */
863 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
864 &num_groups);
865 if (!NT_STATUS_IS_OK(status)) {
866 goto done;
869 group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
870 if (!group_sids) {
871 status = NT_STATUS_NO_MEMORY;
872 goto done;
875 for (i=0; i<num_strings; i++) {
876 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
877 ADS_EXTENDED_DN_HEX_STRING,
878 &(group_sids)[i]);
879 if (!ADS_ERR_OK(rc)) {
880 /* ignore members without SIDs */
881 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
882 NT_STATUS_NOT_FOUND)) {
883 continue;
885 else {
886 status = ads_ntstatus(rc);
887 goto done;
890 num_sids++;
893 if (i == 0) {
894 DEBUG(1,("No memberOf for this user?!?\n"));
895 status = NT_STATUS_NO_MEMORY;
896 goto done;
899 for (i=0; i<num_sids; i++) {
901 /* ignore Builtin groups from ADS - Guenther */
902 if (sid_check_is_in_builtin(&group_sids[i])) {
903 continue;
906 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
907 &num_groups);
908 if (!NT_STATUS_IS_OK(status)) {
909 goto done;
914 *p_num_groups = num_groups;
915 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
917 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
918 user_dn));
920 done:
921 TALLOC_FREE(strings);
922 TALLOC_FREE(group_sids);
924 return status;
928 /* Lookup groups a user is a member of. */
929 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
930 TALLOC_CTX *mem_ctx,
931 const struct dom_sid *sid,
932 uint32 *p_num_groups, struct dom_sid **user_sids)
934 ADS_STRUCT *ads = NULL;
935 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
936 ADS_STATUS rc;
937 int count;
938 LDAPMessage *msg = NULL;
939 char *user_dn = NULL;
940 struct dom_sid *sids;
941 int i;
942 struct dom_sid primary_group;
943 uint32 primary_group_rid;
944 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
945 uint32_t num_groups = 0;
947 DEBUG(3,("ads: lookup_usergroups\n"));
948 *p_num_groups = 0;
950 status = lookup_usergroups_cached(domain, mem_ctx, sid,
951 p_num_groups, user_sids);
952 if (NT_STATUS_IS_OK(status)) {
953 return NT_STATUS_OK;
956 if ( !winbindd_can_contact_domain( domain ) ) {
957 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
958 domain->name));
960 /* Tell the cache manager not to remember this one */
962 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
965 ads = ads_cached_connection(domain);
967 if (!ads) {
968 domain->last_status = NT_STATUS_SERVER_DISABLED;
969 status = NT_STATUS_SERVER_DISABLED;
970 goto done;
973 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
975 if (!ADS_ERR_OK(rc)) {
976 status = ads_ntstatus(rc);
977 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
978 "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
979 goto done;
982 count = ads_count_replies(ads, msg);
983 if (count != 1) {
984 status = NT_STATUS_UNSUCCESSFUL;
985 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
986 "invalid number of results (count=%d)\n",
987 sid_string_dbg(sid), count));
988 goto done;
991 if (!msg) {
992 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
993 sid_string_dbg(sid)));
994 status = NT_STATUS_UNSUCCESSFUL;
995 goto done;
998 user_dn = ads_get_dn(ads, mem_ctx, msg);
999 if (user_dn == NULL) {
1000 status = NT_STATUS_NO_MEMORY;
1001 goto done;
1004 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
1005 DEBUG(1,("%s: No primary group for sid=%s !?\n",
1006 domain->name, sid_string_dbg(sid)));
1007 goto done;
1010 sid_compose(&primary_group, &domain->sid, primary_group_rid);
1012 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
1014 /* there must always be at least one group in the token,
1015 unless we are talking to a buggy Win2k server */
1017 /* actually this only happens when the machine account has no read
1018 * permissions on the tokenGroup attribute - gd */
1020 if (count == 0) {
1022 /* no tokenGroups */
1024 /* lookup what groups this user is a member of by DN search on
1025 * "memberOf" */
1027 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
1028 &primary_group,
1029 &num_groups, user_sids);
1030 *p_num_groups = num_groups;
1031 if (NT_STATUS_IS_OK(status)) {
1032 goto done;
1035 /* lookup what groups this user is a member of by DN search on
1036 * "member" */
1038 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
1039 &primary_group,
1040 &num_groups, user_sids);
1041 *p_num_groups = num_groups;
1042 goto done;
1045 *user_sids = NULL;
1046 num_groups = 0;
1048 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
1049 &num_groups);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 goto done;
1054 for (i=0;i<count;i++) {
1056 /* ignore Builtin groups from ADS - Guenther */
1057 if (sid_check_is_in_builtin(&sids[i])) {
1058 continue;
1061 status = add_sid_to_array_unique(mem_ctx, &sids[i],
1062 user_sids, &num_groups);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 goto done;
1068 *p_num_groups = (uint32)num_groups;
1069 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1071 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
1072 sid_string_dbg(sid)));
1073 done:
1074 TALLOC_FREE(user_dn);
1075 ads_msgfree(ads, msg);
1076 return status;
1079 /* Lookup aliases a user is member of - use rpc methods */
1080 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
1081 TALLOC_CTX *mem_ctx,
1082 uint32 num_sids, const struct dom_sid *sids,
1083 uint32 *num_aliases, uint32 **alias_rids)
1085 return reconnect_methods.lookup_useraliases(domain, mem_ctx,
1086 num_sids, sids,
1087 num_aliases,
1088 alias_rids);
1092 find the members of a group, given a group rid and domain
1094 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
1095 TALLOC_CTX *mem_ctx,
1096 const struct dom_sid *group_sid,
1097 enum lsa_SidType type,
1098 uint32 *num_names,
1099 struct dom_sid **sid_mem, char ***names,
1100 uint32 **name_types)
1102 ADS_STATUS rc;
1103 ADS_STRUCT *ads = NULL;
1104 char *ldap_exp;
1105 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1106 char *sidbinstr;
1107 char **members = NULL;
1108 int i;
1109 size_t num_members = 0;
1110 ads_control args;
1111 struct dom_sid *sid_mem_nocache = NULL;
1112 char **names_nocache = NULL;
1113 enum lsa_SidType *name_types_nocache = NULL;
1114 char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */
1115 uint32 num_nocache = 0;
1116 TALLOC_CTX *tmp_ctx = NULL;
1118 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1119 sid_string_dbg(group_sid)));
1121 *num_names = 0;
1123 tmp_ctx = talloc_new(mem_ctx);
1124 if (!tmp_ctx) {
1125 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1126 status = NT_STATUS_NO_MEMORY;
1127 goto done;
1130 if ( !winbindd_can_contact_domain( domain ) ) {
1131 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1132 domain->name));
1133 return NT_STATUS_OK;
1136 ads = ads_cached_connection(domain);
1138 if (!ads) {
1139 domain->last_status = NT_STATUS_SERVER_DISABLED;
1140 goto done;
1143 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1144 status = NT_STATUS_NO_MEMORY;
1145 goto done;
1148 /* search for all members of the group */
1149 ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1150 TALLOC_FREE(sidbinstr);
1151 if (ldap_exp == NULL) {
1152 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1153 status = NT_STATUS_NO_MEMORY;
1154 goto done;
1157 args.control = ADS_EXTENDED_DN_OID;
1158 args.val = ADS_EXTENDED_DN_HEX_STRING;
1159 args.critical = True;
1161 rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1162 ldap_exp, &args, "member", &members, &num_members);
1164 if (!ADS_ERR_OK(rc)) {
1165 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1166 status = NT_STATUS_UNSUCCESSFUL;
1167 goto done;
1170 DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1172 /* Now that we have a list of sids, we need to get the
1173 * lists of names and name_types belonging to these sids.
1174 * even though conceptually not quite clean, we use the
1175 * RPC call lsa_lookup_sids for this since it can handle a
1176 * list of sids. ldap calls can just resolve one sid at a time.
1178 * At this stage, the sids are still hidden in the exetended dn
1179 * member output format. We actually do a little better than
1180 * stated above: In extracting the sids from the member strings,
1181 * we try to resolve as many sids as possible from the
1182 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1184 if (num_members) {
1185 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
1186 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
1187 (*name_types) = talloc_zero_array(mem_ctx, uint32, num_members);
1188 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
1190 if ((members == NULL) || (*sid_mem == NULL) ||
1191 (*names == NULL) || (*name_types == NULL) ||
1192 (sid_mem_nocache == NULL))
1194 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1195 status = NT_STATUS_NO_MEMORY;
1196 goto done;
1199 else {
1200 (*sid_mem) = NULL;
1201 (*names) = NULL;
1202 (*name_types) = NULL;
1205 for (i=0; i<num_members; i++) {
1206 enum lsa_SidType name_type;
1207 char *name, *domain_name;
1208 struct dom_sid sid;
1210 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1211 &sid);
1212 if (!ADS_ERR_OK(rc)) {
1213 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1214 NT_STATUS_NOT_FOUND)) {
1215 /* Group members can be objects, like Exchange
1216 * Public Folders, that don't have a SID. Skip
1217 * them. */
1218 continue;
1220 else {
1221 status = ads_ntstatus(rc);
1222 goto done;
1225 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1226 &name_type)) {
1227 DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1228 "cache\n", sid_string_dbg(&sid)));
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);
1236 (*name_types)[*num_names] = name_type;
1237 (*num_names)++;
1239 else {
1240 DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1241 "cache\n", sid_string_dbg(&sid)));
1242 sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1243 num_nocache++;
1247 DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1248 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1250 /* handle sids not resolved from cache by lsa_lookup_sids */
1251 if (num_nocache > 0) {
1253 status = winbindd_lookup_sids(tmp_ctx,
1254 domain,
1255 num_nocache,
1256 sid_mem_nocache,
1257 &domains_nocache,
1258 &names_nocache,
1259 &name_types_nocache);
1261 if (!(NT_STATUS_IS_OK(status) ||
1262 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1263 NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1265 DEBUG(1, ("lsa_lookupsids call failed with %s "
1266 "- retrying...\n", nt_errstr(status)));
1268 status = winbindd_lookup_sids(tmp_ctx,
1269 domain,
1270 num_nocache,
1271 sid_mem_nocache,
1272 &domains_nocache,
1273 &names_nocache,
1274 &name_types_nocache);
1277 if (NT_STATUS_IS_OK(status) ||
1278 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
1280 /* Copy the entries over from the "_nocache" arrays
1281 * to the result arrays, skipping the gaps the
1282 * lookup_sids call left. */
1283 for (i=0; i < num_nocache; i++) {
1284 if (((names_nocache)[i] != NULL) &&
1285 ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
1287 sid_copy(&(*sid_mem)[*num_names],
1288 &sid_mem_nocache[i]);
1289 (*names)[*num_names] =
1290 fill_domain_username_talloc(
1291 *names,
1292 domains_nocache[i],
1293 names_nocache[i],
1294 true);
1295 (*name_types)[*num_names] = name_types_nocache[i];
1296 (*num_names)++;
1300 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1301 DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
1302 "not map any SIDs at all.\n"));
1303 /* Don't handle this as an error here.
1304 * There is nothing left to do with respect to the
1305 * overall result... */
1307 else if (!NT_STATUS_IS_OK(status)) {
1308 DEBUG(10, ("lookup_groupmem: Error looking up %d "
1309 "sids via rpc_lsa_lookup_sids: %s\n",
1310 (int)num_members, nt_errstr(status)));
1311 goto done;
1315 status = NT_STATUS_OK;
1316 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1317 sid_string_dbg(group_sid)));
1319 done:
1321 TALLOC_FREE(tmp_ctx);
1323 return status;
1326 /* find the sequence number for a domain */
1327 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
1329 ADS_STRUCT *ads = NULL;
1330 ADS_STATUS rc;
1332 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
1334 if ( !winbindd_can_contact_domain( domain ) ) {
1335 DEBUG(10,("sequence: No incoming trust for domain %s\n",
1336 domain->name));
1337 *seq = time(NULL);
1338 return NT_STATUS_OK;
1341 *seq = DOM_SEQUENCE_NONE;
1343 ads = ads_cached_connection(domain);
1345 if (!ads) {
1346 domain->last_status = NT_STATUS_SERVER_DISABLED;
1347 return NT_STATUS_UNSUCCESSFUL;
1350 rc = ads_USN(ads, seq);
1352 if (!ADS_ERR_OK(rc)) {
1354 /* its a dead connection, destroy it */
1356 if (domain->private_data) {
1357 ads = (ADS_STRUCT *)domain->private_data;
1358 ads->is_mine = True;
1359 ads_destroy(&ads);
1360 ads_kdestroy(WINBIND_CCACHE_NAME);
1361 domain->private_data = NULL;
1364 return ads_ntstatus(rc);
1367 /* find the lockout policy of a domain - use rpc methods */
1368 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1369 TALLOC_CTX *mem_ctx,
1370 struct samr_DomInfo12 *policy)
1372 return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
1375 /* find the password policy of a domain - use rpc methods */
1376 static NTSTATUS password_policy(struct winbindd_domain *domain,
1377 TALLOC_CTX *mem_ctx,
1378 struct samr_DomInfo1 *policy)
1380 return reconnect_methods.password_policy(domain, mem_ctx, policy);
1383 /* get a list of trusted domains */
1384 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1385 TALLOC_CTX *mem_ctx,
1386 struct netr_DomainTrustList *trusts)
1388 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1389 WERROR werr;
1390 int i;
1391 uint32 flags;
1392 struct rpc_pipe_client *cli;
1393 int ret_count;
1394 struct dcerpc_binding_handle *b;
1396 DEBUG(3,("ads: trusted_domains\n"));
1398 ZERO_STRUCTP(trusts);
1400 /* If this is our primary domain or a root in our forest,
1401 query for all trusts. If not, then just look for domain
1402 trusts in the target forest */
1404 if (domain->primary || domain_is_forest_root(domain)) {
1405 flags = NETR_TRUST_FLAG_OUTBOUND |
1406 NETR_TRUST_FLAG_INBOUND |
1407 NETR_TRUST_FLAG_IN_FOREST;
1408 } else {
1409 flags = NETR_TRUST_FLAG_IN_FOREST;
1412 result = cm_connect_netlogon(domain, &cli);
1414 if (!NT_STATUS_IS_OK(result)) {
1415 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1416 "for PIPE_NETLOGON (%s)\n",
1417 domain->name, nt_errstr(result)));
1418 return NT_STATUS_UNSUCCESSFUL;
1421 b = cli->binding_handle;
1423 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1424 cli->desthost,
1425 flags,
1426 trusts,
1427 &werr);
1428 if (!NT_STATUS_IS_OK(result)) {
1429 return result;
1432 if (!W_ERROR_IS_OK(werr)) {
1433 return werror_to_ntstatus(werr);
1435 if (trusts->count == 0) {
1436 return NT_STATUS_OK;
1439 /* Copy across names and sids */
1441 ret_count = 0;
1442 for (i = 0; i < trusts->count; i++) {
1443 struct netr_DomainTrust *trust = &trusts->array[i];
1444 struct winbindd_domain d;
1446 ZERO_STRUCT(d);
1449 * drop external trusts if this is not our primary
1450 * domain. This means that the returned number of
1451 * domains may be less that the ones actually trusted
1452 * by the DC.
1455 if ((trust->trust_attributes
1456 == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1457 !domain->primary )
1459 DEBUG(10,("trusted_domains: Skipping external trusted "
1460 "domain %s because it is outside of our "
1461 "primary domain\n",
1462 trust->netbios_name));
1463 continue;
1466 /* add to the trusted domain cache */
1468 d.name = discard_const_p(char, trust->netbios_name);
1469 d.alt_name = discard_const_p(char, trust->dns_name);
1471 if (trust->sid) {
1472 sid_copy(&d.sid, trust->sid);
1473 } else {
1474 sid_copy(&d.sid, &global_sid_NULL);
1477 if ( domain->primary ) {
1478 DEBUG(10,("trusted_domains(ads): Searching "
1479 "trusted domain list of %s and storing "
1480 "trust flags for domain %s\n",
1481 domain->name, d.alt_name));
1483 d.domain_flags = trust->trust_flags;
1484 d.domain_type = trust->trust_type;
1485 d.domain_trust_attribs = trust->trust_attributes;
1487 wcache_tdc_add_domain( &d );
1488 ret_count++;
1489 } else if (domain_is_forest_root(domain)) {
1490 /* Check if we already have this record. If
1491 * we are following our forest root that is not
1492 * our primary domain, we want to keep trust
1493 * flags from the perspective of our primary
1494 * domain not our forest root. */
1495 struct winbindd_tdc_domain *exist = NULL;
1497 exist = wcache_tdc_fetch_domain(
1498 talloc_tos(), trust->netbios_name);
1499 if (!exist) {
1500 DEBUG(10,("trusted_domains(ads): Searching "
1501 "trusted domain list of %s and "
1502 "storing trust flags for domain "
1503 "%s\n", domain->name, d.alt_name));
1504 d.domain_flags = trust->trust_flags;
1505 d.domain_type = trust->trust_type;
1506 d.domain_trust_attribs =
1507 trust->trust_attributes;
1509 wcache_tdc_add_domain( &d );
1510 ret_count++;
1512 TALLOC_FREE(exist);
1513 } else {
1514 /* This gets a little tricky. If we are
1515 following a transitive forest trust, then
1516 innerit the flags, type, and attribs from
1517 the domain we queried to make sure we don't
1518 record the view of the trust from the wrong
1519 side. Always view it from the side of our
1520 primary domain. --jerry */
1521 struct winbindd_tdc_domain *parent = NULL;
1523 DEBUG(10,("trusted_domains(ads): Searching "
1524 "trusted domain list of %s and inheriting "
1525 "trust flags for domain %s\n",
1526 domain->name, d.alt_name));
1528 parent = wcache_tdc_fetch_domain(talloc_tos(),
1529 domain->name);
1530 if (parent) {
1531 d.domain_flags = parent->trust_flags;
1532 d.domain_type = parent->trust_type;
1533 d.domain_trust_attribs = parent->trust_attribs;
1534 } else {
1535 d.domain_flags = domain->domain_flags;
1536 d.domain_type = domain->domain_type;
1537 d.domain_trust_attribs =
1538 domain->domain_trust_attribs;
1540 TALLOC_FREE(parent);
1542 wcache_tdc_add_domain( &d );
1543 ret_count++;
1546 return result;
1549 /* the ADS backend methods are exposed via this structure */
1550 struct winbindd_methods ads_methods = {
1551 True,
1552 query_user_list,
1553 enum_dom_groups,
1554 enum_local_groups,
1555 name_to_sid,
1556 sid_to_name,
1557 rids_to_names,
1558 query_user,
1559 lookup_usergroups,
1560 lookup_useraliases,
1561 lookup_groupmem,
1562 sequence_number,
1563 lockout_policy,
1564 password_policy,
1565 trusted_domains,
1568 #endif