Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Enumeration Module
5 :
6 : Authors:
7 : Simo Sorce <ssorce@redhat.com>
8 : Jakub Hrozek <jhrozek@redhat.com>
9 :
10 : Copyright (C) 2013 Red Hat
11 :
12 : This program is free software; you can redistribute it and/or modify
13 : it under the terms of the GNU General Public License as published by
14 : the Free Software Foundation; either version 3 of the License, or
15 : (at your option) any later version.
16 :
17 : This program is distributed in the hope that it will be useful,
18 : but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : GNU General Public License for more details.
21 :
22 : You should have received a copy of the GNU General Public License
23 : along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include <errno.h>
27 :
28 : #include "util/util.h"
29 : #include "db/sysdb.h"
30 : #include "providers/ldap/ldap_common.h"
31 : #include "providers/ldap/sdap_async.h"
32 : #include "providers/ldap/sdap_async_enum.h"
33 : #include "providers/ldap/sdap_idmap.h"
34 :
35 : static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
36 : struct tevent_context *ev,
37 : struct sdap_id_ctx *ctx,
38 : struct sdap_domain *sdom,
39 : struct sdap_id_op *op,
40 : bool purge);
41 : static errno_t enum_users_recv(struct tevent_req *req);
42 :
43 : static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
44 : struct tevent_context *ev,
45 : struct sdap_id_ctx *ctx,
46 : struct sdap_domain *sdom,
47 : struct sdap_id_op *op,
48 : bool purge);
49 : static errno_t enum_groups_recv(struct tevent_req *req);
50 :
51 : /* ==Enumeration-Request-with-connections=================================== */
52 : struct sdap_dom_enum_ex_state {
53 : struct tevent_context *ev;
54 : struct sdap_id_ctx *ctx;
55 : struct sdap_domain *sdom;
56 :
57 : struct sdap_id_conn_ctx *user_conn;
58 : struct sdap_id_conn_ctx *group_conn;
59 : struct sdap_id_conn_ctx *svc_conn;
60 : struct sdap_id_op *user_op;
61 : struct sdap_id_op *group_op;
62 : struct sdap_id_op *svc_op;
63 :
64 : bool purge;
65 : };
66 :
67 : static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
68 : struct sdap_id_op *op,
69 : tevent_req_fn tcb);
70 : static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq);
71 : static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq);
72 : static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq);
73 : static errno_t sdap_dom_enum_search_users(struct tevent_req *req);
74 : static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq);
75 : static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq);
76 : static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq);
77 : static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq);
78 : static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq);
79 :
80 : struct tevent_req *
81 0 : sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
82 : struct tevent_context *ev,
83 : struct sdap_id_ctx *ctx,
84 : struct sdap_domain *sdom,
85 : struct sdap_id_conn_ctx *user_conn,
86 : struct sdap_id_conn_ctx *group_conn,
87 : struct sdap_id_conn_ctx *svc_conn)
88 : {
89 : struct tevent_req *req;
90 : struct sdap_dom_enum_ex_state *state;
91 : int t;
92 : errno_t ret;
93 :
94 0 : req = tevent_req_create(memctx, &state, struct sdap_dom_enum_ex_state);
95 0 : if (req == NULL) return NULL;
96 :
97 0 : state->ev = ev;
98 0 : state->ctx = ctx;
99 0 : state->sdom = sdom;
100 0 : state->user_conn = user_conn;
101 0 : state->group_conn = group_conn;
102 0 : state->svc_conn = svc_conn;
103 0 : sdom->last_enum = tevent_timeval_current();
104 :
105 0 : t = dp_opt_get_int(ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT);
106 0 : if ((sdom->last_purge.tv_sec + t) < sdom->last_enum.tv_sec) {
107 0 : state->purge = true;
108 : }
109 :
110 0 : state->user_op = sdap_id_op_create(state, user_conn->conn_cache);
111 0 : if (state->user_op == NULL) {
112 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for users\n");
113 0 : ret = EIO;
114 0 : goto fail;
115 : }
116 :
117 0 : ret = sdap_dom_enum_ex_retry(req, state->user_op,
118 : sdap_dom_enum_ex_get_users);
119 0 : if (ret != EOK) {
120 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_ex_retry failed\n");
121 0 : goto fail;
122 : }
123 :
124 0 : return req;
125 :
126 : fail:
127 0 : tevent_req_error(req, ret);
128 0 : tevent_req_post(req, ev);
129 0 : return req;
130 : }
131 :
132 0 : static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
133 : struct sdap_id_op *op,
134 : tevent_req_fn tcb)
135 : {
136 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
137 : struct sdap_dom_enum_ex_state);
138 : struct tevent_req *subreq;
139 : errno_t ret;
140 :
141 0 : subreq = sdap_id_op_connect_send(op, state, &ret);
142 0 : if (subreq == NULL) {
143 0 : DEBUG(SSSDBG_OP_FAILURE,
144 : "sdap_id_op_connect_send failed: %d\n", ret);
145 0 : return ret;
146 : }
147 :
148 0 : tevent_req_set_callback(subreq, tcb, req);
149 0 : return EOK;
150 : }
151 :
152 0 : static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq)
153 : {
154 : errno_t ret;
155 : int dp_error;
156 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
157 : struct tevent_req);
158 :
159 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
160 0 : talloc_zfree(subreq);
161 0 : if (ret != EOK) {
162 0 : if (dp_error == DP_ERR_OFFLINE) {
163 0 : DEBUG(SSSDBG_TRACE_FUNC,
164 : "Backend is marked offline, retry later!\n");
165 0 : tevent_req_done(req);
166 : } else {
167 0 : DEBUG(SSSDBG_MINOR_FAILURE,
168 : "Domain enumeration failed to connect to " \
169 : "LDAP server: (%d)[%s]\n", ret, strerror(ret));
170 0 : tevent_req_error(req, ret);
171 : }
172 0 : return false;
173 : }
174 :
175 0 : return true;
176 : }
177 :
178 0 : static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq)
179 : {
180 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
181 : struct tevent_req);
182 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
183 : struct sdap_dom_enum_ex_state);
184 : bool use_id_mapping;
185 : errno_t ret;
186 :
187 0 : if (sdap_dom_enum_ex_connected(subreq) == false) {
188 0 : return;
189 : }
190 :
191 0 : use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
192 0 : state->ctx->opts->idmap_ctx,
193 0 : state->sdom->dom->name,
194 0 : state->sdom->dom->domain_id);
195 :
196 : /* If POSIX attributes have been requested with an AD server and we
197 : * have no idea about POSIX attributes support, run a one-time check
198 : */
199 0 : if (use_id_mapping == false &&
200 0 : state->ctx->opts->schema_type == SDAP_SCHEMA_AD &&
201 0 : state->ctx->srv_opts &&
202 0 : state->ctx->srv_opts->posix_checked == false) {
203 0 : subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts,
204 : sdap_id_op_handle(state->user_op),
205 0 : state->sdom->user_search_bases,
206 0 : dp_opt_get_int(state->ctx->opts->basic,
207 : SDAP_SEARCH_TIMEOUT));
208 0 : if (subreq == NULL) {
209 0 : tevent_req_error(req, ENOMEM);
210 0 : return;
211 : }
212 0 : tevent_req_set_callback(subreq,
213 : sdap_dom_enum_ex_posix_check_done, req);
214 0 : return;
215 : }
216 :
217 :
218 0 : ret = sdap_dom_enum_search_users(req);
219 0 : if (ret != EOK) {
220 0 : tevent_req_error(req, ret);
221 0 : return;
222 : }
223 : /* Execution resumes in sdap_dom_enum_ex_users_done */
224 : }
225 :
226 0 : static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq)
227 : {
228 : errno_t ret;
229 : bool has_posix;
230 : int dp_error;
231 :
232 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
233 : struct tevent_req);
234 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
235 : struct sdap_dom_enum_ex_state);
236 :
237 0 : ret = sdap_posix_check_recv(subreq, &has_posix);
238 0 : talloc_zfree(subreq);
239 0 : if (ret != EOK && ret != ERR_NO_POSIX) {
240 : /* We can only finish the id_op on error as the connection
241 : * is re-used by the user search
242 : */
243 0 : ret = sdap_id_op_done(state->user_op, ret, &dp_error);
244 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
245 : /* retry */
246 0 : ret = sdap_dom_enum_ex_retry(req, state->user_op,
247 : sdap_dom_enum_ex_get_users);
248 0 : if (ret != EOK) {
249 0 : tevent_req_error(req, ret);
250 : }
251 0 : return;
252 0 : } else if (dp_error == DP_ERR_OFFLINE) {
253 0 : DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
254 0 : tevent_req_done(req);
255 0 : return;
256 : } else {
257 : /* Non-recoverable error */
258 0 : DEBUG(SSSDBG_OP_FAILURE,
259 : "POSIX check failed: %d: %s\n", ret, sss_strerror(ret));
260 0 : tevent_req_error(req, ret);
261 0 : return;
262 : }
263 : }
264 :
265 0 : state->ctx->srv_opts->posix_checked = true;
266 :
267 : /* If the check ran to completion, we know for certain about the attributes
268 : */
269 0 : if (has_posix == false) {
270 0 : tevent_req_error(req, ERR_NO_POSIX);
271 0 : return;
272 : }
273 :
274 :
275 0 : ret = sdap_dom_enum_search_users(req);
276 0 : if (ret != EOK) {
277 0 : tevent_req_error(req, ret);
278 0 : return;
279 : }
280 : /* Execution resumes in sdap_dom_enum_ex_users_done */
281 : }
282 :
283 0 : static errno_t sdap_dom_enum_search_users(struct tevent_req *req)
284 : {
285 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
286 : struct sdap_dom_enum_ex_state);
287 : struct tevent_req *subreq;
288 :
289 0 : subreq = enum_users_send(state, state->ev,
290 : state->ctx, state->sdom,
291 0 : state->user_op, state->purge);
292 0 : if (subreq == NULL) {
293 0 : return ENOMEM;
294 : }
295 0 : tevent_req_set_callback(subreq, sdap_dom_enum_ex_users_done, req);
296 0 : return EOK;
297 : }
298 :
299 0 : static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq)
300 : {
301 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
302 : struct tevent_req);
303 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
304 : struct sdap_dom_enum_ex_state);
305 : errno_t ret;
306 : int dp_error;
307 :
308 0 : ret = enum_users_recv(subreq);
309 0 : talloc_zfree(subreq);
310 0 : ret = sdap_id_op_done(state->user_op, ret, &dp_error);
311 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
312 : /* retry */
313 0 : ret = sdap_dom_enum_ex_retry(req, state->user_op,
314 : sdap_dom_enum_ex_get_users);
315 0 : if (ret != EOK) {
316 0 : tevent_req_error(req, ret);
317 0 : return;
318 : }
319 0 : return;
320 0 : } else if (dp_error == DP_ERR_OFFLINE) {
321 0 : DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
322 0 : tevent_req_done(req);
323 0 : return;
324 0 : } else if (ret != EOK && ret != ENOENT) {
325 : /* Non-recoverable error */
326 0 : DEBUG(SSSDBG_OP_FAILURE,
327 : "User enumeration failed: %d: %s\n", ret, sss_strerror(ret));
328 0 : tevent_req_error(req, ret);
329 0 : return;
330 : }
331 :
332 0 : state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache);
333 0 : if (state->group_op == NULL) {
334 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for groups\n");
335 0 : tevent_req_error(req, EIO);
336 0 : return;
337 : }
338 :
339 0 : ret = sdap_dom_enum_ex_retry(req, state->group_op,
340 : sdap_dom_enum_ex_get_groups);
341 0 : if (ret != EOK) {
342 0 : tevent_req_error(req, ret);
343 0 : return;
344 : }
345 :
346 : /* Continues to sdap_dom_enum_ex_get_groups */
347 : }
348 :
349 0 : static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq)
350 : {
351 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
352 : struct tevent_req);
353 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
354 : struct sdap_dom_enum_ex_state);
355 :
356 0 : if (sdap_dom_enum_ex_connected(subreq) == false) {
357 0 : return;
358 : }
359 :
360 0 : subreq = enum_groups_send(state, state->ev, state->ctx,
361 : state->sdom,
362 0 : state->group_op, state->purge);
363 0 : if (subreq == NULL) {
364 0 : tevent_req_error(req, ENOMEM);
365 0 : return;
366 : }
367 0 : tevent_req_set_callback(subreq, sdap_dom_enum_ex_groups_done, req);
368 : }
369 :
370 0 : static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq)
371 : {
372 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
373 : struct tevent_req);
374 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
375 : struct sdap_dom_enum_ex_state);
376 : int ret;
377 : int dp_error;
378 :
379 0 : ret = enum_groups_recv(subreq);
380 0 : talloc_zfree(subreq);
381 0 : ret = sdap_id_op_done(state->group_op, ret, &dp_error);
382 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
383 : /* retry */
384 0 : ret = sdap_dom_enum_ex_retry(req, state->group_op,
385 : sdap_dom_enum_ex_get_groups);
386 0 : if (ret != EOK) {
387 0 : tevent_req_error(req, ret);
388 0 : return;
389 : }
390 0 : return;
391 0 : } else if (dp_error == DP_ERR_OFFLINE) {
392 0 : DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
393 0 : tevent_req_done(req);
394 0 : return;
395 0 : } else if (ret != EOK && ret != ENOENT) {
396 : /* Non-recoverable error */
397 0 : DEBUG(SSSDBG_OP_FAILURE,
398 : "Group enumeration failed: %d: %s\n", ret, sss_strerror(ret));
399 0 : tevent_req_error(req, ret);
400 0 : return;
401 : }
402 :
403 :
404 0 : state->svc_op = sdap_id_op_create(state, state->svc_conn->conn_cache);
405 0 : if (state->svc_op == NULL) {
406 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for svcs\n");
407 0 : tevent_req_error(req, EIO);
408 0 : return;
409 : }
410 :
411 0 : ret = sdap_dom_enum_ex_retry(req, state->svc_op,
412 : sdap_dom_enum_ex_get_svcs);
413 0 : if (ret != EOK) {
414 0 : tevent_req_error(req, ret);
415 0 : return;
416 : }
417 : }
418 :
419 0 : static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq)
420 : {
421 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
422 : struct tevent_req);
423 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
424 : struct sdap_dom_enum_ex_state);
425 :
426 0 : if (sdap_dom_enum_ex_connected(subreq) == false) {
427 0 : return;
428 : }
429 :
430 0 : subreq = enum_services_send(state, state->ev, state->ctx,
431 0 : state->svc_op, state->purge);
432 0 : if (!subreq) {
433 0 : tevent_req_error(req, ENOMEM);
434 0 : return;
435 : }
436 0 : tevent_req_set_callback(subreq, sdap_dom_enum_ex_svcs_done, req);
437 : }
438 :
439 0 : static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq)
440 : {
441 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
442 : struct tevent_req);
443 0 : struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
444 : struct sdap_dom_enum_ex_state);
445 : int ret;
446 : int dp_error;
447 :
448 0 : ret = enum_services_recv(subreq);
449 0 : talloc_zfree(subreq);
450 0 : ret = sdap_id_op_done(state->svc_op, ret, &dp_error);
451 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
452 : /* retry */
453 0 : ret = sdap_dom_enum_ex_retry(req, state->user_op,
454 : sdap_dom_enum_ex_get_svcs);
455 0 : if (ret != EOK) {
456 0 : tevent_req_error(req, ret);
457 0 : return;
458 : }
459 0 : return;
460 0 : } else if (dp_error == DP_ERR_OFFLINE) {
461 0 : DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
462 0 : tevent_req_done(req);
463 0 : return;
464 0 : } else if (ret != EOK && ret != ENOENT) {
465 : /* Non-recoverable error */
466 0 : DEBUG(SSSDBG_OP_FAILURE,
467 : "Service enumeration failed: %d: %s\n", ret, sss_strerror(ret));
468 0 : tevent_req_error(req, ret);
469 0 : return;
470 : }
471 :
472 : /* Ok, we've completed an enumeration. Save this to the
473 : * sysdb so we can postpone starting up the enumeration
474 : * process on the next SSSD service restart (to avoid
475 : * slowing down system boot-up
476 : */
477 0 : ret = sysdb_set_enumerated(state->sdom->dom, true);
478 0 : if (ret != EOK) {
479 0 : DEBUG(SSSDBG_MINOR_FAILURE,
480 : "Could not mark domain as having enumerated.\n");
481 : /* This error is non-fatal, so continue */
482 : }
483 :
484 0 : if (state->purge) {
485 0 : ret = ldap_id_cleanup(state->ctx->opts, state->sdom);
486 0 : if (ret != EOK) {
487 : /* Not fatal, worst case we'll have stale entries that would be
488 : * removed on a subsequent online lookup
489 : */
490 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Cleanup failed: [%d]: %s\n",
491 : ret, sss_strerror(ret));
492 : }
493 : }
494 :
495 0 : tevent_req_done(req);
496 : }
497 :
498 0 : errno_t sdap_dom_enum_ex_recv(struct tevent_req *req)
499 : {
500 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
501 :
502 0 : return EOK;
503 : }
504 :
505 : /* ==Enumeration-Request==================================================== */
506 : struct tevent_req *
507 0 : sdap_dom_enum_send(TALLOC_CTX *memctx,
508 : struct tevent_context *ev,
509 : struct sdap_id_ctx *ctx,
510 : struct sdap_domain *sdom,
511 : struct sdap_id_conn_ctx *conn)
512 : {
513 0 : return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom, conn, conn, conn);
514 : }
515 :
516 0 : errno_t sdap_dom_enum_recv(struct tevent_req *req)
517 : {
518 0 : return sdap_dom_enum_ex_recv(req);
519 : }
520 :
521 : /* ==User-Enumeration===================================================== */
522 : struct enum_users_state {
523 : struct tevent_context *ev;
524 : struct sdap_id_ctx *ctx;
525 : struct sdap_domain *sdom;
526 : struct sdap_id_op *op;
527 :
528 : char *filter;
529 : const char **attrs;
530 : };
531 :
532 : static void enum_users_done(struct tevent_req *subreq);
533 :
534 0 : static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
535 : struct tevent_context *ev,
536 : struct sdap_id_ctx *ctx,
537 : struct sdap_domain *sdom,
538 : struct sdap_id_op *op,
539 : bool purge)
540 : {
541 : struct tevent_req *req, *subreq;
542 : struct enum_users_state *state;
543 : int ret;
544 : bool use_mapping;
545 :
546 0 : req = tevent_req_create(memctx, &state, struct enum_users_state);
547 0 : if (!req) return NULL;
548 :
549 0 : state->ev = ev;
550 0 : state->sdom = sdom;
551 0 : state->ctx = ctx;
552 0 : state->op = op;
553 :
554 0 : use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
555 0 : ctx->opts->idmap_ctx,
556 0 : sdom->dom->name,
557 0 : sdom->dom->domain_id);
558 :
559 : /* We always want to filter on objectclass and an available name */
560 0 : state->filter = talloc_asprintf(state,
561 : "(&(objectclass=%s)(%s=*)",
562 0 : ctx->opts->user_map[SDAP_OC_USER].name,
563 0 : ctx->opts->user_map[SDAP_AT_USER_NAME].name);
564 0 : if (!state->filter) {
565 0 : DEBUG(SSSDBG_MINOR_FAILURE,
566 : "Failed to build base filter\n");
567 0 : ret = ENOMEM;
568 0 : goto fail;
569 : }
570 :
571 0 : if (use_mapping) {
572 : /* If we're ID-mapping, check for the objectSID as well */
573 0 : state->filter = talloc_asprintf_append_buffer(
574 0 : state->filter, "(%s=*)",
575 0 : ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name);
576 : } else {
577 : /* We're not ID-mapping, so make sure to only get entries
578 : * that have UID and GID
579 : */
580 0 : state->filter = talloc_asprintf_append_buffer(
581 0 : state->filter, "(%s=*)(%s=*)",
582 0 : ctx->opts->user_map[SDAP_AT_USER_UID].name,
583 0 : ctx->opts->user_map[SDAP_AT_USER_GID].name);
584 : }
585 0 : if (!state->filter) {
586 0 : DEBUG(SSSDBG_MINOR_FAILURE,
587 : "Failed to build base filter\n");
588 0 : ret = ENOMEM;
589 0 : goto fail;
590 : }
591 :
592 0 : if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) {
593 : /* If we have lastUSN available and we're not doing a full
594 : * refresh, limit to changes with a higher entryUSN value.
595 : */
596 0 : state->filter = talloc_asprintf_append_buffer(
597 0 : state->filter,
598 : "(%s>=%s)(!(%s=%s))",
599 0 : ctx->opts->user_map[SDAP_AT_USER_USN].name,
600 0 : ctx->srv_opts->max_user_value,
601 0 : ctx->opts->user_map[SDAP_AT_USER_USN].name,
602 0 : ctx->srv_opts->max_user_value);
603 :
604 0 : if (!state->filter) {
605 0 : DEBUG(SSSDBG_MINOR_FAILURE,
606 : "Failed to build base filter\n");
607 0 : ret = ENOMEM;
608 0 : goto fail;
609 : }
610 : }
611 :
612 : /* Terminate the search filter */
613 0 : state->filter = talloc_asprintf_append_buffer(state->filter, ")");
614 0 : if (!state->filter) {
615 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to build base filter\n");
616 0 : ret = ENOMEM;
617 0 : goto fail;
618 : }
619 :
620 : /* TODO: handle attrs_type */
621 0 : ret = build_attrs_from_map(state, ctx->opts->user_map,
622 0 : ctx->opts->user_map_cnt,
623 0 : NULL, &state->attrs, NULL);
624 0 : if (ret != EOK) goto fail;
625 :
626 : /* TODO: restrict the enumerations to using a single
627 : * search base at a time.
628 : */
629 :
630 0 : subreq = sdap_get_users_send(state, state->ev,
631 0 : state->sdom->dom,
632 0 : state->sdom->dom->sysdb,
633 0 : state->ctx->opts,
634 0 : state->sdom->user_search_bases,
635 0 : sdap_id_op_handle(state->op),
636 0 : state->attrs, state->filter,
637 0 : dp_opt_get_int(state->ctx->opts->basic,
638 : SDAP_ENUM_SEARCH_TIMEOUT),
639 : SDAP_LOOKUP_ENUMERATE);
640 0 : if (!subreq) {
641 0 : ret = ENOMEM;
642 0 : goto fail;
643 : }
644 0 : tevent_req_set_callback(subreq, enum_users_done, req);
645 :
646 0 : return req;
647 :
648 : fail:
649 0 : tevent_req_error(req, ret);
650 0 : tevent_req_post(req, ev);
651 0 : return req;
652 : }
653 :
654 0 : static void enum_users_done(struct tevent_req *subreq)
655 : {
656 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
657 : struct tevent_req);
658 0 : struct enum_users_state *state = tevent_req_data(req,
659 : struct enum_users_state);
660 : char *usn_value;
661 0 : char *endptr = NULL;
662 : unsigned usn_number;
663 : int ret;
664 :
665 0 : ret = sdap_get_users_recv(subreq, state, &usn_value);
666 0 : talloc_zfree(subreq);
667 0 : if (ret) {
668 0 : tevent_req_error(req, ret);
669 0 : return;
670 : }
671 :
672 0 : if (usn_value) {
673 0 : talloc_zfree(state->ctx->srv_opts->max_user_value);
674 0 : state->ctx->srv_opts->max_user_value =
675 0 : talloc_steal(state->ctx, usn_value);
676 :
677 0 : usn_number = strtoul(usn_value, &endptr, 10);
678 0 : if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
679 0 : && (usn_number > state->ctx->srv_opts->last_usn)) {
680 0 : state->ctx->srv_opts->last_usn = usn_number;
681 : }
682 : }
683 :
684 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Users higher USN value: [%s]\n",
685 : state->ctx->srv_opts->max_user_value);
686 :
687 0 : tevent_req_done(req);
688 : }
689 :
690 0 : static errno_t enum_users_recv(struct tevent_req *req)
691 : {
692 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
693 :
694 0 : return EOK;
695 : }
696 :
697 : /* =Group-Enumeration===================================================== */
698 : struct enum_groups_state {
699 : struct tevent_context *ev;
700 : struct sdap_id_ctx *ctx;
701 : struct sdap_domain *sdom;
702 : struct sdap_id_op *op;
703 :
704 : char *filter;
705 : const char **attrs;
706 : };
707 :
708 : static void enum_groups_done(struct tevent_req *subreq);
709 :
710 0 : static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
711 : struct tevent_context *ev,
712 : struct sdap_id_ctx *ctx,
713 : struct sdap_domain *sdom,
714 : struct sdap_id_op *op,
715 : bool purge)
716 : {
717 : struct tevent_req *req, *subreq;
718 : struct enum_groups_state *state;
719 : int ret;
720 : bool use_mapping;
721 : char *oc_list;
722 :
723 0 : req = tevent_req_create(memctx, &state, struct enum_groups_state);
724 0 : if (!req) return NULL;
725 :
726 0 : state->ev = ev;
727 0 : state->sdom = sdom;
728 0 : state->ctx = ctx;
729 0 : state->op = op;
730 :
731 0 : use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
732 0 : ctx->opts->idmap_ctx,
733 0 : sdom->dom->name,
734 0 : sdom->dom->domain_id);
735 :
736 : /* We always want to filter on objectclass and an available name */
737 0 : oc_list = sdap_make_oc_list(state, ctx->opts->group_map);
738 0 : if (oc_list == NULL) {
739 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
740 0 : ret = ENOMEM;
741 0 : goto fail;
742 : }
743 :
744 0 : state->filter = talloc_asprintf(state, "(&(%s)(%s=*)", oc_list,
745 0 : ctx->opts->group_map[SDAP_AT_GROUP_NAME].name);
746 0 : if (!state->filter) {
747 0 : DEBUG(SSSDBG_MINOR_FAILURE,
748 : "Failed to build base filter\n");
749 0 : ret = ENOMEM;
750 0 : goto fail;
751 : }
752 :
753 0 : if (use_mapping) {
754 : /* If we're ID-mapping, check for the objectSID as well */
755 0 : state->filter = talloc_asprintf_append_buffer(
756 0 : state->filter, "(%s=*)",
757 0 : ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name);
758 : } else {
759 : /* We're not ID-mapping, so make sure to only get entries
760 : * that have a non-zero GID.
761 : */
762 0 : state->filter = talloc_asprintf_append_buffer(
763 0 : state->filter, "(&(%s=*)(!(%s=0)))",
764 0 : ctx->opts->group_map[SDAP_AT_GROUP_GID].name,
765 0 : ctx->opts->group_map[SDAP_AT_GROUP_GID].name);
766 : }
767 0 : if (!state->filter) {
768 0 : DEBUG(SSSDBG_MINOR_FAILURE,
769 : "Failed to build base filter\n");
770 0 : ret = ENOMEM;
771 0 : goto fail;
772 : }
773 :
774 0 : if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) {
775 0 : state->filter = talloc_asprintf_append_buffer(
776 0 : state->filter,
777 : "(%s>=%s)(!(%s=%s))",
778 0 : ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
779 0 : ctx->srv_opts->max_group_value,
780 0 : ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
781 0 : ctx->srv_opts->max_group_value);
782 0 : if (!state->filter) {
783 0 : DEBUG(SSSDBG_MINOR_FAILURE,
784 : "Failed to build base filter\n");
785 0 : ret = ENOMEM;
786 0 : goto fail;
787 : }
788 : }
789 :
790 : /* Terminate the search filter */
791 0 : state->filter = talloc_asprintf_append_buffer(state->filter, ")");
792 0 : if (!state->filter) {
793 0 : DEBUG(SSSDBG_MINOR_FAILURE,
794 : "Failed to build base filter\n");
795 0 : ret = ENOMEM;
796 0 : goto fail;
797 : }
798 :
799 : /* TODO: handle attrs_type */
800 0 : ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
801 0 : NULL, &state->attrs, NULL);
802 0 : if (ret != EOK) goto fail;
803 :
804 : /* TODO: restrict the enumerations to using a single
805 : * search base at a time.
806 : */
807 :
808 0 : subreq = sdap_get_groups_send(state, state->ev,
809 0 : state->sdom,
810 0 : state->ctx->opts,
811 0 : sdap_id_op_handle(state->op),
812 0 : state->attrs, state->filter,
813 0 : dp_opt_get_int(state->ctx->opts->basic,
814 : SDAP_ENUM_SEARCH_TIMEOUT),
815 : SDAP_LOOKUP_ENUMERATE, false);
816 0 : if (!subreq) {
817 0 : ret = ENOMEM;
818 0 : goto fail;
819 : }
820 0 : tevent_req_set_callback(subreq, enum_groups_done, req);
821 :
822 0 : return req;
823 :
824 : fail:
825 0 : tevent_req_error(req, ret);
826 0 : tevent_req_post(req, ev);
827 0 : return req;
828 : }
829 :
830 0 : static void enum_groups_done(struct tevent_req *subreq)
831 : {
832 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
833 : struct tevent_req);
834 0 : struct enum_groups_state *state = tevent_req_data(req,
835 : struct enum_groups_state);
836 : char *usn_value;
837 0 : char *endptr = NULL;
838 : unsigned usn_number;
839 : int ret;
840 :
841 0 : ret = sdap_get_groups_recv(subreq, state, &usn_value);
842 0 : talloc_zfree(subreq);
843 0 : if (ret) {
844 0 : tevent_req_error(req, ret);
845 0 : return;
846 : }
847 :
848 0 : if (usn_value) {
849 0 : talloc_zfree(state->ctx->srv_opts->max_group_value);
850 0 : state->ctx->srv_opts->max_group_value =
851 0 : talloc_steal(state->ctx, usn_value);
852 0 : usn_number = strtoul(usn_value, &endptr, 10);
853 0 : if ((endptr == NULL || (*endptr == '\0' && endptr != usn_value))
854 0 : && (usn_number > state->ctx->srv_opts->last_usn)) {
855 0 : state->ctx->srv_opts->last_usn = usn_number;
856 : }
857 : }
858 :
859 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Groups higher USN value: [%s]\n",
860 : state->ctx->srv_opts->max_group_value);
861 :
862 0 : tevent_req_done(req);
863 : }
864 :
865 0 : static errno_t enum_groups_recv(struct tevent_req *req)
866 : {
867 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
868 :
869 0 : return EOK;
870 : }
|