"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.4.2/src/confdb/confdb.c" (19 Feb 2021, 80777 Bytes) of package /linux/misc/sssd-2.4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "confdb.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.1_vs_2.4.2.

    1 /*
    2    SSSD
    3 
    4    SSSD Configuration 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 #define RETRIEVE_DOMAIN_ERROR_MSG "Error (%d [%s]) retrieving domain [%s], "\
   43                                   "skipping!\n"
   44 
   45 /* SSSD domain name that is used for the auto-configured files domain */
   46 #define IMPLICIT_FILES_DOMAIN_NAME "implicit_files"
   47 
   48 
   49 static int confdb_get_enabled_domain_list(struct confdb_ctx *cdb,
   50                                           TALLOC_CTX *ctx, char ***_result);
   51 static int confdb_get_domain_enabled(struct confdb_ctx *cdb,
   52                                      const char *domain, bool *_enabled);
   53 
   54 
   55 static char *prepend_cn(char *str, int *slen, const char *comp, int clen)
   56 {
   57     char *ret;
   58 
   59     ret = talloc_realloc(NULL, str, char, *slen + 4 + clen + 1);
   60     if (!ret)
   61         return NULL;
   62 
   63     /* move current string to the end */
   64     memmove(&ret[clen +4], ret, *slen+1); /* includes termination */
   65     memcpy(ret, "cn=", 3);
   66     memcpy(&ret[3], comp, clen);
   67     ret[clen+3] = ',';
   68 
   69     *slen = *slen + 4 + clen;
   70 
   71     return ret;
   72 }
   73 
   74 int parse_section(TALLOC_CTX *mem_ctx, const char *section,
   75                   char **sec_dn, const char **rdn_name)
   76 {
   77     TALLOC_CTX *tmp_ctx;
   78     char *dn = NULL;
   79     char *p;
   80     const char *s;
   81     int l, ret;
   82 
   83     /* section must be a non null string and must not start with '/' */
   84     if (!section || !*section || *section == '/') return EINVAL;
   85 
   86     tmp_ctx = talloc_new(mem_ctx);
   87     if (!tmp_ctx) return ENOMEM;
   88 
   89     s = section;
   90     l = 0;
   91     while ((p = strchrnul(s, '/'))) {
   92         if (l == 0) {
   93             dn = talloc_asprintf(tmp_ctx, "cn=%s", s);
   94             l = 3 + (p-s);
   95             dn[l] = '\0';
   96         } else {
   97             dn = prepend_cn(dn, &l, s, p-s);
   98         }
   99         if (!dn) {
  100             ret = ENOMEM;
  101             goto done;
  102         }
  103         if (*p == '\0') {
  104             if (rdn_name) *rdn_name = s;
  105             break; /* reached end */
  106         }
  107         s = p+1;
  108         if (*s == '\0') { /* a section cannot end in '.' */
  109             ret = EINVAL;
  110             goto done;
  111         }
  112     }
  113 
  114     *sec_dn = talloc_steal(mem_ctx, dn);
  115     ret = EOK;
  116 
  117 done:
  118     talloc_free(tmp_ctx);
  119     return ret;
  120 }
  121 
  122 int confdb_add_param(struct confdb_ctx *cdb,
  123                      bool replace,
  124                      const char *section,
  125                      const char *attribute,
  126                      const char **values)
  127 {
  128     TALLOC_CTX *tmp_ctx = NULL;
  129     struct ldb_message *msg;
  130     struct ldb_result *res;
  131     struct ldb_dn *dn;
  132     char *secdn;
  133     const char *rdn_name;
  134     int ret, i;
  135 
  136     tmp_ctx = talloc_new(NULL);
  137     if (!tmp_ctx) {
  138         ret = ENOMEM;
  139         goto done;
  140     }
  141 
  142     ret = parse_section(tmp_ctx, section, &secdn, &rdn_name);
  143     if (ret != EOK) {
  144         goto done;
  145     }
  146 
  147     dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
  148     CONFDB_ZERO_CHECK_OR_JUMP(dn, ret, EIO, done);
  149 
  150     ret = ldb_search(cdb->ldb, tmp_ctx, &res,
  151                      dn, LDB_SCOPE_BASE, NULL, NULL);
  152     if (ret != LDB_SUCCESS) {
  153         ret = EIO;
  154         goto done;
  155     }
  156 
  157     msg = ldb_msg_new(tmp_ctx);
  158     CONFDB_ZERO_CHECK_OR_JUMP(msg, ret, ENOMEM, done);
  159 
  160     msg->dn = talloc_steal(msg, dn);
  161     CONFDB_ZERO_CHECK_OR_JUMP(msg->dn, ret, ENOMEM, done);
  162 
  163     if (res->count == 0) { /* add a new message */
  164         errno = 0;
  165 
  166         /* cn first */
  167         ret = ldb_msg_add_string(msg, "cn", rdn_name);
  168         if (ret != LDB_SUCCESS) {
  169             if (errno) ret = errno;
  170             else ret = EIO;
  171             goto done;
  172         }
  173 
  174         /* now the requested attribute */
  175         for (i = 0; values[i]; i++) {
  176             ret = ldb_msg_add_string(msg, attribute, values[i]);
  177             if (ret != LDB_SUCCESS) {
  178                 if (errno) ret = errno;
  179                 else ret = EIO;
  180                 goto done;
  181             }
  182         }
  183 
  184         ret = ldb_add(cdb->ldb, msg);
  185         if (ret != LDB_SUCCESS) {
  186             ret = EIO;
  187             goto done;
  188         }
  189 
  190     } else {
  191         int optype;
  192         errno = 0;
  193 
  194         /* mark this as a replacement */
  195         if (replace) optype = LDB_FLAG_MOD_REPLACE;
  196         else optype = LDB_FLAG_MOD_ADD;
  197         ret = ldb_msg_add_empty(msg, attribute, optype, NULL);
  198         if (ret != LDB_SUCCESS) {
  199             if (errno) ret = errno;
  200             else ret = EIO;
  201             goto done;
  202         }
  203 
  204         /* now the requested attribute */
  205         for (i = 0; values[i]; i++) {
  206             ret = ldb_msg_add_string(msg, attribute, values[i]);
  207             if (ret != LDB_SUCCESS) {
  208                 if (errno) ret = errno;
  209                 else ret = EIO;
  210                 goto done;
  211             }
  212         }
  213 
  214         ret = ldb_modify(cdb->ldb, msg);
  215         if (ret != LDB_SUCCESS) {
  216             DEBUG(SSSDBG_MINOR_FAILURE,
  217                   "ldb_modify failed: [%s](%d)[%s]\n",
  218                   ldb_strerror(ret), ret, ldb_errstring(cdb->ldb));
  219             ret = EIO;
  220             goto done;
  221         }
  222     }
  223 
  224     ret = EOK;
  225 
  226 done:
  227     talloc_free(tmp_ctx);
  228     if (ret != EOK) {
  229         DEBUG(SSSDBG_CRIT_FAILURE,
  230               "Failed to add [%s] to [%s], error [%d] (%s)\n",
  231                   attribute, section, ret, strerror(ret));
  232     }
  233     return ret;
  234 }
  235 
  236 int confdb_get_param(struct confdb_ctx *cdb,
  237                      TALLOC_CTX *mem_ctx,
  238                      const char *section,
  239                      const char *attribute,
  240                      char ***values)
  241 {
  242     TALLOC_CTX *tmp_ctx;
  243     struct ldb_result *res;
  244     struct ldb_dn *dn;
  245     char *secdn;
  246     const char *attrs[] = { attribute, NULL };
  247     char **vals;
  248     struct ldb_message_element *el;
  249     int ret, i;
  250 
  251     tmp_ctx = talloc_new(mem_ctx);
  252     if (!tmp_ctx)
  253         return ENOMEM;
  254 
  255     ret = parse_section(tmp_ctx, section, &secdn, NULL);
  256     if (ret != EOK) {
  257         goto done;
  258     }
  259 
  260     dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
  261     if (!dn) {
  262         ret = EIO;
  263         goto done;
  264     }
  265 
  266     ret = ldb_search(cdb->ldb, tmp_ctx, &res,
  267                      dn, LDB_SCOPE_BASE, attrs, NULL);
  268     if (ret != LDB_SUCCESS) {
  269         ret = EIO;
  270         goto done;
  271     }
  272     if (res->count > 1) {
  273         ret = EIO;
  274         goto done;
  275     }
  276 
  277     vals = talloc_zero(mem_ctx, char *);
  278     ret = EOK;
  279 
  280     if (res->count > 0) {
  281         el = ldb_msg_find_element(res->msgs[0], attribute);
  282         if (el && el->num_values > 0) {
  283             vals = talloc_realloc(mem_ctx, vals, char *, el->num_values +1);
  284             if (!vals) {
  285                 ret = ENOMEM;
  286                 goto done;
  287             }
  288             /* should always be strings so this should be safe */
  289             for (i = 0; i < el->num_values; i++) {
  290                 struct ldb_val v = el->values[i];
  291                 vals[i] = talloc_strndup(vals, (char *)v.data, v.length);
  292                 if (!vals[i]) {
  293                     ret = ENOMEM;
  294                     goto done;
  295                 }
  296             }
  297             vals[i] = NULL;
  298         }
  299     }
  300 
  301     *values = vals;
  302 
  303 done:
  304     talloc_free(tmp_ctx);
  305     if (ret != EOK) {
  306         DEBUG(SSSDBG_CRIT_FAILURE,
  307               "Failed to get [%s] from [%s], error [%d] (%s)\n",
  308                   attribute, section, ret, strerror(ret));
  309     }
  310     return ret;
  311 }
  312 
  313 int confdb_set_string(struct confdb_ctx *cdb,
  314                       const char *section,
  315                       const char *attribute,
  316                       const char *val)
  317 {
  318     TALLOC_CTX *tmp_ctx;
  319     struct ldb_dn *dn;
  320     char *secdn;
  321     struct ldb_message *msg;
  322     int ret, lret;
  323 
  324     tmp_ctx = talloc_new(NULL);
  325     if (!tmp_ctx) {
  326         return ENOMEM;
  327     }
  328 
  329     ret = parse_section(tmp_ctx, section, &secdn, NULL);
  330     if (ret != EOK) {
  331         goto done;
  332     }
  333 
  334     dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
  335     if (!dn) {
  336         ret = EIO;
  337         goto done;
  338     }
  339 
  340     msg = ldb_msg_new(tmp_ctx);
  341     if (!msg) {
  342         ret = ENOMEM;
  343         goto done;
  344     }
  345 
  346     msg->dn = dn;
  347 
  348     lret = ldb_msg_add_empty(msg, attribute, LDB_FLAG_MOD_REPLACE, NULL);
  349     if (lret != LDB_SUCCESS) {
  350         DEBUG(SSSDBG_MINOR_FAILURE,
  351               "ldb_msg_add_empty failed: [%s]\n", ldb_strerror(lret));
  352         ret = EIO;
  353         goto done;
  354     }
  355 
  356     lret = ldb_msg_add_string(msg, attribute, val);
  357     if (lret != LDB_SUCCESS) {
  358         DEBUG(SSSDBG_MINOR_FAILURE,
  359               "ldb_msg_add_string failed: [%s]\n", ldb_strerror(lret));
  360         ret = EIO;
  361         goto done;
  362     }
  363 
  364     lret = ldb_modify(cdb->ldb, msg);
  365     if (lret != LDB_SUCCESS) {
  366         DEBUG(SSSDBG_MINOR_FAILURE,
  367               "ldb_modify failed: [%s](%d)[%s]\n",
  368               ldb_strerror(lret), lret, ldb_errstring(cdb->ldb));
  369         ret = EIO;
  370         goto done;
  371     }
  372 
  373     ret = EOK;
  374 
  375 done:
  376     talloc_free(tmp_ctx);
  377     if (ret != EOK) {
  378         DEBUG(SSSDBG_CRIT_FAILURE,
  379               "Failed to set [%s] from [%s], error [%d] (%s)\n",
  380                attribute, section, ret, strerror(ret));
  381     }
  382     return ret;
  383 }
  384 
  385 int confdb_get_string(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
  386                       const char *section, const char *attribute,
  387                       const char *defstr, char **result)
  388 {
  389     char **values = NULL;
  390     char *restr;
  391     int ret;
  392 
  393     ret = confdb_get_param(cdb, ctx, section, attribute, &values);
  394     if (ret != EOK) {
  395         goto failed;
  396     }
  397 
  398     if (values[0]) {
  399         if (values[1] != NULL) {
  400             /* too many values */
  401             ret = EINVAL;
  402             goto failed;
  403         }
  404         restr = talloc_steal(ctx, values[0]);
  405     } else {
  406         /* Did not return a value, so use the default */
  407 
  408         if (defstr == NULL) { /* No default given */
  409             *result = NULL;
  410             talloc_free(values);
  411             return EOK;
  412         }
  413 
  414         /* Copy the default string */
  415         restr = talloc_strdup(ctx, defstr);
  416     }
  417     if (!restr) {
  418         ret = ENOMEM;
  419         goto failed;
  420     }
  421 
  422     talloc_free(values);
  423 
  424     *result = restr;
  425     return EOK;
  426 
  427 failed:
  428     talloc_free(values);
  429     DEBUG(SSSDBG_CRIT_FAILURE,
  430           "Failed to get [%s] from [%s], error [%d] (%s)\n",
  431               attribute, section, ret, strerror(ret));
  432     return ret;
  433 }
  434 
  435 int confdb_get_int(struct confdb_ctx *cdb,
  436                    const char *section, const char *attribute,
  437                    int defval, int *result)
  438 {
  439     char **values = NULL;
  440     long val;
  441     int ret;
  442     TALLOC_CTX *tmp_ctx;
  443 
  444     tmp_ctx = talloc_new(NULL);
  445     if (tmp_ctx == NULL) {
  446         ret = ENOMEM;
  447         goto failed;
  448     }
  449 
  450     ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
  451     if (ret != EOK) {
  452         goto failed;
  453     }
  454 
  455     if (values[0]) {
  456         if (values[1] != NULL) {
  457             /* too many values */
  458             ret = EINVAL;
  459             goto failed;
  460         }
  461 
  462         errno = 0;
  463         val = strtol(values[0], NULL, 0);
  464         ret = errno;
  465         if (ret != 0) {
  466             goto failed;
  467         }
  468 
  469         if (val < INT_MIN || val > INT_MAX) {
  470             ret = ERANGE;
  471             goto failed;
  472         }
  473 
  474     } else {
  475         val = defval;
  476     }
  477 
  478     talloc_free(tmp_ctx);
  479 
  480     *result = (int)val;
  481     return EOK;
  482 
  483 failed:
  484     talloc_free(tmp_ctx);
  485     DEBUG(SSSDBG_CRIT_FAILURE,
  486           "Failed to read [%s] from [%s], error [%d] (%s)\n",
  487               attribute, section, ret, strerror(ret));
  488     return ret;
  489 }
  490 
  491 long confdb_get_long(struct confdb_ctx *cdb,
  492                      const char *section, const char *attribute,
  493                      long defval, long *result)
  494 {
  495     char **values = NULL;
  496     long val;
  497     int ret;
  498     TALLOC_CTX *tmp_ctx;
  499 
  500     tmp_ctx = talloc_new(NULL);
  501     if (tmp_ctx == NULL) {
  502         ret = ENOMEM;
  503         goto failed;
  504     }
  505 
  506     ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
  507     if (ret != EOK) {
  508         goto failed;
  509     }
  510 
  511     if (values[0]) {
  512         if (values[1] != NULL) {
  513             /* too many values */
  514             ret = EINVAL;
  515             goto failed;
  516         }
  517 
  518         errno = 0;
  519         val = strtol(values[0], NULL, 0);
  520         ret = errno;
  521         if (ret != 0) {
  522             goto failed;
  523         }
  524 
  525     } else {
  526         val = defval;
  527     }
  528 
  529     talloc_free(tmp_ctx);
  530 
  531     *result = val;
  532     return EOK;
  533 
  534 failed:
  535     talloc_free(tmp_ctx);
  536     DEBUG(SSSDBG_CRIT_FAILURE,
  537           "Failed to read [%s] from [%s], error [%d] (%s)\n",
  538               attribute, section, ret, strerror(ret));
  539     return ret;
  540 }
  541 
  542 int confdb_get_bool(struct confdb_ctx *cdb,
  543                     const char *section, const char *attribute,
  544                     bool defval, bool *result)
  545 {
  546     char **values = NULL;
  547     bool val;
  548     int ret;
  549     TALLOC_CTX *tmp_ctx;
  550 
  551     tmp_ctx = talloc_new(NULL);
  552     if (tmp_ctx == NULL) {
  553         ret = ENOMEM;
  554         goto failed;
  555     }
  556 
  557     ret = confdb_get_param(cdb, tmp_ctx, section, attribute, &values);
  558     if (ret != EOK) {
  559         goto failed;
  560     }
  561 
  562     if (values[0]) {
  563         if (values[1] != NULL) {
  564             /* too many values */
  565             ret = EINVAL;
  566             goto failed;
  567         }
  568 
  569         if (strcasecmp(values[0], "FALSE") == 0) {
  570             val = false;
  571 
  572         } else if (strcasecmp(values[0], "TRUE") == 0) {
  573             val = true;
  574 
  575         } else {
  576 
  577             DEBUG(SSSDBG_OP_FAILURE, "Value is not a boolean!\n");
  578             ret = EINVAL;
  579             goto failed;
  580         }
  581 
  582     } else {
  583         val = defval;
  584     }
  585 
  586     talloc_free(tmp_ctx);
  587 
  588     *result = val;
  589     return EOK;
  590 
  591 failed:
  592     talloc_free(tmp_ctx);
  593     DEBUG(SSSDBG_CRIT_FAILURE,
  594           "Failed to read [%s] from [%s], error [%d] (%s)\n",
  595               attribute, section, ret, strerror(ret));
  596     return ret;
  597 }
  598 
  599 /* WARNING: Unlike other similar functions, this one does NOT take a default,
  600  * and returns ENOENT if the attribute was not found ! */
  601 int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
  602                               const char *section, const char *attribute,
  603                               char ***result)
  604 {
  605     char **values = NULL;
  606     int ret;
  607 
  608     ret = confdb_get_param(cdb, ctx, section, attribute, &values);
  609     if (ret != EOK) {
  610         goto done;
  611     }
  612 
  613     if (values && values[0]) {
  614         if (values[1] != NULL) {
  615             /* too many values */
  616             ret = EINVAL;
  617             goto done;
  618         }
  619     } else {
  620         /* Did not return a value */
  621         ret = ENOENT;
  622         goto done;
  623     }
  624 
  625     ret = split_on_separator(ctx, values[0], ',', true, true, result, NULL);
  626 
  627 done:
  628     talloc_free(values);
  629     if (ret != EOK && ret != ENOENT) {
  630         DEBUG(SSSDBG_OP_FAILURE,
  631               "Failed to get [%s] from [%s], error [%d] (%s)\n",
  632                   attribute, section, ret, strerror(ret));
  633     }
  634     return ret;
  635 }
  636 
  637 int confdb_init(TALLOC_CTX *mem_ctx,
  638                 struct confdb_ctx **cdb_ctx,
  639                 const char *confdb_location)
  640 {
  641     struct confdb_ctx *cdb;
  642     int ret = EOK;
  643     mode_t old_umask;
  644 
  645     cdb = talloc_zero(mem_ctx, struct confdb_ctx);
  646     if (!cdb)
  647         return ENOMEM;
  648 
  649     /* Because confdb calls use sync ldb calls, we create a separate event
  650      * context here. This will prevent the ldb sync calls to start nested
  651      * events.
  652      * NOTE: this means that we *cannot* do async calls and return in confdb
  653      * unless we convert all calls and hook back to the main event context.
  654      */
  655 
  656     cdb->pev = tevent_context_init(cdb);
  657     if (!cdb->pev) {
  658         talloc_free(cdb);
  659         return EIO;
  660     }
  661 
  662     cdb->ldb = ldb_init(cdb, cdb->pev);
  663     if (!cdb->ldb) {
  664         talloc_free(cdb);
  665         return EIO;
  666     }
  667 
  668     ret = ldb_set_debug(cdb->ldb, ldb_debug_messages, NULL);
  669     if (ret != LDB_SUCCESS) {
  670         DEBUG(SSSDBG_FATAL_FAILURE,"Could not set up debug fn.\n");
  671         talloc_free(cdb);
  672         return EIO;
  673     }
  674 
  675     old_umask = umask(SSS_DFL_UMASK);
  676 
  677     ret = ldb_connect(cdb->ldb, confdb_location, 0, NULL);
  678     umask(old_umask);
  679     if (ret != LDB_SUCCESS) {
  680         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to open config database [%s]\n",
  681                   confdb_location);
  682         talloc_free(cdb);
  683         return EIO;
  684     }
  685 
  686     *cdb_ctx = cdb;
  687 
  688     return EOK;
  689 }
  690 
  691 static errno_t get_entry_as_uint32(struct ldb_message *msg,
  692                                    uint32_t *return_value,
  693                                    const char *entry,
  694                                    uint32_t default_value)
  695 {
  696     const char *tmp = NULL;
  697     char *endptr;
  698     uint32_t u32ret = 0;
  699 
  700     *return_value = 0;
  701 
  702     if (!msg || !entry) {
  703         return EFAULT;
  704     }
  705 
  706     tmp = ldb_msg_find_attr_as_string(msg, entry, NULL);
  707     if (tmp == NULL) {
  708         *return_value = default_value;
  709         return EOK;
  710     }
  711 
  712     if ((*tmp == '-') || (*tmp == '\0')) {
  713         return EINVAL;
  714     }
  715 
  716     u32ret = strtouint32 (tmp, &endptr, 10);
  717     if (errno) {
  718         return errno;
  719     }
  720 
  721     if (*endptr != '\0') {
  722         /* Not all of the string was a valid number */
  723         return EINVAL;
  724     }
  725 
  726     *return_value = u32ret;
  727     return EOK;
  728 }
  729 
  730 static errno_t get_entry_as_bool(struct ldb_message *msg,
  731                                    bool *return_value,
  732                                    const char *entry,
  733                                    bool default_value)
  734 {
  735     const char *tmp = NULL;
  736 
  737     *return_value = 0;
  738 
  739     if (!msg || !entry) {
  740         return EFAULT;
  741     }
  742 
  743     tmp = ldb_msg_find_attr_as_string(msg, entry, NULL);
  744     if (tmp == NULL || *tmp == '\0') {
  745         *return_value = default_value;
  746         return EOK;
  747     }
  748 
  749     if (strcasecmp(tmp, "FALSE") == 0) {
  750         *return_value = 0;
  751     }
  752     else if (strcasecmp(tmp, "TRUE") == 0) {
  753         *return_value = 1;
  754     }
  755     else {
  756         return EINVAL;
  757     }
  758 
  759     return EOK;
  760 }
  761 
  762 
  763 /* The default UID/GID for domains is 1. This wouldn't work well with
  764  * the local provider */
  765 static uint32_t confdb_get_min_id(struct sss_domain_info *domain)
  766 {
  767     uint32_t defval = SSSD_MIN_ID;
  768 
  769     if (domain && local_provider_is_built()
  770             && strcasecmp(domain->provider, "local") == 0) {
  771         defval = SSSD_LOCAL_MINID;
  772     }
  773 
  774     return defval;
  775 }
  776 
  777 static errno_t init_cached_auth_timeout(struct confdb_ctx *cdb,
  778                                         struct ldb_message *msg,
  779                                         uint32_t *_cached_auth_timeout)
  780 {
  781     int cred_expiration;
  782     int id_timeout;
  783     errno_t ret;
  784     uint32_t cached_auth_timeout;
  785 
  786     ret = get_entry_as_uint32(msg, &cached_auth_timeout,
  787                               CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT, 0);
  788     if (ret != EOK) {
  789         DEBUG(SSSDBG_FATAL_FAILURE,
  790               "Invalid value for [%s]\n", CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT);
  791         goto done;
  792     }
  793 
  794     ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
  795                          CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration);
  796     if (ret != EOK) {
  797         DEBUG(SSSDBG_CRIT_FAILURE,
  798               "Failed to read expiration time of offline credentials.\n");
  799         goto done;
  800     }
  801 
  802     /* convert from days to seconds */
  803     cred_expiration *= 3600 * 24;
  804     if (cred_expiration != 0 &&
  805         cred_expiration < cached_auth_timeout) {
  806         cached_auth_timeout = cred_expiration;
  807     }
  808 
  809     /* Set up the PAM identity timeout */
  810     ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
  811                          CONFDB_PAM_ID_TIMEOUT, 5,
  812                          &id_timeout);
  813     if (ret != EOK) goto done;
  814 
  815     if (cached_auth_timeout > id_timeout) {
  816         DEBUG(SSSDBG_MINOR_FAILURE,
  817               "cached_auth_timeout is greater than pam_id_timeout so be aware "
  818               "that back end could be called to handle initgroups.\n");
  819     }
  820 
  821     ret = EOK;
  822 
  823 done:
  824     if (ret == EOK) {
  825         *_cached_auth_timeout = cached_auth_timeout;
  826     }
  827     return ret;
  828 }
  829 
  830 static int confdb_get_domain_section(TALLOC_CTX *mem_ctx,
  831                                      struct confdb_ctx *cdb,
  832                                      const char *section,
  833                                      const char *name,
  834                                      struct ldb_result **_res)
  835 {
  836     TALLOC_CTX *tmp_ctx;
  837     int ret;
  838     struct ldb_result *res;
  839     struct ldb_dn *dn;
  840 
  841     tmp_ctx = talloc_new(NULL);
  842     if (tmp_ctx == NULL) {
  843         return ENOMEM;
  844     }
  845 
  846     dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", name, section);
  847     if (dn == NULL) {
  848         ret = ENOMEM;
  849         goto done;
  850     }
  851 
  852     ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
  853                      LDB_SCOPE_BASE, NULL, NULL);
  854     if (ret != LDB_SUCCESS) {
  855         ret = sss_ldb_error_to_errno(ret);
  856         goto done;
  857     }
  858 
  859     if (res->count == 0) {
  860         ret = ENOENT;
  861         goto done;
  862     } else if (res->count > 1) {
  863         ret = E2BIG;
  864         goto done;
  865     }
  866 
  867     *_res = talloc_steal(mem_ctx, res);
  868     ret = EOK;
  869 done:
  870     talloc_free(tmp_ctx);
  871     return ret;
  872 }
  873 
  874 static char *confdb_get_domain_hostname(TALLOC_CTX *mem_ctx,
  875                                         struct ldb_result *res,
  876                                         const char *provider)
  877 {
  878     char sys[HOST_NAME_MAX + 1] = {'\0'};
  879     const char *opt = NULL;
  880     int ret;
  881 
  882     if (strcasecmp(provider, "ad") == 0) {
  883         opt = ldb_msg_find_attr_as_string(res->msgs[0], "ad_hostname", NULL);
  884     } else if (strcasecmp(provider, "ipa") == 0) {
  885         opt = ldb_msg_find_attr_as_string(res->msgs[0], "ipa_hostname", NULL);
  886     }
  887 
  888     if (opt != NULL) {
  889         return talloc_strdup(mem_ctx, opt);
  890     }
  891 
  892     ret = gethostname(sys, sizeof(sys));
  893     if (ret != 0) {
  894         ret = errno;
  895         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get hostname [%d]: %s\n", ret,
  896               sss_strerror(ret));
  897         return NULL;
  898     }
  899 
  900     return talloc_strdup(mem_ctx, sys);
  901 }
  902 
  903 static int confdb_get_domain_internal(struct confdb_ctx *cdb,
  904                                       TALLOC_CTX *mem_ctx,
  905                                       const char *name,
  906                                       struct sss_domain_info **_domain)
  907 {
  908     struct sss_domain_info *domain;
  909     struct ldb_result *res;
  910     TALLOC_CTX *tmp_ctx;
  911     const char *tmp, *tmp_pam_target, *tmp_auth;
  912     int ret, val;
  913     uint32_t entry_cache_timeout;
  914     char *default_domain;
  915     bool fqnames_default = false;
  916     int memcache_timeout;
  917 
  918     tmp_ctx = talloc_new(mem_ctx);
  919     if (!tmp_ctx) return ENOMEM;
  920 
  921     ret = confdb_get_domain_section(tmp_ctx, cdb, CONFDB_DOMAIN_BASEDN,
  922                                     name, &res);
  923     if (ret == ENOENT) {
  924         DEBUG(SSSDBG_FATAL_FAILURE, "Unknown domain [%s]\n", name);
  925         goto done;
  926     } else if (ret != EOK) {
  927         DEBUG(SSSDBG_FATAL_FAILURE,
  928               "Error %d: %s while retrieving %s\n",
  929               ret, sss_strerror(ret), name);
  930         goto done;
  931     }
  932 
  933     ret = confdb_get_int(cdb,
  934                          CONFDB_NSS_CONF_ENTRY,
  935                          CONFDB_MEMCACHE_TIMEOUT,
  936                          300, &memcache_timeout);
  937     if (ret != EOK) {
  938         DEBUG(SSSDBG_FATAL_FAILURE,
  939               "Unable to get memory cache entry timeout.\n");
  940         goto done;
  941     }
  942 
  943     domain = talloc_zero(mem_ctx, struct sss_domain_info);
  944     if (!domain) {
  945         ret = ENOMEM;
  946         goto done;
  947     }
  948 
  949     tmp = ldb_msg_find_attr_as_string(res->msgs[0], "cn", NULL);
  950     if (!tmp) {
  951         DEBUG(SSSDBG_FATAL_FAILURE,
  952               "Invalid configuration entry, fatal error!\n");
  953         ret = EINVAL;
  954         goto done;
  955     }
  956     domain->name = talloc_strdup(domain, tmp);
  957     if (!domain->name) {
  958         ret = ENOMEM;
  959         goto done;
  960     }
  961     domain->conn_name = domain->name;
  962 
  963     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
  964                                       CONFDB_DOMAIN_ID_PROVIDER,
  965                                       NULL);
  966     if (tmp) {
  967         domain->provider = talloc_strdup(domain, tmp);
  968         if (!domain->provider) {
  969             ret = ENOMEM;
  970             goto done;
  971         }
  972     }
  973     else {
  974         DEBUG(SSSDBG_FATAL_FAILURE,
  975               "Domain [%s] does not specify an ID provider, disabling!\n",
  976                   domain->name);
  977         ret = EINVAL;
  978         goto done;
  979     }
  980 
  981     tmp = ldb_msg_find_attr_as_string(res->msgs[0], CONFDB_DOMAIN_AUTO_UPG, NULL);
  982     if (tmp == NULL || *tmp == '\0') {
  983         tmp = "false";
  984     }
  985 
  986     if (strcasecmp(domain->provider, "local") == 0) {
  987         if (!local_provider_is_built()) {
  988             DEBUG(SSSDBG_FATAL_FAILURE,
  989                   "ID provider 'local' no longer supported, disabling\n");
  990             ret = EINVAL;
  991             goto done;
  992         }
  993     }
  994 
  995     domain->mpg_mode = str_to_domain_mpg_mode(tmp);
  996 
  997     if (local_provider_is_built()
  998             && strcasecmp(domain->provider, "local") == 0) {
  999         /* If this is the local provider, we need to ensure that
 1000          * no other provider was specified for other types, since
 1001          * the local provider cannot load them.
 1002          */
 1003         tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1004                                           CONFDB_DOMAIN_AUTH_PROVIDER,
 1005                                           NULL);
 1006         if (tmp && strcasecmp(tmp, "local") != 0) {
 1007             DEBUG(SSSDBG_FATAL_FAILURE,
 1008                   "Local ID provider does not support [%s] as an AUTH provider.\n", tmp);
 1009             ret = EINVAL;
 1010             goto done;
 1011         }
 1012 
 1013         tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1014                                           CONFDB_DOMAIN_ACCESS_PROVIDER,
 1015                                           NULL);
 1016         if (tmp && strcasecmp(tmp, "permit") != 0) {
 1017             DEBUG(SSSDBG_FATAL_FAILURE,
 1018                   "Local ID provider does not support [%s] as an ACCESS provider.\n", tmp);
 1019             ret = EINVAL;
 1020             goto done;
 1021         }
 1022 
 1023         tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1024                                           CONFDB_DOMAIN_CHPASS_PROVIDER,
 1025                                           NULL);
 1026         if (tmp && strcasecmp(tmp, "local") != 0) {
 1027             DEBUG(SSSDBG_FATAL_FAILURE,
 1028                   "Local ID provider does not support [%s] as a CHPASS provider.\n", tmp);
 1029             ret = EINVAL;
 1030             goto done;
 1031         }
 1032 
 1033         /* The LOCAL provider use always Magic Private Groups */
 1034         domain->mpg_mode = MPG_ENABLED;
 1035     }
 1036 
 1037     domain->timeout = ldb_msg_find_attr_as_int(res->msgs[0],
 1038                                                CONFDB_DOMAIN_TIMEOUT, 0);
 1039 
 1040     /* Determine if this domain can be enumerated */
 1041 
 1042     /* TEMP: test if the old bitfield conf value is used and warn it has been
 1043      * superseded. */
 1044     val = ldb_msg_find_attr_as_int(res->msgs[0], CONFDB_DOMAIN_ENUMERATE, 0);
 1045     if (val > 0) { /* ok there was a number in here */
 1046         DEBUG(SSSDBG_FATAL_FAILURE,
 1047               "Warning: enumeration parameter in %s still uses integers! "
 1048                   "Enumeration is now a boolean and takes true/false values. "
 1049                   "Interpreting as true\n", domain->name);
 1050         domain->enumerate = true;
 1051     } else { /* assume the new format */
 1052         ret = get_entry_as_bool(res->msgs[0], &domain->enumerate,
 1053                                 CONFDB_DOMAIN_ENUMERATE, 0);
 1054         if(ret != EOK) {
 1055             DEBUG(SSSDBG_FATAL_FAILURE,
 1056                   "Invalid value for %s\n", CONFDB_DOMAIN_ENUMERATE);
 1057             goto done;
 1058         }
 1059     }
 1060 
 1061     if (is_files_provider(domain)) {
 1062         /* The password field must be reported as 'x', else pam_unix won't
 1063          * authenticate this entry. See man pwconv(8) for more details.
 1064          */
 1065         domain->pwfield = "x";
 1066     }
 1067 
 1068     if (domain->provider != NULL && strcasecmp(domain->provider, "proxy") == 0) {
 1069         /* The password field must be reported as 'x' for proxy provider
 1070          * using files library, else pam_unix won't authenticate this entry.
 1071          * We set this only for sssd-shadowutils target which can be used
 1072          * to authenticate with pam_unix only. Otherwise we let administrator
 1073          * to overwrite default * value with pwfield option to avoid regression
 1074          * on more common use case where remote authentication is required. */
 1075         tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1076                                           CONFDB_PROXY_LIBNAME,
 1077                                           NULL);
 1078 
 1079         tmp_auth = ldb_msg_find_attr_as_string(res->msgs[0],
 1080                                                 CONFDB_DOMAIN_AUTH_PROVIDER,
 1081                                                 NULL);
 1082 
 1083         tmp_pam_target = ldb_msg_find_attr_as_string(res->msgs[0],
 1084                                                      CONFDB_PROXY_PAM_TARGET,
 1085                                                      NULL);
 1086 
 1087         if (tmp != NULL && tmp_pam_target != NULL
 1088             && strcasecmp(tmp, "files") == 0
 1089             && (tmp_auth == NULL || strcasecmp(tmp_auth, "proxy") == 0)
 1090             && strcmp(tmp_pam_target, "sssd-shadowutils") == 0) {
 1091             domain->pwfield = "x";
 1092         }
 1093     }
 1094 
 1095     if (!domain->enumerate) {
 1096         DEBUG(SSSDBG_TRACE_FUNC, "No enumeration for [%s]!\n", domain->name);
 1097         DEBUG(SSSDBG_TRACE_FUNC,
 1098               "Please note that when enumeration is disabled `getent "
 1099               "passwd` does not return all users by design. See "
 1100               "sssd.conf man page for more detailed information\n");
 1101     }
 1102 
 1103     ret = confdb_get_string(cdb, tmp_ctx, CONFDB_MONITOR_CONF_ENTRY,
 1104                             CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
 1105                             &default_domain);
 1106     if (ret != EOK) {
 1107         DEBUG(SSSDBG_OP_FAILURE,
 1108               "Cannot get the default domain [%d]: %s\n",
 1109                ret, strerror(ret));
 1110         goto done;
 1111     }
 1112 
 1113     /* Determine if user/group names will be Fully Qualified
 1114      * in NSS interfaces */
 1115     if (default_domain != NULL
 1116              && is_files_provider(domain) == false) {
 1117         DEBUG(SSSDBG_CONF_SETTINGS,
 1118               "Default domain suffix set. Changing default for "
 1119               "use_fully_qualified_names to True.\n");
 1120         fqnames_default = true;
 1121     }
 1122 
 1123     ret = get_entry_as_bool(res->msgs[0], &domain->fqnames,
 1124                             CONFDB_DOMAIN_FQ, fqnames_default);
 1125     if (ret != EOK) {
 1126         DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for %s\n",
 1127               CONFDB_DOMAIN_FQ);
 1128         goto done;
 1129     }
 1130 
 1131     if (default_domain != NULL
 1132             && domain->fqnames == false
 1133             && is_files_provider(domain) == false) {
 1134         DEBUG(SSSDBG_FATAL_FAILURE,
 1135               "Invalid configuration detected (default_domain_suffix is used "
 1136               "while use_fully_qualified_names was set to false).\n");
 1137         ret = ERR_INVALID_CONFIG;
 1138         goto done;
 1139     }
 1140 
 1141     ret = get_entry_as_bool(res->msgs[0], &domain->ignore_group_members,
 1142                             CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS, 0);
 1143     if(ret != EOK) {
 1144         DEBUG(SSSDBG_FATAL_FAILURE,
 1145               "Invalid value for %s\n",
 1146                CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS);
 1147         goto done;
 1148     }
 1149 
 1150     ret = get_entry_as_uint32(res->msgs[0], &domain->id_min,
 1151                               CONFDB_DOMAIN_MINID,
 1152                               confdb_get_min_id(domain));
 1153     if (ret != EOK) {
 1154         DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for minId\n");
 1155         ret = EINVAL;
 1156         goto done;
 1157     }
 1158 
 1159     ret = get_entry_as_uint32(res->msgs[0], &domain->id_max,
 1160                               CONFDB_DOMAIN_MAXID, 0);
 1161     if (ret != EOK) {
 1162         DEBUG(SSSDBG_FATAL_FAILURE, "Invalid value for maxId\n");
 1163         ret = EINVAL;
 1164         goto done;
 1165     }
 1166 
 1167     if (domain->id_max && (domain->id_max < domain->id_min)) {
 1168         DEBUG(SSSDBG_FATAL_FAILURE, "Invalid domain range\n");
 1169         ret = EINVAL;
 1170         goto done;
 1171     }
 1172 
 1173     /* Do we allow to cache credentials */
 1174     ret = get_entry_as_bool(res->msgs[0], &domain->cache_credentials,
 1175                             CONFDB_DOMAIN_CACHE_CREDS, 0);
 1176     if(ret != EOK) {
 1177         DEBUG(SSSDBG_FATAL_FAILURE,
 1178               "Invalid value for %s\n", CONFDB_DOMAIN_CACHE_CREDS);
 1179         goto done;
 1180     }
 1181 
 1182     ret = get_entry_as_uint32(res->msgs[0],
 1183                               &domain->cache_credentials_min_ff_length,
 1184                               CONFDB_DOMAIN_CACHE_CREDS_MIN_FF_LENGTH,
 1185                               CONFDB_DEFAULT_CACHE_CREDS_MIN_FF_LENGTH);
 1186     if (ret != EOK) {
 1187         DEBUG(SSSDBG_FATAL_FAILURE,
 1188               "Invalid value for %s\n",
 1189               CONFDB_DOMAIN_CACHE_CREDS_MIN_FF_LENGTH);
 1190         goto done;
 1191     }
 1192 
 1193     /* Get the global entry cache timeout setting */
 1194     ret = get_entry_as_uint32(res->msgs[0], &entry_cache_timeout,
 1195                               CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT, 5400);
 1196     if (ret != EOK) {
 1197         DEBUG(SSSDBG_FATAL_FAILURE,
 1198               "Invalid value for [%s]\n",
 1199                 CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT);
 1200         goto done;
 1201     }
 1202 
 1203     /* Override the user cache timeout, if specified */
 1204     ret = get_entry_as_uint32(res->msgs[0], &domain->user_timeout,
 1205                               CONFDB_DOMAIN_USER_CACHE_TIMEOUT,
 1206                               entry_cache_timeout);
 1207     if (ret != EOK) {
 1208         DEBUG(SSSDBG_FATAL_FAILURE,
 1209               "Invalid value for [%s]\n",
 1210                CONFDB_DOMAIN_USER_CACHE_TIMEOUT);
 1211         goto done;
 1212     }
 1213 
 1214     if (domain->user_timeout < memcache_timeout) {
 1215         DEBUG(SSSDBG_CONF_SETTINGS,
 1216               "%s is less than %s. User records will not be updated before "
 1217               "memory cache entry expires.\n",
 1218               CONFDB_DOMAIN_USER_CACHE_TIMEOUT, CONFDB_MEMCACHE_TIMEOUT);
 1219     }
 1220 
 1221     /* Override the group cache timeout, if specified */
 1222     ret = get_entry_as_uint32(res->msgs[0], &domain->group_timeout,
 1223                               CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT,
 1224                               entry_cache_timeout);
 1225     if (ret != EOK) {
 1226         DEBUG(SSSDBG_FATAL_FAILURE,
 1227               "Invalid value for [%s]\n",
 1228                CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT);
 1229         goto done;
 1230     }
 1231 
 1232     if (domain->group_timeout < memcache_timeout) {
 1233         DEBUG(SSSDBG_CONF_SETTINGS,
 1234               "%s is less than %s. Group records will not be updated before "
 1235               "memory cache entry expires.\n",
 1236               CONFDB_DOMAIN_GROUP_CACHE_TIMEOUT, CONFDB_MEMCACHE_TIMEOUT);
 1237     }
 1238 
 1239     /* Override the netgroup cache timeout, if specified */
 1240     ret = get_entry_as_uint32(res->msgs[0], &domain->netgroup_timeout,
 1241                               CONFDB_DOMAIN_NETGROUP_CACHE_TIMEOUT,
 1242                               entry_cache_timeout);
 1243     if (ret != EOK) {
 1244         DEBUG(SSSDBG_FATAL_FAILURE,
 1245               "Invalid value for [%s]\n",
 1246                CONFDB_DOMAIN_NETGROUP_CACHE_TIMEOUT);
 1247         goto done;
 1248     }
 1249 
 1250     /* Override the service cache timeout, if specified */
 1251     ret = get_entry_as_uint32(res->msgs[0], &domain->service_timeout,
 1252                               CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT,
 1253                               entry_cache_timeout);
 1254     if (ret != EOK) {
 1255         DEBUG(SSSDBG_FATAL_FAILURE,
 1256               "Invalid value for [%s]\n",
 1257                CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT);
 1258         goto done;
 1259     }
 1260 
 1261     /* Override the autofs cache timeout, if specified */
 1262     ret = get_entry_as_uint32(res->msgs[0], &domain->autofsmap_timeout,
 1263                               CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT,
 1264                               entry_cache_timeout);
 1265     if (ret != EOK) {
 1266         DEBUG(SSSDBG_FATAL_FAILURE,
 1267               "Invalid value for [%s]\n",
 1268                CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT);
 1269         goto done;
 1270     }
 1271 
 1272     /* Override the sudo cache timeout, if specified */
 1273     ret = get_entry_as_uint32(res->msgs[0], &domain->sudo_timeout,
 1274                               CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT,
 1275                               entry_cache_timeout);
 1276     if (ret != EOK) {
 1277         DEBUG(SSSDBG_FATAL_FAILURE,
 1278               "Invalid value for [%s]\n",
 1279                CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT);
 1280         goto done;
 1281     }
 1282 
 1283     /* Override the ssh known hosts timeout, if specified */
 1284     ret = get_entry_as_uint32(res->msgs[0], &domain->ssh_host_timeout,
 1285                               CONFDB_DOMAIN_SSH_HOST_CACHE_TIMEOUT,
 1286                               entry_cache_timeout);
 1287     if (ret != EOK) {
 1288         DEBUG(SSSDBG_FATAL_FAILURE,
 1289               "Invalid value for [%s]\n",
 1290               CONFDB_DOMAIN_SSH_HOST_CACHE_TIMEOUT);
 1291         goto done;
 1292     }
 1293 
 1294     /* Override the computer timeout, if specified */
 1295     ret = get_entry_as_uint32(res->msgs[0], &domain->computer_timeout,
 1296                               CONFDB_DOMAIN_COMPUTER_CACHE_TIMEOUT,
 1297                               entry_cache_timeout);
 1298     if (ret != EOK) {
 1299         DEBUG(SSSDBG_FATAL_FAILURE,
 1300               "Invalid value for [%s]\n",
 1301               CONFDB_DOMAIN_COMPUTER_CACHE_TIMEOUT);
 1302         goto done;
 1303     }
 1304 
 1305     /* Override the resolver timeout, if specified */
 1306     ret = get_entry_as_uint32(res->msgs[0], &domain->resolver_timeout,
 1307                               CONFDB_DOMAIN_RESOLVER_CACHE_TIMEOUT,
 1308                               entry_cache_timeout);
 1309     if (ret != EOK) {
 1310         DEBUG(SSSDBG_FATAL_FAILURE,
 1311               "Invalid value for [%s]\n",
 1312                CONFDB_DOMAIN_RESOLVER_CACHE_TIMEOUT);
 1313         goto done;
 1314     }
 1315 
 1316     /* Set refresh_expired_interval, if specified */
 1317     ret = get_entry_as_uint32(res->msgs[0], &domain->refresh_expired_interval,
 1318                               CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL,
 1319                               0);
 1320     if (ret != EOK) {
 1321         DEBUG(SSSDBG_FATAL_FAILURE,
 1322               "Invalid value for [%s]\n",
 1323                CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL);
 1324         goto done;
 1325     }
 1326 
 1327     /* detect and fix misconfiguration */
 1328     if (domain->refresh_expired_interval > entry_cache_timeout) {
 1329         DEBUG(SSSDBG_CONF_SETTINGS,
 1330               "refresh_expired_interval (%d) cannot be greater than "
 1331               "entry_cache_timeout (%u)\n",
 1332               domain->refresh_expired_interval, entry_cache_timeout);
 1333 
 1334         domain->refresh_expired_interval = 0.75 * entry_cache_timeout;
 1335 
 1336         DEBUG(SSSDBG_CONF_SETTINGS,
 1337               "refresh_expired_interval is being set to recommended value "
 1338               "entry_cache_timeout * 0.75 (%u).\n",
 1339               domain->refresh_expired_interval);
 1340     }
 1341 
 1342     /* Set the PAM warning time, if specified. If not specified, pass on
 1343      * the "not set" value of "-1" which means "use provider default". The
 1344      * value 0 means "always display the warning if server sends one" */
 1345     domain->pwd_expiration_warning = -1;
 1346 
 1347     val = ldb_msg_find_attr_as_int(res->msgs[0],
 1348                                    CONFDB_DOMAIN_PWD_EXPIRATION_WARNING,
 1349                                    -1);
 1350     if (val == -1) {
 1351         ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
 1352                              CONFDB_PAM_PWD_EXPIRATION_WARNING,
 1353                              -1, &val);
 1354         if (ret != EOK) {
 1355             DEBUG(SSSDBG_CRIT_FAILURE,
 1356                   "Failed to read PAM expiration warning, not fatal.\n");
 1357             val = -1;
 1358         }
 1359     }
 1360 
 1361     DEBUG(SSSDBG_TRACE_LIBS, "pwd_expiration_warning is %d\n", val);
 1362     if (val >= 0) {
 1363         DEBUG(SSSDBG_CONF_SETTINGS,
 1364               "Setting domain password expiration warning to %d days\n", val);
 1365         /* The value is in days, transform it to seconds */
 1366         domain->pwd_expiration_warning = val * 24 * 3600;
 1367     }
 1368 
 1369     ret = get_entry_as_uint32(res->msgs[0], &domain->override_gid,
 1370                               CONFDB_DOMAIN_OVERRIDE_GID, 0);
 1371     if (ret != EOK) {
 1372         DEBUG(SSSDBG_FATAL_FAILURE,
 1373               "Invalid value for [%s]\n", CONFDB_DOMAIN_OVERRIDE_GID);
 1374         goto done;
 1375     }
 1376 
 1377     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1378                                       CONFDB_NSS_OVERRIDE_HOMEDIR, NULL);
 1379     /* Here we skip the files provider as it should always return *only*
 1380      * what's in the files and nothing else. */
 1381     if (tmp != NULL && !is_files_provider(domain)) {
 1382         domain->override_homedir = talloc_strdup(domain, tmp);
 1383         if (!domain->override_homedir) {
 1384             ret = ENOMEM;
 1385             goto done;
 1386         }
 1387     }
 1388 
 1389     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1390                                       CONFDB_NSS_FALLBACK_HOMEDIR, NULL);
 1391     if (tmp != NULL) {
 1392         domain->fallback_homedir = talloc_strdup(domain, tmp);
 1393         if (!domain->fallback_homedir) {
 1394             ret = ENOMEM;
 1395             goto done;
 1396         }
 1397     } else {
 1398         if (strcasecmp(domain->provider, "ad") == 0) {
 1399             /* ad provider default */
 1400             domain->fallback_homedir = talloc_strdup(domain, "/home/%d/%u");
 1401             if (!domain->fallback_homedir) {
 1402                 ret = ENOMEM;
 1403                 goto done;
 1404             }
 1405         }
 1406     }
 1407 
 1408     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1409                                       CONFDB_DOMAIN_SUBDOMAIN_HOMEDIR,
 1410                                       CONFDB_DOMAIN_DEFAULT_SUBDOMAIN_HOMEDIR);
 1411     if (tmp != NULL) {
 1412         domain->subdomain_homedir = talloc_strdup(domain, tmp);
 1413         if (!domain->subdomain_homedir) {
 1414             ret = ENOMEM;
 1415             goto done;
 1416         }
 1417     }
 1418 
 1419     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1420                                       CONFDB_NSS_HOMEDIR_SUBSTRING, NULL);
 1421     if (tmp != NULL) {
 1422         domain->homedir_substr = talloc_strdup(domain, tmp);
 1423         if (domain->homedir_substr == NULL) {
 1424             ret = ENOMEM;
 1425             goto done;
 1426         }
 1427     }
 1428 
 1429     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1430                                       CONFDB_NSS_OVERRIDE_SHELL, NULL);
 1431     /* Here we skip the files provider as it should always return *only*
 1432      * what's in the files and nothing else. */
 1433     if (tmp != NULL && !is_files_provider(domain)) {
 1434         domain->override_shell = talloc_strdup(domain, tmp);
 1435         if (!domain->override_shell) {
 1436             ret = ENOMEM;
 1437             goto done;
 1438         }
 1439     }
 1440 
 1441     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1442                                       CONFDB_NSS_DEFAULT_SHELL, NULL);
 1443     if (tmp != NULL) {
 1444         domain->default_shell = talloc_strdup(domain, tmp);
 1445         if (!domain->default_shell) {
 1446             ret = ENOMEM;
 1447             goto done;
 1448         }
 1449     }
 1450 
 1451     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1452                                       CONFDB_DOMAIN_CASE_SENSITIVE, NULL);
 1453     if (tmp != NULL) {
 1454         if (strcasecmp(tmp, "true") == 0) {
 1455             domain->case_sensitive = true;
 1456             domain->case_preserve = true;
 1457         } else if (strcasecmp(tmp, "false") == 0) {
 1458             domain->case_sensitive = false;
 1459             domain->case_preserve = false;
 1460         } else if (strcasecmp(tmp, "preserving") == 0) {
 1461             domain->case_sensitive = false;
 1462             domain->case_preserve = true;
 1463         } else {
 1464             DEBUG(SSSDBG_FATAL_FAILURE,
 1465                   "Invalid value for %s\n", CONFDB_DOMAIN_CASE_SENSITIVE);
 1466             ret = EINVAL;
 1467             goto done;
 1468         }
 1469     } else {
 1470         /* default */
 1471         if (strcasecmp(domain->provider, "ad") == 0) {
 1472             domain->case_sensitive = false;
 1473             domain->case_preserve = false;
 1474         } else {
 1475             domain->case_sensitive = true;
 1476             domain->case_preserve = true;
 1477         }
 1478     }
 1479 
 1480     if (domain->case_sensitive == false &&
 1481         local_provider_is_built() &&
 1482         strcasecmp(domain->provider, "local") == 0) {
 1483         DEBUG(SSSDBG_FATAL_FAILURE,
 1484              "Local ID provider does not support the case insensitive flag\n");
 1485         ret = EINVAL;
 1486         goto done;
 1487     }
 1488 
 1489     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1490                                       CONFDB_NSS_PWFIELD, NULL);
 1491     if (tmp != NULL) {
 1492         domain->pwfield = talloc_strdup(domain, tmp);
 1493         if (!domain->pwfield) {
 1494             ret = ENOMEM;
 1495             goto done;
 1496         }
 1497     }
 1498 
 1499     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1500                                       CONFDB_SUBDOMAIN_ENUMERATE,
 1501                                       CONFDB_DEFAULT_SUBDOMAIN_ENUMERATE);
 1502     if (tmp != NULL) {
 1503         ret = split_on_separator(domain, tmp, ',', true, true,
 1504                                  &domain->sd_enumerate, NULL);
 1505         if (ret != 0) {
 1506             DEBUG(SSSDBG_FATAL_FAILURE,
 1507                   "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
 1508             goto done;
 1509         }
 1510     }
 1511 
 1512     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1513                                       CONFDB_DOMAIN_SUBDOMAIN_INHERIT,
 1514                                       NULL);
 1515     if (tmp != NULL) {
 1516         ret = split_on_separator(domain, tmp, ',', true, true,
 1517                                  &domain->sd_inherit, NULL);
 1518         if (ret != 0) {
 1519             DEBUG(SSSDBG_FATAL_FAILURE,
 1520                   "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
 1521             goto done;
 1522         }
 1523     }
 1524 
 1525     domain->type = DOM_TYPE_POSIX;
 1526     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1527                                       CONFDB_DOMAIN_TYPE,
 1528                                       CONFDB_DOMAIN_TYPE_POSIX);
 1529     if (tmp != NULL) {
 1530         if (strcasecmp(tmp, CONFDB_DOMAIN_TYPE_POSIX) == 0) {
 1531             domain->type = DOM_TYPE_POSIX;
 1532         } else if (strcasecmp(tmp, CONFDB_DOMAIN_TYPE_APP) == 0) {
 1533             domain->type = DOM_TYPE_APPLICATION;
 1534         } else {
 1535             DEBUG(SSSDBG_FATAL_FAILURE,
 1536                   "Invalid value %s for [%s]\n", tmp, CONFDB_DOMAIN_TYPE);
 1537             ret = EINVAL;
 1538             goto done;
 1539         }
 1540     }
 1541 
 1542     ret = get_entry_as_uint32(res->msgs[0], &domain->subdomain_refresh_interval,
 1543                               CONFDB_DOMAIN_SUBDOMAIN_REFRESH,
 1544                               CONFDB_DOMAIN_SUBDOMAIN_REFRESH_DEFAULT_VALUE);
 1545     if (ret != EOK) {
 1546         DEBUG(SSSDBG_FATAL_FAILURE,
 1547               "Invalid value for [%s]\n", CONFDB_DOMAIN_SUBDOMAIN_REFRESH);
 1548         goto done;
 1549     } else if (domain->subdomain_refresh_interval == 0) {
 1550         DEBUG(SSSDBG_MINOR_FAILURE,
 1551               "Invalid value for [%s]. Setting up the default value: %d\n",
 1552               CONFDB_DOMAIN_SUBDOMAIN_REFRESH,
 1553               CONFDB_DOMAIN_SUBDOMAIN_REFRESH_DEFAULT_VALUE);
 1554 
 1555         domain->subdomain_refresh_interval =
 1556             CONFDB_DOMAIN_SUBDOMAIN_REFRESH_DEFAULT_VALUE;
 1557     }
 1558 
 1559     ret = init_cached_auth_timeout(cdb, res->msgs[0],
 1560                                    &domain->cached_auth_timeout);
 1561     if (ret != EOK) {
 1562         DEBUG(SSSDBG_CRIT_FAILURE,
 1563               "init_cached_auth_timeout failed: %s:[%d].\n",
 1564               sss_strerror(ret), ret);
 1565         goto done;
 1566     }
 1567 
 1568     domain->hostname = confdb_get_domain_hostname(domain, res, domain->provider);
 1569     if (domain->hostname == NULL) {
 1570         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain hostname\n");
 1571         goto done;
 1572     }
 1573 
 1574     domain->krb5_keytab = NULL;
 1575     tmp = ldb_msg_find_attr_as_string(res->msgs[0], "krb5_keytab", NULL);
 1576     if (tmp != NULL) {
 1577         domain->krb5_keytab = talloc_strdup(domain, tmp);
 1578         if (domain->krb5_keytab == NULL) {
 1579             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain keytab!\n");
 1580             goto done;
 1581         }
 1582     }
 1583 
 1584     tmp = ldb_msg_find_attr_as_string(res->msgs[0], CONFDB_PAM_GSSAPI_SERVICES,
 1585                                       NULL);
 1586     if (tmp != NULL) {
 1587         ret = split_on_separator(domain, tmp, ',', true, true,
 1588                                  &domain->gssapi_services, NULL);
 1589         if (ret != 0) {
 1590             DEBUG(SSSDBG_FATAL_FAILURE,
 1591                   "Cannot parse %s\n", CONFDB_PAM_GSSAPI_SERVICES);
 1592             goto done;
 1593         }
 1594     }
 1595 
 1596     tmp = ldb_msg_find_attr_as_string(res->msgs[0], CONFDB_PAM_GSSAPI_CHECK_UPN,
 1597                                       NULL);
 1598     if (tmp != NULL) {
 1599         domain->gssapi_check_upn = talloc_strdup(domain, tmp);
 1600         if (domain->gssapi_check_upn == NULL) {
 1601             ret = ENOMEM;
 1602             goto done;
 1603         }
 1604     }
 1605 
 1606     tmp = ldb_msg_find_attr_as_string(res->msgs[0],
 1607                                       CONFDB_PAM_GSSAPI_INDICATORS_MAP,
 1608                                       NULL);
 1609     if (tmp != NULL && tmp[0] != '\0') {
 1610         ret = split_on_separator(domain, tmp, ',', true, true,
 1611                                  &domain->gssapi_indicators_map, NULL);
 1612         if (ret != 0) {
 1613             DEBUG(SSSDBG_FATAL_FAILURE,
 1614                   "Cannot parse %s\n", CONFDB_PAM_GSSAPI_INDICATORS_MAP);
 1615             goto done;
 1616         }
 1617     }
 1618 
 1619     domain->has_views = false;
 1620     domain->view_name = NULL;
 1621 
 1622     domain->state = DOM_ACTIVE;
 1623 
 1624     *_domain = domain;
 1625     ret = EOK;
 1626 done:
 1627     talloc_free(tmp_ctx);
 1628     return ret;
 1629 }
 1630 
 1631 int confdb_get_domains(struct confdb_ctx *cdb,
 1632                        struct sss_domain_info **domains)
 1633 {
 1634     TALLOC_CTX *tmp_ctx;
 1635     struct sss_domain_info *domain = NULL;
 1636     char **domlist;
 1637     int ret, i;
 1638 
 1639     if (cdb->doms) {
 1640         *domains = cdb->doms;
 1641         return EOK;
 1642     }
 1643 
 1644     tmp_ctx = talloc_new(NULL);
 1645     if (!tmp_ctx) return ENOMEM;
 1646 
 1647     ret = confdb_get_enabled_domain_list(cdb, tmp_ctx, &domlist);
 1648     if (ret == ENOENT) {
 1649         DEBUG(SSSDBG_MINOR_FAILURE, "No domains configured, fatal error!\n");
 1650         goto done;
 1651     }
 1652     if (ret != EOK ) {
 1653         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
 1654         goto done;
 1655     }
 1656 
 1657     for (i = 0; domlist[i]; i++) {
 1658         /* check if domain name is really unique */
 1659         DLIST_FOR_EACH(domain, cdb->doms) {
 1660             if (strcasecmp(domain->name, domlist[i]) == 0) {
 1661                 DEBUG(SSSDBG_FATAL_FAILURE,
 1662                       SAME_DOMAINS_ERROR_MSG, domlist[i], domain->name);
 1663                 sss_log(SSS_LOG_CRIT,
 1664                         SAME_DOMAINS_ERROR_MSG, domlist[i], domain->name);
 1665 
 1666                 ret = EINVAL;
 1667                 goto done;
 1668             }
 1669         }
 1670 
 1671         domain = NULL;
 1672         ret = confdb_get_domain_internal(cdb, cdb, domlist[i], &domain);
 1673         if (ret) {
 1674             DEBUG(SSSDBG_FATAL_FAILURE,
 1675                   RETRIEVE_DOMAIN_ERROR_MSG,
 1676                   ret, sss_strerror(ret), domlist[i]);
 1677             sss_log(SSS_LOG_CRIT,
 1678                     RETRIEVE_DOMAIN_ERROR_MSG,
 1679                     ret, sss_strerror(ret), domlist[i]);
 1680 
 1681             continue;
 1682         }
 1683 
 1684         DLIST_ADD_END(cdb->doms, domain, struct sss_domain_info *);
 1685     }
 1686 
 1687     if (cdb->doms == NULL) {
 1688         DEBUG(SSSDBG_FATAL_FAILURE,
 1689               "No properly configured domains, fatal error!\n");
 1690         ret = ENOENT;
 1691         goto done;
 1692     }
 1693 
 1694     *domains = cdb->doms;
 1695     ret = EOK;
 1696 
 1697 done:
 1698     talloc_free(tmp_ctx);
 1699     return ret;
 1700 }
 1701 
 1702 int confdb_get_domain(struct confdb_ctx *cdb,
 1703                       const char *name,
 1704                       struct sss_domain_info **_domain)
 1705 {
 1706     struct sss_domain_info *dom, *doms;
 1707     int ret;
 1708 
 1709     ret = confdb_get_domains(cdb, &doms);
 1710     if (ret != EOK) {
 1711         return ret;
 1712     }
 1713 
 1714     for (dom = doms; dom; dom = get_next_domain(dom, 0)) {
 1715         if (strcasecmp(dom->name, name) == 0) {
 1716             *_domain = dom;
 1717             return EOK;
 1718         }
 1719     }
 1720 
 1721     return ENOENT;
 1722 }
 1723 
 1724 int confdb_list_all_domain_names(TALLOC_CTX *mem_ctx,
 1725                                  struct confdb_ctx *cdb,
 1726                                  char ***_names)
 1727 {
 1728     TALLOC_CTX *tmp_ctx = NULL;
 1729     struct ldb_dn *dn = NULL;
 1730     struct ldb_result *res = NULL;
 1731     static const char *attrs[] = {CONFDB_DOMAIN_ATTR, NULL};
 1732     const char *name = NULL;
 1733     char **names = NULL;
 1734     int i;
 1735     int ret;
 1736 
 1737     tmp_ctx = talloc_new(NULL);
 1738     if (tmp_ctx == NULL) {
 1739         return ENOMEM;
 1740     }
 1741 
 1742     dn = ldb_dn_new(tmp_ctx, cdb->ldb, CONFDB_DOMAIN_BASEDN);
 1743     if (dn == NULL) {
 1744         ret = ENOMEM;
 1745         goto done;
 1746     }
 1747 
 1748     ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
 1749                      attrs, NULL);
 1750     if (ret != LDB_SUCCESS) {
 1751         ret = EIO;
 1752         goto done;
 1753     }
 1754 
 1755     names = talloc_zero_array(tmp_ctx, char*, res->count + 1);
 1756     if (names == NULL) {
 1757         ret = ENOMEM;
 1758         goto done;
 1759     }
 1760 
 1761     for (i = 0; i < res->count; i++) {
 1762         name = ldb_msg_find_attr_as_string(res->msgs[i], CONFDB_DOMAIN_ATTR,
 1763                                            NULL);
 1764         if (name == NULL) {
 1765             DEBUG(SSSDBG_MINOR_FAILURE,
 1766                   "The object [%s] doesn't have a name\n",
 1767                    ldb_dn_get_linearized(res->msgs[i]->dn));
 1768             ret = EINVAL;
 1769             goto done;
 1770         }
 1771 
 1772         names[i] = talloc_strdup(names, name);
 1773         if (names[i] == NULL) {
 1774             ret = ENOMEM;
 1775             goto done;
 1776         }
 1777     }
 1778 
 1779     *_names = talloc_steal(mem_ctx, names);
 1780 
 1781     ret = EOK;
 1782 
 1783 done:
 1784     talloc_free(tmp_ctx);
 1785     return ret;
 1786 }
 1787 
 1788 int confdb_get_sub_sections(TALLOC_CTX *mem_ctx,
 1789                             struct confdb_ctx *cdb,
 1790                             const char *section,
 1791                             char ***sections,
 1792                             int *num_sections)
 1793 {
 1794     TALLOC_CTX *tmp_ctx = NULL;
 1795     char *secdn;
 1796     struct ldb_dn *base = NULL;
 1797     struct ldb_result *res = NULL;
 1798     static const char *attrs[] = {"cn", NULL};
 1799     char **names;
 1800     int base_comp_num;
 1801     int num;
 1802     int i;
 1803     int ret;
 1804 
 1805     tmp_ctx = talloc_new(mem_ctx);
 1806     if (tmp_ctx == NULL) {
 1807         return ENOMEM;
 1808     }
 1809 
 1810     ret = parse_section(tmp_ctx, section, &secdn, NULL);
 1811     if (ret != EOK) {
 1812         goto done;
 1813     }
 1814 
 1815     base = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
 1816     if (base == NULL) {
 1817         ret = ENOMEM;
 1818         goto done;
 1819     }
 1820 
 1821     base_comp_num = ldb_dn_get_comp_num(base);
 1822 
 1823     ret = ldb_search(cdb->ldb, tmp_ctx, &res, base, LDB_SCOPE_SUBTREE,
 1824                      attrs, NULL);
 1825     if (ret != LDB_SUCCESS) {
 1826         ret = EIO;
 1827         goto done;
 1828     }
 1829 
 1830     names = talloc_zero_array(tmp_ctx, char *, res->count + 1);
 1831     if (names == NULL) {
 1832         ret = ENOMEM;
 1833         goto done;
 1834     }
 1835 
 1836     for (num = 0, i = 0; i < res->count; i++) {
 1837         const struct ldb_val *val;
 1838         char *name;
 1839         int n;
 1840         int j;
 1841 
 1842         n = ldb_dn_get_comp_num(res->msgs[i]->dn);
 1843         if (n == base_comp_num) continue;
 1844 
 1845         name = NULL;
 1846         for (j = n - base_comp_num - 1; j >= 0; j--) {
 1847             val = ldb_dn_get_component_val(res->msgs[i]->dn, j);
 1848             if (name == NULL) {
 1849                 name = talloc_strndup(names,
 1850                                       (const char *)val->data, val->length);
 1851             } else {
 1852                 name = talloc_asprintf(names, "%s/%.*s", name,
 1853                                        (int)val->length,
 1854                                        (const char *)val->data);
 1855             }
 1856             if (name == NULL) {
 1857                 ret = ENOMEM;
 1858                 goto done;
 1859             }
 1860         }
 1861 
 1862         names[num] = name;
 1863         if (names[num] == NULL) {
 1864             ret = ENOMEM;
 1865             goto done;
 1866         }
 1867 
 1868         num++;
 1869     }
 1870 
 1871     *sections = talloc_steal(mem_ctx, names);
 1872     *num_sections = num;
 1873     ret = EOK;
 1874 
 1875 done:
 1876     talloc_free(tmp_ctx);
 1877     return ret;
 1878 }
 1879 
 1880 static bool need_implicit_files_domain(TALLOC_CTX *tmp_ctx,
 1881                                        struct confdb_ctx *cdb,
 1882                                        struct ldb_result *doms)
 1883 {
 1884     const char *id_provider = NULL;
 1885     unsigned int i;
 1886     errno_t ret;
 1887     char **domlist;
 1888     const char *val;
 1889 
 1890     ret = confdb_get_string_as_list(cdb, tmp_ctx,
 1891                                     CONFDB_MONITOR_CONF_ENTRY,
 1892                                     CONFDB_MONITOR_ACTIVE_DOMAINS,
 1893                                     &domlist);
 1894     if (ret == ENOENT) {
 1895         return true;
 1896     } else if (ret != EOK) {
 1897         DEBUG(SSSDBG_CRIT_FAILURE,
 1898               "Cannot get active domains %d[%s]\n",
 1899               ret, sss_strerror(ret));
 1900         return false;
 1901     }
 1902 
 1903     for (i = 0; i < doms->count; i++) {
 1904         val = ldb_msg_find_attr_as_string(doms->msgs[i], CONFDB_DOMAIN_ATTR,
 1905                                           NULL);
 1906         if (val == NULL) {
 1907             DEBUG(SSSDBG_CRIT_FAILURE,
 1908                   "The object [%s] doesn't have a name\n",
 1909                   ldb_dn_get_linearized(doms->msgs[i]->dn));
 1910             continue;
 1911         }
 1912 
 1913         /* skip disabled domain */
 1914         if (!string_in_list(val, domlist, false)) {
 1915             continue;
 1916         }
 1917 
 1918         id_provider = ldb_msg_find_attr_as_string(doms->msgs[i],
 1919                                                   CONFDB_DOMAIN_ID_PROVIDER,
 1920                                                   NULL);
 1921         if (id_provider == NULL) {
 1922             DEBUG(SSSDBG_OP_FAILURE,
 1923                   "The object [%s] doesn't have an id_provider\n",
 1924                   ldb_dn_get_linearized(doms->msgs[i]->dn));
 1925             continue;
 1926         }
 1927 
 1928         if (strcasecmp(id_provider, "files") == 0) {
 1929             return false;
 1930         }
 1931 
 1932         if (strcasecmp(id_provider, "proxy") == 0) {
 1933             val = ldb_msg_find_attr_as_string(doms->msgs[i],
 1934                                               CONFDB_PROXY_LIBNAME, NULL);
 1935             if (val == NULL) {
 1936                 DEBUG(SSSDBG_OP_FAILURE,
 1937                       "The object [%s] doesn't have proxy_lib_name with "
 1938                       "id_provider proxy\n",
 1939                       ldb_dn_get_linearized(doms->msgs[i]->dn));
 1940                 continue;
 1941             }
 1942 
 1943             /* id_provider = proxy + proxy_lib_name = files are equivalent
 1944              * to id_provider = files
 1945              */
 1946             if (strcmp(val, "files") == 0) {
 1947                 return false;
 1948             }
 1949         }
 1950     }
 1951 
 1952     return true;
 1953 }
 1954 
 1955 static int confdb_has_files_domain(struct confdb_ctx *cdb)
 1956 {
 1957     TALLOC_CTX *tmp_ctx = NULL;
 1958     struct ldb_dn *dn = NULL;
 1959     struct ldb_result *res = NULL;
 1960     static const char *attrs[] = { CONFDB_DOMAIN_ID_PROVIDER,
 1961                                    CONFDB_DOMAIN_ATTR,
 1962                                    CONFDB_PROXY_LIBNAME, NULL };
 1963     int ret;
 1964     bool need_files_dom;
 1965 
 1966     tmp_ctx = talloc_new(NULL);
 1967     if (tmp_ctx == NULL) {
 1968         return ENOMEM;
 1969     }
 1970 
 1971     dn = ldb_dn_new(tmp_ctx, cdb->ldb, CONFDB_DOMAIN_BASEDN);
 1972     if (dn == NULL) {
 1973         ret = ENOMEM;
 1974         goto done;
 1975     }
 1976 
 1977     ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
 1978                      attrs, NULL);
 1979     if (ret != LDB_SUCCESS) {
 1980         ret = EIO;
 1981         goto done;
 1982     }
 1983 
 1984     need_files_dom = need_implicit_files_domain(tmp_ctx, cdb, res);
 1985 
 1986     ret = need_files_dom ? ENOENT : EOK;
 1987 done:
 1988     talloc_free(tmp_ctx);
 1989     return ret;
 1990 }
 1991 
 1992 static int create_files_domain(struct confdb_ctx *cdb,
 1993                                const char *name)
 1994 {
 1995     TALLOC_CTX *tmp_ctx = NULL;
 1996     errno_t ret;
 1997     char *cdb_path = NULL;
 1998     const char *val[2] = { NULL, NULL };
 1999 
 2000     tmp_ctx = talloc_new(NULL);
 2001     if (tmp_ctx == NULL) {
 2002         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
 2003         return ENOMEM;
 2004     }
 2005 
 2006     cdb_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
 2007     if (cdb_path == NULL) {
 2008         ret = ENOMEM;
 2009         goto done;
 2010     }
 2011 
 2012     val[0] = "files";
 2013     ret = confdb_add_param(cdb, true, cdb_path, "id_provider", val);
 2014     if (ret != EOK) {
 2015         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n",
 2016               ret, sss_strerror(ret));
 2017         goto done;
 2018     }
 2019 
 2020     ret = EOK;
 2021 done:
 2022     talloc_free(tmp_ctx);
 2023     return ret;
 2024 }
 2025 
 2026 static int activate_files_domain(struct confdb_ctx *cdb,
 2027                                  const char *name)
 2028 {
 2029     errno_t ret;
 2030     TALLOC_CTX *tmp_ctx;
 2031     char *monitor_domlist;
 2032     const char *domlist[2] = { NULL, NULL };
 2033 
 2034     tmp_ctx = talloc_new(NULL);
 2035     if (tmp_ctx == NULL) {
 2036         return ENOMEM;
 2037     }
 2038 
 2039     ret = confdb_get_string(cdb, tmp_ctx,
 2040                             CONFDB_MONITOR_CONF_ENTRY,
 2041                             CONFDB_MONITOR_ACTIVE_DOMAINS,
 2042                             NULL,
 2043                             &monitor_domlist);
 2044     if (ret != EOK) {
 2045         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
 2046         goto done;
 2047     }
 2048 
 2049     if (monitor_domlist != NULL) {
 2050         domlist[0] = talloc_asprintf(tmp_ctx, "%s,%s", name, monitor_domlist);
 2051         if (domlist[0] == NULL) {
 2052             ret = ENOMEM;
 2053             goto done;
 2054         }
 2055     } else {
 2056         domlist[0] = name;
 2057     }
 2058 
 2059     ret = confdb_add_param(cdb, true,
 2060                            CONFDB_MONITOR_CONF_ENTRY,
 2061                            CONFDB_MONITOR_ACTIVE_DOMAINS,
 2062                            domlist);
 2063     if (ret != EOK) {
 2064         DEBUG(SSSDBG_CRIT_FAILURE,
 2065               "Cannot extend the domain list [%d]: %s\n",
 2066               ret, sss_strerror(ret));
 2067         return ret;
 2068     }
 2069 
 2070     ret = EOK;
 2071 done:
 2072     talloc_free(tmp_ctx);
 2073     return ret;
 2074 }
 2075 
 2076 static int confdb_ensure_files_domain(struct confdb_ctx *cdb,
 2077                                       const char *implicit_files_dom_name)
 2078 {
 2079 #ifdef ADD_FILES_DOMAIN
 2080     const bool default_enable_files = true;
 2081 #else
 2082     const bool default_enable_files = false;
 2083 #endif
 2084     errno_t ret;
 2085     bool enable_files;
 2086 
 2087     ret = confdb_get_bool(cdb,
 2088                           CONFDB_MONITOR_CONF_ENTRY,
 2089                           CONFDB_MONITOR_ENABLE_FILES_DOM,
 2090                           default_enable_files, &enable_files);
 2091     if (ret != EOK) {
 2092         DEBUG(SSSDBG_MINOR_FAILURE,
 2093               "Cannot get the value of %s assuming %s\n",
 2094               CONFDB_MONITOR_ENABLE_FILES_DOM,
 2095               default_enable_files ? "true" : "false");
 2096         return ret;
 2097     }
 2098 
 2099     if (enable_files == false) {
 2100         DEBUG(SSSDBG_CONF_SETTINGS, "The implicit files domain is disabled\n");
 2101         return EOK;
 2102     }
 2103 
 2104     ret = confdb_has_files_domain(cdb);
 2105     if (ret == EOK) {
 2106         DEBUG(SSSDBG_CONF_SETTINGS, "The files domain is already enabled\n");
 2107         return EOK;
 2108     } else if (ret != ENOENT) {
 2109         DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up the files domain\n");
 2110         return ret;
 2111     }
 2112 
 2113     /* ENOENT, so let's add a files domain */
 2114     ret = create_files_domain(cdb, implicit_files_dom_name);
 2115     if (ret != EOK) {
 2116         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add an implicit files domain\n");
 2117         return ret;
 2118     }
 2119 
 2120     return activate_files_domain(cdb, implicit_files_dom_name);
 2121 }
 2122 
 2123 static int confdb_get_parent_domain(TALLOC_CTX *mem_ctx,
 2124                                     const char *name,
 2125                                     struct confdb_ctx *cdb,
 2126                                     struct ldb_result *app_dom,
 2127                                     struct ldb_result **_parent_dom)
 2128 {
 2129     const char *inherit_from;
 2130 
 2131     inherit_from = ldb_msg_find_attr_as_string(app_dom->msgs[0],
 2132                                                CONFDB_DOMAIN_INHERIT_FROM, NULL);
 2133     if (inherit_from == NULL) {
 2134         DEBUG(SSSDBG_CONF_SETTINGS,
 2135               "%s does not inherit from any POSIX domain\n", name);
 2136         *_parent_dom = NULL;
 2137         return EOK;
 2138     }
 2139 
 2140     return confdb_get_domain_section(mem_ctx, cdb,
 2141                                      CONFDB_DOMAIN_BASEDN, inherit_from,
 2142                                      _parent_dom);
 2143 }
 2144 
 2145 static int confdb_add_app_domain(TALLOC_CTX *mem_ctx,
 2146                                  struct confdb_ctx *cdb,
 2147                                  const char *name)
 2148 {
 2149     char *cdb_path = NULL;
 2150     const char *val[2] = { NULL, NULL };
 2151     int ret;
 2152 
 2153     cdb_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
 2154     if (cdb_path == NULL) {
 2155         return ENOMEM;
 2156     }
 2157 
 2158     val[0] = CONFDB_DOMAIN_TYPE_APP;
 2159     ret = confdb_add_param(cdb, true, cdb_path, CONFDB_DOMAIN_TYPE, val);
 2160     if (ret != EOK) {
 2161         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n",
 2162               ret, sss_strerror(ret));
 2163         return ret;
 2164     }
 2165 
 2166     return EOK;
 2167 }
 2168 
 2169 static int confdb_merge_parent_domain(const char *name,
 2170                                       struct confdb_ctx *cdb,
 2171                                       struct ldb_result *app_section)
 2172 {
 2173     int ret;
 2174     int ldb_flag;
 2175     struct ldb_result *parent_domain = NULL;
 2176     struct ldb_message *replace_msg = NULL;
 2177     struct ldb_message *app_msg = NULL;
 2178     struct ldb_dn *domain_dn;
 2179     struct ldb_message_element *el = NULL;
 2180     TALLOC_CTX *tmp_ctx = NULL;
 2181 
 2182     tmp_ctx = talloc_new(NULL);
 2183     if (tmp_ctx == NULL) {
 2184         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
 2185         return ENOMEM;
 2186     }
 2187 
 2188     domain_dn = ldb_dn_new_fmt(tmp_ctx,
 2189                                cdb->ldb,
 2190                                "%s=%s,%s",
 2191                                CONFDB_DOMAIN_ATTR,
 2192                                name,
 2193                                CONFDB_DOMAIN_BASEDN);
 2194     if (domain_dn == NULL) {
 2195         ret = ENOMEM;
 2196         goto done;
 2197     }
 2198 
 2199     /* Copy the parent domain parameters */
 2200     ret = confdb_get_parent_domain(tmp_ctx, name, cdb,
 2201                                    app_section, &parent_domain);
 2202     if (ret != EOK) {
 2203         DEBUG(SSSDBG_OP_FAILURE,
 2204               "Cannot retrieve the parent domain [%d]: %s\n",
 2205               ret, sss_strerror(ret));
 2206         goto done;
 2207     }
 2208 
 2209     if (parent_domain != NULL) {
 2210         replace_msg = ldb_msg_copy(tmp_ctx, parent_domain->msgs[0]);
 2211         if (replace_msg == NULL) {
 2212             ret = ENOMEM;
 2213             goto done;
 2214         }
 2215         replace_msg->dn = domain_dn;
 2216 
 2217         for (unsigned i = 0; i < replace_msg->num_elements; i++) {
 2218             replace_msg->elements[i].flags = LDB_FLAG_MOD_ADD;
 2219         }
 2220 
 2221         el = ldb_msg_find_element(replace_msg, "cn");
 2222         if (el != NULL) {
 2223             /* Don't add second cn */
 2224             ldb_msg_remove_element(replace_msg, el);
 2225         }
 2226 
 2227         ret = ldb_modify(cdb->ldb, replace_msg);
 2228         if (ret != LDB_SUCCESS) {
 2229             ret = sss_ldb_error_to_errno(ret);
 2230             DEBUG(SSSDBG_OP_FAILURE,
 2231                 "Inheriting options from parent domain failed [%d]: %s\n",
 2232                 ret, sss_strerror(ret));
 2233             goto done;
 2234         }
 2235     }
 2236 
 2237     /* Finally, add any app-domain specific overrides */
 2238     app_msg = ldb_msg_new(tmp_ctx);
 2239     if (app_msg == NULL) {
 2240         ret = ENOMEM;
 2241         goto done;
 2242     }
 2243     app_msg->dn = domain_dn;
 2244 
 2245     for (unsigned i = 0; i < app_section->msgs[0]->num_elements; i++) {
 2246         struct ldb_message_element *app_el = &app_section->msgs[0]->elements[i];
 2247 
 2248         /* These elements will be skipped when replacing attributes in
 2249          * a domain to avoid EEXIST errors
 2250          */
 2251         if (strcasecmp(app_el->name, "cn") == 0) {
 2252             continue;
 2253         }
 2254 
 2255         if (replace_msg != NULL) {
 2256             el = ldb_msg_find_element(replace_msg,
 2257                                       app_section->msgs[0]->elements[i].name);
 2258             if (el == NULL) {
 2259                 /* Adding an element */
 2260                 ldb_flag = LDB_FLAG_MOD_ADD;
 2261             } else {
 2262                 /* Overriding an element */
 2263                 ldb_flag = LDB_FLAG_MOD_REPLACE;
 2264             }
 2265         } else {
 2266             /* If there was no domain to inherit from, just add all */
 2267             ldb_flag = LDB_FLAG_MOD_ADD;
 2268         }
 2269 
 2270         ret = ldb_msg_add(app_msg,
 2271                           &app_section->msgs[0]->elements[i],
 2272                           ldb_flag);
 2273         if (ret != LDB_SUCCESS) {
 2274             continue;
 2275         }
 2276     }
 2277 
 2278     /* We use permissive modification here because adding cn or
 2279      * distinguishedName from the app_section to the application
 2280      * message would throw EEXIST
 2281      */
 2282     ret = sss_ldb_modify_permissive(cdb->ldb, app_msg);
 2283     if (ret != LDB_SUCCESS) {
 2284         ret = sss_ldb_error_to_errno(ret);
 2285         DEBUG(SSSDBG_OP_FAILURE,
 2286               "Adding app-specific options failed [%d]: %s\n",
 2287               ret, sss_strerror(ret));
 2288         goto done;
 2289     }
 2290 
 2291     DEBUG(SSSDBG_TRACE_LIBS, "Added a domain section for %s\n", name);
 2292     ret = EOK;
 2293 done:
 2294     talloc_free(tmp_ctx);
 2295     return ret;
 2296 }
 2297 
 2298 int confdb_expand_app_domains(struct confdb_ctx *cdb)
 2299 {
 2300     int ret;
 2301     char **domlist;
 2302     TALLOC_CTX *tmp_ctx;
 2303     struct ldb_result *app_domain = NULL;
 2304 
 2305     tmp_ctx = talloc_new(NULL);
 2306     if (tmp_ctx == NULL) {
 2307         return ENOMEM;
 2308     }
 2309 
 2310     ret = confdb_ensure_files_domain(cdb, IMPLICIT_FILES_DOMAIN_NAME);
 2311     if (ret != EOK) {
 2312         DEBUG(SSSDBG_MINOR_FAILURE,
 2313               "Cannot add the implicit files domain [%d]: %s\n",
 2314               ret, strerror(ret));
 2315         /* Not fatal */
 2316     }
 2317 
 2318     ret = confdb_get_string_as_list(cdb, tmp_ctx,
 2319                                     CONFDB_MONITOR_CONF_ENTRY,
 2320                                     CONFDB_MONITOR_ACTIVE_DOMAINS,
 2321                                     &domlist);
 2322     if (ret == ENOENT) {
 2323         DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured, fatal error!\n");
 2324         goto done;
 2325     } else if (ret != EOK ) {
 2326         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n");
 2327         goto done;
 2328     }
 2329 
 2330     for (int i = 0; domlist[i]; i++) {
 2331         ret = confdb_get_domain_section(tmp_ctx, cdb,
 2332                                         CONFDB_APP_DOMAIN_BASEDN, domlist[i],
 2333                                         &app_domain);
 2334         if (ret == ENOENT) {
 2335             DEBUG(SSSDBG_TRACE_INTERNAL,
 2336                   "%s is not an app domain\n", domlist[i]);
 2337             continue;
 2338         } else if (ret != EOK) {
 2339             DEBUG(SSSDBG_FATAL_FAILURE,
 2340                   "Error %d: %s while retrieving %s\n",
 2341                   ret, sss_strerror(ret), domlist[i]);
 2342             goto done;
 2343         }
 2344 
 2345         ret = confdb_add_app_domain(tmp_ctx, cdb, domlist[i]);
 2346         if (ret != EOK) {
 2347             DEBUG(SSSDBG_OP_FAILURE,
 2348                   "Cannot add the app domain section [%d]: %s\n",
 2349                   ret, sss_strerror(ret));
 2350             goto done;
 2351         }
 2352 
 2353         ret = confdb_merge_parent_domain(domlist[i], cdb, app_domain);
 2354         if (ret != EOK) {
 2355             DEBUG(SSSDBG_OP_FAILURE,
 2356                   "Cannot add options into the app domain section [%d]: %s\n",
 2357                   ret, sss_strerror(ret));
 2358             goto done;
 2359         }
 2360     }
 2361 
 2362     ret = EOK;
 2363 done:
 2364     talloc_free(tmp_ctx);
 2365     return ret;
 2366 }
 2367 
 2368 static errno_t certmap_local_check(struct ldb_message *msg)
 2369 {
 2370     const char *rule_name;
 2371     const char *tmp_str;
 2372     int ret;
 2373 
 2374     rule_name = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_NAME, NULL);
 2375     if (rule_name == NULL) {
 2376         DEBUG(SSSDBG_CRIT_FAILURE, "Certificate mapping rule [%s] has no name.",
 2377                                    ldb_dn_get_linearized(msg->dn));
 2378         return EINVAL;
 2379     }
 2380 
 2381     tmp_str = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_DOMAINS, NULL);
 2382     if (tmp_str != NULL) {
 2383         DEBUG(SSSDBG_CONF_SETTINGS,
 2384               "Option [%s] is ignored for local certmap rules.\n",
 2385               CONFDB_CERTMAP_DOMAINS);
 2386     }
 2387 
 2388     tmp_str = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_MAPRULE, NULL);
 2389     if (tmp_str != NULL) {
 2390         if (tmp_str[0] != '(' || tmp_str[strlen(tmp_str) - 1] != ')') {
 2391             DEBUG(SSSDBG_CONF_SETTINGS,
 2392                   "Mapping rule must be in braces (...).\n");
 2393             return EINVAL;
 2394         }
 2395         DEBUG(SSSDBG_TRACE_ALL, "Using [%s] mapping rule of [%s].\n",
 2396                                 tmp_str, ldb_dn_get_linearized(msg->dn));
 2397         return EOK;
 2398     }
 2399 
 2400     tmp_str = talloc_asprintf(msg, "(%s)", rule_name);
 2401     if (tmp_str == NULL) {
 2402         DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
 2403         return ENOMEM;
 2404     }
 2405     ret = ldb_msg_add_string(msg, CONFDB_CERTMAP_MAPRULE, tmp_str);
 2406     if (ret != LDB_SUCCESS) {
 2407         talloc_free(discard_const(tmp_str));
 2408         DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
 2409         return EIO;
 2410     }
 2411 
 2412     DEBUG(SSSDBG_TRACE_ALL, "Using [%s] as mapping rule for [%s].\n",
 2413                             tmp_str, ldb_dn_get_linearized(msg->dn));
 2414 
 2415     return EOK;
 2416 }
 2417 
 2418 static errno_t confdb_get_all_certmaps(TALLOC_CTX *mem_ctx,
 2419                                        struct confdb_ctx *cdb,
 2420                                        struct sss_domain_info *dom,
 2421                                        struct certmap_info ***_certmap_list)
 2422 {
 2423     TALLOC_CTX *tmp_ctx = NULL;
 2424     struct ldb_dn *dn = NULL;
 2425     struct ldb_result *res = NULL;
 2426     /* The attribute order is important, because it is used in
 2427      * sysdb_ldb_msg_attr_to_certmap_info and must match
 2428      * enum certmap_info_member. */
 2429     static const char *attrs[] = { CONFDB_CERTMAP_NAME,
 2430                                    CONFDB_CERTMAP_MAPRULE,
 2431                                    CONFDB_CERTMAP_MATCHRULE,
 2432                                    CONFDB_CERTMAP_PRIORITY,
 2433                                    CONFDB_CERTMAP_DOMAINS,
 2434                                    NULL};
 2435     struct certmap_info **certmap_list = NULL;
 2436     size_t c;
 2437     int ret;
 2438 
 2439     tmp_ctx = talloc_new(NULL);
 2440     if (tmp_ctx == NULL) {
 2441         return ENOMEM;
 2442     }
 2443 
 2444     dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", dom->name,
 2445                                                        CONFDB_CERTMAP_BASEDN);
 2446     if (dn == NULL) {
 2447         ret = ENOMEM;
 2448         goto done;
 2449     }
 2450 
 2451     ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL,
 2452                      attrs, NULL);
 2453     if (ret != LDB_SUCCESS) {
 2454         ret = EIO;
 2455         goto done;
 2456     }
 2457 
 2458     certmap_list = talloc_zero_array(tmp_ctx, struct certmap_info *,
 2459                                      res->count + 1);
 2460     if (certmap_list == NULL) {
 2461         ret = ENOMEM;
 2462         goto done;
 2463     }
 2464 
 2465     for (c = 0; c < res->count; c++) {
 2466         if (is_files_provider(dom)) {
 2467             ret = certmap_local_check(res->msgs[c]);
 2468             if (ret != EOK) {
 2469                 DEBUG(SSSDBG_CONF_SETTINGS,
 2470                       "Invalid certificate mapping [%s] for local user, "
 2471                       "ignored.\n", ldb_dn_get_linearized(res->msgs[c]->dn));
 2472                 continue;
 2473             }
 2474         }
 2475         ret = sysdb_ldb_msg_attr_to_certmap_info(certmap_list, res->msgs[c],
 2476                                                  attrs, &certmap_list[c]);
 2477         if (ret != EOK) {
 2478             DEBUG(SSSDBG_OP_FAILURE,
 2479                   "sysdb_ldb_msg_attr_to_certmap_info failed.\n");
 2480             goto done;
 2481         }
 2482     }
 2483 
 2484     *_certmap_list = talloc_steal(mem_ctx, certmap_list);
 2485 
 2486     ret = EOK;
 2487 
 2488 done:
 2489     talloc_free(tmp_ctx);
 2490     return ret;
 2491 }
 2492 
 2493 int confdb_certmap_to_sysdb(struct confdb_ctx *cdb,
 2494                             struct sss_domain_info *dom)
 2495 {
 2496     int ret;
 2497     TALLOC_CTX *tmp_ctx;
 2498     struct certmap_info **certmap_list;
 2499 
 2500     tmp_ctx = talloc_new(NULL);
 2501     if (tmp_ctx == NULL) {
 2502         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
 2503         return ENOMEM;
 2504     }
 2505 
 2506     ret = confdb_get_all_certmaps(tmp_ctx, cdb, dom, &certmap_list);
 2507     if (ret != EOK) {
 2508         DEBUG(SSSDBG_OP_FAILURE, "confdb_get_all_certmaps failed.\n");
 2509         goto done;
 2510     }
 2511 
 2512     ret = sysdb_update_certmap(dom->sysdb, certmap_list, false /* TODO */);
 2513     if (ret != EOK) {
 2514         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed.\n");
 2515         goto done;
 2516     }
 2517 
 2518     ret = EOK;
 2519 
 2520 done:
 2521     talloc_free(tmp_ctx);
 2522 
 2523     return ret;
 2524 }
 2525 
 2526 /**
 2527  * Retrieve the list of enabled domains considering the explicit list
 2528  * and the 'enabled' attribute.
 2529  * @param cdb The database configuration context.
 2530  * @param ctx The memory context.
 2531  * @param result Output variable where the list of domains will be stored.
 2532  * @return 0 if the list was retrieved properly, another value on error.
 2533  */
 2534 static int confdb_get_enabled_domain_list(struct confdb_ctx *cdb,
 2535                                           TALLOC_CTX *ctx, char ***_result)
 2536 {
 2537     int ret;
 2538     char **domlist = NULL;
 2539     char **all_domains = NULL;
 2540     bool enabled = false;
 2541 
 2542     TALLOC_CTX *tmp_ctx = NULL;
 2543 
 2544     tmp_ctx = talloc_new(NULL);
 2545     ret = confdb_get_string_as_list(cdb, tmp_ctx,
 2546                                     CONFDB_MONITOR_CONF_ENTRY,
 2547                                     CONFDB_MONITOR_ACTIVE_DOMAINS,
 2548                                     &domlist);
 2549     if (ret != EOK) {
 2550         DEBUG(SSSDBG_OP_FAILURE,
 2551               "Failed to get [%s] from [%s], error [%d] (%s)\n",
 2552               CONFDB_MONITOR_ACTIVE_DOMAINS, "sssd",
 2553               ret, strerror(ret));
 2554         goto done;
 2555     }
 2556 
 2557     ret = confdb_list_all_domain_names(tmp_ctx, cdb, &all_domains);
 2558     if (ret != EOK) {
 2559         DEBUG(SSSDBG_OP_FAILURE,
 2560               "Failed retrieving all domain name "
 2561               "list, error [%d], description '%s'\n",
 2562               ret, strerror(ret));
 2563         goto done;
 2564     }
 2565 
 2566     for (int idx = 0; all_domains[idx]; idx++) {
 2567         ret = confdb_get_domain_enabled(cdb, all_domains[idx], &enabled);
 2568         if (ret != EOK && ret != ENOENT) {
 2569             DEBUG(SSSDBG_OP_FAILURE,
 2570                   "Failed retrieving 'enabled' attribute from '%s' domain; "
 2571                   "error [%d], description '%s'\n",
 2572                   all_domains[idx],
 2573                   ret, strerror(ret));
 2574             goto done;
 2575         }
 2576 
 2577         if (ret == ENOENT) continue;
 2578 
 2579         if (enabled && !string_in_list(all_domains[idx], domlist, false)) {
 2580             ret = add_string_to_list(tmp_ctx, all_domains[idx], &domlist);
 2581             if (ret != EOK) {
 2582                 DEBUG(SSSDBG_OP_FAILURE,
 2583                     "Failed adding '%s' domain to domain list; "
 2584                     "error [%d], description '%s'\n",
 2585                     all_domains[idx],
 2586                     ret, strerror(ret));
 2587                 goto done;
 2588             }
 2589         }
 2590 
 2591         if (!enabled && string_in_list(all_domains[idx], domlist, false)) {
 2592             ret = del_string_from_list(all_domains[idx], &domlist, false);
 2593             if (ret != EOK) {
 2594                 DEBUG(SSSDBG_OP_FAILURE,
 2595                     "Failed deleting '%s' domain from domain list; "
 2596                     "error [%d], description '%s'\n",
 2597                     all_domains[idx],
 2598                     ret, strerror(ret));
 2599                 goto done;
 2600             }
 2601         }
 2602     }
 2603 
 2604     ret = EOK;
 2605     talloc_steal(ctx, domlist);
 2606     *_result = domlist;
 2607 
 2608 done:
 2609     talloc_free(tmp_ctx);
 2610     return ret;
 2611 }
 2612 
 2613 
 2614 /**
 2615  * Retrieve the enabled attribute for a specific domain.
 2616  * @param cdb The database configuration context.
 2617  * @param domain The domain name.
 2618  * @param enabled The output variable; it can not be NULL; if the
 2619  * domain is explicitely enabled, *enabled is equal to 1; if the
 2620  * domain is explicitely disabled, *enabled is equal to 0.
 2621  * @param Return EOK if the operation happened properly and *enabled
 2622  * contain the value of the attribute; if no entry found for enabled
 2623  * attribute it returns ENOENT, else an error code.
 2624  */
 2625 static int confdb_get_domain_enabled(struct confdb_ctx *cdb,
 2626                                      const char *domain, bool *_enabled)
 2627 {
 2628     TALLOC_CTX *tmp_ctx = NULL;
 2629     char *section = NULL;
 2630     char **values = NULL;
 2631     int ret = EINVAL;
 2632 
 2633     section = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, domain);
 2634     values = NULL;
 2635     ret = confdb_get_param(cdb, tmp_ctx, section, CONFDB_DOMAIN_ENABLED, &values);
 2636     if (ret != EOK && ret != ENOENT) {
 2637         DEBUG(SSSDBG_OP_FAILURE,
 2638               "Failed retrieving '%s' attribute in '%s' section; "
 2639               "error [%d], description '%s'\n",
 2640               CONFDB_DOMAIN_ENABLED, section,
 2641               ret, strerror(ret));
 2642         goto done;
 2643     }
 2644 
 2645     /* Check return and output value */
 2646     if (ret == ENOENT || !values || !values[0]) {
 2647         ret = ENOENT;
 2648         goto done;
 2649     }
 2650     if (values[1]) {
 2651         /* More than one value it's an invalid configuration file */
 2652         ret = EINVAL;
 2653         goto done;
 2654     }
 2655     if (0 == strcasecmp(values[0], "true")) {
 2656         ret = EOK;
 2657         *_enabled = true;
 2658         goto done;
 2659     }
 2660     if (0 == strcasecmp(values[0], "false")) {
 2661         ret = EOK;
 2662         *_enabled = false;
 2663         goto done;
 2664     }
 2665     /* Failed to parse value */
 2666     ret = EINVAL;
 2667 done:
 2668     talloc_free(tmp_ctx);
 2669     return ret;
 2670 }