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 "libcli/wbclient/wbclient.h"
25 #include "nsswitch/wb_reqtrans.h"
26 #include "system/network.h"
27 #include "libcli/util/error.h"
28 #include "libcli/security/dom_sid.h"
31 * Initialize the wbclient context, talloc_free() when done.
33 * \param mem_ctx talloc context to allocate memory from
34 * \param msg_ctx message context to use
37 struct wbc_context *wbc_init(TALLOC_CTX *mem_ctx,
38 struct imessaging_context *msg_ctx,
39 struct tevent_context *event_ctx)
41 struct wbc_context *ctx;
43 ctx = talloc(mem_ctx, struct wbc_context);
44 if (ctx == NULL) return NULL;
46 ctx->event_ctx = event_ctx;
48 ctx->irpc_handle = irpc_binding_handle_by_name(ctx, msg_ctx,
51 if (ctx->irpc_handle == NULL) {
59 struct wbc_idmap_state {
60 struct composite_context *ctx;
61 struct winbind_get_idmap *req;
65 static void sids_to_xids_recv_ids(struct tevent_req *subreq);
67 struct composite_context *wbc_sids_to_xids_send(struct wbc_context *wbc_ctx,
72 struct composite_context *ctx;
73 struct wbc_idmap_state *state;
74 struct tevent_req *subreq;
76 DEBUG(5, ("wbc_sids_to_xids called\n"));
78 ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
79 if (ctx == NULL) return NULL;
81 state = talloc(ctx, struct wbc_idmap_state);
82 if (composite_nomem(state, ctx)) return ctx;
83 ctx->private_data = state;
85 state->req = talloc(state, struct winbind_get_idmap);
86 if (composite_nomem(state->req, ctx)) return ctx;
88 state->req->in.count = count;
89 state->req->in.level = WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS;
90 state->req->in.ids = ids;
93 subreq = dcerpc_winbind_get_idmap_r_send(state,
97 if (composite_nomem(subreq, ctx)) return ctx;
99 tevent_req_set_callback(subreq, sids_to_xids_recv_ids, state);
104 static void sids_to_xids_recv_ids(struct tevent_req *subreq)
106 struct wbc_idmap_state *state =
107 tevent_req_callback_data(subreq,
108 struct wbc_idmap_state);
110 state->ctx->status = dcerpc_winbind_get_idmap_r_recv(subreq, state);
112 if (!composite_is_ok(state->ctx)) return;
114 state->ids = state->req->out.ids;
115 composite_done(state->ctx);
118 NTSTATUS wbc_sids_to_xids_recv(struct composite_context *ctx,
121 NTSTATUS status = composite_wait(ctx);
122 DEBUG(5, ("wbc_sids_to_xids_recv called\n"));
123 if (NT_STATUS_IS_OK(status)) {
124 struct wbc_idmap_state *state = talloc_get_type_abort(
126 struct wbc_idmap_state);
133 static void xids_to_sids_recv_ids(struct tevent_req *subreq);
135 struct composite_context *wbc_xids_to_sids_send(struct wbc_context *wbc_ctx,
140 struct composite_context *ctx;
141 struct wbc_idmap_state *state;
142 struct tevent_req *subreq;
144 DEBUG(5, ("wbc_xids_to_sids called\n"));
146 ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
147 if (ctx == NULL) return NULL;
149 state = talloc(ctx, struct wbc_idmap_state);
150 if (composite_nomem(state, ctx)) return ctx;
151 ctx->private_data = state;
153 state->req = talloc(state, struct winbind_get_idmap);
154 if (composite_nomem(state->req, ctx)) return ctx;
156 state->req->in.count = count;
157 state->req->in.level = WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS;
158 state->req->in.ids = ids;
161 subreq = dcerpc_winbind_get_idmap_r_send(state,
163 wbc_ctx->irpc_handle,
165 if (composite_nomem(subreq, ctx)) return ctx;
167 tevent_req_set_callback(subreq, xids_to_sids_recv_ids, state);
172 static void xids_to_sids_recv_ids(struct tevent_req *subreq)
174 struct wbc_idmap_state *state =
175 tevent_req_callback_data(subreq,
176 struct wbc_idmap_state);
178 state->ctx->status = dcerpc_winbind_get_idmap_r_recv(subreq, state);
180 if (!composite_is_ok(state->ctx)) return;
182 state->ids = state->req->out.ids;
183 composite_done(state->ctx);
186 NTSTATUS wbc_xids_to_sids_recv(struct composite_context *ctx,
189 NTSTATUS status = composite_wait(ctx);
190 DEBUG(5, ("wbc_xids_to_sids_recv called\n"));
191 if (NT_STATUS_IS_OK(status)) {
192 struct wbc_idmap_state *state = talloc_get_type_abort(
194 struct wbc_idmap_state);
201 static int wb_simple_trans(struct tevent_context *ev, int fd,
202 struct winbindd_request *wb_req,
204 struct winbindd_response **resp, int *err)
206 struct tevent_req *req;
210 req = wb_simple_trans_send(ev, ev, NULL, fd, wb_req);
216 polled = tevent_req_poll(req, ev);
219 DEBUG(10, ("tevent_req_poll returned %s\n",
224 ret = wb_simple_trans_recv(req, mem_ctx, resp, err);
229 static const char *winbindd_socket_dir(void)
231 #ifdef SOCKET_WRAPPER
234 env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR);
240 return WINBINDD_SOCKET_DIR;
243 static int winbindd_pipe_sock(void)
245 struct sockaddr_un sunaddr = {};
249 ret = asprintf(&path, "%s/%s", winbindd_socket_dir(),
250 WINBINDD_SOCKET_NAME);
255 sunaddr.sun_family = AF_UNIX;
256 strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
259 fd = socket(AF_UNIX, SOCK_STREAM, 0);
264 ret = connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
275 NTSTATUS wbc_sids_to_xids(struct tevent_context *ev, struct id_map *ids,
279 struct winbindd_request req = {};
280 struct winbindd_response *resp;
286 fd = winbindd_pipe_sock();
288 return map_nt_error_from_unix_common(errno);
291 mem_ctx = talloc_new(NULL);
292 if (mem_ctx == NULL) {
294 return NT_STATUS_NO_MEMORY;
297 sidslen = count * (DOM_SID_STR_BUFLEN + 1);
299 sids = talloc_array(mem_ctx, char, sidslen);
302 TALLOC_FREE(mem_ctx);
303 return NT_STATUS_NO_MEMORY;
307 for (i=0; i<count; i++) {
308 p += dom_sid_string_buf(ids[i].sid, p, sidslen - (p - sids));
313 DEBUG(10, ("sids=\n%s", sids));
315 req.length = sizeof(struct winbindd_request);
316 req.cmd = WINBINDD_SIDS_TO_XIDS;
318 req.extra_data.data = sids;
319 req.extra_len = sidslen;
321 ret = wb_simple_trans(ev, fd, &req, mem_ctx, &resp, &err);
323 return map_nt_error_from_unix_common(err);
328 p = resp->extra_data.data;
330 for (i=0; i<count; i++) {
331 struct unixid *id = &ids[i].xid;
336 id->type = ID_TYPE_UID;
337 id->id = strtoul(p+1, &q, 10);
340 id->type = ID_TYPE_GID;
341 id->id = strtoul(p+1, &q, 10);
344 id->type = ID_TYPE_BOTH;
345 id->id = strtoul(p+1, &q, 10);
348 id->type = ID_TYPE_NOT_SPECIFIED;
353 ids[i].status = ID_MAPPED;
355 if (q == NULL || q[0] != '\n') {
356 TALLOC_FREE(mem_ctx);
357 return NT_STATUS_INTERNAL_ERROR;