Line data Source code
1 : /*
2 : SSSD
3 :
4 : IPA Identity Backend Module for sub-domains
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2012 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 "util/sss_nss.h"
29 : #include "util/strtonum.h"
30 : #include "db/sysdb.h"
31 : #include "providers/ldap/ldap_common.h"
32 : #include "providers/ldap/sdap_async.h"
33 : #include "providers/ipa/ipa_id.h"
34 : #include "providers/ad/ad_id.h"
35 : #include "providers/ipa/ipa_subdomains.h"
36 :
37 : static struct tevent_req *
38 : ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx,
39 : struct tevent_context *ev,
40 : struct ipa_id_ctx *ipa_ctx,
41 : struct be_req *be_req,
42 : struct sysdb_attrs *override_attrs,
43 : struct be_acct_req *ar);
44 : static errno_t
45 : ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out);
46 :
47 : struct ipa_subdomain_account_state {
48 : struct tevent_context *ev;
49 : struct ipa_id_ctx *ipa_ctx;
50 : struct sdap_id_ctx *ctx;
51 : struct sdap_id_op *op;
52 : struct sysdb_ctx *sysdb;
53 : struct sss_domain_info *domain;
54 : struct be_req *be_req;
55 : struct be_acct_req *ar;
56 :
57 : bool ipa_server_mode;
58 : bool server_retry;
59 : int entry_type;
60 : const char *filter;
61 : int filter_type;
62 : struct sysdb_attrs *override_attrs;
63 :
64 : int dp_error;
65 : };
66 :
67 : static void ipa_subdomain_account_connected(struct tevent_req *subreq);
68 : static void ipa_subdomain_account_got_override(struct tevent_req *subreq);
69 : static void ipa_subdomain_account_done(struct tevent_req *subreq);
70 : static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req,
71 : struct be_acct_req *ar);
72 :
73 0 : struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx,
74 : struct tevent_context *ev,
75 : struct ipa_id_ctx *ipa_ctx,
76 : struct be_req *be_req,
77 : struct be_acct_req *ar)
78 : {
79 : struct tevent_req *req;
80 : struct ipa_subdomain_account_state *state;
81 : struct tevent_req *subreq;
82 : int ret;
83 :
84 0 : req = tevent_req_create(memctx, &state, struct ipa_subdomain_account_state);
85 0 : if (req == NULL) {
86 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
87 0 : return NULL;
88 : }
89 :
90 0 : state->ev = ev;
91 0 : state->ipa_ctx = ipa_ctx;
92 0 : state->ctx = ipa_ctx->sdap_id_ctx;
93 0 : state->dp_error = DP_ERR_FATAL;
94 :
95 0 : state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
96 0 : if (!state->op) {
97 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
98 0 : ret = ENOMEM;
99 0 : goto fail;
100 : }
101 :
102 0 : state->domain = find_domain_by_name(state->ctx->be->domain,
103 0 : ar->domain, true);
104 0 : if (state->domain == NULL) {
105 0 : DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
106 0 : ret = ENOMEM;
107 0 : goto fail;
108 : }
109 0 : state->sysdb = state->domain->sysdb;
110 0 : state->be_req = be_req;
111 0 : state->ar = ar;
112 0 : state->ipa_server_mode = dp_opt_get_bool(state->ipa_ctx->ipa_options->basic,
113 : IPA_SERVER_MODE);
114 0 : state->override_attrs = NULL;
115 :
116 : /* With views we cannot got directly to the look up the AD objects but
117 : * have to check first if the request matches an override in the given
118 : * view. But there are cases where this can be skipped and the AD object
119 : * can be searched directly:
120 : * - if no view is defined, i.e. the server does not supprt views yet
121 : * - searches by SID: because we do not override the SID
122 : * - if the responder does not send the EXTRA_INPUT_MAYBE_WITH_VIEW flags,
123 : * because in this case the entry was found in the cache and the
124 : * original value is used for the search (e.g. during cache updates) */
125 0 : if (state->ipa_ctx->view_name == NULL
126 0 : || state->ar->filter_type == BE_FILTER_SECID
127 0 : || (!state->ipa_server_mode
128 0 : && state->ar->extra_value != NULL
129 0 : && strcmp(state->ar->extra_value,
130 : EXTRA_INPUT_MAYBE_WITH_VIEW) != 0 )) {
131 0 : ret = ipa_subdomain_account_get_original_step(req, state->ar);
132 0 : if (ret != EOK) {
133 0 : DEBUG(SSSDBG_OP_FAILURE,
134 : "ipa_subdomain_account_get_original_step failed.\n");
135 0 : goto fail;
136 : }
137 :
138 0 : return req;
139 : }
140 :
141 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
142 0 : if (!subreq) {
143 0 : goto fail;
144 : }
145 0 : tevent_req_set_callback(subreq, ipa_subdomain_account_connected, req);
146 :
147 0 : return req;
148 :
149 : fail:
150 0 : tevent_req_error(req, ret);
151 0 : tevent_req_post(req, ev);
152 0 : return req;
153 : }
154 :
155 0 : static void ipa_subdomain_account_connected(struct tevent_req *subreq)
156 : {
157 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
158 : struct tevent_req);
159 0 : struct ipa_subdomain_account_state *state = tevent_req_data(req,
160 : struct ipa_subdomain_account_state);
161 0 : int dp_error = DP_ERR_FATAL;
162 : int ret;
163 :
164 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
165 0 : talloc_zfree(subreq);
166 0 : if (ret != EOK) {
167 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
168 0 : goto fail;
169 : }
170 :
171 0 : subreq = ipa_get_ad_override_send(state, state->ev, state->ctx,
172 0 : state->ipa_ctx->ipa_options,
173 0 : dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
174 : IPA_KRB5_REALM),
175 0 : state->ipa_ctx->view_name, state->ar);
176 0 : if (subreq == NULL) {
177 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
178 0 : ret = ENOMEM;
179 0 : goto fail;
180 : }
181 :
182 0 : tevent_req_set_callback(subreq, ipa_subdomain_account_got_override, req);
183 :
184 0 : return;
185 :
186 : fail:
187 0 : state->dp_error = dp_error;
188 0 : tevent_req_error(req, ret);
189 0 : return;
190 : }
191 :
192 : #define OVERRIDE_ANCHOR_SID_PREFIX ":SID:"
193 : #define OVERRIDE_ANCHOR_SID_PREFIX_LEN (sizeof(OVERRIDE_ANCHOR_SID_PREFIX) -1 )
194 :
195 0 : static void ipa_subdomain_account_got_override(struct tevent_req *subreq)
196 : {
197 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
198 : struct tevent_req);
199 0 : struct ipa_subdomain_account_state *state = tevent_req_data(req,
200 : struct ipa_subdomain_account_state);
201 0 : int dp_error = DP_ERR_FATAL;
202 : int ret;
203 0 : const char *anchor = NULL;
204 : struct be_acct_req *ar;
205 :
206 0 : ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
207 : &state->override_attrs);
208 0 : talloc_zfree(subreq);
209 0 : if (ret != EOK) {
210 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
211 0 : goto fail;
212 : }
213 :
214 0 : if (state->override_attrs != NULL) {
215 0 : DEBUG(SSSDBG_TRACE_ALL, "Processing override.\n");
216 0 : ret = sysdb_attrs_get_string(state->override_attrs,
217 : SYSDB_OVERRIDE_ANCHOR_UUID,
218 : &anchor);
219 0 : if (ret != EOK) {
220 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
221 0 : goto fail;
222 : }
223 0 : if (anchor != NULL && strncmp(OVERRIDE_ANCHOR_SID_PREFIX, anchor,
224 : OVERRIDE_ANCHOR_SID_PREFIX_LEN) == 0) {
225 :
226 0 : ret = get_be_acct_req_for_sid(state,
227 : anchor + OVERRIDE_ANCHOR_SID_PREFIX_LEN,
228 0 : state->ar->domain,
229 : &ar);
230 0 : if (ret != EOK) {
231 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
232 0 : goto fail;
233 : }
234 :
235 0 : if (state->ipa_server_mode
236 0 : && (state->ar->entry_type & BE_REQ_TYPE_MASK)
237 : == BE_REQ_INITGROUPS) {
238 0 : DEBUG(SSSDBG_TRACE_ALL,
239 : "Switching back to BE_REQ_INITGROUPS.\n");
240 0 : ar->entry_type = BE_REQ_INITGROUPS;
241 0 : ar->filter_type = BE_FILTER_SECID;
242 0 : ar->attr_type = BE_ATTR_CORE;
243 : }
244 : } else {
245 0 : DEBUG(SSSDBG_CRIT_FAILURE,
246 : "Unsupported override anchor type [%s].\n", anchor);
247 0 : ret = EINVAL;
248 0 : goto fail;
249 : }
250 : } else {
251 0 : ar = state->ar;
252 : }
253 :
254 0 : ret = ipa_subdomain_account_get_original_step(req, ar);
255 0 : if (ret != EOK) {
256 0 : DEBUG(SSSDBG_OP_FAILURE,
257 : "ipa_subdomain_account_get_original_step failed.\n");
258 0 : goto fail;
259 : }
260 :
261 0 : return;
262 :
263 : fail:
264 0 : state->dp_error = dp_error;
265 0 : tevent_req_error(req, ret);
266 0 : return;
267 : }
268 :
269 0 : static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req,
270 : struct be_acct_req *ar)
271 : {
272 0 : struct ipa_subdomain_account_state *state = tevent_req_data(req,
273 : struct ipa_subdomain_account_state);
274 : struct tevent_req *subreq;
275 :
276 0 : if (state->ipa_server_mode) {
277 0 : subreq = ipa_srv_ad_acct_send(state, state->ev, state->ipa_ctx,
278 : state->be_req, state->override_attrs, ar);
279 : } else {
280 0 : subreq = ipa_get_subdom_acct_send(state, state->ev, state->ipa_ctx,
281 : state->override_attrs, ar);
282 : }
283 :
284 0 : if (subreq == NULL) {
285 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct_send failed.\n");
286 0 : return ENOMEM;
287 : }
288 :
289 0 : tevent_req_set_callback(subreq, ipa_subdomain_account_done, req);
290 :
291 0 : return EOK;
292 : }
293 :
294 :
295 0 : static void ipa_subdomain_account_done(struct tevent_req *subreq)
296 : {
297 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
298 : struct tevent_req);
299 0 : struct ipa_subdomain_account_state *state = tevent_req_data(req,
300 : struct ipa_subdomain_account_state);
301 0 : int dp_error = DP_ERR_FATAL;
302 : int ret;
303 :
304 0 : if (state->ipa_server_mode) {
305 0 : ret = ipa_srv_ad_acct_recv(subreq, &dp_error);
306 : } else {
307 0 : ret = ipa_get_subdom_acct_recv(subreq, &dp_error);
308 : }
309 0 : talloc_zfree(subreq);
310 0 : if (ret != EOK) {
311 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n",
312 : ret, sss_strerror(ret));
313 0 : state->dp_error = dp_error;
314 0 : tevent_req_error(req, ret);
315 0 : return;
316 : }
317 :
318 0 : state->dp_error = DP_ERR_OK;
319 0 : tevent_req_done(req);
320 0 : return;
321 : }
322 :
323 0 : errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out)
324 : {
325 0 : struct ipa_subdomain_account_state *state = tevent_req_data(req,
326 : struct ipa_subdomain_account_state);
327 :
328 0 : if (dp_error_out) {
329 0 : *dp_error_out = state->dp_error;
330 : }
331 :
332 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
333 :
334 0 : return EOK;
335 : }
336 :
337 : struct ipa_get_subdom_acct {
338 : struct tevent_context *ev;
339 : struct ipa_id_ctx *ipa_ctx;
340 : struct sdap_id_ctx *ctx;
341 : struct sdap_id_op *op;
342 : struct sysdb_ctx *sysdb;
343 : struct sss_domain_info *domain;
344 : struct sysdb_attrs *override_attrs;
345 :
346 : int entry_type;
347 : const char *filter;
348 : int filter_type;
349 :
350 : int dp_error;
351 : };
352 :
353 : static void ipa_get_subdom_acct_connected(struct tevent_req *subreq);
354 : static void ipa_get_subdom_acct_done(struct tevent_req *subreq);
355 :
356 0 : struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
357 : struct tevent_context *ev,
358 : struct ipa_id_ctx *ipa_ctx,
359 : struct sysdb_attrs *override_attrs,
360 : struct be_acct_req *ar)
361 : {
362 : struct tevent_req *req;
363 : struct ipa_get_subdom_acct *state;
364 : struct tevent_req *subreq;
365 : int ret;
366 :
367 0 : req = tevent_req_create(memctx, &state, struct ipa_get_subdom_acct);
368 0 : if (!req) return NULL;
369 :
370 0 : state->ev = ev;
371 0 : state->ipa_ctx = ipa_ctx;
372 0 : state->ctx = ipa_ctx->sdap_id_ctx;
373 0 : state->dp_error = DP_ERR_FATAL;
374 0 : state->override_attrs = override_attrs;
375 :
376 0 : state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
377 0 : if (!state->op) {
378 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
379 0 : ret = ENOMEM;
380 0 : goto fail;
381 : }
382 :
383 0 : state->domain = find_domain_by_name(state->ctx->be->domain,
384 0 : ar->domain, true);
385 0 : if (state->domain == NULL) {
386 0 : DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
387 0 : ret = ENOMEM;
388 0 : goto fail;
389 : }
390 0 : state->sysdb = state->domain->sysdb;
391 :
392 0 : state->entry_type = (ar->entry_type & BE_REQ_TYPE_MASK);
393 0 : state->filter = ar->filter_value;
394 0 : state->filter_type = ar->filter_type;
395 :
396 0 : switch (state->entry_type) {
397 : case BE_REQ_USER:
398 : case BE_REQ_GROUP:
399 : case BE_REQ_BY_SECID:
400 : case BE_REQ_USER_AND_GROUP:
401 : case BE_REQ_INITGROUPS:
402 0 : ret = EOK;
403 0 : break;
404 : default:
405 0 : ret = EINVAL;
406 0 : DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain request type.\n");
407 : }
408 0 : if (ret != EOK) goto fail;
409 :
410 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
411 0 : if (!subreq) {
412 0 : goto fail;
413 : }
414 0 : tevent_req_set_callback(subreq, ipa_get_subdom_acct_connected, req);
415 :
416 0 : return req;
417 :
418 : fail:
419 0 : tevent_req_error(req, ret);
420 0 : tevent_req_post(req, ev);
421 0 : return req;
422 : }
423 :
424 0 : static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
425 : {
426 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
427 : struct tevent_req);
428 0 : struct ipa_get_subdom_acct *state = tevent_req_data(req,
429 : struct ipa_get_subdom_acct);
430 0 : int dp_error = DP_ERR_FATAL;
431 : int ret;
432 : char *endptr;
433 : struct req_input *req_input;
434 :
435 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
436 0 : talloc_zfree(subreq);
437 0 : if (ret != EOK) {
438 0 : state->dp_error = dp_error;
439 0 : tevent_req_error(req, ret);
440 0 : return;
441 : }
442 :
443 0 : if (state->entry_type == BE_REQ_INITGROUPS) {
444 : /* With V1 of the extdom plugin a user lookup will resolve the full
445 : * group membership of the user. */
446 0 : if (sdap_is_extension_supported(sdap_id_op_handle(state->op),
447 : EXOP_SID2NAME_V1_OID)) {
448 0 : state->entry_type = BE_REQ_USER;
449 : } else {
450 0 : DEBUG(SSSDBG_TRACE_FUNC, "Initgroups requests are not handled " \
451 : "by the IPA provider but are resolved " \
452 : "by the responder directly from the " \
453 : "cache.\n");
454 0 : tevent_req_error(req, ENOTSUP);
455 0 : return;
456 : }
457 : }
458 :
459 0 : req_input = talloc(state, struct req_input);
460 0 : if (req_input == NULL) {
461 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n");
462 0 : tevent_req_error(req, ENOMEM);
463 0 : return;
464 : }
465 :
466 0 : switch (state->filter_type) {
467 : case BE_FILTER_NAME:
468 0 : req_input->type = REQ_INP_NAME;
469 0 : req_input->inp.name = talloc_strdup(req_input, state->filter);
470 0 : if (req_input->inp.name == NULL) {
471 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
472 0 : tevent_req_error(req, ENOMEM);
473 0 : return;
474 : }
475 0 : break;
476 : case BE_FILTER_IDNUM:
477 0 : req_input->type = REQ_INP_ID;
478 0 : req_input->inp.id = strtouint32(state->filter, &endptr, 10);
479 0 : if (errno || *endptr || (state->filter == endptr)) {
480 0 : tevent_req_error(req, errno ? errno : EINVAL);
481 0 : return;
482 : }
483 0 : break;
484 : case BE_FILTER_SECID:
485 0 : req_input->type = REQ_INP_SECID;
486 0 : req_input->inp.secid = talloc_strdup(req_input, state->filter);
487 0 : if (req_input->inp.secid == NULL) {
488 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
489 0 : tevent_req_error(req, ENOMEM);
490 0 : return;
491 : }
492 0 : break;
493 : default:
494 0 : DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n");
495 0 : state->dp_error = dp_error;
496 0 : tevent_req_error(req, EINVAL);
497 0 : return;
498 : }
499 :
500 0 : subreq = ipa_s2n_get_acct_info_send(state,
501 : state->ev,
502 : state->ipa_ctx,
503 0 : state->ctx->opts,
504 : state->domain,
505 : state->override_attrs,
506 : sdap_id_op_handle(state->op),
507 : state->entry_type,
508 : req_input);
509 0 : if (!subreq) {
510 0 : tevent_req_error(req, ENOMEM);
511 0 : return;
512 : }
513 0 : tevent_req_set_callback(subreq, ipa_get_subdom_acct_done, req);
514 :
515 0 : return;
516 : }
517 :
518 0 : static void ipa_get_subdom_acct_done(struct tevent_req *subreq)
519 : {
520 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
521 : struct tevent_req);
522 0 : struct ipa_get_subdom_acct *state = tevent_req_data(req,
523 : struct ipa_get_subdom_acct);
524 0 : int dp_error = DP_ERR_FATAL;
525 : int ret;
526 :
527 0 : ret = ipa_s2n_get_acct_info_recv(subreq);
528 0 : talloc_zfree(subreq);
529 :
530 0 : ret = sdap_id_op_done(state->op, ret, &dp_error);
531 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
532 : /* retry */
533 0 : subreq = sdap_id_op_connect_send(state->op, state, &ret);
534 0 : if (!subreq) {
535 0 : tevent_req_error(req, ret);
536 0 : return;
537 : }
538 0 : tevent_req_set_callback(subreq, ipa_get_subdom_acct_connected, req);
539 0 : return;
540 : }
541 :
542 0 : if (ret && ret != ENOENT) {
543 0 : state->dp_error = dp_error;
544 0 : tevent_req_error(req, ret);
545 0 : return;
546 : }
547 :
548 : /* FIXME: do we need some special handling of ENOENT */
549 :
550 0 : state->dp_error = DP_ERR_OK;
551 0 : tevent_req_done(req);
552 : }
553 :
554 0 : int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out)
555 : {
556 0 : struct ipa_get_subdom_acct *state = tevent_req_data(req,
557 : struct ipa_get_subdom_acct);
558 :
559 0 : if (dp_error_out) {
560 0 : *dp_error_out = state->dp_error;
561 : }
562 :
563 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
564 :
565 0 : return EOK;
566 : }
567 :
568 : /* IPA lookup for server mode. Directly to AD. */
569 : struct ipa_get_ad_acct_state {
570 : int dp_error;
571 : struct tevent_context *ev;
572 : struct ipa_id_ctx *ipa_ctx;
573 : struct be_req *be_req;
574 : struct be_acct_req *ar;
575 : struct sss_domain_info *obj_dom;
576 : char *object_sid;
577 : struct sysdb_attrs *override_attrs;
578 : struct ldb_message *obj_msg;
579 : };
580 :
581 : static void ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq);
582 : static void ipa_get_ad_override_done(struct tevent_req *subreq);
583 : static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req);
584 : static errno_t ipa_get_ad_ipa_membership_step(struct tevent_req *req);
585 : static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq);
586 : static void ipa_get_ad_acct_done(struct tevent_req *subreq);
587 : static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
588 : struct sss_domain_info *dom);
589 :
590 : static struct tevent_req *
591 0 : ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
592 : struct tevent_context *ev,
593 : struct ipa_id_ctx *ipa_ctx,
594 : struct be_req *be_req,
595 : struct sysdb_attrs *override_attrs,
596 : struct be_acct_req *ar)
597 : {
598 : errno_t ret;
599 : struct tevent_req *req;
600 : struct tevent_req *subreq;
601 : struct ipa_get_ad_acct_state *state;
602 : struct sdap_domain *sdom;
603 : struct sdap_id_conn_ctx **clist;
604 : struct sdap_id_ctx *sdap_id_ctx;;
605 : struct ad_id_ctx *ad_id_ctx;
606 :
607 0 : req = tevent_req_create(mem_ctx, &state, struct ipa_get_ad_acct_state);
608 0 : if (req == NULL) return NULL;
609 :
610 0 : state->dp_error = -1;
611 0 : state->ev = ev;
612 0 : state->ipa_ctx = ipa_ctx;
613 0 : state->be_req = be_req;
614 0 : state->ar = ar;
615 0 : state->obj_msg = NULL;
616 0 : state->override_attrs = override_attrs;
617 :
618 : /* This can only be a subdomain request, verify subdomain */
619 0 : state->obj_dom = find_domain_by_name(ipa_ctx->sdap_id_ctx->be->domain,
620 0 : ar->domain, true);
621 0 : if (state->obj_dom == NULL) {
622 0 : ret = EINVAL;
623 0 : goto fail;
624 : }
625 :
626 : /* Let's see if this subdomain has a ad_id_ctx */
627 0 : ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, state->obj_dom);
628 0 : if (ad_id_ctx == NULL) {
629 0 : ret = EINVAL;
630 0 : goto fail;
631 : }
632 0 : sdap_id_ctx = ad_id_ctx->sdap_id_ctx;
633 :
634 : /* We read users and groups from GC. From groups, we may switch to
635 : * using LDAP connection in the group request itself, but in order
636 : * to resolve Universal group memberships, we also need the GC
637 : * connection
638 : */
639 0 : switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
640 : case BE_REQ_INITGROUPS:
641 : case BE_REQ_BY_SECID:
642 : case BE_REQ_GROUP:
643 0 : clist = ad_gc_conn_list(req, ad_id_ctx, state->obj_dom);
644 0 : break;
645 : default:
646 0 : clist = ad_ldap_conn_list(req, ad_id_ctx, state->obj_dom);
647 0 : break;
648 : }
649 :
650 0 : if (clist == NULL) {
651 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot generate AD connection list!\n");
652 0 : ret = ENOMEM;
653 0 : goto fail;
654 : }
655 :
656 : /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */
657 0 : sdom = sdap_domain_get(sdap_id_ctx->opts, state->obj_dom);
658 0 : if (sdom == NULL) {
659 0 : ret = EIO;
660 0 : goto fail;
661 : }
662 :
663 0 : subreq = ad_handle_acct_info_send(req, be_req, ar, sdap_id_ctx,
664 : ad_id_ctx->ad_options, sdom, clist);
665 0 : if (subreq == NULL) {
666 0 : ret = ENOMEM;
667 0 : goto fail;
668 : }
669 0 : tevent_req_set_callback(subreq, ipa_get_ad_acct_ad_part_done, req);
670 0 : return req;
671 :
672 : fail:
673 0 : state->dp_error = DP_ERR_FATAL;
674 0 : tevent_req_error(req, ret);
675 0 : tevent_req_post(req, ev);
676 0 : return req;
677 : }
678 :
679 : static struct ad_id_ctx *
680 0 : ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
681 : struct sss_domain_info *dom)
682 : {
683 : struct ipa_ad_server_ctx *iter;
684 :
685 0 : DLIST_FOR_EACH(iter, ipa_ctx->server_mode->trusts) {
686 0 : if (iter->dom == dom) break;
687 : }
688 :
689 0 : return (iter) ? iter->ad_id_ctx : NULL;
690 : }
691 :
692 : static errno_t
693 0 : get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
694 : const char *fqname, uint32_t uid,
695 : const char *original, const char **_homedir)
696 : {
697 : errno_t ret;
698 : const char *name;
699 : const char *homedir;
700 : TALLOC_CTX *tmp_ctx;
701 : struct sss_nss_homedir_ctx homedir_ctx;
702 :
703 0 : tmp_ctx = talloc_new(mem_ctx);
704 0 : if (tmp_ctx == NULL) {
705 0 : ret = ENOMEM;
706 0 : goto done;
707 : }
708 :
709 0 : if (strstr(dom->subdomain_homedir, "%o") != NULL && original == NULL) {
710 0 : DEBUG(SSSDBG_TRACE_ALL,
711 : "Original home directory for user: %s is empty.\n", fqname);
712 0 : ret = ERR_HOMEDIR_IS_NULL;
713 0 : goto done;
714 : }
715 :
716 0 : ZERO_STRUCT(homedir_ctx);
717 :
718 0 : homedir_ctx.uid = uid;
719 0 : homedir_ctx.domain = dom->name;
720 0 : homedir_ctx.flatname = dom->flat_name;
721 0 : homedir_ctx.config_homedir_substr = dom->homedir_substr;
722 0 : homedir_ctx.original = original;
723 0 : ret = sss_parse_name_const(tmp_ctx, dom->names, fqname,
724 : NULL, &name);
725 0 : if (ret != EOK) {
726 0 : goto done;
727 : }
728 :
729 : /* To be compatible with the old winbind based user lookups and IPA
730 : * clients the user name in the home directory path will be lower-case. */
731 0 : homedir_ctx.username = sss_tc_utf8_str_tolower(tmp_ctx, name);
732 0 : if (homedir_ctx.username == NULL) {
733 0 : ret = ENOMEM;
734 0 : goto done;
735 : }
736 :
737 0 : homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir,
738 : &homedir_ctx);
739 0 : if (homedir == NULL) {
740 0 : DEBUG(SSSDBG_OP_FAILURE, "expand_homedir_template failed\n");
741 0 : ret = ENOMEM;
742 0 : goto done;
743 : }
744 :
745 0 : if (_homedir == NULL) {
746 0 : ret = EINVAL;
747 0 : goto done;
748 : }
749 0 : *_homedir = talloc_steal(mem_ctx, homedir);
750 :
751 : done:
752 0 : talloc_free(tmp_ctx);
753 0 : return ret;
754 : }
755 :
756 : static errno_t
757 0 : store_homedir_of_user(struct sss_domain_info *domain,
758 : const char *fqname, const char *homedir)
759 : {
760 : errno_t ret;
761 : errno_t sret;
762 : TALLOC_CTX *tmp_ctx;
763 0 : bool in_transaction = false;
764 : struct sysdb_attrs *attrs;
765 0 : struct sysdb_ctx *sysdb = domain->sysdb;
766 :
767 0 : tmp_ctx = talloc_new(NULL);
768 0 : if (tmp_ctx == NULL) {
769 0 : ret = ENOMEM;
770 0 : goto done;
771 : }
772 :
773 0 : attrs = sysdb_new_attrs(tmp_ctx);
774 0 : if (attrs == NULL) {
775 0 : ret = ENOMEM;
776 0 : goto done;
777 : }
778 :
779 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir);
780 0 : if (ret != EOK) {
781 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Error setting homedir: [%s]\n",
782 : strerror(ret));
783 0 : goto done;
784 : }
785 :
786 0 : ret = sysdb_transaction_start(sysdb);
787 0 : if (ret != EOK) {
788 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
789 0 : goto done;
790 : }
791 :
792 0 : in_transaction = true;
793 :
794 0 : ret = sysdb_set_user_attr(domain, fqname, attrs, SYSDB_MOD_REP);
795 0 : if (ret != EOK) {
796 0 : DEBUG(SSSDBG_CRIT_FAILURE,
797 : "Failed to update homedir information!\n");
798 0 : goto done;
799 : }
800 :
801 0 : ret = sysdb_transaction_commit(sysdb);
802 0 : if (ret != EOK) {
803 0 : DEBUG(SSSDBG_CRIT_FAILURE,
804 : "Cannot commit sysdb transaction [%d]: %s.\n",
805 : ret, strerror(ret));
806 0 : goto done;
807 : }
808 :
809 0 : in_transaction = false;
810 :
811 : done:
812 0 : if (in_transaction) {
813 0 : sret = sysdb_transaction_cancel(sysdb);
814 0 : if (sret != EOK) {
815 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction.\n");
816 : }
817 : }
818 0 : talloc_free(tmp_ctx);
819 0 : return ret;
820 : }
821 :
822 : static errno_t
823 0 : apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
824 : struct ldb_message *msg)
825 : {
826 : errno_t ret;
827 : uint32_t uid;
828 : const char *fqname;
829 : const char *original;
830 0 : const char *homedir = NULL;
831 0 : struct ldb_message_element *msg_el = NULL;
832 : size_t c;
833 :
834 0 : msg_el = ldb_msg_find_element(msg, SYSDB_OBJECTCLASS);
835 0 : if (msg_el == NULL) {
836 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_find_element failed.\n");
837 0 : ret = ENOENT;
838 0 : goto done;
839 : }
840 :
841 0 : for (c = 0; c < msg_el->num_values; c++) {
842 0 : if (strncmp(SYSDB_USER_CLASS, (const char *)msg_el->values[c].data,
843 0 : msg_el->values[c].length) == 0) {
844 0 : break;
845 : }
846 : }
847 0 : if (c == msg_el->num_values) {
848 0 : DEBUG(SSSDBG_TRACE_ALL,
849 : "User objectclass not found, object is not a user.\n");
850 0 : ret = ENOENT;
851 0 : goto done;
852 : }
853 :
854 0 : fqname = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
855 0 : if (fqname == NULL) {
856 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing user name.\n");
857 0 : ret = EINVAL;
858 0 : goto done;
859 : }
860 :
861 0 : uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
862 0 : if (uid == 0) {
863 0 : DEBUG(SSSDBG_OP_FAILURE, "UID for user [%s] is not known.\n",
864 : fqname);
865 0 : ret = ENOENT;
866 0 : goto done;
867 : }
868 :
869 0 : original = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
870 0 : if (original == NULL) {
871 0 : DEBUG(SSSDBG_TRACE_ALL, "Missing homedir of %s.\n", fqname);
872 : }
873 :
874 0 : ret = get_subdomain_homedir_of_user(mem_ctx, dom, fqname, uid, original,
875 : &homedir);
876 0 : if (ret != EOK) {
877 0 : DEBUG(SSSDBG_OP_FAILURE,
878 : "get_subdomain_homedir_of_user failed: [%d]: [%s]\n",
879 : ret, sss_strerror(ret));
880 0 : if (ret == ERR_HOMEDIR_IS_NULL) {
881 : /* This is not fatal, fallback_homedir will be used. */
882 0 : ret = EOK;
883 : }
884 0 : goto done;
885 : }
886 :
887 0 : ret = store_homedir_of_user(dom, fqname, homedir);
888 0 : if (ret != EOK) {
889 0 : DEBUG(SSSDBG_OP_FAILURE,
890 : "store_homedir_of_user failed: [%d]: [%s]\n",
891 : ret, sss_strerror(ret));
892 0 : goto done;
893 : }
894 :
895 : done:
896 0 : return ret;
897 : }
898 :
899 0 : errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
900 : struct sss_domain_info *dom,
901 : struct be_acct_req *ar,
902 : struct ldb_message **_msg)
903 : {
904 : errno_t ret;
905 : uint32_t id;
906 0 : struct ldb_message *msg = NULL;
907 0 : struct ldb_result *res = NULL;
908 0 : const char *attrs[] = { SYSDB_NAME,
909 : SYSDB_UIDNUM,
910 : SYSDB_SID_STR,
911 : SYSDB_OBJECTCLASS,
912 : SYSDB_UUID,
913 : SYSDB_GHOST,
914 : SYSDB_HOMEDIR,
915 : NULL };
916 : char *name;
917 :
918 0 : if (ar->filter_type == BE_FILTER_SECID) {
919 0 : ret = sysdb_search_object_by_sid(mem_ctx, dom, ar->filter_value, attrs,
920 : &res);
921 0 : if (ret != EOK) {
922 0 : DEBUG(SSSDBG_OP_FAILURE,
923 : "Failed to make request to our cache: [%d]: [%s]\n",
924 : ret, sss_strerror(ret));
925 0 : goto done;
926 : }
927 :
928 0 : *_msg = res->msgs[0];
929 :
930 0 : ret = EOK;
931 0 : goto done;
932 0 : } else if (ar->filter_type == BE_FILTER_UUID) {
933 0 : ret = sysdb_search_object_by_uuid(mem_ctx, dom, ar->filter_value, attrs,
934 : &res);
935 0 : if (ret != EOK) {
936 0 : DEBUG(SSSDBG_OP_FAILURE,
937 : "Failed to make request to our cache: [%d]: [%s]\n",
938 : ret, sss_strerror(ret));
939 0 : goto done;
940 : }
941 :
942 0 : *_msg = res->msgs[0];
943 :
944 0 : ret = EOK;
945 0 : goto done;
946 0 : } else if (ar->filter_type == BE_FILTER_CERT) {
947 0 : ret = sysdb_search_object_by_cert(mem_ctx, dom, ar->filter_value, attrs,
948 : &res);
949 0 : if (ret != EOK) {
950 0 : DEBUG(SSSDBG_OP_FAILURE,
951 : "Failed to make request to our cache: [%d]: [%s]\n",
952 : ret, sss_strerror(ret));
953 0 : goto done;
954 : }
955 :
956 0 : *_msg = res->msgs[0];
957 :
958 0 : ret = EOK;
959 0 : goto done;
960 0 : } else if (ar->filter_type == BE_FILTER_IDNUM) {
961 0 : errno = 0;
962 0 : id = strtouint32(ar->filter_value, NULL, 10);
963 0 : if (errno != 0) {
964 0 : ret = errno;
965 0 : DEBUG(SSSDBG_OP_FAILURE, "strtouint32 failed.\n");
966 0 : goto done;
967 : }
968 :
969 0 : switch (ar->entry_type & BE_REQ_TYPE_MASK) {
970 : case BE_REQ_GROUP:
971 0 : ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg);
972 0 : break;
973 : case BE_REQ_INITGROUPS:
974 : case BE_REQ_USER:
975 : case BE_REQ_USER_AND_GROUP:
976 0 : ret = sysdb_search_user_by_uid(mem_ctx, dom, id, attrs, &msg);
977 0 : if (ret == ENOENT && (ar->entry_type & BE_REQ_TYPE_MASK)
978 : == BE_REQ_USER_AND_GROUP) {
979 0 : ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg);
980 : }
981 0 : break;
982 : default:
983 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d].\n",
984 : (ar->entry_type & BE_REQ_TYPE_MASK));
985 0 : ret = EINVAL;
986 0 : goto done;
987 : }
988 0 : } else if (ar->filter_type == BE_FILTER_NAME) {
989 0 : name = sss_get_domain_name(mem_ctx, ar->filter_value, dom);
990 0 : if (name == NULL) {
991 0 : DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_name failed\n");
992 0 : ret = ENOMEM;
993 0 : goto done;
994 : }
995 :
996 0 : switch (ar->entry_type & BE_REQ_TYPE_MASK) {
997 : case BE_REQ_GROUP:
998 0 : ret = sysdb_search_group_by_name(mem_ctx, dom, name, attrs, &msg);
999 0 : break;
1000 : case BE_REQ_INITGROUPS:
1001 : case BE_REQ_USER:
1002 : case BE_REQ_USER_AND_GROUP:
1003 0 : ret = sysdb_search_user_by_name(mem_ctx, dom, name, attrs, &msg);
1004 0 : if (ret == ENOENT && (ar->entry_type & BE_REQ_TYPE_MASK)
1005 : == BE_REQ_USER_AND_GROUP) {
1006 0 : ret = sysdb_search_group_by_name(mem_ctx, dom, name,
1007 : attrs, &msg);
1008 : }
1009 0 : break;
1010 : default:
1011 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d].\n",
1012 : (ar->entry_type & BE_REQ_TYPE_MASK));
1013 0 : ret = EINVAL;
1014 0 : goto done;
1015 : }
1016 : } else {
1017 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected filter type.\n");
1018 0 : ret = EINVAL;
1019 0 : goto done;
1020 : }
1021 :
1022 0 : if (ret != EOK && ret != ENOENT) {
1023 0 : DEBUG(SSSDBG_OP_FAILURE,
1024 : "Failed to make request to our cache: [%d]: [%s]\n",
1025 : ret, sss_strerror(ret));
1026 0 : goto done;
1027 : }
1028 :
1029 0 : *_msg = msg;
1030 :
1031 : done:
1032 0 : return ret;
1033 : }
1034 :
1035 : static void
1036 0 : ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
1037 : {
1038 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1039 : struct tevent_req);
1040 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1041 : struct ipa_get_ad_acct_state);
1042 : errno_t ret;
1043 : const char *sid;
1044 : struct be_acct_req *ar;
1045 :
1046 0 : ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
1047 0 : talloc_zfree(subreq);
1048 0 : if (ret == ERR_SUBDOM_INACTIVE) {
1049 0 : tevent_req_error(req, ret);
1050 0 : return;
1051 0 : } else if (ret != EOK) {
1052 0 : DEBUG(SSSDBG_OP_FAILURE, "AD lookup failed: %d\n", ret);
1053 0 : tevent_req_error(req, ret);
1054 0 : return;
1055 : }
1056 :
1057 0 : ret = get_object_from_cache(state, state->obj_dom, state->ar,
1058 : &state->obj_msg);
1059 0 : if (ret == ENOENT) {
1060 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
1061 0 : tevent_req_done(req);
1062 0 : return;
1063 0 : } else if (ret != EOK) {
1064 0 : DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
1065 0 : goto fail;
1066 : }
1067 :
1068 0 : ret = apply_subdomain_homedir(state, state->obj_dom,
1069 : state->obj_msg);
1070 0 : if (ret != EOK && ret != ENOENT) {
1071 0 : DEBUG(SSSDBG_OP_FAILURE,
1072 : "apply_subdomain_homedir failed: [%d]: [%s].\n",
1073 : ret, sss_strerror(ret));
1074 0 : goto fail;
1075 : }
1076 :
1077 0 : if (state->override_attrs == NULL) {
1078 0 : sid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_SID_STR, NULL);
1079 0 : if (sid == NULL) {
1080 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a SID.\n");
1081 0 : ret = EINVAL;
1082 0 : goto fail;
1083 : }
1084 :
1085 0 : state->object_sid = talloc_strdup(state, sid);
1086 0 : if (state->object_sid == NULL) {
1087 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
1088 0 : ret = ENOMEM;
1089 0 : goto fail;
1090 : }
1091 :
1092 0 : ret = get_be_acct_req_for_sid(state, state->object_sid,
1093 0 : state->obj_dom->name, &ar);
1094 0 : if (ret != EOK) {
1095 0 : DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
1096 0 : goto fail;
1097 : }
1098 :
1099 0 : subreq = ipa_get_ad_override_send(state, state->ev,
1100 0 : state->ipa_ctx->sdap_id_ctx,
1101 0 : state->ipa_ctx->ipa_options,
1102 0 : state->ipa_ctx->server_mode->realm,
1103 0 : state->ipa_ctx->view_name,
1104 : ar);
1105 0 : if (subreq == NULL) {
1106 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
1107 0 : ret = ENOMEM;
1108 0 : goto fail;
1109 : }
1110 0 : tevent_req_set_callback(subreq, ipa_get_ad_override_done, req);
1111 : } else {
1112 0 : ret = ipa_get_ad_apply_override_step(req);
1113 0 : if (ret != EOK) {
1114 0 : DEBUG(SSSDBG_OP_FAILURE,
1115 : "ipa_get_ad_apply_override_step failed.\n");
1116 0 : goto fail;
1117 : }
1118 : }
1119 :
1120 0 : return;
1121 :
1122 : fail:
1123 0 : state->dp_error = DP_ERR_FATAL;
1124 0 : tevent_req_error(req, ret);
1125 0 : return;
1126 : }
1127 :
1128 :
1129 : static void
1130 0 : ipa_get_ad_override_done(struct tevent_req *subreq)
1131 : {
1132 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1133 : struct tevent_req);
1134 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1135 : struct ipa_get_ad_acct_state);
1136 : errno_t ret;
1137 :
1138 0 : ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state,
1139 : &state->override_attrs);
1140 0 : talloc_zfree(subreq);
1141 0 : if (ret != EOK) {
1142 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
1143 0 : tevent_req_error(req, ret);
1144 0 : return;
1145 :
1146 : }
1147 :
1148 0 : ret = ipa_get_ad_apply_override_step(req);
1149 0 : if (ret != EOK) {
1150 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_apply_override_step failed.\n");
1151 0 : goto fail;
1152 : }
1153 :
1154 0 : return;
1155 :
1156 : fail:
1157 0 : state->dp_error = DP_ERR_FATAL;
1158 0 : tevent_req_error(req, ret);
1159 0 : return;
1160 : }
1161 :
1162 0 : static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
1163 : {
1164 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1165 : struct ipa_get_ad_acct_state);
1166 : errno_t ret;
1167 : struct tevent_req *subreq;
1168 : const char *obj_name;
1169 : int entry_type;
1170 0 : size_t groups_count = 0;
1171 0 : struct ldb_message **groups = NULL;
1172 0 : const char *attrs[] = SYSDB_INITGR_ATTRS;
1173 :
1174 0 : if (state->override_attrs != NULL) {
1175 : /* We are in ipa-server-mode, so the view is the default view by
1176 : * definition. */
1177 0 : ret = sysdb_apply_default_override(state->obj_dom,
1178 : state->override_attrs,
1179 0 : state->obj_msg->dn);
1180 0 : if (ret != EOK) {
1181 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_apply_default_override failed.\n");
1182 0 : return ret;
1183 : }
1184 : }
1185 :
1186 0 : entry_type = (state->ar->entry_type & BE_REQ_TYPE_MASK);
1187 0 : if (entry_type != BE_REQ_INITGROUPS
1188 0 : && entry_type != BE_REQ_USER
1189 0 : && entry_type != BE_REQ_BY_SECID) {
1190 0 : tevent_req_done(req);
1191 0 : return EOK;
1192 : }
1193 :
1194 : /* Replace ID with name in search filter */
1195 0 : if ((entry_type == BE_REQ_USER && state->ar->filter_type == BE_FILTER_IDNUM)
1196 0 : || (entry_type == BE_REQ_INITGROUPS
1197 0 : && state->ar->filter_type == BE_FILTER_SECID)
1198 0 : || entry_type == BE_REQ_BY_SECID) {
1199 0 : if (state->obj_msg == NULL) {
1200 0 : ret = get_object_from_cache(state, state->obj_dom, state->ar,
1201 : &state->obj_msg);
1202 0 : if (ret == ENOENT) {
1203 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1204 : "Object not found, ending request\n");
1205 0 : tevent_req_done(req);
1206 0 : return EOK;
1207 0 : } else if (ret != EOK) {
1208 0 : DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
1209 0 : return ret;
1210 : }
1211 : }
1212 :
1213 0 : obj_name = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_NAME,
1214 : NULL);
1215 0 : if (obj_name == NULL) {
1216 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cached object has no name.\n");
1217 0 : return EINVAL;
1218 : }
1219 :
1220 0 : state->ar->filter_value = talloc_strdup(state->ar, obj_name);
1221 0 : if (state->ar->filter_value == NULL) {
1222 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
1223 0 : return ENOMEM;
1224 : }
1225 0 : state->ar->filter_type = BE_FILTER_NAME;
1226 0 : state->ar->entry_type = BE_REQ_USER;
1227 : }
1228 :
1229 : /* Lookup all groups the user is a member of which do not have ORIGINALAD
1230 : * attributes set, i.e. where overrides might not have been applied. */
1231 0 : ret = sysdb_asq_search(state, state->obj_dom, state->obj_msg->dn,
1232 : "(&("SYSDB_GC")("SYSDB_GIDNUM"=*)" \
1233 : "(!("ORIGINALAD_PREFIX SYSDB_GIDNUM"=*))" \
1234 : "(!("ORIGINALAD_PREFIX SYSDB_NAME"=*)))",
1235 : SYSDB_INITGR_ATTR,
1236 : attrs, &groups_count, &groups);
1237 0 : if (ret != EOK) {
1238 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_groups_without_orig failed.\n");
1239 0 : return ret;
1240 : }
1241 :
1242 0 : if (groups != NULL) {
1243 0 : subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
1244 : state->obj_dom, groups_count,
1245 : groups, SYSDB_SID_STR);
1246 0 : if (subreq == NULL) {
1247 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_initgr_get_overrides_send failed.\n");
1248 0 : return ENOMEM;
1249 : }
1250 0 : tevent_req_set_callback(subreq, ipa_id_get_groups_overrides_done, req);
1251 0 : return EOK;
1252 : }
1253 :
1254 0 : ret = ipa_get_ad_ipa_membership_step(req);
1255 0 : if (ret != EOK) {
1256 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_ipa_membership_step failed.\n");
1257 0 : return ret;
1258 : }
1259 :
1260 0 : return EOK;
1261 : }
1262 :
1263 0 : static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq)
1264 : {
1265 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1266 : struct tevent_req);
1267 : errno_t ret;
1268 :
1269 0 : ret = ipa_initgr_get_overrides_recv(subreq, NULL);
1270 0 : talloc_zfree(subreq);
1271 0 : if (ret != EOK) {
1272 0 : DEBUG(SSSDBG_OP_FAILURE,
1273 : "IPA resolve user groups overrides failed [%d].\n", ret);
1274 0 : tevent_req_error(req, ret);
1275 0 : return;
1276 : }
1277 :
1278 0 : ret = ipa_get_ad_ipa_membership_step(req);
1279 0 : if (ret != EOK) {
1280 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_ipa_membership_step failed.\n");
1281 0 : tevent_req_error(req, ret);
1282 0 : return;
1283 : }
1284 :
1285 0 : return;
1286 : }
1287 :
1288 0 : static errno_t ipa_get_ad_ipa_membership_step(struct tevent_req *req)
1289 : {
1290 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1291 : struct ipa_get_ad_acct_state);
1292 : struct tevent_req *subreq;
1293 :
1294 : /* For initgroups request we have to check IPA group memberships of AD
1295 : * users. This has to be done for other user-request as well to make sure
1296 : * IPA related attributes are not overwritten. */
1297 0 : subreq = ipa_get_ad_memberships_send(state, state->ev, state->ar,
1298 0 : state->ipa_ctx->server_mode,
1299 : state->obj_dom,
1300 0 : state->ipa_ctx->sdap_id_ctx,
1301 0 : state->ipa_ctx->server_mode->realm);
1302 0 : if (subreq == NULL) {
1303 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_memberships_send failed.\n");
1304 0 : return ENOMEM;
1305 : }
1306 0 : tevent_req_set_callback(subreq, ipa_get_ad_acct_done, req);
1307 :
1308 0 : return EOK;
1309 : }
1310 :
1311 : static void
1312 0 : ipa_get_ad_acct_done(struct tevent_req *subreq)
1313 : {
1314 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1315 : struct tevent_req);
1316 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1317 : struct ipa_get_ad_acct_state);
1318 : errno_t ret;
1319 :
1320 0 : ret = ipa_get_ad_memberships_recv(subreq, &state->dp_error);
1321 0 : talloc_zfree(subreq);
1322 0 : if (ret != EOK) {
1323 0 : DEBUG(SSSDBG_OP_FAILURE, "IPA external groups lookup failed: %d\n",
1324 : ret);
1325 0 : tevent_req_error(req, ret);
1326 0 : return;
1327 :
1328 : }
1329 :
1330 0 : tevent_req_done(req);
1331 : }
1332 :
1333 : static errno_t
1334 0 : ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
1335 : {
1336 0 : struct ipa_get_ad_acct_state *state = tevent_req_data(req,
1337 : struct ipa_get_ad_acct_state);
1338 :
1339 0 : if (dp_error_out) {
1340 0 : *dp_error_out = state->dp_error;
1341 : }
1342 :
1343 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1344 :
1345 0 : return EOK;
1346 : }
1347 :
1348 : struct ipa_srv_ad_acct_state {
1349 : struct tevent_context *ev;
1350 : struct ipa_id_ctx *ipa_ctx;
1351 : struct be_req *be_req;
1352 : struct sysdb_attrs *override_attrs;
1353 : struct be_acct_req *ar;
1354 :
1355 : struct sss_domain_info *obj_dom;
1356 : struct be_ctx *be_ctx;
1357 : bool retry;
1358 :
1359 : int dp_error;
1360 : };
1361 :
1362 : static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req);
1363 : static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq);
1364 : static void ipa_srv_ad_acct_retried(struct tevent_req *subreq);
1365 :
1366 : static struct tevent_req *
1367 0 : ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx,
1368 : struct tevent_context *ev,
1369 : struct ipa_id_ctx *ipa_ctx,
1370 : struct be_req *be_req,
1371 : struct sysdb_attrs *override_attrs,
1372 : struct be_acct_req *ar)
1373 : {
1374 : errno_t ret;
1375 : struct tevent_req *req;
1376 : struct ipa_srv_ad_acct_state *state;
1377 :
1378 0 : req = tevent_req_create(mem_ctx, &state, struct ipa_srv_ad_acct_state);
1379 0 : if (req == NULL) {
1380 0 : return NULL;
1381 : }
1382 :
1383 0 : state->ev = ev;
1384 0 : state->ipa_ctx = ipa_ctx;
1385 0 : state->be_req = be_req;
1386 0 : state->override_attrs = override_attrs;
1387 0 : state->ar = ar;
1388 0 : state->retry = true;
1389 0 : state->dp_error = DP_ERR_FATAL;
1390 0 : state->be_ctx = be_req_get_be_ctx(state->be_req);
1391 :
1392 0 : state->obj_dom = find_domain_by_name(
1393 0 : state->ipa_ctx->sdap_id_ctx->be->domain,
1394 0 : state->ar->domain, true);
1395 0 : if (state->obj_dom == NULL) {
1396 0 : DEBUG(SSSDBG_OP_FAILURE, "Domain not found\n");
1397 0 : ret = ERR_DOMAIN_NOT_FOUND;
1398 0 : goto fail;
1399 : }
1400 :
1401 0 : ret = ipa_srv_ad_acct_lookup_step(req);
1402 0 : if (ret != EOK) {
1403 0 : goto fail;
1404 : }
1405 :
1406 0 : return req;
1407 :
1408 : fail:
1409 0 : tevent_req_error(req, ret);
1410 0 : tevent_req_post(req, ev);
1411 0 : return req;
1412 : }
1413 :
1414 0 : static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req)
1415 : {
1416 : struct tevent_req *subreq;
1417 0 : struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
1418 : struct ipa_srv_ad_acct_state);
1419 :
1420 0 : DEBUG(SSSDBG_TRACE_FUNC, "Looking up AD account\n");
1421 0 : subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx,
1422 : state->be_req, state->override_attrs,
1423 : state->ar);
1424 0 : if (subreq == NULL) {
1425 0 : return ENOMEM;
1426 : }
1427 0 : tevent_req_set_callback(subreq, ipa_srv_ad_acct_lookup_done, req);
1428 :
1429 0 : return EOK;
1430 : }
1431 :
1432 0 : static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq)
1433 : {
1434 : errno_t ret;
1435 0 : int dp_error = DP_ERR_FATAL;
1436 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1437 : struct tevent_req);
1438 0 : struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
1439 : struct ipa_srv_ad_acct_state);
1440 :
1441 0 : ret = ipa_get_ad_acct_recv(subreq, &dp_error);
1442 0 : talloc_free(subreq);
1443 0 : if (ret == ERR_SUBDOM_INACTIVE && state->retry == true) {
1444 :
1445 0 : state->retry = false;
1446 :
1447 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1448 : "Sudomain lookup failed, will try to reset sudomain..\n");
1449 0 : subreq = ipa_server_trusted_dom_setup_send(state, state->ev,
1450 : state->be_ctx,
1451 : state->ipa_ctx,
1452 : state->obj_dom);
1453 0 : if (subreq == NULL) {
1454 0 : goto fail;
1455 : }
1456 0 : tevent_req_set_callback(subreq, ipa_srv_ad_acct_retried, req);
1457 0 : return;
1458 0 : } else if (ret != EOK) {
1459 0 : be_mark_dom_offline(state->obj_dom, state->be_ctx);
1460 :
1461 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n",
1462 : ret, sss_strerror(ret));
1463 0 : goto fail;
1464 : }
1465 :
1466 0 : state->dp_error = DP_ERR_OK;
1467 0 : tevent_req_done(req);
1468 0 : return;
1469 :
1470 : fail:
1471 0 : state->dp_error = dp_error;
1472 0 : tevent_req_error(req, ret);
1473 : }
1474 :
1475 0 : static void ipa_srv_ad_acct_retried(struct tevent_req *subreq)
1476 : {
1477 : errno_t ret;
1478 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
1479 : struct tevent_req);
1480 0 : struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
1481 : struct ipa_srv_ad_acct_state);
1482 :
1483 0 : ret = ipa_server_trusted_dom_setup_recv(subreq);
1484 0 : talloc_free(subreq);
1485 0 : if (ret != EOK) {
1486 0 : DEBUG(SSSDBG_OP_FAILURE,
1487 : "Failed to re-set subdomain [%d]: %s\n", ret, sss_strerror(ret));
1488 0 : state->dp_error = DP_ERR_FATAL;
1489 0 : tevent_req_error(req, ret);
1490 : }
1491 :
1492 0 : DEBUG(SSSDBG_TRACE_FUNC, "Sudomain re-set, will retry lookup\n");
1493 0 : be_fo_reset_svc(state->be_ctx, state->obj_dom->name);
1494 :
1495 0 : ret = ipa_srv_ad_acct_lookup_step(req);
1496 0 : if (ret != EOK) {
1497 0 : DEBUG(SSSDBG_OP_FAILURE,
1498 : "Failed to look up AD acct [%d]: %s\n", ret, sss_strerror(ret));
1499 0 : state->dp_error = DP_ERR_FATAL;
1500 0 : tevent_req_error(req, ret);
1501 : }
1502 0 : }
1503 :
1504 : static errno_t
1505 0 : ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
1506 : {
1507 0 : struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
1508 : struct ipa_srv_ad_acct_state);
1509 :
1510 0 : if (dp_error_out) {
1511 0 : *dp_error_out = state->dp_error;
1512 : }
1513 :
1514 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1515 0 : return EOK;
1516 : }
|