2 Unix SMB/CIFS implementation.
4 Winbind client library.
6 Copyright (C) 2008 Kai Blin <kai@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "lib/util/tevent_unix.h"
25 #include "libcli/wbclient/wbclient.h"
26 #include "nsswitch/wb_reqtrans.h"
27 #include "system/network.h"
28 #include "libcli/util/error.h"
29 #include "libcli/security/dom_sid.h"
31 static int wb_simple_trans(struct tevent_context
*ev
, int fd
,
32 struct winbindd_request
*wb_req
,
34 struct winbindd_response
**resp
, int *err
)
36 struct tevent_req
*req
;
40 req
= wb_simple_trans_send(ev
, ev
, NULL
, fd
, wb_req
);
46 polled
= tevent_req_poll(req
, ev
);
49 DEBUG(10, ("tevent_req_poll returned %s\n",
54 ret
= wb_simple_trans_recv(req
, mem_ctx
, resp
, err
);
59 static const char *winbindd_socket_dir(void)
64 env_dir
= getenv("SELFTEST_WINBINDD_SOCKET_DIR");
70 return WINBINDD_SOCKET_DIR
;
73 static int winbindd_pipe_sock(void)
75 struct sockaddr_un sunaddr
= {};
79 ret
= asprintf(&path
, "%s/%s", winbindd_socket_dir(),
80 WINBINDD_SOCKET_NAME
);
85 sunaddr
.sun_family
= AF_UNIX
;
86 strlcpy(sunaddr
.sun_path
, path
, sizeof(sunaddr
.sun_path
));
89 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
94 ret
= connect(fd
, (struct sockaddr
*)&sunaddr
, sizeof(sunaddr
));
105 NTSTATUS
wbc_sids_to_xids(struct tevent_context
*ev
, struct id_map
*ids
,
109 struct winbindd_request req
= {};
110 struct winbindd_response
*resp
;
116 fd
= winbindd_pipe_sock();
118 return map_nt_error_from_unix_common(errno
);
121 mem_ctx
= talloc_new(NULL
);
122 if (mem_ctx
== NULL
) {
124 return NT_STATUS_NO_MEMORY
;
127 sidslen
= count
* (DOM_SID_STR_BUFLEN
+ 1);
129 sids
= talloc_array(mem_ctx
, char, sidslen
);
132 TALLOC_FREE(mem_ctx
);
133 return NT_STATUS_NO_MEMORY
;
137 for (i
=0; i
<count
; i
++) {
138 p
+= dom_sid_string_buf(ids
[i
].sid
, p
, sidslen
- (p
- sids
));
143 DEBUG(10, ("sids=\n%s", sids
));
145 req
.length
= sizeof(struct winbindd_request
);
146 req
.cmd
= WINBINDD_SIDS_TO_XIDS
;
148 req
.extra_data
.data
= sids
;
149 req
.extra_len
= (p
- sids
);
151 ret
= wb_simple_trans(ev
, fd
, &req
, mem_ctx
, &resp
, &err
);
153 return map_nt_error_from_unix_common(err
);
158 if (resp
->result
!= WINBINDD_OK
|| p
== NULL
) {
159 return NT_STATUS_INTERNAL_ERROR
;
162 p
= resp
->extra_data
.data
;
164 for (i
=0; i
<count
; i
++) {
165 struct unixid
*id
= &ids
[i
].xid
;
170 id
->type
= ID_TYPE_UID
;
171 id
->id
= strtoul(p
+1, &q
, 10);
174 id
->type
= ID_TYPE_GID
;
175 id
->id
= strtoul(p
+1, &q
, 10);
178 id
->type
= ID_TYPE_BOTH
;
179 id
->id
= strtoul(p
+1, &q
, 10);
182 id
->type
= ID_TYPE_NOT_SPECIFIED
;
187 ids
[i
].status
= ID_MAPPED
;
189 if (q
== NULL
|| q
[0] != '\n') {
190 TALLOC_FREE(mem_ctx
);
191 return NT_STATUS_INTERNAL_ERROR
;
199 struct wbc_id_to_sid_state
{
200 struct winbindd_request wbreq
;
204 static void wbc_id_to_sid_done(struct tevent_req
*subreq
);
206 static struct tevent_req
*wbc_id_to_sid_send(TALLOC_CTX
*mem_ctx
,
207 struct tevent_context
*ev
,
208 int fd
, const struct unixid
*id
)
210 struct tevent_req
*req
, *subreq
;
211 struct wbc_id_to_sid_state
*state
;
213 req
= tevent_req_create(mem_ctx
, &state
, struct wbc_id_to_sid_state
);
220 state
->wbreq
.cmd
= WINBINDD_UID_TO_SID
;
221 state
->wbreq
.data
.uid
= id
->id
;
224 state
->wbreq
.cmd
= WINBINDD_GID_TO_SID
;
225 state
->wbreq
.data
.gid
= id
->id
;
228 tevent_req_error(req
, ENOENT
);
229 return tevent_req_post(req
, ev
);
232 subreq
= wb_simple_trans_send(state
, ev
, NULL
, fd
, &state
->wbreq
);
233 if (tevent_req_nomem(subreq
, req
)) {
234 return tevent_req_post(req
, ev
);
236 tevent_req_set_callback(subreq
, wbc_id_to_sid_done
, req
);
240 static void wbc_id_to_sid_done(struct tevent_req
*subreq
)
242 struct tevent_req
*req
= tevent_req_callback_data(
243 subreq
, struct tevent_req
);
244 struct wbc_id_to_sid_state
*state
= tevent_req_data(
245 req
, struct wbc_id_to_sid_state
);
246 struct winbindd_response
*wbresp
;
249 ret
= wb_simple_trans_recv(subreq
, state
, &wbresp
, &err
);
252 tevent_req_error(req
, err
);
255 if ((wbresp
->result
!= WINBINDD_OK
) ||
256 !dom_sid_parse(wbresp
->data
.sid
.sid
, &state
->sid
)) {
257 tevent_req_error(req
, ENOENT
);
260 tevent_req_done(req
);
263 static int wbc_id_to_sid_recv(struct tevent_req
*req
, struct dom_sid
*sid
)
265 struct wbc_id_to_sid_state
*state
= tevent_req_data(
266 req
, struct wbc_id_to_sid_state
);
269 if (tevent_req_is_unix_error(req
, &err
)) {
272 sid_copy(sid
, &state
->sid
);
276 struct wbc_ids_to_sids_state
{
277 struct tevent_context
*ev
;
284 static void wbc_ids_to_sids_done(struct tevent_req
*subreq
);
286 static struct tevent_req
*wbc_ids_to_sids_send(
287 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
288 int fd
, struct id_map
*ids
, uint32_t count
)
290 struct tevent_req
*req
, *subreq
;
291 struct wbc_ids_to_sids_state
*state
;
293 req
= tevent_req_create(mem_ctx
, &state
,
294 struct wbc_ids_to_sids_state
);
301 state
->count
= count
;
304 tevent_req_done(req
);
305 return tevent_req_post(req
, ev
);
308 subreq
= wbc_id_to_sid_send(state
, state
->ev
, state
->fd
,
309 &state
->ids
[state
->idx
].xid
);
310 if (tevent_req_nomem(subreq
, req
)) {
311 return tevent_req_post(req
, ev
);
313 tevent_req_set_callback(subreq
, wbc_ids_to_sids_done
, req
);
317 static void wbc_ids_to_sids_done(struct tevent_req
*subreq
)
319 struct tevent_req
*req
= tevent_req_callback_data(
320 subreq
, struct tevent_req
);
321 struct wbc_ids_to_sids_state
*state
= tevent_req_data(
322 req
, struct wbc_ids_to_sids_state
);
327 ret
= wbc_id_to_sid_recv(subreq
, &sid
);
330 id
= &state
->ids
[state
->idx
];
332 id
->status
= ID_MAPPED
;
333 id
->sid
= dom_sid_dup(state
->ids
, &sid
);
334 if (id
->sid
== NULL
) {
335 tevent_req_error(req
, ENOMEM
);
339 id
->status
= ID_UNMAPPED
;
344 if (state
->idx
== state
->count
) {
345 tevent_req_done(req
);
349 subreq
= wbc_id_to_sid_send(state
, state
->ev
, state
->fd
,
350 &state
->ids
[state
->idx
].xid
);
351 if (tevent_req_nomem(subreq
, req
)) {
354 tevent_req_set_callback(subreq
, wbc_ids_to_sids_done
, req
);
357 static int wbc_ids_to_sids_recv(struct tevent_req
*req
)
360 if (tevent_req_is_unix_error(req
, &err
)) {
366 NTSTATUS
wbc_xids_to_sids(struct tevent_context
*ev
, struct id_map
*ids
,
369 struct tevent_req
*req
;
374 DEBUG(5, ("wbc_xids_to_sids called: %u ids\n", (unsigned)count
));
376 fd
= winbindd_pipe_sock();
378 status
= map_nt_error_from_unix_common(errno
);
379 DEBUG(10, ("winbindd_pipe_sock returned %s\n",
384 req
= wbc_ids_to_sids_send(ev
, ev
, fd
, ids
, count
);
386 status
= NT_STATUS_NO_MEMORY
;
390 polled
= tevent_req_poll(req
, ev
);
392 status
= map_nt_error_from_unix_common(errno
);
393 DEBUG(10, ("tevent_req_poll returned %s\n",
398 ret
= wbc_ids_to_sids_recv(req
);
401 status
= map_nt_error_from_unix_common(ret
);
402 DEBUG(10, ("tevent_req_poll returned %s\n",
405 status
= NT_STATUS_OK
;