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(WINBINDD_SOCKET_DIR_ENVVAR);
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 = sidslen;
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;