/* convert a sid to a user or group name */ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, enum SID_NAME_USE *type) { const char *attrs[] = {"userPrincipalName", "sAMAccountName", "sAMAccountType", NULL}; ADS_STATUS rc; void *msg = NULL; char *ldap_exp = NULL; char *sidstr = NULL; uint32 atype; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; if (!(sidstr = sid_binstring(sid))) { DEBUG(1,("ads_sid_to_name: sid_binstring failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) { DEBUG(1,("ads_sid_to_name: asprintf failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } rc = ads_search_retry(ads, &msg, ldap_exp, attrs); if (!ADS_ERR_OK(rc)) { status = ads_ntstatus(rc); DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc))); goto done; } if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { goto done; } *name = ads_pull_username(ads, mem_ctx, msg); if (!*name) { DEBUG(1,("ads_sid_to_name: ads_pull_username retuned NULL!\n")); status = NT_STATUS_NO_MEMORY; goto done; } *type = ads_atype_map(atype); status = NT_STATUS_OK; DEBUG(3,("ads sid_to_name mapped %s\n", *name)); done: if (msg) ads_msgfree(ads, msg); SAFE_FREE(ldap_exp); SAFE_FREE(sidstr); return status; }
/* 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 DOM_SID *group_sid, enum lsa_SidType type, uint32 *num_names, 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; 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 = sid_binstring(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, 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, 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 {
ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **dn) { ADS_STATUS rc; LDAPMessage *msg = NULL; LDAPMessage *entry = NULL; char *ldap_exp; char *sidstr = NULL; int count; char *dn2 = NULL; const char *attr[] = { "dn", NULL }; if (!(sidstr = sid_binstring(sid))) { DEBUG(1,("ads_sid_to_dn: sid_binstring failed!\n")); rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto done; } if(!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr))) { DEBUG(1,("ads_sid_to_dn: talloc_asprintf failed!\n")); rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto done; } rc = ads_search_retry(ads, (void **)&msg, ldap_exp, attr); if (!ADS_ERR_OK(rc)) { DEBUG(1,("ads_sid_to_dn ads_search: %s\n", ads_errstr(rc))); goto done; } if ((count = ads_count_replies(ads, msg)) != 1) { fstring sid_string; DEBUG(1,("ads_sid_to_dn (sid=%s): Not found (count=%d)\n", sid_to_string(sid_string, sid), count)); rc = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); goto done; } entry = ads_first_entry(ads, msg); dn2 = ads_get_dn(ads, entry); if (!dn2) { rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto done; } *dn = talloc_strdup(mem_ctx, dn2); if (!*dn) { ads_memfree(ads, dn2); rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); goto done; } rc = ADS_ERROR_NT(NT_STATUS_OK); DEBUG(3,("ads sid_to_dn mapped %s\n", dn2)); SAFE_FREE(dn2); done: if (msg) ads_msgfree(ads, msg); if (dn2) ads_memfree(ads, dn2); SAFE_FREE(sidstr); return rc; }
/* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, struct wbint_userinfo *info) { ADS_STRUCT *ads = NULL; const char *attrs[] = { "*", NULL }; ADS_STATUS rc; int count; LDAPMessage *msg = NULL; char *ldap_exp; char *sidstr; uint32 group_rid; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; struct netr_SamInfo3 *user = NULL; gid_t gid; DEBUG(3,("ads: query_user\n")); info->homedir = NULL; info->shell = NULL; info->primary_gid = (gid_t)-1; /* try netsamlogon cache first */ if ( (user = netsamlogon_cache_get( mem_ctx, sid )) != NULL ) { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_dbg(sid))); sid_compose(&info->user_sid, &domain->sid, user->base.rid); sid_compose(&info->group_sid, &domain->sid, user->base.primary_gid); info->acct_name = talloc_strdup(mem_ctx, user->base.account_name.string); info->full_name = talloc_strdup(mem_ctx, user->base.full_name.string); nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, &info->homedir, &info->shell, &info->full_name, &gid ); info->primary_gid = gid; TALLOC_FREE(user); return NT_STATUS_OK; } if ( !winbindd_can_contact_domain(domain)) { DEBUG(8,("query_user: No incoming trust from domain %s\n", domain->name)); /* We still need to generate some basic information about the user even if we cannot contact the domain. Most of this stuff we can deduce. */ sid_copy( &info->user_sid, sid ); /* Assume "Domain Users" for the primary group */ sid_compose(&info->group_sid, &domain->sid, DOMAIN_GROUP_RID_USERS ); /* Try to fill in what the nss_info backend can do */ nss_get_info_cached( domain, sid, mem_ctx, NULL, NULL, &info->homedir, &info->shell, &info->full_name, &gid); info->primary_gid = gid; status = NT_STATUS_OK; goto done; } /* no cache...do the query */ if ( (ads = ads_cached_connection(domain)) == NULL ) { domain->last_status = NT_STATUS_SERVER_DISABLED; goto done; } sidstr = sid_binstring(talloc_tos(), sid); if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) { status = NT_STATUS_NO_MEMORY; goto done; } rc = ads_search_retry(ads, &msg, ldap_exp, attrs); free(ldap_exp); TALLOC_FREE(sidstr); if (!ADS_ERR_OK(rc) || !msg) { DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_string_dbg(sid), ads_errstr(rc))); goto done; } count = ads_count_replies(ads, msg); if (count != 1) { DEBUG(1,("query_user(sid=%s): Not found\n", sid_string_dbg(sid))); goto done; } info->acct_name = ads_pull_username(ads, mem_ctx, msg); nss_get_info_cached( domain, sid, mem_ctx, ads, msg, &info->homedir, &info->shell, &info->full_name, &gid); info->primary_gid = gid; if (info->full_name == NULL) { info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); } if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { DEBUG(1,("No primary group for %s !?\n", sid_string_dbg(sid))); goto done; } sid_copy(&info->user_sid, sid); sid_compose(&info->group_sid, &domain->sid, group_rid); status = NT_STATUS_OK; DEBUG(3,("ads query_user gave %s\n", info->acct_name)); done: if (msg) ads_msgfree(ads, msg); return status; }