Line data Source code
1 : /*
2 : SSSD
3 :
4 : AD Subdomains Module
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2013 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 "providers/ldap/sdap_async.h"
26 : #include "providers/ad/ad_subdomains.h"
27 : #include "providers/ad/ad_domain_info.h"
28 : #include "providers/ad/ad_srv.h"
29 : #include "providers/ad/ad_common.h"
30 :
31 : #include "providers/ldap/sdap_idmap.h"
32 : #include "util/util_sss_idmap.h"
33 : #include <ctype.h>
34 : #include <ndr.h>
35 : #include <ndr/ndr_nbt.h>
36 :
37 : /* Attributes of AD trusted domains */
38 : #define AD_AT_FLATNAME "flatName"
39 : #define AD_AT_SID "securityIdentifier"
40 : #define AD_AT_TRUST_TYPE "trustType"
41 : #define AD_AT_TRUST_PARTNER "trustPartner"
42 : #define AD_AT_TRUST_ATTRS "trustAttributes"
43 :
44 : /* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
45 : * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx
46 : * for example.
47 : *
48 : * The absence of msDS-TrustForestTrustInfo attribute denotes a domain from
49 : * the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
50 : * for more information.
51 : */
52 : #define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
53 : #define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")"
54 : #define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
55 :
56 : /* do not refresh more often than every 5 seconds for now */
57 : #define AD_SUBDOMAIN_REFRESH_LIMIT 5
58 :
59 : struct ad_subdomains_ctx {
60 : struct be_ctx *be_ctx;
61 : struct sdap_id_ctx *sdap_id_ctx;
62 : struct sdap_domain *sdom;
63 : struct sdap_id_conn_ctx *ldap_ctx;
64 : struct sss_idmap_ctx *idmap_ctx;
65 : char *domain_name;
66 :
67 : time_t last_refreshed;
68 : struct tevent_timer *timer_event;
69 : struct ad_id_ctx *ad_id_ctx;
70 : };
71 :
72 : struct ad_subdomains_req_ctx {
73 : struct be_req *be_req;
74 : struct ad_subdomains_ctx *sd_ctx;
75 : struct sdap_id_op *sdap_op;
76 :
77 : char *current_filter;
78 : size_t base_iter;
79 :
80 : struct ad_id_ctx *root_id_ctx;
81 : struct sdap_id_op *root_op;
82 : size_t root_base_iter;
83 : struct sysdb_attrs *root_domain_attrs;
84 : struct sss_domain_info *root_domain;
85 :
86 : size_t reply_count;
87 : struct sysdb_attrs **reply;
88 :
89 : char *master_sid;
90 : char *flat_name;
91 : char *site;
92 : char *forest;
93 : };
94 :
95 : static errno_t
96 0 : ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
97 : struct ad_id_ctx *id_ctx,
98 : struct sss_domain_info *subdom,
99 : struct ad_id_ctx **_subdom_id_ctx)
100 : {
101 : struct ad_options *ad_options;
102 : struct ad_id_ctx *ad_id_ctx;
103 : const char *gc_service_name;
104 : struct ad_srv_plugin_ctx *srv_ctx;
105 : char *ad_domain;
106 : char *ad_site_override;
107 : struct sdap_domain *sdom;
108 : errno_t ret;
109 : const char *realm;
110 : const char *hostname;
111 :
112 0 : realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
113 0 : hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
114 0 : ad_domain = subdom->name;
115 0 : if (realm == NULL || hostname == NULL || ad_domain == NULL) {
116 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm or hostname.\n");
117 0 : return EINVAL;
118 : }
119 :
120 0 : ad_options = ad_create_2way_trust_options(id_ctx, realm,
121 : ad_domain, hostname);
122 0 : if (ad_options == NULL) {
123 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
124 0 : talloc_free(ad_options);
125 0 : return ENOMEM;
126 : }
127 :
128 0 : ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
129 :
130 0 : gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
131 0 : if (gc_service_name == NULL) {
132 0 : talloc_free(ad_options);
133 0 : return ENOMEM;
134 : }
135 :
136 0 : ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
137 0 : subdom->name, gc_service_name,
138 0 : subdom->name, &ad_options->service);
139 0 : if (ret != EOK) {
140 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
141 0 : talloc_free(ad_options);
142 0 : return ret;
143 : }
144 :
145 0 : ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
146 0 : if (ad_id_ctx == NULL) {
147 0 : talloc_free(ad_options);
148 0 : return ENOMEM;
149 : }
150 0 : ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
151 0 : ad_options->id_ctx = ad_id_ctx;
152 :
153 : /* use AD plugin */
154 0 : srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
155 : default_host_dbs,
156 0 : ad_id_ctx->ad_options->id,
157 : hostname,
158 : ad_domain,
159 : ad_site_override);
160 0 : if (srv_ctx == NULL) {
161 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
162 0 : return ENOMEM;
163 : }
164 0 : be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
165 : ad_srv_plugin_recv, srv_ctx, "AD");
166 :
167 0 : ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
168 0 : ad_id_ctx->sdap_id_ctx->opts->sdom,
169 : subdom->parent);
170 0 : if (ret != EOK) {
171 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
172 0 : talloc_free(ad_options);
173 0 : return ret;
174 : }
175 :
176 0 : sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
177 0 : if (sdom == NULL) {
178 0 : return EFAULT;
179 : }
180 :
181 0 : sdap_inherit_options(subdom->parent->sd_inherit,
182 0 : id_ctx->sdap_id_ctx->opts,
183 0 : ad_id_ctx->sdap_id_ctx->opts);
184 :
185 : /* Set up the ID mapping object */
186 0 : ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
187 0 : id_ctx->sdap_id_ctx->opts->idmap_ctx;
188 :
189 0 : *_subdom_id_ctx = ad_id_ctx;
190 0 : return EOK;
191 : }
192 :
193 : static errno_t
194 0 : ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
195 : struct sss_domain_info *parent)
196 : {
197 : int ret;
198 : struct sdap_domain *sditer;
199 : struct ad_id_ctx *subdom_id_ctx;
200 :
201 0 : ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
202 0 : if (ret != EOK) {
203 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_domain_subdom_add failed.\n");
204 0 : return ret;
205 : }
206 :
207 0 : DLIST_FOR_EACH(sditer, ctx->sdom) {
208 0 : if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
209 0 : ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
210 : sditer->dom, &subdom_id_ctx);
211 0 : if (ret != EOK) {
212 0 : DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
213 : } else {
214 0 : sditer->pvt = subdom_id_ctx;
215 : }
216 : }
217 : }
218 :
219 0 : return EOK;
220 : }
221 :
222 0 : static errno_t ad_subdom_enumerates(struct sss_domain_info *parent,
223 : struct sysdb_attrs *attrs,
224 : bool *_enumerates)
225 : {
226 : errno_t ret;
227 : const char *name;
228 :
229 0 : ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
230 0 : if (ret != EOK) {
231 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
232 0 : return ret;
233 : }
234 :
235 0 : *_enumerates = subdomain_enumerates(parent, name);
236 0 : return EOK;
237 : }
238 :
239 : static errno_t
240 0 : ad_subdom_store(struct ad_subdomains_ctx *ctx,
241 : struct sss_domain_info *domain,
242 : struct sysdb_attrs *subdom_attrs,
243 : bool enumerate)
244 : {
245 : TALLOC_CTX *tmp_ctx;
246 : const char *name;
247 : char *realm;
248 : const char *flat;
249 : errno_t ret;
250 : enum idmap_error_code err;
251 : struct ldb_message_element *el;
252 0 : char *sid_str = NULL;
253 : uint32_t trust_type;
254 : bool mpg;
255 :
256 0 : tmp_ctx = talloc_new(NULL);
257 0 : if (tmp_ctx == NULL) {
258 0 : ret = ENOMEM;
259 0 : goto done;
260 : }
261 :
262 0 : ret = sysdb_attrs_get_uint32_t(subdom_attrs, AD_AT_TRUST_TYPE,
263 : &trust_type);
264 0 : if (ret != EOK) {
265 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_uint32_t failed.\n");
266 0 : goto done;
267 : }
268 :
269 0 : ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_TRUST_PARTNER, &name);
270 0 : if (ret != EOK) {
271 0 : DEBUG(SSSDBG_OP_FAILURE, "failed to get subdomain name\n");
272 0 : goto done;
273 : }
274 :
275 0 : realm = get_uppercase_realm(tmp_ctx, name);
276 0 : if (!realm) {
277 0 : ret = ENOMEM;
278 0 : goto done;
279 : }
280 :
281 0 : ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_FLATNAME, &flat);
282 0 : if (ret) {
283 0 : DEBUG(SSSDBG_OP_FAILURE, "failed to get flat name of subdomain %s\n",
284 : name);
285 0 : goto done;
286 : }
287 :
288 0 : ret = sysdb_attrs_get_el(subdom_attrs, AD_AT_SID, &el);
289 0 : if (ret != EOK || el->num_values != 1) {
290 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_attrs_get_el failed.\n");
291 0 : goto done;
292 : }
293 :
294 0 : err = sss_idmap_bin_sid_to_sid(ctx->idmap_ctx,
295 0 : el->values[0].data,
296 0 : el->values[0].length,
297 : &sid_str);
298 0 : if (err != IDMAP_SUCCESS) {
299 0 : DEBUG(SSSDBG_MINOR_FAILURE,
300 : "Could not convert SID: [%s].\n", idmap_error_string(err));
301 0 : ret = EFAULT;
302 0 : goto done;
303 : }
304 :
305 0 : mpg = sdap_idmap_domain_has_algorithmic_mapping(
306 0 : ctx->sdap_id_ctx->opts->idmap_ctx,
307 : name,
308 : sid_str);
309 :
310 0 : ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
311 0 : mpg, enumerate, domain->forest, 0);
312 0 : if (ret != EOK) {
313 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
314 0 : goto done;
315 : }
316 :
317 0 : ret = EOK;
318 : done:
319 0 : sss_idmap_free_sid(ctx->sdap_id_ctx->opts->idmap_ctx->map, sid_str);
320 0 : talloc_free(tmp_ctx);
321 :
322 0 : return ret;
323 : }
324 :
325 0 : static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx,
326 : int count, bool root_domain,
327 : struct sysdb_attrs **reply,
328 : bool *changes)
329 0 : {
330 : struct sdap_domain *sdom;
331 : struct sss_domain_info *domain, *dom;
332 0 : bool handled[count];
333 : const char *value;
334 0 : const char *root_name = NULL;
335 : int c, h;
336 : int ret;
337 : bool enumerate;
338 :
339 0 : domain = ctx->be_ctx->domain;
340 0 : memset(handled, 0, sizeof(bool) * count);
341 0 : h = 0;
342 :
343 0 : if (root_domain) {
344 0 : ret = sysdb_attrs_get_string(reply[0], AD_AT_TRUST_PARTNER,
345 : &root_name);
346 0 : if (ret != EOK) {
347 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
348 0 : goto done;
349 : }
350 : }
351 :
352 : /* check existing subdomains */
353 0 : for (dom = get_next_domain(domain, true);
354 0 : dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
355 0 : dom = get_next_domain(dom, false)) {
356 :
357 : /* If we are handling root domain, skip all the other domains. We don't
358 : * want to accidentally remove non-root domains
359 : */
360 0 : if (root_name && strcmp(root_name, dom->name) != 0) {
361 0 : continue;
362 : }
363 :
364 0 : for (c = 0; c < count; c++) {
365 0 : if (handled[c]) {
366 0 : continue;
367 : }
368 0 : ret = sysdb_attrs_get_string(reply[c], AD_AT_TRUST_PARTNER, &value);
369 0 : if (ret != EOK) {
370 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
371 0 : goto done;
372 : }
373 0 : if (strcmp(value, dom->name) == 0) {
374 0 : break;
375 : }
376 : }
377 :
378 0 : if (c >= count) {
379 : /* ok this subdomain does not exist anymore, let's clean up */
380 0 : sss_domain_set_state(dom, DOM_DISABLED);
381 0 : ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
382 0 : if (ret != EOK) {
383 0 : goto done;
384 : }
385 :
386 0 : sdom = sdap_domain_get(ctx->sdap_id_ctx->opts, dom);
387 0 : if (sdom == NULL) {
388 0 : DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Domain does not exist?\n");
389 0 : continue;
390 : }
391 :
392 : /* Remove the subdomain from the list of LDAP domains */
393 0 : sdap_domain_remove(ctx->sdap_id_ctx->opts, dom);
394 :
395 0 : be_ptask_destroy(&sdom->enum_task);
396 0 : be_ptask_destroy(&sdom->cleanup_task);
397 :
398 : /* terminate all requests for this subdomain so we can free it */
399 0 : be_terminate_domain_requests(ctx->be_ctx, dom->name);
400 0 : talloc_zfree(sdom);
401 : } else {
402 : /* ok let's try to update it */
403 0 : ret = ad_subdom_enumerates(domain, reply[c], &enumerate);
404 0 : if (ret != EOK) {
405 0 : goto done;
406 : }
407 :
408 0 : ret = ad_subdom_store(ctx, domain, reply[c], enumerate);
409 0 : if (ret) {
410 : /* Nothing we can do about the error. Let's at least try
411 : * to reuse the existing domains
412 : */
413 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
414 : "will try to use cached subdomain\n");
415 : }
416 0 : handled[c] = true;
417 0 : h++;
418 : }
419 : }
420 :
421 0 : if (count == h) {
422 : /* all domains were already accounted for and have been updated */
423 0 : ret = EOK;
424 0 : *changes = false;
425 0 : goto done;
426 : }
427 :
428 : /* if we get here it means we have changes to the subdomains list */
429 0 : *changes = true;
430 :
431 0 : for (c = 0; c < count; c++) {
432 0 : if (handled[c]) {
433 0 : continue;
434 : }
435 : /* Nothing we can do about the error. Let's at least try
436 : * to reuse the existing domains.
437 : */
438 0 : ret = ad_subdom_enumerates(domain, reply[c], &enumerate);
439 0 : if (ret != EOK) {
440 0 : goto done;
441 : }
442 :
443 0 : ret = ad_subdom_store(ctx, domain, reply[c], enumerate);
444 0 : if (ret) {
445 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
446 : "will try to use cached subdomain\n");
447 : }
448 : }
449 :
450 0 : ret = EOK;
451 :
452 : done:
453 0 : if (ret != EOK) {
454 0 : ctx->last_refreshed = 0;
455 : } else {
456 0 : ctx->last_refreshed = time(NULL);
457 : }
458 :
459 0 : return ret;
460 : }
461 :
462 0 : static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx)
463 : {
464 : errno_t ret;
465 :
466 0 : ret = sss_write_krb5_conf_snippet(
467 0 : dp_opt_get_string(ctx->ad_id_ctx->ad_options->basic,
468 : AD_KRB5_CONFD_PATH));
469 0 : if (ret != EOK) {
470 0 : DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
471 : /* Just continue */
472 : }
473 :
474 0 : ret = sysdb_update_subdomains(ctx->be_ctx->domain);
475 0 : if (ret != EOK) {
476 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
477 0 : return ret;
478 : }
479 :
480 0 : ret = sss_write_domain_mappings(ctx->be_ctx->domain);
481 0 : if (ret != EOK) {
482 0 : DEBUG(SSSDBG_MINOR_FAILURE, "sss_krb5_write_mappings failed.\n");
483 : /* Just continue */
484 : }
485 :
486 0 : ret = ads_store_sdap_subdom(ctx, ctx->be_ctx->domain);
487 0 : if (ret != EOK) {
488 0 : DEBUG(SSSDBG_OP_FAILURE, "ads_store_sdap_subdom failed.\n");
489 0 : return ret;
490 : }
491 :
492 0 : return EOK;
493 : }
494 :
495 : static void ad_subdomains_get_conn_done(struct tevent_req *req);
496 : static void ad_subdomains_master_dom_done(struct tevent_req *req);
497 : static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx);
498 : static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx);
499 :
500 0 : static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
501 : struct be_req *be_req)
502 : {
503 0 : struct ad_subdomains_req_ctx *req_ctx = NULL;
504 : struct tevent_req *req;
505 0 : int dp_error = DP_ERR_FATAL;
506 : int ret;
507 :
508 0 : req_ctx = talloc_zero(be_req, struct ad_subdomains_req_ctx);
509 0 : if (req_ctx == NULL) {
510 0 : ret = ENOMEM;
511 0 : goto done;
512 : }
513 :
514 0 : req_ctx->be_req = be_req;
515 0 : req_ctx->sd_ctx = ctx;
516 0 : req_ctx->current_filter = NULL;
517 0 : req_ctx->base_iter = 0;
518 0 : req_ctx->root_base_iter = 0;
519 0 : req_ctx->root_id_ctx = NULL;
520 0 : req_ctx->root_op = NULL;
521 0 : req_ctx->root_domain = NULL;
522 0 : req_ctx->root_domain_attrs = NULL;
523 0 : req_ctx->reply_count = 0;
524 0 : req_ctx->reply = NULL;
525 :
526 0 : req_ctx->sdap_op = sdap_id_op_create(req_ctx,
527 0 : ctx->ldap_ctx->conn_cache);
528 0 : if (req_ctx->sdap_op == NULL) {
529 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
530 0 : ret = ENOMEM;
531 0 : goto done;
532 : }
533 :
534 0 : req = sdap_id_op_connect_send(req_ctx->sdap_op, req_ctx, &ret);
535 0 : if (req == NULL) {
536 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
537 : ret, strerror(ret));
538 0 : goto done;
539 : }
540 :
541 0 : tevent_req_set_callback(req, ad_subdomains_get_conn_done, req_ctx);
542 :
543 0 : return;
544 :
545 : done:
546 0 : talloc_free(req_ctx);
547 0 : if (ret == EOK) {
548 0 : dp_error = DP_ERR_OK;
549 : }
550 0 : be_req_terminate(be_req, dp_error, ret, NULL);
551 : }
552 :
553 0 : static void ad_subdomains_get_conn_done(struct tevent_req *req)
554 : {
555 : int ret;
556 0 : int dp_error = DP_ERR_FATAL;
557 : struct ad_subdomains_req_ctx *ctx;
558 :
559 0 : ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
560 :
561 0 : ret = sdap_id_op_connect_recv(req, &dp_error);
562 0 : talloc_zfree(req);
563 0 : if (ret) {
564 0 : if (dp_error == DP_ERR_OFFLINE) {
565 0 : DEBUG(SSSDBG_MINOR_FAILURE,
566 : "No AD server is available, cannot get the "
567 : "subdomain list while offline\n");
568 : } else {
569 0 : DEBUG(SSSDBG_OP_FAILURE,
570 : "Failed to connect to AD server: [%d](%s)\n",
571 : ret, strerror(ret));
572 : }
573 :
574 0 : goto fail;
575 : }
576 :
577 0 : req = ad_master_domain_send(ctx, ctx->sd_ctx->be_ctx->ev,
578 0 : ctx->sd_ctx->ldap_ctx,
579 : ctx->sdap_op,
580 0 : ctx->sd_ctx->domain_name);
581 0 : if (req == NULL) {
582 0 : DEBUG(SSSDBG_OP_FAILURE, "ad_master_domain_send failed.\n");
583 0 : ret = ENOMEM;
584 0 : goto fail;
585 : }
586 0 : tevent_req_set_callback(req, ad_subdomains_master_dom_done, ctx);
587 0 : return;
588 :
589 : fail:
590 0 : be_req_terminate(ctx->be_req, dp_error, ret, NULL);
591 : }
592 :
593 0 : static void ad_subdomains_master_dom_done(struct tevent_req *req)
594 : {
595 : struct ad_subdomains_req_ctx *ctx;
596 : errno_t ret;
597 : const char *realm;
598 :
599 0 : ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
600 :
601 0 : ret = ad_master_domain_recv(req, ctx,
602 : &ctx->flat_name, &ctx->master_sid,
603 : &ctx->site, &ctx->forest);
604 0 : talloc_zfree(req);
605 0 : if (ret != EOK) {
606 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot retrieve master domain info\n");
607 0 : goto done;
608 : }
609 :
610 0 : realm = dp_opt_get_cstring(ctx->sd_ctx->ad_id_ctx->ad_options->basic,
611 : AD_KRB5_REALM);
612 0 : if (realm == NULL) {
613 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm.\n");
614 0 : ret = EINVAL;
615 0 : goto done;
616 : }
617 :
618 0 : ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
619 : realm,
620 0 : ctx->flat_name, ctx->master_sid,
621 0 : ctx->forest);
622 0 : if (ret != EOK) {
623 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info\n");
624 0 : goto done;
625 : }
626 :
627 0 : if (ctx->forest == NULL ||
628 0 : strcasecmp(ctx->sd_ctx->be_ctx->domain->name, ctx->forest) != 0) {
629 0 : DEBUG(SSSDBG_TRACE_FUNC,
630 : "SSSD needs to look up the forest root domain\n");
631 0 : ret = ad_subdomains_get_root(ctx);
632 : } else {
633 0 : DEBUG(SSSDBG_TRACE_FUNC,
634 : "Connected to forest root, looking up child domains..\n");
635 :
636 0 : ctx->root_op = ctx->sdap_op;
637 0 : ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx;
638 :
639 0 : ret = ad_subdomains_get_slave(ctx);
640 : }
641 :
642 0 : if (ret == EAGAIN) {
643 0 : return;
644 0 : } else if (ret != EOK) {
645 0 : goto done;
646 : }
647 :
648 : done:
649 0 : be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
650 : }
651 :
652 : static void ad_subdomains_get_root_domain_done(struct tevent_req *req);
653 :
654 0 : static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx)
655 : {
656 : struct tevent_req *req;
657 : struct sdap_search_base *base;
658 : struct sdap_id_ctx *sdap_id_ctx;
659 : char *filter;
660 0 : const char *forest_root_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
661 : AD_AT_SID, AD_AT_TRUST_TYPE,
662 : AD_AT_TRUST_ATTRS, NULL };
663 :
664 0 : sdap_id_ctx = ctx->sd_ctx->sdap_id_ctx;
665 0 : base = sdap_id_ctx->opts->sdom->search_bases[ctx->root_base_iter];
666 0 : if (base == NULL) {
667 0 : return EOK;
668 : }
669 :
670 0 : filter = talloc_asprintf(ctx, FOREST_ROOT_FILTER_FMT, ctx->forest);
671 0 : if (filter == NULL) {
672 0 : return ENOMEM;
673 : }
674 :
675 0 : req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
676 : sdap_id_ctx->opts,
677 : sdap_id_op_handle(ctx->sdap_op),
678 : base->basedn, LDAP_SCOPE_SUBTREE,
679 : filter, forest_root_attrs,
680 : NULL, 0,
681 0 : dp_opt_get_int(sdap_id_ctx->opts->basic,
682 : SDAP_SEARCH_TIMEOUT),
683 : false);
684 :
685 0 : if (req == NULL) {
686 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
687 0 : return ENOMEM;
688 : }
689 :
690 0 : tevent_req_set_callback(req, ad_subdomains_get_root_domain_done, ctx);
691 0 : return EAGAIN;
692 : }
693 :
694 : static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx);
695 : static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx);
696 : static void ad_subdomains_root_conn_done(struct tevent_req *req);
697 :
698 0 : static void ad_subdomains_get_root_domain_done(struct tevent_req *req)
699 : {
700 : int ret;
701 : size_t reply_count;
702 0 : struct sysdb_attrs **reply = NULL;
703 : struct ad_subdomains_req_ctx *ctx;
704 0 : int dp_error = DP_ERR_FATAL;
705 0 : bool has_changes = false;
706 :
707 0 : ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
708 :
709 0 : ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
710 0 : talloc_zfree(req);
711 0 : if (ret != EOK) {
712 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
713 0 : goto fail;
714 : }
715 :
716 0 : if (reply_count == 0) {
717 : /* If no root domain was found in the default search base, try the
718 : * next one, if available
719 : */
720 0 : ctx->root_base_iter++;
721 0 : ret = ad_subdomains_get_root(ctx);
722 0 : if (ret == EAGAIN) {
723 0 : return;
724 : }
725 :
726 0 : goto fail;
727 0 : } else if (reply_count > 1) {
728 0 : DEBUG(SSSDBG_CRIT_FAILURE,
729 : "Multiple results for root domain search, "
730 : "domain list might be incomplete!\n");
731 :
732 0 : ctx->root_op = ctx->sdap_op;
733 0 : ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx;
734 :
735 0 : ret = ad_subdomains_get_slave(ctx);
736 0 : if (ret == EAGAIN) {
737 0 : return;
738 : }
739 :
740 0 : goto fail;
741 : }
742 : /* Exactly one result, good. */
743 :
744 : /* We won't use the operation to the local LDAP anymore, but
745 : * read from the forest root
746 : */
747 0 : ret = sdap_id_op_done(ctx->sdap_op, ret, &dp_error);
748 0 : if (ret != EOK) {
749 0 : if (dp_error == DP_ERR_OFFLINE) {
750 0 : DEBUG(SSSDBG_MINOR_FAILURE,
751 : "No AD server is available, cannot get the "
752 : "subdomain list while offline\n");
753 : } else {
754 0 : DEBUG(SSSDBG_OP_FAILURE,
755 : "Failed to search the AD server: [%d](%s)\n",
756 : ret, strerror(ret));
757 : }
758 0 : goto fail;
759 : }
760 :
761 0 : ret = ad_subdomains_refresh(ctx->sd_ctx, 1, true, reply, &has_changes);
762 0 : if (ret != EOK) {
763 0 : DEBUG(SSSDBG_OP_FAILURE, "ad_subdomains_refresh failed.\n");
764 0 : goto fail;
765 : }
766 :
767 0 : if (has_changes) {
768 0 : ret = ad_subdom_reinit(ctx->sd_ctx);
769 0 : if (ret != EOK) {
770 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
771 0 : goto fail;
772 : }
773 : }
774 :
775 0 : ctx->root_domain_attrs = reply[0];
776 0 : ctx->root_domain = ads_get_root_domain(ctx);
777 0 : if (ctx->root_domain == NULL) {
778 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
779 0 : ret = EFAULT;
780 0 : goto fail;
781 : }
782 :
783 0 : ctx->root_id_ctx = ads_get_root_id_ctx(ctx);
784 0 : if (ctx->root_id_ctx == NULL) {
785 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n");
786 0 : ret = EFAULT;
787 0 : goto fail;
788 : }
789 :
790 0 : ctx->root_op = sdap_id_op_create(ctx,
791 0 : ctx->root_id_ctx->ldap_ctx->conn_cache);
792 0 : if (ctx->root_op == NULL) {
793 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
794 0 : ret = ENOMEM;
795 0 : goto fail;
796 : }
797 :
798 0 : req = sdap_id_op_connect_send(ctx->root_op, ctx, &ret);
799 0 : if (req == NULL) {
800 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
801 : ret, strerror(ret));
802 0 : goto fail;
803 : }
804 :
805 0 : tevent_req_set_callback(req, ad_subdomains_root_conn_done, ctx);
806 0 : return;
807 :
808 : fail:
809 0 : if (ret == EOK) {
810 0 : ctx->sd_ctx->last_refreshed = time(NULL);
811 0 : dp_error = DP_ERR_OK;
812 : }
813 0 : be_req_terminate(ctx->be_req, dp_error, ret, NULL);
814 : }
815 :
816 0 : static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx)
817 : {
818 : errno_t ret;
819 : const char *name;
820 : struct sss_domain_info *root;
821 :
822 0 : ret = sysdb_attrs_get_string(ctx->root_domain_attrs, AD_AT_TRUST_PARTNER, &name);
823 0 : if (ret != EOK) {
824 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
825 0 : return NULL;
826 : }
827 :
828 : /* With a subsequent run, the root should already be known */
829 0 : root = find_domain_by_name(ctx->sd_ctx->be_ctx->domain,
830 : name, false);
831 :
832 0 : return root;
833 : }
834 :
835 0 : static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
836 : {
837 : errno_t ret;
838 : struct sdap_domain *sdom;
839 : struct ad_id_ctx *root_id_ctx;
840 :
841 0 : sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts,
842 : ctx->root_domain);
843 0 : if (sdom == NULL) {
844 0 : DEBUG(SSSDBG_OP_FAILURE,
845 : "Cannot get the sdom for %s!\n", ctx->root_domain->name);
846 0 : return NULL;
847 : }
848 :
849 0 : if (sdom->pvt == NULL) {
850 0 : ret = ad_subdom_ad_ctx_new(ctx->sd_ctx->be_ctx,
851 0 : ctx->sd_ctx->ad_id_ctx,
852 : ctx->root_domain,
853 : &root_id_ctx);
854 0 : if (ret != EOK) {
855 0 : DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
856 0 : return NULL;
857 : }
858 :
859 0 : sdom->pvt = root_id_ctx;
860 : } else {
861 0 : root_id_ctx = sdom->pvt;
862 : }
863 :
864 0 : root_id_ctx->ldap_ctx->ignore_mark_offline = true;
865 0 : return root_id_ctx;
866 : }
867 :
868 0 : static void ad_subdomains_root_conn_done(struct tevent_req *req)
869 : {
870 : int ret;
871 0 : int dp_error = DP_ERR_FATAL;
872 : struct ad_subdomains_req_ctx *ctx;
873 :
874 0 : ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
875 :
876 0 : ret = sdap_id_op_connect_recv(req, &dp_error);
877 0 : talloc_zfree(req);
878 0 : if (ret) {
879 0 : be_mark_dom_offline(ctx->root_domain, be_req_get_be_ctx(ctx->be_req));
880 :
881 0 : DEBUG(SSSDBG_OP_FAILURE,
882 : "Failed to connect to AD server: [%d](%s)\n",
883 : ret, strerror(ret));
884 0 : goto fail;
885 : }
886 :
887 0 : ret = ad_subdomains_get_slave(ctx);
888 0 : if (ret == EAGAIN) {
889 0 : return;
890 0 : } else if (ret != EOK) {
891 0 : goto fail;
892 : }
893 :
894 : fail:
895 0 : be_req_terminate(ctx->be_req, dp_error, ret, NULL);
896 : }
897 :
898 : static void ad_subdomains_get_slave_domain_done(struct tevent_req *req);
899 :
900 0 : static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx)
901 : {
902 : struct tevent_req *req;
903 : struct sdap_search_base *base;
904 0 : const char *slave_dom_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
905 : AD_AT_SID, AD_AT_TRUST_TYPE,
906 : AD_AT_TRUST_ATTRS, NULL };
907 :
908 0 : base = ctx->root_id_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter];
909 0 : if (base == NULL) {
910 0 : return EOK;
911 : }
912 :
913 0 : req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
914 0 : ctx->root_id_ctx->sdap_id_ctx->opts,
915 : sdap_id_op_handle(ctx->root_op),
916 : base->basedn, LDAP_SCOPE_SUBTREE,
917 : SLAVE_DOMAIN_FILTER, slave_dom_attrs,
918 : NULL, 0,
919 0 : dp_opt_get_int(ctx->root_id_ctx->sdap_id_ctx->opts->basic,
920 : SDAP_SEARCH_TIMEOUT),
921 : false);
922 :
923 0 : if (req == NULL) {
924 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
925 0 : return ENOMEM;
926 : }
927 :
928 0 : tevent_req_set_callback(req, ad_subdomains_get_slave_domain_done, ctx);
929 0 : return EAGAIN;
930 : }
931 :
932 0 : static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx,
933 : struct sss_domain_info *domain,
934 : size_t nsd, struct sysdb_attrs **sd,
935 : struct sysdb_attrs *root,
936 : size_t *_nsd_out,
937 : struct sysdb_attrs ***_sd_out)
938 : {
939 : size_t i, sdi;
940 : struct sysdb_attrs **sd_out;
941 : const char *sd_name;
942 : errno_t ret;
943 :
944 0 : if (root == NULL) {
945 : /* We are connected directly to the root domain. The 'sd'
946 : * list is complete and we can just use it
947 : */
948 0 : *_nsd_out = nsd;
949 0 : *_sd_out = sd;
950 0 : return EOK;
951 : }
952 :
953 : /* If we searched for root separately, we must:
954 : * a) treat the root domain as a subdomain
955 : * b) filter the subdomain we are connected to from the subdomain
956 : * list, from our point of view, it's the master domain
957 : */
958 0 : sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1);
959 0 : if (sd_out == NULL) {
960 0 : return ENOMEM;
961 : }
962 :
963 0 : sdi = 0;
964 0 : for (i = 0; i < nsd; i++) {
965 0 : ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name);
966 0 : if (ret != EOK) {
967 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
968 0 : goto fail;
969 : }
970 :
971 0 : if (strcasecmp(sd_name, domain->name) == 0) {
972 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
973 : "Not including primary domain %s in the subdomain list\n",
974 : domain->name);
975 0 : continue;
976 : }
977 :
978 0 : sd_out[sdi] = talloc_steal(sd_out, sd[i]);
979 0 : sdi++;
980 : }
981 :
982 : /* Now include the root */
983 0 : sd_out[sdi] = talloc_steal(sd_out, root);
984 :
985 0 : *_nsd_out = sdi+1;
986 0 : *_sd_out = sd_out;
987 0 : return EOK;
988 :
989 : fail:
990 0 : talloc_free(sd_out);
991 0 : return ret;
992 : }
993 :
994 0 : static void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
995 : {
996 : int ret;
997 : size_t reply_count;
998 0 : struct sysdb_attrs **reply = NULL;
999 : struct ad_subdomains_req_ctx *ctx;
1000 0 : int dp_error = DP_ERR_FATAL;
1001 0 : bool refresh_has_changes = false;
1002 : size_t nsubdoms;
1003 : struct sysdb_attrs **subdoms;
1004 :
1005 0 : ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
1006 :
1007 0 : ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
1008 0 : talloc_zfree(req);
1009 0 : if (ret != EOK) {
1010 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
1011 0 : goto done;
1012 : }
1013 :
1014 0 : if (reply_count) {
1015 0 : ctx->reply = talloc_realloc(ctx, ctx->reply, struct sysdb_attrs *,
1016 : ctx->reply_count + reply_count);
1017 0 : if (ctx->reply == NULL) {
1018 0 : ret = ENOMEM;
1019 0 : goto done;
1020 : }
1021 0 : memcpy(ctx->reply+ctx->reply_count, reply,
1022 : reply_count * sizeof(struct sysdb_attrs *));
1023 0 : ctx->reply_count += reply_count;
1024 : }
1025 :
1026 0 : ctx->base_iter++;
1027 0 : ret = ad_subdomains_get_slave(ctx);
1028 0 : if (ret == EAGAIN) {
1029 : /* Search in progress */
1030 0 : return;
1031 : }
1032 :
1033 0 : ret = sdap_id_op_done(ctx->root_op, ret, &dp_error);
1034 0 : if (ret != EOK) {
1035 0 : if (dp_error == DP_ERR_OFFLINE) {
1036 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1037 : "No AD server is available, cannot get the "
1038 : "subdomain list while offline\n");
1039 : } else {
1040 0 : DEBUG(SSSDBG_OP_FAILURE,
1041 : "Failed to search the AD server: [%d](%s)\n",
1042 : ret, strerror(ret));
1043 : }
1044 0 : tevent_req_error(req, ret);
1045 0 : return;
1046 : }
1047 :
1048 : /* Based on whether we are connected to the forest root or not, we might
1049 : * need to exclude the subdomain we are connected to from the list of
1050 : * subdomains
1051 : */
1052 0 : ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain,
1053 : ctx->reply_count, ctx->reply,
1054 : ctx->root_domain_attrs, &nsubdoms, &subdoms);
1055 0 : if (ret != EOK) {
1056 0 : DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n"));
1057 0 : tevent_req_error(req, ret);
1058 0 : return;
1059 : }
1060 :
1061 : /* Got all the subdomains, let's process them */
1062 0 : ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, false, subdoms,
1063 : &refresh_has_changes);
1064 0 : if (ret != EOK) {
1065 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
1066 0 : goto done;
1067 : }
1068 :
1069 0 : DEBUG(SSSDBG_TRACE_LIBS, "There are %schanges\n",
1070 : refresh_has_changes ? "" : "no ");
1071 :
1072 0 : if (refresh_has_changes) {
1073 0 : ret = ad_subdom_reinit(ctx->sd_ctx);
1074 0 : if (ret != EOK) {
1075 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
1076 0 : goto done;
1077 : }
1078 : }
1079 :
1080 0 : ret = EOK;
1081 : done:
1082 0 : if (ret == EOK) {
1083 0 : ctx->sd_ctx->last_refreshed = time(NULL);
1084 0 : dp_error = DP_ERR_OK;
1085 : }
1086 0 : be_req_terminate(ctx->be_req, dp_error, ret, NULL);
1087 : }
1088 :
1089 : static void ad_subdom_online_cb(void *pvt);
1090 :
1091 0 : static void ad_subdom_timer_refresh(struct tevent_context *ev,
1092 : struct tevent_timer *te,
1093 : struct timeval current_time,
1094 : void *pvt)
1095 : {
1096 0 : ad_subdom_online_cb(pvt);
1097 0 : }
1098 :
1099 0 : static void ad_subdom_be_req_callback(struct be_req *be_req,
1100 : int dp_err, int dp_ret,
1101 : const char *errstr)
1102 : {
1103 0 : talloc_free(be_req);
1104 0 : }
1105 :
1106 0 : static void ad_subdom_online_cb(void *pvt)
1107 : {
1108 : struct ad_subdomains_ctx *ctx;
1109 : struct be_req *be_req;
1110 : struct timeval tv;
1111 : uint32_t refresh_interval;
1112 :
1113 0 : ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
1114 0 : if (!ctx) {
1115 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
1116 0 : return;
1117 : }
1118 :
1119 0 : refresh_interval = ctx->be_ctx->domain->subdomain_refresh_interval;
1120 :
1121 0 : be_req = be_req_create(ctx, NULL, ctx->be_ctx,
1122 : ad_subdom_be_req_callback, NULL);
1123 0 : if (be_req == NULL) {
1124 0 : DEBUG(SSSDBG_CRIT_FAILURE, "be_req_create() failed.\n");
1125 0 : return;
1126 : }
1127 :
1128 0 : ad_subdomains_retrieve(ctx, be_req);
1129 :
1130 0 : tv = tevent_timeval_current_ofs(refresh_interval, 0);
1131 0 : ctx->timer_event = tevent_add_timer(ctx->be_ctx->ev, ctx, tv,
1132 : ad_subdom_timer_refresh, ctx);
1133 0 : if (!ctx->timer_event) {
1134 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom timer event\n");
1135 : }
1136 : }
1137 :
1138 0 : static void ad_subdom_offline_cb(void *pvt)
1139 : {
1140 : struct ad_subdomains_ctx *ctx;
1141 :
1142 0 : ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
1143 :
1144 0 : if (ctx) {
1145 0 : talloc_zfree(ctx->timer_event);
1146 : }
1147 0 : }
1148 :
1149 0 : void ad_subdomains_handler(struct be_req *be_req)
1150 : {
1151 0 : struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
1152 : struct ad_subdomains_ctx *ctx;
1153 : time_t now;
1154 :
1155 0 : ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
1156 : struct ad_subdomains_ctx);
1157 0 : if (!ctx) {
1158 0 : be_req_terminate(be_req, DP_ERR_FATAL, EINVAL, NULL);
1159 0 : return;
1160 : }
1161 :
1162 0 : now = time(NULL);
1163 :
1164 0 : if (ctx->last_refreshed > now - AD_SUBDOMAIN_REFRESH_LIMIT) {
1165 0 : be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
1166 0 : return;
1167 : }
1168 :
1169 0 : ad_subdomains_retrieve(ctx, be_req);
1170 : }
1171 :
1172 : struct bet_ops ad_subdomains_ops = {
1173 : .handler = ad_subdomains_handler,
1174 : .finalize = NULL
1175 : };
1176 :
1177 0 : int ad_subdom_init(struct be_ctx *be_ctx,
1178 : struct ad_id_ctx *id_ctx,
1179 : const char *ad_domain,
1180 : struct bet_ops **ops,
1181 : void **pvt_data)
1182 : {
1183 : struct ad_subdomains_ctx *ctx;
1184 : int ret;
1185 : enum idmap_error_code err;
1186 :
1187 0 : ctx = talloc_zero(id_ctx, struct ad_subdomains_ctx);
1188 0 : if (ctx == NULL) {
1189 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
1190 0 : return ENOMEM;
1191 : }
1192 :
1193 0 : ctx->be_ctx = be_ctx;
1194 0 : ctx->sdom = id_ctx->sdap_id_ctx->opts->sdom;
1195 0 : ctx->ldap_ctx = id_ctx->ldap_ctx;
1196 0 : ctx->sdap_id_ctx = id_ctx->sdap_id_ctx;
1197 0 : ctx->domain_name = talloc_strdup(ctx, ad_domain);
1198 0 : if (ctx->domain_name == NULL) {
1199 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
1200 0 : return ENOMEM;
1201 : }
1202 0 : ctx->ad_id_ctx = id_ctx;
1203 0 : *ops = &ad_subdomains_ops;
1204 0 : *pvt_data = ctx;
1205 :
1206 0 : ret = be_add_online_cb(ctx, be_ctx, ad_subdom_online_cb, ctx, NULL);
1207 0 : if (ret != EOK) {
1208 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom online callback\n");
1209 : }
1210 :
1211 0 : ret = be_add_offline_cb(ctx, be_ctx, ad_subdom_offline_cb, ctx, NULL);
1212 0 : if (ret != EOK) {
1213 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom offline callback\n");
1214 : }
1215 :
1216 0 : err = sss_idmap_init(sss_idmap_talloc, ctx, sss_idmap_talloc_free,
1217 : &ctx->idmap_ctx);
1218 0 : if (err != IDMAP_SUCCESS) {
1219 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize idmap context.\n");
1220 0 : return EFAULT;
1221 : }
1222 :
1223 0 : ret = ad_subdom_reinit(ctx);
1224 0 : if (ret != EOK) {
1225 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not reinitialize subdomains. "
1226 : "Users from trusted domains might not be resolved correctly\n");
1227 : /* Ignore this error and try to discover the subdomains later */
1228 : }
1229 :
1230 0 : return EOK;
1231 : }
|