librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_ads.c
blob1e45ad9e8518eb963ee3c4a9f3e0615ae5b818e5
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;
104 ads->auth.realm = realm;
106 ads->auth.realm = SMB_STRDUP(realm);
107 if (!strupper_m(ads->auth.realm)) {
108 ads_destroy(&ads);
109 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
112 /* Setup the server affinity cache. We don't reaally care
113 about the name. Just setup affinity and the KRB5_CONFIG
114 file. */
115 get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
117 status = ads_connect(ads);
118 if (!ADS_ERR_OK(status)) {
119 DEBUG(1,("ads_connect for domain %s failed: %s\n",
120 dom_name, ads_errstr(status)));
121 ads_destroy(&ads);
122 return status;
125 /* set the flag that says we don't own the memory even
126 though we do so that ads_destroy() won't destroy the
127 structure we pass back by reference */
129 ads->is_mine = False;
131 *adsp = ads;
133 return status;
136 ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
138 char *ldap_server, *realm, *password;
139 struct winbindd_domain *wb_dom;
141 ads_cached_connection_reuse(adsp);
142 if (*adsp != NULL) {
143 return ADS_SUCCESS;
147 * At this point we only have the NetBIOS domain name.
148 * Check if we can get server nam and realm from SAF cache
149 * and the domain list.
151 ldap_server = saf_fetch(dom_name);
152 DEBUG(10, ("ldap_server from saf cache: '%s'\n",
153 ldap_server ? ldap_server : ""));
155 wb_dom = find_domain_from_name_noinit(dom_name);
156 if (wb_dom == NULL) {
157 DEBUG(10, ("could not find domain '%s'\n", dom_name));
158 realm = NULL;
159 } else {
160 DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
161 " domain '%s'\n", wb_dom->alt_name, dom_name));
162 realm = wb_dom->alt_name;
165 /* the machine acct password might have change - fetch it every time */
166 password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
167 realm = SMB_STRDUP(lp_realm());
169 return ads_cached_connection_connect(adsp, realm, dom_name, ldap_server,
170 password, realm, 0);
174 return our ads connections structure for a domain. We keep the connection
175 open to make things faster
177 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
179 ADS_STATUS status;
180 char *password, *realm;
182 DEBUG(10,("ads_cached_connection\n"));
183 ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
185 if (domain->private_data) {
186 return (ADS_STRUCT *)domain->private_data;
189 /* the machine acct password might have change - fetch it every time */
191 if ( IS_DC ) {
193 if ( !pdb_get_trusteddom_pw( domain->name, &password, NULL,
194 NULL ) ) {
195 return NULL;
197 realm = NULL;
199 else {
200 struct winbindd_domain *our_domain = domain;
203 password = secrets_fetch_machine_password(lp_workgroup(), NULL,
204 NULL);
205 /* always give preference to the alt_name in our
206 primary domain if possible */
208 if ( !domain->primary )
209 our_domain = find_our_domain();
211 if (our_domain->alt_name != NULL) {
212 realm = SMB_STRDUP( our_domain->alt_name );
214 else
215 realm = SMB_STRDUP( lp_realm() );
218 status = ads_cached_connection_connect(
219 (ADS_STRUCT **)&domain->private_data,
220 domain->alt_name,
221 domain->name, NULL,
222 password, realm,
223 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
226 if (!ADS_ERR_OK(status)) {
227 /* if we get ECONNREFUSED then it might be a NT4
228 server, fall back to MSRPC */
229 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
230 status.err.rc == ECONNREFUSED) {
231 /* 'reconnect_methods' is the MS-RPC backend. */
232 DEBUG(1,("Trying MSRPC methods\n"));
233 domain->backend = &reconnect_methods;
235 return NULL;
238 return (ADS_STRUCT *)domain->private_data;
241 /* Query display info for a realm. This is the basic user list fn */
242 static NTSTATUS query_user_list(struct winbindd_domain *domain,
243 TALLOC_CTX *mem_ctx,
244 uint32 *num_entries,
245 struct wbint_userinfo **pinfo)
247 ADS_STRUCT *ads = NULL;
248 const char *attrs[] = { "*", NULL };
249 int i, count;
250 ADS_STATUS rc;
251 LDAPMessage *res = NULL;
252 LDAPMessage *msg = NULL;
253 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
255 *num_entries = 0;
257 DEBUG(3,("ads: query_user_list\n"));
259 if ( !winbindd_can_contact_domain( domain ) ) {
260 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
261 domain->name));
262 return NT_STATUS_OK;
265 ads = ads_cached_connection(domain);
267 if (!ads) {
268 domain->last_status = NT_STATUS_SERVER_DISABLED;
269 goto done;
272 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
273 if (!ADS_ERR_OK(rc)) {
274 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
275 status = ads_ntstatus(rc);
276 } else if (!res) {
277 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
279 goto done;
282 count = ads_count_replies(ads, res);
283 if (count == 0) {
284 DEBUG(1,("query_user_list: No users found\n"));
285 goto done;
288 (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
289 if (!*pinfo) {
290 status = NT_STATUS_NO_MEMORY;
291 goto done;
294 count = 0;
296 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
297 struct wbint_userinfo *info = &((*pinfo)[count]);
298 uint32 group;
299 uint32 atype;
301 if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
302 ds_atype_map(atype) != SID_NAME_USER) {
303 DEBUG(1,("Not a user account? atype=0x%x\n", atype));
304 continue;
307 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
308 info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
309 info->homedir = NULL;
310 info->shell = NULL;
311 info->primary_gid = (gid_t)-1;
313 if (!ads_pull_sid(ads, msg, "objectSid",
314 &info->user_sid)) {
315 DEBUG(1, ("No sid for %s !?\n", info->acct_name));
316 continue;
319 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
320 DEBUG(1, ("No primary group for %s !?\n",
321 info->acct_name));
322 continue;
324 sid_compose(&info->group_sid, &domain->sid, group);
326 count += 1;
329 (*num_entries) = count;
330 ads_msgfree(ads, res);
332 for (i=0; i<count; i++) {
333 struct wbint_userinfo *info = &((*pinfo)[i]);
334 const char *gecos = NULL;
335 gid_t primary_gid = (gid_t)-1;
337 status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
338 &info->homedir, &info->shell,
339 &gecos, &primary_gid);
340 if (!NT_STATUS_IS_OK(status)) {
342 * Deliberately ignore this error, there might be more
343 * users to fill
345 continue;
348 if (gecos != NULL) {
349 info->full_name = gecos;
351 info->primary_gid = primary_gid;
354 status = NT_STATUS_OK;
356 DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
358 done:
359 return status;
362 /* list all domain groups */
363 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
364 TALLOC_CTX *mem_ctx,
365 uint32 *num_entries,
366 struct wb_acct_info **info)
368 ADS_STRUCT *ads = NULL;
369 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
370 "name", "objectSid", NULL};
371 int i, count;
372 ADS_STATUS rc;
373 LDAPMessage *res = NULL;
374 LDAPMessage *msg = NULL;
375 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
376 const char *filter;
377 bool enum_dom_local_groups = False;
379 *num_entries = 0;
381 DEBUG(3,("ads: enum_dom_groups\n"));
383 if ( !winbindd_can_contact_domain( domain ) ) {
384 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
385 domain->name));
386 return NT_STATUS_OK;
389 /* only grab domain local groups for our domain */
390 if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
391 enum_dom_local_groups = True;
394 /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
395 * rollup-fixes:
397 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
398 * default value, it MUST be absent. In case of extensible matching the
399 * "dnattr" boolean defaults to FALSE and so it must be only be present
400 * when set to TRUE.
402 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
403 * filter using bitwise matching rule then the buggy AD fails to decode
404 * the extensible match. As a workaround set it to TRUE and thereby add
405 * the dnAttributes "dn" field to cope with those older AD versions.
406 * It should not harm and won't put any additional load on the AD since
407 * none of the dn components have a bitmask-attribute.
409 * Thanks to Ralf Haferkamp for input and testing - Guenther */
411 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
412 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
413 ADS_LDAP_MATCHING_RULE_BIT_AND,
414 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
416 if (filter == NULL) {
417 status = NT_STATUS_NO_MEMORY;
418 goto done;
421 ads = ads_cached_connection(domain);
423 if (!ads) {
424 domain->last_status = NT_STATUS_SERVER_DISABLED;
425 goto done;
428 rc = ads_search_retry(ads, &res, filter, attrs);
429 if (!ADS_ERR_OK(rc)) {
430 status = ads_ntstatus(rc);
431 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
432 goto done;
433 } else if (!res) {
434 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
435 goto done;
438 count = ads_count_replies(ads, res);
439 if (count == 0) {
440 DEBUG(1,("enum_dom_groups: No groups found\n"));
441 goto done;
444 (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
445 if (!*info) {
446 status = NT_STATUS_NO_MEMORY;
447 goto done;
450 i = 0;
452 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
453 char *name, *gecos;
454 struct dom_sid sid;
455 uint32 rid;
457 name = ads_pull_username(ads, mem_ctx, msg);
458 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
459 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
460 DEBUG(1,("No sid for %s !?\n", name));
461 continue;
464 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
465 DEBUG(1,("No rid for %s !?\n", name));
466 continue;
469 fstrcpy((*info)[i].acct_name, name);
470 fstrcpy((*info)[i].acct_desc, gecos);
471 (*info)[i].rid = rid;
472 i++;
475 (*num_entries) = i;
477 status = NT_STATUS_OK;
479 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
481 done:
482 if (res)
483 ads_msgfree(ads, res);
485 return status;
488 /* list all domain local groups */
489 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
490 TALLOC_CTX *mem_ctx,
491 uint32 *num_entries,
492 struct wb_acct_info **info)
495 * This is a stub function only as we returned the domain
496 * local groups in enum_dom_groups() if the domain->native field
497 * was true. This is a simple performance optimization when
498 * using LDAP.
500 * if we ever need to enumerate domain local groups separately,
501 * then this optimization in enum_dom_groups() will need
502 * to be split out
504 *num_entries = 0;
506 return NT_STATUS_OK;
509 /* convert a single name to a sid in a domain - use rpc methods */
510 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
511 TALLOC_CTX *mem_ctx,
512 const char *domain_name,
513 const char *name,
514 uint32_t flags,
515 struct dom_sid *sid,
516 enum lsa_SidType *type)
518 return reconnect_methods.name_to_sid(domain, mem_ctx,
519 domain_name, name, flags,
520 sid, type);
523 /* convert a domain SID to a user or group name - use rpc methods */
524 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
525 TALLOC_CTX *mem_ctx,
526 const struct dom_sid *sid,
527 char **domain_name,
528 char **name,
529 enum lsa_SidType *type)
531 return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
532 domain_name, name, type);
535 /* convert a list of rids to names - use rpc methods */
536 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
537 TALLOC_CTX *mem_ctx,
538 const struct dom_sid *sid,
539 uint32 *rids,
540 size_t num_rids,
541 char **domain_name,
542 char ***names,
543 enum lsa_SidType **types)
545 return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
546 rids, num_rids,
547 domain_name, names, types);
550 /* If you are looking for "dn_lookup": Yes, it used to be here!
551 * It has gone now since it was a major speed bottleneck in
552 * lookup_groupmem (its only use). It has been replaced by
553 * an rpc lookup sids call... R.I.P. */
555 /* Lookup user information from a rid */
556 static NTSTATUS query_user(struct winbindd_domain *domain,
557 TALLOC_CTX *mem_ctx,
558 const struct dom_sid *sid,
559 struct wbint_userinfo *info)
561 ADS_STRUCT *ads = NULL;
562 const char *attrs[] = { "*", NULL };
563 ADS_STATUS rc;
564 int count;
565 LDAPMessage *msg = NULL;
566 char *ldap_exp;
567 char *sidstr;
568 uint32 group_rid;
569 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
570 struct netr_SamInfo3 *user = NULL;
571 gid_t gid = -1;
572 int ret;
573 char *ads_name;
575 DEBUG(3,("ads: query_user\n"));
577 info->homedir = NULL;
578 info->shell = NULL;
580 /* try netsamlogon cache first */
582 if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
584 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
585 sid_string_dbg(sid)));
587 sid_compose(&info->user_sid, &domain->sid, user->base.rid);
588 sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);
590 info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
591 info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
593 nss_get_info_cached( domain, sid, mem_ctx,
594 &info->homedir, &info->shell, &info->full_name,
595 &gid );
596 info->primary_gid = gid;
598 TALLOC_FREE(user);
600 return NT_STATUS_OK;
603 if ( !winbindd_can_contact_domain(domain)) {
604 DEBUG(8,("query_user: No incoming trust from domain %s\n",
605 domain->name));
607 /* We still need to generate some basic information
608 about the user even if we cannot contact the
609 domain. Most of this stuff we can deduce. */
611 sid_copy( &info->user_sid, sid );
613 /* Assume "Domain Users" for the primary group */
615 sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );
617 /* Try to fill in what the nss_info backend can do */
619 nss_get_info_cached( domain, sid, mem_ctx,
620 &info->homedir, &info->shell, &info->full_name,
621 &gid);
622 info->primary_gid = gid;
624 return NT_STATUS_OK;
627 /* no cache...do the query */
629 if ( (ads = ads_cached_connection(domain)) == NULL ) {
630 domain->last_status = NT_STATUS_SERVER_DISABLED;
631 return NT_STATUS_SERVER_DISABLED;
634 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
636 ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
637 TALLOC_FREE(sidstr);
638 if (ret == -1) {
639 return NT_STATUS_NO_MEMORY;
641 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
642 SAFE_FREE(ldap_exp);
643 if (!ADS_ERR_OK(rc)) {
644 DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
645 sid_string_dbg(sid), ads_errstr(rc)));
646 return ads_ntstatus(rc);
647 } else if (!msg) {
648 DEBUG(1,("query_user(sid=%s) ads_search returned NULL res\n",
649 sid_string_dbg(sid)));
650 return NT_STATUS_INTERNAL_ERROR;
653 count = ads_count_replies(ads, msg);
654 if (count != 1) {
655 DEBUG(1,("query_user(sid=%s): Not found\n",
656 sid_string_dbg(sid)));
657 ads_msgfree(ads, msg);
658 return NT_STATUS_NO_SUCH_USER;
661 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
663 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
664 DEBUG(1,("No primary group for %s !?\n",
665 sid_string_dbg(sid)));
666 ads_msgfree(ads, msg);
667 return NT_STATUS_NO_SUCH_USER;
669 sid_copy(&info->user_sid, sid);
670 sid_compose(&info->group_sid, &domain->sid, group_rid);
673 * We have to fetch the "name" attribute before doing the
674 * nss_get_info_cached call. nss_get_info_cached might destroy
675 * the ads struct, potentially invalidating the ldap message.
677 ads_name = ads_pull_string(ads, mem_ctx, msg, "name");
679 ads_msgfree(ads, msg);
680 msg = NULL;
682 status = nss_get_info_cached( domain, sid, mem_ctx,
683 &info->homedir, &info->shell, &info->full_name,
684 &gid);
685 info->primary_gid = gid;
686 if (!NT_STATUS_IS_OK(status)) {
687 DEBUG(1, ("nss_get_info_cached failed: %s\n",
688 nt_errstr(status)));
689 return status;
692 if (info->full_name == NULL) {
693 info->full_name = ads_name;
694 } else {
695 TALLOC_FREE(ads_name);
698 status = NT_STATUS_OK;
700 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
701 return NT_STATUS_OK;
704 /* Lookup groups a user is a member of - alternate method, for when
705 tokenGroups are not available. */
706 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
707 TALLOC_CTX *mem_ctx,
708 const char *user_dn,
709 struct dom_sid *primary_group,
710 uint32_t *p_num_groups, struct dom_sid **user_sids)
712 ADS_STATUS rc;
713 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
714 int count;
715 LDAPMessage *res = NULL;
716 LDAPMessage *msg = NULL;
717 char *ldap_exp;
718 ADS_STRUCT *ads;
719 const char *group_attrs[] = {"objectSid", NULL};
720 char *escaped_dn;
721 uint32_t num_groups = 0;
723 DEBUG(3,("ads: lookup_usergroups_member\n"));
725 if ( !winbindd_can_contact_domain( domain ) ) {
726 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
727 domain->name));
728 return NT_STATUS_OK;
731 ads = ads_cached_connection(domain);
733 if (!ads) {
734 domain->last_status = NT_STATUS_SERVER_DISABLED;
735 goto done;
738 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
739 status = NT_STATUS_NO_MEMORY;
740 goto done;
743 ldap_exp = talloc_asprintf(mem_ctx,
744 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
745 escaped_dn,
746 ADS_LDAP_MATCHING_RULE_BIT_AND,
747 GROUP_TYPE_SECURITY_ENABLED);
748 if (!ldap_exp) {
749 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
750 TALLOC_FREE(escaped_dn);
751 status = NT_STATUS_NO_MEMORY;
752 goto done;
755 TALLOC_FREE(escaped_dn);
757 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
759 if (!ADS_ERR_OK(rc)) {
760 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
761 return ads_ntstatus(rc);
762 } else if (!res) {
763 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
764 return NT_STATUS_INTERNAL_ERROR;
768 count = ads_count_replies(ads, res);
770 *user_sids = NULL;
771 num_groups = 0;
773 /* always add the primary group to the sid array */
774 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
775 &num_groups);
776 if (!NT_STATUS_IS_OK(status)) {
777 goto done;
780 if (count > 0) {
781 for (msg = ads_first_entry(ads, res); msg;
782 msg = ads_next_entry(ads, msg)) {
783 struct dom_sid group_sid;
785 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
786 DEBUG(1,("No sid for this group ?!?\n"));
787 continue;
790 /* ignore Builtin groups from ADS - Guenther */
791 if (sid_check_is_in_builtin(&group_sid)) {
792 continue;
795 status = add_sid_to_array(mem_ctx, &group_sid,
796 user_sids, &num_groups);
797 if (!NT_STATUS_IS_OK(status)) {
798 goto done;
804 *p_num_groups = num_groups;
805 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
807 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
808 done:
809 if (res)
810 ads_msgfree(ads, res);
812 return status;
815 /* Lookup groups a user is a member of - alternate method, for when
816 tokenGroups are not available. */
817 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
818 TALLOC_CTX *mem_ctx,
819 const char *user_dn,
820 struct dom_sid *primary_group,
821 uint32_t *p_num_groups,
822 struct dom_sid **user_sids)
824 ADS_STATUS rc;
825 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
826 ADS_STRUCT *ads;
827 const char *attrs[] = {"memberOf", NULL};
828 uint32_t num_groups = 0;
829 struct dom_sid *group_sids = NULL;
830 int i;
831 char **strings = NULL;
832 size_t num_strings = 0, num_sids = 0;
835 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
837 if ( !winbindd_can_contact_domain( domain ) ) {
838 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
839 "domain %s\n", domain->name));
840 return NT_STATUS_OK;
843 ads = ads_cached_connection(domain);
845 if (!ads) {
846 domain->last_status = NT_STATUS_SERVER_DISABLED;
847 return NT_STATUS_UNSUCCESSFUL;
850 rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
851 ADS_EXTENDED_DN_HEX_STRING,
852 &strings, &num_strings);
854 if (!ADS_ERR_OK(rc)) {
855 DEBUG(1,("lookup_usergroups_memberof ads_search "
856 "member=%s: %s\n", user_dn, ads_errstr(rc)));
857 return ads_ntstatus(rc);
860 *user_sids = NULL;
861 num_groups = 0;
863 /* always add the primary group to the sid array */
864 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
865 &num_groups);
866 if (!NT_STATUS_IS_OK(status)) {
867 goto done;
870 group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
871 if (!group_sids) {
872 status = NT_STATUS_NO_MEMORY;
873 goto done;
876 for (i=0; i<num_strings; i++) {
877 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
878 ADS_EXTENDED_DN_HEX_STRING,
879 &(group_sids)[i]);
880 if (!ADS_ERR_OK(rc)) {
881 /* ignore members without SIDs */
882 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
883 NT_STATUS_NOT_FOUND)) {
884 continue;
886 else {
887 status = ads_ntstatus(rc);
888 goto done;
891 num_sids++;
894 if (i == 0) {
895 DEBUG(1,("No memberOf for this user?!?\n"));
896 status = NT_STATUS_NO_MEMORY;
897 goto done;
900 for (i=0; i<num_sids; i++) {
902 /* ignore Builtin groups from ADS - Guenther */
903 if (sid_check_is_in_builtin(&group_sids[i])) {
904 continue;
907 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
908 &num_groups);
909 if (!NT_STATUS_IS_OK(status)) {
910 goto done;
915 *p_num_groups = num_groups;
916 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
918 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
919 user_dn));
921 done:
922 TALLOC_FREE(strings);
923 TALLOC_FREE(group_sids);
925 return status;
929 /* Lookup groups a user is a member of. */
930 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
931 TALLOC_CTX *mem_ctx,
932 const struct dom_sid *sid,
933 uint32 *p_num_groups, struct dom_sid **user_sids)
935 ADS_STRUCT *ads = NULL;
936 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
937 ADS_STATUS rc;
938 int count;
939 LDAPMessage *msg = NULL;
940 char *user_dn = NULL;
941 struct dom_sid *sids;
942 int i;
943 struct dom_sid primary_group;
944 uint32 primary_group_rid;
945 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
946 uint32_t num_groups = 0;
948 DEBUG(3,("ads: lookup_usergroups\n"));
949 *p_num_groups = 0;
951 status = lookup_usergroups_cached(domain, mem_ctx, sid,
952 p_num_groups, user_sids);
953 if (NT_STATUS_IS_OK(status)) {
954 return NT_STATUS_OK;
957 if ( !winbindd_can_contact_domain( domain ) ) {
958 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
959 domain->name));
961 /* Tell the cache manager not to remember this one */
963 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
966 ads = ads_cached_connection(domain);
968 if (!ads) {
969 domain->last_status = NT_STATUS_SERVER_DISABLED;
970 status = NT_STATUS_SERVER_DISABLED;
971 goto done;
974 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
976 if (!ADS_ERR_OK(rc)) {
977 status = ads_ntstatus(rc);
978 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
979 "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
980 goto done;
983 count = ads_count_replies(ads, msg);
984 if (count != 1) {
985 status = NT_STATUS_UNSUCCESSFUL;
986 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
987 "invalid number of results (count=%d)\n",
988 sid_string_dbg(sid), count));
989 goto done;
992 if (!msg) {
993 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
994 sid_string_dbg(sid)));
995 status = NT_STATUS_UNSUCCESSFUL;
996 goto done;
999 user_dn = ads_get_dn(ads, mem_ctx, msg);
1000 if (user_dn == NULL) {
1001 status = NT_STATUS_NO_MEMORY;
1002 goto done;
1005 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
1006 DEBUG(1,("%s: No primary group for sid=%s !?\n",
1007 domain->name, sid_string_dbg(sid)));
1008 goto done;
1011 sid_compose(&primary_group, &domain->sid, primary_group_rid);
1013 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
1015 /* there must always be at least one group in the token,
1016 unless we are talking to a buggy Win2k server */
1018 /* actually this only happens when the machine account has no read
1019 * permissions on the tokenGroup attribute - gd */
1021 if (count == 0) {
1023 /* no tokenGroups */
1025 /* lookup what groups this user is a member of by DN search on
1026 * "memberOf" */
1028 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
1029 &primary_group,
1030 &num_groups, user_sids);
1031 *p_num_groups = num_groups;
1032 if (NT_STATUS_IS_OK(status)) {
1033 goto done;
1036 /* lookup what groups this user is a member of by DN search on
1037 * "member" */
1039 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
1040 &primary_group,
1041 &num_groups, user_sids);
1042 *p_num_groups = num_groups;
1043 goto done;
1046 *user_sids = NULL;
1047 num_groups = 0;
1049 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
1050 &num_groups);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 goto done;
1055 for (i=0;i<count;i++) {
1057 /* ignore Builtin groups from ADS - Guenther */
1058 if (sid_check_is_in_builtin(&sids[i])) {
1059 continue;
1062 status = add_sid_to_array_unique(mem_ctx, &sids[i],
1063 user_sids, &num_groups);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 goto done;
1069 *p_num_groups = (uint32)num_groups;
1070 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1072 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
1073 sid_string_dbg(sid)));
1074 done:
1075 TALLOC_FREE(user_dn);
1076 ads_msgfree(ads, msg);
1077 return status;
1080 /* Lookup aliases a user is member of - use rpc methods */
1081 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
1082 TALLOC_CTX *mem_ctx,
1083 uint32 num_sids, const struct dom_sid *sids,
1084 uint32 *num_aliases, uint32 **alias_rids)
1086 return reconnect_methods.lookup_useraliases(domain, mem_ctx,
1087 num_sids, sids,
1088 num_aliases,
1089 alias_rids);
1093 find the members of a group, given a group rid and domain
1095 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
1096 TALLOC_CTX *mem_ctx,
1097 const struct dom_sid *group_sid,
1098 enum lsa_SidType type,
1099 uint32 *num_names,
1100 struct dom_sid **sid_mem, char ***names,
1101 uint32 **name_types)
1103 ADS_STATUS rc;
1104 ADS_STRUCT *ads = NULL;
1105 char *ldap_exp;
1106 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1107 char *sidbinstr;
1108 char **members = NULL;
1109 int i;
1110 size_t num_members = 0;
1111 ads_control args;
1112 struct dom_sid *sid_mem_nocache = NULL;
1113 char **names_nocache = NULL;
1114 enum lsa_SidType *name_types_nocache = NULL;
1115 char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */
1116 uint32 num_nocache = 0;
1117 TALLOC_CTX *tmp_ctx = NULL;
1119 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1120 sid_string_dbg(group_sid)));
1122 *num_names = 0;
1124 tmp_ctx = talloc_new(mem_ctx);
1125 if (!tmp_ctx) {
1126 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1127 status = NT_STATUS_NO_MEMORY;
1128 goto done;
1131 if ( !winbindd_can_contact_domain( domain ) ) {
1132 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1133 domain->name));
1134 return NT_STATUS_OK;
1137 ads = ads_cached_connection(domain);
1139 if (!ads) {
1140 domain->last_status = NT_STATUS_SERVER_DISABLED;
1141 goto done;
1144 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1145 status = NT_STATUS_NO_MEMORY;
1146 goto done;
1149 /* search for all members of the group */
1150 ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1151 TALLOC_FREE(sidbinstr);
1152 if (ldap_exp == NULL) {
1153 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1154 status = NT_STATUS_NO_MEMORY;
1155 goto done;
1158 args.control = ADS_EXTENDED_DN_OID;
1159 args.val = ADS_EXTENDED_DN_HEX_STRING;
1160 args.critical = True;
1162 rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1163 ldap_exp, &args, "member", &members, &num_members);
1165 if (!ADS_ERR_OK(rc)) {
1166 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1167 status = NT_STATUS_UNSUCCESSFUL;
1168 goto done;
1171 DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1173 /* Now that we have a list of sids, we need to get the
1174 * lists of names and name_types belonging to these sids.
1175 * even though conceptually not quite clean, we use the
1176 * RPC call lsa_lookup_sids for this since it can handle a
1177 * list of sids. ldap calls can just resolve one sid at a time.
1179 * At this stage, the sids are still hidden in the exetended dn
1180 * member output format. We actually do a little better than
1181 * stated above: In extracting the sids from the member strings,
1182 * we try to resolve as many sids as possible from the
1183 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1185 if (num_members) {
1186 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
1187 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
1188 (*name_types) = talloc_zero_array(mem_ctx, uint32, num_members);
1189 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
1191 if ((members == NULL) || (*sid_mem == NULL) ||
1192 (*names == NULL) || (*name_types == NULL) ||
1193 (sid_mem_nocache == NULL))
1195 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1196 status = NT_STATUS_NO_MEMORY;
1197 goto done;
1200 else {
1201 (*sid_mem) = NULL;
1202 (*names) = NULL;
1203 (*name_types) = NULL;
1206 for (i=0; i<num_members; i++) {
1207 enum lsa_SidType name_type;
1208 char *name, *domain_name;
1209 struct dom_sid sid;
1211 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1212 &sid);
1213 if (!ADS_ERR_OK(rc)) {
1214 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1215 NT_STATUS_NOT_FOUND)) {
1216 /* Group members can be objects, like Exchange
1217 * Public Folders, that don't have a SID. Skip
1218 * them. */
1219 continue;
1221 else {
1222 status = ads_ntstatus(rc);
1223 goto done;
1226 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1227 &name_type)) {
1228 DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1229 "cache\n", sid_string_dbg(&sid)));
1230 sid_copy(&(*sid_mem)[*num_names], &sid);
1231 (*names)[*num_names] = fill_domain_username_talloc(
1232 *names,
1233 domain_name,
1234 name,
1235 true);
1237 (*name_types)[*num_names] = name_type;
1238 (*num_names)++;
1240 else {
1241 DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1242 "cache\n", sid_string_dbg(&sid)));
1243 sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1244 num_nocache++;
1248 DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1249 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1251 /* handle sids not resolved from cache by lsa_lookup_sids */
1252 if (num_nocache > 0) {
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);
1262 if (!(NT_STATUS_IS_OK(status) ||
1263 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1264 NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1266 DEBUG(1, ("lsa_lookupsids call failed with %s "
1267 "- retrying...\n", nt_errstr(status)));
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);
1278 if (NT_STATUS_IS_OK(status) ||
1279 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
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))
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)++;
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... */
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;
1316 status = NT_STATUS_OK;
1317 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1318 sid_string_dbg(group_sid)));
1320 done:
1322 TALLOC_FREE(tmp_ctx);
1324 return status;
1327 /* find the sequence number for a domain */
1328 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
1330 ADS_STRUCT *ads = NULL;
1331 ADS_STATUS rc;
1333 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
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;
1342 *seq = DOM_SEQUENCE_NONE;
1344 ads = ads_cached_connection(domain);
1346 if (!ads) {
1347 domain->last_status = NT_STATUS_SERVER_DISABLED;
1348 return NT_STATUS_UNSUCCESSFUL;
1351 rc = ads_USN(ads, seq);
1353 if (!ADS_ERR_OK(rc)) {
1355 /* its a dead connection, destroy it */
1357 if (domain->private_data) {
1358 ads = (ADS_STRUCT *)domain->private_data;
1359 ads->is_mine = True;
1360 ads_destroy(&ads);
1361 ads_kdestroy(WINBIND_CCACHE_NAME);
1362 domain->private_data = NULL;
1365 return ads_ntstatus(rc);
1368 /* find the lockout policy of a domain - use rpc methods */
1369 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1370 TALLOC_CTX *mem_ctx,
1371 struct samr_DomInfo12 *policy)
1373 return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
1376 /* find the password policy of a domain - use rpc methods */
1377 static NTSTATUS password_policy(struct winbindd_domain *domain,
1378 TALLOC_CTX *mem_ctx,
1379 struct samr_DomInfo1 *policy)
1381 return reconnect_methods.password_policy(domain, mem_ctx, policy);
1384 /* get a list of trusted domains */
1385 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1386 TALLOC_CTX *mem_ctx,
1387 struct netr_DomainTrustList *trusts)
1389 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1390 WERROR werr;
1391 int i;
1392 uint32 flags;
1393 struct rpc_pipe_client *cli;
1394 int ret_count;
1395 struct dcerpc_binding_handle *b;
1397 DEBUG(3,("ads: trusted_domains\n"));
1399 ZERO_STRUCTP(trusts);
1401 /* If this is our primary domain or a root in our forest,
1402 query for all trusts. If not, then just look for domain
1403 trusts in the target forest */
1405 if (domain->primary || domain_is_forest_root(domain)) {
1406 flags = NETR_TRUST_FLAG_OUTBOUND |
1407 NETR_TRUST_FLAG_INBOUND |
1408 NETR_TRUST_FLAG_IN_FOREST;
1409 } else {
1410 flags = NETR_TRUST_FLAG_IN_FOREST;
1413 result = cm_connect_netlogon(domain, &cli);
1415 if (!NT_STATUS_IS_OK(result)) {
1416 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1417 "for PIPE_NETLOGON (%s)\n",
1418 domain->name, nt_errstr(result)));
1419 return NT_STATUS_UNSUCCESSFUL;
1422 b = cli->binding_handle;
1424 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1425 cli->desthost,
1426 flags,
1427 trusts,
1428 &werr);
1429 if (!NT_STATUS_IS_OK(result)) {
1430 return result;
1433 if (!W_ERROR_IS_OK(werr)) {
1434 return werror_to_ntstatus(werr);
1436 if (trusts->count == 0) {
1437 return NT_STATUS_OK;
1440 /* Copy across names and sids */
1442 ret_count = 0;
1443 for (i = 0; i < trusts->count; i++) {
1444 struct netr_DomainTrust *trust = &trusts->array[i];
1445 struct winbindd_domain d;
1447 ZERO_STRUCT(d);
1450 * drop external trusts if this is not our primary
1451 * domain. This means that the returned number of
1452 * domains may be less that the ones actually trusted
1453 * by the DC.
1456 if ((trust->trust_attributes
1457 == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1458 !domain->primary )
1460 DEBUG(10,("trusted_domains: Skipping external trusted "
1461 "domain %s because it is outside of our "
1462 "primary domain\n",
1463 trust->netbios_name));
1464 continue;
1467 /* add to the trusted domain cache */
1469 d.name = discard_const_p(char, trust->netbios_name);
1470 d.alt_name = discard_const_p(char, trust->dns_name);
1472 if (trust->sid) {
1473 sid_copy(&d.sid, trust->sid);
1474 } else {
1475 sid_copy(&d.sid, &global_sid_NULL);
1478 if ( domain->primary ) {
1479 DEBUG(10,("trusted_domains(ads): Searching "
1480 "trusted domain list of %s and storing "
1481 "trust flags for domain %s\n",
1482 domain->name, d.alt_name));
1484 d.domain_flags = trust->trust_flags;
1485 d.domain_type = trust->trust_type;
1486 d.domain_trust_attribs = trust->trust_attributes;
1488 wcache_tdc_add_domain( &d );
1489 ret_count++;
1490 } else if (domain_is_forest_root(domain)) {
1491 /* Check if we already have this record. If
1492 * we are following our forest root that is not
1493 * our primary domain, we want to keep trust
1494 * flags from the perspective of our primary
1495 * domain not our forest root. */
1496 struct winbindd_tdc_domain *exist = NULL;
1498 exist = wcache_tdc_fetch_domain(
1499 talloc_tos(), trust->netbios_name);
1500 if (!exist) {
1501 DEBUG(10,("trusted_domains(ads): Searching "
1502 "trusted domain list of %s and "
1503 "storing trust flags for domain "
1504 "%s\n", domain->name, d.alt_name));
1505 d.domain_flags = trust->trust_flags;
1506 d.domain_type = trust->trust_type;
1507 d.domain_trust_attribs =
1508 trust->trust_attributes;
1510 wcache_tdc_add_domain( &d );
1511 ret_count++;
1513 TALLOC_FREE(exist);
1514 } else {
1515 /* This gets a little tricky. If we are
1516 following a transitive forest trust, then
1517 innerit the flags, type, and attribs from
1518 the domain we queried to make sure we don't
1519 record the view of the trust from the wrong
1520 side. Always view it from the side of our
1521 primary domain. --jerry */
1522 struct winbindd_tdc_domain *parent = NULL;
1524 DEBUG(10,("trusted_domains(ads): Searching "
1525 "trusted domain list of %s and inheriting "
1526 "trust flags for domain %s\n",
1527 domain->name, d.alt_name));
1529 parent = wcache_tdc_fetch_domain(talloc_tos(),
1530 domain->name);
1531 if (parent) {
1532 d.domain_flags = parent->trust_flags;
1533 d.domain_type = parent->trust_type;
1534 d.domain_trust_attribs = parent->trust_attribs;
1535 } else {
1536 d.domain_flags = domain->domain_flags;
1537 d.domain_type = domain->domain_type;
1538 d.domain_trust_attribs =
1539 domain->domain_trust_attribs;
1541 TALLOC_FREE(parent);
1543 wcache_tdc_add_domain( &d );
1544 ret_count++;
1547 return result;
1550 /* the ADS backend methods are exposed via this structure */
1551 struct winbindd_methods ads_methods = {
1552 True,
1553 query_user_list,
1554 enum_dom_groups,
1555 enum_local_groups,
1556 name_to_sid,
1557 sid_to_name,
1558 rids_to_names,
1559 query_user,
1560 lookup_usergroups,
1561 lookup_useraliases,
1562 lookup_groupmem,
1563 sequence_number,
1564 lockout_policy,
1565 password_policy,
1566 trusted_domains,
1569 #endif