LCOV - code coverage report
Current view: top level - confdb - confdb.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 389 722 53.9 %
Date: 2015-10-19 Functions: 17 19 89.5 %

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

Generated by: LCOV version 1.10