Line data Source code
1 : /*
2 : SSSD
3 :
4 : System Database - Sub-domain related calls
5 :
6 : Copyright (C) 2012 Jan Zeleny <jzeleny@redhat.com>
7 : Copyright (C) 2012 Sumit Bose <sbose@redhat.com>
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "util/util.h"
24 : #include "db/sysdb_private.h"
25 :
26 47 : struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
27 : struct sss_domain_info *parent,
28 : const char *name,
29 : const char *realm,
30 : const char *flat_name,
31 : const char *id,
32 : bool mpg,
33 : bool enumerate,
34 : const char *forest,
35 : uint32_t trust_direction)
36 : {
37 : struct sss_domain_info *dom;
38 : bool inherit_option;
39 :
40 47 : DEBUG(SSSDBG_TRACE_FUNC,
41 : "Creating [%s] as subdomain of [%s]!\n", name, parent->name);
42 :
43 47 : dom = talloc_zero(mem_ctx, struct sss_domain_info);
44 47 : if (dom == NULL) {
45 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
46 0 : return NULL;
47 : }
48 :
49 47 : dom->parent = parent;
50 :
51 : /* Sub-domains always have the same view as the parent */
52 47 : dom->has_views = parent->has_views;
53 47 : if (parent->view_name != NULL) {
54 5 : dom->view_name = talloc_strdup(dom, parent->view_name);
55 5 : if (dom->view_name == NULL) {
56 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy parent's view name.\n");
57 0 : goto fail;
58 : }
59 : }
60 :
61 47 : dom->name = talloc_strdup(dom, name);
62 47 : if (dom->name == NULL) {
63 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy domain name.\n");
64 0 : goto fail;
65 : }
66 :
67 47 : dom->provider = talloc_strdup(dom, parent->provider);
68 47 : if (dom->provider == NULL) {
69 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy provider name.\n");
70 0 : goto fail;
71 : }
72 :
73 47 : dom->conn_name = talloc_strdup(dom, parent->conn_name);
74 47 : if (dom->conn_name == NULL) {
75 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy connection name.\n");
76 0 : goto fail;
77 : }
78 :
79 47 : if (realm != NULL) {
80 40 : dom->realm = talloc_strdup(dom, realm);
81 40 : if (dom->realm == NULL) {
82 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy realm name.\n");
83 0 : goto fail;
84 : }
85 : }
86 :
87 47 : if (flat_name != NULL) {
88 40 : dom->flat_name = talloc_strdup(dom, flat_name);
89 40 : if (dom->flat_name == NULL) {
90 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy flat name.\n");
91 0 : goto fail;
92 : }
93 : }
94 :
95 47 : if (id != NULL) {
96 40 : dom->domain_id = talloc_strdup(dom, id);
97 40 : if (dom->domain_id == NULL) {
98 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy id.\n");
99 0 : goto fail;
100 : }
101 : }
102 :
103 47 : if (forest != NULL) {
104 23 : dom->forest = talloc_strdup(dom, forest);
105 23 : if (dom->forest == NULL) {
106 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy forest.\n");
107 0 : goto fail;
108 : }
109 : }
110 :
111 47 : dom->enumerate = enumerate;
112 47 : dom->fqnames = true;
113 47 : dom->mpg = mpg;
114 47 : dom->state = DOM_ACTIVE;
115 :
116 : /* If the parent domain filters out group members, the subdomain should
117 : * as well if configured */
118 47 : inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS,
119 : parent->sd_inherit, false);
120 47 : if (inherit_option) {
121 0 : dom->ignore_group_members = parent->ignore_group_members;
122 : }
123 :
124 47 : dom->trust_direction = trust_direction;
125 : /* If the parent domain explicitly limits ID ranges, the subdomain
126 : * should honour the limits as well.
127 : */
128 47 : dom->id_min = parent->id_min ? parent->id_min : 0;
129 47 : dom->id_max = parent->id_max ? parent->id_max : 0xffffffff;
130 47 : dom->pwd_expiration_warning = parent->pwd_expiration_warning;
131 47 : dom->cache_credentials = parent->cache_credentials;
132 47 : dom->cache_credentials_min_ff_length =
133 47 : parent->cache_credentials_min_ff_length;
134 47 : dom->case_sensitive = false;
135 47 : dom->user_timeout = parent->user_timeout;
136 47 : dom->group_timeout = parent->group_timeout;
137 47 : dom->netgroup_timeout = parent->netgroup_timeout;
138 47 : dom->service_timeout = parent->service_timeout;
139 47 : dom->names = parent->names;
140 :
141 47 : dom->override_homedir = parent->override_homedir;
142 47 : dom->fallback_homedir = parent->fallback_homedir;
143 47 : dom->subdomain_homedir = parent->subdomain_homedir;
144 47 : dom->override_shell = parent->override_shell;
145 47 : dom->default_shell = parent->default_shell;
146 47 : dom->homedir_substr = parent->homedir_substr;
147 :
148 47 : if (parent->sysdb == NULL) {
149 0 : DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n");
150 0 : goto fail;
151 : }
152 47 : dom->sysdb = parent->sysdb;
153 :
154 47 : return dom;
155 :
156 : fail:
157 0 : talloc_free(dom);
158 0 : return NULL;
159 : }
160 :
161 50 : static bool is_forest_root(struct sss_domain_info *d)
162 : {
163 50 : if (d->forest == NULL) {
164 : /* IPA subdomain provider saves/saved trusted forest root domains
165 : * without the forest attribute. Those are automatically forest
166 : * roots
167 : */
168 37 : return true;
169 : }
170 :
171 13 : if (d->realm && (strcasecmp(d->forest, d->realm) == 0)) {
172 13 : return true;
173 : }
174 :
175 0 : return false;
176 : }
177 :
178 62 : static bool is_same_forest(struct sss_domain_info *root,
179 : struct sss_domain_info *member)
180 : {
181 62 : if (member->forest != NULL
182 34 : && root->realm != NULL
183 30 : && strcasecmp(member->forest, root->realm) == 0) {
184 14 : return true;
185 : }
186 :
187 48 : return false;
188 : }
189 :
190 22 : static void link_forest_roots(struct sss_domain_info *domain)
191 : {
192 : struct sss_domain_info *d;
193 : struct sss_domain_info *dd;
194 :
195 86 : for (d = domain; d; d = get_next_domain(d, true)) {
196 64 : d->forest_root = NULL;
197 : }
198 :
199 86 : for (d = domain; d; d = get_next_domain(d, true)) {
200 64 : if (d->forest_root != NULL) {
201 14 : continue;
202 : }
203 :
204 50 : if (is_forest_root(d) == true) {
205 50 : d->forest_root = d;
206 50 : DEBUG(SSSDBG_TRACE_INTERNAL, "[%s] is a forest root\n", d->name);
207 :
208 207 : for (dd = domain; dd; dd = get_next_domain(dd, true)) {
209 157 : if (dd->forest_root != NULL) {
210 95 : continue;
211 : }
212 :
213 62 : if (is_same_forest(d, dd) == true) {
214 14 : dd->forest_root = d;
215 14 : DEBUG(SSSDBG_TRACE_INTERNAL,
216 : "[%s] is a forest root of [%s]\n",
217 : d->forest_root->name,
218 : dd->name);
219 : }
220 : }
221 : }
222 : }
223 22 : }
224 :
225 29 : errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
226 : {
227 : int i;
228 : errno_t ret;
229 : TALLOC_CTX *tmp_ctx;
230 : struct ldb_result *res;
231 29 : const char *attrs[] = {"cn",
232 : SYSDB_SUBDOMAIN_REALM,
233 : SYSDB_SUBDOMAIN_FLAT,
234 : SYSDB_SUBDOMAIN_ID,
235 : SYSDB_SUBDOMAIN_MPG,
236 : SYSDB_SUBDOMAIN_ENUM,
237 : SYSDB_SUBDOMAIN_FOREST,
238 : SYSDB_SUBDOMAIN_TRUST_DIRECTION,
239 : NULL};
240 : struct sss_domain_info *dom;
241 : struct ldb_dn *basedn;
242 : const char *name;
243 : const char *realm;
244 : const char *flat;
245 : const char *id;
246 : const char *forest;
247 : bool mpg;
248 : bool enumerate;
249 : uint32_t trust_direction;
250 :
251 29 : tmp_ctx = talloc_new(NULL);
252 29 : if (tmp_ctx == NULL) {
253 0 : ret = ENOMEM;
254 0 : goto done;
255 : }
256 :
257 29 : basedn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, SYSDB_BASE);
258 29 : if (basedn == NULL) {
259 0 : ret = EIO;
260 0 : goto done;
261 : }
262 29 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
263 : basedn, LDB_SCOPE_ONELEVEL,
264 : attrs, "objectclass=%s", SYSDB_SUBDOMAIN_CLASS);
265 29 : if (ret != LDB_SUCCESS) {
266 0 : ret = EIO;
267 0 : goto done;
268 : }
269 :
270 : /* disable all domains,
271 : * let the search result refresh any that are still valid */
272 34 : for (dom = domain->subdomains; dom; dom = get_next_domain(dom, false)) {
273 5 : sss_domain_set_state(dom, DOM_DISABLED);
274 : }
275 :
276 29 : if (res->count == 0) {
277 7 : ret = EOK;
278 7 : goto done;
279 : }
280 :
281 57 : for (i = 0; i < res->count; i++) {
282 :
283 35 : name = ldb_msg_find_attr_as_string(res->msgs[i], "cn", NULL);
284 35 : if (name == NULL) {
285 0 : DEBUG(SSSDBG_MINOR_FAILURE,
286 : "The object [%s] doesn't have a name\n",
287 : ldb_dn_get_linearized(res->msgs[i]->dn));
288 0 : ret = EINVAL;
289 0 : goto done;
290 : }
291 :
292 35 : realm = ldb_msg_find_attr_as_string(res->msgs[i],
293 : SYSDB_SUBDOMAIN_REALM, NULL);
294 :
295 35 : flat = ldb_msg_find_attr_as_string(res->msgs[i],
296 : SYSDB_SUBDOMAIN_FLAT, NULL);
297 :
298 35 : id = ldb_msg_find_attr_as_string(res->msgs[i],
299 : SYSDB_SUBDOMAIN_ID, NULL);
300 :
301 35 : mpg = ldb_msg_find_attr_as_bool(res->msgs[i],
302 : SYSDB_SUBDOMAIN_MPG, false);
303 :
304 35 : enumerate = ldb_msg_find_attr_as_bool(res->msgs[i],
305 : SYSDB_SUBDOMAIN_ENUM, false);
306 :
307 35 : forest = ldb_msg_find_attr_as_string(res->msgs[i],
308 : SYSDB_SUBDOMAIN_FOREST, NULL);
309 :
310 35 : trust_direction = ldb_msg_find_attr_as_int(res->msgs[i],
311 : SYSDB_SUBDOMAIN_TRUST_DIRECTION,
312 : 0);
313 :
314 : /* explicitly use dom->next as we need to check 'disabled' domains */
315 51 : for (dom = domain->subdomains; dom; dom = dom->next) {
316 19 : if (strcasecmp(dom->name, name) == 0) {
317 3 : sss_domain_set_state(dom, DOM_ACTIVE);
318 :
319 : /* in theory these may change, but it should never happen */
320 3 : if (strcasecmp(dom->realm, realm) != 0) {
321 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
322 : "Realm name changed from [%s] to [%s]!\n",
323 : dom->realm, realm);
324 0 : talloc_zfree(dom->realm);
325 0 : dom->realm = talloc_strdup(dom, realm);
326 0 : if (dom->realm == NULL) {
327 0 : ret = ENOMEM;
328 0 : goto done;
329 : }
330 : }
331 3 : if (strcasecmp(dom->flat_name, flat) != 0) {
332 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
333 : "Flat name changed from [%s] to [%s]!\n",
334 : dom->flat_name, flat);
335 0 : talloc_zfree(dom->flat_name);
336 0 : dom->flat_name = talloc_strdup(dom, flat);
337 0 : if (dom->flat_name == NULL) {
338 0 : ret = ENOMEM;
339 0 : goto done;
340 : }
341 : }
342 3 : if (strcasecmp(dom->domain_id, id) != 0) {
343 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
344 : "Domain changed from [%s] to [%s]!\n",
345 : dom->domain_id, id);
346 0 : talloc_zfree(dom->domain_id);
347 0 : dom->domain_id = talloc_strdup(dom, id);
348 0 : if (dom->domain_id == NULL) {
349 0 : ret = ENOMEM;
350 0 : goto done;
351 : }
352 : }
353 :
354 3 : if (dom->mpg != mpg) {
355 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
356 : "MPG state change from [%s] to [%s]!\n",
357 : dom->mpg ? "true" : "false",
358 : mpg ? "true" : "false");
359 0 : dom->mpg = mpg;
360 : }
361 :
362 3 : if (dom->enumerate != enumerate) {
363 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
364 : "enumerate state change from [%s] to [%s]!\n",
365 : dom->enumerate ? "true" : "false",
366 : enumerate ? "true" : "false");
367 0 : dom->enumerate = enumerate;
368 : }
369 :
370 3 : if ((dom->forest == NULL && forest != NULL)
371 3 : || (dom->forest != NULL && forest != NULL
372 0 : && strcasecmp(dom->forest, forest) != 0)) {
373 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
374 : "Forest changed from [%s] to [%s]!\n",
375 : dom->forest, forest);
376 0 : talloc_zfree(dom->forest);
377 0 : dom->forest = talloc_strdup(dom, forest);
378 0 : if (dom->forest == NULL) {
379 0 : ret = ENOMEM;
380 0 : goto done;
381 : }
382 : }
383 :
384 3 : if (!dom->has_views && dom->view_name == NULL) {
385 : /* maybe views are not initialized, copy from parent */
386 3 : dom->has_views = dom->parent->has_views;
387 6 : if (dom->parent->view_name != NULL) {
388 0 : dom->view_name = talloc_strdup(dom,
389 0 : dom->parent->view_name);
390 0 : if (dom->view_name == NULL) {
391 0 : DEBUG(SSSDBG_OP_FAILURE,
392 : "Failed to copy parent's view name.\n");
393 0 : ret = ENOMEM;
394 0 : goto done;
395 : }
396 : }
397 : } else {
398 0 : if (dom->has_views != dom->parent->has_views
399 0 : || strcmp(dom->view_name,
400 0 : dom->parent->view_name) != 0) {
401 0 : DEBUG(SSSDBG_CRIT_FAILURE,
402 : "Sub-domain [%s][%s] and parent [%s][%s] " \
403 : "views are different.\n",
404 : dom->has_views ? "has view" : "has no view",
405 : dom->view_name,
406 : dom->parent->has_views ? "has view" : "has no view",
407 : dom->parent->view_name);
408 0 : ret = EINVAL;
409 0 : goto done;
410 : }
411 : }
412 :
413 3 : if (dom->trust_direction != trust_direction) {
414 2 : DEBUG(SSSDBG_TRACE_INTERNAL,
415 : "Trust direction change from [%d] to [%d]!\n",
416 : dom->trust_direction, trust_direction);
417 2 : dom->trust_direction = trust_direction;
418 : }
419 :
420 3 : break;
421 : }
422 : }
423 : /* If not found in loop it is a new subdomain */
424 35 : if (dom == NULL) {
425 32 : dom = new_subdomain(domain, domain, name, realm,
426 : flat, id, mpg, enumerate, forest,
427 : trust_direction);
428 32 : if (dom == NULL) {
429 0 : ret = ENOMEM;
430 0 : goto done;
431 : }
432 32 : DLIST_ADD_END(domain->subdomains, dom, struct sss_domain_info *);
433 : }
434 : }
435 :
436 22 : link_forest_roots(domain);
437 :
438 22 : ret = EOK;
439 :
440 : done:
441 29 : talloc_free(tmp_ctx);
442 29 : return ret;
443 : }
444 :
445 21 : errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
446 : {
447 : errno_t ret;
448 : TALLOC_CTX *tmp_ctx;
449 : const char *tmp_str;
450 : struct ldb_dn *basedn;
451 : struct ldb_result *res;
452 21 : const char *attrs[] = {"cn",
453 : SYSDB_SUBDOMAIN_REALM,
454 : SYSDB_SUBDOMAIN_FLAT,
455 : SYSDB_SUBDOMAIN_ID,
456 : SYSDB_SUBDOMAIN_FOREST,
457 : NULL};
458 21 : char *view_name = NULL;
459 :
460 21 : tmp_ctx = talloc_new(NULL);
461 21 : if (tmp_ctx == NULL) {
462 0 : return ENOMEM;
463 : }
464 :
465 21 : basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
466 : SYSDB_DOM_BASE, domain->name);
467 21 : if (basedn == NULL) {
468 0 : ret = EIO;
469 0 : goto done;
470 : }
471 21 : ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
472 : basedn, LDB_SCOPE_BASE, attrs, NULL);
473 21 : if (ret != LDB_SUCCESS) {
474 0 : ret = EIO;
475 0 : goto done;
476 : }
477 :
478 21 : if (res->count == 0) {
479 0 : ret = ENOENT;
480 0 : goto done;
481 : }
482 :
483 21 : if (res->count > 1) {
484 0 : DEBUG(SSSDBG_OP_FAILURE, "Base search returned [%d] results, "
485 : "expected 1.\n", res->count);
486 0 : ret = EINVAL;
487 0 : goto done;
488 : }
489 :
490 21 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_REALM,
491 : NULL);
492 32 : if (tmp_str != NULL &&
493 17 : (domain->realm == NULL || strcasecmp(tmp_str, domain->realm) != 0)) {
494 7 : talloc_free(domain->realm);
495 7 : domain->realm = talloc_strdup(domain, tmp_str);
496 7 : if (domain->realm == NULL) {
497 0 : ret = ENOMEM;
498 0 : goto done;
499 : }
500 : }
501 :
502 21 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FLAT,
503 : NULL);
504 32 : if (tmp_str != NULL &&
505 17 : (domain->flat_name == NULL ||
506 6 : strcasecmp(tmp_str, domain->flat_name) != 0)) {
507 7 : talloc_free(domain->flat_name);
508 7 : domain->flat_name = talloc_strdup(domain, tmp_str);
509 7 : if (domain->flat_name == NULL) {
510 0 : ret = ENOMEM;
511 0 : goto done;
512 : }
513 : }
514 :
515 21 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_ID,
516 : NULL);
517 32 : if (tmp_str != NULL &&
518 17 : (domain->domain_id == NULL ||
519 6 : strcasecmp(tmp_str, domain->domain_id) != 0)) {
520 7 : talloc_free(domain->domain_id);
521 7 : domain->domain_id = talloc_strdup(domain, tmp_str);
522 7 : if (domain->domain_id == NULL) {
523 0 : ret = ENOMEM;
524 0 : goto done;
525 : }
526 : }
527 :
528 21 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FOREST,
529 : NULL);
530 32 : if (tmp_str != NULL &&
531 17 : (domain->forest == NULL ||
532 6 : strcasecmp(tmp_str, domain->forest) != 0)) {
533 6 : talloc_free(domain->forest);
534 6 : domain->forest = talloc_strdup(domain, tmp_str);
535 6 : if (domain->forest == NULL) {
536 0 : ret = ENOMEM;
537 0 : goto done;
538 : }
539 : }
540 :
541 21 : ret = sysdb_get_view_name(tmp_ctx, domain->sysdb, &view_name);
542 21 : if (ret != EOK && ret != ENOENT) {
543 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n");
544 0 : goto done;
545 : }
546 :
547 : /* If no view is defined the default view will be used. In this case
548 : * domain->has_views is FALSE and
549 : * domain->view_name is set to SYSDB_DEFAULT_VIEW_NAME
550 : *
551 : * If there is a view defined
552 : * domain->has_views is TRUE and
553 : * domain->view_name is set to the given view name
554 : *
555 : * Currently changing the view is not supported hence we have to check for
556 : * changes and error out accordingly.
557 : */
558 21 : if (ret == ENOENT || is_default_view(view_name)) {
559 : /* handle default view */
560 42 : if (domain->has_views) {
561 0 : DEBUG(SSSDBG_CRIT_FAILURE,
562 : "View name change is currently not supported. " \
563 : "New view is the default view while current view is [%s]. " \
564 : "View name is not changed!\n", domain->view_name);
565 : } else {
566 21 : if (domain->view_name == NULL) {
567 12 : domain->view_name = talloc_strdup(domain,
568 : SYSDB_DEFAULT_VIEW_NAME);
569 12 : if (domain->view_name == NULL) {
570 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
571 0 : ret = ENOMEM;
572 0 : goto done;
573 : }
574 : } else {
575 9 : if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) != 0) {
576 0 : DEBUG(SSSDBG_CRIT_FAILURE,
577 : "Domain [%s] has no view but view name [%s] " \
578 : "is not the default view name [%s].\n",
579 : domain->name, domain->view_name,
580 : SYSDB_DEFAULT_VIEW_NAME);
581 0 : ret = EINVAL;
582 0 : goto done;
583 : }
584 : }
585 : }
586 : } else {
587 : /* handle view other than default */
588 0 : if (domain->has_views) {
589 0 : if (strcmp(domain->view_name, view_name) != 0) {
590 0 : DEBUG(SSSDBG_CRIT_FAILURE,
591 : "View name change is currently not supported. " \
592 : "New view is [%s] while current view is [%s]. " \
593 : "View name is not changed!\n",
594 : view_name, domain->view_name);
595 : }
596 : } else {
597 0 : if (domain->view_name == NULL) {
598 0 : domain->has_views = true;
599 0 : domain->view_name = talloc_steal(domain, view_name);
600 0 : if (domain->view_name == NULL) {
601 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_steal failed.\n");
602 0 : ret = ENOMEM;
603 0 : goto done;
604 : }
605 : } else {
606 0 : if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
607 0 : DEBUG(SSSDBG_CRIT_FAILURE,
608 : "View name change is currently not supported. " \
609 : "New view is [%s] while current is the default view. " \
610 : "View name is not changed!\n", view_name);
611 : } else {
612 0 : DEBUG(SSSDBG_CRIT_FAILURE,
613 : "Domain currently has no views, " \
614 : "but current view name is set to [%s] " \
615 : "and new view name is [%s].\n",
616 : domain->view_name, view_name);
617 0 : ret = EINVAL;
618 0 : goto done;
619 : }
620 : }
621 : }
622 : }
623 :
624 21 : ret = EOK;
625 :
626 : done:
627 21 : talloc_free(tmp_ctx);
628 21 : return ret;
629 : }
630 :
631 6 : errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain,
632 : const char *realm,
633 : const char *flat,
634 : const char *id,
635 : const char* forest)
636 : {
637 : TALLOC_CTX *tmp_ctx;
638 : struct ldb_message *msg;
639 : int ret;
640 6 : bool do_update = false;
641 :
642 6 : tmp_ctx = talloc_new(NULL);
643 6 : if (tmp_ctx == NULL) {
644 0 : return ENOMEM;
645 : }
646 :
647 6 : msg = ldb_msg_new(tmp_ctx);
648 6 : if (msg == NULL) {
649 0 : ret = ENOMEM;
650 0 : goto done;
651 : }
652 :
653 6 : msg->dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
654 : SYSDB_DOM_BASE, domain->name);
655 6 : if (msg->dn == NULL) {
656 0 : ret = EIO;
657 0 : goto done;
658 : }
659 :
660 7 : if (flat != NULL && (domain->flat_name == NULL ||
661 1 : strcmp(domain->flat_name, flat) != 0)) {
662 6 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT,
663 : LDB_FLAG_MOD_REPLACE, NULL);
664 6 : if (ret != LDB_SUCCESS) {
665 0 : ret = sysdb_error_to_errno(ret);
666 0 : goto done;
667 : }
668 :
669 6 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat);
670 6 : if (ret != LDB_SUCCESS) {
671 0 : ret = sysdb_error_to_errno(ret);
672 0 : goto done;
673 : }
674 :
675 6 : do_update = true;
676 : }
677 :
678 7 : if (id != NULL && (domain->domain_id == NULL ||
679 1 : strcmp(domain->domain_id, id) != 0)) {
680 6 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID,
681 : LDB_FLAG_MOD_REPLACE, NULL);
682 6 : if (ret != LDB_SUCCESS) {
683 0 : ret = sysdb_error_to_errno(ret);
684 0 : goto done;
685 : }
686 :
687 6 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, id);
688 6 : if (ret != LDB_SUCCESS) {
689 0 : ret = sysdb_error_to_errno(ret);
690 0 : goto done;
691 : }
692 :
693 6 : do_update = true;
694 : }
695 :
696 7 : if (forest != NULL && (domain->forest == NULL ||
697 1 : strcmp(domain->forest, forest) != 0)) {
698 6 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST,
699 : LDB_FLAG_MOD_REPLACE, NULL);
700 6 : if (ret != LDB_SUCCESS) {
701 0 : ret = sysdb_error_to_errno(ret);
702 0 : goto done;
703 : }
704 :
705 6 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest);
706 6 : if (ret != LDB_SUCCESS) {
707 0 : ret = sysdb_error_to_errno(ret);
708 0 : goto done;
709 : }
710 :
711 6 : do_update = true;
712 : }
713 :
714 7 : if (realm != NULL && (domain->realm == NULL ||
715 1 : strcmp(domain->realm, realm) != 0)) {
716 6 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_REALM,
717 : LDB_FLAG_MOD_REPLACE, NULL);
718 6 : if (ret != LDB_SUCCESS) {
719 0 : ret = sysdb_error_to_errno(ret);
720 0 : goto done;
721 : }
722 :
723 6 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm);
724 6 : if (ret != LDB_SUCCESS) {
725 0 : ret = sysdb_error_to_errno(ret);
726 0 : goto done;
727 : }
728 :
729 6 : do_update = true;
730 : }
731 :
732 6 : if (do_update == false) {
733 0 : ret = EOK;
734 0 : goto done;
735 : }
736 :
737 6 : ret = ldb_modify(domain->sysdb->ldb, msg);
738 6 : if (ret != LDB_SUCCESS) {
739 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to "
740 : "[%s]: [%d][%s]!\n", domain->name, ret,
741 : ldb_errstring(domain->sysdb->ldb));
742 0 : ret = sysdb_error_to_errno(ret);
743 0 : goto done;
744 : }
745 :
746 6 : ret = sysdb_master_domain_update(domain);
747 6 : if (ret != EOK) {
748 0 : goto done;
749 : }
750 :
751 6 : ret = EOK;
752 :
753 : done:
754 6 : talloc_free(tmp_ctx);
755 :
756 6 : return ret;
757 : }
758 :
759 35 : errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb,
760 : const char *name, const char *realm,
761 : const char *flat_name, const char *domain_id,
762 : bool mpg, bool enumerate, const char *forest,
763 : uint32_t trust_direction)
764 : {
765 : TALLOC_CTX *tmp_ctx;
766 : struct ldb_message *msg;
767 : struct ldb_dn *dn;
768 : struct ldb_result *res;
769 35 : const char *attrs[] = {"cn",
770 : SYSDB_SUBDOMAIN_REALM,
771 : SYSDB_SUBDOMAIN_FLAT,
772 : SYSDB_SUBDOMAIN_ID,
773 : SYSDB_SUBDOMAIN_MPG,
774 : SYSDB_SUBDOMAIN_ENUM,
775 : SYSDB_SUBDOMAIN_FOREST,
776 : SYSDB_SUBDOMAIN_TRUST_DIRECTION,
777 : NULL};
778 : const char *tmp_str;
779 : bool tmp_bool;
780 35 : bool store = false;
781 35 : int realm_flags = 0;
782 35 : int flat_flags = 0;
783 35 : int id_flags = 0;
784 35 : int mpg_flags = 0;
785 35 : int enum_flags = 0;
786 35 : int forest_flags = 0;
787 35 : int td_flags = 0;
788 : uint32_t tmp_td;
789 : int ret;
790 :
791 35 : tmp_ctx = talloc_new(NULL);
792 35 : if (tmp_ctx == NULL) {
793 0 : return ENOMEM;
794 : }
795 :
796 35 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, name);
797 35 : if (dn == NULL) {
798 0 : ret = EIO;
799 0 : goto done;
800 : }
801 35 : ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
802 : dn, LDB_SCOPE_BASE, attrs, NULL);
803 35 : if (ret != LDB_SUCCESS) {
804 0 : ret = EIO;
805 0 : goto done;
806 : }
807 :
808 35 : if (res->count == 0) {
809 15 : ret = sysdb_domain_create(sysdb, name);
810 15 : if (ret) {
811 0 : goto done;
812 : }
813 15 : store = true;
814 15 : if (realm) realm_flags = LDB_FLAG_MOD_ADD;
815 15 : if (flat_name) flat_flags = LDB_FLAG_MOD_ADD;
816 15 : if (domain_id) id_flags = LDB_FLAG_MOD_ADD;
817 15 : mpg_flags = LDB_FLAG_MOD_ADD;
818 15 : enum_flags = LDB_FLAG_MOD_ADD;
819 15 : if (forest) forest_flags = LDB_FLAG_MOD_ADD;
820 15 : if (trust_direction) td_flags = LDB_FLAG_MOD_ADD;
821 20 : } else if (res->count != 1) {
822 0 : ret = EINVAL;
823 0 : goto done;
824 : } else { /* 1 found */
825 20 : if (realm) {
826 20 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
827 : SYSDB_SUBDOMAIN_REALM, NULL);
828 20 : if (!tmp_str || strcasecmp(tmp_str, realm) != 0) {
829 1 : realm_flags = LDB_FLAG_MOD_REPLACE;
830 : }
831 : }
832 20 : if (flat_name) {
833 14 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
834 : SYSDB_SUBDOMAIN_FLAT, NULL);
835 14 : if (!tmp_str || strcasecmp(tmp_str, flat_name) != 0) {
836 1 : flat_flags = LDB_FLAG_MOD_REPLACE;
837 : }
838 : }
839 20 : if (domain_id) {
840 20 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
841 : SYSDB_SUBDOMAIN_ID, NULL);
842 20 : if (!tmp_str || strcasecmp(tmp_str, domain_id) != 0) {
843 1 : id_flags = LDB_FLAG_MOD_REPLACE;
844 : }
845 : }
846 :
847 20 : tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_MPG,
848 20 : !mpg);
849 20 : if (tmp_bool != mpg) {
850 1 : mpg_flags = LDB_FLAG_MOD_REPLACE;
851 : }
852 20 : tmp_bool = ldb_msg_find_attr_as_bool(res->msgs[0], SYSDB_SUBDOMAIN_ENUM,
853 20 : !enumerate);
854 20 : if (tmp_bool != enumerate) {
855 1 : enum_flags = LDB_FLAG_MOD_REPLACE;
856 : }
857 :
858 20 : if (forest) {
859 13 : tmp_str = ldb_msg_find_attr_as_string(res->msgs[0],
860 : SYSDB_SUBDOMAIN_FOREST, NULL);
861 13 : if (!tmp_str || strcasecmp(tmp_str, forest) != 0) {
862 0 : forest_flags = LDB_FLAG_MOD_REPLACE;
863 : }
864 : }
865 :
866 20 : tmp_td = ldb_msg_find_attr_as_uint(res->msgs[0],
867 : SYSDB_SUBDOMAIN_TRUST_DIRECTION,
868 : 0);
869 20 : if (tmp_td != trust_direction) {
870 4 : td_flags = LDB_FLAG_MOD_REPLACE;
871 : }
872 : }
873 :
874 35 : if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0
875 19 : && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0
876 19 : && td_flags == 0) {
877 15 : ret = EOK;
878 15 : goto done;
879 : }
880 :
881 20 : msg = ldb_msg_new(tmp_ctx);
882 20 : if (msg == NULL) {
883 0 : ret = ENOMEM;
884 0 : goto done;
885 : }
886 20 : msg->dn = dn;
887 :
888 20 : if (store) {
889 15 : ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL);
890 15 : if (ret != LDB_SUCCESS) {
891 0 : ret = sysdb_error_to_errno(ret);
892 0 : goto done;
893 : }
894 :
895 15 : ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_SUBDOMAIN_CLASS);
896 15 : if (ret != LDB_SUCCESS) {
897 0 : ret = sysdb_error_to_errno(ret);
898 0 : goto done;
899 : }
900 : }
901 :
902 20 : if (realm_flags) {
903 16 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_REALM, realm_flags, NULL);
904 16 : if (ret != LDB_SUCCESS) {
905 0 : ret = sysdb_error_to_errno(ret);
906 0 : goto done;
907 : }
908 :
909 16 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm);
910 16 : if (ret != LDB_SUCCESS) {
911 0 : ret = sysdb_error_to_errno(ret);
912 0 : goto done;
913 : }
914 : }
915 :
916 20 : if (flat_flags) {
917 15 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FLAT, flat_flags, NULL);
918 15 : if (ret != LDB_SUCCESS) {
919 0 : ret = sysdb_error_to_errno(ret);
920 0 : goto done;
921 : }
922 :
923 15 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FLAT, flat_name);
924 15 : if (ret != LDB_SUCCESS) {
925 0 : ret = sysdb_error_to_errno(ret);
926 0 : goto done;
927 : }
928 : }
929 :
930 20 : if (id_flags) {
931 16 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ID, id_flags, NULL);
932 16 : if (ret != LDB_SUCCESS) {
933 0 : ret = sysdb_error_to_errno(ret);
934 0 : goto done;
935 : }
936 :
937 16 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ID, domain_id);
938 16 : if (ret != LDB_SUCCESS) {
939 0 : ret = sysdb_error_to_errno(ret);
940 0 : goto done;
941 : }
942 : }
943 :
944 20 : if (mpg_flags) {
945 16 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_MPG, mpg_flags, NULL);
946 16 : if (ret != LDB_SUCCESS) {
947 0 : ret = sysdb_error_to_errno(ret);
948 0 : goto done;
949 : }
950 :
951 16 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_MPG,
952 : mpg ? "TRUE" : "FALSE");
953 16 : if (ret != LDB_SUCCESS) {
954 0 : ret = sysdb_error_to_errno(ret);
955 0 : goto done;
956 : }
957 : }
958 :
959 20 : if (enum_flags) {
960 16 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_ENUM, enum_flags, NULL);
961 16 : if (ret != LDB_SUCCESS) {
962 0 : ret = sysdb_error_to_errno(ret);
963 0 : goto done;
964 : }
965 :
966 16 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_ENUM,
967 : enumerate ? "TRUE" : "FALSE");
968 16 : if (ret != LDB_SUCCESS) {
969 0 : ret = sysdb_error_to_errno(ret);
970 0 : goto done;
971 : }
972 : }
973 :
974 20 : if (forest_flags) {
975 11 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, forest_flags,
976 : NULL);
977 11 : if (ret != LDB_SUCCESS) {
978 0 : ret = sysdb_error_to_errno(ret);
979 0 : goto done;
980 : }
981 :
982 11 : ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest);
983 11 : if (ret != LDB_SUCCESS) {
984 0 : ret = sysdb_error_to_errno(ret);
985 0 : goto done;
986 : }
987 : }
988 :
989 20 : if (td_flags) {
990 7 : ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_TRUST_DIRECTION,
991 : td_flags, NULL);
992 7 : if (ret != LDB_SUCCESS) {
993 0 : ret = sysdb_error_to_errno(ret);
994 0 : goto done;
995 : }
996 :
997 7 : ret = ldb_msg_add_fmt(msg, SYSDB_SUBDOMAIN_TRUST_DIRECTION,
998 : "%u", trust_direction);
999 7 : if (ret != LDB_SUCCESS) {
1000 0 : ret = sysdb_error_to_errno(ret);
1001 0 : goto done;
1002 : }
1003 : }
1004 :
1005 20 : ret = ldb_modify(sysdb->ldb, msg);
1006 20 : if (ret != LDB_SUCCESS) {
1007 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to "
1008 : "[%s]: [%d][%s]!\n", name, ret,
1009 : ldb_errstring(sysdb->ldb));
1010 0 : ret = sysdb_error_to_errno(ret);
1011 0 : goto done;
1012 : }
1013 :
1014 20 : ret = EOK;
1015 :
1016 : done:
1017 35 : talloc_free(tmp_ctx);
1018 :
1019 35 : return ret;
1020 : }
1021 :
1022 3 : errno_t sysdb_subdomain_delete(struct sysdb_ctx *sysdb, const char *name)
1023 : {
1024 3 : TALLOC_CTX *tmp_ctx = NULL;
1025 : struct ldb_dn *dn;
1026 : int ret;
1027 :
1028 3 : tmp_ctx = talloc_new(NULL);
1029 3 : if (tmp_ctx == NULL) {
1030 0 : ret = ENOMEM;
1031 0 : goto done;
1032 : }
1033 :
1034 3 : DEBUG(SSSDBG_TRACE_FUNC, "Removing sub-domain [%s] from db.\n", name);
1035 3 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, name);
1036 3 : if (dn == NULL) {
1037 0 : ret = ENOMEM;
1038 0 : goto done;
1039 : }
1040 :
1041 3 : ret = sysdb_delete_recursive(sysdb, dn, true);
1042 3 : if (ret != EOK) {
1043 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
1044 0 : goto done;
1045 : }
1046 :
1047 : done:
1048 3 : talloc_free(tmp_ctx);
1049 3 : return ret;
1050 : }
|