Line data Source code
1 : /*
2 : SSSD
3 :
4 : IPA Subdomains Module
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2011 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "providers/ldap/sdap_async.h"
26 : #include "providers/ldap/sdap_idmap.h"
27 : #include "providers/ldap/sdap_ops.h"
28 : #include "providers/ipa/ipa_subdomains.h"
29 : #include "providers/ipa/ipa_common.h"
30 : #include "providers/ipa/ipa_id.h"
31 :
32 : #include <ctype.h>
33 :
34 : #define SUBDOMAINS_FILTER "objectclass=ipaNTTrustedDomain"
35 : #define MASTER_DOMAIN_FILTER "objectclass=ipaNTDomainAttrs"
36 : #define RANGE_FILTER "objectclass=ipaIDRange"
37 :
38 : #define IPA_CN "cn"
39 : #define IPA_FLATNAME "ipaNTFlatName"
40 : #define IPA_SID "ipaNTSecurityIdentifier"
41 : #define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID"
42 : #define IPA_RANGE_TYPE "ipaRangeType"
43 :
44 : #define IPA_BASE_ID "ipaBaseID"
45 : #define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
46 : #define IPA_BASE_RID "ipaBaseRID"
47 : #define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID"
48 : #define OBJECTCLASS "objectClass"
49 :
50 : #define IPA_ASSIGNED_ID_VIEW "ipaAssignedIDView"
51 :
52 : /* do not refresh more often than every 5 seconds for now */
53 : #define IPA_SUBDOMAIN_REFRESH_LIMIT 5
54 :
55 : #define IPA_SUBDOMAIN_DISABLED_PERIOD 3600
56 :
57 : struct ipa_subdomains_ctx {
58 : struct be_ctx *be_ctx;
59 : struct ipa_id_ctx *ipa_id_ctx;
60 : struct sdap_id_ctx *sdap_id_ctx;
61 : struct sdap_search_base **search_bases;
62 : struct sdap_search_base **master_search_bases;
63 : struct sdap_search_base **ranges_search_bases;
64 : struct sdap_search_base **host_search_bases;
65 :
66 : time_t last_refreshed;
67 : bool view_read_at_init;
68 : };
69 :
70 : static errno_t
71 0 : ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx)
72 : {
73 : errno_t ret;
74 :
75 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
76 : "Re-initializing domain %s\n", ctx->be_ctx->domain->name);
77 :
78 0 : ret = sss_write_krb5_conf_snippet(
79 0 : dp_opt_get_string(ctx->ipa_id_ctx->ipa_options->basic,
80 : IPA_KRB5_CONFD_PATH));
81 0 : if (ret != EOK) {
82 0 : DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
83 : /* Just continue */
84 : }
85 :
86 0 : ret = sysdb_master_domain_update(ctx->be_ctx->domain);
87 0 : if (ret != EOK) {
88 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed.\n");
89 0 : return ret;
90 : }
91 :
92 0 : ret = sysdb_update_subdomains(ctx->be_ctx->domain);
93 0 : if (ret != EOK) {
94 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
95 0 : return ret;
96 : }
97 :
98 0 : ret = sss_write_domain_mappings(ctx->be_ctx->domain);
99 0 : if (ret != EOK) {
100 0 : DEBUG(SSSDBG_MINOR_FAILURE,
101 : "sss_krb5_write_mappings failed.\n");
102 : /* Just continue */
103 : }
104 :
105 0 : return EOK;
106 : }
107 :
108 0 : static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
109 : char *domain_name,
110 : size_t count,
111 : struct sysdb_attrs **reply,
112 : struct range_info ***_range_list)
113 : {
114 0 : struct range_info **range_list = NULL;
115 : struct range_info *r;
116 : const char *value;
117 : size_t c;
118 : size_t d;
119 : int ret;
120 : enum idmap_error_code err;
121 : char *name1;
122 : char *name2;
123 : char *sid1;
124 : char *sid2;
125 : uint32_t rid1;
126 : uint32_t rid2;
127 : struct sss_idmap_range range1;
128 : struct sss_idmap_range range2;
129 : bool mapping1;
130 : bool mapping2;
131 :
132 0 : range_list = talloc_array(mem_ctx, struct range_info *, count + 1);
133 0 : if (range_list == NULL) {
134 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
135 0 : return ENOMEM;
136 : }
137 :
138 0 : for (c = 0; c < count; c++) {
139 0 : r = talloc_zero(range_list, struct range_info);
140 0 : if (r == NULL) {
141 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
142 0 : ret = ENOMEM;
143 0 : goto done;
144 : }
145 :
146 0 : ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
147 0 : if (ret != EOK) {
148 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
149 0 : goto done;
150 : }
151 :
152 0 : r->name = talloc_strdup(r, value);
153 0 : if (r->name == NULL) {
154 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
155 0 : ret = ENOMEM;
156 0 : goto done;
157 : }
158 :
159 0 : ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value);
160 0 : if (ret == EOK) {
161 0 : r->trusted_dom_sid = talloc_strdup(r, value);
162 0 : if (r->trusted_dom_sid == NULL) {
163 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
164 0 : ret = ENOMEM;
165 0 : goto done;
166 : }
167 0 : } else if (ret != ENOENT) {
168 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
169 0 : goto done;
170 : }
171 :
172 0 : ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID,
173 : &r->base_id);
174 0 : if (ret != EOK && ret != ENOENT) {
175 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
176 0 : goto done;
177 : }
178 :
179 0 : ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE,
180 : &r->id_range_size);
181 0 : if (ret != EOK && ret != ENOENT) {
182 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
183 0 : goto done;
184 : }
185 :
186 0 : ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID,
187 : &r->base_rid);
188 0 : if (ret != EOK && ret != ENOENT) {
189 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
190 0 : goto done;
191 : }
192 :
193 0 : ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID,
194 : &r->secondary_base_rid);
195 0 : if (ret != EOK && ret != ENOENT) {
196 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
197 0 : goto done;
198 : }
199 :
200 0 : ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value);
201 0 : if (ret == EOK) {
202 0 : r->range_type = talloc_strdup(r, value);
203 0 : if (r->range_type == NULL) {
204 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
205 0 : ret = ENOMEM;
206 0 : goto done;
207 : }
208 0 : } else if (ret == ENOENT) {
209 : /* Older IPA servers might not have the range_type attribute, but
210 : * only support local ranges and trusts with algorithmic mapping. */
211 0 : if (r->trusted_dom_sid == NULL) {
212 0 : r->range_type = talloc_strdup(r, IPA_RANGE_LOCAL);
213 : } else {
214 0 : r->range_type = talloc_strdup(r, IPA_RANGE_AD_TRUST);
215 : }
216 : } else {
217 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
218 0 : goto done;
219 : }
220 0 : if (r->range_type == NULL) {
221 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
222 0 : ret = ENOMEM;
223 0 : goto done;
224 : }
225 :
226 0 : ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1,
227 : &range1, &mapping1);
228 0 : if (ret != EOK) {
229 0 : DEBUG(SSSDBG_OP_FAILURE, "get_idmap_data_from_range failed.\n");
230 0 : goto done;
231 : }
232 0 : for (d = 0; d < c; d++) {
233 0 : ret = get_idmap_data_from_range(range_list[d], domain_name, &name2,
234 : &sid2, &rid2, &range2, &mapping2);
235 0 : if (ret != EOK) {
236 0 : DEBUG(SSSDBG_OP_FAILURE,
237 : "get_idmap_data_from_range failed.\n");
238 0 : goto done;
239 : }
240 :
241 0 : err = sss_idmap_check_collision_ex(name1, sid1, &range1, rid1,
242 0 : r->name, mapping1,
243 : name2, sid2, &range2, rid2,
244 0 : range_list[d]->name, mapping2);
245 0 : if (err != IDMAP_SUCCESS) {
246 0 : DEBUG(SSSDBG_CRIT_FAILURE,
247 : "Collision of ranges [%s] and [%s] detected.\n",
248 : r->name, range_list[d]->name);
249 0 : ret = EINVAL;
250 0 : goto done;
251 : }
252 : }
253 :
254 0 : range_list[c] = r;
255 : }
256 :
257 0 : range_list[c] = NULL;
258 :
259 0 : *_range_list = range_list;
260 0 : ret = EOK;
261 :
262 : done:
263 0 : if (ret != EOK) {
264 0 : talloc_free(range_list);
265 : }
266 :
267 0 : return ret;
268 : }
269 :
270 0 : static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent,
271 : struct sysdb_attrs *attrs,
272 : bool *_enumerates)
273 : {
274 : errno_t ret;
275 : const char *name;
276 :
277 0 : ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
278 0 : if (ret != EOK) {
279 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
280 0 : return ret;
281 : }
282 :
283 0 : *_enumerates = subdomain_enumerates(parent, name);
284 0 : return EOK;
285 : }
286 :
287 0 : static errno_t ipa_subdom_get_forest(TALLOC_CTX *mem_ctx,
288 : struct ldb_context *ldb_ctx,
289 : struct sysdb_attrs *attrs,
290 : char **_forest)
291 : {
292 : int ret;
293 0 : struct ldb_dn *dn = NULL;
294 : const char *name;
295 : const struct ldb_val *val;
296 0 : char *forest = NULL;
297 :
298 0 : dn = ipa_subdom_ldb_dn(mem_ctx, ldb_ctx, attrs);
299 0 : if (dn == NULL) {
300 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_subdom_ldb_dn failed.\n");
301 0 : ret = EIO;
302 0 : goto done;
303 : }
304 :
305 0 : if (ipa_subdom_is_member_dom(dn) == false) {
306 0 : ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
307 0 : if (ret) {
308 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
309 0 : goto done;
310 : }
311 :
312 0 : forest = talloc_strdup(mem_ctx, name);
313 0 : if (forest == NULL) {
314 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
315 0 : ret = ENOMEM;
316 0 : goto done;
317 : }
318 :
319 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "The forest name is %s\n", forest);
320 0 : ret = EOK;
321 0 : goto done;
322 : }
323 :
324 0 : val = ldb_dn_get_component_val(dn, 1);
325 0 : forest = talloc_strndup(mem_ctx, (const char *) val->data, val->length);
326 0 : if (forest == NULL) {
327 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
328 0 : ret = ENOMEM;
329 0 : goto done;
330 : }
331 :
332 0 : ret = EOK;
333 : done:
334 0 : talloc_free(dn);
335 :
336 0 : if (ret == EOK) {
337 0 : *_forest = forest;
338 : }
339 :
340 0 : return ret;
341 : }
342 :
343 0 : static errno_t ipa_get_sd_trust_direction(struct sysdb_attrs *sd,
344 : struct ipa_id_ctx *id_ctx,
345 : struct ldb_context *ldb_ctx,
346 : uint32_t *_direction)
347 : {
348 0 : if (id_ctx->server_mode != NULL) {
349 0 : return ipa_server_get_trust_direction(sd, ldb_ctx, _direction);
350 : } else {
351 : /* Clients do not have access to the trust objects's trust direction
352 : * and don't generally care
353 : */
354 0 : *_direction = 0;
355 0 : return EOK;
356 : }
357 : }
358 :
359 0 : static errno_t ipa_subdom_store(struct sss_domain_info *parent,
360 : struct ipa_id_ctx *id_ctx,
361 : struct sdap_idmap_ctx *sdap_idmap_ctx,
362 : struct sysdb_attrs *attrs)
363 : {
364 : TALLOC_CTX *tmp_ctx;
365 : const char *name;
366 : char *realm;
367 : const char *flat;
368 : const char *id;
369 0 : char *forest = NULL;
370 : int ret;
371 : bool mpg;
372 : bool enumerate;
373 : uint32_t direction;
374 :
375 0 : tmp_ctx = talloc_new(parent);
376 0 : if (tmp_ctx == NULL) {
377 0 : return ENOMEM;
378 : }
379 :
380 0 : ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
381 0 : if (ret != EOK) {
382 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
383 0 : goto done;
384 : }
385 :
386 0 : realm = get_uppercase_realm(tmp_ctx, name);
387 0 : if (!realm) {
388 0 : ret = ENOMEM;
389 0 : goto done;
390 : }
391 :
392 0 : ret = sysdb_attrs_get_string(attrs, IPA_FLATNAME, &flat);
393 0 : if (ret) {
394 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
395 0 : goto done;
396 : }
397 :
398 0 : ret = sysdb_attrs_get_string(attrs, IPA_TRUSTED_DOMAIN_SID, &id);
399 0 : if (ret) {
400 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
401 0 : goto done;
402 : }
403 :
404 0 : mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, id);
405 :
406 0 : ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb),
407 : attrs, &forest);
408 0 : if (ret != EOK) {
409 0 : goto done;
410 : }
411 :
412 0 : ret = ipa_subdom_enumerates(parent, attrs, &enumerate);
413 0 : if (ret != EOK) {
414 0 : goto done;
415 : }
416 :
417 0 : ret = ipa_get_sd_trust_direction(attrs, id_ctx,
418 : sysdb_ctx_get_ldb(parent->sysdb),
419 : &direction);
420 0 : if (ret != EOK) {
421 0 : DEBUG(SSSDBG_OP_FAILURE,
422 : "ipa_get_sd_trust_direction failed: %d\n", ret);
423 0 : goto done;
424 : }
425 :
426 0 : DEBUG(SSSDBG_FUNC_DATA,
427 : "Trust direction of %s is %s\n", name, ipa_trust_dir2str(direction));
428 0 : ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat,
429 : id, mpg, enumerate, forest,
430 : direction);
431 0 : if (ret) {
432 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
433 0 : goto done;
434 : }
435 :
436 0 : ret = EOK;
437 : done:
438 0 : talloc_free(tmp_ctx);
439 0 : return ret;
440 : }
441 :
442 0 : static void ipa_subdom_store_step(struct sss_domain_info *parent,
443 : struct ipa_id_ctx *id_ctx,
444 : struct sdap_idmap_ctx *sdap_idmap_ctx,
445 : struct sysdb_attrs *attrs)
446 : {
447 : int ret;
448 :
449 0 : ret = ipa_subdom_store(parent, id_ctx, sdap_idmap_ctx, attrs);
450 0 : if (ret == ERR_TRUST_NOT_SUPPORTED) {
451 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Unsupported trust type, skipping\n");
452 0 : } else if (ret) {
453 : /* Nothing we can do about the error. */
454 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
455 : "will try to use cached subdomain\n");
456 : }
457 0 : }
458 :
459 0 : static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
460 : int count, struct sysdb_attrs **reply,
461 : bool *changes)
462 : {
463 : struct sss_domain_info *parent, *dom;
464 0 : bool handled[count];
465 : const char *value;
466 : int c, h;
467 : int ret;
468 :
469 0 : parent = ctx->be_ctx->domain;
470 0 : memset(handled, 0, sizeof(bool) * count);
471 0 : h = 0;
472 :
473 : /* check existing subdomains */
474 0 : for (dom = get_next_domain(parent, SSS_GND_DESCEND);
475 0 : dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
476 0 : dom = get_next_domain(dom, 0)) {
477 0 : for (c = 0; c < count; c++) {
478 0 : if (handled[c]) {
479 0 : continue;
480 : }
481 0 : ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
482 0 : if (ret != EOK) {
483 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
484 0 : goto done;
485 : }
486 0 : if (strcmp(value, dom->name) == 0) {
487 0 : break;
488 : }
489 : }
490 :
491 0 : if (c >= count) {
492 : /* ok this subdomain does not exist anymore, let's clean up */
493 0 : sss_domain_set_state(dom, DOM_DISABLED);
494 0 : ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
495 0 : if (ret != EOK) {
496 0 : goto done;
497 : }
498 :
499 : /* Remove the AD ID ctx from the list of LDAP domains */
500 0 : ipa_ad_subdom_remove(ctx->be_ctx, ctx->ipa_id_ctx, dom);
501 : } else {
502 : /* ok let's try to update it */
503 0 : ipa_subdom_store_step(parent, ctx->ipa_id_ctx,
504 0 : ctx->sdap_id_ctx->opts->idmap_ctx,
505 0 : reply[c]);
506 0 : handled[c] = true;
507 0 : h++;
508 : }
509 : }
510 :
511 0 : if (count == h) {
512 : /* all domains were already accounted for and have been updated */
513 0 : ret = EOK;
514 0 : goto done;
515 : }
516 :
517 : /* if we get here it means we have changes to the subdomains list */
518 0 : *changes = true;
519 :
520 0 : for (c = 0; c < count; c++) {
521 0 : if (handled[c]) {
522 0 : continue;
523 : }
524 :
525 0 : ipa_subdom_store_step(parent, ctx->ipa_id_ctx,
526 0 : ctx->sdap_id_ctx->opts->idmap_ctx,
527 0 : reply[c]);
528 : }
529 :
530 0 : ret = EOK;
531 : done:
532 0 : if (ret != EOK) {
533 0 : ctx->last_refreshed = 0;
534 : } else {
535 0 : ctx->last_refreshed = time(NULL);
536 : }
537 :
538 0 : return ret;
539 : }
540 :
541 0 : static errno_t ipa_apply_view(struct sss_domain_info *domain,
542 : struct ipa_id_ctx *ipa_id_ctx,
543 : const char *view_name,
544 : bool read_at_init)
545 : {
546 0 : const char *current = ipa_id_ctx->view_name;
547 0 : struct sysdb_ctx *sysdb = domain->sysdb;
548 0 : bool in_transaction = false;
549 : errno_t sret;
550 : errno_t ret;
551 :
552 0 : DEBUG(SSSDBG_TRACE_ALL, "read_at_init [%s] current view [%s]\n",
553 : read_at_init ? "true" : "false", ipa_id_ctx->view_name);
554 :
555 0 : if (current != NULL && strcmp(current, view_name) != 0 && read_at_init) {
556 0 : DEBUG(SSSDBG_CRIT_FAILURE, "View name changed, this is not supported "
557 : "at runtime. Please restart SSSD to get the new view applied.\n");
558 0 : return EOK;
559 : }
560 :
561 0 : if (current != NULL && strcmp(current, view_name) == 0) {
562 0 : DEBUG(SSSDBG_TRACE_FUNC, "View name did not change.\n");
563 0 : return EOK;
564 : }
565 :
566 0 : DEBUG(SSSDBG_TRACE_FUNC, "View name changed to [%s].\n", view_name);
567 :
568 : /* View name changed. If there was a non-default non-local view
569 : * was used the tree in cache containing the override values is
570 : * removed. In all cases sysdb_invalidate_overrides() is called to
571 : * remove the override attribute from the cached user objects.
572 : *
573 : * Typically ctx->sd_ctx->id_ctx->view_name == NULL means that the
574 : * cache was empty but there was a bug in with caused that the
575 : * view name was not written to the cache at all. In this case the
576 : * cache must be invalidated if the new view is not the
577 : * default-view as well. */
578 :
579 0 : if (current != NULL || !is_default_view(view_name)) {
580 0 : ret = sysdb_transaction_start(sysdb);
581 0 : if (ret != EOK) {
582 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to start transaction "
583 : "[%d]: %s\n", ret, sss_strerror(ret));
584 0 : goto done;
585 : }
586 :
587 0 : in_transaction = true;
588 :
589 0 : if (!is_default_view(current) && !is_local_view(current)) {
590 : /* Old view was not the default view, delete view tree */
591 0 : ret = sysdb_delete_view_tree(sysdb, current);
592 0 : if (ret != EOK) {
593 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to delete old view tree "
594 : "[%d]: %s\n", ret, sss_strerror(ret));
595 0 : goto done;
596 : }
597 : }
598 :
599 0 : ret = sysdb_invalidate_overrides(sysdb);
600 0 : if (ret != EOK) {
601 0 : DEBUG(SSSDBG_OP_FAILURE, " Unable to invalidate overrides "
602 : "[%d]: %s\n", ret, sss_strerror(ret));
603 0 : goto done;
604 : }
605 :
606 0 : ret = sysdb_transaction_commit(sysdb);
607 0 : if (ret != EOK) {
608 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to commint transaction "
609 : "[%d]: %s\n", ret, sss_strerror(ret));
610 0 : goto done;
611 : }
612 :
613 0 : in_transaction = false;
614 : }
615 :
616 0 : ret = sysdb_update_view_name(sysdb, view_name);
617 0 : if (ret != EOK) {
618 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot update view name "
619 : "[%d]: %s\n", ret, sss_strerror(ret));
620 0 : goto done;
621 : }
622 :
623 0 : talloc_free(ipa_id_ctx->view_name);
624 0 : ipa_id_ctx->view_name = talloc_strdup(ipa_id_ctx, view_name);
625 0 : if (ipa_id_ctx->view_name == NULL) {
626 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
627 0 : ret = ENOMEM;
628 0 : goto done;
629 : }
630 :
631 0 : if (!read_at_init) {
632 : /* refresh view data of all domains at startup */
633 0 : ret = sysdb_master_domain_update(domain);
634 0 : if (ret != EOK) {
635 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed "
636 : "[%d]: %s\n", ret, sss_strerror(ret));
637 0 : goto done;
638 : }
639 :
640 0 : ret = sysdb_update_subdomains(domain);
641 0 : if (ret != EOK) {
642 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed "
643 : "[%d]: %s\n", ret, sss_strerror(ret));
644 0 : goto done;
645 : }
646 : }
647 :
648 : done:
649 0 : if (in_transaction) {
650 0 : sret = sysdb_transaction_cancel(sysdb);
651 0 : if (sret != EOK) {
652 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
653 : }
654 : }
655 :
656 0 : return ret;
657 : }
658 :
659 : struct ipa_subdomains_ranges_state {
660 : struct sss_domain_info *domain;
661 : };
662 :
663 : static void ipa_subdomains_ranges_done(struct tevent_req *subreq);
664 :
665 : static struct tevent_req *
666 0 : ipa_subdomains_ranges_send(TALLOC_CTX *mem_ctx,
667 : struct tevent_context *ev,
668 : struct ipa_subdomains_ctx *sd_ctx,
669 : struct sdap_handle *sh)
670 : {
671 : struct ipa_subdomains_ranges_state *state;
672 : struct tevent_req *subreq;
673 : struct tevent_req *req;
674 : errno_t ret;
675 0 : const char *attrs[] = { OBJECTCLASS, IPA_CN,
676 : IPA_BASE_ID, IPA_BASE_RID, IPA_SECONDARY_BASE_RID,
677 : IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID,
678 : IPA_RANGE_TYPE, NULL };
679 :
680 0 : req = tevent_req_create(mem_ctx, &state,
681 : struct ipa_subdomains_ranges_state);
682 0 : if (req == NULL) {
683 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
684 0 : return NULL;
685 : }
686 :
687 0 : if (sd_ctx->ranges_search_bases == NULL) {
688 0 : DEBUG(SSSDBG_TRACE_FUNC, "No search base is set\n");
689 0 : ret = EOK;
690 0 : goto immediately;
691 : }
692 :
693 0 : state->domain = sd_ctx->be_ctx->domain;
694 :
695 0 : subreq = sdap_search_bases_send(state, ev, sd_ctx->sdap_id_ctx->opts, sh,
696 : sd_ctx->ranges_search_bases, NULL, false,
697 : 0, RANGE_FILTER, attrs);
698 0 : if (subreq == NULL) {
699 0 : ret = ENOMEM;
700 0 : goto immediately;
701 : }
702 :
703 0 : tevent_req_set_callback(subreq, ipa_subdomains_ranges_done, req);
704 :
705 0 : return req;
706 :
707 : immediately:
708 0 : if (ret == EOK) {
709 0 : tevent_req_done(req);
710 : } else {
711 0 : tevent_req_error(req, ret);
712 : }
713 0 : tevent_req_post(req, ev);
714 :
715 0 : return req;
716 : }
717 :
718 0 : static void ipa_subdomains_ranges_done(struct tevent_req *subreq)
719 : {
720 : struct ipa_subdomains_ranges_state *state;
721 : struct tevent_req *req;
722 : struct range_info **range_list;
723 : struct sysdb_attrs **reply;
724 : size_t reply_count;
725 : errno_t ret;
726 :
727 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
728 0 : state = tevent_req_data(req, struct ipa_subdomains_ranges_state);
729 :
730 0 : ret = sdap_search_bases_recv(subreq, state, &reply_count, &reply);
731 0 : talloc_zfree(subreq);
732 0 : if (ret != EOK) {
733 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get data from LDAP [%d]: %s\n",
734 : ret, sss_strerror(ret));
735 0 : goto done;
736 : }
737 :
738 0 : ret = ipa_ranges_parse_results(state, state->domain->name,
739 : reply_count, reply, &range_list);
740 0 : if (ret != EOK) {
741 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to parse range resulg [%d]: %s\n",
742 : ret, sss_strerror(ret));
743 0 : goto done;
744 : }
745 :
746 0 : ret = sysdb_update_ranges(state->domain->sysdb, range_list);
747 0 : talloc_free(range_list);
748 0 : if (ret != EOK) {
749 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to update ranges [%d]: %s\n",
750 : ret, sss_strerror(ret));
751 0 : goto done;
752 : }
753 :
754 : done:
755 0 : if (ret != EOK) {
756 0 : tevent_req_error(req, ret);
757 0 : return;
758 : }
759 :
760 0 : tevent_req_done(req);
761 : }
762 :
763 0 : static errno_t ipa_subdomains_ranges_recv(struct tevent_req *req)
764 : {
765 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
766 :
767 0 : return EOK;
768 : }
769 :
770 : struct ipa_subdomains_master_state {
771 : struct sss_domain_info *domain;
772 : struct ipa_options *ipa_options;
773 : };
774 :
775 : static void ipa_subdomains_master_done(struct tevent_req *subreq);
776 :
777 : static struct tevent_req *
778 0 : ipa_subdomains_master_send(TALLOC_CTX *mem_ctx,
779 : struct tevent_context *ev,
780 : struct ipa_subdomains_ctx *sd_ctx,
781 : struct sdap_handle *sh)
782 : {
783 : struct ipa_subdomains_master_state *state;
784 : struct sss_domain_info *domain;
785 : struct tevent_req *subreq;
786 : struct tevent_req *req;
787 : errno_t ret;
788 0 : const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_SID, NULL };
789 :
790 0 : req = tevent_req_create(mem_ctx, &state,
791 : struct ipa_subdomains_master_state);
792 0 : if (req == NULL) {
793 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
794 0 : return NULL;
795 : }
796 :
797 0 : if (sd_ctx->master_search_bases == NULL) {
798 0 : DEBUG(SSSDBG_TRACE_FUNC, "No search base is set\n");
799 0 : ret = EOK;
800 0 : goto immediately;
801 : }
802 :
803 0 : state->domain = domain = sd_ctx->be_ctx->domain;
804 0 : state->ipa_options = sd_ctx->ipa_id_ctx->ipa_options;
805 :
806 0 : ret = sysdb_master_domain_update(domain);
807 0 : if (ret != EOK) {
808 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to update master domain [%d]: %s\n",
809 : ret, sss_strerror(ret));
810 0 : goto immediately;
811 : }
812 :
813 0 : if (domain->flat_name != NULL && domain->domain_id != NULL
814 0 : && domain->realm != NULL) {
815 0 : DEBUG(SSSDBG_TRACE_FUNC, "Master record is up to date.\n");
816 0 : ret = EOK;
817 0 : goto immediately;
818 : }
819 :
820 0 : subreq = sdap_search_bases_return_first_send(state, ev,
821 0 : sd_ctx->sdap_id_ctx->opts, sh,
822 : sd_ctx->master_search_bases, NULL, false,
823 : 0, MASTER_DOMAIN_FILTER, attrs);
824 0 : if (subreq == NULL) {
825 0 : ret = ENOMEM;
826 0 : goto immediately;
827 : }
828 :
829 0 : tevent_req_set_callback(subreq, ipa_subdomains_master_done, req);
830 :
831 0 : return req;
832 :
833 : immediately:
834 0 : if (ret == EOK) {
835 0 : tevent_req_done(req);
836 : } else {
837 0 : tevent_req_error(req, ret);
838 : }
839 0 : tevent_req_post(req, ev);
840 :
841 0 : return req;
842 : }
843 :
844 0 : static void ipa_subdomains_master_done(struct tevent_req *subreq)
845 : {
846 : struct ipa_subdomains_master_state *state;
847 : struct tevent_req *req;
848 : struct sysdb_attrs **reply;
849 : size_t reply_count;
850 0 : const char *flat = NULL;
851 0 : const char *id = NULL;
852 0 : const char *realm = NULL;
853 : errno_t ret;
854 :
855 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
856 0 : state = tevent_req_data(req, struct ipa_subdomains_master_state);
857 :
858 0 : ret = sdap_search_bases_return_first_recv(subreq, state,
859 : &reply_count, &reply);
860 0 : talloc_zfree(subreq);
861 0 : if (ret != EOK) {
862 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get data from LDAP [%d]: %s\n",
863 : ret, sss_strerror(ret));
864 0 : goto done;
865 : }
866 :
867 0 : if (reply_count > 0) {
868 0 : ret = sysdb_attrs_get_string(reply[0], IPA_FLATNAME, &flat);
869 0 : if (ret != EOK) {
870 0 : goto done;
871 : }
872 :
873 0 : ret = sysdb_attrs_get_string(reply[0], IPA_SID, &id);
874 0 : if (ret != EOK) {
875 0 : goto done;
876 : }
877 : } else {
878 : /* All search paths are searched and no master domain record was
879 : * found.
880 : *
881 : * A default IPA installation will not have a master domain record,
882 : * this is only created by ipa-adtrust-install. Nevertheless we should
883 : * continue to read other data like the idview on IPA clients. */
884 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Master domain record not found!\n");
885 : }
886 :
887 0 : realm = dp_opt_get_string(state->ipa_options->basic, IPA_KRB5_REALM);
888 0 : if (realm == NULL) {
889 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
890 0 : ret = EINVAL;
891 0 : goto done;
892 : }
893 :
894 0 : ret = sysdb_master_domain_add_info(state->domain, realm, flat, id, NULL);
895 0 : if (ret != EOK) {
896 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add master domain info "
897 : "[%d]: %s\n", ret, sss_strerror(ret));
898 0 : goto done;
899 : }
900 :
901 0 : ret = EOK;
902 :
903 : done:
904 0 : if (ret != EOK) {
905 0 : tevent_req_error(req, ret);
906 0 : return;
907 : }
908 :
909 0 : tevent_req_done(req);
910 : }
911 :
912 0 : static errno_t ipa_subdomains_master_recv(struct tevent_req *req)
913 : {
914 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
915 :
916 0 : return EOK;
917 : }
918 :
919 : struct ipa_subdomains_slave_state {
920 : struct ipa_subdomains_ctx *sd_ctx;
921 : struct be_ctx *be_ctx;
922 : struct ipa_id_ctx *ipa_id_ctx;
923 : };
924 :
925 : static void ipa_subdomains_slave_search_done(struct tevent_req *subreq);
926 : static void ipa_subdomains_slave_trusts_done(struct tevent_req *subreq);
927 :
928 : static struct tevent_req *
929 0 : ipa_subdomains_slave_send(TALLOC_CTX *mem_ctx,
930 : struct tevent_context *ev,
931 : struct ipa_subdomains_ctx *sd_ctx,
932 : struct sdap_handle *sh)
933 : {
934 : struct ipa_subdomains_slave_state *state;
935 : struct tevent_req *subreq;
936 : struct tevent_req *req;
937 : errno_t ret;
938 0 : const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID,
939 : IPA_TRUST_DIRECTION, NULL };
940 :
941 0 : req = tevent_req_create(mem_ctx, &state,
942 : struct ipa_subdomains_slave_state);
943 0 : if (req == NULL) {
944 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
945 0 : return NULL;
946 : }
947 :
948 0 : if (sd_ctx->search_bases == NULL) {
949 0 : DEBUG(SSSDBG_TRACE_FUNC, "No search base is set\n");
950 0 : ret = EOK;
951 0 : goto immediately;
952 : }
953 :
954 0 : state->sd_ctx = sd_ctx;
955 0 : state->be_ctx = sd_ctx->be_ctx;
956 0 : state->ipa_id_ctx = sd_ctx->ipa_id_ctx;
957 :
958 0 : subreq = sdap_search_bases_send(state, ev, sd_ctx->sdap_id_ctx->opts, sh,
959 : sd_ctx->search_bases, NULL, false,
960 : 0, SUBDOMAINS_FILTER, attrs);
961 0 : if (subreq == NULL) {
962 0 : ret = ENOMEM;
963 0 : goto immediately;
964 : }
965 :
966 0 : tevent_req_set_callback(subreq, ipa_subdomains_slave_search_done, req);
967 :
968 0 : return req;
969 :
970 : immediately:
971 0 : if (ret == EOK) {
972 0 : tevent_req_done(req);
973 : } else {
974 0 : tevent_req_error(req, ret);
975 : }
976 0 : tevent_req_post(req, ev);
977 :
978 0 : return req;
979 : }
980 :
981 0 : static void ipa_subdomains_slave_search_done(struct tevent_req *subreq)
982 : {
983 : struct ipa_subdomains_slave_state *state;
984 : struct tevent_req *req;
985 : struct sysdb_attrs **reply;
986 : size_t reply_count;
987 : bool has_changes;
988 : errno_t ret;
989 :
990 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
991 0 : state = tevent_req_data(req, struct ipa_subdomains_slave_state);
992 :
993 0 : ret = sdap_search_bases_recv(subreq, state, &reply_count, &reply);
994 0 : talloc_zfree(subreq);
995 0 : if (ret != EOK) {
996 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get data from LDAP [%d]: %s\n",
997 : ret, sss_strerror(ret));
998 0 : goto done;
999 : }
1000 :
1001 0 : ret = ipa_subdomains_refresh(state->sd_ctx, reply_count, reply,
1002 : &has_changes);
1003 0 : if (ret != EOK) {
1004 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
1005 0 : goto done;
1006 : }
1007 :
1008 0 : if (!has_changes) {
1009 0 : ret = EOK;
1010 0 : goto done;
1011 : }
1012 :
1013 0 : ret = ipa_subdom_reinit(state->sd_ctx);
1014 0 : if (ret != EOK) {
1015 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
1016 0 : goto done;
1017 : }
1018 :
1019 0 : if (state->sd_ctx->ipa_id_ctx->server_mode == NULL) {
1020 0 : ret = EOK;
1021 0 : goto done;
1022 : }
1023 :
1024 0 : subreq = ipa_server_create_trusts_send(state, state->be_ctx->ev,
1025 : state->be_ctx, state->ipa_id_ctx,
1026 0 : state->be_ctx->domain);
1027 0 : if (subreq == NULL) {
1028 0 : ret = ENOMEM;
1029 0 : goto done;
1030 : }
1031 0 : tevent_req_set_callback(subreq, ipa_subdomains_slave_trusts_done, req);
1032 0 : return;
1033 :
1034 : done:
1035 0 : if (ret != EOK) {
1036 0 : tevent_req_error(req, ret);
1037 0 : return;
1038 : }
1039 :
1040 0 : tevent_req_done(req);
1041 : }
1042 :
1043 0 : static void ipa_subdomains_slave_trusts_done(struct tevent_req *subreq)
1044 : {
1045 : struct tevent_req *req;
1046 : errno_t ret;
1047 :
1048 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1049 :
1050 0 : ret = ipa_server_create_trusts_recv(subreq);
1051 0 : talloc_zfree(subreq);
1052 0 : if (ret != EOK) {
1053 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create trusts [%d]: %s\n",
1054 : ret, sss_strerror(ret));
1055 0 : tevent_req_error(req, ret);
1056 0 : return;
1057 : }
1058 :
1059 0 : tevent_req_done(req);
1060 : }
1061 :
1062 0 : static errno_t ipa_subdomains_slave_recv(struct tevent_req *req)
1063 : {
1064 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1065 :
1066 0 : return EOK;
1067 : }
1068 :
1069 : struct ipa_subdomains_view_name_state {
1070 : struct ipa_subdomains_ctx *sd_ctx;
1071 : };
1072 :
1073 : static void ipa_subdomains_view_name_done(struct tevent_req *subreq);
1074 :
1075 : static struct tevent_req *
1076 0 : ipa_subdomains_view_name_send(TALLOC_CTX *mem_ctx,
1077 : struct tevent_context *ev,
1078 : struct ipa_subdomains_ctx *sd_ctx,
1079 : struct sdap_handle *sh)
1080 : {
1081 : struct ipa_subdomains_view_name_state *state;
1082 : struct sdap_attr_map_info *maps;
1083 : struct tevent_req *subreq;
1084 : struct tevent_req *req;
1085 : struct ipa_options *ipa_options;
1086 : const char *filter;
1087 0 : const char *attrs[] = {IPA_CN, OBJECTCLASS, NULL};
1088 : errno_t ret;
1089 :
1090 0 : req = tevent_req_create(mem_ctx, &state,
1091 : struct ipa_subdomains_view_name_state);
1092 0 : if (req == NULL) {
1093 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1094 0 : return NULL;
1095 : }
1096 :
1097 0 : if (sd_ctx->ipa_id_ctx->server_mode != NULL) {
1098 : /* Only get view on clients, on servers it is always 'default'. */
1099 0 : ret = EOK;
1100 0 : goto immediately;
1101 : }
1102 :
1103 0 : state->sd_ctx = sd_ctx;
1104 :
1105 0 : ipa_options = sd_ctx->ipa_id_ctx->ipa_options;
1106 :
1107 0 : maps = talloc_zero_array(state, struct sdap_attr_map_info, 2);
1108 0 : if (maps == NULL) {
1109 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero() failed\n");
1110 0 : ret = ENOMEM;
1111 0 : goto immediately;
1112 : }
1113 0 : maps[0].map = ipa_options->view_map;
1114 0 : maps->num_attrs = IPA_OPTS_VIEW;
1115 :
1116 0 : filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=%s))",
1117 0 : ipa_options->host_map[IPA_OC_HOST].name,
1118 0 : ipa_options->host_map[IPA_AT_HOST_FQDN].name,
1119 : dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME));
1120 0 : if (filter == NULL) {
1121 0 : ret = ENOMEM;
1122 0 : goto immediately;
1123 : }
1124 :
1125 : /* We add SDAP_DEREF_FLG_SILENT because old IPA servers don't have
1126 : * the attribute we dereference, causing the deref call to fail. */
1127 0 : subreq = sdap_deref_bases_return_first_send(state, ev,
1128 0 : sd_ctx->sdap_id_ctx->opts, sh, sd_ctx->host_search_bases,
1129 : maps, filter, attrs, IPA_ASSIGNED_ID_VIEW,
1130 : SDAP_DEREF_FLG_SILENT, 0);
1131 0 : if (subreq == NULL) {
1132 0 : ret = ENOMEM;
1133 0 : goto immediately;
1134 : }
1135 :
1136 0 : tevent_req_set_callback(subreq, ipa_subdomains_view_name_done, req);
1137 :
1138 0 : return req;
1139 :
1140 : immediately:
1141 0 : if (ret == EOK) {
1142 0 : tevent_req_done(req);
1143 : } else {
1144 0 : tevent_req_error(req, ret);
1145 : }
1146 0 : tevent_req_post(req, ev);
1147 :
1148 0 : return req;
1149 : }
1150 :
1151 0 : static void ipa_subdomains_view_name_done(struct tevent_req *subreq)
1152 : {
1153 : struct ipa_subdomains_view_name_state *state;
1154 : struct tevent_req *req;
1155 : size_t reply_count;
1156 : struct sdap_deref_attrs **reply;
1157 : const char *view_name;
1158 : errno_t ret;
1159 :
1160 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1161 0 : state = tevent_req_data(req, struct ipa_subdomains_view_name_state);
1162 :
1163 0 : ret = sdap_deref_bases_return_first_recv(subreq, state,
1164 : &reply_count, &reply);
1165 0 : talloc_zfree(subreq);
1166 0 : if (ret != EOK) {
1167 : /* Depending on the version 389ds return a different error code if the
1168 : * search for the view name failed because our dereference attribute
1169 : * ipaAssignedIDView is not known. Newer version return
1170 : * LDAP_UNAVAILABLE_CRITICAL_EXTENSION(12) which is translated to
1171 : * EOPNOTSUPP and older versions return LDAP_PROTOCOL_ERROR(2) which
1172 : * is returned as EIO. In both cases we have to assume that the server
1173 : * is not view aware and keep the view name unset. */
1174 0 : if (ret == EOPNOTSUPP || ret == EIO) {
1175 0 : DEBUG(SSSDBG_TRACE_FUNC, "Unable to get view name, looks " \
1176 : "like server does not support views.\n");
1177 0 : ret = EOK;
1178 0 : goto done;
1179 : }
1180 :
1181 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to get view name [%d]: %s\n",
1182 : ret, sss_strerror(ret));
1183 0 : goto done;
1184 : }
1185 :
1186 0 : if (reply_count == 0) {
1187 0 : DEBUG(SSSDBG_TRACE_FUNC, "No view found, using default.\n");
1188 0 : view_name = SYSDB_DEFAULT_VIEW_NAME;
1189 0 : } else if (reply_count == 1) {
1190 0 : ret = sysdb_attrs_get_string(reply[0]->attrs, SYSDB_VIEW_NAME,
1191 : &view_name);
1192 0 : if (ret != EOK) {
1193 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
1194 0 : goto done;
1195 : }
1196 : } else {
1197 0 : DEBUG(SSSDBG_CRIT_FAILURE, "More than one object returned.\n");
1198 0 : ret = EINVAL;
1199 0 : goto done;
1200 : }
1201 :
1202 0 : ret = ipa_apply_view(state->sd_ctx->be_ctx->domain,
1203 0 : state->sd_ctx->ipa_id_ctx, view_name,
1204 0 : state->sd_ctx->view_read_at_init);
1205 0 : if (ret != EOK) {
1206 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set view [%d]: %s\n",
1207 : ret, sss_strerror(ret));
1208 0 : goto done;
1209 : }
1210 :
1211 0 : state->sd_ctx->view_read_at_init = true;
1212 :
1213 : done:
1214 0 : if (ret != EOK) {
1215 0 : tevent_req_error(req, ret);
1216 0 : return;
1217 : }
1218 :
1219 0 : tevent_req_done(req);
1220 : }
1221 :
1222 0 : static errno_t ipa_subdomains_view_name_recv(struct tevent_req *req)
1223 : {
1224 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1225 :
1226 0 : return EOK;
1227 : }
1228 :
1229 :
1230 : struct ipa_subdomains_refresh_state {
1231 : struct tevent_context *ev;
1232 : struct ipa_subdomains_ctx *sd_ctx;
1233 : struct sdap_id_op *sdap_op;
1234 : };
1235 :
1236 : static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req);
1237 : static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq);
1238 : static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq);
1239 : static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq);
1240 : static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq);
1241 : static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq);
1242 :
1243 : static struct tevent_req *
1244 0 : ipa_subdomains_refresh_send(TALLOC_CTX *mem_ctx,
1245 : struct tevent_context *ev,
1246 : struct ipa_subdomains_ctx *sd_ctx)
1247 : {
1248 : struct ipa_subdomains_refresh_state *state;
1249 : struct tevent_req *req;
1250 : errno_t ret;
1251 :
1252 0 : req = tevent_req_create(mem_ctx, &state,
1253 : struct ipa_subdomains_refresh_state);
1254 0 : if (req == NULL) {
1255 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1256 0 : return NULL;
1257 : }
1258 :
1259 0 : state->ev = ev;
1260 0 : state->sd_ctx = sd_ctx;
1261 :
1262 0 : state->sdap_op = sdap_id_op_create(state,
1263 0 : sd_ctx->sdap_id_ctx->conn->conn_cache);
1264 0 : if (state->sdap_op == NULL) {
1265 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
1266 0 : ret = ENOMEM;
1267 0 : goto immediately;
1268 : }
1269 :
1270 0 : ret = ipa_subdomains_refresh_retry(req);
1271 0 : if (ret == EAGAIN) {
1272 : /* asynchronous processing */
1273 0 : return req;
1274 : }
1275 :
1276 : immediately:
1277 0 : if (ret == EOK) {
1278 0 : tevent_req_done(req);
1279 : } else {
1280 0 : tevent_req_error(req, ret);
1281 : }
1282 0 : tevent_req_post(req, ev);
1283 :
1284 0 : return req;
1285 : }
1286 :
1287 0 : static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req)
1288 : {
1289 : struct ipa_subdomains_refresh_state *state;
1290 : struct tevent_req *subreq;
1291 : int ret;
1292 :
1293 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1294 :
1295 0 : subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
1296 0 : if (subreq == NULL) {
1297 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
1298 : "[%d]: %s\n", ret, sss_strerror(ret));
1299 0 : return ret;
1300 : }
1301 :
1302 0 : tevent_req_set_callback(subreq, ipa_subdomains_refresh_connect_done, req);
1303 :
1304 0 : return EAGAIN;
1305 : }
1306 :
1307 0 : static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq)
1308 : {
1309 : struct ipa_subdomains_refresh_state *state;
1310 : struct tevent_req *req;
1311 : int dp_error;
1312 : errno_t ret;
1313 :
1314 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1315 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1316 :
1317 0 : ret = sdap_id_op_connect_recv(subreq, &dp_error);
1318 0 : talloc_zfree(subreq);
1319 :
1320 0 : if (ret != EOK) {
1321 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
1322 : "[%d]: %s\n", ret, sss_strerror(ret));
1323 0 : if (dp_error == DP_ERR_OFFLINE) {
1324 0 : DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, "
1325 : "cannot get the subdomain list while offline\n");
1326 0 : ret = ERR_OFFLINE;
1327 : }
1328 0 : tevent_req_error(req, ret);
1329 0 : return;
1330 : }
1331 :
1332 0 : subreq = ipa_subdomains_ranges_send(state, state->ev, state->sd_ctx,
1333 : sdap_id_op_handle(state->sdap_op));
1334 0 : if (subreq == NULL) {
1335 0 : tevent_req_error(req, ENOMEM);
1336 0 : return;
1337 : }
1338 :
1339 0 : tevent_req_set_callback(subreq, ipa_subdomains_refresh_ranges_done, req);
1340 0 : return;
1341 : }
1342 :
1343 0 : static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq)
1344 : {
1345 : struct ipa_subdomains_refresh_state *state;
1346 : struct tevent_req *req;
1347 : errno_t ret;
1348 :
1349 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1350 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1351 :
1352 0 : ret = ipa_subdomains_ranges_recv(subreq);
1353 0 : talloc_zfree(subreq);
1354 0 : if (ret != EOK) {
1355 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get IPA ranges "
1356 : "[%d]: %s\n", ret, sss_strerror(ret));
1357 0 : tevent_req_error(req, ret);
1358 0 : return;
1359 : }
1360 :
1361 0 : subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx,
1362 : sdap_id_op_handle(state->sdap_op));
1363 0 : if (subreq == NULL) {
1364 0 : tevent_req_error(req, ENOMEM);
1365 0 : return;
1366 : }
1367 :
1368 0 : tevent_req_set_callback(subreq, ipa_subdomains_refresh_master_done, req);
1369 0 : return;
1370 : }
1371 :
1372 0 : static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq)
1373 : {
1374 : struct ipa_subdomains_refresh_state *state;
1375 : struct tevent_req *req;
1376 : errno_t ret;
1377 :
1378 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1379 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1380 :
1381 0 : ret = ipa_subdomains_master_recv(subreq);
1382 0 : talloc_zfree(subreq);
1383 0 : if (ret != EOK) {
1384 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get master domain "
1385 : "[%d]: %s\n", ret, sss_strerror(ret));
1386 0 : tevent_req_error(req, ret);
1387 0 : return;
1388 : }
1389 :
1390 0 : subreq = ipa_subdomains_slave_send(state, state->ev, state->sd_ctx,
1391 : sdap_id_op_handle(state->sdap_op));
1392 0 : if (subreq == NULL) {
1393 0 : tevent_req_error(req, ENOMEM);
1394 0 : return;
1395 : }
1396 :
1397 0 : tevent_req_set_callback(subreq, ipa_subdomains_refresh_slave_done, req);
1398 0 : return;
1399 : }
1400 :
1401 0 : static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq)
1402 : {
1403 : struct ipa_subdomains_refresh_state *state;
1404 : struct tevent_req *req;
1405 : errno_t ret;
1406 :
1407 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1408 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1409 :
1410 0 : ret = ipa_subdomains_slave_recv(subreq);
1411 0 : talloc_zfree(subreq);
1412 0 : if (ret != EOK) {
1413 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get subdomains "
1414 : "[%d]: %s\n", ret, sss_strerror(ret));
1415 0 : tevent_req_error(req, ret);
1416 0 : return;
1417 : }
1418 :
1419 0 : subreq = ipa_subdomains_view_name_send(state, state->ev, state->sd_ctx,
1420 : sdap_id_op_handle(state->sdap_op));
1421 0 : if (subreq == NULL) {
1422 0 : tevent_req_error(req, ENOMEM);
1423 0 : return;
1424 : }
1425 :
1426 0 : tevent_req_set_callback(subreq, ipa_subdomains_refresh_view_done, req);
1427 0 : return;
1428 : }
1429 :
1430 0 : static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq)
1431 : {
1432 : struct ipa_subdomains_refresh_state *state;
1433 : struct tevent_req *req;
1434 : int dp_error;
1435 : errno_t ret;
1436 :
1437 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1438 0 : state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
1439 :
1440 0 : ret = ipa_subdomains_view_name_recv(subreq);
1441 0 : talloc_zfree(subreq);
1442 0 : ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
1443 0 : if (dp_error == DP_ERR_OK && ret != EOK) {
1444 : /* retry */
1445 0 : ret = ipa_subdomains_refresh_retry(req);
1446 0 : if (ret != EOK) {
1447 0 : goto done;
1448 : }
1449 0 : return;
1450 0 : } else if (dp_error == DP_ERR_OFFLINE) {
1451 0 : ret = ERR_OFFLINE;
1452 0 : goto done;
1453 0 : } else if (ret != EOK) {
1454 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get view name "
1455 : "[%d]: %s\n", ret, sss_strerror(ret));
1456 0 : goto done;
1457 : }
1458 :
1459 : done:
1460 0 : if (ret != EOK) {
1461 0 : DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n",
1462 : ret, sss_strerror(ret));
1463 0 : tevent_req_error(req, ret);
1464 0 : return;
1465 : }
1466 :
1467 0 : DEBUG(SSSDBG_TRACE_FUNC, "Subdomains refreshed.\n");
1468 0 : tevent_req_done(req);
1469 : }
1470 :
1471 0 : static errno_t ipa_subdomains_refresh_recv(struct tevent_req *req)
1472 : {
1473 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1474 :
1475 0 : return EOK;
1476 : }
1477 :
1478 : struct ipa_subdomains_handler_state {
1479 : struct dp_reply_std reply;
1480 : };
1481 :
1482 : static void ipa_subdomains_handler_done(struct tevent_req *subreq);
1483 :
1484 : static struct tevent_req *
1485 0 : ipa_subdomains_handler_send(TALLOC_CTX *mem_ctx,
1486 : struct ipa_subdomains_ctx *sd_ctx,
1487 : struct dp_subdomains_data *data,
1488 : struct dp_req_params *params)
1489 : {
1490 : struct ipa_subdomains_handler_state *state;
1491 : struct tevent_req *req;
1492 : struct tevent_req *subreq;
1493 : errno_t ret;
1494 :
1495 0 : req = tevent_req_create(mem_ctx, &state,
1496 : struct ipa_subdomains_handler_state);
1497 0 : if (req == NULL) {
1498 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1499 0 : return NULL;
1500 : }
1501 :
1502 :
1503 0 : if (sd_ctx->last_refreshed > time(NULL) - IPA_SUBDOMAIN_REFRESH_LIMIT) {
1504 0 : DEBUG(SSSDBG_TRACE_FUNC, "Subdomains were recently refreshed, "
1505 : "nothing to do\n");
1506 0 : ret = EOK;
1507 0 : goto immediately;
1508 : }
1509 :
1510 0 : subreq = ipa_subdomains_refresh_send(state, params->ev, sd_ctx);
1511 0 : if (subreq == NULL) {
1512 0 : ret = ENOMEM;
1513 0 : goto immediately;
1514 : }
1515 :
1516 0 : tevent_req_set_callback(subreq, ipa_subdomains_handler_done, req);
1517 :
1518 0 : return req;
1519 :
1520 : immediately:
1521 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
1522 :
1523 : /* TODO For backward compatibility we always return EOK to DP now. */
1524 0 : tevent_req_done(req);
1525 0 : tevent_req_post(req, params->ev);
1526 :
1527 0 : return req;
1528 : }
1529 :
1530 0 : static void ipa_subdomains_handler_done(struct tevent_req *subreq)
1531 : {
1532 : struct ipa_subdomains_handler_state *state;
1533 : struct tevent_req *req;
1534 : errno_t ret;
1535 :
1536 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
1537 0 : state = tevent_req_data(req, struct ipa_subdomains_handler_state);
1538 :
1539 0 : ret = ipa_subdomains_refresh_recv(subreq);
1540 0 : talloc_zfree(subreq);
1541 0 : if (ret != EOK) {
1542 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh subdomains [%d]: %s\n",
1543 : ret, sss_strerror(ret));
1544 : }
1545 :
1546 : /* TODO For backward compatibility we always return EOK to DP now. */
1547 0 : dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
1548 0 : tevent_req_done(req);
1549 0 : }
1550 :
1551 0 : static errno_t ipa_subdomains_handler_recv(TALLOC_CTX *mem_ctx,
1552 : struct tevent_req *req,
1553 : struct dp_reply_std *data)
1554 : {
1555 : struct ipa_subdomains_handler_state *state;
1556 :
1557 0 : state = tevent_req_data(req, struct ipa_subdomains_handler_state);
1558 :
1559 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
1560 :
1561 0 : *data = state->reply;
1562 :
1563 0 : return EOK;
1564 : }
1565 :
1566 : static struct tevent_req *
1567 0 : ipa_subdomains_ptask_send(TALLOC_CTX *mem_ctx,
1568 : struct tevent_context *ev,
1569 : struct be_ctx *be_ctx,
1570 : struct be_ptask *be_ptask,
1571 : void *pvt)
1572 : {
1573 : struct ipa_subdomains_ctx *sd_ctx;
1574 0 : sd_ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
1575 :
1576 0 : return ipa_subdomains_refresh_send(mem_ctx, ev, sd_ctx);
1577 : }
1578 :
1579 : static errno_t
1580 0 : ipa_subdomains_ptask_recv(struct tevent_req *req)
1581 : {
1582 0 : return ipa_subdomains_refresh_recv(req);
1583 : }
1584 :
1585 0 : errno_t ipa_subdomains_init(TALLOC_CTX *mem_ctx,
1586 : struct be_ctx *be_ctx,
1587 : struct ipa_id_ctx *ipa_id_ctx,
1588 : struct dp_method *dp_methods)
1589 : {
1590 : struct ipa_subdomains_ctx *sd_ctx;
1591 : struct ipa_options *ipa_options;
1592 : time_t period;
1593 : errno_t ret;
1594 :
1595 0 : ipa_options = ipa_id_ctx->ipa_options;
1596 :
1597 0 : sd_ctx = talloc_zero(mem_ctx, struct ipa_subdomains_ctx);
1598 0 : if (sd_ctx == NULL) {
1599 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
1600 0 : return ENOMEM;
1601 : }
1602 :
1603 0 : sd_ctx->be_ctx = be_ctx;
1604 0 : sd_ctx->ipa_id_ctx = ipa_id_ctx;
1605 0 : sd_ctx->sdap_id_ctx = ipa_id_ctx->sdap_id_ctx;
1606 0 : sd_ctx->search_bases = ipa_options->subdomains_search_bases;
1607 0 : sd_ctx->master_search_bases = ipa_options->master_domain_search_bases;
1608 0 : sd_ctx->ranges_search_bases = ipa_options->ranges_search_bases;
1609 0 : sd_ctx->host_search_bases = ipa_options->host_search_bases;
1610 :
1611 0 : dp_set_method(dp_methods, DPM_DOMAINS_HANDLER,
1612 : ipa_subdomains_handler_send, ipa_subdomains_handler_recv, sd_ctx,
1613 : struct ipa_subdomains_ctx, struct dp_subdomains_data, struct dp_reply_std);
1614 :
1615 0 : period = be_ctx->domain->subdomain_refresh_interval;
1616 0 : ret = be_ptask_create(sd_ctx, be_ctx, period, 0, 0, 0, period,
1617 : BE_PTASK_OFFLINE_DISABLE, 0,
1618 : ipa_subdomains_ptask_send, ipa_subdomains_ptask_recv, sd_ctx,
1619 : "Subdomains Refresh", NULL);
1620 0 : if (ret != EOK) {
1621 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask "
1622 : "[%d]: %s\n", ret, sss_strerror(ret));
1623 : /* Ignore, responders will trigger refresh from time to time. */
1624 : }
1625 :
1626 0 : ret = ipa_subdom_reinit(sd_ctx);
1627 0 : if (ret != EOK) {
1628 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not reinitialize subdomains. "
1629 : "Users from trusted domains might not be resolved correctly\n");
1630 : /* Ignore this error and try to discover the subdomains later */
1631 : }
1632 :
1633 0 : ret = ipa_ad_subdom_init(be_ctx, ipa_id_ctx);
1634 0 : if (ret != EOK) {
1635 0 : DEBUG(SSSDBG_CRIT_FAILURE, "ipa_ad_subdom_init() failed.\n");
1636 0 : return ret;
1637 : }
1638 :
1639 0 : return EOK;
1640 : }
|