/* convert a domain SID to a user or group name */ static NTSTATUS sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **domain_name, char **name, enum lsa_SidType *type) { const char *dom, *nam; DEBUG(10, ("Converting SID %s\n", sid_string_static(sid))); /* Paranoia check */ if (!sid_check_is_in_builtin(sid) && !sid_check_is_in_our_domain(sid)) { DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with " "passdb backend\n", sid_string_static(sid))); return NT_STATUS_NONE_MAPPED; } if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) { return NT_STATUS_NONE_MAPPED; } *domain_name = talloc_strdup(mem_ctx, dom); *name = talloc_strdup(mem_ctx, nam); return NT_STATUS_OK; }
/* Lookup user information from a rid or username. */ static NTSTATUS sam_query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid, struct wbint_userinfo *user_info) { struct rpc_pipe_client *samr_pipe; struct policy_handle dom_pol; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_query_user\n")); ZERO_STRUCT(dom_pol); /* Paranoia check */ if (!sid_check_is_in_our_domain(user_sid)) { return NT_STATUS_NO_SUCH_USER; } if (user_info) { user_info->homedir = NULL; user_info->shell = NULL; user_info->primary_gid = (gid_t) -1; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol); if (!NT_STATUS_IS_OK(status)) { goto done; } b = samr_pipe->binding_handle; status = rpc_query_user(tmp_ctx, samr_pipe, &dom_pol, &domain->sid, user_sid, user_info); done: if (b && is_valid_policy_hnd(&dom_pol)) { dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result); } TALLOC_FREE(tmp_ctx); return status; }
static int net_groupmap_cleanup(struct net_context *c, int argc, const char **argv) { GROUP_MAP **maps = NULL; size_t i, entries; if (c->display_usage) { d_printf( "%s\n" "net groupmap cleanup\n" " %s\n", _("Usage:"), _("Delete all group mappings")); return 0; } if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &maps, &entries, ENUM_ALL_MAPPED)) { d_fprintf(stderr, _("Could not list group mappings\n")); return -1; } for (i=0; i<entries; i++) { if (maps[i]->gid == -1) printf(_("Group %s is not mapped\n"), maps[i]->nt_name); if (!sid_check_is_in_our_domain(&maps[i]->sid)) { printf(_("Deleting mapping for NT Group %s, sid %s\n"), maps[i]->nt_name, sid_string_tos(&maps[i]->sid)); pdb_delete_group_mapping_entry(maps[i]->sid); } } TALLOC_FREE(maps); return 0; }
/* convert a domain SID to a user or group name */ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *sid, char **pdomain_name, char **pname, enum lsa_SidType *ptype) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; char *domain_name = NULL; char *name = NULL; enum lsa_SidType type; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_sid_to_name\n")); ZERO_STRUCT(lsa_policy); /* Paranoia check */ if (!sid_check_is_in_builtin(sid) && !sid_check_is_in_our_domain(sid) && !sid_check_is_in_unix_users(sid) && !sid_check_is_unix_users(sid) && !sid_check_is_in_unix_groups(sid) && !sid_check_is_unix_groups(sid) && !sid_check_is_in_wellknown_domain(sid)) { DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to " "lookup SID %s\n", sid_string_dbg(sid))); return NT_STATUS_NONE_MAPPED; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_sid_to_name(tmp_ctx, lsa_pipe, &lsa_policy, domain, sid, &domain_name, &name, &type); if (ptype) { *ptype = type; } if (pname) { *pname = talloc_move(mem_ctx, &name); } if (pdomain_name) { *pdomain_name = talloc_move(mem_ctx, &domain_name); } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
/******************************************************************* gets a domain user's groups ********************************************************************/ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SAM_ACCOUNT *sam_pass) { GROUP_MAP *map=NULL; int i, num, num_entries, cur_gid=0; struct group *grp; DOM_GID *gids; fstring user_name; uint32 grid; uint32 tmp_rid; BOOL ret; *numgroups= 0; fstrcpy(user_name, pdb_get_username(sam_pass)); grid=pdb_get_group_rid(sam_pass); DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name)); /* we must wrap this is become/unbecome root for ldap backends */ become_root(); /* first get the list of the domain groups */ ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED); unbecome_root(); /* end wrapper for group enumeration */ if ( !ret ) return False; DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries)); /* * alloc memory. In the worse case, we alloc memory for nothing. * but I prefer to alloc for nothing * than reallocing everytime. */ gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) * num_entries); /* for each group, check if the user is a member of. Only include groups from this domain */ for(i=0; i<num_entries; i++) { if ( !sid_check_is_in_our_domain(&map[i].sid) ) { DEBUG(10,("get_domain_user_groups: skipping check of %s since it is not in our domain\n", map[i].nt_name)); continue; } if ((grp=sys_getgrgid(map[i].gid)) == NULL) { /* very weird !!! */ DEBUG(5,("get_domain_user_groups: gid %d doesn't exist anymore !\n", (int)map[i].gid)); continue; } for(num=0; grp->gr_mem[num]!=NULL; num++) { if(strcmp(grp->gr_mem[num], user_name)==0) { /* we found the user, add the group to the list */ sid_peek_rid(&map[i].sid, &(gids[cur_gid].g_rid)); gids[cur_gid].attr=7; DEBUG(10,("get_domain_user_groups: user found in group %s\n", map[i].nt_name)); cur_gid++; break; } } } /* we have checked the groups */ /* we must now check the gid of the user or the primary group rid, that's the same */ for (i=0; i<cur_gid && grid!=gids[i].g_rid; i++) ; /* the user's gid is already there */ if (i!=cur_gid) { /* * the primary group of the user but be the first one in the list * don't ask ! JFM. */ gids[i].g_rid=gids[0].g_rid; gids[0].g_rid=grid; goto done; } for(i=0; i<num_entries; i++) { sid_peek_rid(&map[i].sid, &tmp_rid); if (tmp_rid==grid) { /* * the primary group of the user but be the first one in the list * don't ask ! JFM. */ gids[cur_gid].g_rid=gids[0].g_rid; gids[0].g_rid=tmp_rid; gids[cur_gid].attr=7; DEBUG(10,("get_domain_user_groups: primary gid of user found in group %s\n", map[i].nt_name)); cur_gid++; goto done; /* leave the loop early */ } } DEBUG(0,("get_domain_user_groups: primary gid of user [%s] is not a Domain group !\n", user_name)); DEBUGADD(0,("get_domain_user_groups: You should fix it, NT doesn't like that\n")); done: *pgids=gids; *numgroups=cur_gid; SAFE_FREE(map); return True; }
/* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, uint32 *num_names, DOM_SID **sid_mem, char ***names, uint32 **name_types) { size_t i, num_members, num_mapped; uint32 *rids; NTSTATUS result; const DOM_SID **sids; struct lsa_dom_info *lsa_domains; struct lsa_name_info *lsa_names; TALLOC_CTX *tmp_ctx; if (!sid_check_is_in_our_domain(group_sid)) { /* There's no groups, only aliases in BUILTIN */ return NT_STATUS_NO_SUCH_GROUP; } if (!(tmp_ctx = talloc_init("lookup_groupmem"))) { return NT_STATUS_NO_MEMORY; } result = pdb_enum_group_members(tmp_ctx, group_sid, &rids, &num_members); if (!NT_STATUS_IS_OK(result)) { TALLOC_FREE(tmp_ctx); return result; } if (num_members == 0) { *num_names = 0; *sid_mem = NULL; *names = NULL; *name_types = NULL; TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; } *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members); *names = TALLOC_ARRAY(mem_ctx, char *, num_members); *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members); sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members); if (((*sid_mem) == NULL) || ((*names) == NULL) || ((*name_types) == NULL) || (sids == NULL)) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } /* * Prepare an array of sid pointers for the lookup_sids calling * convention. */ for (i=0; i<num_members; i++) { DOM_SID *sid = &((*sid_mem)[i]); if (!sid_compose(sid, &domain->sid, rids[i])) { TALLOC_FREE(tmp_ctx); return NT_STATUS_INTERNAL_ERROR; } sids[i] = sid; } result = lookup_sids(tmp_ctx, num_members, sids, 1, &lsa_domains, &lsa_names); if (!NT_STATUS_IS_OK(result)) { TALLOC_FREE(tmp_ctx); return result; } num_mapped = 0; for (i=0; i<num_members; i++) { if (lsa_names[i].type != SID_NAME_USER) { DEBUG(2, ("Got %s as group member -- ignoring\n", sid_type_lookup(lsa_names[i].type))); continue; } if (!((*names)[i] = talloc_strdup((*names), lsa_names[i].name))) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } (*name_types)[i] = lsa_names[i].type; num_mapped += 1; } *num_names = num_mapped; TALLOC_FREE(tmp_ctx); return NT_STATUS_OK; }