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/>.
26 #include "rpc_client/rpc_client.h"
27 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "../libds/common/flags.h"
31 #include "../libcli/ldap/ldap_ndr.h"
32 #include "../libcli/security/security.h"
33 #include "../libds/common/flag_mapping.h"
39 #define DBGC_CLASS DBGC_WINBIND
41 extern struct winbindd_methods reconnect_methods;
43 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
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;
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)) {
67 /* we own this ADS_STRUCT so make sure it goes away */
68 DEBUG(7,("Deleting expired krb5 credential cache\n"));
71 ads_kdestroy(WINBIND_CCACHE_NAME);
77 static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
78 const char *dom_name_alt,
80 const char *ldap_server,
87 struct sockaddr_storage dc_ss;
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);
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)) {
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
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)));
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;
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);
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));
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,
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)
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 */
193 if ( !pdb_get_trusteddom_pw( domain->name, &password, NULL,
200 struct winbindd_domain *our_domain = domain;
203 password = secrets_fetch_machine_password(lp_workgroup(), 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 );
215 realm = SMB_STRDUP( lp_realm() );
218 status = ads_cached_connection_connect(
219 (ADS_STRUCT **)&domain->private_data,
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;
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,
245 struct wbint_userinfo **pinfo)
247 ADS_STRUCT *ads = NULL;
248 const char *attrs[] = { "*", NULL };
251 LDAPMessage *res = NULL;
252 LDAPMessage *msg = NULL;
253 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
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",
265 ads = ads_cached_connection(domain);
268 domain->last_status = NT_STATUS_SERVER_DISABLED;
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);
277 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
282 count = ads_count_replies(ads, res);
284 DEBUG(1,("query_user_list: No users found\n"));
288 (*pinfo) = talloc_zero_array(mem_ctx, struct wbint_userinfo, count);
290 status = NT_STATUS_NO_MEMORY;
296 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
297 struct wbint_userinfo *info = &((*pinfo)[count]);
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));
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;
311 info->primary_gid = (gid_t)-1;
313 if (!ads_pull_sid(ads, msg, "objectSid",
315 DEBUG(1, ("No sid for %s !?\n", info->acct_name));
319 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
320 DEBUG(1, ("No primary group for %s !?\n",
324 sid_compose(&info->group_sid, &domain->sid, group);
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
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)));
362 /* list all domain groups */
363 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
366 struct wb_acct_info **info)
368 ADS_STRUCT *ads = NULL;
369 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
370 "name", "objectSid", NULL};
373 LDAPMessage *res = NULL;
374 LDAPMessage *msg = NULL;
375 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
377 bool enum_dom_local_groups = False;
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",
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
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
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;
421 ads = ads_cached_connection(domain);
424 domain->last_status = NT_STATUS_SERVER_DISABLED;
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)));
434 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
438 count = ads_count_replies(ads, res);
440 DEBUG(1,("enum_dom_groups: No groups found\n"));
444 (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
446 status = NT_STATUS_NO_MEMORY;
452 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
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));
464 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
465 DEBUG(1,("No rid for %s !?\n", name));
469 fstrcpy((*info)[i].acct_name, name);
470 fstrcpy((*info)[i].acct_desc, gecos);
471 (*info)[i].rid = rid;
477 status = NT_STATUS_OK;
479 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
483 ads_msgfree(ads, res);
488 /* list all domain local groups */
489 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
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
500 * if we ever need to enumerate domain local groups separately,
501 * then this optimization in enum_dom_groups() will need
509 /* convert a single name to a sid in a domain - use rpc methods */
510 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
512 const char *domain_name,
516 enum lsa_SidType *type)
518 return reconnect_methods.name_to_sid(domain, mem_ctx,
519 domain_name, name, flags,
523 /* convert a domain SID to a user or group name - use rpc methods */
524 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
526 const struct dom_sid *sid,
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,
538 const struct dom_sid *sid,
543 enum lsa_SidType **types)
545 return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
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,
558 const struct dom_sid *sid,
559 struct wbint_userinfo *info)
561 ADS_STRUCT *ads = NULL;
562 const char *attrs[] = { "*", NULL };
565 LDAPMessage *msg = NULL;
569 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
570 struct netr_SamInfo3 *user = NULL;
575 DEBUG(3,("ads: query_user\n"));
577 info->homedir = 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,
596 info->primary_gid = gid;
603 if ( !winbindd_can_contact_domain(domain)) {
604 DEBUG(8,("query_user: No incoming trust from domain %s\n",
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,
622 info->primary_gid = gid;
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);
639 return NT_STATUS_NO_MEMORY;
641 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
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);
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);
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);
682 status = nss_get_info_cached( domain, sid, mem_ctx,
683 &info->homedir, &info->shell, &info->full_name,
685 info->primary_gid = gid;
686 if (!NT_STATUS_IS_OK(status)) {
687 DEBUG(1, ("nss_get_info_cached failed: %s\n",
692 if (info->full_name == NULL) {
693 info->full_name = ads_name;
695 TALLOC_FREE(ads_name);
698 status = NT_STATUS_OK;
700 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
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,
709 struct dom_sid *primary_group,
710 uint32_t *p_num_groups, struct dom_sid **user_sids)
713 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
715 LDAPMessage *res = NULL;
716 LDAPMessage *msg = NULL;
719 const char *group_attrs[] = {"objectSid", NULL};
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",
731 ads = ads_cached_connection(domain);
734 domain->last_status = NT_STATUS_SERVER_DISABLED;
738 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
739 status = NT_STATUS_NO_MEMORY;
743 ldap_exp = talloc_asprintf(mem_ctx,
744 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
746 ADS_LDAP_MATCHING_RULE_BIT_AND,
747 GROUP_TYPE_SECURITY_ENABLED);
749 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
750 TALLOC_FREE(escaped_dn);
751 status = NT_STATUS_NO_MEMORY;
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);
763 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
764 return NT_STATUS_INTERNAL_ERROR;
768 count = ads_count_replies(ads, res);
773 /* always add the primary group to the sid array */
774 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
776 if (!NT_STATUS_IS_OK(status)) {
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"));
790 /* ignore Builtin groups from ADS - Guenther */
791 if (sid_check_is_in_builtin(&group_sid)) {
795 status = add_sid_to_array(mem_ctx, &group_sid,
796 user_sids, &num_groups);
797 if (!NT_STATUS_IS_OK(status)) {
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));
810 ads_msgfree(ads, res);
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,
820 struct dom_sid *primary_group,
821 uint32_t *p_num_groups,
822 struct dom_sid **user_sids)
825 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
827 const char *attrs[] = {"memberOf", NULL};
828 uint32_t num_groups = 0;
829 struct dom_sid *group_sids = NULL;
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));
843 ads = ads_cached_connection(domain);
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);
863 /* always add the primary group to the sid array */
864 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
866 if (!NT_STATUS_IS_OK(status)) {
870 group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
872 status = NT_STATUS_NO_MEMORY;
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,
880 if (!ADS_ERR_OK(rc)) {
881 /* ignore members without SIDs */
882 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
883 NT_STATUS_NOT_FOUND)) {
887 status = ads_ntstatus(rc);
895 DEBUG(1,("No memberOf for this user?!?\n"));
896 status = NT_STATUS_NO_MEMORY;
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])) {
907 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
909 if (!NT_STATUS_IS_OK(status)) {
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",
922 TALLOC_FREE(strings);
923 TALLOC_FREE(group_sids);
929 /* Lookup groups a user is a member of. */
930 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
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};
939 LDAPMessage *msg = NULL;
940 char *user_dn = NULL;
941 struct dom_sid *sids;
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"));
951 status = lookup_usergroups_cached(domain, mem_ctx, sid,
952 p_num_groups, user_sids);
953 if (NT_STATUS_IS_OK(status)) {
957 if ( !winbindd_can_contact_domain( domain ) ) {
958 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
961 /* Tell the cache manager not to remember this one */
963 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
966 ads = ads_cached_connection(domain);
969 domain->last_status = NT_STATUS_SERVER_DISABLED;
970 status = NT_STATUS_SERVER_DISABLED;
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)));
983 count = ads_count_replies(ads, msg);
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));
993 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
994 sid_string_dbg(sid)));
995 status = NT_STATUS_UNSUCCESSFUL;
999 user_dn = ads_get_dn(ads, mem_ctx, msg);
1000 if (user_dn == NULL) {
1001 status = NT_STATUS_NO_MEMORY;
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)));
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 */
1023 /* no tokenGroups */
1025 /* lookup what groups this user is a member of by DN search on
1028 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
1030 &num_groups, user_sids);
1031 *p_num_groups = num_groups;
1032 if (NT_STATUS_IS_OK(status)) {
1036 /* lookup what groups this user is a member of by DN search on
1039 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
1041 &num_groups, user_sids);
1042 *p_num_groups = num_groups;
1049 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
1051 if (!NT_STATUS_IS_OK(status)) {
1055 for (i=0;i<count;i++) {
1057 /* ignore Builtin groups from ADS - Guenther */
1058 if (sid_check_is_in_builtin(&sids[i])) {
1062 status = add_sid_to_array_unique(mem_ctx, &sids[i],
1063 user_sids, &num_groups);
1064 if (!NT_STATUS_IS_OK(status)) {
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)));
1075 TALLOC_FREE(user_dn);
1076 ads_msgfree(ads, msg);
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,
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,
1100 struct dom_sid **sid_mem, char ***names,
1101 uint32 **name_types)
1104 ADS_STRUCT *ads = NULL;
1106 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1108 char **members = NULL;
1110 size_t num_members = 0;
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)));
1124 tmp_ctx = talloc_new(mem_ctx);
1126 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1127 status = NT_STATUS_NO_MEMORY;
1131 if ( !winbindd_can_contact_domain( domain ) ) {
1132 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1134 return NT_STATUS_OK;
1137 ads = ads_cached_connection(domain);
1140 domain->last_status = NT_STATUS_SERVER_DISABLED;
1144 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1145 status = NT_STATUS_NO_MEMORY;
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;
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;
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. */
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;
1203 (*name_types) = NULL;
1206 for (i=0; i<num_members; i++) {
1207 enum lsa_SidType name_type;
1208 char *name, *domain_name;
1211 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
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
1222 status = ads_ntstatus(rc);
1226 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
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(
1237 (*name_types)[*num_names] = name_type;
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);
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,
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,
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(
1296 (*name_types)[*num_names] = name_types_nocache[i];
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)));
1316 status = NT_STATUS_OK;
1317 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1318 sid_string_dbg(group_sid)));
1322 TALLOC_FREE(tmp_ctx);
1327 /* find the sequence number for a domain */
1328 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
1330 ADS_STRUCT *ads = NULL;
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",
1339 return NT_STATUS_OK;
1342 *seq = DOM_SEQUENCE_NONE;
1344 ads = ads_cached_connection(domain);
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;
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;
1393 struct rpc_pipe_client *cli;
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;
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,
1429 if (!NT_STATUS_IS_OK(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 */
1443 for (i = 0; i < trusts->count; i++) {
1444 struct netr_DomainTrust *trust = &trusts->array[i];
1445 struct winbindd_domain 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
1456 if ((trust->trust_attributes
1457 == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1460 DEBUG(10,("trusted_domains: Skipping external trusted "
1461 "domain %s because it is outside of our "
1463 trust->netbios_name));
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);
1473 sid_copy(&d.sid, trust->sid);
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 );
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);
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 );
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(),
1532 d.domain_flags = parent->trust_flags;
1533 d.domain_type = parent->trust_type;
1534 d.domain_trust_attribs = parent->trust_attribs;
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 );
1550 /* the ADS backend methods are exposed via this structure */
1551 struct winbindd_methods ads_methods = {