sharesec: Check if share exists in configuration
[samba.git] / source3 / winbindd / winbindd_idmap.c
blobbf5c4d9ff32eee415bea8e5bdb64ffdf49b5f5d2
1 /*
2 Unix SMB/CIFS implementation.
4 Async helpers for blocking functions
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Gerald Carter 2006
8 Copyright (C) Simo Sorce 2007
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "winbindd.h"
26 #include "../libcli/security/security.h"
27 #include "passdb/lookup_sid.h"
28 #include "lib/global_contexts.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_WINBIND
33 static struct winbindd_child *static_idmap_child = NULL;
36 * Map idmap ranges to domain names, taken from smb.conf. This is
37 * stored in the parent winbind and used to assemble xids2sids/sids2xids calls
38 * into per-idmap-domain chunks.
40 static struct wb_parent_idmap_config static_parent_idmap_config;
42 struct winbindd_child *idmap_child(void)
44 return static_idmap_child;
47 bool is_idmap_child(const struct winbindd_child *child)
49 if (child == static_idmap_child) {
50 return true;
53 return false;
56 pid_t idmap_child_pid(void)
58 return static_idmap_child->pid;
61 struct dcerpc_binding_handle *idmap_child_handle(void)
64 * The caller needs to use wb_parent_idmap_setup_send/recv
65 * before talking to the idmap child!
67 SMB_ASSERT(static_parent_idmap_config.num_doms > 0);
68 return static_idmap_child->binding_handle;
71 static void init_idmap_child_done(struct tevent_req *subreq);
73 NTSTATUS init_idmap_child(TALLOC_CTX *mem_ctx)
75 struct tevent_req *subreq = NULL;
77 if (static_idmap_child != NULL) {
78 DBG_ERR("idmap child already allocated\n");
79 return NT_STATUS_INTERNAL_ERROR;
82 static_idmap_child = talloc_zero(mem_ctx, struct winbindd_child);
83 if (static_idmap_child == NULL) {
84 return NT_STATUS_NO_MEMORY;
87 subreq = wb_parent_idmap_setup_send(static_idmap_child,
88 global_event_context());
89 if (subreq == NULL) {
91 * This is only an optimization, so we're free to
92 * to ignore errors
94 DBG_ERR("wb_parent_idmap_setup_send() failed\n");
95 return NT_STATUS_NO_MEMORY;
97 tevent_req_set_callback(subreq, init_idmap_child_done, NULL);
98 DBG_DEBUG("wb_parent_idmap_setup_send() started\n");
99 return NT_STATUS_OK;
102 static void init_idmap_child_done(struct tevent_req *subreq)
104 const struct wb_parent_idmap_config *cfg = NULL;
105 NTSTATUS status;
107 status = wb_parent_idmap_setup_recv(subreq, &cfg);
108 TALLOC_FREE(subreq);
109 if (!NT_STATUS_IS_OK(status)) {
111 * This is only an optimization, so we're free to
112 * to ignore errors
114 DBG_ERR("wb_parent_idmap_setup_recv() failed %s\n",
115 nt_errstr(status));
116 return;
119 DBG_DEBUG("wb_parent_idmap_setup_recv() finished\n");
122 struct wb_parent_idmap_setup_state {
123 struct tevent_context *ev;
124 struct wb_parent_idmap_config *cfg;
125 size_t dom_idx;
128 static void wb_parent_idmap_setup_cleanup(struct tevent_req *req,
129 enum tevent_req_state req_state)
131 struct wb_parent_idmap_setup_state *state =
132 tevent_req_data(req,
133 struct wb_parent_idmap_setup_state);
135 if (req_state == TEVENT_REQ_DONE) {
136 state->cfg = NULL;
137 return;
140 if (state->cfg == NULL) {
141 return;
144 state->cfg->num_doms = 0;
145 state->cfg->initialized = false;
146 TALLOC_FREE(state->cfg->doms);
147 state->cfg = NULL;
150 static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq);
151 static bool wb_parent_idmap_setup_scan_config(const char *domname,
152 void *private_data);
153 static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req);
154 static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq);
156 struct tevent_req *wb_parent_idmap_setup_send(TALLOC_CTX *mem_ctx,
157 struct tevent_context *ev)
159 struct tevent_req *req = NULL;
160 struct wb_parent_idmap_setup_state *state = NULL;
161 struct tevent_req *subreq = NULL;
163 req = tevent_req_create(mem_ctx, &state,
164 struct wb_parent_idmap_setup_state);
165 if (req == NULL) {
166 return NULL;
168 *state = (struct wb_parent_idmap_setup_state) {
169 .ev = ev,
170 .cfg = &static_parent_idmap_config,
171 .dom_idx = 0,
174 if (state->cfg->initialized) {
175 tevent_req_done(req);
176 return tevent_req_post(req, ev);
179 if (state->cfg->queue == NULL) {
180 state->cfg->queue = tevent_queue_create(NULL,
181 "wb_parent_idmap_config_queue");
182 if (tevent_req_nomem(state->cfg->queue, req)) {
183 return tevent_req_post(req, ev);
187 subreq = tevent_queue_wait_send(state, state->ev, state->cfg->queue);
188 if (tevent_req_nomem(subreq, req)) {
189 return tevent_req_post(req, ev);
191 tevent_req_set_callback(subreq,
192 wb_parent_idmap_setup_queue_wait_done,
193 req);
195 return req;
198 static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq)
200 struct tevent_req *req =
201 tevent_req_callback_data(subreq,
202 struct tevent_req);
203 struct wb_parent_idmap_setup_state *state =
204 tevent_req_data(req,
205 struct wb_parent_idmap_setup_state);
206 bool ok;
209 * Note we don't call TALLOC_FREE(subreq) here in order to block the
210 * queue until tevent_req_received() in wb_parent_idmap_setup_recv()
211 * will destroy it implicitly.
213 ok = tevent_queue_wait_recv(subreq);
214 if (!ok) {
215 DBG_ERR("tevent_queue_wait_recv() failed\n");
216 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
217 return;
220 if (state->cfg->num_doms != 0) {
222 * If we're not the first one we're done.
224 tevent_req_done(req);
225 return;
229 * From this point we start changing state->cfg,
230 * which is &static_parent_idmap_config,
231 * so we better setup a cleanup function
232 * to undo the changes on failure.
234 tevent_req_set_cleanup_fn(req, wb_parent_idmap_setup_cleanup);
237 * Put the passdb idmap domain first. We always need to try
238 * there first.
240 state->cfg->doms = talloc_zero_array(NULL,
241 struct wb_parent_idmap_config_dom,
243 if (tevent_req_nomem(state->cfg->doms, req)) {
244 return;
246 state->cfg->doms[0].low_id = 0;
247 state->cfg->doms[0].high_id = UINT_MAX;
248 state->cfg->doms[0].name = talloc_strdup(state->cfg->doms,
249 get_global_sam_name());
250 if (tevent_req_nomem(state->cfg->doms[0].name, req)) {
251 return;
253 state->cfg->num_doms += 1;
255 lp_scan_idmap_domains(wb_parent_idmap_setup_scan_config, req);
256 if (!tevent_req_is_in_progress(req)) {
257 return;
260 wb_parent_idmap_setup_lookupname_next(req);
263 static bool wb_parent_idmap_setup_scan_config(const char *domname,
264 void *private_data)
266 struct tevent_req *req =
267 talloc_get_type_abort(private_data,
268 struct tevent_req);
269 struct wb_parent_idmap_setup_state *state =
270 tevent_req_data(req,
271 struct wb_parent_idmap_setup_state);
272 struct wb_parent_idmap_config_dom *map = NULL;
273 size_t i;
274 const char *range;
275 unsigned low_id, high_id;
276 int ret;
278 range = idmap_config_const_string(domname, "range", NULL);
279 if (range == NULL) {
280 DBG_DEBUG("No range for domain %s found\n", domname);
281 return false;
284 ret = sscanf(range, "%u - %u", &low_id, &high_id);
285 if (ret != 2) {
286 DBG_DEBUG("Invalid range spec \"%s\" for domain %s\n",
287 range, domname);
288 return false;
291 if (low_id > high_id) {
292 DBG_DEBUG("Invalid range %u - %u for domain %s\n",
293 low_id, high_id, domname);
294 return false;
297 for (i=0; i<state->cfg->num_doms; i++) {
298 if (strequal(domname, state->cfg->doms[i].name)) {
299 map = &state->cfg->doms[i];
300 break;
304 if (map == NULL) {
305 struct wb_parent_idmap_config_dom *tmp;
306 char *name;
308 name = talloc_strdup(state, domname);
309 if (name == NULL) {
310 DBG_ERR("talloc failed\n");
311 return false;
314 tmp = talloc_realloc(
315 NULL, state->cfg->doms, struct wb_parent_idmap_config_dom,
316 state->cfg->num_doms+1);
317 if (tmp == NULL) {
318 DBG_ERR("talloc failed\n");
319 return false;
321 state->cfg->doms = tmp;
323 map = &state->cfg->doms[state->cfg->num_doms];
324 state->cfg->num_doms += 1;
325 ZERO_STRUCTP(map);
326 map->name = talloc_move(state->cfg->doms, &name);
329 map->low_id = low_id;
330 map->high_id = high_id;
332 return false;
335 static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req)
337 struct wb_parent_idmap_setup_state *state =
338 tevent_req_data(req,
339 struct wb_parent_idmap_setup_state);
340 struct wb_parent_idmap_config_dom *dom =
341 &state->cfg->doms[state->dom_idx];
342 struct tevent_req *subreq = NULL;
344 next_domain:
345 if (state->dom_idx == state->cfg->num_doms) {
347 * We're done, so start the idmap child
349 setup_child(NULL, static_idmap_child, "log.winbindd", "idmap");
350 static_parent_idmap_config.initialized = true;
351 tevent_req_done(req);
352 return;
355 if (strequal(dom->name, "*")) {
356 state->dom_idx++;
357 goto next_domain;
360 subreq = wb_lookupname_send(state,
361 state->ev,
362 dom->name,
363 dom->name,
365 LOOKUP_NAME_NO_NSS);
366 if (tevent_req_nomem(subreq, req)) {
367 return;
369 tevent_req_set_callback(subreq,
370 wb_parent_idmap_setup_lookupname_done,
371 req);
374 static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq)
376 struct tevent_req *req =
377 tevent_req_callback_data(subreq,
378 struct tevent_req);
379 struct wb_parent_idmap_setup_state *state =
380 tevent_req_data(req,
381 struct wb_parent_idmap_setup_state);
382 struct wb_parent_idmap_config_dom *dom =
383 &state->cfg->doms[state->dom_idx];
384 enum lsa_SidType type;
385 NTSTATUS status;
387 status = wb_lookupname_recv(subreq, &dom->sid, &type);
388 TALLOC_FREE(subreq);
389 if (NT_STATUS_IS_OK(status) && type == SID_NAME_UNKNOWN) {
390 status = NT_STATUS_NONE_MAPPED;
392 if (!NT_STATUS_IS_OK(status)) {
393 DBG_ERR("Lookup domain name '%s' failed '%s'\n",
394 dom->name,
395 nt_errstr(status));
397 state->dom_idx++;
398 wb_parent_idmap_setup_lookupname_next(req);
399 return;
402 if (type != SID_NAME_DOMAIN) {
403 struct dom_sid_buf buf;
405 DBG_ERR("SID %s for idmap domain name '%s' "
406 "not a domain SID\n",
407 dom_sid_str_buf(&dom->sid, &buf),
408 dom->name);
410 ZERO_STRUCT(dom->sid);
413 state->dom_idx++;
414 wb_parent_idmap_setup_lookupname_next(req);
416 return;
419 NTSTATUS wb_parent_idmap_setup_recv(struct tevent_req *req,
420 const struct wb_parent_idmap_config **_cfg)
422 const struct wb_parent_idmap_config *cfg = &static_parent_idmap_config;
423 NTSTATUS status;
425 *_cfg = NULL;
427 if (tevent_req_is_nterror(req, &status)) {
428 tevent_req_received(req);
429 return status;
433 * Note state->cfg is already set to NULL by
434 * wb_parent_idmap_setup_cleanup()
436 *_cfg = cfg;
437 tevent_req_received(req);
438 return NT_STATUS_OK;