1 /*
2 SSSD
3
4 LDAP Identity Enumeration
5
6 Authors:
7 Simo Sorce <ssorce@redhat.com>
8
9 Copyright (C) 2009 Red Hat
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include <errno.h>
26 #include <time.h>
27 #include <sys/time.h>
28
29 #include "util/util.h"
30 #include "db/sysdb.h"
31 #include "providers/ldap/ldap_common.h"
32 #include "providers/ldap/sdap_async.h"
33
34 extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx,
35 struct tevent_context *ev,
36 struct sdap_id_ctx *ctx);
37
38 /* ==Enumeration-Task===================================================== */
39
40 static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
41 struct sdap_id_ctx *ctx);
42
43 static void ldap_id_enumerate_reschedule(struct tevent_req *req);
44
45 static void ldap_id_enumerate_timeout(struct tevent_context *ev,
46 struct tevent_timer *te,
47 struct timeval tv, void *pvt);
48
49 static void ldap_id_enumerate_timer(struct tevent_context *ev,
50 struct tevent_timer *tt,
51 struct timeval tv, void *pvt)
52 {
53 struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx);
54 struct tevent_timer *timeout;
55 struct tevent_req *req;
56 int delay;
57
58 if (be_is_offline(ctx->be)) {
59 DEBUG(4, ("Backend is marked offline, retry later!\n"));
60 /* schedule starting from now, not the last run */
61 delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
62 tv = tevent_timeval_current_ofs(delay, 0);
63 ldap_id_enumerate_set_timer(ctx, tv);
64 return;
65 }
66
67 req = ldap_id_enumerate_send(ev, ctx);
68 if (!req) {
69 DEBUG(1, ("Failed to schedule enumeration, retrying later!\n"));
70 /* schedule starting from now, not the last run */
71 delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
72 tv = tevent_timeval_current_ofs(delay, 0);
73 ldap_id_enumerate_set_timer(ctx, tv);
74 return;
75 }
76 tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx);
77
78 /* if enumeration takes so long, either we try to enumerate too
79 * frequently, or something went seriously wrong */
80 delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
81 tv = tevent_timeval_current_ofs(delay, 0);
Event returned_pointer: Pointer "timeout" returned by "_tevent_add_timer(ctx->be->ev, req, tv, ldap_id_enumerate_timeout, req, &"ldap_id_enumerate_timeout", &"providers/ldap/ldap_id_enum.c:82")" is never used.
|
82 timeout = tevent_add_timer(ctx->be->ev, req, tv,
83 ldap_id_enumerate_timeout, req);
84 return;
85 }
86
87 static void ldap_id_enumerate_timeout(struct tevent_context *ev,
88 struct tevent_timer *te,
89 struct timeval tv, void *pvt)
90 {
91 struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
92 struct sdap_id_ctx *ctx = tevent_req_callback_data(req,
93 struct sdap_id_ctx);
94 int delay;
95
96 delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
97 DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay));
98
99 tv = tevent_timeval_current_ofs(delay, 0);
100 ldap_id_enumerate_set_timer(ctx, tv);
101
102 talloc_zfree(req);
103 }
104
105 static void ldap_id_enumerate_reschedule(struct tevent_req *req)
106 {
107 struct sdap_id_ctx *ctx = tevent_req_callback_data(req,
108 struct sdap_id_ctx);
109 enum tevent_req_state tstate;
110 uint64_t err;
111 struct timeval tv;
112 int delay;
113
114 if (tevent_req_is_error(req, &tstate, &err)) {
115 /* On error schedule starting from now, not the last run */
116 tv = tevent_timeval_current();
117 } else {
118 tv = ctx->last_enum;
119 }
120 talloc_zfree(req);
121
122 delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
123 tv = tevent_timeval_add(&tv, delay, 0);
124 ldap_id_enumerate_set_timer(ctx, tv);
125 }
126
127
128
129 int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv)
130 {
131 struct tevent_timer *enum_task;
132
133 DEBUG(6, ("Scheduling next enumeration at %ld.%ld\n",
134 (long)tv.tv_sec, (long)tv.tv_usec));
135
136 enum_task = tevent_add_timer(ctx->be->ev, ctx,
137 tv, ldap_id_enumerate_timer, ctx);
138 if (!enum_task) {
139 DEBUG(0, ("FATAL: failed to setup enumeration task!\n"));
140 return EFAULT;
141 }
142
143 return EOK;
144 }
145
146 #define MAX_ENUM_RESTARTS 3
147
148 struct global_enum_state {
149 struct tevent_context *ev;
150 struct sdap_id_ctx *ctx;
151
152 bool purge;
153 int restarts;
154 };
155
156 static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
157 struct tevent_context *ev,
158 struct sdap_id_ctx *ctx,
159 bool purge);
160 static void ldap_id_enum_users_done(struct tevent_req *subreq);
161 static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
162 struct tevent_context *ev,
163 struct sdap_id_ctx *ctx,
164 bool purge);
165 static void ldap_id_enum_groups_done(struct tevent_req *subreq);
166 static void ldap_id_enum_cleanup_done(struct tevent_req *subreq);
167 static int ldap_id_enum_users_restart(struct tevent_req *req);
168 static int ldap_id_enum_groups_restart(struct tevent_req *req);
169
170 static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
171 struct sdap_id_ctx *ctx)
172 {
173 struct global_enum_state *state;
174 struct tevent_req *req, *subreq;
175 int t;
176
177 req = tevent_req_create(ctx, &state, struct global_enum_state);
178 if (!req) return NULL;
179
180 state->ev = ev;
181 state->ctx = ctx;
182 state->restarts = 0;
183
184 ctx->last_enum = tevent_timeval_current();
185
186 t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT);
187 if ((ctx->last_purge.tv_sec + t) < ctx->last_enum.tv_sec) {
188 state->purge = true;
189 } else {
190 state->purge = false;
191 }
192
193 subreq = enum_users_send(state, ev, ctx, state->purge);
194 if (!subreq) {
195 talloc_zfree(req);
196 return NULL;
197 }
198 tevent_req_set_callback(subreq, ldap_id_enum_users_done, req);
199
200 return req;
201 }
202
203 static void ldap_id_enum_users_done(struct tevent_req *subreq)
204 {
205 struct tevent_req *req = tevent_req_callback_data(subreq,
206 struct tevent_req);
207 struct global_enum_state *state = tevent_req_data(req,
208 struct global_enum_state);
209 enum tevent_req_state tstate;
210 uint64_t err = 0;
211 int ret;
212
213 if (tevent_req_is_error(subreq, &tstate, &err)) {
214 if (tstate != TEVENT_REQ_USER_ERROR) {
215 err = EIO;
216 }
217 if (err != ENOENT) {
218 goto fail;
219 }
220 }
221 talloc_zfree(subreq);
222
223 subreq = enum_groups_send(state, state->ev, state->ctx, state->purge);
224 if (!subreq) {
225 goto fail;
226 }
227 tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req);
228
229 return;
230
231 fail:
232 if (err) {
233 DEBUG(9, ("User enumeration failed with: (%d)[%s]\n",
234 (int)err, strerror(err)));
235
236 if (sdap_check_gssapi_reconnect(state->ctx)) {
237 if (state->ctx->gsh) {
238 state->ctx->gsh->connected = false;
239 }
240 ret = ldap_id_enum_users_restart(req);
241 if (ret == EOK) return;
242 }
243 sdap_mark_offline(state->ctx);
244 }
245
246 DEBUG(1, ("Failed to enumerate users, retrying later!\n"));
247 tevent_req_done(req);
248 }
249
250 static void ldap_id_enum_groups_done(struct tevent_req *subreq)
251 {
252 struct tevent_req *req = tevent_req_callback_data(subreq,
253 struct tevent_req);
254 struct global_enum_state *state = tevent_req_data(req,
255 struct global_enum_state);
256 enum tevent_req_state tstate;
257 uint64_t err = 0;
258 int ret;
259
260 if (tevent_req_is_error(subreq, &tstate, &err)) {
261 if (tstate != TEVENT_REQ_USER_ERROR) {
262 err = EIO;
263 }
264 if (err != ENOENT) {
265 goto fail;
266 }
267 }
268 talloc_zfree(subreq);
269
270 if (state->purge) {
271
272 subreq = ldap_id_cleanup_send(state, state->ev, state->ctx);
273 if (!subreq) {
274 goto fail;
275 }
276 tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req);
277
278 return;
279 }
280
281 tevent_req_done(req);
282 return;
283
284 fail:
285 /* check if credentials are expired otherwise go offline on failures */
286 if (sdap_check_gssapi_reconnect(state->ctx)) {
287 if (state->ctx->gsh) {
288 state->ctx->gsh->connected = false;
289 }
290 ret = ldap_id_enum_groups_restart(req);
291 if (ret == EOK) return;
292 }
293 sdap_mark_offline(state->ctx);
294 DEBUG(1, ("Failed to enumerate groups (%d [%s]), retrying later!\n",
295 (int)err, strerror(err)));
296 tevent_req_done(req);
297 }
298
299 static void ldap_id_enum_cleanup_done(struct tevent_req *subreq)
300 {
301 struct tevent_req *req = tevent_req_callback_data(subreq,
302 struct tevent_req);
303 talloc_zfree(subreq);
304 tevent_req_done(req);
305 }
306
307 static void ldap_id_enum_users_immediate(struct tevent_context *ctx,
308 struct tevent_immediate *im,
309 void *private_data)
310 {
311 struct tevent_req *req = talloc_get_type(private_data,
312 struct tevent_req);
313 struct global_enum_state *state = tevent_req_data(req,
314 struct global_enum_state);
315 struct tevent_req *subreq;
316
317 subreq = enum_users_send(state, state->ev, state->ctx, state->purge);
318 if (subreq == NULL) {
319 tevent_req_error(req, ENOMEM);
320 return;
321 }
322 tevent_req_set_callback(subreq, ldap_id_enum_users_done, req);
323 }
324
325 static int ldap_id_enum_users_restart(struct tevent_req *req)
326 {
327 struct global_enum_state *state = tevent_req_data(req,
328 struct global_enum_state);
329 struct tevent_immediate *im;
330
331 state->restarts++;
332 if (state->restarts < MAX_ENUM_RESTARTS) {
333 return ELOOP;
334 }
335
336 im = tevent_create_immediate(req);
337 if (!im) {
338 return ENOMEM;
339 }
340
341 /* schedule a completely new event to avoid deep recursions */
342 tevent_schedule_immediate(im, state->ev,
343 ldap_id_enum_users_immediate, req);
344
345 return EOK;
346 }
347
348 static void ldap_id_enum_groups_immediate(struct tevent_context *ctx,
349 struct tevent_immediate *im,
350 void *private_data)
351 {
352 struct tevent_req *req = talloc_get_type(private_data,
353 struct tevent_req);
354 struct global_enum_state *state = tevent_req_data(req,
355 struct global_enum_state);
356 struct tevent_req *subreq;
357
358 subreq = enum_groups_send(state, state->ev, state->ctx, state->purge);
359 if (subreq == NULL) {
360 tevent_req_error(req, ENOMEM);
361 return;
362 }
363 tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req);
364 }
365
366 static int ldap_id_enum_groups_restart(struct tevent_req *req)
367 {
368 struct global_enum_state *state = tevent_req_data(req,
369 struct global_enum_state);
370 struct tevent_immediate *im;
371
372 state->restarts++;
373 if (state->restarts < MAX_ENUM_RESTARTS) {
374 return ELOOP;
375 }
376
377 im = tevent_create_immediate(req);
378 if (!im) {
379 return ENOMEM;
380 }
381
382 /* schedule a completely new event to avoid deep recursions */
383 tevent_schedule_immediate(im, state->ev,
384 ldap_id_enum_groups_immediate, req);
385
386 return EOK;
387 }
388
389
390 /* ==User-Enumeration===================================================== */
391
392 struct enum_users_state {
393 struct tevent_context *ev;
394 struct sdap_id_ctx *ctx;
395
396 char *filter;
397 const char **attrs;
398 };
399
400 static void enum_users_connect_done(struct tevent_req *subreq);
401 static void enum_users_op_done(struct tevent_req *subreq);
402
403 static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
404 struct tevent_context *ev,
405 struct sdap_id_ctx *ctx,
406 bool purge)
407 {
408 struct tevent_req *req, *subreq;
409 struct enum_users_state *state;
410 int ret;
411
412 req = tevent_req_create(memctx, &state, struct enum_users_state);
413 if (!req) return NULL;
414
415 state->ev = ev;
416 state->ctx = ctx;
417
418 if (ctx->max_user_timestamp && !purge) {
419
420 state->filter = talloc_asprintf(state,
421 "(&(%s=*)(objectclass=%s)(%s>=%s)(!(%s=%s)))",
422 ctx->opts->user_map[SDAP_AT_USER_NAME].name,
423 ctx->opts->user_map[SDAP_OC_USER].name,
424 ctx->opts->user_map[SDAP_AT_USER_MODSTAMP].name,
425 ctx->max_user_timestamp,
426 ctx->opts->user_map[SDAP_AT_USER_MODSTAMP].name,
427 ctx->max_user_timestamp);
428 } else {
429 state->filter = talloc_asprintf(state,
430 "(&(%s=*)(objectclass=%s))",
431 ctx->opts->user_map[SDAP_AT_USER_NAME].name,
432 ctx->opts->user_map[SDAP_OC_USER].name);
433 }
434 if (!state->filter) {
435 DEBUG(2, ("Failed to build filter\n"));
436 ret = ENOMEM;
437 goto fail;
438 }
439
440 /* TODO: handle attrs_type */
441 ret = build_attrs_from_map(state, ctx->opts->user_map,
442 SDAP_OPTS_USER, &state->attrs);
443 if (ret != EOK) goto fail;
444
445 if (!sdap_connected(ctx)) {
446
447 /* FIXME: add option to decide if tls should be used
448 * or SASL/GSSAPI, etc ... */
449 subreq = sdap_cli_connect_send(state, ev, ctx->opts,
450 ctx->be, ctx->service,
451 &ctx->rootDSE);
452 if (!subreq) {
453 ret = ENOMEM;
454 goto fail;
455 }
456
457 tevent_req_set_callback(subreq, enum_users_connect_done, req);
458
459 return req;
460 }
461
462 subreq = sdap_get_users_send(state, state->ev,
463 state->ctx->be->domain,
464 state->ctx->be->sysdb,
465 state->ctx->opts,
466 state->ctx->gsh,
467 state->attrs, state->filter);
468 if (!subreq) {
469 ret = ENOMEM;
470 goto fail;
471 }
472 tevent_req_set_callback(subreq, enum_users_op_done, req);
473
474 return req;
475
476 fail:
477 tevent_req_error(req, ret);
478 tevent_req_post(req, ev);
479 return req;
480 }
481
482 static void enum_users_connect_done(struct tevent_req *subreq)
483 {
484 struct tevent_req *req = tevent_req_callback_data(subreq,
485 struct tevent_req);
486 struct enum_users_state *state = tevent_req_data(req,
487 struct enum_users_state);
488 int ret;
489
490 ret = sdap_cli_connect_recv(subreq, state->ctx,
491 &state->ctx->gsh, &state->ctx->rootDSE);
492 talloc_zfree(subreq);
493 if (ret) {
494 if (ret == ENOTSUP) {
495 DEBUG(0, ("Authentication mechanism not Supported by server"));
496 }
497 tevent_req_error(req, ret);
498 return;
499 }
500
501 subreq = sdap_get_users_send(state, state->ev,
502 state->ctx->be->domain,
503 state->ctx->be->sysdb,
504 state->ctx->opts, state->ctx->gsh,
505 state->attrs, state->filter);
506 if (!subreq) {
507 tevent_req_error(req, ENOMEM);
508 return;
509 }
510 tevent_req_set_callback(subreq, enum_users_op_done, req);
511 }
512
513 static void enum_users_op_done(struct tevent_req *subreq)
514 {
515 struct tevent_req *req = tevent_req_callback_data(subreq,
516 struct tevent_req);
517 struct enum_users_state *state = tevent_req_data(req,
518 struct enum_users_state);
519 char *timestamp;
520 int ret;
521
522 ret = sdap_get_users_recv(subreq, state, ×tamp);
523 talloc_zfree(subreq);
524 if (ret) {
525 tevent_req_error(req, ret);
526 return;
527 }
528
529 if (timestamp) {
530 talloc_zfree(state->ctx->max_user_timestamp);
531 state->ctx->max_user_timestamp = talloc_steal(state->ctx, timestamp);
532 }
533
534 DEBUG(4, ("Users higher timestamp: [%s]\n",
535 state->ctx->max_user_timestamp));
536
537 tevent_req_done(req);
538 }
539
540 /* =Group-Enumeration===================================================== */
541
542 struct enum_groups_state {
543 struct tevent_context *ev;
544 struct sdap_id_ctx *ctx;
545
546 char *filter;
547 const char **attrs;
548 };
549
550 static void enum_groups_connect_done(struct tevent_req *subreq);
551 static void enum_groups_op_done(struct tevent_req *subreq);
552
553 static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
554 struct tevent_context *ev,
555 struct sdap_id_ctx *ctx,
556 bool purge)
557 {
558 struct tevent_req *req, *subreq;
559 struct enum_groups_state *state;
560 const char *attr_name;
561 int ret;
562
563 req = tevent_req_create(memctx, &state, struct enum_groups_state);
564 if (!req) return NULL;
565
566 state->ev = ev;
567 state->ctx = ctx;
568
569 attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
570
571 if (ctx->max_group_timestamp && !purge) {
572
573 state->filter = talloc_asprintf(state,
574 "(&(%s=*)(objectclass=%s)(%s>=%s)(!(%s=%s)))",
575 ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
576 ctx->opts->group_map[SDAP_OC_GROUP].name,
577 ctx->opts->group_map[SDAP_AT_GROUP_MODSTAMP].name,
578 ctx->max_group_timestamp,
579 ctx->opts->group_map[SDAP_AT_GROUP_MODSTAMP].name,
580 ctx->max_group_timestamp);
581 } else {
582 state->filter = talloc_asprintf(state,
583 "(&(%s=*)(objectclass=%s))",
584 ctx->opts->group_map[SDAP_AT_GROUP_NAME].name,
585 ctx->opts->group_map[SDAP_OC_GROUP].name);
586 }
587 if (!state->filter) {
588 DEBUG(2, ("Failed to build filter\n"));
589 ret = ENOMEM;
590 goto fail;
591 }
592
593 /* TODO: handle attrs_type */
594 ret = build_attrs_from_map(state, ctx->opts->group_map,
595 SDAP_OPTS_GROUP, &state->attrs);
596 if (ret != EOK) goto fail;
597
598 if (!sdap_connected(ctx)) {
599
600 /* FIXME: add option to decide if tls should be used
601 * or SASL/GSSAPI, etc ... */
602 subreq = sdap_cli_connect_send(state, ev, ctx->opts,
603 ctx->be, ctx->service,
604 &ctx->rootDSE);
605 if (!subreq) {
606 ret = ENOMEM;
607 goto fail;
608 }
609
610 tevent_req_set_callback(subreq, enum_groups_connect_done, req);
611
612 return req;
613 }
614
615 subreq = sdap_get_groups_send(state, state->ev,
616 state->ctx->be->domain,
617 state->ctx->be->sysdb,
618 state->ctx->opts, state->ctx->gsh,
619 state->attrs, state->filter);
620 if (!subreq) {
621 ret = ENOMEM;
622 goto fail;
623 }
624 tevent_req_set_callback(subreq, enum_groups_op_done, req);
625
626 return req;
627
628 fail:
629 tevent_req_error(req, ret);
630 tevent_req_post(req, ev);
631 return req;
632 }
633
634 static void enum_groups_connect_done(struct tevent_req *subreq)
635 {
636 struct tevent_req *req = tevent_req_callback_data(subreq,
637 struct tevent_req);
638 struct enum_groups_state *state = tevent_req_data(req,
639 struct enum_groups_state);
640 int ret;
641
642 ret = sdap_cli_connect_recv(subreq, state->ctx,
643 &state->ctx->gsh, &state->ctx->rootDSE);
644 talloc_zfree(subreq);
645 if (ret) {
646 if (ret == ENOTSUP) {
647 DEBUG(0, ("Authentication mechanism not Supported by server"));
648 }
649 tevent_req_error(req, ret);
650 return;
651 }
652
653 subreq = sdap_get_groups_send(state, state->ev,
654 state->ctx->be->domain,
655 state->ctx->be->sysdb,
656 state->ctx->opts, state->ctx->gsh,
657 state->attrs, state->filter);
658 if (!subreq) {
659 tevent_req_error(req, ENOMEM);
660 return;
661 }
662 tevent_req_set_callback(subreq, enum_groups_op_done, req);
663 }
664
665 static void enum_groups_op_done(struct tevent_req *subreq)
666 {
667 struct tevent_req *req = tevent_req_callback_data(subreq,
668 struct tevent_req);
669 struct enum_groups_state *state = tevent_req_data(req,
670 struct enum_groups_state);
671 char *timestamp;
672 int ret;
673
674 ret = sdap_get_groups_recv(subreq, state, ×tamp);
675 talloc_zfree(subreq);
676 if (ret) {
677 tevent_req_error(req, ret);
678 return;
679 }
680
681 if (timestamp) {
682 talloc_zfree(state->ctx->max_group_timestamp);
683 state->ctx->max_group_timestamp = talloc_steal(state->ctx, timestamp);
684 }
685
686 DEBUG(4, ("Groups higher timestamp: [%s]\n",
687 state->ctx->max_group_timestamp));
688
689 tevent_req_done(req);
690 }
691