s4:registry/util - Don't include the trailing '\0' in the internal data format but...
[Samba/ekacnet.git] / source3 / winbindd / winbindd_group.c
blobeab5c26df4fc2e16f1f176c1f45241d170671743
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Jeremy Allison 2001.
8 Copyright (C) Gerald (Jerry) Carter 2003.
9 Copyright (C) Volker Lendecke 2005
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "winbindd.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_WINBIND
31 /* Fill a grent structure from various other information */
33 bool fill_grent(TALLOC_CTX *mem_ctx, struct winbindd_gr *gr,
34 const char *dom_name, const char *gr_name, gid_t unix_gid)
36 fstring full_group_name;
37 char *mapped_name = NULL;
38 struct winbindd_domain *domain = find_domain_from_name_noinit(dom_name);
39 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
41 nt_status = normalize_name_map(mem_ctx, domain, gr_name,
42 &mapped_name);
44 /* Basic whitespace replacement */
45 if (NT_STATUS_IS_OK(nt_status)) {
46 fill_domain_username(full_group_name, dom_name,
47 mapped_name, true);
49 /* Mapped to an aliase */
50 else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) {
51 fstrcpy(full_group_name, mapped_name);
53 /* no change */
54 else {
55 fill_domain_username( full_group_name, dom_name,
56 gr_name, True );
59 gr->gr_gid = unix_gid;
61 /* Group name and password */
63 safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1);
64 safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1);
66 return True;
69 /* Get the list of domain groups and domain aliases for a domain. We fill in
70 the sam_entries and num_sam_entries fields with domain group information.
71 Return True if some groups were returned, False otherwise. */
73 bool get_sam_group_entries(struct getent_state *ent)
75 NTSTATUS status;
76 uint32 num_entries;
77 struct acct_info *name_list = NULL;
78 TALLOC_CTX *mem_ctx;
79 bool result = False;
80 struct acct_info *sam_grp_entries = NULL;
81 struct winbindd_domain *domain;
83 if (ent->got_sam_entries)
84 return False;
86 if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)",
87 ent->domain_name))) {
88 DEBUG(1, ("get_sam_group_entries: "
89 "could not create talloc context!\n"));
90 return False;
93 /* Free any existing group info */
95 SAFE_FREE(ent->sam_entries);
96 ent->num_sam_entries = 0;
97 ent->got_sam_entries = True;
99 /* Enumerate domain groups */
101 num_entries = 0;
103 if (!(domain = find_domain_from_name(ent->domain_name))) {
104 DEBUG(3, ("no such domain %s in get_sam_group_entries\n",
105 ent->domain_name));
106 goto done;
109 /* always get the domain global groups */
111 status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries,
112 &sam_grp_entries);
114 if (!NT_STATUS_IS_OK(status)) {
115 DEBUG(3, ("get_sam_group_entries: "
116 "could not enumerate domain groups! Error: %s\n",
117 nt_errstr(status)));
118 result = False;
119 goto done;
122 /* Copy entries into return buffer */
124 if (num_entries) {
125 name_list = SMB_MALLOC_ARRAY(struct acct_info, num_entries);
126 if (!name_list) {
127 DEBUG(0,("get_sam_group_entries: Failed to malloc "
128 "memory for %d domain groups!\n",
129 num_entries));
130 result = False;
131 goto done;
133 memcpy(name_list, sam_grp_entries,
134 num_entries * sizeof(struct acct_info));
137 ent->num_sam_entries = num_entries;
139 /* get the domain local groups if we are a member of a native win2k
140 * domain and are not using LDAP to get the groups */
142 if ( ( lp_security() != SEC_ADS && domain->native_mode
143 && domain->primary) || domain->internal )
145 DEBUG(4,("get_sam_group_entries: %s domain; "
146 "enumerating local groups as well\n",
147 domain->native_mode ? "Native Mode 2k":
148 "BUILTIN or local"));
150 status = domain->methods->enum_local_groups(domain, mem_ctx,
151 &num_entries,
152 &sam_grp_entries);
154 if ( !NT_STATUS_IS_OK(status) ) {
155 DEBUG(3,("get_sam_group_entries: "
156 "Failed to enumerate "
157 "domain local groups with error %s!\n",
158 nt_errstr(status)));
159 num_entries = 0;
161 else
162 DEBUG(4,("get_sam_group_entries: "
163 "Returned %d local groups\n",
164 num_entries));
166 /* Copy entries into return buffer */
168 if ( num_entries ) {
169 name_list = SMB_REALLOC_ARRAY(name_list,
170 struct acct_info,
171 ent->num_sam_entries+
172 num_entries);
173 if (!name_list) {
174 DEBUG(0,("get_sam_group_entries: "
175 "Failed to realloc more memory "
176 "for %d local groups!\n",
177 num_entries));
178 result = False;
179 goto done;
182 memcpy(&name_list[ent->num_sam_entries],
183 sam_grp_entries,
184 num_entries * sizeof(struct acct_info));
187 ent->num_sam_entries += num_entries;
191 /* Fill in remaining fields */
193 ent->sam_entries = name_list;
194 ent->sam_entry_index = 0;
196 result = (ent->num_sam_entries > 0);
198 done:
199 talloc_destroy(mem_ctx);
201 return result;
204 /* Get user supplementary groups. This is much quicker than trying to
205 invert the groups database. We merge the groups from the gids and
206 other_sids info3 fields as trusted domain, universal group
207 memberships, and nested groups (win2k native mode only) are not
208 returned by the getgroups RPC call but are present in the info3. */
210 struct getgroups_state {
211 struct winbindd_cli_state *state;
212 struct winbindd_domain *domain;
213 char *domname;
214 char *username;
215 DOM_SID user_sid;
217 const DOM_SID *token_sids;
218 size_t i, num_token_sids;
220 gid_t *token_gids;
221 size_t num_token_gids;
224 enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain,
225 struct winbindd_cli_state *state)
227 DOM_SID user_sid;
228 NTSTATUS status;
230 char *sidstring;
231 ssize_t len;
232 DOM_SID *groups;
233 uint32 num_groups;
235 /* Ensure null termination */
236 state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
238 if (!string_to_sid(&user_sid, state->request->data.sid)) {
239 DEBUG(1, ("Could not get convert sid %s from string\n",
240 state->request->data.sid));
241 return WINBINDD_ERROR;
244 status = domain->methods->lookup_usergroups(domain, state->mem_ctx,
245 &user_sid, &num_groups,
246 &groups);
247 if (!NT_STATUS_IS_OK(status))
248 return WINBINDD_ERROR;
250 if (num_groups == 0) {
251 state->response->data.num_entries = 0;
252 state->response->extra_data.data = NULL;
253 return WINBINDD_OK;
256 if (!print_sidlist(state->mem_ctx,
257 groups, num_groups,
258 &sidstring, &len)) {
259 DEBUG(0, ("talloc failed\n"));
260 return WINBINDD_ERROR;
263 state->response->extra_data.data = sidstring;
264 state->response->length += len+1;
265 state->response->data.num_entries = num_groups;
267 return WINBINDD_OK;
270 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
271 struct winbindd_cli_state *state)
273 DOM_SID *sids = NULL;
274 size_t num_sids = 0;
275 char *sidstr = NULL;
276 ssize_t len;
277 size_t i;
278 uint32 num_aliases;
279 uint32 *alias_rids;
280 NTSTATUS result;
282 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
284 sidstr = state->request->extra_data.data;
285 if (sidstr == NULL) {
286 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
287 if (!sidstr) {
288 DEBUG(0, ("Out of memory\n"));
289 return WINBINDD_ERROR;
293 DEBUG(10, ("Sidlist: %s\n", sidstr));
295 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
296 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
297 return WINBINDD_ERROR;
300 num_aliases = 0;
301 alias_rids = NULL;
303 result = domain->methods->lookup_useraliases(domain,
304 state->mem_ctx,
305 num_sids, sids,
306 &num_aliases,
307 &alias_rids);
309 if (!NT_STATUS_IS_OK(result)) {
310 DEBUG(3, ("Could not lookup_useraliases: %s\n",
311 nt_errstr(result)));
312 return WINBINDD_ERROR;
315 num_sids = 0;
316 sids = NULL;
317 sidstr = NULL;
319 DEBUG(10, ("Got %d aliases\n", num_aliases));
321 for (i=0; i<num_aliases; i++) {
322 DOM_SID sid;
323 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
324 sid_copy(&sid, &domain->sid);
325 sid_append_rid(&sid, alias_rids[i]);
326 result = add_sid_to_array(state->mem_ctx, &sid, &sids,
327 &num_sids);
328 if (!NT_STATUS_IS_OK(result)) {
329 return WINBINDD_ERROR;
334 if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
335 DEBUG(0, ("Could not print_sidlist\n"));
336 state->response->extra_data.data = NULL;
337 return WINBINDD_ERROR;
340 state->response->extra_data.data = NULL;
342 if (sidstr) {
343 state->response->extra_data.data = sidstr;
344 DEBUG(10, ("aliases_list: %s\n",
345 (char *)state->response->extra_data.data));
346 state->response->length += len+1;
347 state->response->data.num_entries = num_sids;
350 return WINBINDD_OK;
353 struct getgr_countmem {
354 int num;
355 size_t len;
358 static int getgr_calc_memberlen(DATA_BLOB key, void *data, void *priv)
360 struct wbint_Principal *m = talloc_get_type_abort(
361 data, struct wbint_Principal);
362 struct getgr_countmem *buf = (struct getgr_countmem *)priv;
364 buf->num += 1;
365 buf->len += strlen(m->name) + 1;
366 return 0;
369 struct getgr_stringmem {
370 size_t ofs;
371 char *buf;
374 static int getgr_unparse_members(DATA_BLOB key, void *data, void *priv)
376 struct wbint_Principal *m = talloc_get_type_abort(
377 data, struct wbint_Principal);
378 struct getgr_stringmem *buf = (struct getgr_stringmem *)priv;
379 int len;
381 len = strlen(m->name);
383 memcpy(buf->buf + buf->ofs, m->name, len);
384 buf->ofs += len;
385 buf->buf[buf->ofs] = ',';
386 buf->ofs += 1;
387 return 0;
390 NTSTATUS winbindd_print_groupmembers(struct talloc_dict *members,
391 TALLOC_CTX *mem_ctx,
392 int *num_members, char **result)
394 struct getgr_countmem c;
395 struct getgr_stringmem m;
396 int res;
398 c.num = 0;
399 c.len = 0;
401 res = talloc_dict_traverse(members, getgr_calc_memberlen, &c);
402 if (res != 0) {
403 DEBUG(5, ("talloc_dict_traverse failed\n"));
404 return NT_STATUS_INTERNAL_ERROR;
407 m.ofs = 0;
408 m.buf = talloc_array(mem_ctx, char, c.len);
409 if (m.buf == NULL) {
410 DEBUG(5, ("talloc failed\n"));
411 return NT_STATUS_NO_MEMORY;
414 res = talloc_dict_traverse(members, getgr_unparse_members, &m);
415 if (res != 0) {
416 DEBUG(5, ("talloc_dict_traverse failed\n"));
417 TALLOC_FREE(m.buf);
418 return NT_STATUS_INTERNAL_ERROR;
420 m.buf[c.len-1] = '\0';
422 *num_members = c.num;
423 *result = m.buf;
424 return NT_STATUS_OK;