Line data Source code
1 : /*
2 : SSSD
3 :
4 : NSS Configuratoin DB
5 :
6 : Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "config.h"
23 :
24 : #include <ctype.h>
25 : #include "util/util.h"
26 : #include "confdb/confdb.h"
27 : #include "confdb/confdb_private.h"
28 : #include "util/strtonum.h"
29 : #include "db/sysdb.h"
30 :
31 : #define CONFDB_ZERO_CHECK_OR_JUMP(var, ret, err, label) do { \
32 : if (!var) { \
33 : ret = err; \
34 : goto label; \
35 : } \
36 : } while(0)
37 :
38 : /* Warning messages */
39 : #define SAME_DOMAINS_ERROR_MSG "Domain '%s' is the same as or differs only "\
40 : "in case from domain '%s'.\n"
41 :
42 18460 : static char *prepend_cn(char *str, int *slen, const char *comp, int clen)
43 : {
44 : char *ret;
45 :
46 18460 : ret = talloc_realloc(NULL, str, char, *slen + 4 + clen + 1);
47 18460 : if (!ret)
48 0 : return NULL;
49 :
50 : /* move current string to the end */
51 18460 : memmove(&ret[clen +4], ret, *slen+1); /* includes termination */
52 18460 : memcpy(ret, "cn=", 3);
53 18460 : memcpy(&ret[3], comp, clen);
54 18460 : ret[clen+3] = ',';
55 :
56 18460 : *slen = *slen + 4 + clen;
57 :
58 18460 : return ret;
59 : }
60 :
61 13290 : int parse_section(TALLOC_CTX *mem_ctx, const char *section,
62 : char **sec_dn, const char **rdn_name)
63 : {
64 : TALLOC_CTX *tmp_ctx;
65 13290 : char *dn = NULL;
66 : char *p;
67 : const char *s;
68 : int l, ret;
69 :
70 : /* section must be a non null string and must not start with '/' */
71 13290 : if (!section || !*section || *section == '/') return EINVAL;
72 :
73 13290 : tmp_ctx = talloc_new(mem_ctx);
74 13290 : if (!tmp_ctx) return ENOMEM;
75 :
76 13290 : s = section;
77 13290 : l = 0;
78 45040 : while ((p = strchrnul(s, '/'))) {
79 31750 : if (l == 0) {
80 13290 : dn = talloc_asprintf(tmp_ctx, "cn=%s", s);
81 13290 : l = 3 + (p-s);
82 13290 : dn[l] = '\0';
83 : } else {
84 18460 : dn = prepend_cn(dn, &l, s, p-s);
85 : }
86 31750 : if (!dn) {
87 0 : ret = ENOMEM;
88 0 : goto done;
89 : }
90 31750 : if (*p == '\0') {
91 13290 : if (rdn_name) *rdn_name = s;
92 13290 : break; /* reached end */
93 : }
94 18460 : s = p+1;
95 18460 : if (*s == '\0') { /* a section cannot end in '.' */
96 0 : ret = EINVAL;
97 0 : goto done;
98 : }
99 : }
100 :
101 13290 : *sec_dn = talloc_steal(mem_ctx, dn);
102 13290 : ret = EOK;
103 :
104 : done:
105 13290 : talloc_free(tmp_ctx);
106 13290 : return ret;
107 : }
108 :
109 4063 : int confdb_add_param(struct confdb_ctx *cdb,
110 : bool replace,
111 : const char *section,
112 : const char *attribute,
113 : const char **values)
114 : {
115 4063 : TALLOC_CTX *tmp_ctx = NULL;
116 : struct ldb_message *msg;
117 : struct ldb_result *res;
118 : struct ldb_dn *dn;
119 : char *secdn;
120 : const char *rdn_name;
121 : int ret, i;
122 :
123 4063 : tmp_ctx = talloc_new(NULL);
124 4063 : if (!tmp_ctx) {
125 0 : ret = ENOMEM;
126 0 : goto done;
127 : }
128 :
129 4063 : ret = parse_section(tmp_ctx, section, &secdn, &rdn_name);
130 4063 : if (ret != EOK) {
131 0 : goto done;
132 : }
133 :
134 4063 : dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
135 4063 : CONFDB_ZERO_CHECK_OR_JUMP(dn, ret, EIO, done);
136 :
137 4063 : ret = ldb_search(cdb->ldb, tmp_ctx, &res,
138 : dn, LDB_SCOPE_BASE, NULL, NULL);
139 4063 : if (ret != LDB_SUCCESS) {
140 0 : ret = EIO;
141 0 : goto done;
142 : }
143 :
144 4063 : msg = ldb_msg_new(tmp_ctx);
145 4063 : CONFDB_ZERO_CHECK_OR_JUMP(msg, ret, ENOMEM, done);
146 :
147 4063 : msg->dn = talloc_steal(msg, dn);
148 4063 : CONFDB_ZERO_CHECK_OR_JUMP(msg->dn, ret, ENOMEM, done);
149 :
150 4063 : if (res->count == 0) { /* add a new message */
151 195 : errno = 0;
152 :
153 : /* cn first */
154 195 : ret = ldb_msg_add_string(msg, "cn", rdn_name);
155 195 : if (ret != LDB_SUCCESS) {
156 0 : if (errno) ret = errno;
157 0 : else ret = EIO;
158 0 : goto done;
159 : }
160 :
161 : /* now the requested attribute */
162 390 : for (i = 0; values[i]; i++) {
163 195 : ret = ldb_msg_add_string(msg, attribute, values[i]);
164 195 : if (ret != LDB_SUCCESS) {
165 0 : if (errno) ret = errno;
166 0 : else ret = EIO;
167 0 : goto done;
168 : }
169 : }
170 :
171 195 : ret = ldb_add(cdb->ldb, msg);
172 195 : if (ret != LDB_SUCCESS) {
173 0 : ret = EIO;
174 0 : goto done;
175 : }
176 :
177 : } else {
178 : int optype;
179 3868 : errno = 0;
180 :
181 : /* mark this as a replacement */
182 3868 : if (replace) optype = LDB_FLAG_MOD_REPLACE;
183 0 : else optype = LDB_FLAG_MOD_ADD;
184 3868 : ret = ldb_msg_add_empty(msg, attribute, optype, NULL);
185 3868 : if (ret != LDB_SUCCESS) {
186 0 : if (errno) ret = errno;
187 0 : else ret = EIO;
188 0 : goto done;
189 : }
190 :
191 : /* now the requested attribute */
192 7736 : for (i = 0; values[i]; i++) {
193 3868 : ret = ldb_msg_add_string(msg, attribute, values[i]);
194 3868 : if (ret != LDB_SUCCESS) {
195 0 : if (errno) ret = errno;
196 0 : else ret = EIO;
197 0 : goto done;
198 : }
199 : }
200 :
201 3868 : ret = ldb_modify(cdb->ldb, msg);
202 3868 : if (ret != LDB_SUCCESS) {
203 0 : DEBUG(SSSDBG_MINOR_FAILURE,
204 : "ldb_modify failed: [%s](%d)[%s]\n",
205 : ldb_strerror(ret), ret, ldb_errstring(cdb->ldb));
206 0 : ret = EIO;
207 0 : goto done;
208 : }
209 : }
210 :
211 4063 : ret = EOK;
212 :
213 : done:
214 4063 : talloc_free(tmp_ctx);
215 4063 : if (ret != EOK) {
216 0 : DEBUG(SSSDBG_CRIT_FAILURE,
217 : "Failed to add [%s] to [%s], error [%d] (%s)\n",
218 : attribute, section, ret, strerror(ret));
219 : }
220 4063 : return ret;
221 : }
222 :
223 9227 : int confdb_get_param(struct confdb_ctx *cdb,
224 : TALLOC_CTX *mem_ctx,
225 : const char *section,
226 : const char *attribute,
227 : char ***values)
228 : {
229 : TALLOC_CTX *tmp_ctx;
230 : struct ldb_result *res;
231 : struct ldb_dn *dn;
232 : char *secdn;
233 9227 : const char *attrs[] = { attribute, NULL };
234 : char **vals;
235 : struct ldb_message_element *el;
236 : int ret, i;
237 :
238 9227 : tmp_ctx = talloc_new(mem_ctx);
239 9227 : if (!tmp_ctx)
240 0 : return ENOMEM;
241 :
242 9227 : ret = parse_section(tmp_ctx, section, &secdn, NULL);
243 9227 : if (ret != EOK) {
244 0 : goto done;
245 : }
246 :
247 9227 : dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
248 9227 : if (!dn) {
249 0 : ret = EIO;
250 0 : goto done;
251 : }
252 :
253 9227 : ret = ldb_search(cdb->ldb, tmp_ctx, &res,
254 : dn, LDB_SCOPE_BASE, attrs, NULL);
255 9227 : if (ret != LDB_SUCCESS) {
256 0 : ret = EIO;
257 0 : goto done;
258 : }
259 9227 : if (res->count > 1) {
260 0 : ret = EIO;
261 0 : goto done;
262 : }
263 :
264 9227 : vals = talloc_zero(mem_ctx, char *);
265 9227 : ret = EOK;
266 :
267 9227 : if (res->count > 0) {
268 6707 : el = ldb_msg_find_element(res->msgs[0], attribute);
269 6707 : if (el && el->num_values > 0) {
270 2021 : vals = talloc_realloc(mem_ctx, vals, char *, el->num_values +1);
271 2021 : if (!vals) {
272 0 : ret = ENOMEM;
273 0 : goto done;
274 : }
275 : /* should always be strings so this should be safe */
276 4042 : for (i = 0; i < el->num_values; i++) {
277 2021 : struct ldb_val v = el->values[i];
278 2021 : vals[i] = talloc_strndup(vals, (char *)v.data, v.length);
279 2021 : if (!vals[i]) {
280 0 : ret = ENOMEM;
281 0 : goto done;
282 : }
283 : }
284 2021 : vals[i] = NULL;
285 : }
286 : }
287 :
288 9227 : *values = vals;
289 :
290 : done:
291 9227 : talloc_free(tmp_ctx);
292 9227 : if (ret != EOK) {
293 0 : DEBUG(SSSDBG_CRIT_FAILURE,
294 : "Failed to get [%s] from [%s], error [%d] (%s)\n",
295 : attribute, section, ret, strerror(ret));
296 : }
297 9227 : return ret;
298 : }
299 :
300 0 : int confdb_set_string(struct confdb_ctx *cdb,
301 : const char *section,
302 : const char *attribute,
303 : const char *val)
304 : {
305 : TALLOC_CTX *tmp_ctx;
306 : struct ldb_dn *dn;
307 : char *secdn;
308 : struct ldb_message *msg;
309 : int ret, lret;
310 :
311 0 : tmp_ctx = talloc_new(NULL);
312 0 : if (!tmp_ctx) {
313 0 : return ENOMEM;
314 : }
315 :
316 0 : ret = parse_section(tmp_ctx, section, &secdn, NULL);
317 0 : if (ret != EOK) {
318 0 : goto done;
319 : }
320 :
321 0 : dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
322 0 : if (!dn) {
323 0 : ret = EIO;
324 0 : goto done;
325 : }
326 :
327 0 : msg = ldb_msg_new(tmp_ctx);
328 0 : if (!msg) {
329 0 : ret = ENOMEM;
330 0 : goto done;
331 : }
332 :
333 0 : msg->dn = dn;
334 :
335 0 : lret = ldb_msg_add_empty(msg, attribute, LDB_FLAG_MOD_REPLACE, NULL);
336 0 : if (lret != LDB_SUCCESS) {
337 0 : DEBUG(SSSDBG_MINOR_FAILURE,
338 : "ldb_msg_add_empty failed: [%s]\n", ldb_strerror(lret));
339 0 : ret = EIO;
340 0 : goto done;
341 : }
342 :
343 0 : lret = ldb_msg_add_string(msg, attribute, val);
344 0 : if (lret != LDB_SUCCESS) {
345 0 : DEBUG(SSSDBG_MINOR_FAILURE,
346 : "ldb_msg_add_string failed: [%s]\n", ldb_strerror(lret));
347 0 : ret = EIO;
348 0 : goto done;
349 : }
350 :
351 0 : lret = ldb_modify(cdb->ldb, msg);
352 0 : if (lret != LDB_SUCCESS) {
353 0 : DEBUG(SSSDBG_MINOR_FAILURE,
354 : "ldb_modify failed: [%s](%d)[%s]\n",
355 : ldb_strerror(lret), lret, ldb_errstring(cdb->ldb));
356 0 : ret = EIO;
357 0 : goto done;
358 : }
359 :
360 0 : ret = EOK;
361 :
362 : done:
363 0 : talloc_free(tmp_ctx);
364 0 : if (ret != EOK) {
365 0 : DEBUG(SSSDBG_CRIT_FAILURE,
366 : "Failed to set [%s] from [%s], error [%d] (%s)\n",
367 : attribute, section, ret, strerror(ret));
368 : }
369 0 : return ret;
370 : }
371 :
372 2890 : int confdb_get_string(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
373 : const char *section, const char *attribute,
374 : const char *defstr, char **result)
375 : {
376 2890 : char **values = NULL;
377 : char *restr;
378 : int ret;
379 :
380 2890 : ret = confdb_get_param(cdb, ctx, section, attribute, &values);
381 2890 : if (ret != EOK) {
382 0 : goto failed;
383 : }
384 :
385 2890 : if (values[0]) {
386 309 : if (values[1] != NULL) {
387 : /* too many values */
388 0 : ret = EINVAL;
389 0 : goto failed;
390 : }
391 309 : restr = talloc_steal(ctx, values[0]);
392 : } else {
393 : /* Did not return a value, so use the default */
394 :
395 2581 : if (defstr == NULL) { /* No default given */
396 2110 : *result = NULL;
397 2110 : talloc_free(values);
398 2110 : return EOK;
399 : }
400 :
401 : /* Copy the default string */
402 471 : restr = talloc_strdup(ctx, defstr);
403 : }
404 780 : if (!restr) {
405 0 : ret = ENOMEM;
406 0 : goto failed;
407 : }
408 :
409 780 : talloc_free(values);
410 :
411 780 : *result = restr;
412 780 : return EOK;
413 :
414 : failed:
415 0 : talloc_free(values);
416 0 : DEBUG(SSSDBG_CRIT_FAILURE,
417 : "Failed to get [%s] from [%s], error [%d] (%s)\n",
418 : attribute, section, ret, strerror(ret));
419 0 : return ret;
420 : }
421 :
422 4838 : int confdb_get_int(struct confdb_ctx *cdb,
423 : const char *section, const char *attribute,
424 : int defval, int *result)
425 : {
426 4838 : char **values = NULL;
427 : long val;
428 : int ret;
429 : TALLOC_CTX *tmp_ctx;
430 :
431 4838 : tmp_ctx = talloc_new(NULL);
432 4838 : if (tmp_ctx == NULL) {
433 0 : ret = ENOMEM;
434 0 : goto failed;
435 : }
436 :
437 4838 : ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
438 4838 : if (ret != EOK) {
439 0 : goto failed;
440 : }
441 :
442 4838 : if (values[0]) {
443 660 : if (values[1] != NULL) {
444 : /* too many values */
445 0 : ret = EINVAL;
446 0 : goto failed;
447 : }
448 :
449 660 : errno = 0;
450 660 : val = strtol(values[0], NULL, 0);
451 660 : if (errno) {
452 0 : ret = errno;
453 0 : goto failed;
454 : }
455 :
456 660 : if (val < INT_MIN || val > INT_MAX) {
457 0 : ret = ERANGE;
458 0 : goto failed;
459 : }
460 :
461 : } else {
462 4178 : val = defval;
463 : }
464 :
465 4838 : talloc_free(tmp_ctx);
466 :
467 4838 : *result = (int)val;
468 4838 : return EOK;
469 :
470 : failed:
471 0 : talloc_free(tmp_ctx);
472 0 : DEBUG(SSSDBG_CRIT_FAILURE,
473 : "Failed to read [%s] from [%s], error [%d] (%s)\n",
474 : attribute, section, ret, strerror(ret));
475 0 : return ret;
476 : }
477 :
478 0 : long confdb_get_long(struct confdb_ctx *cdb,
479 : const char *section, const char *attribute,
480 : long defval, long *result)
481 : {
482 0 : char **values = NULL;
483 : long val;
484 : int ret;
485 : TALLOC_CTX *tmp_ctx;
486 :
487 0 : tmp_ctx = talloc_new(NULL);
488 0 : if (tmp_ctx == NULL) {
489 0 : ret = ENOMEM;
490 0 : goto failed;
491 : }
492 :
493 0 : ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
494 0 : if (ret != EOK) {
495 0 : goto failed;
496 : }
497 :
498 0 : if (values[0]) {
499 0 : if (values[1] != NULL) {
500 : /* too many values */
501 0 : ret = EINVAL;
502 0 : goto failed;
503 : }
504 :
505 0 : errno = 0;
506 0 : val = strtol(values[0], NULL, 0);
507 0 : if (errno) {
508 0 : ret = errno;
509 0 : goto failed;
510 : }
511 :
512 : } else {
513 0 : val = defval;
514 : }
515 :
516 0 : talloc_free(tmp_ctx);
517 :
518 0 : *result = val;
519 0 : return EOK;
520 :
521 : failed:
522 0 : talloc_free(tmp_ctx);
523 0 : DEBUG(SSSDBG_CRIT_FAILURE,
524 : "Failed to read [%s] from [%s], error [%d] (%s)\n",
525 : attribute, section, ret, strerror(ret));
526 0 : return ret;
527 : }
528 :
529 315 : int confdb_get_bool(struct confdb_ctx *cdb,
530 : const char *section, const char *attribute,
531 : bool defval, bool *result)
532 : {
533 315 : char **values = NULL;
534 : bool val;
535 : int ret;
536 : TALLOC_CTX *tmp_ctx;
537 :
538 315 : tmp_ctx = talloc_new(NULL);
539 315 : if (tmp_ctx == NULL) {
540 0 : ret = ENOMEM;
541 0 : goto failed;
542 : }
543 :
544 315 : ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
545 315 : if (ret != EOK) {
546 0 : goto failed;
547 : }
548 :
549 315 : if (values[0]) {
550 2 : if (values[1] != NULL) {
551 : /* too many values */
552 0 : ret = EINVAL;
553 0 : goto failed;
554 : }
555 :
556 2 : if (strcasecmp(values[0], "FALSE") == 0) {
557 1 : val = false;
558 :
559 1 : } else if (strcasecmp(values[0], "TRUE") == 0) {
560 1 : val = true;
561 :
562 : } else {
563 :
564 0 : DEBUG(SSSDBG_OP_FAILURE, "Value is not a boolean!\n");
565 0 : ret = EINVAL;
566 0 : goto failed;
567 : }
568 :
569 : } else {
570 313 : val = defval;
571 : }
572 :
573 315 : talloc_free(tmp_ctx);
574 :
575 315 : *result = val;
576 315 : return EOK;
577 :
578 : failed:
579 0 : talloc_free(tmp_ctx);
580 0 : DEBUG(SSSDBG_CRIT_FAILURE,
581 : "Failed to read [%s] from [%s], error [%d] (%s)\n",
582 : attribute, section, ret, strerror(ret));
583 0 : return ret;
584 : }
585 :
586 : /* WARNING: Unlike other similar functions, this one does NOT take a default,
587 : * and returns ENOENT if the attribute was not found ! */
588 1184 : int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
589 : const char *section, const char *attribute,
590 : char ***result)
591 : {
592 1184 : char **values = NULL;
593 : int ret;
594 :
595 1184 : ret = confdb_get_param(cdb, ctx, section, attribute, &values);
596 1184 : if (ret != EOK) {
597 0 : goto done;
598 : }
599 :
600 1184 : if (values && values[0]) {
601 2100 : if (values[1] != NULL) {
602 : /* too many values */
603 0 : ret = EINVAL;
604 0 : goto done;
605 : }
606 : } else {
607 : /* Did not return a value */
608 134 : ret = ENOENT;
609 134 : goto done;
610 : }
611 :
612 1050 : ret = split_on_separator(ctx, values[0], ',', true, true, result, NULL);
613 :
614 : done:
615 1184 : talloc_free(values);
616 1184 : if (ret != EOK && ret != ENOENT) {
617 0 : DEBUG(SSSDBG_OP_FAILURE,
618 : "Failed to get [%s] from [%s], error [%d] (%s)\n",
619 : attribute, section, ret, strerror(ret));
620 : }
621 1184 : return ret;
622 : }
623 :
624 1041 : int confdb_init(TALLOC_CTX *mem_ctx,
625 : struct confdb_ctx **cdb_ctx,
626 : const char *confdb_location)
627 : {
628 : struct confdb_ctx *cdb;
629 1041 : int ret = EOK;
630 : mode_t old_umask;
631 :
632 1041 : cdb = talloc_zero(mem_ctx, struct confdb_ctx);
633 1041 : if (!cdb)
634 0 : return ENOMEM;
635 :
636 : /* Because confdb calls use sync ldb calls, we create a separate event
637 : * context here. This will prevent the ldb sync calls to start nested
638 : * events.
639 : * NOTE: this means that we *cannot* do async calls and return in confdb
640 : * unless we convert all calls and hook back to the main event context.
641 : */
642 :
643 1041 : cdb->pev = tevent_context_init(cdb);
644 1041 : if (!cdb->pev) {
645 0 : talloc_free(cdb);
646 0 : return EIO;
647 : }
648 :
649 1041 : cdb->ldb = ldb_init(cdb, cdb->pev);
650 1041 : if (!cdb->ldb) {
651 0 : talloc_free(cdb);
652 0 : return EIO;
653 : }
654 :
655 1041 : ret = ldb_set_debug(cdb->ldb, ldb_debug_messages, NULL);
656 1041 : if (ret != LDB_SUCCESS) {
657 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Could not set up debug fn.\n");
658 0 : talloc_free(cdb);
659 0 : return EIO;
660 : }
661 :
662 1041 : old_umask = umask(SSS_DFL_UMASK);
663 :
664 1041 : ret = ldb_connect(cdb->ldb, confdb_location, 0, NULL);
665 1041 : umask(old_umask);
666 1041 : if (ret != LDB_SUCCESS) {
667 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Unable to open config database [%s]\n",
668 : confdb_location);
669 0 : talloc_free(cdb);
670 0 : return EIO;
671 : }
672 :
673 1041 : *cdb_ctx = cdb;
674 :
675 1041 : return EOK;
676 : }
677 :
678 16230 : static errno_t get_entry_as_uint32(struct ldb_message *msg,
679 : uint32_t *return_value,
680 : const char *entry,
681 : uint32_t default_value)
682 : {
683 16230 : const char *tmp = NULL;
684 : char *endptr;
685 16230 : uint32_t u32ret = 0;
686 :
687 16230 : *return_value = 0;
688 :
689 16230 : if (!msg || !entry) {
690 0 : return EFAULT;
691 : }
692 :
693 16230 : tmp = ldb_msg_find_attr_as_string(msg, entry, NULL);
694 16230 : if (tmp == NULL) {
695 16230 : *return_value = default_value;
696 16230 : return EOK;
697 : }
698 :
699 0 : if ((*tmp == '-') || (*tmp == '\0')) {
700 0 : return EINVAL;
701 : }
702 :
703 0 : u32ret = strtouint32 (tmp, &endptr, 10);
704 0 : if (errno) {
705 0 : return errno;
706 : }
707 :
708 0 : if (*endptr != '\0') {
709 : /* Not all of the string was a valid number */
710 0 : return EINVAL;
711 : }
712 :
713 0 : *return_value = u32ret;
714 0 : return EOK;
715 : }
716 :
717 5410 : static errno_t get_entry_as_bool(struct ldb_message *msg,
718 : bool *return_value,
719 : const char *entry,
720 : bool default_value)
721 : {
722 5410 : const char *tmp = NULL;
723 :
724 5410 : *return_value = 0;
725 :
726 5410 : if (!msg || !entry) {
727 0 : return EFAULT;
728 : }
729 :
730 5410 : tmp = ldb_msg_find_attr_as_string(msg, entry, NULL);
731 5410 : if (tmp == NULL || *tmp == '\0') {
732 3562 : *return_value = default_value;
733 3562 : return EOK;
734 : }
735 :
736 1848 : if (strcasecmp(tmp, "FALSE") == 0) {
737 907 : *return_value = 0;
738 : }
739 941 : else if (strcasecmp(tmp, "TRUE") == 0) {
740 941 : *return_value = 1;
741 : }
742 : else {
743 0 : return EINVAL;
744 : }
745 :
746 1848 : return EOK;
747 : }
748 :
749 :
750 : /* The default UID/GID for domains is 1. This wouldn't work well with
751 : * the local provider */
752 1082 : static uint32_t confdb_get_min_id(struct sss_domain_info *domain)
753 : {
754 1082 : uint32_t defval = SSSD_MIN_ID;
755 :
756 1082 : if (domain && strcasecmp(domain->provider, "local") == 0) {
757 871 : defval = SSSD_LOCAL_MINID;
758 : }
759 :
760 1082 : return defval;
761 : }
762 :
763 1082 : static errno_t init_cached_auth_timeout(struct confdb_ctx *cdb,
764 : struct ldb_message *msg,
765 : uint32_t *_cached_auth_timeout)
766 : {
767 : int cred_expiration;
768 : int id_timeout;
769 : errno_t ret;
770 : uint32_t cached_auth_timeout;
771 :
772 1082 : ret = get_entry_as_uint32(msg, &cached_auth_timeout,
773 : CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT, 0);
774 1082 : if (ret != EOK) {
775 0 : DEBUG(SSSDBG_FATAL_FAILURE,
776 : "Invalid value for [%s]\n", CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT);
777 0 : goto done;
778 : }
779 :
780 1082 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
781 : CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration);
782 1082 : if (ret != EOK) {
783 0 : DEBUG(SSSDBG_CRIT_FAILURE,
784 : "Failed to read expiration time of offline credentials.\n");
785 0 : goto done;
786 : }
787 :
788 : /* convert from days to seconds */
789 1082 : cred_expiration *= 3600 * 24;
790 1687 : if (cred_expiration != 0 &&
791 605 : cred_expiration < cached_auth_timeout) {
792 0 : cached_auth_timeout = cred_expiration;
793 : }
794 :
795 : /* Set up the PAM identity timeout */
796 1082 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
797 : CONFDB_PAM_ID_TIMEOUT, 5,
798 : &id_timeout);
799 1082 : if (ret != EOK) goto done;
800 :
801 1082 : if (cached_auth_timeout > id_timeout) {
802 0 : DEBUG(SSSDBG_MINOR_FAILURE,
803 : "cached_auth_timeout is greater than pam_id_timeout so be aware "
804 : "that back end could be called to handle initgroups.\n");
805 : }
806 :
807 1082 : ret = EOK;
808 :
809 : done:
810 1082 : if (ret == EOK) {
811 1082 : *_cached_auth_timeout = cached_auth_timeout;
812 : }
813 1082 : return ret;
814 : }
815 :
816 1082 : static int confdb_get_domain_internal(struct confdb_ctx *cdb,
817 : TALLOC_CTX *mem_ctx,
818 : const char *name,
819 : struct sss_domain_info **_domain)
820 : {
821 : struct sss_domain_info *domain;
822 : struct ldb_result *res;
823 : TALLOC_CTX *tmp_ctx;
824 : struct ldb_dn *dn;
825 : const char *tmp;
826 : int ret, val;
827 : uint32_t entry_cache_timeout;
828 : char *default_domain;
829 1082 : bool fqnames_default = false;
830 : int memcache_timeout;
831 :
832 1082 : tmp_ctx = talloc_new(mem_ctx);
833 1082 : if (!tmp_ctx) return ENOMEM;
834 :
835 1082 : dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb,
836 : "cn=%s,%s", name, CONFDB_DOMAIN_BASEDN);
837 1082 : if (!dn) {
838 0 : ret = ENOMEM;
839 0 : goto done;
840 : }
841 :
842 1082 : ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
843 : LDB_SCOPE_BASE, NULL, NULL);
844 1082 : if (ret != LDB_SUCCESS) {
845 0 : ret = EIO;
846 0 : goto done;
847 : }
848 :
849 1082 : if (res->count != 1) {
850 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Unknown domain [%s]\n", name);
851 0 : ret = ENOENT;
852 0 : goto done;
853 : }
854 :
855 1082 : ret = confdb_get_int(cdb,
856 : CONFDB_NSS_CONF_ENTRY,
857 : CONFDB_MEMCACHE_TIMEOUT,
858 : 300, &memcache_timeout);
859 1082 : if (ret != EOK) {
860 0 : DEBUG(SSSDBG_FATAL_FAILURE,
861 : "Unable to get memory cache entry timeout.\n");
862 0 : goto done;
863 : }
864 :
865 1082 : domain = talloc_zero(mem_ctx, struct sss_domain_info);
866 1082 : if (!domain) {
867 0 : ret = ENOMEM;
868 0 : goto done;
869 : }
870 :
871 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0], "cn", NULL);
872 1082 : if (!tmp) {
873 0 : DEBUG(SSSDBG_FATAL_FAILURE,
874 : "Invalid configuration entry, fatal error!\n");
875 0 : ret = EINVAL;
876 0 : goto done;
877 : }
878 1082 : domain->name = talloc_strdup(domain, tmp);
879 1082 : if (!domain->name) {
880 0 : ret = ENOMEM;
881 0 : goto done;
882 : }
883 1082 : domain->conn_name = domain->name;
884 :
885 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
886 : CONFDB_DOMAIN_ID_PROVIDER,
887 : NULL);
888 1082 : if (tmp) {
889 1082 : domain->provider = talloc_strdup(domain, tmp);
890 1082 : if (!domain->provider) {
891 0 : ret = ENOMEM;
892 0 : goto done;
893 : }
894 : }
895 : else {
896 0 : DEBUG(SSSDBG_FATAL_FAILURE,
897 : "Domain [%s] does not specify an ID provider, disabling!\n",
898 : domain->name);
899 0 : ret = EINVAL;
900 0 : goto done;
901 : }
902 :
903 1082 : if (strcasecmp(domain->provider, "files") == 0) {
904 : /* The files provider is not valid anymore */
905 0 : DEBUG(SSSDBG_FATAL_FAILURE, "The \"files\" provider is invalid\n");
906 0 : ret = EINVAL;
907 0 : goto done;
908 : }
909 :
910 1082 : if (strcasecmp(domain->provider, "local") == 0) {
911 : /* If this is the local provider, we need to ensure that
912 : * no other provider was specified for other types, since
913 : * the local provider cannot load them.
914 : */
915 871 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
916 : CONFDB_DOMAIN_AUTH_PROVIDER,
917 : NULL);
918 871 : if (tmp && strcasecmp(tmp, "local") != 0) {
919 0 : DEBUG(SSSDBG_FATAL_FAILURE,
920 : "Local ID provider does not support [%s] as an AUTH provider.\n", tmp);
921 0 : ret = EINVAL;
922 0 : goto done;
923 : }
924 :
925 871 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
926 : CONFDB_DOMAIN_ACCESS_PROVIDER,
927 : NULL);
928 871 : if (tmp && strcasecmp(tmp, "permit") != 0) {
929 0 : DEBUG(SSSDBG_FATAL_FAILURE,
930 : "Local ID provider does not support [%s] as an ACCESS provider.\n", tmp);
931 0 : ret = EINVAL;
932 0 : goto done;
933 : }
934 :
935 871 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
936 : CONFDB_DOMAIN_CHPASS_PROVIDER,
937 : NULL);
938 871 : if (tmp && strcasecmp(tmp, "local") != 0) {
939 0 : DEBUG(SSSDBG_FATAL_FAILURE,
940 : "Local ID provider does not support [%s] as a CHPASS provider.\n", tmp);
941 0 : ret = EINVAL;
942 0 : goto done;
943 : }
944 :
945 : /* The LOCAL provider use always Magic Private Groups */
946 871 : domain->mpg = true;
947 : }
948 :
949 1082 : domain->timeout = ldb_msg_find_attr_as_int(res->msgs[0],
950 : CONFDB_DOMAIN_TIMEOUT, 0);
951 :
952 : /* Determine if this domain can be enumerated */
953 :
954 : /* TEMP: test if the old bitfield conf value is used and warn it has been
955 : * superceeded. */
956 1082 : val = ldb_msg_find_attr_as_int(res->msgs[0], CONFDB_DOMAIN_ENUMERATE, 0);
957 1082 : if (val > 0) { /* ok there was a number in here */
958 0 : DEBUG(SSSDBG_FATAL_FAILURE,
959 : "Warning: enumeration parameter in %s still uses integers! "
960 : "Enumeration is now a boolean and takes true/false values. "
961 : "Interpreting as true\n", domain->name);
962 0 : domain->enumerate = true;
963 : } else { /* assume the new format */
964 1082 : ret = get_entry_as_bool(res->msgs[0], &domain->enumerate,
965 : CONFDB_DOMAIN_ENUMERATE, 0);
966 1082 : if(ret != EOK) {
967 0 : DEBUG(SSSDBG_FATAL_FAILURE,
968 : "Invalid value for %s\n", CONFDB_DOMAIN_ENUMERATE);
969 0 : goto done;
970 : }
971 : }
972 1082 : if (!domain->enumerate) {
973 1043 : DEBUG(SSSDBG_TRACE_FUNC, "No enumeration for [%s]!\n", domain->name);
974 : }
975 :
976 1082 : ret = confdb_get_string(cdb, tmp_ctx, CONFDB_MONITOR_CONF_ENTRY,
977 : CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
978 : &default_domain);
979 1082 : if (ret != EOK) {
980 0 : DEBUG(SSSDBG_OP_FAILURE,
981 : "Cannnot get the default domain [%d]: %s\n",
982 : ret, strerror(ret));
983 0 : goto done;
984 : }
985 :
986 : /* Determine if user/group names will be Fully Qualified
987 : * in NSS interfaces */
988 1082 : if (default_domain != NULL) {
989 0 : DEBUG(SSSDBG_CONF_SETTINGS,
990 : "Default domain suffix set. Changing default for "
991 : "use_fully_qualified_names to True.\n");
992 0 : fqnames_default = true;
993 : }
994 :
995 1082 : ret = get_entry_as_bool(res->msgs[0], &domain->fqnames,
996 : CONFDB_DOMAIN_FQ, fqnames_default);
997 1082 : if (ret != EOK) {
998 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for %s\n",
999 : CONFDB_DOMAIN_FQ);
1000 0 : goto done;
1001 : }
1002 :
1003 1082 : if (default_domain != NULL && domain->fqnames == false) {
1004 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1005 : "Invalid configuration detected (default_domain_suffix is used "
1006 : "while use_fully_qualified_names was set to false).\n");
1007 0 : ret = ERR_INVALID_CONFIG;
1008 0 : goto done;
1009 : }
1010 :
1011 1082 : ret = get_entry_as_bool(res->msgs[0], &domain->ignore_group_members,
1012 : CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS, 0);
1013 1082 : if(ret != EOK) {
1014 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1015 : "Invalid value for %s\n",
1016 : CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS);
1017 0 : goto done;
1018 : }
1019 :
1020 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->id_min,
1021 : CONFDB_DOMAIN_MINID,
1022 : confdb_get_min_id(domain));
1023 1082 : if (ret != EOK) {
1024 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for minId\n");
1025 0 : ret = EINVAL;
1026 0 : goto done;
1027 : }
1028 :
1029 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->id_max,
1030 : CONFDB_DOMAIN_MAXID, 0);
1031 1082 : if (ret != EOK) {
1032 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for maxId\n");
1033 0 : ret = EINVAL;
1034 0 : goto done;
1035 : }
1036 :
1037 1082 : if (domain->id_max && (domain->id_max < domain->id_min)) {
1038 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Invalid domain range\n");
1039 0 : ret = EINVAL;
1040 0 : goto done;
1041 : }
1042 :
1043 : /* Do we allow to cache credentials */
1044 1082 : ret = get_entry_as_bool(res->msgs[0], &domain->cache_credentials,
1045 : CONFDB_DOMAIN_CACHE_CREDS, 0);
1046 1082 : if(ret != EOK) {
1047 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1048 : "Invalid value for %s\n", CONFDB_DOMAIN_CACHE_CREDS);
1049 0 : goto done;
1050 : }
1051 :
1052 1082 : ret = get_entry_as_uint32(res->msgs[0],
1053 : &domain->cache_credentials_min_ff_length,
1054 : CONFDB_DOMAIN_CACHE_CREDS_MIN_FF_LENGTH,
1055 : CONFDB_DEFAULT_CACHE_CREDS_MIN_FF_LENGTH);
1056 1082 : if (ret != EOK) {
1057 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1058 : "Invalid value for %s\n",
1059 : CONFDB_DOMAIN_CACHE_CREDS_MIN_FF_LENGTH);
1060 0 : goto done;
1061 : }
1062 :
1063 1082 : ret = get_entry_as_bool(res->msgs[0], &domain->legacy_passwords,
1064 : CONFDB_DOMAIN_LEGACY_PASS, 0);
1065 1082 : if(ret != EOK) {
1066 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1067 : "Invalid value for %s\n", CONFDB_DOMAIN_LEGACY_PASS);
1068 0 : goto done;
1069 : }
1070 :
1071 : /* Get the global entry cache timeout setting */
1072 1082 : ret = get_entry_as_uint32(res->msgs[0], &entry_cache_timeout,
1073 : CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT, 5400);
1074 1082 : if (ret != EOK) {
1075 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1076 : "Invalid value for [%s]\n",
1077 : CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT);
1078 0 : goto done;
1079 : }
1080 :
1081 : /* Override the user cache timeout, if specified */
1082 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->user_timeout,
1083 : CONFDB_DOMAIN_USER_CACHE_TIMEOUT,
1084 : entry_cache_timeout);
1085 1082 : if (ret != EOK) {
1086 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1087 : "Invalid value for [%s]\n",
1088 : CONFDB_DOMAIN_USER_CACHE_TIMEOUT);
1089 0 : goto done;
1090 : }
1091 :
1092 1082 : if (domain->user_timeout < memcache_timeout) {
1093 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1094 : "%s is less than %s. User records will not be updated before "
1095 : "memory cache entry expires.\n",
1096 : CONFDB_DOMAIN_USER_CACHE_TIMEOUT, CONFDB_MEMCACHE_TIMEOUT);
1097 : }
1098 :
1099 : /* Override the group cache timeout, if specified */
1100 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->group_timeout,
1101 : CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT,
1102 : entry_cache_timeout);
1103 1082 : if (ret != EOK) {
1104 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1105 : "Invalid value for [%s]\n",
1106 : CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT);
1107 0 : goto done;
1108 : }
1109 :
1110 1082 : if (domain->group_timeout < memcache_timeout) {
1111 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1112 : "%s is less than %s. Group records will not be updated before "
1113 : "memory cache entry expires.\n",
1114 : CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT, CONFDB_MEMCACHE_TIMEOUT);
1115 : }
1116 :
1117 : /* Override the netgroup cache timeout, if specified */
1118 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->netgroup_timeout,
1119 : CONFDB_DOMAIN_NETGROUP_CACHE_TIMEOUT,
1120 : entry_cache_timeout);
1121 1082 : if (ret != EOK) {
1122 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1123 : "Invalid value for [%s]\n",
1124 : CONFDB_DOMAIN_NETGROUP_CACHE_TIMEOUT);
1125 0 : goto done;
1126 : }
1127 :
1128 : /* Override the service cache timeout, if specified */
1129 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->service_timeout,
1130 : CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT,
1131 : entry_cache_timeout);
1132 1082 : if (ret != EOK) {
1133 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1134 : "Invalid value for [%s]\n",
1135 : CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT);
1136 0 : goto done;
1137 : }
1138 :
1139 : /* Override the autofs cache timeout, if specified */
1140 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->autofsmap_timeout,
1141 : CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT,
1142 : entry_cache_timeout);
1143 1082 : if (ret != EOK) {
1144 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1145 : "Invalid value for [%s]\n",
1146 : CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT);
1147 0 : goto done;
1148 : }
1149 :
1150 : /* Override the sudo cache timeout, if specified */
1151 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->sudo_timeout,
1152 : CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT,
1153 : entry_cache_timeout);
1154 1082 : if (ret != EOK) {
1155 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1156 : "Invalid value for [%s]\n",
1157 : CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT);
1158 0 : goto done;
1159 : }
1160 :
1161 : /* Override the ssh known hosts timeout, if specified */
1162 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->ssh_host_timeout,
1163 : CONFDB_DOMAIN_SSH_HOST_CACHE_TIMEOUT,
1164 : entry_cache_timeout);
1165 1082 : if (ret != EOK) {
1166 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1167 : "Invalid value for [%s]\n",
1168 : CONFDB_DOMAIN_SSH_HOST_CACHE_TIMEOUT);
1169 0 : goto done;
1170 : }
1171 :
1172 : /* Set refresh_expired_interval, if specified */
1173 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->refresh_expired_interval,
1174 : CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL,
1175 : 0);
1176 1082 : if (ret != EOK) {
1177 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1178 : "Invalid value for [%s]\n",
1179 : CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL);
1180 0 : goto done;
1181 : }
1182 :
1183 : /* detect and fix misconfiguration */
1184 1082 : if (domain->refresh_expired_interval > entry_cache_timeout) {
1185 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1186 : "refresh_expired_interval (%d) cannot be greater than "
1187 : "entry_cache_timeout (%u)\n",
1188 : domain->refresh_expired_interval, entry_cache_timeout);
1189 :
1190 0 : domain->refresh_expired_interval = 0.75 * entry_cache_timeout;
1191 :
1192 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1193 : "refresh_expired_interval is being set to recommended value "
1194 : "entry_cache_timeout * 0.75 (%u).\n",
1195 : domain->refresh_expired_interval);
1196 : }
1197 :
1198 : /* Set the PAM warning time, if specified. If not specified, pass on
1199 : * the "not set" value of "-1" which means "use provider default". The
1200 : * value 0 means "always display the warning if server sends one" */
1201 1082 : domain->pwd_expiration_warning = -1;
1202 :
1203 1082 : val = ldb_msg_find_attr_as_int(res->msgs[0],
1204 : CONFDB_DOMAIN_PWD_EXPIRATION_WARNING,
1205 : -1);
1206 1082 : if (val == -1) {
1207 1082 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
1208 : CONFDB_PAM_PWD_EXPIRATION_WARNING,
1209 : -1, &val);
1210 1082 : if (ret != EOK) {
1211 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1212 : "Failed to read PAM expiration warning, not fatal.\n");
1213 0 : val = -1;
1214 : }
1215 : }
1216 :
1217 1082 : DEBUG(SSSDBG_TRACE_LIBS, "pwd_expiration_warning is %d\n", val);
1218 1082 : if (val >= 0) {
1219 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1220 : "Setting domain password expiration warning to %d days\n", val);
1221 : /* The value is in days, transform it to seconds */
1222 0 : domain->pwd_expiration_warning = val * 24 * 3600;
1223 : }
1224 :
1225 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->override_gid,
1226 : CONFDB_DOMAIN_OVERRIDE_GID, 0);
1227 1082 : if (ret != EOK) {
1228 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1229 : "Invalid value for [%s]\n", CONFDB_DOMAIN_OVERRIDE_GID);
1230 0 : goto done;
1231 : }
1232 :
1233 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1234 : CONFDB_NSS_OVERRIDE_HOMEDIR, NULL);
1235 1082 : if (tmp != NULL) {
1236 0 : domain->override_homedir = talloc_strdup(domain, tmp);
1237 0 : if (!domain->override_homedir) {
1238 0 : ret = ENOMEM;
1239 0 : goto done;
1240 : }
1241 : }
1242 :
1243 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1244 : CONFDB_NSS_FALLBACK_HOMEDIR, NULL);
1245 1082 : if (tmp != NULL) {
1246 0 : domain->fallback_homedir = talloc_strdup(domain, tmp);
1247 0 : if (!domain->fallback_homedir) {
1248 0 : ret = ENOMEM;
1249 0 : goto done;
1250 : }
1251 : }
1252 :
1253 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1254 : CONFDB_DOMAIN_SUBDOMAIN_HOMEDIR,
1255 : CONFDB_DOMAIN_DEFAULT_SUBDOMAIN_HOMEDIR);
1256 1082 : if (tmp != NULL) {
1257 1082 : domain->subdomain_homedir = talloc_strdup(domain, tmp);
1258 1082 : if (!domain->subdomain_homedir) {
1259 0 : ret = ENOMEM;
1260 0 : goto done;
1261 : }
1262 : }
1263 :
1264 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1265 : CONFDB_NSS_HOMEDIR_SUBSTRING, NULL);
1266 1082 : if (tmp != NULL) {
1267 0 : domain->homedir_substr = talloc_strdup(domain, tmp);
1268 0 : if (domain->homedir_substr == NULL) {
1269 0 : ret = ENOMEM;
1270 0 : goto done;
1271 : }
1272 : }
1273 :
1274 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1275 : CONFDB_NSS_OVERRIDE_SHELL, NULL);
1276 1082 : if (tmp != NULL) {
1277 0 : domain->override_shell = talloc_strdup(domain, tmp);
1278 0 : if (!domain->override_shell) {
1279 0 : ret = ENOMEM;
1280 0 : goto done;
1281 : }
1282 : }
1283 :
1284 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1285 : CONFDB_NSS_DEFAULT_SHELL, NULL);
1286 1082 : if (tmp != NULL) {
1287 0 : domain->default_shell = talloc_strdup(domain, tmp);
1288 0 : if (!domain->default_shell) {
1289 0 : ret = ENOMEM;
1290 0 : goto done;
1291 : }
1292 : }
1293 :
1294 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1295 : CONFDB_DOMAIN_CASE_SENSITIVE, "true");
1296 1082 : if (tmp != NULL) {
1297 1082 : if (strcasecmp(tmp, "true") == 0) {
1298 1082 : domain->case_sensitive = true;
1299 1082 : domain->case_preserve = true;
1300 0 : } else if (strcasecmp(tmp, "false") == 0) {
1301 0 : domain->case_sensitive = false;
1302 0 : domain->case_preserve = false;
1303 0 : } else if (strcasecmp(tmp, "preserving") == 0) {
1304 0 : domain->case_sensitive = false;
1305 0 : domain->case_preserve = true;
1306 : } else {
1307 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1308 : "Invalid value for %s\n", CONFDB_DOMAIN_CASE_SENSITIVE);
1309 0 : goto done;
1310 : }
1311 : } else {
1312 : /* default */
1313 0 : domain->case_sensitive = true;
1314 0 : domain->case_preserve = true;
1315 : }
1316 1082 : if (domain->case_sensitive == false &&
1317 0 : strcasecmp(domain->provider, "local") == 0) {
1318 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1319 : "Local ID provider does not support the case insensitive flag\n");
1320 0 : ret = EINVAL;
1321 0 : goto done;
1322 : }
1323 :
1324 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1325 : CONFDB_SUBDOMAIN_ENUMERATE,
1326 : CONFDB_DEFAULT_SUBDOMAIN_ENUMERATE);
1327 1082 : if (tmp != NULL) {
1328 1082 : ret = split_on_separator(domain, tmp, ',', true, true,
1329 : &domain->sd_enumerate, NULL);
1330 1082 : if (ret != 0) {
1331 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1332 : "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
1333 0 : goto done;
1334 : }
1335 : }
1336 :
1337 1082 : tmp = ldb_msg_find_attr_as_string(res->msgs[0],
1338 : CONFDB_DOMAIN_SUBDOMAIN_INHERIT,
1339 : NULL);
1340 1082 : if (tmp != NULL) {
1341 0 : ret = split_on_separator(domain, tmp, ',', true, true,
1342 : &domain->sd_inherit, NULL);
1343 0 : if (ret != 0) {
1344 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1345 : "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
1346 0 : goto done;
1347 : }
1348 : }
1349 :
1350 1082 : ret = get_entry_as_uint32(res->msgs[0], &domain->subdomain_refresh_interval,
1351 : CONFDB_DOMAIN_SUBDOMAIN_REFRESH, 14400);
1352 1082 : if (ret != EOK || domain->subdomain_refresh_interval == 0) {
1353 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1354 : "Invalid value for [%s]\n", CONFDB_DOMAIN_SUBDOMAIN_REFRESH);
1355 0 : goto done;
1356 : }
1357 :
1358 1082 : ret = init_cached_auth_timeout(cdb, res->msgs[0],
1359 : &domain->cached_auth_timeout);
1360 1082 : if (ret != EOK) {
1361 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1362 : "init_cached_auth_timeout failed: %s:[%d].\n",
1363 : sss_strerror(ret), ret);
1364 0 : goto done;
1365 : }
1366 :
1367 1082 : domain->has_views = false;
1368 1082 : domain->view_name = NULL;
1369 :
1370 1082 : domain->state = DOM_ACTIVE;
1371 :
1372 1082 : *_domain = domain;
1373 1082 : ret = EOK;
1374 : done:
1375 1082 : talloc_free(tmp_ctx);
1376 1082 : return ret;
1377 : }
1378 :
1379 1082 : int confdb_get_domains(struct confdb_ctx *cdb,
1380 : struct sss_domain_info **domains)
1381 : {
1382 : TALLOC_CTX *tmp_ctx;
1383 1082 : struct sss_domain_info *domain = NULL;
1384 : char **domlist;
1385 : int ret, i;
1386 :
1387 1082 : if (cdb->doms) {
1388 48 : *domains = cdb->doms;
1389 48 : return EOK;
1390 : }
1391 :
1392 1034 : tmp_ctx = talloc_new(NULL);
1393 1034 : if (!tmp_ctx) return ENOMEM;
1394 :
1395 1034 : ret = confdb_get_string_as_list(cdb, tmp_ctx,
1396 : CONFDB_MONITOR_CONF_ENTRY,
1397 : CONFDB_MONITOR_ACTIVE_DOMAINS,
1398 : &domlist);
1399 1034 : if (ret == ENOENT) {
1400 0 : DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured, fatal error!\n");
1401 0 : goto done;
1402 : }
1403 1034 : if (ret != EOK ) {
1404 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
1405 0 : goto done;
1406 : }
1407 :
1408 2116 : for (i = 0; domlist[i]; i++) {
1409 : /* check if domain name is really unique */
1410 1172 : DLIST_FOR_EACH(domain, cdb->doms) {
1411 90 : if (strcasecmp(domain->name, domlist[i]) == 0) {
1412 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1413 : SAME_DOMAINS_ERROR_MSG, domlist[i], domain->name);
1414 0 : sss_log(SSS_LOG_CRIT,
1415 0 : SAME_DOMAINS_ERROR_MSG, domlist[i], domain->name);
1416 :
1417 0 : ret = EINVAL;
1418 0 : goto done;
1419 : }
1420 : }
1421 :
1422 1082 : domain = NULL;
1423 1082 : ret = confdb_get_domain_internal(cdb, cdb, domlist[i], &domain);
1424 1082 : if (ret) {
1425 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1426 : "Error (%d [%s]) retrieving domain [%s], skipping!\n",
1427 : ret, sss_strerror(ret), domlist[i]);
1428 0 : continue;
1429 : }
1430 :
1431 1082 : DLIST_ADD_END(cdb->doms, domain, struct sss_domain_info *);
1432 : }
1433 :
1434 1034 : if (cdb->doms == NULL) {
1435 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1436 : "No properly configured domains, fatal error!\n");
1437 0 : ret = ENOENT;
1438 0 : goto done;
1439 : }
1440 :
1441 1034 : *domains = cdb->doms;
1442 1034 : ret = EOK;
1443 :
1444 : done:
1445 1034 : talloc_free(tmp_ctx);
1446 1034 : return ret;
1447 : }
1448 :
1449 1081 : int confdb_get_domain(struct confdb_ctx *cdb,
1450 : const char *name,
1451 : struct sss_domain_info **_domain)
1452 : {
1453 : struct sss_domain_info *dom, *doms;
1454 : int ret;
1455 :
1456 1081 : ret = confdb_get_domains(cdb, &doms);
1457 1081 : if (ret != EOK) {
1458 0 : return ret;
1459 : }
1460 :
1461 1171 : for (dom = doms; dom; dom = get_next_domain(dom, false)) {
1462 1171 : if (strcasecmp(dom->name, name) == 0) {
1463 1081 : *_domain = dom;
1464 1081 : return EOK;
1465 : }
1466 : }
1467 :
1468 0 : return ENOENT;
1469 : }
1470 :
1471 3 : int confdb_list_all_domain_names(TALLOC_CTX *mem_ctx,
1472 : struct confdb_ctx *cdb,
1473 : char ***_names)
1474 : {
1475 3 : TALLOC_CTX *tmp_ctx = NULL;
1476 3 : struct ldb_dn *dn = NULL;
1477 3 : struct ldb_result *res = NULL;
1478 : static const char *attrs[] = {CONFDB_DOMAIN_ATTR, NULL};
1479 3 : const char *name = NULL;
1480 3 : char **names = NULL;
1481 : int i;
1482 : int ret;
1483 :
1484 3 : tmp_ctx = talloc_new(NULL);
1485 3 : if (tmp_ctx == NULL) {
1486 0 : return ENOMEM;
1487 : }
1488 :
1489 3 : dn = ldb_dn_new(tmp_ctx, cdb->ldb, CONFDB_DOMAIN_BASEDN);
1490 3 : if (dn == NULL) {
1491 0 : ret = ENOMEM;
1492 0 : goto done;
1493 : }
1494 :
1495 3 : ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
1496 : attrs, NULL);
1497 3 : if (ret != LDB_SUCCESS) {
1498 0 : ret = EIO;
1499 0 : goto done;
1500 : }
1501 :
1502 3 : names = talloc_zero_array(tmp_ctx, char*, res->count + 1);
1503 3 : if (names == NULL) {
1504 0 : ret = ENOMEM;
1505 0 : goto done;
1506 : }
1507 :
1508 6 : for (i = 0; i < res->count; i++) {
1509 3 : name = ldb_msg_find_attr_as_string(res->msgs[i], CONFDB_DOMAIN_ATTR,
1510 : NULL);
1511 3 : if (name == NULL) {
1512 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1513 : "The object [%s] doesn't have a name\n",
1514 : ldb_dn_get_linearized(res->msgs[i]->dn));
1515 0 : ret = EINVAL;
1516 0 : goto done;
1517 : }
1518 :
1519 3 : names[i] = talloc_strdup(names, name);
1520 3 : if (names[i] == NULL) {
1521 0 : ret = ENOMEM;
1522 0 : goto done;
1523 : }
1524 : }
1525 :
1526 3 : *_names = talloc_steal(mem_ctx, names);
1527 :
1528 3 : ret = EOK;
1529 :
1530 : done:
1531 3 : talloc_free(tmp_ctx);
1532 3 : return ret;
1533 : }
|