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/>.
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
,
44 /* Basic whitespace replacement */
45 if (NT_STATUS_IS_OK(nt_status
)) {
46 fill_domain_username(full_group_name
, dom_name
,
49 /* Mapped to an aliase */
50 else if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_FILE_RENAMED
)) {
51 fstrcpy(full_group_name
, mapped_name
);
55 fill_domain_username( full_group_name
, dom_name
,
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);
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
)
77 struct acct_info
*name_list
= NULL
;
80 struct acct_info
*sam_grp_entries
= NULL
;
81 struct winbindd_domain
*domain
;
83 if (ent
->got_sam_entries
)
86 if (!(mem_ctx
= talloc_init("get_sam_group_entries(%s)",
88 DEBUG(1, ("get_sam_group_entries: "
89 "could not create talloc context!\n"));
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 */
103 if (!(domain
= find_domain_from_name(ent
->domain_name
))) {
104 DEBUG(3, ("no such domain %s in get_sam_group_entries\n",
109 /* always get the domain global groups */
111 status
= domain
->methods
->enum_dom_groups(domain
, mem_ctx
, &num_entries
,
114 if (!NT_STATUS_IS_OK(status
)) {
115 DEBUG(3, ("get_sam_group_entries: "
116 "could not enumerate domain groups! Error: %s\n",
122 /* Copy entries into return buffer */
125 name_list
= SMB_MALLOC_ARRAY(struct acct_info
, num_entries
);
127 DEBUG(0,("get_sam_group_entries: Failed to malloc "
128 "memory for %d domain groups!\n",
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
,
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",
162 DEBUG(4,("get_sam_group_entries: "
163 "Returned %d local groups\n",
166 /* Copy entries into return buffer */
169 name_list
= SMB_REALLOC_ARRAY(name_list
,
171 ent
->num_sam_entries
+
174 DEBUG(0,("get_sam_group_entries: "
175 "Failed to realloc more memory "
176 "for %d local groups!\n",
182 memcpy(&name_list
[ent
->num_sam_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);
199 talloc_destroy(mem_ctx
);
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
;
217 const DOM_SID
*token_sids
;
218 size_t i
, num_token_sids
;
221 size_t num_token_gids
;
224 enum winbindd_result
winbindd_dual_getuserdomgroups(struct winbindd_domain
*domain
,
225 struct winbindd_cli_state
*state
)
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
,
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
;
256 if (!print_sidlist(state
->mem_ctx
,
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
;
270 enum winbindd_result
winbindd_dual_getsidaliases(struct winbindd_domain
*domain
,
271 struct winbindd_cli_state
*state
)
273 DOM_SID
*sids
= NULL
;
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 */
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
;
303 result
= domain
->methods
->lookup_useraliases(domain
,
309 if (!NT_STATUS_IS_OK(result
)) {
310 DEBUG(3, ("Could not lookup_useraliases: %s\n",
312 return WINBINDD_ERROR
;
319 DEBUG(10, ("Got %d aliases\n", num_aliases
));
321 for (i
=0; i
<num_aliases
; i
++) {
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
,
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
;
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
;
353 struct getgr_countmem
{
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
;
365 buf
->len
+= strlen(m
->name
) + 1;
369 struct getgr_stringmem
{
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
;
381 len
= strlen(m
->name
);
383 memcpy(buf
->buf
+ buf
->ofs
, m
->name
, len
);
385 buf
->buf
[buf
->ofs
] = ',';
390 NTSTATUS
winbindd_print_groupmembers(struct talloc_dict
*members
,
392 int *num_members
, char **result
)
394 struct getgr_countmem c
;
395 struct getgr_stringmem m
;
401 res
= talloc_dict_traverse(members
, getgr_calc_memberlen
, &c
);
403 DEBUG(5, ("talloc_dict_traverse failed\n"));
404 return NT_STATUS_INTERNAL_ERROR
;
408 m
.buf
= talloc_array(mem_ctx
, char, c
.len
);
410 DEBUG(5, ("talloc failed\n"));
411 return NT_STATUS_NO_MEMORY
;
414 res
= talloc_dict_traverse(members
, getgr_unparse_members
, &m
);
416 DEBUG(5, ("talloc_dict_traverse failed\n"));
418 return NT_STATUS_INTERNAL_ERROR
;
420 m
.buf
[c
.len
-1] = '\0';
422 *num_members
= c
.num
;