ADS_STATUS ads_search_retry_extended_dn_ranged(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *dn, const char **attrs, enum ads_extended_dn_flags flags, char ***strings, size_t *num_strings) { ads_control args; args.control = ADS_EXTENDED_DN_OID; args.val = flags; args.critical = True; /* we can only range process one attribute */ if (!attrs || !attrs[0] || attrs[1]) { return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); } return ads_ranged_search(ads, mem_ctx, LDAP_SCOPE_BASE, dn, "(objectclass=*)", &args, attrs[0], strings, num_strings); }
/* find the members of a group, given a group rid and domain */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *group_sid, enum lsa_SidType type, uint32 *num_names, struct dom_sid **sid_mem, char ***names, uint32 **name_types) { ADS_STATUS rc; ADS_STRUCT *ads = NULL; char *ldap_exp; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; char *sidbinstr; char **members = NULL; int i; size_t num_members = 0; ads_control args; struct dom_sid *sid_mem_nocache = NULL; char **names_nocache = NULL; enum lsa_SidType *name_types_nocache = NULL; char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */ uint32 num_nocache = 0; TALLOC_CTX *tmp_ctx = NULL; DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, sid_string_dbg(group_sid))); *num_names = 0; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto done; } if ( !winbindd_can_contact_domain( domain ) ) { DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n", domain->name)); return NT_STATUS_OK; } ads = ads_cached_connection(domain); if (!ads) { domain->last_status = NT_STATUS_SERVER_DISABLED; goto done; } if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } /* search for all members of the group */ ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr); TALLOC_FREE(sidbinstr); if (ldap_exp == NULL) { DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } args.control = ADS_EXTENDED_DN_OID; args.val = ADS_EXTENDED_DN_HEX_STRING; args.critical = True; rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path, ldap_exp, &args, "member", &members, &num_members); if (!ADS_ERR_OK(rc)) { DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc))); status = NT_STATUS_UNSUCCESSFUL; goto done; } DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members)); /* Now that we have a list of sids, we need to get the * lists of names and name_types belonging to these sids. * even though conceptually not quite clean, we use the * RPC call lsa_lookup_sids for this since it can handle a * list of sids. ldap calls can just resolve one sid at a time. * * At this stage, the sids are still hidden in the exetended dn * member output format. We actually do a little better than * stated above: In extracting the sids from the member strings, * we try to resolve as many sids as possible from the * cache. Only the rest is passed to the lsa_lookup_sids call. */ if (num_members) { (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members); (*names) = talloc_zero_array(mem_ctx, char *, num_members); (*name_types) = talloc_zero_array(mem_ctx, uint32, num_members); (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members); if ((members == NULL) || (*sid_mem == NULL) || (*names == NULL) || (*name_types == NULL) || (sid_mem_nocache == NULL)) { DEBUG(1, ("ads: lookup_groupmem: talloc failed\n")); status = NT_STATUS_NO_MEMORY; goto done; } } else {