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 "../librpc/gen_ndr/ndr_netlogon_c.h"
27 #include "../libds/common/flags.h"
30 #include "../libcli/ldap/ldap_ndr.h"
31 #include "../libcli/security/security.h"
32 #include "../libds/common/flag_mapping.h"
37 #define DBGC_CLASS DBGC_WINBIND
39 extern struct winbindd_methods reconnect_methods;
42 return our ads connections structure for a domain. We keep the connection
43 open to make things faster
45 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
50 struct sockaddr_storage dc_ss;
52 DEBUG(10,("ads_cached_connection\n"));
54 if (domain->private_data) {
57 time_t now = time(NULL);
59 /* check for a valid structure */
60 ads = (ADS_STRUCT *)domain->private_data;
62 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
64 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
65 (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
67 if ( ads->config.realm && (expire > now)) {
70 /* we own this ADS_STRUCT so make sure it goes away */
71 DEBUG(7,("Deleting expired krb5 credential cache\n"));
74 ads_kdestroy("MEMORY:winbind_ccache");
75 domain->private_data = NULL;
79 /* we don't want this to affect the users ccache */
80 setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1);
82 ads = ads_init(domain->alt_name, domain->name, NULL);
84 DEBUG(1,("ads_init for domain %s failed\n", domain->name));
88 /* the machine acct password might have change - fetch it every time */
90 SAFE_FREE(ads->auth.password);
91 SAFE_FREE(ads->auth.realm);
95 if ( !pdb_get_trusteddom_pw( domain->name, &ads->auth.password, NULL, NULL ) ) {
99 ads->auth.realm = SMB_STRDUP( ads->server.realm );
100 strupper_m( ads->auth.realm );
103 struct winbindd_domain *our_domain = domain;
105 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
107 /* always give preference to the alt_name in our
108 primary domain if possible */
110 if ( !domain->primary )
111 our_domain = find_our_domain();
113 if ( our_domain->alt_name[0] != '\0' ) {
114 ads->auth.realm = SMB_STRDUP( our_domain->alt_name );
115 strupper_m( ads->auth.realm );
118 ads->auth.realm = SMB_STRDUP( lp_realm() );
121 ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
123 /* Setup the server affinity cache. We don't reaally care
124 about the name. Just setup affinity and the KRB5_CONFIG
127 get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ss );
129 status = ads_connect(ads);
130 if (!ADS_ERR_OK(status) || !ads->config.realm) {
131 DEBUG(1,("ads_connect for domain %s failed: %s\n",
132 domain->name, ads_errstr(status)));
135 /* if we get ECONNREFUSED then it might be a NT4
136 server, fall back to MSRPC */
137 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
138 status.err.rc == ECONNREFUSED) {
139 /* 'reconnect_methods' is the MS-RPC backend. */
140 DEBUG(1,("Trying MSRPC methods\n"));
141 domain->backend = &reconnect_methods;
146 /* set the flag that says we don't own the memory even
147 though we do so that ads_destroy() won't destroy the
148 structure we pass back by reference */
150 ads->is_mine = False;
152 domain->private_data = (void *)ads;
157 /* Query display info for a realm. This is the basic user list fn */
158 static NTSTATUS query_user_list(struct winbindd_domain *domain,
161 struct wbint_userinfo **pinfo)
163 ADS_STRUCT *ads = NULL;
164 const char *attrs[] = { "*", NULL };
167 LDAPMessage *res = NULL;
168 LDAPMessage *msg = NULL;
169 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
173 DEBUG(3,("ads: query_user_list\n"));
175 if ( !winbindd_can_contact_domain( domain ) ) {
176 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
181 ads = ads_cached_connection(domain);
184 domain->last_status = NT_STATUS_SERVER_DISABLED;
188 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
189 if (!ADS_ERR_OK(rc) || !res) {
190 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
194 count = ads_count_replies(ads, res);
196 DEBUG(1,("query_user_list: No users found\n"));
200 (*pinfo) = TALLOC_ZERO_ARRAY(mem_ctx, struct wbint_userinfo, count);
202 status = NT_STATUS_NO_MEMORY;
208 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
209 struct wbint_userinfo *info = &((*pinfo)[count]);
213 if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
214 ds_atype_map(atype) != SID_NAME_USER) {
215 DEBUG(1,("Not a user account? atype=0x%x\n", atype));
219 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
220 info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
221 info->homedir = NULL;
223 info->primary_gid = (gid_t)-1;
225 if (!ads_pull_sid(ads, msg, "objectSid",
227 DEBUG(1, ("No sid for %s !?\n", info->acct_name));
231 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) {
232 DEBUG(1, ("No primary group for %s !?\n",
236 sid_compose(&info->group_sid, &domain->sid, group);
241 (*num_entries) = count;
242 ads_msgfree(ads, res);
244 for (i=0; i<count; i++) {
245 struct wbint_userinfo *info = &((*pinfo)[i]);
246 const char *gecos = NULL;
247 gid_t primary_gid = (gid_t)-1;
249 status = nss_get_info_cached(domain, &info->user_sid, mem_ctx,
250 &info->homedir, &info->shell,
251 &gecos, &primary_gid);
252 if (!NT_STATUS_IS_OK(status)) {
254 * Deliberately ignore this error, there might be more
261 info->full_name = gecos;
263 info->primary_gid = primary_gid;
266 status = NT_STATUS_OK;
268 DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries)));
274 /* list all domain groups */
275 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
278 struct wb_acct_info **info)
280 ADS_STRUCT *ads = NULL;
281 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
282 "name", "objectSid", NULL};
285 LDAPMessage *res = NULL;
286 LDAPMessage *msg = NULL;
287 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
289 bool enum_dom_local_groups = False;
293 DEBUG(3,("ads: enum_dom_groups\n"));
295 if ( !winbindd_can_contact_domain( domain ) ) {
296 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
301 /* only grab domain local groups for our domain */
302 if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
303 enum_dom_local_groups = True;
306 /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
309 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
310 * default value, it MUST be absent. In case of extensible matching the
311 * "dnattr" boolean defaults to FALSE and so it must be only be present
314 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
315 * filter using bitwise matching rule then the buggy AD fails to decode
316 * the extensible match. As a workaround set it to TRUE and thereby add
317 * the dnAttributes "dn" field to cope with those older AD versions.
318 * It should not harm and won't put any additional load on the AD since
319 * none of the dn components have a bitmask-attribute.
321 * Thanks to Ralf Haferkamp for input and testing - Guenther */
323 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
324 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
325 ADS_LDAP_MATCHING_RULE_BIT_AND,
326 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
328 if (filter == NULL) {
329 status = NT_STATUS_NO_MEMORY;
333 ads = ads_cached_connection(domain);
336 domain->last_status = NT_STATUS_SERVER_DISABLED;
340 rc = ads_search_retry(ads, &res, filter, attrs);
341 if (!ADS_ERR_OK(rc) || !res) {
342 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
346 count = ads_count_replies(ads, res);
348 DEBUG(1,("enum_dom_groups: No groups found\n"));
352 (*info) = TALLOC_ZERO_ARRAY(mem_ctx, struct wb_acct_info, count);
354 status = NT_STATUS_NO_MEMORY;
360 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
365 name = ads_pull_username(ads, mem_ctx, msg);
366 gecos = ads_pull_string(ads, mem_ctx, msg, "name");
367 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
368 DEBUG(1,("No sid for %s !?\n", name));
372 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
373 DEBUG(1,("No rid for %s !?\n", name));
377 fstrcpy((*info)[i].acct_name, name);
378 fstrcpy((*info)[i].acct_desc, gecos);
379 (*info)[i].rid = rid;
385 status = NT_STATUS_OK;
387 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
391 ads_msgfree(ads, res);
396 /* list all domain local groups */
397 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
400 struct wb_acct_info **info)
403 * This is a stub function only as we returned the domain
404 * local groups in enum_dom_groups() if the domain->native field
405 * was true. This is a simple performance optimization when
408 * if we ever need to enumerate domain local groups separately,
409 * then this optimization in enum_dom_groups() will need
417 /* convert a single name to a sid in a domain - use rpc methods */
418 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
420 const char *domain_name,
424 enum lsa_SidType *type)
426 return reconnect_methods.name_to_sid(domain, mem_ctx,
427 domain_name, name, flags,
431 /* convert a domain SID to a user or group name - use rpc methods */
432 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
434 const struct dom_sid *sid,
437 enum lsa_SidType *type)
439 return reconnect_methods.sid_to_name(domain, mem_ctx, sid,
440 domain_name, name, type);
443 /* convert a list of rids to names - use rpc methods */
444 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
446 const struct dom_sid *sid,
451 enum lsa_SidType **types)
453 return reconnect_methods.rids_to_names(domain, mem_ctx, sid,
455 domain_name, names, types);
458 /* If you are looking for "dn_lookup": Yes, it used to be here!
459 * It has gone now since it was a major speed bottleneck in
460 * lookup_groupmem (its only use). It has been replaced by
461 * an rpc lookup sids call... R.I.P. */
463 /* Lookup user information from a rid */
464 static NTSTATUS query_user(struct winbindd_domain *domain,
466 const struct dom_sid *sid,
467 struct wbint_userinfo *info)
469 ADS_STRUCT *ads = NULL;
470 const char *attrs[] = { "*", NULL };
473 LDAPMessage *msg = NULL;
477 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
478 struct netr_SamInfo3 *user = NULL;
483 DEBUG(3,("ads: query_user\n"));
485 info->homedir = NULL;
488 /* try netsamlogon cache first */
490 if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL )
492 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
493 sid_string_dbg(sid)));
495 sid_compose(&info->user_sid, &domain->sid, user->base.rid);
496 sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid);
498 info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string);
499 info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string);
501 nss_get_info_cached( domain, sid, mem_ctx,
502 &info->homedir, &info->shell, &info->full_name,
504 info->primary_gid = gid;
511 if ( !winbindd_can_contact_domain(domain)) {
512 DEBUG(8,("query_user: No incoming trust from domain %s\n",
515 /* We still need to generate some basic information
516 about the user even if we cannot contact the
517 domain. Most of this stuff we can deduce. */
519 sid_copy( &info->user_sid, sid );
521 /* Assume "Domain Users" for the primary group */
523 sid_compose(&info->group_sid, &domain->sid, DOMAIN_RID_USERS );
525 /* Try to fill in what the nss_info backend can do */
527 nss_get_info_cached( domain, sid, mem_ctx,
528 &info->homedir, &info->shell, &info->full_name,
530 info->primary_gid = gid;
535 /* no cache...do the query */
537 if ( (ads = ads_cached_connection(domain)) == NULL ) {
538 domain->last_status = NT_STATUS_SERVER_DISABLED;
539 return NT_STATUS_SERVER_DISABLED;
542 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
544 ret = asprintf(&ldap_exp, "(objectSid=%s)", sidstr);
547 return NT_STATUS_NO_MEMORY;
549 rc = ads_search_retry(ads, &msg, ldap_exp, attrs);
551 if (!ADS_ERR_OK(rc) || !msg) {
552 DEBUG(1,("query_user(sid=%s) ads_search: %s\n",
553 sid_string_dbg(sid), ads_errstr(rc)));
554 return ads_ntstatus(rc);
557 count = ads_count_replies(ads, msg);
559 DEBUG(1,("query_user(sid=%s): Not found\n",
560 sid_string_dbg(sid)));
561 ads_msgfree(ads, msg);
562 return NT_STATUS_NO_SUCH_USER;
565 info->acct_name = ads_pull_username(ads, mem_ctx, msg);
567 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
568 DEBUG(1,("No primary group for %s !?\n",
569 sid_string_dbg(sid)));
570 ads_msgfree(ads, msg);
571 return NT_STATUS_NO_SUCH_USER;
573 sid_copy(&info->user_sid, sid);
574 sid_compose(&info->group_sid, &domain->sid, group_rid);
577 * We have to fetch the "name" attribute before doing the
578 * nss_get_info_cached call. nss_get_info_cached might destroy
579 * the ads struct, potentially invalidating the ldap message.
581 ads_name = ads_pull_string(ads, mem_ctx, msg, "name");
583 ads_msgfree(ads, msg);
586 status = nss_get_info_cached( domain, sid, mem_ctx,
587 &info->homedir, &info->shell, &info->full_name,
589 info->primary_gid = gid;
590 if (!NT_STATUS_IS_OK(status)) {
591 DEBUG(1, ("nss_get_info_cached failed: %s\n",
596 if (info->full_name == NULL) {
597 info->full_name = ads_name;
599 TALLOC_FREE(ads_name);
602 status = NT_STATUS_OK;
604 DEBUG(3,("ads query_user gave %s\n", info->acct_name));
608 /* Lookup groups a user is a member of - alternate method, for when
609 tokenGroups are not available. */
610 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
613 struct dom_sid *primary_group,
614 uint32_t *p_num_groups, struct dom_sid **user_sids)
617 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
619 LDAPMessage *res = NULL;
620 LDAPMessage *msg = NULL;
623 const char *group_attrs[] = {"objectSid", NULL};
625 uint32_t num_groups = 0;
627 DEBUG(3,("ads: lookup_usergroups_member\n"));
629 if ( !winbindd_can_contact_domain( domain ) ) {
630 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
635 ads = ads_cached_connection(domain);
638 domain->last_status = NT_STATUS_SERVER_DISABLED;
642 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
643 status = NT_STATUS_NO_MEMORY;
647 ldap_exp = talloc_asprintf(mem_ctx,
648 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
650 ADS_LDAP_MATCHING_RULE_BIT_AND,
651 GROUP_TYPE_SECURITY_ENABLED);
653 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
654 TALLOC_FREE(escaped_dn);
655 status = NT_STATUS_NO_MEMORY;
659 TALLOC_FREE(escaped_dn);
661 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
663 if (!ADS_ERR_OK(rc) || !res) {
664 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
665 return ads_ntstatus(rc);
668 count = ads_count_replies(ads, res);
673 /* always add the primary group to the sid array */
674 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
676 if (!NT_STATUS_IS_OK(status)) {
681 for (msg = ads_first_entry(ads, res); msg;
682 msg = ads_next_entry(ads, msg)) {
683 struct dom_sid group_sid;
685 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
686 DEBUG(1,("No sid for this group ?!?\n"));
690 /* ignore Builtin groups from ADS - Guenther */
691 if (sid_check_is_in_builtin(&group_sid)) {
695 status = add_sid_to_array(mem_ctx, &group_sid,
696 user_sids, &num_groups);
697 if (!NT_STATUS_IS_OK(status)) {
704 *p_num_groups = num_groups;
705 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
707 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
710 ads_msgfree(ads, res);
715 /* Lookup groups a user is a member of - alternate method, for when
716 tokenGroups are not available. */
717 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
720 struct dom_sid *primary_group,
721 uint32_t *p_num_groups,
722 struct dom_sid **user_sids)
725 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
727 const char *attrs[] = {"memberOf", NULL};
728 uint32_t num_groups = 0;
729 struct dom_sid *group_sids = NULL;
731 char **strings = NULL;
732 size_t num_strings = 0, num_sids = 0;
735 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
737 if ( !winbindd_can_contact_domain( domain ) ) {
738 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
739 "domain %s\n", domain->name));
743 ads = ads_cached_connection(domain);
746 domain->last_status = NT_STATUS_SERVER_DISABLED;
747 return NT_STATUS_UNSUCCESSFUL;
750 rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
751 ADS_EXTENDED_DN_HEX_STRING,
752 &strings, &num_strings);
754 if (!ADS_ERR_OK(rc)) {
755 DEBUG(1,("lookup_usergroups_memberof ads_search "
756 "member=%s: %s\n", user_dn, ads_errstr(rc)));
757 return ads_ntstatus(rc);
763 /* always add the primary group to the sid array */
764 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
766 if (!NT_STATUS_IS_OK(status)) {
770 group_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_strings + 1);
772 status = NT_STATUS_NO_MEMORY;
776 for (i=0; i<num_strings; i++) {
777 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
778 ADS_EXTENDED_DN_HEX_STRING,
780 if (!ADS_ERR_OK(rc)) {
781 /* ignore members without SIDs */
782 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
783 NT_STATUS_NOT_FOUND)) {
787 status = ads_ntstatus(rc);
795 DEBUG(1,("No memberOf for this user?!?\n"));
796 status = NT_STATUS_NO_MEMORY;
800 for (i=0; i<num_sids; i++) {
802 /* ignore Builtin groups from ADS - Guenther */
803 if (sid_check_is_in_builtin(&group_sids[i])) {
807 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
809 if (!NT_STATUS_IS_OK(status)) {
815 *p_num_groups = num_groups;
816 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
818 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
822 TALLOC_FREE(strings);
823 TALLOC_FREE(group_sids);
829 /* Lookup groups a user is a member of. */
830 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
832 const struct dom_sid *sid,
833 uint32 *p_num_groups, struct dom_sid **user_sids)
835 ADS_STRUCT *ads = NULL;
836 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
839 LDAPMessage *msg = NULL;
840 char *user_dn = NULL;
841 struct dom_sid *sids;
843 struct dom_sid primary_group;
844 uint32 primary_group_rid;
845 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
846 uint32_t num_groups = 0;
848 DEBUG(3,("ads: lookup_usergroups\n"));
851 status = lookup_usergroups_cached(domain, mem_ctx, sid,
852 p_num_groups, user_sids);
853 if (NT_STATUS_IS_OK(status)) {
857 if ( !winbindd_can_contact_domain( domain ) ) {
858 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
861 /* Tell the cache manager not to remember this one */
863 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
866 ads = ads_cached_connection(domain);
869 domain->last_status = NT_STATUS_SERVER_DISABLED;
870 status = NT_STATUS_SERVER_DISABLED;
874 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
876 if (!ADS_ERR_OK(rc)) {
877 status = ads_ntstatus(rc);
878 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
879 "%s\n", sid_string_dbg(sid), ads_errstr(rc)));
883 count = ads_count_replies(ads, msg);
885 status = NT_STATUS_UNSUCCESSFUL;
886 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
887 "invalid number of results (count=%d)\n",
888 sid_string_dbg(sid), count));
893 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
894 sid_string_dbg(sid)));
895 status = NT_STATUS_UNSUCCESSFUL;
899 user_dn = ads_get_dn(ads, mem_ctx, msg);
900 if (user_dn == NULL) {
901 status = NT_STATUS_NO_MEMORY;
905 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
906 DEBUG(1,("%s: No primary group for sid=%s !?\n",
907 domain->name, sid_string_dbg(sid)));
911 sid_compose(&primary_group, &domain->sid, primary_group_rid);
913 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
915 /* there must always be at least one group in the token,
916 unless we are talking to a buggy Win2k server */
918 /* actually this only happens when the machine account has no read
919 * permissions on the tokenGroup attribute - gd */
925 /* lookup what groups this user is a member of by DN search on
928 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
930 &num_groups, user_sids);
931 *p_num_groups = num_groups;
932 if (NT_STATUS_IS_OK(status)) {
936 /* lookup what groups this user is a member of by DN search on
939 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
941 &num_groups, user_sids);
942 *p_num_groups = num_groups;
949 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
951 if (!NT_STATUS_IS_OK(status)) {
955 for (i=0;i<count;i++) {
957 /* ignore Builtin groups from ADS - Guenther */
958 if (sid_check_is_in_builtin(&sids[i])) {
962 status = add_sid_to_array_unique(mem_ctx, &sids[i],
963 user_sids, &num_groups);
964 if (!NT_STATUS_IS_OK(status)) {
969 *p_num_groups = (uint32)num_groups;
970 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
972 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
973 sid_string_dbg(sid)));
975 TALLOC_FREE(user_dn);
976 ads_msgfree(ads, msg);
980 /* Lookup aliases a user is member of - use rpc methods */
981 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
983 uint32 num_sids, const struct dom_sid *sids,
984 uint32 *num_aliases, uint32 **alias_rids)
986 return reconnect_methods.lookup_useraliases(domain, mem_ctx,
993 find the members of a group, given a group rid and domain
995 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
997 const struct dom_sid *group_sid,
998 enum lsa_SidType type,
1000 struct dom_sid **sid_mem, char ***names,
1001 uint32 **name_types)
1004 ADS_STRUCT *ads = NULL;
1006 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1008 char **members = NULL;
1010 size_t num_members = 0;
1012 struct dom_sid *sid_mem_nocache = NULL;
1013 char **names_nocache = NULL;
1014 enum lsa_SidType *name_types_nocache = NULL;
1015 char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */
1016 uint32 num_nocache = 0;
1017 TALLOC_CTX *tmp_ctx = NULL;
1019 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1020 sid_string_dbg(group_sid)));
1024 tmp_ctx = talloc_new(mem_ctx);
1026 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1027 status = NT_STATUS_NO_MEMORY;
1031 if ( !winbindd_can_contact_domain( domain ) ) {
1032 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1034 return NT_STATUS_OK;
1037 ads = ads_cached_connection(domain);
1040 domain->last_status = NT_STATUS_SERVER_DISABLED;
1044 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1045 status = NT_STATUS_NO_MEMORY;
1049 /* search for all members of the group */
1050 ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1051 TALLOC_FREE(sidbinstr);
1052 if (ldap_exp == NULL) {
1053 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1054 status = NT_STATUS_NO_MEMORY;
1058 args.control = ADS_EXTENDED_DN_OID;
1059 args.val = ADS_EXTENDED_DN_HEX_STRING;
1060 args.critical = True;
1062 rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1063 ldap_exp, &args, "member", &members, &num_members);
1065 if (!ADS_ERR_OK(rc)) {
1066 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1067 status = NT_STATUS_UNSUCCESSFUL;
1071 DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1073 /* Now that we have a list of sids, we need to get the
1074 * lists of names and name_types belonging to these sids.
1075 * even though conceptually not quite clean, we use the
1076 * RPC call lsa_lookup_sids for this since it can handle a
1077 * list of sids. ldap calls can just resolve one sid at a time.
1079 * At this stage, the sids are still hidden in the exetended dn
1080 * member output format. We actually do a little better than
1081 * stated above: In extracting the sids from the member strings,
1082 * we try to resolve as many sids as possible from the
1083 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1086 (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
1087 (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
1088 (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members);
1089 (sid_mem_nocache) = TALLOC_ZERO_ARRAY(tmp_ctx, struct dom_sid, num_members);
1091 if ((members == NULL) || (*sid_mem == NULL) ||
1092 (*names == NULL) || (*name_types == NULL) ||
1093 (sid_mem_nocache == NULL))
1095 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1096 status = NT_STATUS_NO_MEMORY;
1103 (*name_types) = NULL;
1106 for (i=0; i<num_members; i++) {
1107 enum lsa_SidType name_type;
1108 char *name, *domain_name;
1111 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1113 if (!ADS_ERR_OK(rc)) {
1114 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1115 NT_STATUS_NOT_FOUND)) {
1116 /* Group members can be objects, like Exchange
1117 * Public Folders, that don't have a SID. Skip
1122 status = ads_ntstatus(rc);
1126 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1128 DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1129 "cache\n", sid_string_dbg(&sid)));
1130 sid_copy(&(*sid_mem)[*num_names], &sid);
1131 (*names)[*num_names] = fill_domain_username_talloc(
1137 (*name_types)[*num_names] = name_type;
1141 DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1142 "cache\n", sid_string_dbg(&sid)));
1143 sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1148 DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1149 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1151 /* handle sids not resolved from cache by lsa_lookup_sids */
1152 if (num_nocache > 0) {
1154 status = winbindd_lookup_sids(tmp_ctx,
1160 &name_types_nocache);
1162 if (!(NT_STATUS_IS_OK(status) ||
1163 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1164 NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1166 DEBUG(1, ("lsa_lookupsids call failed with %s "
1167 "- retrying...\n", nt_errstr(status)));
1169 status = winbindd_lookup_sids(tmp_ctx,
1175 &name_types_nocache);
1178 if (NT_STATUS_IS_OK(status) ||
1179 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
1181 /* Copy the entries over from the "_nocache" arrays
1182 * to the result arrays, skipping the gaps the
1183 * lookup_sids call left. */
1184 for (i=0; i < num_nocache; i++) {
1185 if (((names_nocache)[i] != NULL) &&
1186 ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
1188 sid_copy(&(*sid_mem)[*num_names],
1189 &sid_mem_nocache[i]);
1190 (*names)[*num_names] =
1191 fill_domain_username_talloc(
1196 (*name_types)[*num_names] = name_types_nocache[i];
1201 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1202 DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
1203 "not map any SIDs at all.\n"));
1204 /* Don't handle this as an error here.
1205 * There is nothing left to do with respect to the
1206 * overall result... */
1208 else if (!NT_STATUS_IS_OK(status)) {
1209 DEBUG(10, ("lookup_groupmem: Error looking up %d "
1210 "sids via rpc_lsa_lookup_sids: %s\n",
1211 (int)num_members, nt_errstr(status)));
1216 status = NT_STATUS_OK;
1217 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1218 sid_string_dbg(group_sid)));
1222 TALLOC_FREE(tmp_ctx);
1227 /* find the sequence number for a domain */
1228 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
1230 ADS_STRUCT *ads = NULL;
1233 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
1235 if ( !winbindd_can_contact_domain( domain ) ) {
1236 DEBUG(10,("sequence: No incoming trust for domain %s\n",
1239 return NT_STATUS_OK;
1242 *seq = DOM_SEQUENCE_NONE;
1244 ads = ads_cached_connection(domain);
1247 domain->last_status = NT_STATUS_SERVER_DISABLED;
1248 return NT_STATUS_UNSUCCESSFUL;
1251 rc = ads_USN(ads, seq);
1253 if (!ADS_ERR_OK(rc)) {
1255 /* its a dead connection, destroy it */
1257 if (domain->private_data) {
1258 ads = (ADS_STRUCT *)domain->private_data;
1259 ads->is_mine = True;
1261 ads_kdestroy("MEMORY:winbind_ccache");
1262 domain->private_data = NULL;
1265 return ads_ntstatus(rc);
1268 /* find the lockout policy of a domain - use rpc methods */
1269 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1270 TALLOC_CTX *mem_ctx,
1271 struct samr_DomInfo12 *policy)
1273 return reconnect_methods.lockout_policy(domain, mem_ctx, policy);
1276 /* find the password policy of a domain - use rpc methods */
1277 static NTSTATUS password_policy(struct winbindd_domain *domain,
1278 TALLOC_CTX *mem_ctx,
1279 struct samr_DomInfo1 *policy)
1281 return reconnect_methods.password_policy(domain, mem_ctx, policy);
1284 /* get a list of trusted domains */
1285 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1286 TALLOC_CTX *mem_ctx,
1287 struct netr_DomainTrustList *trusts)
1289 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1293 struct rpc_pipe_client *cli;
1295 struct dcerpc_binding_handle *b;
1297 DEBUG(3,("ads: trusted_domains\n"));
1299 ZERO_STRUCTP(trusts);
1301 /* If this is our primary domain or a root in our forest,
1302 query for all trusts. If not, then just look for domain
1303 trusts in the target forest */
1305 if (domain->primary || domain_is_forest_root(domain)) {
1306 flags = NETR_TRUST_FLAG_OUTBOUND |
1307 NETR_TRUST_FLAG_INBOUND |
1308 NETR_TRUST_FLAG_IN_FOREST;
1310 flags = NETR_TRUST_FLAG_IN_FOREST;
1313 result = cm_connect_netlogon(domain, &cli);
1315 if (!NT_STATUS_IS_OK(result)) {
1316 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1317 "for PIPE_NETLOGON (%s)\n",
1318 domain->name, nt_errstr(result)));
1319 return NT_STATUS_UNSUCCESSFUL;
1322 b = cli->binding_handle;
1324 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1329 if (!NT_STATUS_IS_OK(result)) {
1333 if (!W_ERROR_IS_OK(werr)) {
1334 return werror_to_ntstatus(werr);
1336 if (trusts->count == 0) {
1337 return NT_STATUS_OK;
1340 /* Copy across names and sids */
1343 for (i = 0; i < trusts->count; i++) {
1344 struct netr_DomainTrust *trust = &trusts->array[i];
1345 struct winbindd_domain d;
1350 * drop external trusts if this is not our primary
1351 * domain. This means that the returned number of
1352 * domains may be less that the ones actually trusted
1356 if ((trust->trust_attributes
1357 == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1360 DEBUG(10,("trusted_domains: Skipping external trusted "
1361 "domain %s because it is outside of our "
1363 trust->netbios_name));
1367 /* add to the trusted domain cache */
1369 fstrcpy(d.name, trust->netbios_name);
1370 fstrcpy(d.alt_name, trust->dns_name);
1372 sid_copy(&d.sid, trust->sid);
1374 sid_copy(&d.sid, &global_sid_NULL);
1377 if ( domain->primary ) {
1378 DEBUG(10,("trusted_domains(ads): Searching "
1379 "trusted domain list of %s and storing "
1380 "trust flags for domain %s\n",
1381 domain->name, d.alt_name));
1383 d.domain_flags = trust->trust_flags;
1384 d.domain_type = trust->trust_type;
1385 d.domain_trust_attribs = trust->trust_attributes;
1387 wcache_tdc_add_domain( &d );
1389 } else if (domain_is_forest_root(domain)) {
1390 /* Check if we already have this record. If
1391 * we are following our forest root that is not
1392 * our primary domain, we want to keep trust
1393 * flags from the perspective of our primary
1394 * domain not our forest root. */
1395 struct winbindd_tdc_domain *exist = NULL;
1397 exist = wcache_tdc_fetch_domain(
1398 talloc_tos(), trust->netbios_name);
1400 DEBUG(10,("trusted_domains(ads): Searching "
1401 "trusted domain list of %s and "
1402 "storing trust flags for domain "
1403 "%s\n", domain->name, d.alt_name));
1404 d.domain_flags = trust->trust_flags;
1405 d.domain_type = trust->trust_type;
1406 d.domain_trust_attribs =
1407 trust->trust_attributes;
1409 wcache_tdc_add_domain( &d );
1414 /* This gets a little tricky. If we are
1415 following a transitive forest trust, then
1416 innerit the flags, type, and attribs from
1417 the domain we queried to make sure we don't
1418 record the view of the trust from the wrong
1419 side. Always view it from the side of our
1420 primary domain. --jerry */
1421 struct winbindd_tdc_domain *parent = NULL;
1423 DEBUG(10,("trusted_domains(ads): Searching "
1424 "trusted domain list of %s and inheriting "
1425 "trust flags for domain %s\n",
1426 domain->name, d.alt_name));
1428 parent = wcache_tdc_fetch_domain(talloc_tos(),
1431 d.domain_flags = parent->trust_flags;
1432 d.domain_type = parent->trust_type;
1433 d.domain_trust_attribs = parent->trust_attribs;
1435 d.domain_flags = domain->domain_flags;
1436 d.domain_type = domain->domain_type;
1437 d.domain_trust_attribs =
1438 domain->domain_trust_attribs;
1440 TALLOC_FREE(parent);
1442 wcache_tdc_add_domain( &d );
1449 /* the ADS backend methods are exposed via this structure */
1450 struct winbindd_methods ads_methods = {