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