s3-winbindd: Use correct realm for trusted domains in idmap child
[Samba.git] / source3 / winbindd / winbindd_ads.c
blob1da24624fabe948e291773d7778efcc358a4ae45
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 "../libcli/ldap/ldap_ndr.h"
31 #include "../libcli/security/security.h"
32 #include "../libds/common/flag_mapping.h"
33 #include "passdb.h"
35 #ifdef HAVE_ADS
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
40 extern struct winbindd_methods reconnect_methods;
42 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
44 /**
45 * Check if cached connection can be reused. If the connection cannot
46 * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
48 static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
51 ADS_STRUCT *ads = *adsp;
53 if (ads != NULL) {
54 time_t expire;
55 time_t now = time(NULL);
57 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
59 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
60 "is now %d)\n", (uint32)expire - (uint32)now,
61 (uint32) expire, (uint32) now));
63 if ( ads->config.realm && (expire > now)) {
64 return;
65 } else {
66 /* we own this ADS_STRUCT so make sure it goes away */
67 DEBUG(7,("Deleting expired krb5 credential cache\n"));
68 ads->is_mine = True;
69 ads_destroy( &ads );
70 ads_kdestroy(WINBIND_CCACHE_NAME);
71 *adsp = NULL;
76 static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
77 const char *dom_name_alt,
78 const char *dom_name,
79 const char *ldap_server,
80 char *password,
81 char *realm,
82 time_t renewable)
84 ADS_STRUCT *ads;
85 ADS_STATUS status;
86 struct sockaddr_storage dc_ss;
87 fstring dc_name;
89 if (realm == NULL) {
90 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
93 /* we don't want this to affect the users ccache */
94 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
96 ads = ads_init(dom_name_alt, dom_name, ldap_server);
97 if (!ads) {
98 DEBUG(1,("ads_init for domain %s failed\n", dom_name));
99 return ADS_ERROR(LDAP_NO_MEMORY);
102 SAFE_FREE(ads->auth.password);
103 SAFE_FREE(ads->auth.realm);
105 ads->auth.renewable = renewable;
106 ads->auth.password = password;
108 ads->auth.realm = SMB_STRDUP(realm);
109 if (!strupper_m(ads->auth.realm)) {
110 ads_destroy(&ads);
111 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
114 /* Setup the server affinity cache. We don't reaally care
115 about the name. Just setup affinity and the KRB5_CONFIG
116 file. */
117 get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
119 status = ads_connect(ads);
120 if (!ADS_ERR_OK(status)) {
121 DEBUG(1,("ads_connect for domain %s failed: %s\n",
122 dom_name, ads_errstr(status)));
123 ads_destroy(&ads);
124 return status;
127 /* set the flag that says we don't own the memory even
128 though we do so that ads_destroy() won't destroy the
129 structure we pass back by reference */
131 ads->is_mine = False;
133 *adsp = ads;
135 return status;
138 ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
140 char *ldap_server, *realm, *password;
141 struct winbindd_domain *wb_dom;
142 ADS_STATUS status;
144 ads_cached_connection_reuse(adsp);
145 if (*adsp != NULL) {
146 return ADS_SUCCESS;
150 * At this point we only have the NetBIOS domain name.
151 * Check if we can get server nam and realm from SAF cache
152 * and the domain list.
154 ldap_server = saf_fetch(talloc_tos(), dom_name);
155 DEBUG(10, ("ldap_server from saf cache: '%s'\n",
156 ldap_server ? ldap_server : ""));
158 wb_dom = find_domain_from_name(dom_name);
159 if (wb_dom == NULL) {
160 DEBUG(10, ("could not find domain '%s'\n", dom_name));
161 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
164 DEBUG(10, ("find_domain_from_name found realm '%s' for "
165 " domain '%s'\n", wb_dom->alt_name, dom_name));
167 if (!get_trust_pw_clear(dom_name, &password, NULL, NULL)) {
168 TALLOC_FREE(ldap_server);
169 return ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
172 if (IS_DC) {
173 realm = SMB_STRDUP(wb_dom->alt_name);
174 } else {
175 struct winbindd_domain *our_domain = wb_dom;
177 /* always give preference to the alt_name in our
178 primary domain if possible */
180 if (!wb_dom->primary) {
181 our_domain = find_our_domain();
184 if (our_domain->alt_name != NULL) {
185 realm = SMB_STRDUP(our_domain->alt_name);
186 } else {
187 realm = SMB_STRDUP(lp_realm());
191 status = ads_cached_connection_connect(
192 adsp, /* Returns ads struct. */
193 wb_dom->alt_name, /* realm to connect to. */
194 dom_name, /* 'workgroup' name for ads_init */
195 ldap_server, /* DNS name to connect to. */
196 password, /* password for auth realm. */
197 realm, /* realm used for krb5 ticket. */
198 0); /* renewable ticket time. */
200 SAFE_FREE(realm);
201 TALLOC_FREE(ldap_server);
203 return status;
207 return our ads connections structure for a domain. We keep the connection
208 open to make things faster
210 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
212 ADS_STATUS status;
213 char *password, *realm;
215 DEBUG(10,("ads_cached_connection\n"));
216 ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
218 if (domain->private_data) {
219 return (ADS_STRUCT *)domain->private_data;
222 /* the machine acct password might have change - fetch it every time */
224 if (!get_trust_pw_clear(domain->name, &password, NULL, NULL)) {
225 return NULL;
228 if ( IS_DC ) {
230 realm = SMB_STRDUP(domain->alt_name);
232 else {
233 struct winbindd_domain *our_domain = domain;
236 /* always give preference to the alt_name in our
237 primary domain if possible */
239 if ( !domain->primary )
240 our_domain = find_our_domain();
242 if (our_domain->alt_name != NULL) {
243 realm = SMB_STRDUP( our_domain->alt_name );
245 else
246 realm = SMB_STRDUP( lp_realm() );
249 status = ads_cached_connection_connect(
250 (ADS_STRUCT **)&domain->private_data,
251 domain->alt_name,
252 domain->name, NULL,
253 password, realm,
254 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
255 SAFE_FREE(realm);
257 if (!ADS_ERR_OK(status)) {
258 /* if we get ECONNREFUSED then it might be a NT4
259 server, fall back to MSRPC */
260 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
261 status.err.rc == ECONNREFUSED) {
262 /* 'reconnect_methods' is the MS-RPC backend. */
263 DEBUG(1,("Trying MSRPC methods\n"));
264 domain->backend = &reconnect_methods;
266 return NULL;
269 return (ADS_STRUCT *)domain->private_data;
272 /* Query display info for a realm. This is the basic user list fn */
273 static NTSTATUS query_user_list(struct winbindd_domain *domain,
274 TALLOC_CTX *mem_ctx,
275 uint32 *num_entries,
276 struct wbint_userinfo **pinfo)
278 ADS_STRUCT *ads = NULL;
279 const char *attrs[] = { "*", NULL };
280 int i, count;
281 ADS_STATUS rc;
282 LDAPMessage *res = NULL;
283 LDAPMessage *msg = NULL;
284 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
286 *num_entries = 0;
288 DEBUG(3,("ads: query_user_list\n"));
290 if ( !winbindd_can_contact_domain( domain ) ) {
291 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
292 domain->name));
293 return NT_STATUS_OK;
296 ads = ads_cached_connection(domain);
298 if (!ads) {
299 domain->last_status = NT_STATUS_SERVER_DISABLED;
300 goto done;
303 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
304 if (!ADS_ERR_OK(rc)) {
305 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
306 status = ads_ntstatus(rc);
307 goto done;
308 } else if (!res) {
309 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
310 goto done;
313 count = ads_count_replies(ads, res);
314 if (count == 0) {
315 DEBUG(1,("query_user_list: No users found\n"));
316 goto done;
319 (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
320 if (!*pinfo) {
321 status = NT_STATUS_NO_MEMORY;
322 goto done;
325 count = 0;
327 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
328 struct wbint_userinfo *info = &((*pinfo)[count]);
329 uint32 group;
330 uint32 atype;
332 if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
333 ds_atype_map(atype) != SID_NAME_USER) {
334 DEBUG(1,("Not a user account? atype=0x%x\n", atype));
335 continue;
338 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
339 info->full_name = ads_pull_string(ads, mem_ctx, msg, "displayName");
340 if (info->full_name == NULL) {
341 info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
343 info->homedir = NULL;
344 info->shell = NULL;
345 info->primary_gid = (gid_t)-1;
347 if (!ads_pull_sid(ads, msg, "objectSid",
348 &info->user_sid)) {
349 DEBUG(1, ("No sid for %s !?\n", info->acct_name));
350 continue;
353 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
354 DEBUG(1, ("No primary group for %s !?\n",
355 info->acct_name));
356 continue;
358 sid_compose(&info->group_sid, &domain->sid, group);
360 count += 1;
363 (*num_entries) = count;
364 ads_msgfree(ads, res);
366 for (i=0; i<count; i++) {
367 struct wbint_userinfo *info = &((*pinfo)[i]);
368 const char *gecos = NULL;
369 gid_t primary_gid = (gid_t)-1;
371 status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
372 &info->homedir, &info->shell,
373 &gecos, &primary_gid);
374 if (!NT_STATUS_IS_OK(status)) {
376 * Deliberately ignore this error, there might be more
377 * users to fill
379 continue;
382 if (gecos != NULL) {
383 info->full_name = gecos;
385 info->primary_gid = primary_gid;
388 status = NT_STATUS_OK;
390 DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
392 done:
393 return status;
396 /* list all domain groups */
397 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
398 TALLOC_CTX *mem_ctx,
399 uint32 *num_entries,
400 struct wb_acct_info **info)
402 ADS_STRUCT *ads = NULL;
403 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
404 "name", "objectSid", NULL};
405 int i, count;
406 ADS_STATUS rc;
407 LDAPMessage *res = NULL;
408 LDAPMessage *msg = NULL;
409 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
410 const char *filter;
411 bool enum_dom_local_groups = False;
413 *num_entries = 0;
415 DEBUG(3,("ads: enum_dom_groups\n"));
417 if ( !winbindd_can_contact_domain( domain ) ) {
418 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
419 domain->name));
420 return NT_STATUS_OK;
423 /* only grab domain local groups for our domain */
424 if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
425 enum_dom_local_groups = True;
428 /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
429 * rollup-fixes:
431 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
432 * default value, it MUST be absent. In case of extensible matching the
433 * "dnattr" boolean defaults to FALSE and so it must be only be present
434 * when set to TRUE.
436 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
437 * filter using bitwise matching rule then the buggy AD fails to decode
438 * the extensible match. As a workaround set it to TRUE and thereby add
439 * the dnAttributes "dn" field to cope with those older AD versions.
440 * It should not harm and won't put any additional load on the AD since
441 * none of the dn components have a bitmask-attribute.
443 * Thanks to Ralf Haferkamp for input and testing - Guenther */
445 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
446 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
447 ADS_LDAP_MATCHING_RULE_BIT_AND,
448 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
450 if (filter == NULL) {
451 status = NT_STATUS_NO_MEMORY;
452 goto done;
455 ads = ads_cached_connection(domain);
457 if (!ads) {
458 domain->last_status = NT_STATUS_SERVER_DISABLED;
459 goto done;
462 rc = ads_search_retry(ads, &res, filter, attrs);
463 if (!ADS_ERR_OK(rc)) {
464 status = ads_ntstatus(rc);
465 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
466 goto done;
467 } else if (!res) {
468 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
469 goto done;
472 count = ads_count_replies(ads, res);
473 if (count == 0) {
474 DEBUG(1,("enum_dom_groups: No groups found\n"));
475 goto done;
478 (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
479 if (!*info) {
480 status = NT_STATUS_NO_MEMORY;
481 goto done;
484 i = 0;
486 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
487 char *name, *gecos;
488 struct dom_sid sid;
489 uint32 rid;
491 name = ads_pull_username(ads, mem_ctx, msg);
492 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
493 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
494 DEBUG(1,("No sid for %s !?\n", name));
495 continue;
498 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
499 DEBUG(1,("No rid for %s !?\n", name));
500 continue;
503 fstrcpy((*info)[i].acct_name, name);
504 fstrcpy((*info)[i].acct_desc, gecos);
505 (*info)[i].rid = rid;
506 i++;
509 (*num_entries) = i;
511 status = NT_STATUS_OK;
513 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
515 done:
516 if (res)
517 ads_msgfree(ads, res);
519 return status;
522 /* list all domain local groups */
523 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
524 TALLOC_CTX *mem_ctx,
525 uint32 *num_entries,
526 struct wb_acct_info **info)
529 * This is a stub function only as we returned the domain
530 * local groups in enum_dom_groups() if the domain->native field
531 * was true. This is a simple performance optimization when
532 * using LDAP.
534 * if we ever need to enumerate domain local groups separately,
535 * then this optimization in enum_dom_groups() will need
536 * to be split out
538 *num_entries = 0;
540 return NT_STATUS_OK;
543 /* convert a single name to a sid in a domain - use rpc methods */
544 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
545 TALLOC_CTX *mem_ctx,
546 const char *domain_name,
547 const char *name,
548 uint32_t flags,
549 struct dom_sid *sid,
550 enum lsa_SidType *type)
552 return reconnect_methods.name_to_sid(domain, mem_ctx,
553 domain_name, name, flags,
554 sid, type);
557 /* convert a domain SID to a user or group name - use rpc methods */
558 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
559 TALLOC_CTX *mem_ctx,
560 const struct dom_sid *sid,
561 char **domain_name,
562 char **name,
563 enum lsa_SidType *type)
565 return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
566 domain_name, name, type);
569 /* convert a list of rids to names - use rpc methods */
570 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
571 TALLOC_CTX *mem_ctx,
572 const struct dom_sid *sid,
573 uint32 *rids,
574 size_t num_rids,
575 char **domain_name,
576 char ***names,
577 enum lsa_SidType **types)
579 return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
580 rids, num_rids,
581 domain_name, names, types);
584 /* If you are looking for "dn_lookup": Yes, it used to be here!
585 * It has gone now since it was a major speed bottleneck in
586 * lookup_groupmem (its only use). It has been replaced by
587 * an rpc lookup sids call... R.I.P. */
589 /* Lookup user information from a rid */
590 static NTSTATUS query_user(struct winbindd_domain *domain,
591 TALLOC_CTX *mem_ctx,
592 const struct dom_sid *sid,
593 struct wbint_userinfo *info)
595 ADS_STRUCT *ads = NULL;
596 const char *attrs[] = { "*", NULL };
597 ADS_STATUS rc;
598 int count;
599 LDAPMessage *msg = NULL;
600 char *ldap_exp;
601 char *sidstr;
602 uint32 group_rid;
603 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
604 struct netr_SamInfo3 *user = NULL;
605 gid_t gid = -1;
606 int ret;
607 char *full_name;
609 DEBUG(3,("ads: query_user\n"));
611 info->homedir = NULL;
612 info->shell = NULL;
614 /* try netsamlogon cache first */
616 if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
618 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
619 sid_string_dbg(sid)));
621 sid_compose(&info->user_sid, &domain->sid, user->base.rid);
622 sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);
624 info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
625 info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
627 nss_get_info_cached( domain, sid, mem_ctx,
628 &info->homedir, &info->shell, &info->full_name,
629 &gid );
630 info->primary_gid = gid;
632 TALLOC_FREE(user);
634 if (info->full_name == NULL) {
635 /* this might fail so we dont check the return code */
636 wcache_query_user_fullname(domain,
637 mem_ctx,
638 sid,
639 &info->full_name);
642 return NT_STATUS_OK;
645 if ( !winbindd_can_contact_domain(domain)) {
646 DEBUG(8,("query_user: No incoming trust from domain %s\n",
647 domain->name));
649 /* We still need to generate some basic information
650 about the user even if we cannot contact the
651 domain. Most of this stuff we can deduce. */
653 sid_copy( &info->user_sid, sid );
655 /* Assume "Domain Users" for the primary group */
657 sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );
659 /* Try to fill in what the nss_info backend can do */
661 nss_get_info_cached( domain, sid, mem_ctx,
662 &info->homedir, &info->shell, &info->full_name,
663 &gid);
664 info->primary_gid = gid;
666 return NT_STATUS_OK;
669 /* no cache...do the query */
671 if ( (ads = ads_cached_connection(domain)) == NULL ) {
672 domain->last_status = NT_STATUS_SERVER_DISABLED;
673 return NT_STATUS_SERVER_DISABLED;
676 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
678 ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
679 TALLOC_FREE(sidstr);
680 if (ret == -1) {
681 return NT_STATUS_NO_MEMORY;
683 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
684 SAFE_FREE(ldap_exp);
685 if (!ADS_ERR_OK(rc)) {
686 DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
687 sid_string_dbg(sid), ads_errstr(rc)));
688 return ads_ntstatus(rc);
689 } else if (!msg) {
690 DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n",
691 sid_string_dbg(sid)));
692 return NT_STATUS_INTERNAL_ERROR;
695 count = ads_count_replies(ads, msg);
696 if (count != 1) {
697 DEBUG(1,("query_user(sid=%s): Not found\n",
698 sid_string_dbg(sid)));
699 ads_msgfree(ads, msg);
700 return NT_STATUS_NO_SUCH_USER;
703 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
705 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
706 DEBUG(1,("No primary group for %s !?\n",
707 sid_string_dbg(sid)));
708 ads_msgfree(ads, msg);
709 return NT_STATUS_NO_SUCH_USER;
711 sid_copy(&info->user_sid, sid);
712 sid_compose(&info->group_sid, &domain->sid, group_rid);
715 * We have to fetch the "name" attribute before doing the
716 * nss_get_info_cached call. nss_get_info_cached might destroy
717 * the ads struct, potentially invalidating the ldap message.
719 full_name = ads_pull_string(ads, mem_ctx, msg, "displayName");
720 if (full_name == NULL) {
721 full_name = ads_pull_string(ads, mem_ctx, msg, "name");
724 ads_msgfree(ads, msg);
725 msg = NULL;
727 status = nss_get_info_cached( domain, sid, mem_ctx,
728 &info->homedir, &info->shell, &info->full_name,
729 &gid);
730 info->primary_gid = gid;
731 if (!NT_STATUS_IS_OK(status)) {
732 DEBUG(1, ("nss_get_info_cached failed: %s\n",
733 nt_errstr(status)));
734 return status;
737 if (info->full_name == NULL) {
738 info->full_name = full_name;
739 } else {
740 TALLOC_FREE(full_name);
743 status = NT_STATUS_OK;
745 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
746 return NT_STATUS_OK;
749 /* Lookup groups a user is a member of - alternate method, for when
750 tokenGroups are not available. */
751 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
752 TALLOC_CTX *mem_ctx,
753 const char *user_dn,
754 struct dom_sid *primary_group,
755 uint32_t *p_num_groups, struct dom_sid **user_sids)
757 ADS_STATUS rc;
758 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
759 int count;
760 LDAPMessage *res = NULL;
761 LDAPMessage *msg = NULL;
762 char *ldap_exp;
763 ADS_STRUCT *ads;
764 const char *group_attrs[] = {"objectSid", NULL};
765 char *escaped_dn;
766 uint32_t num_groups = 0;
768 DEBUG(3,("ads: lookup_usergroups_member\n"));
770 if ( !winbindd_can_contact_domain( domain ) ) {
771 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
772 domain->name));
773 return NT_STATUS_OK;
776 ads = ads_cached_connection(domain);
778 if (!ads) {
779 domain->last_status = NT_STATUS_SERVER_DISABLED;
780 goto done;
783 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
784 status = NT_STATUS_NO_MEMORY;
785 goto done;
788 ldap_exp = talloc_asprintf(mem_ctx,
789 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
790 escaped_dn,
791 ADS_LDAP_MATCHING_RULE_BIT_AND,
792 GROUP_TYPE_SECURITY_ENABLED);
793 if (!ldap_exp) {
794 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
795 TALLOC_FREE(escaped_dn);
796 status = NT_STATUS_NO_MEMORY;
797 goto done;
800 TALLOC_FREE(escaped_dn);
802 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
804 if (!ADS_ERR_OK(rc)) {
805 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
806 return ads_ntstatus(rc);
807 } else if (!res) {
808 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
809 return NT_STATUS_INTERNAL_ERROR;
813 count = ads_count_replies(ads, res);
815 *user_sids = NULL;
816 num_groups = 0;
818 /* always add the primary group to the sid array */
819 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
820 &num_groups);
821 if (!NT_STATUS_IS_OK(status)) {
822 goto done;
825 if (count > 0) {
826 for (msg = ads_first_entry(ads, res); msg;
827 msg = ads_next_entry(ads, msg)) {
828 struct dom_sid group_sid;
830 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
831 DEBUG(1,("No sid for this group ?!?\n"));
832 continue;
835 /* ignore Builtin groups from ADS - Guenther */
836 if (sid_check_is_in_builtin(&group_sid)) {
837 continue;
840 status = add_sid_to_array(mem_ctx, &group_sid,
841 user_sids, &num_groups);
842 if (!NT_STATUS_IS_OK(status)) {
843 goto done;
849 *p_num_groups = num_groups;
850 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
852 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
853 done:
854 if (res)
855 ads_msgfree(ads, res);
857 return status;
860 /* Lookup groups a user is a member of - alternate method, for when
861 tokenGroups are not available. */
862 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
863 TALLOC_CTX *mem_ctx,
864 const char *user_dn,
865 struct dom_sid *primary_group,
866 uint32_t *p_num_groups,
867 struct dom_sid **user_sids)
869 ADS_STATUS rc;
870 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
871 ADS_STRUCT *ads;
872 const char *attrs[] = {"memberOf", NULL};
873 uint32_t num_groups = 0;
874 struct dom_sid *group_sids = NULL;
875 int i;
876 char **strings = NULL;
877 size_t num_strings = 0, num_sids = 0;
880 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
882 if ( !winbindd_can_contact_domain( domain ) ) {
883 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
884 "domain %s\n", domain->name));
885 return NT_STATUS_OK;
888 ads = ads_cached_connection(domain);
890 if (!ads) {
891 domain->last_status = NT_STATUS_SERVER_DISABLED;
892 return NT_STATUS_UNSUCCESSFUL;
895 rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
896 ADS_EXTENDED_DN_HEX_STRING,
897 &strings, &num_strings);
899 if (!ADS_ERR_OK(rc)) {
900 DEBUG(1,("lookup_usergroups_memberof ads_search "
901 "member=%s: %s\n", user_dn, ads_errstr(rc)));
902 return ads_ntstatus(rc);
905 *user_sids = NULL;
906 num_groups = 0;
908 /* always add the primary group to the sid array */
909 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
910 &num_groups);
911 if (!NT_STATUS_IS_OK(status)) {
912 goto done;
915 group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
916 if (!group_sids) {
917 status = NT_STATUS_NO_MEMORY;
918 goto done;
921 for (i=0; i<num_strings; i++) {
922 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
923 ADS_EXTENDED_DN_HEX_STRING,
924 &(group_sids)[i]);
925 if (!ADS_ERR_OK(rc)) {
926 /* ignore members without SIDs */
927 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
928 NT_STATUS_NOT_FOUND)) {
929 continue;
931 else {
932 status = ads_ntstatus(rc);
933 goto done;
936 num_sids++;
939 if (i == 0) {
940 DEBUG(1,("No memberOf for this user?!?\n"));
941 status = NT_STATUS_NO_MEMORY;
942 goto done;
945 for (i=0; i<num_sids; i++) {
947 /* ignore Builtin groups from ADS - Guenther */
948 if (sid_check_is_in_builtin(&group_sids[i])) {
949 continue;
952 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
953 &num_groups);
954 if (!NT_STATUS_IS_OK(status)) {
955 goto done;
960 *p_num_groups = num_groups;
961 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
963 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
964 user_dn));
966 done:
967 TALLOC_FREE(strings);
968 TALLOC_FREE(group_sids);
970 return status;
974 /* Lookup groups a user is a member of. */
975 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
976 TALLOC_CTX *mem_ctx,
977 const struct dom_sid *sid,
978 uint32 *p_num_groups, struct dom_sid **user_sids)
980 ADS_STRUCT *ads = NULL;
981 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
982 ADS_STATUS rc;
983 int count;
984 LDAPMessage *msg = NULL;
985 char *user_dn = NULL;
986 struct dom_sid *sids;
987 int i;
988 struct dom_sid primary_group;
989 uint32 primary_group_rid;
990 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
991 uint32_t num_groups = 0;
993 DEBUG(3,("ads: lookup_usergroups\n"));
994 *p_num_groups = 0;
996 status = lookup_usergroups_cached(domain, mem_ctx, sid,
997 p_num_groups, user_sids);
998 if (NT_STATUS_IS_OK(status)) {
999 return NT_STATUS_OK;
1002 if ( !winbindd_can_contact_domain( domain ) ) {
1003 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
1004 domain->name));
1006 /* Tell the cache manager not to remember this one */
1008 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
1011 ads = ads_cached_connection(domain);
1013 if (!ads) {
1014 domain->last_status = NT_STATUS_SERVER_DISABLED;
1015 status = NT_STATUS_SERVER_DISABLED;
1016 goto done;
1019 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
1021 if (!ADS_ERR_OK(rc)) {
1022 status = ads_ntstatus(rc);
1023 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
1024 "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
1025 goto done;
1028 count = ads_count_replies(ads, msg);
1029 if (count != 1) {
1030 status = NT_STATUS_UNSUCCESSFUL;
1031 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
1032 "invalid number of results (count=%d)\n",
1033 sid_string_dbg(sid), count));
1034 goto done;
1037 if (!msg) {
1038 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
1039 sid_string_dbg(sid)));
1040 status = NT_STATUS_UNSUCCESSFUL;
1041 goto done;
1044 user_dn = ads_get_dn(ads, mem_ctx, msg);
1045 if (user_dn == NULL) {
1046 status = NT_STATUS_NO_MEMORY;
1047 goto done;
1050 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
1051 DEBUG(1,("%s: No primary group for sid=%s !?\n",
1052 domain->name, sid_string_dbg(sid)));
1053 goto done;
1056 sid_compose(&primary_group, &domain->sid, primary_group_rid);
1058 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
1060 /* there must always be at least one group in the token,
1061 unless we are talking to a buggy Win2k server */
1063 /* actually this only happens when the machine account has no read
1064 * permissions on the tokenGroup attribute - gd */
1066 if (count == 0) {
1068 /* no tokenGroups */
1070 /* lookup what groups this user is a member of by DN search on
1071 * "memberOf" */
1073 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
1074 &primary_group,
1075 &num_groups, user_sids);
1076 *p_num_groups = num_groups;
1077 if (NT_STATUS_IS_OK(status)) {
1078 goto done;
1081 /* lookup what groups this user is a member of by DN search on
1082 * "member" */
1084 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
1085 &primary_group,
1086 &num_groups, user_sids);
1087 *p_num_groups = num_groups;
1088 goto done;
1091 *user_sids = NULL;
1092 num_groups = 0;
1094 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
1095 &num_groups);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 goto done;
1100 for (i=0;i<count;i++) {
1102 /* ignore Builtin groups from ADS - Guenther */
1103 if (sid_check_is_in_builtin(&sids[i])) {
1104 continue;
1107 status = add_sid_to_array_unique(mem_ctx, &sids[i],
1108 user_sids, &num_groups);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 goto done;
1114 *p_num_groups = (uint32)num_groups;
1115 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1117 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
1118 sid_string_dbg(sid)));
1119 done:
1120 TALLOC_FREE(user_dn);
1121 ads_msgfree(ads, msg);
1122 return status;
1125 /* Lookup aliases a user is member of - use rpc methods */
1126 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
1127 TALLOC_CTX *mem_ctx,
1128 uint32 num_sids, const struct dom_sid *sids,
1129 uint32 *num_aliases, uint32 **alias_rids)
1131 return reconnect_methods.lookup_useraliases(domain, mem_ctx,
1132 num_sids, sids,
1133 num_aliases,
1134 alias_rids);
1138 find the members of a group, given a group rid and domain
1140 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
1141 TALLOC_CTX *mem_ctx,
1142 const struct dom_sid *group_sid,
1143 enum lsa_SidType type,
1144 uint32 *num_names,
1145 struct dom_sid **sid_mem, char ***names,
1146 uint32 **name_types)
1148 ADS_STATUS rc;
1149 ADS_STRUCT *ads = NULL;
1150 char *ldap_exp;
1151 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1152 char *sidbinstr;
1153 char **members = NULL;
1154 int i;
1155 size_t num_members = 0;
1156 ads_control args;
1157 struct dom_sid *sid_mem_nocache = NULL;
1158 char **names_nocache = NULL;
1159 enum lsa_SidType *name_types_nocache = NULL;
1160 char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */
1161 uint32 num_nocache = 0;
1162 TALLOC_CTX *tmp_ctx = NULL;
1164 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1165 sid_string_dbg(group_sid)));
1167 *num_names = 0;
1169 tmp_ctx = talloc_new(mem_ctx);
1170 if (!tmp_ctx) {
1171 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1172 status = NT_STATUS_NO_MEMORY;
1173 goto done;
1176 if ( !winbindd_can_contact_domain( domain ) ) {
1177 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1178 domain->name));
1179 return NT_STATUS_OK;
1182 ads = ads_cached_connection(domain);
1184 if (!ads) {
1185 domain->last_status = NT_STATUS_SERVER_DISABLED;
1186 goto done;
1189 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1190 status = NT_STATUS_NO_MEMORY;
1191 goto done;
1194 /* search for all members of the group */
1195 ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1196 TALLOC_FREE(sidbinstr);
1197 if (ldap_exp == NULL) {
1198 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1199 status = NT_STATUS_NO_MEMORY;
1200 goto done;
1203 args.control = ADS_EXTENDED_DN_OID;
1204 args.val = ADS_EXTENDED_DN_HEX_STRING;
1205 args.critical = True;
1207 rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1208 ldap_exp, &args, "member", &members, &num_members);
1210 if (!ADS_ERR_OK(rc)) {
1211 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1212 status = NT_STATUS_UNSUCCESSFUL;
1213 goto done;
1216 DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1218 /* Now that we have a list of sids, we need to get the
1219 * lists of names and name_types belonging to these sids.
1220 * even though conceptually not quite clean, we use the
1221 * RPC call lsa_lookup_sids for this since it can handle a
1222 * list of sids. ldap calls can just resolve one sid at a time.
1224 * At this stage, the sids are still hidden in the exetended dn
1225 * member output format. We actually do a little better than
1226 * stated above: In extracting the sids from the member strings,
1227 * we try to resolve as many sids as possible from the
1228 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1230 if (num_members) {
1231 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
1232 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
1233 (*name_types) = talloc_zero_array(mem_ctx, uint32, num_members);
1234 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
1236 if ((members == NULL) || (*sid_mem == NULL) ||
1237 (*names == NULL) || (*name_types == NULL) ||
1238 (sid_mem_nocache == NULL))
1240 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1241 status = NT_STATUS_NO_MEMORY;
1242 goto done;
1245 else {
1246 (*sid_mem) = NULL;
1247 (*names) = NULL;
1248 (*name_types) = NULL;
1251 for (i=0; i<num_members; i++) {
1252 enum lsa_SidType name_type;
1253 char *name, *domain_name;
1254 struct dom_sid sid;
1256 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1257 &sid);
1258 if (!ADS_ERR_OK(rc)) {
1259 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1260 NT_STATUS_NOT_FOUND)) {
1261 /* Group members can be objects, like Exchange
1262 * Public Folders, that don't have a SID. Skip
1263 * them. */
1264 continue;
1266 else {
1267 status = ads_ntstatus(rc);
1268 goto done;
1271 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1272 &name_type)) {
1273 DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1274 "cache\n", sid_string_dbg(&sid)));
1275 sid_copy(&(*sid_mem)[*num_names], &sid);
1276 (*names)[*num_names] = fill_domain_username_talloc(
1277 *names,
1278 domain_name,
1279 name,
1280 true);
1282 (*name_types)[*num_names] = name_type;
1283 (*num_names)++;
1285 else {
1286 DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1287 "cache\n", sid_string_dbg(&sid)));
1288 sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1289 num_nocache++;
1293 DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1294 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1296 /* handle sids not resolved from cache by lsa_lookup_sids */
1297 if (num_nocache > 0) {
1299 status = winbindd_lookup_sids(tmp_ctx,
1300 domain,
1301 num_nocache,
1302 sid_mem_nocache,
1303 &domains_nocache,
1304 &names_nocache,
1305 &name_types_nocache);
1307 if (!(NT_STATUS_IS_OK(status) ||
1308 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1309 NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1311 DEBUG(1, ("lsa_lookupsids call failed with %s "
1312 "- retrying...\n", nt_errstr(status)));
1314 status = winbindd_lookup_sids(tmp_ctx,
1315 domain,
1316 num_nocache,
1317 sid_mem_nocache,
1318 &domains_nocache,
1319 &names_nocache,
1320 &name_types_nocache);
1323 if (NT_STATUS_IS_OK(status) ||
1324 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
1326 /* Copy the entries over from the "_nocache" arrays
1327 * to the result arrays, skipping the gaps the
1328 * lookup_sids call left. */
1329 for (i=0; i < num_nocache; i++) {
1330 if (((names_nocache)[i] != NULL) &&
1331 ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
1333 sid_copy(&(*sid_mem)[*num_names],
1334 &sid_mem_nocache[i]);
1335 (*names)[*num_names] =
1336 fill_domain_username_talloc(
1337 *names,
1338 domains_nocache[i],
1339 names_nocache[i],
1340 true);
1341 (*name_types)[*num_names] = name_types_nocache[i];
1342 (*num_names)++;
1346 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1347 DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
1348 "not map any SIDs at all.\n"));
1349 /* Don't handle this as an error here.
1350 * There is nothing left to do with respect to the
1351 * overall result... */
1353 else if (!NT_STATUS_IS_OK(status)) {
1354 DEBUG(10, ("lookup_groupmem: Error looking up %d "
1355 "sids via rpc_lsa_lookup_sids: %s\n",
1356 (int)num_members, nt_errstr(status)));
1357 goto done;
1361 status = NT_STATUS_OK;
1362 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1363 sid_string_dbg(group_sid)));
1365 done:
1367 TALLOC_FREE(tmp_ctx);
1369 return status;
1372 /* find the sequence number for a domain */
1373 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
1375 ADS_STRUCT *ads = NULL;
1376 ADS_STATUS rc;
1378 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
1380 if ( !winbindd_can_contact_domain( domain ) ) {
1381 DEBUG(10,("sequence: No incoming trust for domain %s\n",
1382 domain->name));
1383 *seq = time(NULL);
1384 return NT_STATUS_OK;
1387 *seq = DOM_SEQUENCE_NONE;
1389 ads = ads_cached_connection(domain);
1391 if (!ads) {
1392 domain->last_status = NT_STATUS_SERVER_DISABLED;
1393 return NT_STATUS_UNSUCCESSFUL;
1396 rc = ads_USN(ads, seq);
1398 if (!ADS_ERR_OK(rc)) {
1400 /* its a dead connection, destroy it */
1402 if (domain->private_data) {
1403 ads = (ADS_STRUCT *)domain->private_data;
1404 ads->is_mine = True;
1405 ads_destroy(&ads);
1406 ads_kdestroy(WINBIND_CCACHE_NAME);
1407 domain->private_data = NULL;
1410 return ads_ntstatus(rc);
1413 /* find the lockout policy of a domain - use rpc methods */
1414 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1415 TALLOC_CTX *mem_ctx,
1416 struct samr_DomInfo12 *policy)
1418 return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
1421 /* find the password policy of a domain - use rpc methods */
1422 static NTSTATUS password_policy(struct winbindd_domain *domain,
1423 TALLOC_CTX *mem_ctx,
1424 struct samr_DomInfo1 *policy)
1426 return reconnect_methods.password_policy(domain, mem_ctx, policy);
1429 /* get a list of trusted domains */
1430 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1431 TALLOC_CTX *mem_ctx,
1432 struct netr_DomainTrustList *trusts)
1434 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1435 WERROR werr;
1436 int i;
1437 uint32 flags;
1438 struct rpc_pipe_client *cli;
1439 int ret_count;
1440 struct dcerpc_binding_handle *b;
1442 DEBUG(3,("ads: trusted_domains\n"));
1444 ZERO_STRUCTP(trusts);
1446 /* If this is our primary domain or a root in our forest,
1447 query for all trusts. If not, then just look for domain
1448 trusts in the target forest */
1450 if (domain->primary || domain_is_forest_root(domain)) {
1451 flags = NETR_TRUST_FLAG_OUTBOUND |
1452 NETR_TRUST_FLAG_INBOUND |
1453 NETR_TRUST_FLAG_IN_FOREST;
1454 } else {
1455 flags = NETR_TRUST_FLAG_IN_FOREST;
1458 result = cm_connect_netlogon(domain, &cli);
1460 if (!NT_STATUS_IS_OK(result)) {
1461 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1462 "for PIPE_NETLOGON (%s)\n",
1463 domain->name, nt_errstr(result)));
1464 return NT_STATUS_UNSUCCESSFUL;
1467 b = cli->binding_handle;
1469 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1470 cli->desthost,
1471 flags,
1472 trusts,
1473 &werr);
1474 if (!NT_STATUS_IS_OK(result)) {
1475 return result;
1478 if (!W_ERROR_IS_OK(werr)) {
1479 return werror_to_ntstatus(werr);
1481 if (trusts->count == 0) {
1482 return NT_STATUS_OK;
1485 /* Copy across names and sids */
1487 ret_count = 0;
1488 for (i = 0; i < trusts->count; i++) {
1489 struct netr_DomainTrust *trust = &trusts->array[i];
1490 struct winbindd_domain d;
1492 ZERO_STRUCT(d);
1495 * drop external trusts if this is not our primary
1496 * domain. This means that the returned number of
1497 * domains may be less that the ones actually trusted
1498 * by the DC.
1501 if ((trust->trust_attributes
1502 == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1503 !domain->primary )
1505 DEBUG(10,("trusted_domains: Skipping external trusted "
1506 "domain %s because it is outside of our "
1507 "primary domain\n",
1508 trust->netbios_name));
1509 continue;
1512 /* add to the trusted domain cache */
1514 d.name = discard_const_p(char, trust->netbios_name);
1515 d.alt_name = discard_const_p(char, trust->dns_name);
1517 if (trust->sid) {
1518 sid_copy(&d.sid, trust->sid);
1519 } else {
1520 sid_copy(&d.sid, &global_sid_NULL);
1523 if ( domain->primary ) {
1524 DEBUG(10,("trusted_domains(ads): Searching "
1525 "trusted domain list of %s and storing "
1526 "trust flags for domain %s\n",
1527 domain->name, d.alt_name));
1529 d.domain_flags = trust->trust_flags;
1530 d.domain_type = trust->trust_type;
1531 d.domain_trust_attribs = trust->trust_attributes;
1533 wcache_tdc_add_domain( &d );
1534 ret_count++;
1535 } else if (domain_is_forest_root(domain)) {
1536 /* Check if we already have this record. If
1537 * we are following our forest root that is not
1538 * our primary domain, we want to keep trust
1539 * flags from the perspective of our primary
1540 * domain not our forest root. */
1541 struct winbindd_tdc_domain *exist = NULL;
1543 exist = wcache_tdc_fetch_domain(
1544 talloc_tos(), trust->netbios_name);
1545 if (!exist) {
1546 DEBUG(10,("trusted_domains(ads): Searching "
1547 "trusted domain list of %s and "
1548 "storing trust flags for domain "
1549 "%s\n", domain->name, d.alt_name));
1550 d.domain_flags = trust->trust_flags;
1551 d.domain_type = trust->trust_type;
1552 d.domain_trust_attribs =
1553 trust->trust_attributes;
1555 wcache_tdc_add_domain( &d );
1556 ret_count++;
1558 TALLOC_FREE(exist);
1559 } else {
1560 /* This gets a little tricky. If we are
1561 following a transitive forest trust, then
1562 innerit the flags, type, and attribs from
1563 the domain we queried to make sure we don't
1564 record the view of the trust from the wrong
1565 side. Always view it from the side of our
1566 primary domain. --jerry */
1567 struct winbindd_tdc_domain *parent = NULL;
1569 DEBUG(10,("trusted_domains(ads): Searching "
1570 "trusted domain list of %s and inheriting "
1571 "trust flags for domain %s\n",
1572 domain->name, d.alt_name));
1574 parent = wcache_tdc_fetch_domain(talloc_tos(),
1575 domain->name);
1576 if (parent) {
1577 d.domain_flags = parent->trust_flags;
1578 d.domain_type = parent->trust_type;
1579 d.domain_trust_attribs = parent->trust_attribs;
1580 } else {
1581 d.domain_flags = domain->domain_flags;
1582 d.domain_type = domain->domain_type;
1583 d.domain_trust_attribs =
1584 domain->domain_trust_attribs;
1586 TALLOC_FREE(parent);
1588 wcache_tdc_add_domain( &d );
1589 ret_count++;
1592 return result;
1595 /* the ADS backend methods are exposed via this structure */
1596 struct winbindd_methods ads_methods = {
1597 True,
1598 query_user_list,
1599 enum_dom_groups,
1600 enum_local_groups,
1601 name_to_sid,
1602 sid_to_name,
1603 rids_to_names,
1604 query_user,
1605 lookup_usergroups,
1606 lookup_useraliases,
1607 lookup_groupmem,
1608 sequence_number,
1609 lockout_policy,
1610 password_policy,
1611 trusted_domains,
1614 #endif