Line data Source code
1 : /*
2 : SSSD
3 :
4 : IPA Identity Backend Module
5 :
6 : Authors:
7 : Jan Zeleny <jzeleny@redhat.com>
8 :
9 : Copyright (C) 2011 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 :
27 : #include "util/util.h"
28 : #include "db/sysdb.h"
29 : #include "providers/ldap/ldap_common.h"
30 : #include "providers/ldap/sdap_async.h"
31 : #include "providers/ipa/ipa_id.h"
32 :
33 : static struct tevent_req *
34 : ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
35 : struct ipa_id_ctx *ipa_ctx,
36 : struct be_acct_req *ar);
37 :
38 : static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error);
39 :
40 0 : static bool is_object_overridable(struct be_acct_req *ar)
41 : {
42 0 : bool ret = false;
43 :
44 0 : switch (ar->entry_type & BE_REQ_TYPE_MASK) {
45 : case BE_REQ_USER:
46 : case BE_REQ_GROUP:
47 : case BE_REQ_INITGROUPS:
48 : case BE_REQ_BY_SECID:
49 : case BE_REQ_USER_AND_GROUP:
50 : case BE_REQ_BY_UUID:
51 : case BE_REQ_BY_CERT:
52 0 : ret = true;
53 0 : break;
54 : default:
55 0 : break;
56 : }
57 :
58 0 : return ret;
59 : }
60 :
61 : struct ipa_resolve_user_list_state {
62 : struct tevent_context *ev;
63 : struct ipa_id_ctx *ipa_ctx;
64 : struct ldb_message_element *users;
65 : const char *domain_name;
66 : size_t user_idx;
67 :
68 : int dp_error;
69 : };
70 :
71 : static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req);
72 : static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq);
73 :
74 : static struct tevent_req *
75 0 : ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
76 : struct ipa_id_ctx *ipa_ctx,
77 : const char *domain_name,
78 : struct ldb_message_element *users)
79 : {
80 : int ret;
81 : struct tevent_req *req;
82 : struct ipa_resolve_user_list_state *state;
83 :
84 0 : req = tevent_req_create(memctx, &state,
85 : struct ipa_resolve_user_list_state);
86 0 : if (req == NULL) {
87 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
88 0 : return NULL;
89 : }
90 :
91 0 : state->ev = ev;
92 0 : state->ipa_ctx = ipa_ctx;
93 0 : state->domain_name = domain_name;
94 0 : state->users = users;
95 0 : state->user_idx = 0;
96 0 : state->dp_error = DP_ERR_FATAL;
97 :
98 0 : ret = ipa_resolve_user_list_get_user_step(req);
99 0 : if (ret == EAGAIN) {
100 0 : return req;
101 0 : } else if (ret == EOK) {
102 0 : state->dp_error = DP_ERR_OK;
103 0 : tevent_req_done(req);
104 : } else {
105 0 : DEBUG(SSSDBG_OP_FAILURE,
106 : "ipa_resolve_user_list_get_user_step failed.\n");
107 0 : tevent_req_error(req, ret);
108 : }
109 0 : tevent_req_post(req, ev);
110 0 : return req;
111 : }
112 :
113 0 : static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req)
114 : {
115 : int ret;
116 : struct tevent_req *subreq;
117 : struct be_acct_req *ar;
118 0 : struct ipa_resolve_user_list_state *state = tevent_req_data(req,
119 : struct ipa_resolve_user_list_state);
120 :
121 0 : if (state->user_idx >= state->users->num_values) {
122 0 : return EOK;
123 : }
124 :
125 0 : ret = get_be_acct_req_for_user_name(state,
126 0 : (char *) state->users->values[state->user_idx].data,
127 : state->domain_name, &ar);
128 0 : if (ret != EOK) {
129 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_user_name failed.\n");
130 0 : return ret;
131 : }
132 :
133 0 : DEBUG(SSSDBG_TRACE_ALL, "Trying to resolve user [%s].\n", ar->filter_value);
134 :
135 0 : subreq = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx, ar);
136 0 : if (subreq == NULL) {
137 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
138 0 : return ENOMEM;
139 : }
140 :
141 0 : tevent_req_set_callback(subreq, ipa_resolve_user_list_get_user_done, req);
142 :
143 0 : return EAGAIN;
144 : }
145 :
146 0 : static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq)
147 : {
148 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
149 : struct tevent_req);
150 0 : struct ipa_resolve_user_list_state *state = tevent_req_data(req,
151 : struct ipa_resolve_user_list_state);
152 : int ret;
153 :
154 0 : ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
155 0 : talloc_zfree(subreq);
156 0 : if (ret != EOK) {
157 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
158 0 : goto done;
159 : }
160 :
161 0 : state->user_idx++;
162 :
163 0 : ret = ipa_resolve_user_list_get_user_step(req);
164 0 : if (ret == EAGAIN) {
165 0 : return;
166 : }
167 0 : if (ret != EOK) {
168 0 : DEBUG(SSSDBG_OP_FAILURE,
169 : "ipa_resolve_user_list_get_user_step failed.\n");
170 : }
171 :
172 : done:
173 0 : if (ret == EOK) {
174 0 : state->dp_error = DP_ERR_OK;
175 0 : tevent_req_done(req);
176 : } else {
177 0 : if (state->dp_error == DP_ERR_OK) {
178 0 : state->dp_error = DP_ERR_FATAL;
179 : }
180 0 : tevent_req_error(req, ret);
181 : }
182 0 : return;
183 : }
184 :
185 0 : static int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
186 : {
187 0 : struct ipa_resolve_user_list_state *state = tevent_req_data(req,
188 : struct ipa_resolve_user_list_state);
189 :
190 0 : if (dp_error) {
191 0 : *dp_error = state->dp_error;
192 : }
193 :
194 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
195 :
196 0 : return EOK;
197 : }
198 :
199 : struct ipa_initgr_get_overrides_state {
200 : struct tevent_context *ev;
201 : struct ipa_id_ctx *ipa_ctx;
202 : struct sss_domain_info *user_dom;
203 : const char *realm;
204 :
205 : struct ldb_message **groups;
206 : size_t group_count;
207 : const char *groups_id_attr;
208 : size_t group_idx;
209 : struct be_acct_req *ar;
210 :
211 : int dp_error;
212 : };
213 :
214 : static int ipa_initgr_get_overrides_step(struct tevent_req *req);
215 :
216 : struct tevent_req *
217 0 : ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
218 : struct tevent_context *ev,
219 : struct ipa_id_ctx *ipa_ctx,
220 : struct sss_domain_info *user_dom,
221 : size_t groups_count,
222 : struct ldb_message **groups,
223 : const char *groups_id_attr)
224 : {
225 : int ret;
226 : struct tevent_req *req;
227 : struct ipa_initgr_get_overrides_state *state;
228 :
229 0 : req = tevent_req_create(memctx, &state,
230 : struct ipa_initgr_get_overrides_state);
231 0 : if (req == NULL) {
232 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
233 0 : return NULL;
234 : }
235 0 : state->ev = ev;
236 0 : state->ipa_ctx = ipa_ctx;
237 0 : state->user_dom = user_dom;
238 0 : state->groups = groups;
239 0 : state->group_count = groups_count;
240 0 : state->group_idx = 0;
241 0 : state->ar = NULL;
242 0 : state->realm = dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
243 : IPA_KRB5_REALM);
244 0 : if (state->realm == NULL) {
245 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
246 0 : ret = EINVAL;
247 0 : goto done;
248 : }
249 0 : state->groups_id_attr = talloc_strdup(state, groups_id_attr);
250 0 : if (state->groups_id_attr == NULL) {
251 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
252 0 : ret = ENOMEM;
253 0 : goto done;
254 : }
255 :
256 0 : ret = ipa_initgr_get_overrides_step(req);
257 : done:
258 0 : if (ret == EOK) {
259 0 : tevent_req_done(req);
260 0 : tevent_req_post(req, ev);
261 0 : } else if (ret != EAGAIN) {
262 0 : tevent_req_error(req, ret);
263 0 : tevent_req_post(req, ev);
264 : }
265 :
266 0 : return req;
267 : }
268 :
269 : static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq);
270 :
271 0 : static int ipa_initgr_get_overrides_step(struct tevent_req *req)
272 : {
273 : int ret;
274 : struct tevent_req *subreq;
275 : const char *ipa_uuid;
276 0 : struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
277 : struct ipa_initgr_get_overrides_state);
278 :
279 0 : DEBUG(SSSDBG_TRACE_LIBS,
280 : "Processing group %zu/%zu\n", state->group_idx, state->group_count);
281 :
282 0 : if (state->group_idx >= state->group_count) {
283 0 : return EOK;
284 : }
285 :
286 0 : ipa_uuid = ldb_msg_find_attr_as_string(state->groups[state->group_idx],
287 : state->groups_id_attr, NULL);
288 0 : if (ipa_uuid == NULL) {
289 : /* This should never happen, the search filter used to get the list
290 : * of groups includes "uuid=*"
291 : */
292 0 : DEBUG(SSSDBG_OP_FAILURE,
293 : "The group %s has no UUID attribute %s, error!\n",
294 : ldb_dn_get_linearized(state->groups[state->group_idx]->dn),
295 : state->groups_id_attr);
296 0 : return EINVAL;
297 : }
298 :
299 0 : talloc_free(state->ar); /* Avoid spiking memory with many groups */
300 :
301 0 : if (strcmp(state->groups_id_attr, SYSDB_UUID) == 0) {
302 0 : ret = get_be_acct_req_for_uuid(state, ipa_uuid,
303 0 : state->user_dom->name, &state->ar);
304 0 : if (ret != EOK) {
305 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
306 0 : return ret;
307 : }
308 0 : } else if (strcmp(state->groups_id_attr, SYSDB_SID_STR) == 0) {
309 0 : ret = get_be_acct_req_for_sid(state, ipa_uuid,
310 0 : state->user_dom->name, &state->ar);
311 0 : if (ret != EOK) {
312 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
313 0 : return ret;
314 : }
315 : } else {
316 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported groups ID type [%s].\n",
317 : state->groups_id_attr);
318 0 : return EINVAL;
319 : }
320 :
321 0 : DEBUG(SSSDBG_TRACE_LIBS, "Fetching group %s\n", ipa_uuid);
322 :
323 0 : subreq = ipa_get_ad_override_send(state, state->ev,
324 0 : state->ipa_ctx->sdap_id_ctx,
325 0 : state->ipa_ctx->ipa_options,
326 : state->realm,
327 0 : state->ipa_ctx->view_name,
328 : state->ar);
329 0 : if (subreq == NULL) {
330 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
331 0 : return ENOMEM;
332 : }
333 0 : tevent_req_set_callback(subreq,
334 : ipa_initgr_get_overrides_override_done, req);
335 0 : return EAGAIN;
336 : }
337 :
338 0 : static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
339 : {
340 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
341 : struct tevent_req);
342 0 : struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
343 : struct ipa_initgr_get_overrides_state);
344 : int ret;
345 0 : struct sysdb_attrs *override_attrs = NULL;
346 :
347 0 : ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state,
348 : &override_attrs);
349 0 : talloc_zfree(subreq);
350 0 : if (ret != EOK) {
351 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
352 0 : tevent_req_error(req, ret);
353 0 : return;
354 : }
355 :
356 0 : if (is_default_view(state->ipa_ctx->view_name)) {
357 0 : ret = sysdb_apply_default_override(state->user_dom, override_attrs,
358 0 : state->groups[state->group_idx]->dn);
359 : } else {
360 0 : ret = sysdb_store_override(state->user_dom,
361 0 : state->ipa_ctx->view_name,
362 : SYSDB_MEMBER_GROUP,
363 : override_attrs,
364 0 : state->groups[state->group_idx]->dn);
365 : }
366 0 : talloc_free(override_attrs);
367 0 : if (ret != EOK) {
368 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
369 0 : tevent_req_error(req, ret);
370 0 : return;
371 : }
372 :
373 0 : state->group_idx++;
374 :
375 0 : ret = ipa_initgr_get_overrides_step(req);
376 0 : if (ret == EAGAIN) {
377 0 : return;
378 0 : } else if (ret != EOK) {
379 0 : tevent_req_error(req, ret);
380 0 : return;
381 : }
382 :
383 0 : tevent_req_done(req);
384 : }
385 :
386 0 : int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error)
387 : {
388 0 : struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
389 : struct ipa_initgr_get_overrides_state);
390 :
391 0 : if (dp_error) {
392 0 : *dp_error = state->dp_error;
393 : }
394 :
395 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
396 0 : return EOK;
397 : }
398 :
399 : /* Given a user name, retrieve an array of group UUIDs of groups that have
400 : * no overrideDN attribute but do have an UUID attribute.
401 : */
402 0 : static errno_t ipa_id_get_group_uuids(TALLOC_CTX *mem_ctx,
403 : struct sysdb_ctx *sysdb,
404 : size_t *_msgs_count,
405 : struct ldb_message ***_msgs)
406 : {
407 : const char *filter;
408 : TALLOC_CTX *tmp_ctx;
409 0 : char **uuid_list = NULL;
410 : errno_t ret;
411 : struct ldb_dn *base_dn;
412 0 : const char *attrs[] = { SYSDB_UUID, NULL };
413 : size_t msgs_count;
414 : struct ldb_message **msgs;
415 :
416 0 : tmp_ctx = talloc_new(mem_ctx);
417 0 : if (tmp_ctx == NULL) {
418 0 : return ENOMEM;
419 : }
420 :
421 0 : filter = talloc_asprintf(tmp_ctx,
422 : "(&(objectclass=%s)(!(%s=*))(%s=*))",
423 : SYSDB_GROUP_CLASS, SYSDB_OVERRIDE_DN,
424 : SYSDB_UUID);
425 0 : if (filter == NULL) {
426 0 : ret = ENOMEM;
427 0 : goto done;
428 : }
429 :
430 0 : base_dn = sysdb_base_dn(sysdb, tmp_ctx);
431 0 : if (base_dn == NULL) {
432 0 : ret = ENOMEM;
433 0 : goto done;
434 : }
435 :
436 0 : ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn,
437 : LDB_SCOPE_SUBTREE, filter, attrs,
438 : &msgs_count, &msgs);
439 0 : if (ret == ENOENT) {
440 0 : DEBUG(SSSDBG_TRACE_FUNC,
441 : "No groups without %s in sysdb\n", SYSDB_OVERRIDE_DN);
442 0 : ret = EOK;
443 0 : goto done;
444 0 : } else if (ret != EOK) {
445 0 : goto done;
446 : }
447 :
448 0 : uuid_list = talloc_zero_array(tmp_ctx, char *, msgs_count);
449 0 : if (uuid_list == NULL) {
450 0 : goto done;
451 : }
452 :
453 0 : *_msgs_count = msgs_count;
454 0 : *_msgs = talloc_steal(mem_ctx, msgs);
455 0 : ret = EOK;
456 : done:
457 0 : talloc_free(tmp_ctx);
458 0 : return ret;
459 : }
460 :
461 : struct ipa_id_get_account_info_state {
462 : struct tevent_context *ev;
463 : struct ipa_id_ctx *ipa_ctx;
464 : struct sdap_id_ctx *ctx;
465 : struct sdap_id_op *op;
466 : struct sysdb_ctx *sysdb;
467 : struct sss_domain_info *domain;
468 : struct be_acct_req *ar;
469 : struct be_acct_req *orig_ar;
470 : const char *realm;
471 :
472 : struct sysdb_attrs *override_attrs;
473 : struct ldb_message *obj_msg;
474 : struct ldb_message_element *ghosts;
475 :
476 : struct ldb_message **user_groups;
477 : size_t group_cnt;
478 : size_t group_idx;
479 :
480 : int dp_error;
481 : };
482 :
483 : static void ipa_id_get_account_info_connected(struct tevent_req *subreq);
484 : static void ipa_id_get_account_info_got_override(struct tevent_req *subreq);
485 : static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
486 : struct be_acct_req *ar);
487 : static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq);
488 : static void ipa_id_get_account_info_done(struct tevent_req *subreq);
489 : static void ipa_id_get_user_list_done(struct tevent_req *subreq);
490 :
491 : static struct tevent_req *
492 0 : ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
493 : struct ipa_id_ctx *ipa_ctx,
494 : struct be_acct_req *ar)
495 : {
496 : int ret;
497 : struct tevent_req *req;
498 : struct tevent_req *subreq;
499 : struct ipa_id_get_account_info_state *state;
500 :
501 0 : req = tevent_req_create(memctx, &state,
502 : struct ipa_id_get_account_info_state);
503 0 : if (req == NULL) {
504 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
505 0 : return NULL;
506 : }
507 :
508 0 : state->ev = ev;
509 0 : state->ipa_ctx = ipa_ctx;
510 0 : state->ctx = ipa_ctx->sdap_id_ctx;
511 0 : state->dp_error = DP_ERR_FATAL;
512 :
513 0 : state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
514 0 : if (state->op == NULL) {
515 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
516 0 : ret = ENOMEM;
517 0 : goto fail;
518 : }
519 :
520 0 : state->domain = find_domain_by_name(state->ctx->be->domain,
521 : ar->domain, true);
522 0 : if (state->domain == NULL) {
523 0 : DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
524 0 : ret = ENOMEM;
525 0 : goto fail;
526 : }
527 0 : state->sysdb = state->domain->sysdb;
528 0 : state->ar = ar;
529 0 : state->realm = dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
530 : IPA_KRB5_REALM);
531 0 : if (state->realm == NULL) {
532 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
533 0 : ret = EINVAL;
534 0 : goto fail;
535 : }
536 :
537 : /* We can skip the override lookup and go directly to the original object
538 : * if
539 : * - the lookup is by SID
540 : * - there is no view set of it is the default view
541 : * - if the EXTRA_INPUT_MAYBE_WITH_VIEW flag is not set
542 : */
543 0 : if (is_default_view(state->ipa_ctx->view_name)
544 0 : || state->ar->filter_type == BE_FILTER_SECID
545 0 : || state->ar->extra_value == NULL
546 0 : || strcmp(state->ar->extra_value,
547 : EXTRA_INPUT_MAYBE_WITH_VIEW) != 0
548 0 : || ! is_object_overridable(state->ar)) {
549 0 : ret = ipa_id_get_account_info_get_original_step(req, ar);
550 0 : if (ret != EOK) {
551 0 : DEBUG(SSSDBG_OP_FAILURE,
552 : "ipa_subdomain_account_get_original_step failed.\n");
553 0 : goto fail;
554 : }
555 : } else {
556 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
557 0 : if (subreq == NULL) {
558 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n");
559 0 : goto fail;
560 : }
561 0 : tevent_req_set_callback(subreq, ipa_id_get_account_info_connected, req);
562 : }
563 :
564 0 : return req;
565 :
566 : fail:
567 0 : tevent_req_error(req, ret);
568 0 : tevent_req_post(req, ev);
569 0 : return req;
570 : }
571 :
572 0 : static void ipa_id_get_account_info_connected(struct tevent_req *subreq)
573 : {
574 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
575 : struct tevent_req);
576 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
577 : struct ipa_id_get_account_info_state);
578 0 : int dp_error = DP_ERR_FATAL;
579 : int ret;
580 :
581 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
582 0 : talloc_zfree(subreq);
583 0 : if (ret != EOK) {
584 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
585 0 : goto fail;
586 : }
587 :
588 0 : subreq = ipa_get_ad_override_send(state, state->ev, state->ctx,
589 0 : state->ipa_ctx->ipa_options, state->realm,
590 0 : state->ipa_ctx->view_name, state->ar);
591 0 : if (subreq == NULL) {
592 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
593 0 : ret = ENOMEM;
594 0 : goto fail;
595 : }
596 :
597 0 : tevent_req_set_callback(subreq, ipa_id_get_account_info_got_override, req);
598 :
599 0 : return;
600 :
601 : fail:
602 0 : state->dp_error = dp_error;
603 0 : tevent_req_error(req, ret);
604 0 : return;
605 : }
606 :
607 0 : static void ipa_id_get_account_info_got_override(struct tevent_req *subreq)
608 : {
609 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
610 : struct tevent_req);
611 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
612 : struct ipa_id_get_account_info_state);
613 0 : int dp_error = DP_ERR_FATAL;
614 : int ret;
615 0 : const char *anchor = NULL;
616 : char *anchor_domain;
617 : char *ipa_uuid;
618 :
619 0 : ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
620 : &state->override_attrs);
621 0 : talloc_zfree(subreq);
622 0 : if (ret != EOK) {
623 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
624 0 : goto fail;
625 : }
626 :
627 0 : if (state->override_attrs != NULL) {
628 0 : ret = sysdb_attrs_get_string(state->override_attrs,
629 : SYSDB_OVERRIDE_ANCHOR_UUID,
630 : &anchor);
631 0 : if (ret != EOK) {
632 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
633 0 : goto fail;
634 : }
635 :
636 0 : ret = split_ipa_anchor(state, anchor, &anchor_domain, &ipa_uuid);
637 0 : if (ret != EOK) {
638 0 : DEBUG(SSSDBG_CRIT_FAILURE,
639 : "Unsupported override anchor [%s].\n", anchor);
640 0 : ret = EINVAL;
641 0 : goto fail;
642 : }
643 :
644 0 : if (strcmp(state->ar->domain, anchor_domain) == 0) {
645 :
646 0 : state->orig_ar = state->ar;
647 :
648 0 : ret = get_be_acct_req_for_uuid(state, ipa_uuid,
649 0 : state->ar->domain,
650 : &state->ar);
651 0 : if (ret != EOK) {
652 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_uuid failed.\n");
653 0 : goto fail;
654 : }
655 :
656 0 : if ((state->orig_ar->entry_type & BE_REQ_TYPE_MASK)
657 : == BE_REQ_INITGROUPS) {
658 0 : DEBUG(SSSDBG_TRACE_ALL,
659 : "Switching back to BE_REQ_INITGROUPS.\n");
660 0 : state->ar->entry_type = BE_REQ_INITGROUPS;
661 0 : state->ar->filter_type = BE_FILTER_UUID;
662 0 : state->ar->attr_type = BE_ATTR_CORE;
663 : }
664 :
665 : } else {
666 0 : DEBUG(SSSDBG_MINOR_FAILURE,
667 : "Anchor from a different domain [%s], expected [%s]. " \
668 : "This is currently not supported, continue lookup in " \
669 : "local IPA domain.\n",
670 : anchor_domain, state->ar->domain);
671 : }
672 : }
673 :
674 0 : ret = ipa_id_get_account_info_get_original_step(req, state->ar);
675 0 : if (ret != EOK) {
676 0 : DEBUG(SSSDBG_OP_FAILURE,
677 : "ipa_subdomain_account_get_original_step failed.\n");
678 0 : goto fail;
679 : }
680 :
681 0 : return;
682 :
683 : fail:
684 0 : state->dp_error = dp_error;
685 0 : tevent_req_error(req, ret);
686 0 : return;
687 : }
688 :
689 0 : static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
690 : struct be_acct_req *ar)
691 : {
692 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
693 : struct ipa_id_get_account_info_state);
694 : struct tevent_req *subreq;
695 :
696 0 : subreq = sdap_handle_acct_req_send(state, state->ctx->be, ar,
697 0 : state->ipa_ctx->sdap_id_ctx,
698 0 : state->ipa_ctx->sdap_id_ctx->opts->sdom,
699 0 : state->ipa_ctx->sdap_id_ctx->conn, true);
700 0 : if (subreq == NULL) {
701 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
702 0 : return ENOMEM;
703 : }
704 0 : tevent_req_set_callback(subreq, ipa_id_get_account_info_orig_done, req);
705 :
706 0 : return EOK;
707 : }
708 :
709 : static void ipa_id_get_user_groups_done(struct tevent_req *subreq);
710 :
711 0 : static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
712 : {
713 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
714 : struct tevent_req);
715 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
716 : struct ipa_id_get_account_info_state);
717 0 : int dp_error = DP_ERR_FATAL;
718 : int ret;
719 : const char *uuid;
720 : const char *class;
721 : enum sysdb_member_type type;
722 :
723 0 : ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL, NULL);
724 0 : talloc_zfree(subreq);
725 0 : if (ret != EOK) {
726 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
727 0 : goto fail;
728 : }
729 :
730 0 : if (! is_object_overridable(state->ar)) {
731 0 : state->dp_error = DP_ERR_OK;
732 0 : tevent_req_done(req);
733 0 : return;
734 : }
735 :
736 0 : ret = get_object_from_cache(state, state->domain, state->ar,
737 : &state->obj_msg);
738 0 : if (ret == ENOENT) {
739 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
740 0 : state->dp_error = DP_ERR_OK;
741 0 : tevent_req_done(req);
742 0 : return;
743 0 : } else if (ret != EOK) {
744 0 : DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
745 0 : goto fail;
746 : }
747 :
748 0 : class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
749 : NULL);
750 0 : if (class == NULL) {
751 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
752 0 : ret = EINVAL;
753 0 : goto fail;
754 : }
755 :
756 :
757 0 : if (!is_default_view(state->ipa_ctx->view_name)) {
758 :
759 0 : if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_GROUP
760 0 : || ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_UUID
761 0 : && strcmp(class, SYSDB_GROUP_CLASS) == 0)) {
762 : /* check for ghost members because ghost members are not allowed
763 : * if a view other than the default view is applied.*/
764 0 : state->ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST);
765 0 : } else if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == \
766 : BE_REQ_INITGROUPS) {
767 : /* Get UUID list of groups that have no overrideDN set. */
768 0 : ret = ipa_id_get_group_uuids(state, state->sysdb,
769 : &state->group_cnt,
770 : &state->user_groups);
771 0 : if (ret != EOK) {
772 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot get UUID list: %d\n", ret);
773 0 : goto fail;
774 : }
775 : }
776 : }
777 :
778 :
779 0 : if (state->override_attrs == NULL) {
780 0 : uuid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_UUID, NULL);
781 0 : if (uuid == NULL) {
782 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a UUID.\n");
783 0 : ret = EINVAL;
784 0 : goto fail;
785 : }
786 :
787 0 : ret = get_be_acct_req_for_uuid(state, uuid, state->domain->name,
788 : &state->ar);
789 0 : if (ret != EOK) {
790 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
791 0 : goto fail;
792 : }
793 :
794 0 : subreq = ipa_get_ad_override_send(state, state->ev,
795 0 : state->ipa_ctx->sdap_id_ctx,
796 0 : state->ipa_ctx->ipa_options,
797 : state->realm,
798 0 : state->ipa_ctx->view_name,
799 : state->ar);
800 0 : if (subreq == NULL) {
801 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
802 0 : ret = ENOMEM;
803 0 : goto fail;
804 : }
805 0 : tevent_req_set_callback(subreq, ipa_id_get_account_info_done, req);
806 0 : return;
807 : } else {
808 0 : if (strcmp(class, SYSDB_USER_CLASS) == 0) {
809 0 : type = SYSDB_MEMBER_USER;
810 : } else {
811 0 : type = SYSDB_MEMBER_GROUP;
812 : }
813 :
814 0 : ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
815 : type,
816 0 : state->override_attrs, state->obj_msg->dn);
817 0 : if (ret != EOK) {
818 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
819 0 : goto fail;
820 : }
821 : }
822 :
823 0 : if (state->ghosts != NULL) {
824 : /* Resolve ghost members */
825 0 : subreq = ipa_resolve_user_list_send(state, state->ev,
826 : state->ipa_ctx,
827 0 : state->domain->name,
828 : state->ghosts);
829 0 : if (subreq == NULL) {
830 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
831 0 : ret = ENOMEM;
832 0 : goto fail;
833 : }
834 0 : tevent_req_set_callback(subreq, ipa_id_get_user_list_done, req);
835 0 : return;
836 : }
837 :
838 0 : if (state->user_groups != NULL) {
839 0 : subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
840 : state->domain, state->group_cnt,
841 : state->user_groups,
842 : SYSDB_UUID);
843 0 : if (subreq == NULL) {
844 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
845 0 : ret = ENOMEM;
846 0 : goto fail;
847 : }
848 0 : tevent_req_set_callback(subreq, ipa_id_get_user_groups_done, req);
849 0 : return;
850 : }
851 :
852 0 : state->dp_error = DP_ERR_OK;
853 0 : tevent_req_done(req);
854 0 : return;
855 :
856 : fail:
857 0 : state->dp_error = dp_error;
858 0 : tevent_req_error(req, ret);
859 0 : return;
860 : }
861 :
862 0 : static void ipa_id_get_account_info_done(struct tevent_req *subreq)
863 : {
864 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
865 : struct tevent_req);
866 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
867 : struct ipa_id_get_account_info_state);
868 0 : int dp_error = DP_ERR_FATAL;
869 : int ret;
870 : const char *class;
871 : enum sysdb_member_type type;
872 :
873 0 : ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
874 : &state->override_attrs);
875 0 : talloc_zfree(subreq);
876 0 : if (ret != EOK) {
877 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
878 0 : goto fail;
879 : }
880 :
881 0 : class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
882 : NULL);
883 0 : if (class == NULL) {
884 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
885 0 : ret = EINVAL;
886 0 : goto fail;
887 : }
888 :
889 0 : if (strcmp(class, SYSDB_USER_CLASS) == 0) {
890 0 : type = SYSDB_MEMBER_USER;
891 : } else {
892 0 : type = SYSDB_MEMBER_GROUP;
893 : }
894 :
895 0 : ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
896 : type,
897 0 : state->override_attrs, state->obj_msg->dn);
898 0 : if (ret != EOK) {
899 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
900 0 : goto fail;
901 : }
902 :
903 0 : if (state->ghosts != NULL) {
904 : /* Resolve ghost members */
905 0 : subreq = ipa_resolve_user_list_send(state, state->ev,
906 : state->ipa_ctx,
907 0 : state->domain->name,
908 : state->ghosts);
909 0 : if (subreq == NULL) {
910 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
911 0 : ret = ENOMEM;
912 0 : goto fail;
913 : }
914 0 : tevent_req_set_callback(subreq, ipa_id_get_user_list_done, req);
915 0 : return;
916 : }
917 :
918 0 : if (state->user_groups != NULL) {
919 0 : subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
920 : state->domain, state->group_cnt,
921 : state->user_groups,
922 : SYSDB_UUID);
923 0 : if (subreq == NULL) {
924 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
925 0 : ret = ENOMEM;
926 0 : goto fail;
927 : }
928 0 : tevent_req_set_callback(subreq, ipa_id_get_user_groups_done, req);
929 0 : return;
930 : }
931 :
932 0 : state->dp_error = DP_ERR_OK;
933 0 : tevent_req_done(req);
934 0 : return;
935 :
936 : fail:
937 0 : state->dp_error = dp_error;
938 0 : tevent_req_error(req, ret);
939 0 : return;
940 : }
941 :
942 0 : static void ipa_id_get_user_list_done(struct tevent_req *subreq)
943 : {
944 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
945 : struct tevent_req);
946 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
947 : struct ipa_id_get_account_info_state);
948 0 : int dp_error = DP_ERR_FATAL;
949 : int ret;
950 :
951 0 : ret = ipa_resolve_user_list_recv(subreq, &dp_error);
952 0 : talloc_zfree(subreq);
953 0 : if (ret != EOK) {
954 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user list %d\n", ret);
955 0 : goto fail;
956 : }
957 :
958 0 : state->dp_error = DP_ERR_OK;
959 0 : tevent_req_done(req);
960 0 : return;
961 :
962 : fail:
963 0 : state->dp_error = dp_error;
964 0 : tevent_req_error(req, ret);
965 0 : return;
966 : }
967 :
968 0 : static void ipa_id_get_user_groups_done(struct tevent_req *subreq)
969 : {
970 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
971 : struct tevent_req);
972 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
973 : struct ipa_id_get_account_info_state);
974 0 : int dp_error = DP_ERR_FATAL;
975 : int ret;
976 :
977 0 : ret = ipa_initgr_get_overrides_recv(subreq, &dp_error);
978 0 : talloc_zfree(subreq);
979 0 : if (ret != EOK) {
980 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user groups %d\n", ret);
981 0 : goto fail;
982 : }
983 :
984 0 : state->dp_error = DP_ERR_OK;
985 0 : tevent_req_done(req);
986 0 : return;
987 :
988 : fail:
989 0 : state->dp_error = dp_error;
990 0 : tevent_req_error(req, ret);
991 0 : return;
992 : }
993 :
994 0 : static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error)
995 : {
996 0 : struct ipa_id_get_account_info_state *state = tevent_req_data(req,
997 : struct ipa_id_get_account_info_state);
998 :
999 0 : if (dp_error) {
1000 0 : *dp_error = state->dp_error;
1001 : }
1002 :
1003 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1004 :
1005 0 : return EOK;
1006 : }
1007 :
1008 : /* Request for netgroups
1009 : * - first start here and then go to ipa_netgroups.c
1010 : */
1011 : struct ipa_id_get_netgroup_state {
1012 : struct tevent_context *ev;
1013 : struct ipa_id_ctx *ctx;
1014 : struct sdap_id_op *op;
1015 : struct sysdb_ctx *sysdb;
1016 : struct sss_domain_info *domain;
1017 :
1018 : const char *name;
1019 : int timeout;
1020 :
1021 : char *filter;
1022 : const char **attrs;
1023 :
1024 : size_t count;
1025 : struct sysdb_attrs **netgroups;
1026 :
1027 : int dp_error;
1028 : };
1029 :
1030 : static void ipa_id_get_netgroup_connected(struct tevent_req *subreq);
1031 : static void ipa_id_get_netgroup_done(struct tevent_req *subreq);
1032 :
1033 0 : static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx,
1034 : struct tevent_context *ev,
1035 : struct ipa_id_ctx *ipa_ctx,
1036 : const char *name)
1037 : {
1038 : struct tevent_req *req;
1039 : struct ipa_id_get_netgroup_state *state;
1040 : struct tevent_req *subreq;
1041 : struct sdap_id_ctx *ctx;
1042 : char *clean_name;
1043 : int ret;
1044 :
1045 0 : ctx = ipa_ctx->sdap_id_ctx;
1046 :
1047 0 : req = tevent_req_create(memctx, &state, struct ipa_id_get_netgroup_state);
1048 0 : if (!req) return NULL;
1049 :
1050 0 : state->ev = ev;
1051 0 : state->ctx = ipa_ctx;
1052 0 : state->dp_error = DP_ERR_FATAL;
1053 :
1054 0 : state->op = sdap_id_op_create(state, ctx->conn->conn_cache);
1055 0 : if (!state->op) {
1056 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
1057 0 : ret = ENOMEM;
1058 0 : goto fail;
1059 : }
1060 :
1061 0 : state->sysdb = ctx->be->domain->sysdb;
1062 0 : state->domain = ctx->be->domain;
1063 0 : state->name = name;
1064 0 : state->timeout = dp_opt_get_int(ctx->opts->basic, SDAP_SEARCH_TIMEOUT);
1065 :
1066 0 : ret = sss_filter_sanitize(state, name, &clean_name);
1067 0 : if (ret != EOK) {
1068 0 : goto fail;
1069 : }
1070 :
1071 0 : state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
1072 0 : ctx->opts->netgroup_map[IPA_AT_NETGROUP_NAME].name,
1073 : clean_name,
1074 0 : ctx->opts->netgroup_map[IPA_OC_NETGROUP].name);
1075 0 : if (!state->filter) {
1076 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n");
1077 0 : ret = ENOMEM;
1078 0 : goto fail;
1079 : }
1080 0 : talloc_zfree(clean_name);
1081 :
1082 0 : ret = build_attrs_from_map(state, ctx->opts->netgroup_map,
1083 : IPA_OPTS_NETGROUP, NULL,
1084 0 : &state->attrs, NULL);
1085 0 : if (ret != EOK) goto fail;
1086 :
1087 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
1088 0 : if (!subreq) {
1089 0 : goto fail;
1090 : }
1091 0 : tevent_req_set_callback(subreq, ipa_id_get_netgroup_connected, req);
1092 :
1093 0 : return req;
1094 :
1095 : fail:
1096 0 : tevent_req_error(req, ret);
1097 0 : tevent_req_post(req, ev);
1098 0 : return req;
1099 : }
1100 :
1101 0 : static void ipa_id_get_netgroup_connected(struct tevent_req *subreq)
1102 : {
1103 0 : struct tevent_req *req =
1104 0 : tevent_req_callback_data(subreq, struct tevent_req);
1105 0 : struct ipa_id_get_netgroup_state *state =
1106 0 : tevent_req_data(req, struct ipa_id_get_netgroup_state);
1107 0 : int dp_error = DP_ERR_FATAL;
1108 : int ret;
1109 0 : struct sdap_id_ctx *sdap_ctx = state->ctx->sdap_id_ctx;
1110 :
1111 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
1112 0 : talloc_zfree(subreq);
1113 :
1114 0 : if (ret != EOK) {
1115 0 : state->dp_error = dp_error;
1116 0 : tevent_req_error(req, ret);
1117 0 : return;
1118 : }
1119 :
1120 0 : subreq = ipa_get_netgroups_send(state, state->ev, state->sysdb,
1121 : state->domain, sdap_ctx->opts,
1122 0 : state->ctx->ipa_options,
1123 : sdap_id_op_handle(state->op),
1124 0 : state->attrs, state->filter,
1125 : state->timeout);
1126 0 : if (!subreq) {
1127 0 : tevent_req_error(req, ENOMEM);
1128 0 : return;
1129 : }
1130 0 : tevent_req_set_callback(subreq, ipa_id_get_netgroup_done, req);
1131 :
1132 0 : return;
1133 : }
1134 :
1135 0 : static void ipa_id_get_netgroup_done(struct tevent_req *subreq)
1136 : {
1137 0 : struct tevent_req *req =
1138 0 : tevent_req_callback_data(subreq, struct tevent_req);
1139 0 : struct ipa_id_get_netgroup_state *state =
1140 0 : tevent_req_data(req, struct ipa_id_get_netgroup_state);
1141 0 : int dp_error = DP_ERR_FATAL;
1142 : int ret;
1143 :
1144 0 : ret = ipa_get_netgroups_recv(subreq, state,
1145 : &state->count, &state->netgroups);
1146 0 : talloc_zfree(subreq);
1147 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
1148 :
1149 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
1150 : /* retry */
1151 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
1152 0 : if (!subreq) {
1153 0 : tevent_req_error(req, ret);
1154 0 : return;
1155 : }
1156 0 : tevent_req_set_callback(subreq, ipa_id_get_netgroup_connected, req);
1157 0 : return;
1158 : }
1159 :
1160 0 : if (ret && ret != ENOENT) {
1161 0 : state->dp_error = dp_error;
1162 0 : tevent_req_error(req, ret);
1163 0 : return;
1164 : }
1165 :
1166 0 : if (ret == EOK && state->count > 1) {
1167 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1168 : "Found more than one netgroup with the name [%s].\n",
1169 : state->name);
1170 0 : tevent_req_error(req, EINVAL);
1171 0 : return;
1172 : }
1173 :
1174 0 : if (ret == ENOENT) {
1175 0 : ret = sysdb_delete_netgroup(state->domain, state->name);
1176 0 : if (ret != EOK && ret != ENOENT) {
1177 0 : tevent_req_error(req, ret);
1178 0 : return;
1179 : }
1180 : }
1181 :
1182 0 : state->dp_error = DP_ERR_OK;
1183 0 : tevent_req_done(req);
1184 0 : return;
1185 : }
1186 :
1187 0 : static int ipa_id_get_netgroup_recv(struct tevent_req *req, int *dp_error)
1188 : {
1189 0 : struct ipa_id_get_netgroup_state *state =
1190 0 : tevent_req_data(req, struct ipa_id_get_netgroup_state);
1191 :
1192 0 : if (dp_error) {
1193 0 : *dp_error = state->dp_error;
1194 : }
1195 :
1196 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1197 :
1198 0 : return EOK;
1199 : }
1200 :
1201 : enum ipa_account_info_type {
1202 : IPA_ACCOUNT_INFO_SUBDOMAIN,
1203 : IPA_ACCOUNT_INFO_NETGROUP,
1204 : IPA_ACCOUNT_INFO_OTHER
1205 : };
1206 :
1207 : static enum ipa_account_info_type
1208 0 : ipa_decide_account_info_type(struct be_acct_req *data, struct be_ctx *be_ctx)
1209 : {
1210 0 : if (strcasecmp(data->domain, be_ctx->domain->name) != 0) {
1211 0 : return IPA_ACCOUNT_INFO_SUBDOMAIN;
1212 0 : } else if ((data->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
1213 0 : return IPA_ACCOUNT_INFO_NETGROUP;
1214 : }
1215 :
1216 0 : return IPA_ACCOUNT_INFO_OTHER;
1217 : }
1218 :
1219 : struct ipa_account_info_handler_state {
1220 : enum ipa_account_info_type type;
1221 : struct dp_reply_std reply;
1222 : };
1223 :
1224 : static void ipa_account_info_handler_done(struct tevent_req *subreq);
1225 :
1226 : struct tevent_req *
1227 0 : ipa_account_info_handler_send(TALLOC_CTX *mem_ctx,
1228 : struct ipa_id_ctx *id_ctx,
1229 : struct be_acct_req *data,
1230 : struct dp_req_params *params)
1231 : {
1232 : struct ipa_account_info_handler_state *state;
1233 0 : struct tevent_req *subreq = NULL;
1234 : struct tevent_req *req;
1235 : errno_t ret;
1236 :
1237 0 : req = tevent_req_create(mem_ctx, &state,
1238 : struct ipa_account_info_handler_state);
1239 0 : if (req == NULL) {
1240 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1241 0 : return NULL;
1242 : }
1243 :
1244 0 : state->type = ipa_decide_account_info_type(data, params->be_ctx);
1245 :
1246 0 : if (sdap_is_enum_request(data)) {
1247 0 : DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
1248 0 : ret = EOK;
1249 0 : goto immediately;
1250 : }
1251 :
1252 0 : switch (state->type) {
1253 : case IPA_ACCOUNT_INFO_SUBDOMAIN:
1254 : /* Subdomain lookups are handled differently on server and client. */
1255 0 : subreq = ipa_subdomain_account_send(state, params->ev, id_ctx, data);
1256 0 : break;
1257 : case IPA_ACCOUNT_INFO_NETGROUP:
1258 0 : if (data->filter_type != BE_FILTER_NAME) {
1259 0 : ret = EINVAL;
1260 0 : goto immediately;
1261 : }
1262 :
1263 0 : subreq = ipa_id_get_netgroup_send(state, params->ev, id_ctx,
1264 : data->filter_value);
1265 0 : break;
1266 : case IPA_ACCOUNT_INFO_OTHER:
1267 0 : subreq = ipa_id_get_account_info_send(state, params->ev, id_ctx, data);
1268 0 : break;
1269 : }
1270 :
1271 0 : if (subreq == NULL) {
1272 0 : ret = ENOMEM;
1273 0 : goto immediately;
1274 : }
1275 :
1276 0 : tevent_req_set_callback(subreq, ipa_account_info_handler_done, req);
1277 :
1278 0 : return req;
1279 :
1280 : immediately:
1281 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
1282 :
1283 : /* TODO For backward compatibility we always return EOK to DP now. */
1284 0 : tevent_req_done(req);
1285 0 : tevent_req_post(req, params->ev);
1286 :
1287 0 : return req;
1288 : }
1289 :
1290 0 : static void ipa_account_info_handler_done(struct tevent_req *subreq)
1291 : {
1292 : struct ipa_account_info_handler_state *state;
1293 : struct tevent_req *req;
1294 : int dp_error;
1295 0 : errno_t ret = ERR_INTERNAL;
1296 :
1297 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1298 0 : state = tevent_req_data(req, struct ipa_account_info_handler_state);
1299 :
1300 0 : switch (state->type) {
1301 : case IPA_ACCOUNT_INFO_SUBDOMAIN:
1302 0 : ret = ipa_subdomain_account_recv(subreq, &dp_error);
1303 0 : break;
1304 : case IPA_ACCOUNT_INFO_NETGROUP:
1305 0 : ret = ipa_id_get_netgroup_recv(subreq, &dp_error);
1306 0 : break;
1307 : case IPA_ACCOUNT_INFO_OTHER:
1308 0 : ret = ipa_id_get_account_info_recv(subreq, &dp_error);
1309 0 : break;
1310 : }
1311 0 : talloc_zfree(subreq);
1312 :
1313 : /* TODO For backward compatibility we always return EOK to DP now. */
1314 0 : dp_reply_std_set(&state->reply, dp_error, ret, NULL);
1315 0 : tevent_req_done(req);
1316 0 : }
1317 :
1318 0 : errno_t ipa_account_info_handler_recv(TALLOC_CTX *mem_ctx,
1319 : struct tevent_req *req,
1320 : struct dp_reply_std *data)
1321 : {
1322 0 : struct ipa_account_info_handler_state *state = NULL;
1323 :
1324 0 : state = tevent_req_data(req, struct ipa_account_info_handler_state);
1325 :
1326 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1327 :
1328 0 : *data = state->reply;
1329 :
1330 0 : return EOK;
1331 : }
|