1 /*
2 SSSD
3
4 Async LDAP Helper routines
5
6 Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
7
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.
12
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.
17
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/>.
20 */
21
22 #include "util/util.h"
23 #include "db/sysdb.h"
24 #include "providers/ldap/sdap_async_private.h"
25
26 /* ==Save-User-Entry====================================================== */
27
28 struct sdap_save_user_state {
29 struct tevent_context *ev;
30 struct sysdb_handle *handle;
31 struct sdap_options *opts;
32
33 struct sss_domain_info *dom;
34
35 const char *name;
36 struct sysdb_attrs *attrs;
37 char *timestamp;
38 };
39
40 static void sdap_save_user_done(struct tevent_req *subreq);
41
42 /* FIXME: support storing additional attributes */
43
44 static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx,
45 struct tevent_context *ev,
46 struct sysdb_handle *handle,
47 struct sdap_options *opts,
48 struct sss_domain_info *dom,
49 struct sysdb_attrs *attrs,
50 bool is_initgr)
51 {
52 struct tevent_req *req, *subreq;
53 struct sdap_save_user_state *state;
54 struct ldb_message_element *el;
55 int ret;
56 const char *pwd;
57 const char *gecos;
58 const char *homedir;
59 const char *shell;
60 long int l;
61 uid_t uid;
62 gid_t gid;
63 struct sysdb_attrs *user_attrs;
64 char *upn = NULL;
65 int i;
66 char *val = NULL;
67 int cache_timeout;
68
69 DEBUG(9, ("Save user\n"));
70
71 req = tevent_req_create(memctx, &state, struct sdap_save_user_state);
72 if (!req) return NULL;
73
74 state->ev = ev;
75 state->handle = handle;
76 state->dom = dom;
77 state->opts = opts;
78 state->attrs = attrs;
79 state->timestamp = NULL;
80
81 ret = sysdb_attrs_get_el(state->attrs,
82 opts->user_map[SDAP_AT_USER_NAME].sys_name, &el);
83 if (ret) goto fail;
84 if (el->num_values == 0) {
85 ret = EINVAL;
86 goto fail;
87 }
88 state->name = (const char *)el->values[0].data;
89
90 ret = sysdb_attrs_get_el(state->attrs,
91 opts->user_map[SDAP_AT_USER_PWD].sys_name, &el);
92 if (ret) goto fail;
93 if (el->num_values == 0) pwd = NULL;
94 else pwd = (const char *)el->values[0].data;
95
96 ret = sysdb_attrs_get_el(state->attrs,
97 opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el);
98 if (ret) goto fail;
99 if (el->num_values == 0) gecos = NULL;
100 else gecos = (const char *)el->values[0].data;
101
102 ret = sysdb_attrs_get_el(state->attrs,
103 opts->user_map[SDAP_AT_USER_HOME].sys_name, &el);
104 if (ret) goto fail;
105 if (el->num_values == 0) homedir = NULL;
106 else homedir = (const char *)el->values[0].data;
107
108 ret = sysdb_attrs_get_el(state->attrs,
109 opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el);
110 if (ret) goto fail;
111 if (el->num_values == 0) shell = NULL;
112 else shell = (const char *)el->values[0].data;
113
114 ret = sysdb_attrs_get_el(state->attrs,
115 opts->user_map[SDAP_AT_USER_UID].sys_name, &el);
116 if (ret) goto fail;
117 if (el->num_values == 0) {
118 DEBUG(1, ("no uid provided for [%s] in domain [%s].\n",
119 state->name, dom->name));
120 ret = EINVAL;
121 goto fail;
122 }
123 errno = 0;
124 l = strtol((const char *)el->values[0].data, NULL, 0);
125 if (errno) {
126 ret = EINVAL;
127 goto fail;
128 }
129 uid = l;
130
131 /* check that the uid is valid for this domain */
132 if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
133 DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
134 state->name));
135 ret = EINVAL;
136 goto fail;
137 }
138
139 ret = sysdb_attrs_get_el(state->attrs,
140 opts->user_map[SDAP_AT_USER_GID].sys_name, &el);
141 if (ret) goto fail;
142 if (el->num_values == 0) {
143 DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
144 state->name, dom->name));
145 ret = EINVAL;
146 goto fail;
147 }
148 errno = 0;
149 l = strtol((const char *)el->values[0].data, NULL, 0);
150 if (errno) {
151 ret = EINVAL;
152 goto fail;
153 }
154 gid = l;
155
156 /* check that the gid is valid for this domain */
157 if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
158 DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
159 state->name));
160 ret = EINVAL;
161 goto fail;
162 }
163
164 user_attrs = sysdb_new_attrs(state);
165 if (user_attrs == NULL) {
166 ret = ENOMEM;
167 goto fail;
168 }
169
170 ret = sysdb_attrs_get_el(state->attrs, SYSDB_ORIG_DN, &el);
171 if (ret) {
172 goto fail;
173 }
174 if (el->num_values == 0) {
175 DEBUG(7, ("Original DN is not available for [%s].\n", state->name));
176 } else {
177 DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n",
178 el->values[0].data, state->name));
179 ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN,
180 (const char *) el->values[0].data);
181 if (ret) {
182 goto fail;
183 }
184 }
185
186 ret = sysdb_attrs_get_el(state->attrs, SYSDB_MEMBEROF, &el);
187 if (ret) {
188 goto fail;
189 }
190 if (el->num_values == 0) {
191 DEBUG(7, ("Original memberOf is not available for [%s].\n",
192 state->name));
193 } else {
194 DEBUG(7, ("Adding original memberOf attributes to [%s].\n",
195 state->name));
196 for (i = 0; i < el->num_values; i++) {
197 ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
198 (const char *) el->values[i].data);
199 if (ret) {
200 goto fail;
201 }
202 }
203 }
204
205 ret = sysdb_attrs_get_el(state->attrs,
206 opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, &el);
207 if (ret) {
208 goto fail;
209 }
210 if (el->num_values == 0) {
211 DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n",
212 state->name));
213 } else {
214 ret = sysdb_attrs_add_string(user_attrs,
215 opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name,
216 (const char*)el->values[0].data);
217 if (ret) {
218 goto fail;
219 }
220 state->timestamp = talloc_strdup(state,
221 (const char*)el->values[0].data);
222 if (!state->timestamp) {
223 ret = ENOMEM;
224 goto fail;
225 }
226 }
227
228 ret = sysdb_attrs_get_el(state->attrs,
229 opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el);
230 if (ret) {
231 goto fail;
232 }
233 if (el->num_values == 0) {
234 DEBUG(7, ("User principle is not available for [%s].\n", state->name));
235 } else {
236 upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
237 if (!upn) {
238 ret = ENOMEM;
239 goto fail;
240 }
241 if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
242 make_realm_upper_case(upn);
243 }
244 DEBUG(7, ("Adding user principle [%s] to attributes of [%s].\n",
245 upn, state->name));
246 ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
247 if (ret) {
248 goto fail;
249 }
250 }
251
252 for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) {
253 ret = sysdb_attrs_get_el(state->attrs, opts->user_map[i].sys_name, &el);
254 if (ret) {
255 goto fail;
256 }
257 if (el->num_values > 0) {
258 DEBUG(9, ("Adding [%s]=[%s] to user attributes.\n",
259 opts->user_map[i].sys_name,
260 (const char*) el->values[0].data));
261 val = talloc_strdup(user_attrs, (const char*) el->values[0].data);
262 if (val == NULL) {
263 ret = ENOMEM;
264 goto fail;
265 }
266 ret = sysdb_attrs_add_string(user_attrs,
267 opts->user_map[i].sys_name, val);
268 if (ret) {
269 goto fail;
270 }
271 }
272 }
273
274 cache_timeout = dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT);
275
276 if (is_initgr) {
277 ret = sysdb_attrs_add_time_t(user_attrs, SYSDB_INITGR_EXPIRE,
278 (cache_timeout ?
279 (time(NULL) + cache_timeout) : 0));
280 if (ret) {
281 goto fail;
282 }
283 }
284
285 DEBUG(6, ("Storing info for user %s\n", state->name));
286
287 subreq = sysdb_store_user_send(state, state->ev, state->handle,
288 state->dom, state->name, pwd,
289 uid, gid, gecos, homedir, shell,
290 user_attrs, cache_timeout);
291 if (!subreq) {
292 ret = ENOMEM;
293 goto fail;
294 }
295 tevent_req_set_callback(subreq, sdap_save_user_done, req);
296
297 return req;
298
299 fail:
300 tevent_req_error(req, ret);
301 tevent_req_post(req, ev);
302 return req;
303 }
304
305 static void sdap_save_user_done(struct tevent_req *subreq)
306 {
307 struct tevent_req *req = tevent_req_callback_data(subreq,
308 struct tevent_req);
309 struct sdap_save_user_state *state = tevent_req_data(req,
310 struct sdap_save_user_state);
311 int ret;
312
313 ret = sysdb_store_user_recv(subreq);
314 talloc_zfree(subreq);
315 if (ret) {
316 DEBUG(2, ("Failed to save user %s\n", state->name));
317 tevent_req_error(req, ret);
318 return;
319 }
320
321 tevent_req_done(req);
322 }
323
324 static int sdap_save_user_recv(struct tevent_req *req,
325 TALLOC_CTX *mem_ctx, char **timestamp)
326 {
327 struct sdap_save_user_state *state = tevent_req_data(req,
328 struct sdap_save_user_state);
329
330 TEVENT_REQ_RETURN_ON_ERROR(req);
331
332 if (timestamp) {
333 *timestamp = talloc_steal(mem_ctx, state->timestamp);
334 }
335
336 return EOK;
337 }
338
339
340 /* ==Generic-Function-to-save-multiple-users============================= */
341
342 struct sdap_save_users_state {
343 struct tevent_context *ev;
344 struct sysdb_ctx *sysdb;
345 struct sdap_options *opts;
346 struct sss_domain_info *dom;
347
348 struct sysdb_attrs **users;
349 int count;
350 int cur;
351
352 struct sysdb_handle *handle;
353
354 char *higher_timestamp;
355 };
356
357 static void sdap_save_users_trans(struct tevent_req *subreq);
358 static void sdap_save_users_store(struct tevent_req *req);
359 static void sdap_save_users_process(struct tevent_req *subreq);
360 struct tevent_req *sdap_save_users_send(TALLOC_CTX *memctx,
361 struct tevent_context *ev,
362 struct sss_domain_info *dom,
363 struct sysdb_ctx *sysdb,
364 struct sdap_options *opts,
365 struct sysdb_attrs **users,
366 int num_users)
367 {
368 struct tevent_req *req, *subreq;
369 struct sdap_save_users_state *state;
370
371 req = tevent_req_create(memctx, &state, struct sdap_save_users_state);
372 if (!req) return NULL;
373
374 state->ev = ev;
375 state->opts = opts;
376 state->sysdb = sysdb;
377 state->dom = dom;
378 state->users = users;
379 state->count = num_users;
380 state->cur = 0;
381 state->handle = NULL;
382 state->higher_timestamp = NULL;
383
384 subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
385 if (!subreq) {
386 tevent_req_error(req, ENOMEM);
387 tevent_req_post(req, ev);
388 return req;
389 }
390 tevent_req_set_callback(subreq, sdap_save_users_trans, req);
391
392 return req;
393 }
394
395 static void sdap_save_users_trans(struct tevent_req *subreq)
396 {
397 struct tevent_req *req;
398 struct sdap_save_users_state *state;
399 int ret;
400
401 req = tevent_req_callback_data(subreq, struct tevent_req);
402 state = tevent_req_data(req, struct sdap_save_users_state);
403
404 ret = sysdb_transaction_recv(subreq, state, &state->handle);
405 talloc_zfree(subreq);
406 if (ret) {
407 tevent_req_error(req, ret);
408 return;
409 }
410
411 sdap_save_users_store(req);
412 }
413
414 static void sdap_save_users_store(struct tevent_req *req)
415 {
416 struct tevent_req *subreq;
417 struct sdap_save_users_state *state;
418
419 state = tevent_req_data(req, struct sdap_save_users_state);
420
421 subreq = sdap_save_user_send(state, state->ev, state->handle,
422 state->opts, state->dom,
423 state->users[state->cur], false);
424 if (!subreq) {
425 tevent_req_error(req, ENOMEM);
426 return;
427 }
428 tevent_req_set_callback(subreq, sdap_save_users_process, req);
429 }
430
431 static void sdap_save_users_process(struct tevent_req *subreq)
432 {
433 struct tevent_req *req;
434 struct sdap_save_users_state *state;
435 char *timestamp = NULL;
436 int ret;
437
438 req = tevent_req_callback_data(subreq, struct tevent_req);
439 state = tevent_req_data(req, struct sdap_save_users_state);
440
441 ret = sdap_save_user_recv(subreq, state, ×tamp);
442 talloc_zfree(subreq);
443
444 /* Do not fail completely on errors.
445 * Just report the failure to save and go on */
446 if (ret) {
447 DEBUG(2, ("Failed to store user %d. Ignoring.\n", state->cur));
448 } else {
449 DEBUG(9, ("User %d processed!\n", state->cur));
450 }
451
452 if (timestamp) {
453 if (state->higher_timestamp) {
454 if (strcmp(timestamp, state->higher_timestamp) > 0) {
455 talloc_zfree(state->higher_timestamp);
456 state->higher_timestamp = timestamp;
457 } else {
458 talloc_zfree(timestamp);
459 }
460 } else {
461 state->higher_timestamp = timestamp;
462 }
463 }
464
465 state->cur++;
466 if (state->cur < state->count) {
467 sdap_save_users_store(req);
468 } else {
469 subreq = sysdb_transaction_commit_send(state, state->ev,
470 state->handle);
471 if (!subreq) {
472 tevent_req_error(req, ENOMEM);
473 return;
474 }
475 /* sysdb_transaction_complete will call tevent_req_done(req) */
476 tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
477 }
478 }
479
480 static int sdap_save_users_recv(struct tevent_req *req,
481 TALLOC_CTX *mem_ctx, char **timestamp)
482 {
483 struct sdap_save_users_state *state = tevent_req_data(req,
484 struct sdap_save_users_state);
485
486 TEVENT_REQ_RETURN_ON_ERROR(req);
487
488 if (timestamp) {
489 *timestamp = talloc_steal(mem_ctx, state->higher_timestamp);
490 }
491
492 return EOK;
493 }
494
495
496 /* ==Search-Users-with-filter============================================= */
497
498 struct sdap_get_users_state {
499 struct tevent_context *ev;
500 struct sdap_options *opts;
501 struct sdap_handle *sh;
502 struct sss_domain_info *dom;
503 struct sysdb_ctx *sysdb;
504 const char **attrs;
505 const char *filter;
506
507 char *higher_timestamp;
508 struct sysdb_attrs **users;
509 size_t count;
510 };
511
512 static void sdap_get_users_process(struct tevent_req *subreq);
513 static void sdap_get_users_done(struct tevent_req *subreq);
514
515 struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
516 struct tevent_context *ev,
517 struct sss_domain_info *dom,
518 struct sysdb_ctx *sysdb,
519 struct sdap_options *opts,
520 struct sdap_handle *sh,
521 const char **attrs,
522 const char *filter)
523 {
524 struct tevent_req *req, *subreq;
525 struct sdap_get_users_state *state;
526
527 req = tevent_req_create(memctx, &state, struct sdap_get_users_state);
528 if (!req) return NULL;
529
530 state->ev = ev;
531 state->opts = opts;
532 state->dom = dom;
533 state->sh = sh;
534 state->sysdb = sysdb;
535 state->filter = filter;
536 state->attrs = attrs;
537 state->higher_timestamp = NULL;
538 state->users = NULL;
539 state->count = 0;
540
541 subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
542 dp_opt_get_string(state->opts->basic,
543 SDAP_USER_SEARCH_BASE),
544 LDAP_SCOPE_SUBTREE,
545 state->filter, state->attrs,
546 state->opts->user_map, SDAP_OPTS_USER);
547 if (!subreq) {
548 talloc_zfree(req);
549 return NULL;
550 }
551 tevent_req_set_callback(subreq, sdap_get_users_process, req);
552
553 return req;
554 }
555
556 static void sdap_get_users_process(struct tevent_req *subreq)
557 {
558 struct tevent_req *req = tevent_req_callback_data(subreq,
559 struct tevent_req);
560 struct sdap_get_users_state *state = tevent_req_data(req,
561 struct sdap_get_users_state);
562 int ret;
563
564 ret = sdap_get_generic_recv(subreq, state,
565 &state->count, &state->users);
566 talloc_zfree(subreq);
567 if (ret) {
568 tevent_req_error(req, ret);
569 return;
570 }
571
572 DEBUG(6, ("Search for users, returned %d results.\n", state->count));
573
574 if (state->count == 0) {
575 tevent_req_error(req, ENOENT);
576 return;
577 }
578
579 subreq = sdap_save_users_send(state, state->ev, state->dom,
580 state->sysdb, state->opts,
581 state->users, state->count);
582 if (!subreq) {
583 tevent_req_error(req, ENOMEM);
584 return;
585 }
586 tevent_req_set_callback(subreq, sdap_get_users_done, req);
587 }
588
589 static void sdap_get_users_done(struct tevent_req *subreq)
590 {
591 struct tevent_req *req = tevent_req_callback_data(subreq,
592 struct tevent_req);
593 struct sdap_get_users_state *state = tevent_req_data(req,
594 struct sdap_get_users_state);
595 int ret;
596
597 DEBUG(9, ("Saving %d Users - Done\n", state->count));
598
599 ret = sdap_save_users_recv(subreq, state, &state->higher_timestamp);
600 talloc_zfree(subreq);
601 if (ret) {
602 DEBUG(2, ("Failed to store users.\n"));
603 tevent_req_error(req, ret);
604 return;
605 }
606
607 tevent_req_done(req);
608 }
609
610 int sdap_get_users_recv(struct tevent_req *req,
611 TALLOC_CTX *mem_ctx, char **timestamp)
612 {
613 struct sdap_get_users_state *state = tevent_req_data(req,
614 struct sdap_get_users_state);
615
616 TEVENT_REQ_RETURN_ON_ERROR(req);
617
618 if (timestamp) {
619 *timestamp = talloc_steal(mem_ctx, state->higher_timestamp);
620 }
621
622 return EOK;
623 }
624
625 /* ==Group-Parsing Routines=============================================== */
626
627 struct sdap_orig_entry_state {
628 int done;
629 };
630
631 static void sdap_find_entry_by_origDN_done(struct tevent_req *req)
632 {
633 struct sdap_orig_entry_state *state = tevent_req_callback_data(req,
634 struct sdap_orig_entry_state);
635 state->done = 1;
636 }
637
638 /* WARNING: this is a sync routine for now */
639 static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx,
640 struct tevent_context *ev,
641 struct sysdb_handle *handle,
642 struct sss_domain_info *domain,
643 const char *orig_dn,
644 char **localdn)
645 {
646 struct tevent_req *req;
647 struct sdap_orig_entry_state *state;
648 static const char *attrs[] = { NULL };
649 struct ldb_dn *base_dn;
650 char *filter;
651 struct ldb_message **msgs;
652 size_t num_msgs;
653 int ret;
654
655 state = talloc_zero(memctx, struct sdap_orig_entry_state);
656 if (!state) {
657 ret = ENOMEM;
658 goto done;
659 }
660
661 filter = talloc_asprintf(state, "%s=%s", SYSDB_ORIG_DN, orig_dn);
662 if (!filter) {
663 ret = ENOMEM;
664 goto done;
665 }
666
667 base_dn = sysdb_domain_dn(sysdb_handle_get_ctx(handle),
668 state, domain->name);
669 if (!base_dn) {
670 ret = ENOMEM;
671 goto done;
672 }
673
674 req = sysdb_search_entry_send(state, ev, handle, base_dn,
675 LDB_SCOPE_SUBTREE, filter, attrs);
676 if (!req) {
677 ret = ENOMEM;
678 goto done;
679 }
680 tevent_req_set_callback(req, sdap_find_entry_by_origDN_done, state);
681
682 /* WARNING: SYNC LOOP HERE */
683 tevent_loop_allow_nesting(ev);
684 while (state->done == 0) {
685 tevent_loop_once(ev);
686 }
687
688 ret = sysdb_search_entry_recv(req, state, &num_msgs, &msgs);
689 if (ret) {
690 goto done;
691 }
692 if (num_msgs != 1) {
693 ret = ENOENT;
694 goto done;
695 }
696
697 *localdn = talloc_strdup(memctx, ldb_dn_get_linearized(msgs[0]->dn));
698 if (!*localdn) {
699 ret = ENOENT;
700 goto done;
701 }
702
703 ret = EOK;
704
705 done:
706 talloc_zfree(state);
707 return ret;
708 }
709
710 static int sdap_fill_memberships(struct sysdb_attrs *group_attrs,
711 struct tevent_context *ev,
712 struct sysdb_handle *handle,
713 struct sdap_options *opts,
714 struct sss_domain_info *domain,
715 struct ldb_val *values,
716 int num_values)
717 {
718 struct ldb_message_element *el;
719 int i, j;
720 int ret;
721
722 switch (opts->schema_type) {
723 case SDAP_SCHEMA_RFC2307:
724 DEBUG(9, ("[RFC2307 Schema]\n"));
725
726 ret = sysdb_attrs_users_from_ldb_vals(group_attrs, SYSDB_MEMBER,
727 domain->name,
728 values, num_values);
729 if (ret) {
730 goto done;
731 }
732
733 break;
734
735 case SDAP_SCHEMA_RFC2307BIS:
736 case SDAP_SCHEMA_IPA_V1:
737 case SDAP_SCHEMA_AD:
738 DEBUG(9, ("[IPA or AD Schema]\n"));
739
740 ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el);
741 if (ret) {
742 goto done;
743 }
744
745 /* Just allocate both big enough to contain all members for now */
746 el->values = talloc_realloc(el, el->values, struct ldb_val,
747 el->num_values + num_values);
748 if (!el->values) {
749 ret = ENOMEM;
750 goto done;
751 }
752
753 for (i = 0, j = el->num_values; i < num_values; i++) {
754
755 /* sync search entry with this as origDN */
756 ret = sdap_find_entry_by_origDN(el->values, ev,
757 handle, domain,
758 (char *)values[i].data,
759 (char **)&el->values[j].data);
760 if (ret != EOK) {
761 if (ret != ENOENT) {
762 goto done;
763 }
764
765 DEBUG(7, (" member #%d (%s): not found!\n",
766 i, (char *)values[i].data));
767 } else {
768 DEBUG(7, (" member #%d (%s): [%s]\n",
769 i, (char *)values[i].data,
770 (char *)el->values[j].data));
771
772 el->values[j].length = strlen((char *)el->values[j].data);
773 j++;
774 }
775 }
776 el->num_values = j;
777
778 break;
779
780 default:
781 DEBUG(0, ("FATAL ERROR: Unhandled schema type! (%d)\n",
782 opts->schema_type));
783 ret = EFAULT;
784 goto done;
785 }
786
787 ret = EOK;
788
789 done:
790 return ret;
791 }
792
793 /* ==Save-Group-Entry===================================================== */
794
795 struct sdap_save_group_state {
796 struct tevent_context *ev;
797 struct sysdb_handle *handle;
798 struct sdap_options *opts;
799
800 struct sss_domain_info *dom;
801
802 const char *name;
803 char *timestamp;
804 };
805
806 static void sdap_save_group_done(struct tevent_req *subreq);
807
808 /* FIXME: support non legacy */
809 /* FIXME: support storing additional attributes */
810
811 static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx,
812 struct tevent_context *ev,
813 struct sysdb_handle *handle,
814 struct sdap_options *opts,
815 struct sss_domain_info *dom,
816 struct sysdb_attrs *attrs,
817 bool store_members)
818 {
819 struct tevent_req *req, *subreq;
820 struct sdap_save_group_state *state;
821 struct ldb_message_element *el;
822 struct sysdb_attrs *group_attrs;
823 long int l;
824 gid_t gid;
825 int ret;
826
827 req = tevent_req_create(memctx, &state, struct sdap_save_group_state);
828 if (!req) return NULL;
829
830 state->ev = ev;
831 state->handle = handle;
832 state->dom = dom;
833 state->opts = opts;
834 state->timestamp = NULL;
835
836 ret = sysdb_attrs_get_el(attrs,
837 opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el);
838 if (ret) goto fail;
839 if (el->num_values == 0) {
840 ret = EINVAL;
841 goto fail;
842 }
843 state->name = (const char *)el->values[0].data;
844
845 ret = sysdb_attrs_get_el(attrs,
846 opts->group_map[SDAP_AT_GROUP_GID].sys_name, &el);
847 if (ret) goto fail;
848 if (el->num_values == 0) {
849 DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
850 state->name, dom->name));
851 ret = EINVAL;
852 goto fail;
853 }
854 errno = 0;
855 l = strtol((const char *)el->values[0].data, NULL, 0);
856 if (errno) {
857 ret = EINVAL;
858 goto fail;
859 }
860 gid = l;
861
862 /* check that the gid is valid for this domain */
863 if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
864 DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
865 state->name));
866 ret = EINVAL;
867 goto fail;
868 }
869
870 group_attrs = sysdb_new_attrs(state);
871 if (!group_attrs) {
872 ret = ENOMEM;
873 goto fail;
874 }
875
876 ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
877 if (ret) {
878 goto fail;
879 }
880 if (el->num_values == 0) {
881 DEBUG(7, ("Original DN is not available for [%s].\n", state->name));
882 } else {
883 DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n",
884 el->values[0].data, state->name));
885 ret = sysdb_attrs_add_string(group_attrs, SYSDB_ORIG_DN,
886 (const char *)el->values[0].data);
887 if (ret) {
888 goto fail;
889 }
890 }
891
892 ret = sysdb_attrs_get_el(attrs,
893 opts->group_map[SDAP_AT_GROUP_MODSTAMP].sys_name, &el);
894 if (ret) {
895 goto fail;
896 }
897 if (el->num_values == 0) {
898 DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n",
899 state->name));
900 } else {
901 ret = sysdb_attrs_add_string(group_attrs,
902 opts->group_map[SDAP_AT_GROUP_MODSTAMP].sys_name,
903 (const char*)el->values[0].data);
904 if (ret) {
905 goto fail;
906 }
907 state->timestamp = talloc_strdup(state,
908 (const char*)el->values[0].data);
909 if (!state->timestamp) {
910 ret = ENOMEM;
911 goto fail;
912 }
913 }
914
915 if (store_members) {
916 ret = sysdb_attrs_get_el(attrs,
917 opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
918 if (ret != EOK) {
919 goto fail;
920 }
921 if (el->num_values == 0) {
922 DEBUG(7, ("No members for group [%s]\n", state->name));
923
924 } else {
925 DEBUG(7, ("Adding member users to group [%s]\n", state->name));
926
927 ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom,
928 el->values, el->num_values);
929 if (ret) {
930 goto fail;
931 }
932 }
933 }
934
935 DEBUG(6, ("Storing info for group %s\n", state->name));
936
937 subreq = sysdb_store_group_send(state, state->ev,
938 state->handle, state->dom,
939 state->name, gid,
940 group_attrs,
941 dp_opt_get_int(opts->basic,
942 SDAP_ENTRY_CACHE_TIMEOUT));
943 if (!subreq) {
944 ret = ENOMEM;
945 goto fail;
946 }
947 tevent_req_set_callback(subreq, sdap_save_group_done, req);
948
949 return req;
950
951 fail:
952 tevent_req_error(req, ret);
953 tevent_req_post(req, ev);
954 return req;
955 }
956
957 static void sdap_save_group_done(struct tevent_req *subreq)
958 {
959 struct tevent_req *req = tevent_req_callback_data(subreq,
960 struct tevent_req);
961 struct sdap_save_group_state *state = tevent_req_data(req,
962 struct sdap_save_group_state);
963 int ret;
964
965 ret = sysdb_store_group_recv(subreq);
966 talloc_zfree(subreq);
967 if (ret) {
968 DEBUG(2, ("Failed to save group %s [%d]\n", state->name, ret));
969 tevent_req_error(req, ret);
970 return;
971 }
972
973 tevent_req_done(req);
974 }
975
976 static int sdap_save_group_recv(struct tevent_req *req,
977 TALLOC_CTX *mem_ctx, char **timestamp)
978 {
979 struct sdap_save_group_state *state = tevent_req_data(req,
980 struct sdap_save_group_state);
981
982 TEVENT_REQ_RETURN_ON_ERROR(req);
983
984 if ( timestamp ) {
985 *timestamp = talloc_steal(mem_ctx, state->timestamp);
986 }
987
988 return EOK;
989 }
990
991
992 /* ==Save-Group-Memebrs=================================================== */
993
994 struct sdap_save_grpmem_state {
995 struct tevent_context *ev;
996 struct sysdb_handle *handle;
997 struct sdap_options *opts;
998
999 struct sss_domain_info *dom;
1000
1001 const char *name;
1002 };
1003
1004 static void sdap_save_grpmem_done(struct tevent_req *subreq);
1005
1006 /* FIXME: support non legacy */
1007 /* FIXME: support storing additional attributes */
1008
1009 static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx,
1010 struct tevent_context *ev,
1011 struct sysdb_handle *handle,
1012 struct sdap_options *opts,
1013 struct sss_domain_info *dom,
1014 struct sysdb_attrs *attrs)
1015 {
1016 struct tevent_req *req, *subreq;
1017 struct sdap_save_grpmem_state *state;
1018 struct ldb_message_element *el;
1019 struct sysdb_attrs *group_attrs = NULL;
1020 int ret;
1021
1022 req = tevent_req_create(memctx, &state, struct sdap_save_grpmem_state);
1023 if (!req) return NULL;
1024
1025 state->ev = ev;
1026 state->handle = handle;
1027 state->dom = dom;
1028 state->opts = opts;
1029
1030 ret = sysdb_attrs_get_string(attrs,
1031 opts->group_map[SDAP_AT_GROUP_NAME].sys_name,
1032 &state->name);
1033 if (ret != EOK) {
1034 goto fail;
1035 }
1036
1037 ret = sysdb_attrs_get_el(attrs,
1038 opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
1039 if (ret != EOK) {
1040 goto fail;
1041 }
1042 if (el->num_values == 0) {
1043 DEBUG(7, ("No members for group [%s]\n", state->name));
1044
1045 } else {
1046 DEBUG(7, ("Adding member users to group [%s]\n", state->name));
1047
1048 group_attrs = sysdb_new_attrs(state);
1049 if (!group_attrs) {
1050 ret = ENOMEM;
1051 goto fail;
1052 }
1053
1054 ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom,
1055 el->values, el->num_values);
1056 if (ret) {
1057 goto fail;
1058 }
1059 }
1060
1061 DEBUG(6, ("Storing members for group %s\n", state->name));
1062
1063 subreq = sysdb_store_group_send(state, state->ev,
1064 state->handle, state->dom,
1065 state->name, 0,
1066 group_attrs,
1067 dp_opt_get_int(opts->basic,
1068 SDAP_ENTRY_CACHE_TIMEOUT));
1069 if (!subreq) {
1070 ret = ENOMEM;
1071 goto fail;
1072 }
1073 tevent_req_set_callback(subreq, sdap_save_grpmem_done, req);
1074
1075 return req;
1076
1077 fail:
1078 tevent_req_error(req, ret);
1079 tevent_req_post(req, ev);
1080 return req;
1081 }
1082
1083 static void sdap_save_grpmem_done(struct tevent_req *subreq)
1084 {
1085 struct tevent_req *req = tevent_req_callback_data(subreq,
1086 struct tevent_req);
1087 struct sdap_save_grpmem_state *state = tevent_req_data(req,
1088 struct sdap_save_grpmem_state);
1089 int ret;
1090
1091 ret = sysdb_store_group_recv(subreq);
1092 talloc_zfree(subreq);
1093 if (ret) {
1094 DEBUG(2, ("Failed to save group members for %s [%d]\n",
1095 state->name, ret));
1096 tevent_req_error(req, ret);
1097 return;
1098 }
1099
1100 tevent_req_done(req);
1101 }
1102
1103 static int sdap_save_grpmem_recv(struct tevent_req *req)
1104 {
1105 TEVENT_REQ_RETURN_ON_ERROR(req);
1106
1107 return EOK;
1108 }
1109
1110
1111 /* ==Generic-Function-to-save-multiple-groups============================= */
1112
1113 struct sdap_save_groups_state {
1114 struct tevent_context *ev;
1115 struct sysdb_ctx *sysdb;
1116 struct sdap_options *opts;
1117 struct sss_domain_info *dom;
1118
1119 struct sysdb_attrs **groups;
1120 int count;
1121 int cur;
1122 bool twopass;
1123
1124 struct sysdb_handle *handle;
1125
1126 char *higher_timestamp;
1127 };
1128
1129 static void sdap_save_groups_trans(struct tevent_req *subreq);
1130 static void sdap_save_groups_save(struct tevent_req *req);
1131 static void sdap_save_groups_loop(struct tevent_req *subreq);
1132 static void sdap_save_groups_mem_save(struct tevent_req *req);
1133 static void sdap_save_groups_mem_loop(struct tevent_req *subreq);
1134 struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx,
1135 struct tevent_context *ev,
1136 struct sss_domain_info *dom,
1137 struct sysdb_ctx *sysdb,
1138 struct sdap_options *opts,
1139 struct sysdb_attrs **groups,
1140 int num_groups)
1141 {
1142 struct tevent_req *req, *subreq;
1143 struct sdap_save_groups_state *state;
1144
1145 req = tevent_req_create(memctx, &state, struct sdap_save_groups_state);
1146 if (!req) return NULL;
1147
1148 state->ev = ev;
1149 state->opts = opts;
1150 state->sysdb = sysdb;
1151 state->dom = dom;
1152 state->groups = groups;
1153 state->count = num_groups;
1154 state->cur = 0;
1155 state->handle = NULL;
1156 state->higher_timestamp = NULL;
1157
1158 switch (opts->schema_type) {
1159 case SDAP_SCHEMA_RFC2307:
1160 state->twopass = false;
1161 break;
1162
1163 case SDAP_SCHEMA_RFC2307BIS:
1164 case SDAP_SCHEMA_IPA_V1:
1165 case SDAP_SCHEMA_AD:
1166 state->twopass = true;
1167 break;
1168
1169 default:
1170 tevent_req_error(req, EINVAL);
1171 tevent_req_post(req, ev);
1172 return req;
1173 }
1174
1175 subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
1176 if (!subreq) {
1177 tevent_req_error(req, ENOMEM);
1178 tevent_req_post(req, ev);
1179 return req;
1180 }
1181 tevent_req_set_callback(subreq, sdap_save_groups_trans, req);
1182
1183 return req;
1184 }
1185
1186 static void sdap_save_groups_trans(struct tevent_req *subreq)
1187 {
1188 struct tevent_req *req;
1189 struct sdap_save_groups_state *state;
1190 int ret;
1191
1192 req = tevent_req_callback_data(subreq, struct tevent_req);
1193 state = tevent_req_data(req, struct sdap_save_groups_state);
1194
1195 ret = sysdb_transaction_recv(subreq, state, &state->handle);
1196 talloc_zfree(subreq);
1197 if (ret) {
1198 tevent_req_error(req, ret);
1199 return;
1200 }
1201
1202 sdap_save_groups_save(req);
1203 }
1204
1205 static void sdap_save_groups_save(struct tevent_req *req)
1206 {
1207 struct tevent_req *subreq;
1208 struct sdap_save_groups_state *state;
1209
1210 state = tevent_req_data(req, struct sdap_save_groups_state);
1211
1212 /* if 2 pass savemembers = false */
1213 subreq = sdap_save_group_send(state, state->ev, state->handle,
1214 state->opts, state->dom,
1215 state->groups[state->cur],
1216 (!state->twopass));
1217 if (!subreq) {
1218 tevent_req_error(req, ENOMEM);
1219 return;
1220 }
1221 tevent_req_set_callback(subreq, sdap_save_groups_loop, req);
1222 }
1223
1224 static void sdap_save_groups_loop(struct tevent_req *subreq)
1225 {
1226 struct tevent_req *req;
1227 struct sdap_save_groups_state *state;
1228 char *timestamp = NULL;
1229 int ret;
1230
1231 req = tevent_req_callback_data(subreq, struct tevent_req);
1232 state = tevent_req_data(req, struct sdap_save_groups_state);
1233
1234 ret = sdap_save_group_recv(subreq, state, ×tamp);
1235 talloc_zfree(subreq);
1236
1237 /* Do not fail completely on errors.
1238 * Just report the failure to save and go on */
1239 if (ret) {
1240 DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur));
1241 } else {
1242 DEBUG(9, ("Group %d processed!\n", state->cur));
1243 }
1244
1245 if (timestamp) {
1246 if (state->higher_timestamp) {
1247 if (strcmp(timestamp, state->higher_timestamp) > 0) {
1248 talloc_zfree(state->higher_timestamp);
1249 state->higher_timestamp = timestamp;
1250 } else {
1251 talloc_zfree(timestamp);
1252 }
1253 } else {
1254 state->higher_timestamp = timestamp;
1255 }
1256 }
1257
1258 state->cur++;
1259 if (state->cur < state->count) {
1260
1261 sdap_save_groups_save(req);
1262
1263 } else if (state->twopass) {
1264
1265 state->cur = 0;
1266 sdap_save_groups_mem_save(req);
1267
1268 } else {
1269
1270 subreq = sysdb_transaction_commit_send(state, state->ev,
1271 state->handle);
1272 if (!subreq) {
1273 tevent_req_error(req, ENOMEM);
1274 return;
1275 }
1276 /* sysdb_transaction_complete will call tevent_req_done(req) */
1277 tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
1278 }
1279 }
1280
1281 static void sdap_save_groups_mem_save(struct tevent_req *req)
1282 {
1283 struct tevent_req *subreq;
1284 struct sdap_save_groups_state *state;
1285
1286 state = tevent_req_data(req, struct sdap_save_groups_state);
1287
1288 subreq = sdap_save_grpmem_send(state, state->ev, state->handle,
1289 state->opts, state->dom,
1290 state->groups[state->cur]);
1291 if (!subreq) {
1292 tevent_req_error(req, ENOMEM);
1293 return;
1294 }
1295 tevent_req_set_callback(subreq, sdap_save_groups_mem_loop, req);
1296 }
1297
1298 static void sdap_save_groups_mem_loop(struct tevent_req *subreq)
1299 {
1300 struct tevent_req *req;
1301 struct sdap_save_groups_state *state;
1302 int ret;
1303
1304 req = tevent_req_callback_data(subreq, struct tevent_req);
1305 state = tevent_req_data(req, struct sdap_save_groups_state);
1306
1307 ret = sdap_save_grpmem_recv(subreq);
1308 talloc_zfree(subreq);
1309
1310 /* Do not fail completely on errors.
1311 * Just report the failure to save and go on */
1312 if (ret) {
1313 DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur));
1314 }
1315
1316 state->cur++;
1317 if (state->cur < state->count) {
1318
1319 sdap_save_groups_mem_save(req);
1320
1321 } else {
1322
1323 subreq = sysdb_transaction_commit_send(state, state->ev,
1324 state->handle);
1325 if (!subreq) {
1326 tevent_req_error(req, ENOMEM);
1327 return;
1328 }
1329 /* sysdb_transaction_complete will call tevent_req_done(req) */
1330 tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
1331 }
1332 }
1333
1334 static int sdap_save_groups_recv(struct tevent_req *req,
1335 TALLOC_CTX *mem_ctx, char **timestamp)
1336 {
1337 struct sdap_save_groups_state *state = tevent_req_data(req,
1338 struct sdap_save_groups_state);
1339
1340 TEVENT_REQ_RETURN_ON_ERROR(req);
1341
1342 if (timestamp) {
1343 *timestamp = talloc_steal(mem_ctx, state->higher_timestamp);
1344 }
1345
1346 return EOK;
1347 }
1348
1349
1350 /* ==Search-Groups-with-filter============================================ */
1351
1352 struct sdap_get_groups_state {
1353 struct tevent_context *ev;
1354 struct sdap_options *opts;
1355 struct sdap_handle *sh;
1356 struct sss_domain_info *dom;
1357 struct sysdb_ctx *sysdb;
1358 const char **attrs;
1359 const char *filter;
1360
1361 char *higher_timestamp;
1362 struct sysdb_attrs **groups;
1363 size_t count;
1364 };
1365
1366 static void sdap_get_groups_process(struct tevent_req *subreq);
1367 static void sdap_get_groups_done(struct tevent_req *subreq);
1368
1369 struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
1370 struct tevent_context *ev,
1371 struct sss_domain_info *dom,
1372 struct sysdb_ctx *sysdb,
1373 struct sdap_options *opts,
1374 struct sdap_handle *sh,
1375 const char **attrs,
1376 const char *filter)
1377 {
1378 struct tevent_req *req, *subreq;
1379 struct sdap_get_groups_state *state;
1380
1381 req = tevent_req_create(memctx, &state, struct sdap_get_groups_state);
1382 if (!req) return NULL;
1383
1384 state->ev = ev;
1385 state->opts = opts;
1386 state->dom = dom;
1387 state->sh = sh;
1388 state->sysdb = sysdb;
1389 state->filter = filter;
1390 state->attrs = attrs;
1391 state->higher_timestamp = NULL;
1392 state->groups = NULL;
1393 state->count = 0;
1394
1395 subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
1396 dp_opt_get_string(state->opts->basic,
1397 SDAP_GROUP_SEARCH_BASE),
1398 LDAP_SCOPE_SUBTREE,
1399 state->filter, state->attrs,
1400 state->opts->group_map, SDAP_OPTS_GROUP);
1401 if (!subreq) {
1402 talloc_zfree(req);
1403 return NULL;
1404 }
1405 tevent_req_set_callback(subreq, sdap_get_groups_process, req);
1406
1407 return req;
1408 }
1409
1410 static void sdap_get_groups_process(struct tevent_req *subreq)
1411 {
1412 struct tevent_req *req = tevent_req_callback_data(subreq,
1413 struct tevent_req);
1414 struct sdap_get_groups_state *state = tevent_req_data(req,
1415 struct sdap_get_groups_state);
1416 int ret;
1417
1418 ret = sdap_get_generic_recv(subreq, state,
1419 &state->count, &state->groups);
1420 talloc_zfree(subreq);
1421 if (ret) {
1422 tevent_req_error(req, ret);
1423 return;
1424 }
1425
1426 DEBUG(6, ("Search for groups, returned %d results.\n", state->count));
1427
1428 if (state->count == 0) {
1429 tevent_req_error(req, ENOENT);
1430 return;
1431 }
1432
1433 subreq = sdap_save_groups_send(state, state->ev, state->dom,
1434 state->sysdb, state->opts,
1435 state->groups, state->count);
1436 if (!subreq) {
1437 tevent_req_error(req, ENOMEM);
1438 return;
1439 }
1440 tevent_req_set_callback(subreq, sdap_get_groups_done, req);
1441 }
1442
1443 static void sdap_get_groups_done(struct tevent_req *subreq)
1444 {
1445 struct tevent_req *req = tevent_req_callback_data(subreq,
1446 struct tevent_req);
1447 struct sdap_get_groups_state *state = tevent_req_data(req,
1448 struct sdap_get_groups_state);
1449 int ret;
1450
1451 DEBUG(9, ("Saving %d Groups - Done\n", state->count));
1452
1453 ret = sdap_save_groups_recv(subreq, state, &state->higher_timestamp);
1454 talloc_zfree(subreq);
1455 if (ret) {
1456 DEBUG(2, ("Failed to store groups.\n"));
1457 tevent_req_error(req, ret);
1458 return;
1459 }
1460
1461 tevent_req_done(req);
1462 }
1463
1464 int sdap_get_groups_recv(struct tevent_req *req,
1465 TALLOC_CTX *mem_ctx, char **timestamp)
1466 {
1467 struct sdap_get_groups_state *state = tevent_req_data(req,
1468 struct sdap_get_groups_state);
1469
1470 TEVENT_REQ_RETURN_ON_ERROR(req);
1471
1472 if (timestamp) {
1473 *timestamp = talloc_steal(mem_ctx, state->higher_timestamp);
1474 }
1475
1476 return EOK;
1477 }
1478
1479
1480 /* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */
1481
1482 struct sdap_initgr_rfc2307_state {
1483 struct tevent_context *ev;
1484 struct sysdb_ctx *sysdb;
1485 struct sdap_options *opts;
1486 struct sss_domain_info *dom;
1487 struct sdap_handle *sh;
1488
1489 struct sdap_op *op;
1490 };
1491
1492 static void sdap_initgr_rfc2307_process(struct tevent_req *subreq);
1493 static void sdap_initgr_rfc2307_done(struct tevent_req *subreq);
1494 struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
1495 struct tevent_context *ev,
1496 struct sdap_options *opts,
1497 struct sysdb_ctx *sysdb,
1498 struct sss_domain_info *dom,
1499 struct sdap_handle *sh,
1500 const char *base_dn,
1501 const char *name,
1502 const char **grp_attrs)
1503 {
1504 struct tevent_req *req, *subreq;
1505 struct sdap_initgr_rfc2307_state *state;
1506 const char *filter;
1507
1508 req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state);
1509 if (!req) return NULL;
1510
1511 state->ev = ev;
1512 state->opts = opts;
1513 state->sysdb = sysdb;
1514 state->dom = dom;
1515 state->sh = sh;
1516 state->op = NULL;
1517
1518 filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
1519 opts->group_map[SDAP_AT_GROUP_MEMBER].name,
1520 name, opts->group_map[SDAP_OC_GROUP].name);
1521 if (!filter) {
1522 talloc_zfree(req);
1523 return NULL;
1524 }
1525
1526 subreq = sdap_get_generic_send(state, state->ev, state->opts,
1527 state->sh, base_dn, LDAP_SCOPE_SUBTREE,
1528 filter, grp_attrs,
1529 state->opts->group_map, SDAP_OPTS_GROUP);
1530 if (!subreq) {
1531 talloc_zfree(req);
1532 return NULL;
1533 }
1534 tevent_req_set_callback(subreq, sdap_initgr_rfc2307_process, req);
1535
1536 return req;
1537 }
1538
1539 static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
1540 {
1541 struct tevent_req *req;
1542 struct sdap_initgr_rfc2307_state *state;
1543 struct sysdb_attrs **groups;
1544 size_t count;
1545 int ret;
1546
1547 req = tevent_req_callback_data(subreq, struct tevent_req);
1548 state = tevent_req_data(req, struct sdap_initgr_rfc2307_state);
1549
1550 ret = sdap_get_generic_recv(subreq, state, &count, &groups);
1551 talloc_zfree(subreq);
1552 if (ret) {
1553 tevent_req_error(req, ret);
1554 return;
1555 }
1556
1557 if (count == 0) {
1558 tevent_req_done(req);
1559 return;
1560 }
1561
1562 subreq = sdap_save_groups_send(state, state->ev, state->dom,
1563 state->sysdb, state->opts,
1564 groups, count);
1565 if (!subreq) {
1566 tevent_req_error(req, ENOMEM);
1567 return;
1568 }
1569 tevent_req_set_callback(subreq, sdap_initgr_rfc2307_done, req);
1570 }
1571
1572 static void sdap_initgr_rfc2307_done(struct tevent_req *subreq)
1573 {
1574 struct tevent_req *req;
1575 int ret;
1576
1577 req = tevent_req_callback_data(subreq, struct tevent_req);
1578
1579 ret = sdap_save_groups_recv(subreq, NULL, NULL);
1580 talloc_zfree(subreq);
1581 if (ret) {
1582 tevent_req_error(req, ret);
1583 return;
1584 }
1585
1586 tevent_req_done(req);
1587 }
1588
1589 static int sdap_initgr_rfc2307_recv(struct tevent_req *req)
1590 {
1591 TEVENT_REQ_RETURN_ON_ERROR(req);
1592
1593 return EOK;
1594 }
1595
1596
1597 /* ==Initgr-call-(groups-a-user-is-member-of)-nested-groups=============== */
1598
1599 struct sdap_initgr_nested_state {
1600 struct tevent_context *ev;
1601 struct sysdb_ctx *sysdb;
1602 struct sdap_options *opts;
1603 struct sss_domain_info *dom;
1604 struct sdap_handle *sh;
1605
1606 const char **grp_attrs;
1607
1608 char *filter;
1609 char **group_dns;
1610 int count;
1611 int cur;
1612
1613 struct sdap_op *op;
1614
1615 struct sysdb_attrs **groups;
1616 int groups_cur;
1617 };
1618
1619 static void sdap_initgr_nested_search(struct tevent_req *subreq);
1620 static void sdap_initgr_nested_store(struct tevent_req *req);
1621 static void sdap_initgr_nested_done(struct tevent_req *subreq);
1622 static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx,
1623 struct tevent_context *ev,
1624 struct sdap_options *opts,
1625 struct sysdb_ctx *sysdb,
1626 struct sss_domain_info *dom,
1627 struct sdap_handle *sh,
1628 struct sysdb_attrs *user,
1629 const char **grp_attrs)
1630 {
1631 struct tevent_req *req, *subreq;
1632 struct sdap_initgr_nested_state *state;
1633 struct ldb_message_element *el;
1634 int i, ret;
1635
1636 req = tevent_req_create(memctx, &state, struct sdap_initgr_nested_state);
1637 if (!req) return NULL;
1638
1639 state->ev = ev;
1640 state->opts = opts;
1641 state->sysdb = sysdb;
1642 state->dom = dom;
1643 state->sh = sh;
1644 state->grp_attrs = grp_attrs;
1645 state->op = NULL;
1646
1647 state->filter = talloc_asprintf(state, "(objectclass=%s)",
1648 opts->group_map[SDAP_OC_GROUP].name);
1649 if (!state->filter) {
1650 talloc_zfree(req);
1651 return NULL;
1652 }
1653
1654 /* TODO: test rootDSE for deref support and use it if available */
1655 /* TODO: or test rootDSE for ASQ support and use it if available */
1656
1657 ret = sysdb_attrs_get_el(user, SYSDB_MEMBEROF, &el);
Event var_compare_op: Comparing "el" to null implies that "el" might be null.
Also see events: [var_deref_op]At conditional (1): "!el": Taking true branch.
| | |
1658 if (ret || !el || el->num_values == 0) {
At conditional (2): "4 <= debug_level": Taking true branch.
At conditional (3): "debug_timestamps": Taking true branch.
| |
1659 DEBUG(4, ("User entry lacks original memberof ?\n"));
1660 /* user with no groups ? */
1661 tevent_req_error(req, ENOENT);
1662 tevent_req_post(req, ev);
1663 }
Event var_deref_op: Dereferencing null variable "el".
Also see events: [var_compare_op] | |
1664 state->count = el->num_values;
1665
1666 state->groups = talloc_zero_array(state, struct sysdb_attrs *,
1667 state->count + 1);;
1668 if (!state->groups) {
1669 talloc_zfree(req);
1670 return NULL;
1671 }
1672 state->groups_cur = 0;
1673
1674 state->group_dns = talloc_array(state, char *, state->count + 1);
1675 if (!state->group_dns) {
1676 talloc_zfree(req);
1677 return NULL;
1678 }
1679 for (i = 0; i < state->count; i++) {
1680 state->group_dns[i] = talloc_strdup(state->group_dns,
1681 (char *)el->values[i].data);
1682 if (!state->group_dns[i]) {
1683 talloc_zfree(req);
1684 return NULL;
1685 }
1686 }
1687 state->group_dns[i] = NULL; /* terminate */
1688 state->cur = 0;
1689
1690 subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
1691 state->group_dns[state->cur],
1692 LDAP_SCOPE_BASE,
1693 state->filter, state->grp_attrs,
1694 state->opts->group_map, SDAP_OPTS_GROUP);
1695 if (!subreq) {
1696 talloc_zfree(req);
1697 return NULL;
1698 }
1699 tevent_req_set_callback(subreq, sdap_initgr_nested_search, req);
1700
1701 return req;
1702 }
1703
1704 static void sdap_initgr_nested_search(struct tevent_req *subreq)
1705 {
1706 struct tevent_req *req;
1707 struct sdap_initgr_nested_state *state;
1708 struct sysdb_attrs **groups;
1709 size_t count;
1710 int ret;
1711
1712 req = tevent_req_callback_data(subreq, struct tevent_req);
1713 state = tevent_req_data(req, struct sdap_initgr_nested_state);
1714
1715 ret = sdap_get_generic_recv(subreq, state, &count, &groups);
1716 talloc_zfree(subreq);
1717 if (ret) {
1718 tevent_req_error(req, ret);
1719 return;
1720 }
1721
1722 if (count == 1) {
1723 state->groups[state->groups_cur] = groups[0];
1724 state->groups_cur++;
1725 } else {
1726 DEBUG(2, ("Search for group %s, returned %d results. Skipping\n",
1727 state->group_dns[state->cur], count));
1728 }
1729
1730 state->cur++;
1731 if (state->cur < state->count) {
1732 subreq = sdap_get_generic_send(state, state->ev,
1733 state->opts, state->sh,
1734 state->group_dns[state->cur],
1735 LDAP_SCOPE_BASE,
1736 state->filter, state->grp_attrs,
1737 state->opts->group_map,
1738 SDAP_OPTS_GROUP);
1739 if (!subreq) {
1740 tevent_req_error(req, ENOMEM);
1741 return;
1742 }
1743 tevent_req_set_callback(subreq, sdap_initgr_nested_search, req);
1744 } else {
1745 sdap_initgr_nested_store(req);
1746 }
1747 }
1748
1749 static void sdap_initgr_nested_store(struct tevent_req *req)
1750 {
1751 struct tevent_req *subreq;
1752 struct sdap_initgr_nested_state *state;
1753
1754 state = tevent_req_data(req, struct sdap_initgr_nested_state);
1755
1756 subreq = sdap_save_groups_send(state, state->ev, state->dom,
1757 state->sysdb, state->opts,
1758 state->groups, state->groups_cur);
1759 if (!subreq) {
1760 tevent_req_error(req, ENOMEM);
1761 return;
1762 }
1763 tevent_req_set_callback(subreq, sdap_initgr_nested_done, req);
1764 }
1765
1766 static void sdap_initgr_nested_done(struct tevent_req *subreq)
1767 {
1768 struct tevent_req *req;
1769 int ret;
1770
1771 req = tevent_req_callback_data(subreq, struct tevent_req);
1772
1773 ret = sdap_save_groups_recv(subreq, NULL, NULL);
1774 talloc_zfree(subreq);
1775 if (ret) {
1776 tevent_req_error(req, ret);
1777 return;
1778 }
1779
1780 tevent_req_done(req);
1781 }
1782
1783 static int sdap_initgr_nested_recv(struct tevent_req *req)
1784 {
1785 TEVENT_REQ_RETURN_ON_ERROR(req);
1786
1787 return EOK;
1788 }
1789
1790
1791 /* ==Initgr-call-(groups-a-user-is-member-of)============================= */
1792
1793 struct sdap_get_initgr_state {
1794 struct tevent_context *ev;
1795 struct sysdb_ctx *sysdb;
1796 struct sdap_options *opts;
1797 struct sss_domain_info *dom;
1798 struct sdap_handle *sh;
1799 const char *name;
1800 const char **grp_attrs;
1801
1802 struct sysdb_attrs *orig_user;
1803
1804 struct sysdb_handle *handle;
1805 };
1806
1807 static void sdap_get_initgr_user(struct tevent_req *subreq);
1808 static void sdap_get_initgr_store(struct tevent_req *subreq);
1809 static void sdap_get_initgr_commit(struct tevent_req *subreq);
1810 static void sdap_get_initgr_process(struct tevent_req *subreq);
1811 static void sdap_get_initgr_done(struct tevent_req *subreq);
1812
1813 struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
1814 struct tevent_context *ev,
1815 struct sss_domain_info *dom,
1816 struct sysdb_ctx *sysdb,
1817 struct sdap_options *opts,
1818 struct sdap_handle *sh,
1819 const char *name,
1820 const char **grp_attrs)
1821 {
1822 struct tevent_req *req, *subreq;
1823 struct sdap_get_initgr_state *state;
1824 const char *base_dn;
1825 char *filter;
1826 const char **attrs;
1827 int ret;
1828
1829 DEBUG(9, ("Retrieving info for initgroups call\n"));
1830
1831 req = tevent_req_create(memctx, &state, struct sdap_get_initgr_state);
1832 if (!req) return NULL;
1833
1834 state->ev = ev;
1835 state->opts = opts;
1836 state->sysdb = sysdb;
1837 state->dom = dom;
1838 state->sh = sh;
1839 state->name = name;
1840 state->grp_attrs = grp_attrs;
1841 state->orig_user = NULL;
1842
1843 filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
1844 state->opts->user_map[SDAP_AT_USER_NAME].name,
1845 state->name,
1846 state->opts->user_map[SDAP_OC_USER].name);
1847 if (!filter) {
1848 talloc_zfree(req);
1849 return NULL;
1850 }
1851
1852 base_dn = dp_opt_get_string(state->opts->basic,
1853 SDAP_USER_SEARCH_BASE);
1854 if (!base_dn) {
1855 talloc_zfree(req);
1856 return NULL;
1857 }
1858
1859 ret = build_attrs_from_map(state, state->opts->user_map,
1860 SDAP_OPTS_USER, &attrs);
1861 if (ret) {
1862 talloc_zfree(req);
1863 return NULL;
1864 }
1865
1866 subreq = sdap_get_generic_send(state, state->ev,
1867 state->opts, state->sh,
1868 base_dn, LDAP_SCOPE_SUBTREE,
1869 filter, attrs,
1870 state->opts->user_map, SDAP_OPTS_USER);
1871 if (!subreq) {
1872 talloc_zfree(req);
1873 return NULL;
1874 }
1875 tevent_req_set_callback(subreq, sdap_get_initgr_user, req);
1876
1877 return req;
1878 }
1879
1880 static void sdap_get_initgr_user(struct tevent_req *subreq)
1881 {
1882 struct tevent_req *req = tevent_req_callback_data(subreq,
1883 struct tevent_req);
1884 struct sdap_get_initgr_state *state = tevent_req_data(req,
1885 struct sdap_get_initgr_state);
1886 struct sysdb_attrs **usr_attrs;
1887 size_t count;
1888 int ret;
1889
1890 DEBUG(9, ("Receiving info for the user\n"));
1891
1892 ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs);
1893 talloc_zfree(subreq);
1894 if (ret) {
1895 tevent_req_error(req, ret);
1896 return;
1897 }
1898
1899 if (count != 1) {
1900 DEBUG(2, ("Expected one user entry and got %d\n", count));
1901 tevent_req_error(req, ENOENT);
1902 return;
1903 }
1904
1905 state->orig_user = usr_attrs[0];
1906
1907 subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
1908 if (!subreq) {
1909 tevent_req_error(req, ENOMEM);
1910 return;
1911 }
1912 tevent_req_set_callback(subreq, sdap_get_initgr_store, req);
1913 }
1914
1915 static void sdap_get_initgr_store(struct tevent_req *subreq)
1916 {
1917 struct tevent_req *req = tevent_req_callback_data(subreq,
1918 struct tevent_req);
1919 struct sdap_get_initgr_state *state = tevent_req_data(req,
1920 struct sdap_get_initgr_state);
1921 int ret;
1922
1923 DEBUG(9, ("Storing the user\n"));
1924
1925 ret = sysdb_transaction_recv(subreq, state, &state->handle);
1926 talloc_zfree(subreq);
1927 if (ret) {
1928 tevent_req_error(req, ret);
1929 return;
1930 }
1931
1932 subreq = sdap_save_user_send(state, state->ev, state->handle,
1933 state->opts, state->dom,
1934 state->orig_user, true);
1935 if (!subreq) {
1936 tevent_req_error(req, ENOMEM);
1937 return;
1938 }
1939 tevent_req_set_callback(subreq, sdap_get_initgr_commit, req);
1940 }
1941
1942 static void sdap_get_initgr_commit(struct tevent_req *subreq)
1943 {
1944 struct tevent_req *req = tevent_req_callback_data(subreq,
1945 struct tevent_req);
1946 struct sdap_get_initgr_state *state = tevent_req_data(req,
1947 struct sdap_get_initgr_state);
1948 int ret;
1949
1950 DEBUG(9, ("Commit change\n"));
1951
1952 ret = sdap_save_user_recv(subreq, NULL, NULL);
1953 talloc_zfree(subreq);
1954 if (ret) {
1955 tevent_req_error(req, ret);
1956 return;
1957 }
1958
1959 subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
1960 if (!subreq) {
1961 tevent_req_error(req, ENOMEM);
1962 return;
1963 }
1964 tevent_req_set_callback(subreq, sdap_get_initgr_process, req);
1965 }
1966
1967 static void sdap_get_initgr_process(struct tevent_req *subreq)
1968 {
1969 struct tevent_req *req = tevent_req_callback_data(subreq,
1970 struct tevent_req);
1971 struct sdap_get_initgr_state *state = tevent_req_data(req,
1972 struct sdap_get_initgr_state);
1973 int ret;
1974
1975 DEBUG(9, ("Process user's groups\n"));
1976
1977 ret = sysdb_transaction_commit_recv(subreq);
1978 talloc_zfree(subreq);
1979 if (ret) {
1980 tevent_req_error(req, ret);
1981 return;
1982 }
1983
1984 switch (state->opts->schema_type) {
1985 case SDAP_SCHEMA_RFC2307:
1986 subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
1987 state->sysdb, state->dom, state->sh,
1988 dp_opt_get_string(state->opts->basic,
1989 SDAP_GROUP_SEARCH_BASE),
1990 state->name, state->grp_attrs);
1991 if (!subreq) {
1992 tevent_req_error(req, ENOMEM);
1993 return;
1994 }
1995 tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
1996 break;
1997
1998 case SDAP_SCHEMA_RFC2307BIS:
1999 case SDAP_SCHEMA_IPA_V1:
2000 case SDAP_SCHEMA_AD:
2001 /* TODO: AD uses a different member/memberof schema
2002 * We need an AD specific call that is able to unroll
2003 * nested groups by doing extensive recursive searches */
2004
2005 subreq = sdap_initgr_nested_send(state, state->ev, state->opts,
2006 state->sysdb, state->dom, state->sh,
2007 state->orig_user, state->grp_attrs);
2008 if (!subreq) {
2009 tevent_req_error(req, ENOMEM);
2010 return;
2011 }
2012 tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
2013 return;
2014
2015 default:
2016 tevent_req_error(req, EINVAL);
2017 return;
2018 }
2019 }
2020
2021 static void sdap_get_initgr_done(struct tevent_req *subreq)
2022 {
2023 struct tevent_req *req = tevent_req_callback_data(subreq,
2024 struct tevent_req);
2025 struct sdap_get_initgr_state *state = tevent_req_data(req,
2026 struct sdap_get_initgr_state);
2027 int ret;
2028
2029 DEBUG(9, ("Initgroups done\n"));
2030
2031 switch (state->opts->schema_type) {
2032 case SDAP_SCHEMA_RFC2307:
2033
2034 ret = sdap_initgr_rfc2307_recv(subreq);
2035 break;
2036
2037 case SDAP_SCHEMA_RFC2307BIS:
2038 case SDAP_SCHEMA_IPA_V1:
2039 case SDAP_SCHEMA_AD:
2040
2041 ret = sdap_initgr_nested_recv(subreq);
2042 break;
2043
2044 default:
2045
2046 ret = EINVAL;
2047 break;
2048 }
2049
2050 talloc_zfree(subreq);
2051 if (ret) {
2052 tevent_req_error(req, ret);
2053 return;
2054 }
2055
2056 tevent_req_done(req);
2057 }
2058
2059 int sdap_get_initgr_recv(struct tevent_req *req)
2060 {
2061 TEVENT_REQ_RETURN_ON_ERROR(req);
2062
2063 return EOK;
2064 }
2065