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