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