LCOV - code coverage report
Current view: top level - db - sysdb.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 439 903 48.6 %
Date: 2015-10-19 Functions: 51 65 78.5 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    System Database
       5             : 
       6             :    Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com>
       7             :    Copyright (C) 2008-2011 Stephen Gallagher <ssorce@redhat.com>
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "util/util.h"
      24             : #include "util/strtonum.h"
      25             : #include "util/sss_utf8.h"
      26             : #include "db/sysdb_private.h"
      27             : #include "confdb/confdb.h"
      28             : #include <time.h>
      29             : 
      30             : #define LDB_MODULES_PATH "LDB_MODULES_PATH"
      31             : 
      32        1197 : errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename,
      33             :                           struct ldb_context **_ldb)
      34             : {
      35             :     int ret;
      36             :     struct ldb_context *ldb;
      37             :     const char *mod_path;
      38             : 
      39        1197 :     if (_ldb == NULL) {
      40           0 :         return EINVAL;
      41             :     }
      42             : 
      43        1197 :     ldb = ldb_init(mem_ctx, NULL);
      44        1197 :     if (!ldb) {
      45           0 :         return EIO;
      46             :     }
      47             : 
      48        1197 :     ret = ldb_set_debug(ldb, ldb_debug_messages, NULL);
      49        1197 :     if (ret != LDB_SUCCESS) {
      50           0 :         return EIO;
      51             :     }
      52             : 
      53        1197 :     mod_path = getenv(LDB_MODULES_PATH);
      54        1197 :     if (mod_path != NULL) {
      55        1197 :         DEBUG(SSSDBG_TRACE_ALL, "Setting ldb module path to [%s].\n", mod_path);
      56        1197 :         ldb_set_modules_dir(ldb, mod_path);
      57             :     }
      58             : 
      59        1197 :     ret = ldb_connect(ldb, filename, 0, NULL);
      60        1197 :     if (ret != LDB_SUCCESS) {
      61           0 :         return EIO;
      62             :     }
      63             : 
      64        1197 :     *_ldb = ldb;
      65             : 
      66        1197 :     return EOK;
      67             : }
      68             : 
      69        1675 : errno_t sysdb_dn_sanitize(TALLOC_CTX *mem_ctx, const char *input,
      70             :                           char **sanitized)
      71             : {
      72             :     struct ldb_val val;
      73        1675 :     errno_t ret = EOK;
      74             : 
      75        1675 :     val.data = (uint8_t *)talloc_strdup(mem_ctx, input);
      76        1675 :     if (!val.data) {
      77           0 :         return ENOMEM;
      78             :     }
      79             : 
      80             :     /* We can't include the trailing NULL because it would
      81             :      * be escaped and result in an unterminated string
      82             :      */
      83        1675 :     val.length = strlen(input);
      84             : 
      85        1675 :     *sanitized = ldb_dn_escape_value(mem_ctx, val);
      86        1675 :     if (!*sanitized) {
      87           0 :         ret = ENOMEM;
      88             :     }
      89             : 
      90        1675 :     talloc_free(val.data);
      91        1675 :     return ret;
      92             : }
      93             : 
      94          25 : struct ldb_dn *sysdb_custom_subtree_dn(TALLOC_CTX *mem_ctx,
      95             :                                        struct sss_domain_info *dom,
      96             :                                        const char *subtree_name)
      97             : {
      98             :     errno_t ret;
      99             :     char *clean_subtree;
     100          25 :     struct ldb_dn *dn = NULL;
     101             :     TALLOC_CTX *tmp_ctx;
     102             : 
     103          25 :     tmp_ctx = talloc_new(NULL);
     104          25 :     if (!tmp_ctx) return NULL;
     105             : 
     106          25 :     ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
     107          25 :     if (ret != EOK) {
     108           0 :         talloc_free(tmp_ctx);
     109           0 :         return NULL;
     110             :     }
     111             : 
     112          25 :     dn = ldb_dn_new_fmt(tmp_ctx, dom->sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
     113             :                         clean_subtree, dom->name);
     114          25 :     if (dn) {
     115          25 :         talloc_steal(mem_ctx, dn);
     116             :     }
     117          25 :     talloc_free(tmp_ctx);
     118             : 
     119          25 :     return dn;
     120             : }
     121             : 
     122          72 : struct ldb_dn *sysdb_custom_dn(TALLOC_CTX *mem_ctx,
     123             :                                struct sss_domain_info *dom,
     124             :                                const char *object_name,
     125             :                                const char *subtree_name)
     126             : {
     127             :     errno_t ret;
     128             :     TALLOC_CTX *tmp_ctx;
     129             :     char *clean_name;
     130             :     char *clean_subtree;
     131          72 :     struct ldb_dn *dn = NULL;
     132             : 
     133          72 :     tmp_ctx = talloc_new(NULL);
     134          72 :     if (!tmp_ctx) {
     135           0 :         return NULL;
     136             :     }
     137             : 
     138          72 :     ret = sysdb_dn_sanitize(tmp_ctx, object_name, &clean_name);
     139          72 :     if (ret != EOK) {
     140           0 :         goto done;
     141             :     }
     142             : 
     143          72 :     ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
     144          72 :     if (ret != EOK) {
     145           0 :         goto done;
     146             :     }
     147             : 
     148          72 :     dn = ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb, SYSDB_TMPL_CUSTOM, clean_name,
     149             :                         clean_subtree, dom->name);
     150             : 
     151             : done:
     152          72 :     talloc_free(tmp_ctx);
     153          72 :     return dn;
     154             : }
     155             : 
     156         719 : struct ldb_dn *sysdb_user_dn(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
     157             :                              const char *name)
     158             : {
     159             :     errno_t ret;
     160             :     char *clean_name;
     161             :     struct ldb_dn *dn;
     162             : 
     163         719 :     ret = sysdb_dn_sanitize(NULL, name, &clean_name);
     164         719 :     if (ret != EOK) {
     165           0 :         return NULL;
     166             :     }
     167             : 
     168         719 :     dn = ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb, SYSDB_TMPL_USER,
     169             :                         clean_name, dom->name);
     170         719 :     talloc_free(clean_name);
     171             : 
     172         719 :     return dn;
     173             : }
     174             : 
     175         468 : struct ldb_dn *sysdb_user_base_dn(TALLOC_CTX *mem_ctx,
     176             :                                   struct sss_domain_info *dom)
     177             : {
     178         468 :     return ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb,
     179             :                           SYSDB_TMPL_USER_BASE, dom->name);
     180             : }
     181             : 
     182         503 : struct ldb_dn *sysdb_group_dn(TALLOC_CTX *mem_ctx,
     183             :                               struct sss_domain_info *dom, const char *name)
     184             : {
     185             :     errno_t ret;
     186             :     char *clean_name;
     187             :     struct ldb_dn *dn;
     188             : 
     189         503 :     ret = sysdb_dn_sanitize(NULL, name, &clean_name);
     190         503 :     if (ret != EOK) {
     191           0 :         return NULL;
     192             :     }
     193             : 
     194         503 :     dn = ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb, SYSDB_TMPL_GROUP,
     195             :                         clean_name, dom->name);
     196         503 :     talloc_free(clean_name);
     197             : 
     198         503 :     return dn;
     199             : }
     200             : 
     201         933 : struct ldb_dn *sysdb_group_base_dn(TALLOC_CTX *mem_ctx,
     202             :                                    struct sss_domain_info *dom)
     203             : {
     204         933 :     return ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb,
     205             :                           SYSDB_TMPL_GROUP_BASE, dom->name);
     206             : }
     207             : 
     208             : 
     209          53 : struct ldb_dn *sysdb_netgroup_dn(TALLOC_CTX *mem_ctx,
     210             :                                  struct sss_domain_info *dom, const char *name)
     211             : {
     212             :     errno_t ret;
     213             :     char *clean_name;
     214             :     struct ldb_dn *dn;
     215             : 
     216          53 :     ret = sysdb_dn_sanitize(NULL, name, &clean_name);
     217          53 :     if (ret != EOK) {
     218           0 :         return NULL;
     219             :     }
     220             : 
     221          53 :     dn = ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb, SYSDB_TMPL_NETGROUP,
     222             :                         clean_name, dom->name);
     223          53 :     talloc_free(clean_name);
     224             : 
     225          53 :     return dn;
     226             : }
     227             : 
     228           1 : struct ldb_dn *sysdb_netgroup_base_dn(TALLOC_CTX *mem_ctx,
     229             :                                       struct sss_domain_info *dom)
     230             : {
     231           1 :     return ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb,
     232             :                           SYSDB_TMPL_NETGROUP_BASE, dom->name);
     233             : }
     234             : 
     235          10 : errno_t sysdb_get_rdn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
     236             :                       const char *dn, char **_name, char **_val)
     237             : {
     238             :     errno_t ret;
     239             :     struct ldb_dn *ldb_dn;
     240          10 :     const char *attr_name = NULL;
     241             :     const struct ldb_val *val;
     242             :     TALLOC_CTX *tmp_ctx;
     243             : 
     244             :     /* We have to create a tmp_ctx here because
     245             :      * ldb_dn_new_fmt() fails if mem_ctx is NULL
     246             :      */
     247          10 :     tmp_ctx = talloc_new(NULL);
     248          10 :     if (!tmp_ctx) {
     249           0 :         return ENOMEM;
     250             :     }
     251             : 
     252          10 :     ldb_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, "%s", dn);
     253          10 :     if (ldb_dn == NULL) {
     254           0 :         ret = ENOMEM;
     255           0 :         goto done;
     256             :     }
     257             : 
     258          10 :     if (_name) {
     259           0 :         attr_name = ldb_dn_get_rdn_name(ldb_dn);
     260           0 :         if (attr_name == NULL) {
     261           0 :             ret = EINVAL;
     262           0 :             goto done;
     263             :         }
     264             : 
     265           0 :         *_name = talloc_strdup(mem_ctx, attr_name);
     266           0 :         if (!*_name) {
     267           0 :             ret = ENOMEM;
     268           0 :             goto done;
     269             :         }
     270             :     }
     271             : 
     272          10 :     val = ldb_dn_get_rdn_val(ldb_dn);
     273          10 :     if (val == NULL) {
     274           0 :         ret = EINVAL;
     275           0 :         if (_name) talloc_free(*_name);
     276           0 :         goto done;
     277             :     }
     278             : 
     279          10 :     *_val = talloc_strndup(mem_ctx, (char *) val->data, val->length);
     280          10 :     if (!*_val) {
     281           0 :         ret = ENOMEM;
     282           0 :         if (_name) talloc_free(*_name);
     283           0 :         goto done;
     284             :     }
     285             : 
     286          10 :     ret = EOK;
     287             : 
     288             : done:
     289          10 :     talloc_zfree(tmp_ctx);
     290          10 :     return ret;
     291             : }
     292             : 
     293          10 : errno_t sysdb_group_dn_name(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx,
     294             :                             const char *dn, char **_name)
     295             : {
     296          10 :     return sysdb_get_rdn(sysdb, mem_ctx, dn, NULL, _name);
     297             : }
     298             : 
     299          28 : struct ldb_dn *sysdb_domain_dn(TALLOC_CTX *mem_ctx,
     300             :                                struct sss_domain_info *dom)
     301             : {
     302          28 :     return ldb_dn_new_fmt(mem_ctx, dom->sysdb->ldb, SYSDB_DOM_BASE, dom->name);
     303             : }
     304             : 
     305          44 : struct ldb_dn *sysdb_base_dn(struct sysdb_ctx *sysdb, TALLOC_CTX *mem_ctx)
     306             : {
     307          44 :     return ldb_dn_new(mem_ctx, sysdb->ldb, SYSDB_BASE);
     308             : }
     309             : 
     310           0 : struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *sysdb)
     311             : {
     312           0 :     return sysdb->ldb;
     313             : }
     314             : 
     315         726 : struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *mem_ctx)
     316             : {
     317         726 :     return talloc_zero(mem_ctx, struct sysdb_attrs);
     318             : }
     319             : 
     320        2689 : int sysdb_attrs_get_el_ext(struct sysdb_attrs *attrs, const char *name,
     321             :                            bool alloc, struct ldb_message_element **el)
     322             : {
     323        2689 :     struct ldb_message_element *e = NULL;
     324             :     int i;
     325             : 
     326        6601 :     for (i = 0; i < attrs->num; i++) {
     327        3912 :         if (strcasecmp(name, attrs->a[i].name) == 0)
     328         203 :             e = &(attrs->a[i]);
     329             :     }
     330             : 
     331        2689 :     if (!e && alloc) {
     332        2293 :         e = talloc_realloc(attrs, attrs->a,
     333             :                            struct ldb_message_element, attrs->num+1);
     334        2293 :         if (!e) return ENOMEM;
     335        2293 :         attrs->a = e;
     336             : 
     337        2293 :         e[attrs->num].name = talloc_strdup(e, name);
     338        2293 :         if (!e[attrs->num].name) return ENOMEM;
     339             : 
     340        2293 :         e[attrs->num].num_values = 0;
     341        2293 :         e[attrs->num].values = NULL;
     342        2293 :         e[attrs->num].flags = 0;
     343             : 
     344        2293 :         e = &(attrs->a[attrs->num]);
     345        2293 :         attrs->num++;
     346             :     }
     347             : 
     348        2689 :     if (!e) {
     349         193 :         return ENOENT;
     350             :     }
     351             : 
     352        2496 :     *el = e;
     353             : 
     354        2496 :     return EOK;
     355             : }
     356             : 
     357        2357 : int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name,
     358             :                        struct ldb_message_element **el)
     359             : {
     360        2357 :     return sysdb_attrs_get_el_ext(attrs, name, true, el);
     361             : }
     362             : 
     363         134 : int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name,
     364             :                            const char **string)
     365             : {
     366             :     struct ldb_message_element *el;
     367             :     int ret;
     368             : 
     369         134 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     370         134 :     if (ret) {
     371          31 :         return ret;
     372             :     }
     373             : 
     374         103 :     if (el->num_values != 1) {
     375           0 :         return ERANGE;
     376             :     }
     377             : 
     378         103 :     *string = (const char *)el->values[0].data;
     379         103 :     return EOK;
     380             : }
     381             : 
     382           0 : int sysdb_attrs_get_int32_t(struct sysdb_attrs *attrs, const char *name,
     383             :                              int32_t *value)
     384             : {
     385             :     struct ldb_message_element *el;
     386             :     int ret;
     387             :     char *endptr;
     388             :     int32_t val;
     389             : 
     390           0 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     391           0 :     if (ret) {
     392           0 :         return ret;
     393             :     }
     394             : 
     395           0 :     if (el->num_values != 1) {
     396           0 :         return ERANGE;
     397             :     }
     398             : 
     399           0 :     errno = 0;
     400           0 :     val = strtoint32((const char *) el->values[0].data, &endptr, 10);
     401           0 :     if (errno != 0) return errno;
     402           0 :     if (*endptr) return EINVAL;
     403             : 
     404           0 :     *value = val;
     405           0 :     return EOK;
     406             : }
     407             : 
     408          20 : int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,
     409             :                              uint32_t *value)
     410             : {
     411             :     struct ldb_message_element *el;
     412             :     int ret;
     413             :     char *endptr;
     414             :     uint32_t val;
     415             : 
     416          20 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     417          20 :     if (ret) {
     418           2 :         return ret;
     419             :     }
     420             : 
     421          18 :     if (el->num_values != 1) {
     422           0 :         return ERANGE;
     423             :     }
     424             : 
     425          18 :     errno = 0;
     426          18 :     val = strtouint32((const char *) el->values[0].data, &endptr, 10);
     427          18 :     if (errno != 0) return errno;
     428          18 :     if (*endptr) return EINVAL;
     429             : 
     430          18 :     *value = val;
     431          18 :     return EOK;
     432             : }
     433             : 
     434           0 : int sysdb_attrs_get_uint16_t(struct sysdb_attrs *attrs, const char *name,
     435             :                              uint16_t *value)
     436             : {
     437             :     struct ldb_message_element *el;
     438             :     int ret;
     439             :     char *endptr;
     440             :     uint16_t val;
     441             : 
     442           0 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     443           0 :     if (ret) {
     444           0 :         return ret;
     445             :     }
     446             : 
     447           0 :     if (el->num_values != 1) {
     448           0 :         return ERANGE;
     449             :     }
     450             : 
     451           0 :     errno = 0;
     452           0 :     val = strtouint16((const char *) el->values[0].data, &endptr, 10);
     453           0 :     if (errno != 0) return errno;
     454           0 :     if (*endptr) return EINVAL;
     455             : 
     456           0 :     *value = val;
     457           0 :     return EOK;
     458             : }
     459             : 
     460         155 : errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name,
     461             :                              bool *value)
     462             : {
     463             :     struct ldb_message_element *el;
     464             :     int ret;
     465             : 
     466         155 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     467         155 :     if (ret) {
     468         155 :         return ret;
     469             :     }
     470             : 
     471           0 :     if (el->num_values != 1) {
     472           0 :         return ERANGE;
     473             :     }
     474             : 
     475           0 :     if (strcmp((const char *)el->values[0].data, "TRUE") == 0)
     476           0 :         *value = true;
     477             :     else
     478           0 :         *value = false;
     479           0 :     return EOK;
     480             : }
     481             : 
     482           2 : const char **sss_ldb_el_to_string_list(TALLOC_CTX *mem_ctx,
     483             :                                        struct ldb_message_element *el)
     484             : {
     485             :     unsigned int u;
     486             :     const char **a;
     487             : 
     488           2 :     a = talloc_zero_array(mem_ctx, const char *, el->num_values + 1);
     489           2 :     if (a == NULL) {
     490           0 :         return NULL;
     491             :     }
     492             : 
     493           6 :     for (u = 0; u < el->num_values; u++) {
     494           8 :         a[u] = talloc_strndup(a, (const char *)el->values[u].data,
     495           4 :                               el->values[u].length);
     496           4 :         if (a[u] == NULL) {
     497           0 :             talloc_free(a);
     498           0 :             return NULL;
     499             :         }
     500             :     }
     501             : 
     502           2 :     return a;
     503             : }
     504             : 
     505           1 : int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name,
     506             :                                  TALLOC_CTX *mem_ctx, const char ***string)
     507             : {
     508             :     struct ldb_message_element *el;
     509             :     int ret;
     510             :     const char **a;
     511             : 
     512           1 :     ret = sysdb_attrs_get_el_ext(attrs, name, false, &el);
     513           1 :     if (ret) {
     514           0 :         return ret;
     515             :     }
     516             : 
     517           1 :     a = sss_ldb_el_to_string_list(mem_ctx, el);
     518           1 :     if (a == NULL) {
     519           0 :         return ENOMEM;
     520             :     }
     521             : 
     522           1 :     *string = a;
     523           1 :     return EOK;
     524             : }
     525             : 
     526             : 
     527        1988 : static int sysdb_attrs_add_val_int(struct sysdb_attrs *attrs,
     528             :                                    const char *name, bool check_values,
     529             :                                    const struct ldb_val *val)
     530             : {
     531        1988 :     struct ldb_message_element *el = NULL;
     532             :     struct ldb_val *vals;
     533             :     int ret;
     534             :     size_t c;
     535             : 
     536        1988 :     ret = sysdb_attrs_get_el(attrs, name, &el);
     537        1988 :     if (ret != EOK) {
     538           0 :         return ret;
     539             :     }
     540             : 
     541        1988 :     if (check_values) {
     542           2 :         for (c = 0; c < el->num_values; c++) {
     543           2 :             if (val->length == el->values[c].length
     544           2 :                     && memcmp(val->data, el->values[c].data,
     545             :                               val->length) == 0) {
     546           2 :                 return EOK;
     547             :             }
     548             :         }
     549             :     }
     550             : 
     551        1986 :     vals = talloc_realloc(attrs->a, el->values,
     552             :                           struct ldb_val, el->num_values+1);
     553        1986 :     if (!vals) return ENOMEM;
     554             : 
     555        1986 :     vals[el->num_values] = ldb_val_dup(vals, val);
     556        1986 :     if (vals[el->num_values].data == NULL &&
     557           0 :         vals[el->num_values].length != 0) {
     558           0 :         return ENOMEM;
     559             :     }
     560             : 
     561        1986 :     el->values = vals;
     562        1986 :     el->num_values++;
     563             : 
     564        1986 :     return EOK;
     565             : }
     566        1986 : int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
     567             :                         const char *name, const struct ldb_val *val)
     568             : {
     569        1986 :     return sysdb_attrs_add_val_int(attrs, name, false, val);
     570             : }
     571             : 
     572             : /* Check if the same value already exists. */
     573           2 : int sysdb_attrs_add_val_safe(struct sysdb_attrs *attrs,
     574             :                              const char *name, const struct ldb_val *val)
     575             : {
     576           2 :     return sysdb_attrs_add_val_int(attrs, name, true, val);
     577             : }
     578             : 
     579           1 : int sysdb_attrs_add_string_safe(struct sysdb_attrs *attrs,
     580             :                                 const char *name, const char *str)
     581             : {
     582             :     struct ldb_val v;
     583             : 
     584           1 :     v.data = (uint8_t *)discard_const(str);
     585           1 :     v.length = strlen(str);
     586             : 
     587           1 :     return sysdb_attrs_add_val_safe(attrs, name, &v);
     588             : }
     589             : 
     590         953 : int sysdb_attrs_add_string(struct sysdb_attrs *attrs,
     591             :                            const char *name, const char *str)
     592             : {
     593             :     struct ldb_val v;
     594             : 
     595         953 :     v.data = (uint8_t *)discard_const(str);
     596         953 :     v.length = strlen(str);
     597             : 
     598         953 :     return sysdb_attrs_add_val(attrs, name, &v);
     599             : }
     600             : 
     601           2 : int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs,
     602             :                                       const char *name, const char *str)
     603             : {
     604             :     char *lc_str;
     605             :     int ret;
     606             : 
     607           2 :     if (attrs == NULL || str == NULL) {
     608           1 :         return EINVAL;
     609             :     }
     610             : 
     611           1 :     lc_str = sss_tc_utf8_str_tolower(attrs, str);
     612           1 :     if (lc_str == NULL) {
     613           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
     614           0 :         return ENOMEM;
     615             :     }
     616             : 
     617           1 :     ret = sysdb_attrs_add_string(attrs, name, lc_str);
     618           1 :     talloc_free(lc_str);
     619             : 
     620           1 :     return ret;
     621             : }
     622             : 
     623           5 : int sysdb_attrs_add_mem(struct sysdb_attrs *attrs, const char *name,
     624             :                         const void *mem, size_t size)
     625             : {
     626             :         struct ldb_val v;
     627             : 
     628           5 :         v.data   = discard_const(mem);
     629           5 :         v.length = size;
     630           5 :         return sysdb_attrs_add_val(attrs, name, &v);
     631             : }
     632             : 
     633         170 : int sysdb_attrs_add_bool(struct sysdb_attrs *attrs,
     634             :                          const char *name, bool value)
     635             : {
     636         170 :     if(value) {
     637         170 :         return sysdb_attrs_add_string(attrs, name, "TRUE");
     638             :     }
     639             : 
     640           0 :     return sysdb_attrs_add_string(attrs, name, "FALSE");
     641             : }
     642             : 
     643         211 : int sysdb_attrs_steal_string(struct sysdb_attrs *attrs,
     644             :                              const char *name, char *str)
     645             : {
     646         211 :     struct ldb_message_element *el = NULL;
     647             :     struct ldb_val *vals;
     648             :     int ret;
     649             : 
     650         211 :     ret = sysdb_attrs_get_el(attrs, name, &el);
     651         211 :     if (ret != EOK) {
     652           0 :         return ret;
     653             :     }
     654             : 
     655         211 :     vals = talloc_realloc(attrs->a, el->values,
     656             :                           struct ldb_val, el->num_values+1);
     657         211 :     if (!vals) return ENOMEM;
     658         211 :     el->values = vals;
     659             : 
     660             :     /* now steal and assign the string */
     661         211 :     talloc_steal(el->values, str);
     662             : 
     663         211 :     el->values[el->num_values].data = (uint8_t *)str;
     664         211 :     el->values[el->num_values].length = strlen(str);
     665         211 :     el->num_values++;
     666             : 
     667         211 :     return EOK;
     668             : }
     669             : 
     670          34 : int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
     671             :                          const char *name, long value)
     672             : {
     673             :     struct ldb_val v;
     674             :     char *str;
     675             :     int ret;
     676             : 
     677          34 :     str = talloc_asprintf(attrs, "%ld", value);
     678          34 :     if (!str) return ENOMEM;
     679             : 
     680          34 :     v.data = (uint8_t *)str;
     681          34 :     v.length = strlen(str);
     682             : 
     683          34 :     ret = sysdb_attrs_add_val(attrs, name, &v);
     684          34 :     talloc_free(str);
     685             : 
     686          34 :     return ret;
     687             : }
     688             : 
     689         158 : int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
     690             :                            const char *name, uint32_t value)
     691             : {
     692         158 :     unsigned long val = value;
     693             :     struct ldb_val v;
     694             :     char *str;
     695             :     int ret;
     696             : 
     697         158 :     str = talloc_asprintf(attrs, "%lu", val);
     698         158 :     if (!str) return ENOMEM;
     699             : 
     700         158 :     v.data = (uint8_t *)str;
     701         158 :     v.length = strlen(str);
     702             : 
     703         158 :     ret = sysdb_attrs_add_val(attrs, name, &v);
     704         158 :     talloc_free(str);
     705             : 
     706         158 :     return ret;
     707             : }
     708             : 
     709         822 : int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
     710             :                            const char *name, time_t value)
     711             : {
     712         822 :     long long val = value;
     713             :     struct ldb_val v;
     714             :     char *str;
     715             :     int ret;
     716             : 
     717         822 :     str = talloc_asprintf(attrs, "%lld", val);
     718         822 :     if (!str) return ENOMEM;
     719             : 
     720         822 :     v.data = (uint8_t *)str;
     721         822 :     v.length = strlen(str);
     722             : 
     723         822 :     ret = sysdb_attrs_add_val(attrs, name, &v);
     724         822 :     talloc_free(str);
     725             : 
     726         822 :     return ret;
     727             : }
     728             : 
     729           2 : int sysdb_attrs_add_lc_name_alias(struct sysdb_attrs *attrs,
     730             :                                   const char *value)
     731             : {
     732           2 :     return sysdb_attrs_add_lower_case_string(attrs, SYSDB_NAME_ALIAS, value);
     733             : }
     734             : 
     735           0 : int sysdb_attrs_copy_values(struct sysdb_attrs *src,
     736             :                             struct sysdb_attrs *dst,
     737             :                             const char *name)
     738             : {
     739           0 :     int ret = EOK;
     740             :     int i;
     741             :     struct ldb_message_element *src_el;
     742             : 
     743           0 :     ret = sysdb_attrs_get_el(src, name, &src_el);
     744           0 :     if (ret != EOK) {
     745           0 :         goto done;
     746             :     }
     747             : 
     748           0 :     for (i = 0; i < src_el->num_values; i++) {
     749           0 :         ret = sysdb_attrs_add_val(dst, name, &src_el->values[i]);
     750           0 :         if (ret != EOK) {
     751           0 :             goto done;
     752             :         }
     753             :     }
     754             : 
     755             : done:
     756           0 :     return ret;
     757             : }
     758             : 
     759           0 : int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs,
     760             :                                     const char *attr_name,
     761             :                                     const char *domain,
     762             :                                     const char *const *list)
     763             : {
     764           0 :     struct ldb_message_element *el = NULL;
     765             :     struct ldb_val *vals;
     766             :     int i, j, num;
     767             :     char *member;
     768             :     int ret;
     769             : 
     770           0 :     ret = sysdb_attrs_get_el(attrs, attr_name, &el);
     771           0 :     if (ret) {
     772           0 :         return ret;
     773             :     }
     774             : 
     775           0 :     for (num = 0; list[num]; num++) /* count */ ;
     776             : 
     777           0 :     vals = talloc_realloc(attrs->a, el->values,
     778             :                           struct ldb_val, el->num_values + num);
     779           0 :     if (!vals) {
     780           0 :         return ENOMEM;
     781             :     }
     782           0 :     el->values = vals;
     783             : 
     784           0 :     DEBUG(SSSDBG_TRACE_ALL, "Adding %d members to existing %d ones\n",
     785             :               num, el->num_values);
     786             : 
     787           0 :     for (i = 0, j = el->num_values; i < num; i++) {
     788             : 
     789           0 :         member = sysdb_user_strdn(el->values, domain, list[i]);
     790           0 :         if (!member) {
     791           0 :             DEBUG(SSSDBG_CONF_SETTINGS,
     792             :                   "Failed to get user dn for [%s]\n", list[i]);
     793           0 :             continue;
     794             :         }
     795           0 :         el->values[j].data = (uint8_t *)member;
     796           0 :         el->values[j].length = strlen(member);
     797           0 :         j++;
     798             : 
     799           0 :         DEBUG(SSSDBG_TRACE_LIBS, "    member #%d: [%s]\n", i, member);
     800             :     }
     801           0 :     el->num_values = j;
     802             : 
     803           0 :     return EOK;
     804             : }
     805             : 
     806          70 : static char *build_dom_dn_str_escape(TALLOC_CTX *mem_ctx, const char *template,
     807             :                                      const char *domain, const char *name)
     808             : {
     809             :     char *ret;
     810             :     int l;
     811             : 
     812          70 :     l = strcspn(name, ",=\n+<>#;\\\"");
     813          70 :     if (name[l] != '\0') {
     814             :         struct ldb_val v;
     815             :         char *tmp;
     816             : 
     817           0 :         v.data = discard_const_p(uint8_t, name);
     818           0 :         v.length = strlen(name);
     819             : 
     820           0 :         tmp = ldb_dn_escape_value(mem_ctx, v);
     821           0 :         if (!tmp) {
     822           0 :             return NULL;
     823             :         }
     824             : 
     825           0 :         ret = talloc_asprintf(mem_ctx, template, tmp, domain);
     826           0 :         talloc_zfree(tmp);
     827           0 :         if (!ret) {
     828           0 :             return NULL;
     829             :         }
     830             : 
     831           0 :         return ret;
     832             :     }
     833             : 
     834          70 :     ret = talloc_asprintf(mem_ctx, template, name, domain);
     835          70 :     if (!ret) {
     836           0 :         return NULL;
     837             :     }
     838             : 
     839          70 :     return ret;
     840             : }
     841             : 
     842           0 : char *sysdb_user_strdn(TALLOC_CTX *mem_ctx,
     843             :                        const char *domain, const char *name)
     844             : {
     845           0 :     return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_USER, domain, name);
     846             : }
     847             : 
     848          70 : char *sysdb_group_strdn(TALLOC_CTX *mem_ctx,
     849             :                         const char *domain, const char *name)
     850             : {
     851          70 :     return build_dom_dn_str_escape(mem_ctx, SYSDB_TMPL_GROUP, domain, name);
     852             : }
     853             : 
     854             : /* TODO: make a more complete and precise mapping */
     855        1866 : int sysdb_error_to_errno(int ldberr)
     856             : {
     857        1866 :     switch (ldberr) {
     858             :     case LDB_SUCCESS:
     859        1865 :         return EOK;
     860             :     case LDB_ERR_OPERATIONS_ERROR:
     861           0 :         return EIO;
     862             :     case LDB_ERR_NO_SUCH_OBJECT:
     863           1 :         return ENOENT;
     864             :     case LDB_ERR_BUSY:
     865           0 :         return EBUSY;
     866             :     case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
     867             :     case LDB_ERR_ENTRY_ALREADY_EXISTS:
     868           0 :         return EEXIST;
     869             :     case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
     870           0 :         return EINVAL;
     871             :     default:
     872           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     873             :               "LDB returned unexpected error: [%s]\n",
     874             :                ldb_strerror(ldberr));
     875           0 :         return EFAULT;
     876             :     }
     877             : }
     878             : 
     879             : /* =Transactions========================================================== */
     880             : 
     881         145 : int sysdb_transaction_start(struct sysdb_ctx *sysdb)
     882             : {
     883             :     int ret;
     884             : 
     885         145 :     ret = ldb_transaction_start(sysdb->ldb);
     886         145 :     if (ret != LDB_SUCCESS) {
     887           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     888             :               "Failed to start ldb transaction! (%d)\n", ret);
     889             :     }
     890         145 :     return sysdb_error_to_errno(ret);
     891             : }
     892             : 
     893         145 : int sysdb_transaction_commit(struct sysdb_ctx *sysdb)
     894             : {
     895             :     int ret;
     896             : 
     897         145 :     ret = ldb_transaction_commit(sysdb->ldb);
     898         145 :     if (ret != LDB_SUCCESS) {
     899           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     900             :               "Failed to commit ldb transaction! (%d)\n", ret);
     901             :     }
     902         145 :     return sysdb_error_to_errno(ret);
     903             : }
     904             : 
     905           0 : int sysdb_transaction_cancel(struct sysdb_ctx *sysdb)
     906             : {
     907             :     int ret;
     908             : 
     909           0 :     ret = ldb_transaction_cancel(sysdb->ldb);
     910           0 :     if (ret != LDB_SUCCESS) {
     911           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     912             :               "Failed to cancel ldb transaction! (%d)\n", ret);
     913             :     }
     914           0 :     return sysdb_error_to_errno(ret);
     915             : }
     916             : 
     917             : /* =Initialization======================================================== */
     918             : 
     919        1081 : int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
     920             :                       const char *provider, const char *name,
     921             :                       const char *base_path, char **_ldb_file)
     922             : {
     923             :     char *ldb_file;
     924             : 
     925             :     /* special case for the local domain */
     926        1081 :     if (strcasecmp(provider, "local") == 0) {
     927         871 :         ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE,
     928             :                                    base_path);
     929             :     } else {
     930         210 :         ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
     931             :                                    base_path, name);
     932             :     }
     933        1081 :     if (!ldb_file) {
     934           0 :         return ENOMEM;
     935             :     }
     936             : 
     937        1081 :     *_ldb_file = ldb_file;
     938        1081 :     return EOK;
     939             : }
     940             : 
     941         131 : errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name)
     942             : {
     943             :     struct ldb_message *msg;
     944             :     TALLOC_CTX *tmp_ctx;
     945             :     int ret;
     946             : 
     947         131 :     tmp_ctx = talloc_new(NULL);
     948         131 :     if (tmp_ctx == NULL) {
     949           0 :         ret = ENOMEM;
     950           0 :         goto done;
     951             :     }
     952             : 
     953             :     /* == create base domain object == */
     954             : 
     955         131 :     msg = ldb_msg_new(tmp_ctx);
     956         131 :     if (!msg) {
     957           0 :         ret = ENOMEM;
     958           0 :         goto done;
     959             :     }
     960         131 :     msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, SYSDB_DOM_BASE, domain_name);
     961         131 :     if (!msg->dn) {
     962           0 :         ret = ENOMEM;
     963           0 :         goto done;
     964             :     }
     965         131 :     ret = ldb_msg_add_string(msg, "cn", domain_name);
     966         131 :     if (ret != LDB_SUCCESS) {
     967           0 :         ret = EIO;
     968           0 :         goto done;
     969             :     }
     970             :     /* do a synchronous add */
     971         131 :     ret = ldb_add(sysdb->ldb, msg);
     972         131 :     if (ret != LDB_SUCCESS) {
     973           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) "
     974             :                                      "for domain %s!\n",
     975             :                                      ret, ldb_errstring(sysdb->ldb),
     976             :                                      domain_name);
     977           0 :         ret = EIO;
     978           0 :         goto done;
     979             :     }
     980         131 :     talloc_zfree(msg);
     981             : 
     982             :     /* == create Users tree == */
     983             : 
     984         131 :     msg = ldb_msg_new(tmp_ctx);
     985         131 :     if (!msg) {
     986           0 :         ret = ENOMEM;
     987           0 :         goto done;
     988             :     }
     989         131 :     msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
     990             :                              SYSDB_TMPL_USER_BASE, domain_name);
     991         131 :     if (!msg->dn) {
     992           0 :         ret = ENOMEM;
     993           0 :         goto done;
     994             :     }
     995         131 :     ret = ldb_msg_add_string(msg, "cn", "Users");
     996         131 :     if (ret != LDB_SUCCESS) {
     997           0 :         ret = EIO;
     998           0 :         goto done;
     999             :     }
    1000             :     /* do a synchronous add */
    1001         131 :     ret = ldb_add(sysdb->ldb, msg);
    1002         131 :     if (ret != LDB_SUCCESS) {
    1003           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) "
    1004             :                                      "for domain %s!\n",
    1005             :                                      ret, ldb_errstring(sysdb->ldb),
    1006             :                                      domain_name);
    1007           0 :         ret = EIO;
    1008           0 :         goto done;
    1009             :     }
    1010         131 :     talloc_zfree(msg);
    1011             : 
    1012             :     /* == create Groups tree == */
    1013             : 
    1014         131 :     msg = ldb_msg_new(tmp_ctx);
    1015         131 :     if (!msg) {
    1016           0 :         ret = ENOMEM;
    1017           0 :         goto done;
    1018             :     }
    1019         131 :     msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb,
    1020             :                              SYSDB_TMPL_GROUP_BASE, domain_name);
    1021         131 :     if (!msg->dn) {
    1022           0 :         ret = ENOMEM;
    1023           0 :         goto done;
    1024             :     }
    1025         131 :     ret = ldb_msg_add_string(msg, "cn", "Groups");
    1026         131 :     if (ret != LDB_SUCCESS) {
    1027           0 :         ret = EIO;
    1028           0 :         goto done;
    1029             :     }
    1030             :     /* do a synchronous add */
    1031         131 :     ret = ldb_add(sysdb->ldb, msg);
    1032         131 :     if (ret != LDB_SUCCESS) {
    1033           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) for "
    1034             :                                      "domain %s!\n",
    1035             :                                      ret, ldb_errstring(sysdb->ldb),
    1036             :                                      domain_name);
    1037           0 :         ret = EIO;
    1038           0 :         goto done;
    1039             :     }
    1040         131 :     talloc_zfree(msg);
    1041             : 
    1042         131 :     ret = EOK;
    1043             : 
    1044             : done:
    1045         131 :     talloc_zfree(tmp_ctx);
    1046         131 :     return ret;
    1047             : }
    1048             : 
    1049             : /* Compare versions of sysdb, returns ERRNO accordingly */
    1050             : static errno_t
    1051           0 : sysdb_version_check(const char *expected,
    1052             :                     const char *received)
    1053             : {
    1054             :     int ret;
    1055             :     unsigned int exp_major, exp_minor, recv_major, recv_minor;
    1056             : 
    1057           0 :     ret = sscanf(expected, "%u.%u", &exp_major, &exp_minor);
    1058           0 :     if (ret != 2) {
    1059           0 :         return EINVAL;
    1060             :     }
    1061           0 :     ret = sscanf(received, "%u.%u", &recv_major, &recv_minor);
    1062           0 :     if (ret != 2) {
    1063           0 :         return EINVAL;
    1064             :     }
    1065             : 
    1066           0 :     if (recv_major > exp_major) {
    1067           0 :         return EUCLEAN;
    1068           0 :     } else if (recv_major < exp_major) {
    1069           0 :         return EMEDIUMTYPE;
    1070             :     }
    1071             : 
    1072           0 :     if (recv_minor > exp_minor) {
    1073           0 :         return EUCLEAN;
    1074           0 :     } else if (recv_minor < exp_minor) {
    1075           0 :         return EMEDIUMTYPE;
    1076             :     }
    1077             : 
    1078           0 :     return EOK;
    1079             : }
    1080             : 
    1081        1081 : int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
    1082             :                                struct sss_domain_info *domain,
    1083             :                                const char *db_path,
    1084             :                                bool allow_upgrade,
    1085             :                                struct sysdb_ctx **_ctx)
    1086             : {
    1087        1081 :     TALLOC_CTX *tmp_ctx = NULL;
    1088             :     struct sysdb_ctx *sysdb;
    1089             :     const char *base_ldif;
    1090             :     struct ldb_ldif *ldif;
    1091             :     struct ldb_message_element *el;
    1092             :     struct ldb_result *res;
    1093             :     struct ldb_dn *verdn;
    1094        1081 :     const char *version = NULL;
    1095             :     int ret;
    1096             : 
    1097        1081 :     sysdb = talloc_zero(mem_ctx, struct sysdb_ctx);
    1098        1081 :     if (!sysdb) {
    1099           0 :         return ENOMEM;
    1100             :     }
    1101             : 
    1102        2162 :     ret = sysdb_get_db_file(sysdb, domain->provider,
    1103        1081 :                             domain->name, db_path,
    1104             :                             &sysdb->ldb_file);
    1105        1081 :     if (ret != EOK) {
    1106           0 :         goto done;
    1107             :     }
    1108        1081 :     DEBUG(SSSDBG_FUNC_DATA,
    1109             :           "DB File for %s: %s\n", domain->name, sysdb->ldb_file);
    1110             : 
    1111        1081 :     ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
    1112        1081 :     if (ret != EOK) {
    1113           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n");
    1114           0 :         goto done;
    1115             :     }
    1116             : 
    1117        1081 :     tmp_ctx = talloc_new(NULL);
    1118        1081 :     if (!tmp_ctx) {
    1119           0 :         ret = ENOMEM;
    1120           0 :         goto done;
    1121             :     }
    1122             : 
    1123        1081 :     verdn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
    1124        1081 :     if (!verdn) {
    1125           0 :         ret = EIO;
    1126           0 :         goto done;
    1127             :     }
    1128             : 
    1129        1081 :     ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
    1130             :                      verdn, LDB_SCOPE_BASE,
    1131             :                      NULL, NULL);
    1132        1081 :     if (ret != LDB_SUCCESS) {
    1133           0 :         ret = EIO;
    1134           0 :         goto done;
    1135             :     }
    1136        1081 :     if (res->count > 1) {
    1137           0 :         ret = EIO;
    1138           0 :         goto done;
    1139             :     }
    1140             : 
    1141        1081 :     if (res->count == 1) {
    1142         965 :         el = ldb_msg_find_element(res->msgs[0], "version");
    1143         965 :         if (!el) {
    1144           0 :             ret = EIO;
    1145           0 :             goto done;
    1146             :         }
    1147             : 
    1148         965 :         if (el->num_values != 1) {
    1149           0 :             ret = EINVAL;
    1150           0 :             goto done;
    1151             :         }
    1152        1930 :         version = talloc_strndup(tmp_ctx,
    1153         965 :                                  (char *)(el->values[0].data),
    1154         965 :                                  el->values[0].length);
    1155         965 :         if (!version) {
    1156           0 :             ret = ENOMEM;
    1157           0 :             goto done;
    1158             :         }
    1159             : 
    1160         965 :         if (strcmp(version, SYSDB_VERSION) == 0) {
    1161             :             /* all fine, return */
    1162         965 :             ret = EOK;
    1163         965 :             goto done;
    1164             :         }
    1165             : 
    1166           0 :         if (!allow_upgrade) {
    1167           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    1168             :                   "Wrong DB version (got %s expected %s)\n",
    1169             :                    version, SYSDB_VERSION);
    1170           0 :             ret = sysdb_version_check(SYSDB_VERSION, version);
    1171           0 :             goto done;
    1172             :         }
    1173             : 
    1174           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Upgrading DB [%s] from version: %s\n",
    1175             :                   domain->name, version);
    1176             : 
    1177           0 :         if (strcmp(version, SYSDB_VERSION_0_3) == 0) {
    1178           0 :             ret = sysdb_upgrade_03(sysdb, &version);
    1179           0 :             if (ret != EOK) {
    1180           0 :                 goto done;
    1181             :             }
    1182             :         }
    1183             : 
    1184           0 :         if (strcmp(version, SYSDB_VERSION_0_4) == 0) {
    1185           0 :             ret = sysdb_upgrade_04(sysdb, &version);
    1186           0 :             if (ret != EOK) {
    1187           0 :                 goto done;
    1188             :             }
    1189             :         }
    1190             : 
    1191           0 :         if (strcmp(version, SYSDB_VERSION_0_5) == 0) {
    1192           0 :             ret = sysdb_upgrade_05(sysdb, &version);
    1193           0 :             if (ret != EOK) {
    1194           0 :                 goto done;
    1195             :             }
    1196             :         }
    1197             : 
    1198           0 :         if (strcmp(version, SYSDB_VERSION_0_6) == 0) {
    1199           0 :             ret = sysdb_upgrade_06(sysdb, &version);
    1200           0 :             if (ret != EOK) {
    1201           0 :                 goto done;
    1202             :             }
    1203             :         }
    1204             : 
    1205           0 :         if (strcmp(version, SYSDB_VERSION_0_7) == 0) {
    1206           0 :             ret = sysdb_upgrade_07(sysdb, &version);
    1207           0 :             if (ret != EOK) {
    1208           0 :                 goto done;
    1209             :             }
    1210             :         }
    1211             : 
    1212           0 :         if (strcmp(version, SYSDB_VERSION_0_8) == 0) {
    1213           0 :             ret = sysdb_upgrade_08(sysdb, &version);
    1214           0 :             if (ret != EOK) {
    1215           0 :                 goto done;
    1216             :             }
    1217             :         }
    1218             : 
    1219           0 :         if (strcmp(version, SYSDB_VERSION_0_9) == 0) {
    1220           0 :             ret = sysdb_upgrade_09(sysdb, &version);
    1221           0 :             if (ret != EOK) {
    1222           0 :                 goto done;
    1223             :             }
    1224             :         }
    1225             : 
    1226           0 :         if (strcmp(version, SYSDB_VERSION_0_10) == 0) {
    1227           0 :             ret = sysdb_upgrade_10(sysdb, domain, &version);
    1228           0 :             if (ret != EOK) {
    1229           0 :                 goto done;
    1230             :             }
    1231             :         }
    1232             : 
    1233           0 :         if (strcmp(version, SYSDB_VERSION_0_11) == 0) {
    1234           0 :             ret = sysdb_upgrade_11(sysdb, domain, &version);
    1235           0 :             if (ret != EOK) {
    1236           0 :                 goto done;
    1237             :             }
    1238             :         }
    1239             : 
    1240           0 :         if (strcmp(version, SYSDB_VERSION_0_12) == 0) {
    1241           0 :             ret = sysdb_upgrade_12(sysdb, &version);
    1242           0 :             if (ret != EOK) {
    1243           0 :                 goto done;
    1244             :             }
    1245             :         }
    1246             : 
    1247           0 :         if (strcmp(version, SYSDB_VERSION_0_13) == 0) {
    1248           0 :             ret = sysdb_upgrade_13(sysdb, &version);
    1249           0 :             if (ret != EOK) {
    1250           0 :                 goto done;
    1251             :             }
    1252             :         }
    1253             : 
    1254           0 :         if (strcmp(version, SYSDB_VERSION_0_14) == 0) {
    1255           0 :             ret = sysdb_upgrade_14(sysdb, &version);
    1256           0 :             if (ret != EOK) {
    1257           0 :                 goto done;
    1258             :             }
    1259             :         }
    1260             : 
    1261           0 :         if (strcmp(version, SYSDB_VERSION_0_15) == 0) {
    1262           0 :             ret = sysdb_upgrade_15(sysdb, &version);
    1263           0 :             if (ret != EOK) {
    1264           0 :                 goto done;
    1265             :             }
    1266             :         }
    1267             : 
    1268           0 :         if (strcmp(version, SYSDB_VERSION_0_16) == 0) {
    1269           0 :             ret = sysdb_upgrade_16(sysdb, &version);
    1270           0 :             if (ret != EOK) {
    1271           0 :                 goto done;
    1272             :             }
    1273             :         }
    1274             : 
    1275             :         /* The version should now match SYSDB_VERSION.
    1276             :          * If not, it means we didn't match any of the
    1277             :          * known older versions. The DB might be
    1278             :          * corrupt or generated by a newer version of
    1279             :          * SSSD.
    1280             :          */
    1281           0 :         if (strcmp(version, SYSDB_VERSION) == 0) {
    1282             :             /* The cache has been upgraded.
    1283             :              * We need to reopen the LDB to ensure that
    1284             :              * any changes made above take effect.
    1285             :              */
    1286           0 :             talloc_zfree(sysdb->ldb);
    1287           0 :             ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
    1288           0 :             if (ret != EOK) {
    1289           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n");
    1290             :             }
    1291           0 :             goto done;
    1292             :         }
    1293             : 
    1294           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    1295             :               "Unknown DB version [%s], expected [%s] for domain %s!\n",
    1296             :               version, SYSDB_VERSION, domain->name);
    1297           0 :         ret = sysdb_version_check(SYSDB_VERSION, version);
    1298           0 :         goto done;
    1299             :     }
    1300             : 
    1301             :     /* SYSDB_BASE does not exists, means db is empty, populate */
    1302             : 
    1303         116 :     base_ldif = SYSDB_BASE_LDIF;
    1304         812 :     while ((ldif = ldb_ldif_read_string(sysdb->ldb, &base_ldif))) {
    1305         580 :         ret = ldb_add(sysdb->ldb, ldif->msg);
    1306         580 :         if (ret != LDB_SUCCESS) {
    1307           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    1308             :                   "Failed to initialize DB (%d, [%s]) for domain %s!\n",
    1309             :                       ret, ldb_errstring(sysdb->ldb), domain->name);
    1310           0 :             ret = EIO;
    1311           0 :             goto done;
    1312             :         }
    1313         580 :         ldb_ldif_read_free(sysdb->ldb, ldif);
    1314             :     }
    1315             : 
    1316         116 :     ret = sysdb_domain_create(sysdb, domain->name);
    1317         116 :     if (ret != EOK) {
    1318           0 :         goto done;
    1319             :     }
    1320             : 
    1321             :     /* The cache has been newly created.
    1322             :      * We need to reopen the LDB to ensure that
    1323             :      * all of the special values take effect
    1324             :      * (such as enabling the memberOf plugin and
    1325             :      * the various indexes).
    1326             :      */
    1327         116 :     talloc_zfree(sysdb->ldb);
    1328         116 :     ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb);
    1329         116 :     if (ret != EOK) {
    1330           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n");
    1331             :     }
    1332             : 
    1333             : done:
    1334        1081 :     talloc_free(tmp_ctx);
    1335        1081 :     if (ret == EOK) {
    1336        1081 :         *_ctx = sysdb;
    1337             :     } else {
    1338           0 :         talloc_free(sysdb);
    1339             :     }
    1340        1081 :     return ret;
    1341             : }
    1342             : 
    1343           0 : int sysdb_init(TALLOC_CTX *mem_ctx,
    1344             :                struct sss_domain_info *domains,
    1345             :                bool allow_upgrade)
    1346             : {
    1347           0 :     return sysdb_init_ext(mem_ctx, domains, allow_upgrade, false, 0, 0);
    1348             : }
    1349             : 
    1350           0 : int sysdb_init_ext(TALLOC_CTX *mem_ctx,
    1351             :                    struct sss_domain_info *domains,
    1352             :                    bool allow_upgrade,
    1353             :                    bool chown_dbfile,
    1354             :                    uid_t uid,
    1355             :                    gid_t gid)
    1356             : {
    1357             :     struct sss_domain_info *dom;
    1358             :     struct sysdb_ctx *sysdb;
    1359             :     int ret;
    1360             : 
    1361           0 :     if (allow_upgrade) {
    1362             :         /* check if we have an old sssd.ldb to upgrade */
    1363           0 :         ret = sysdb_check_upgrade_02(domains, DB_PATH);
    1364           0 :         if (ret != EOK) {
    1365           0 :             return ret;
    1366             :         }
    1367             :     }
    1368             : 
    1369             :     /* open a db for each domain */
    1370           0 :     for (dom = domains; dom; dom = dom->next) {
    1371             : 
    1372           0 :         ret = sysdb_domain_init_internal(mem_ctx, dom, DB_PATH,
    1373             :                                          allow_upgrade, &sysdb);
    1374           0 :         if (ret != EOK) {
    1375           0 :             return ret;
    1376             :         }
    1377             : 
    1378           0 :         if (chown_dbfile) {
    1379           0 :             ret = chown(sysdb->ldb_file, uid, gid);
    1380           0 :             if (ret != 0) {
    1381           0 :                 ret = errno;
    1382           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
    1383             :                       "Cannot set sysdb ownership to %"SPRIuid":%"SPRIgid"\n",
    1384             :                       uid, gid);
    1385           0 :                 return ret;
    1386             :             }
    1387             :         }
    1388             : 
    1389           0 :         dom->sysdb = talloc_move(dom, &sysdb);
    1390             :     }
    1391             : 
    1392           0 :     return EOK;
    1393             : }
    1394             : 
    1395        1081 : int sysdb_domain_init(TALLOC_CTX *mem_ctx,
    1396             :                       struct sss_domain_info *domain,
    1397             :                       const char *db_path,
    1398             :                       struct sysdb_ctx **_ctx)
    1399             : {
    1400        1081 :     return sysdb_domain_init_internal(mem_ctx, domain,
    1401             :                                       db_path, false, _ctx);
    1402             : }
    1403             : 
    1404          37 : int compare_ldb_dn_comp_num(const void *m1, const void *m2)
    1405             : {
    1406          37 :     struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1),
    1407             :                                                struct ldb_message);
    1408          37 :     struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2),
    1409             :                                                struct ldb_message);
    1410             : 
    1411          37 :     return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn);
    1412             : }
    1413             : 
    1414           2 : int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,
    1415             :                              const char *newname)
    1416             : {
    1417           2 :     struct ldb_message_element *e = NULL;
    1418             :     int i;
    1419             :     const char *dummy;
    1420             : 
    1421           2 :     if (attrs == NULL || oldname == NULL || newname == NULL) return EINVAL;
    1422             : 
    1423           7 :     for (i = 0; i < attrs->num; i++) {
    1424           6 :         if (strcasecmp(oldname, attrs->a[i].name) == 0) {
    1425           2 :             e = &(attrs->a[i]);
    1426             :         }
    1427           6 :         if (strcasecmp(newname, attrs->a[i].name) == 0) {
    1428           1 :             DEBUG(SSSDBG_MINOR_FAILURE,
    1429             :                   "New attribute name [%s] already exists.\n", newname);
    1430           1 :             return EEXIST;
    1431             :         }
    1432             :     }
    1433             : 
    1434           1 :     if (e != NULL) {
    1435           1 :         dummy = talloc_strdup(attrs, newname);
    1436           1 :         if (dummy == NULL) {
    1437           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
    1438           0 :             return ENOMEM;
    1439             :         }
    1440             : 
    1441           1 :         talloc_free(discard_const(e->name));
    1442           1 :         e->name = dummy;
    1443             :     }
    1444             : 
    1445           1 :     return EOK;
    1446             : }
    1447             : 
    1448             : /* Search for all incidences of attr_name in a list of
    1449             :  * sysdb_attrs and add their value to a list
    1450             :  *
    1451             :  * TODO: Currently only works for single-valued
    1452             :  * attributes. Multi-valued attributes will return
    1453             :  * only the first entry
    1454             :  */
    1455           1 : errno_t sysdb_attrs_to_list(TALLOC_CTX *mem_ctx,
    1456             :                             struct sysdb_attrs **attrs,
    1457             :                             int attr_count,
    1458             :                             const char *attr_name,
    1459             :                             char ***_list)
    1460             : {
    1461             :     int attr_idx;
    1462             :     int i;
    1463             :     char **list;
    1464             :     char **tmp_list;
    1465             :     int list_idx;
    1466             : 
    1467           1 :     *_list = NULL;
    1468             : 
    1469             :     /* Assume that every attrs entry contains the attr_name
    1470             :      * This may waste a little memory if some entries don't
    1471             :      * have the attribute, but it will save us the trouble
    1472             :      * of continuously resizing the array.
    1473             :      */
    1474           1 :     list = talloc_array(mem_ctx, char *, attr_count+1);
    1475           1 :     if (!list) {
    1476           0 :         return ENOMEM;
    1477             :     }
    1478             : 
    1479           1 :     list_idx = 0;
    1480             :     /* Loop through all entries in attrs */
    1481           4 :     for (attr_idx = 0; attr_idx < attr_count; attr_idx++) {
    1482             :         /* Examine each attribute within the entry */
    1483           4 :         for (i = 0; i < attrs[attr_idx]->num; i++) {
    1484           3 :             if (strcasecmp(attrs[attr_idx]->a[i].name, attr_name) == 0) {
    1485             :                 /* Attribute name matches the requested name
    1486             :                  * Copy it to the output list
    1487             :                  */
    1488           4 :                 list[list_idx] = talloc_strdup(
    1489             :                         list,
    1490           2 :                         (const char *)attrs[attr_idx]->a[i].values[0].data);
    1491           2 :                 if (!list[list_idx]) {
    1492           0 :                     talloc_free(list);
    1493           0 :                     return ENOMEM;
    1494             :                 }
    1495           2 :                 list_idx++;
    1496             : 
    1497             :                 /* We only support single-valued attributes
    1498             :                  * Break here and go on to the next entry
    1499             :                  */
    1500           2 :                 break;
    1501             :             }
    1502             :         }
    1503             :     }
    1504             : 
    1505           1 :     list[list_idx] = NULL;
    1506             : 
    1507             :     /* if list_idx < attr_count, do a realloc to
    1508             :      * reclaim unused memory
    1509             :      */
    1510           1 :     if (list_idx < attr_count) {
    1511           1 :         tmp_list = talloc_realloc(mem_ctx, list, char *, list_idx+1);
    1512           1 :         if (!tmp_list) {
    1513           0 :             talloc_zfree(list);
    1514           0 :             return ENOMEM;
    1515             :         }
    1516           1 :         list = tmp_list;
    1517             :     }
    1518             : 
    1519           1 :     *_list = list;
    1520           1 :     return EOK;
    1521             : }
    1522             : 
    1523           5 : errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
    1524             :                        struct ldb_dn *dn,
    1525             :                        const char *attr_name,
    1526             :                        bool *value)
    1527             : {
    1528             :     TALLOC_CTX *tmp_ctx;
    1529             :     struct ldb_result *res;
    1530             :     errno_t ret;
    1531             :     int lret;
    1532           5 :     const char *attrs[2] = {attr_name, NULL};
    1533             :     struct ldb_message_element *el;
    1534             : 
    1535           5 :     tmp_ctx = talloc_new(NULL);
    1536           5 :     if (tmp_ctx == NULL) {
    1537           0 :         return ENOMEM;
    1538             :     }
    1539             : 
    1540           5 :     lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
    1541             :                       attrs, NULL);
    1542           5 :     if (lret != LDB_SUCCESS) {
    1543           0 :         ret = sysdb_error_to_errno(lret);
    1544           0 :         goto done;
    1545             :     }
    1546             : 
    1547           5 :     if (res->count == 0) {
    1548             :         /* This entry has not been populated in LDB
    1549             :          * This is a common case, as unlike LDAP,
    1550             :          * LDB does not need to have all of its parent
    1551             :          * objects actually exist.
    1552             :          * This object in the sysdb exists mostly just
    1553             :          * to contain this attribute.
    1554             :          */
    1555           2 :         *value = false;
    1556           2 :         ret = ENOENT;
    1557           2 :         goto done;
    1558           3 :     } else if (res->count != 1) {
    1559           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1560             :               "Got more than one reply for base search!\n");
    1561           0 :         ret = EIO;
    1562           0 :         goto done;
    1563             :     }
    1564             : 
    1565           3 :     el = ldb_msg_find_element(res->msgs[0], attr_name);
    1566           3 :     if (el == NULL || el->num_values == 0) {
    1567           1 :         ret = ENOENT;
    1568           1 :         goto done;
    1569             :     }
    1570             : 
    1571           2 :     *value = ldb_msg_find_attr_as_bool(res->msgs[0], attr_name, false);
    1572             : 
    1573           2 :     ret = EOK;
    1574             : 
    1575             : done:
    1576           5 :     talloc_free(tmp_ctx);
    1577           5 :     return ret;
    1578             : }
    1579             : 
    1580           2 : errno_t sysdb_set_bool(struct sysdb_ctx *sysdb,
    1581             :                        struct ldb_dn *dn,
    1582             :                        const char *cn_value,
    1583             :                        const char *attr_name,
    1584             :                        bool value)
    1585             : {
    1586           2 :     TALLOC_CTX *tmp_ctx = NULL;
    1587           2 :     struct ldb_message *msg = NULL;
    1588           2 :     struct ldb_result *res = NULL;
    1589             :     errno_t ret;
    1590             :     int lret;
    1591             : 
    1592           2 :     if (dn == NULL || cn_value == NULL || attr_name == NULL) {
    1593           0 :         return EINVAL;
    1594             :     }
    1595             : 
    1596           2 :     tmp_ctx = talloc_new(NULL);
    1597           2 :     if (tmp_ctx == NULL) {
    1598           0 :         return ENOMEM;
    1599             :     }
    1600             : 
    1601           2 :     lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
    1602             :                       NULL, NULL);
    1603           2 :     if (lret != LDB_SUCCESS) {
    1604           0 :         ret = sysdb_error_to_errno(lret);
    1605           0 :         goto done;
    1606             :     }
    1607             : 
    1608           2 :     msg = ldb_msg_new(tmp_ctx);
    1609           2 :     if (msg == NULL) {
    1610           0 :         ret = ENOMEM;
    1611           0 :         goto done;
    1612             :     }
    1613           2 :     msg->dn = dn;
    1614             : 
    1615           2 :     if (res->count == 0) {
    1616           1 :         lret = ldb_msg_add_string(msg, "cn", cn_value);
    1617           1 :         if (lret != LDB_SUCCESS) {
    1618           0 :             ret = sysdb_error_to_errno(lret);
    1619           0 :             goto done;
    1620             :         }
    1621           1 :     } else if (res->count != 1) {
    1622           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1623             :               "Got more than one reply for base search!\n");
    1624           0 :         ret = EIO;
    1625           0 :         goto done;
    1626             :     } else {
    1627           1 :         lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
    1628           1 :         if (lret != LDB_SUCCESS) {
    1629           0 :             ret = sysdb_error_to_errno(lret);
    1630           0 :             goto done;
    1631             :         }
    1632             :     }
    1633             : 
    1634           2 :     lret = ldb_msg_add_string(msg, attr_name, value ? "TRUE" : "FALSE");
    1635           2 :     if (lret != LDB_SUCCESS) {
    1636           0 :         ret = sysdb_error_to_errno(lret);
    1637           0 :         goto done;
    1638             :     }
    1639             : 
    1640           2 :     if (res->count) {
    1641           1 :         lret = ldb_modify(sysdb->ldb, msg);
    1642             :     } else {
    1643           1 :         lret = ldb_add(sysdb->ldb, msg);
    1644             :     }
    1645             : 
    1646           2 :     if (lret != LDB_SUCCESS) {
    1647           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1648             :               "ldb operation failed: [%s](%d)[%s]\n",
    1649             :               ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb));
    1650             :     }
    1651           2 :     ret = sysdb_error_to_errno(lret);
    1652             : 
    1653             : done:
    1654           2 :     talloc_free(tmp_ctx);
    1655           2 :     return ret;
    1656             : }
    1657             : 
    1658           2 : errno_t sysdb_has_enumerated(struct sss_domain_info *domain,
    1659             :                              bool *has_enumerated)
    1660             : {
    1661             :     errno_t ret;
    1662             :     struct ldb_dn *dn;
    1663             :     TALLOC_CTX *tmp_ctx;
    1664             : 
    1665             : 
    1666           2 :     tmp_ctx = talloc_new(NULL);
    1667           2 :     if (!tmp_ctx) {
    1668           0 :         ret = ENOMEM;
    1669           0 :         goto done;
    1670             :     }
    1671             : 
    1672           2 :     dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_DOM_BASE,
    1673             :                         domain->name);
    1674           2 :     if (!dn) {
    1675           0 :         ret = ENOMEM;
    1676           0 :         goto done;
    1677             :     }
    1678             : 
    1679           2 :     ret = sysdb_get_bool(domain->sysdb, dn, SYSDB_HAS_ENUMERATED,
    1680             :                          has_enumerated);
    1681             : 
    1682             : done:
    1683           2 :     talloc_free(tmp_ctx);
    1684           2 :     return ret;
    1685             : }
    1686             : 
    1687           1 : errno_t sysdb_set_enumerated(struct sss_domain_info *domain,
    1688             :                              bool enumerated)
    1689             : {
    1690             :     errno_t ret;
    1691             :     TALLOC_CTX *tmp_ctx;
    1692             :     struct ldb_dn *dn;
    1693             : 
    1694           1 :     tmp_ctx = talloc_new(NULL);
    1695           1 :     if (!tmp_ctx) {
    1696           0 :         ret = ENOMEM;
    1697           0 :         goto done;
    1698             :     }
    1699             : 
    1700           1 :     dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_DOM_BASE,
    1701             :                         domain->name);
    1702           1 :     if (!dn) {
    1703           0 :         ret = ENOMEM;
    1704           0 :         goto done;
    1705             :     }
    1706             : 
    1707           1 :     ret = sysdb_set_bool(domain->sysdb, dn, domain->name,
    1708             :                          SYSDB_HAS_ENUMERATED, enumerated);
    1709             : 
    1710             : done:
    1711           1 :     talloc_free(tmp_ctx);
    1712           1 :     return ret;
    1713             : }
    1714             : 
    1715           0 : errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
    1716             :                                  struct sysdb_attrs *attrs,
    1717             :                                  const char *ldap_attr,
    1718             :                                  const char **_primary)
    1719             : {
    1720             :     errno_t ret;
    1721           0 :     char *rdn_attr = NULL;
    1722           0 :     char *rdn_val = NULL;
    1723             :     struct ldb_message_element *sysdb_name_el;
    1724             :     struct ldb_message_element *orig_dn_el;
    1725             :     size_t i;
    1726           0 :     TALLOC_CTX *tmp_ctx = NULL;
    1727             : 
    1728           0 :     tmp_ctx = talloc_new(NULL);
    1729           0 :     if (!tmp_ctx) {
    1730           0 :         return ENOMEM;
    1731             :     }
    1732             : 
    1733           0 :     ret = sysdb_attrs_get_el(attrs,
    1734             :                              SYSDB_NAME,
    1735             :                              &sysdb_name_el);
    1736           0 :     if (ret != EOK || sysdb_name_el->num_values == 0) {
    1737           0 :         ret = EINVAL;
    1738           0 :         goto done;
    1739             :     }
    1740             : 
    1741           0 :     if (sysdb_name_el->num_values == 1) {
    1742             :         /* Entry contains only one name. Just return that */
    1743           0 :         *_primary = (const char *)sysdb_name_el->values[0].data;
    1744           0 :         ret = EOK;
    1745           0 :         goto done;
    1746             :     }
    1747             : 
    1748             :     /* Multiple values for name. Check whether one matches the RDN */
    1749             : 
    1750           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
    1751           0 :     if (ret) {
    1752           0 :         goto done;
    1753             :     }
    1754           0 :     if (orig_dn_el->num_values == 0) {
    1755           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Original DN is not available.\n");
    1756           0 :         ret = EINVAL;
    1757           0 :         goto done;
    1758           0 :     } else if (orig_dn_el->num_values == 1) {
    1759           0 :         ret = sysdb_get_rdn(sysdb, tmp_ctx,
    1760           0 :                             (const char *) orig_dn_el->values[0].data,
    1761             :                             &rdn_attr,
    1762             :                             &rdn_val);
    1763           0 :         if (ret != EOK) {
    1764           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not get rdn from [%s]\n",
    1765             :                       (const char *) orig_dn_el->values[0].data);
    1766           0 :             goto done;
    1767             :         }
    1768             :     } else {
    1769           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Should not have more than one origDN\n");
    1770           0 :         ret = EINVAL;
    1771           0 :         goto done;
    1772             :     }
    1773             : 
    1774             :     /* First check whether the attribute name matches */
    1775           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Comparing attribute names [%s] and [%s]\n",
    1776             :               rdn_attr, ldap_attr);
    1777           0 :     if (strcasecmp(rdn_attr, ldap_attr) != 0) {
    1778             :         /* Multiple entries, and the RDN attribute doesn't match.
    1779             :          * We have no way of resolving this deterministically,
    1780             :          * so we'll use the first value as a fallback.
    1781             :          */
    1782           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    1783             :               "The entry has multiple names and the RDN attribute does "
    1784             :                   "not match. Will use the first value as fallback.\n");
    1785           0 :         *_primary = (const char *)sysdb_name_el->values[0].data;
    1786           0 :         ret = EOK;
    1787           0 :         goto done;
    1788             :     }
    1789             : 
    1790           0 :     for (i = 0; i < sysdb_name_el->num_values; i++) {
    1791           0 :         if (strcasecmp(rdn_val,
    1792           0 :                        (const char *)sysdb_name_el->values[i].data) == 0) {
    1793             :             /* This name matches the RDN. Use it */
    1794           0 :             break;
    1795             :         }
    1796             :     }
    1797           0 :     if (i < sysdb_name_el->num_values) {
    1798             :         /* Match was found */
    1799           0 :         *_primary = (const char *)sysdb_name_el->values[i].data;
    1800             :     } else {
    1801             :         /* If we can't match the name to the RDN, we just have to
    1802             :          * throw up our hands. There's no deterministic way to
    1803             :          * decide which name is correct.
    1804             :          */
    1805           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1806             :               "Cannot save entry. Unable to determine groupname\n");
    1807           0 :         ret = EINVAL;
    1808           0 :         goto done;
    1809             :     }
    1810             : 
    1811           0 :     ret = EOK;
    1812             : 
    1813             : done:
    1814           0 :     if (ret != EOK) {
    1815           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1816             :               "Could not determine primary name: [%d][%s]\n",
    1817             :                   ret, strerror(ret));
    1818             :     }
    1819           0 :     talloc_free(tmp_ctx);
    1820           0 :     return ret;
    1821             : }
    1822             : 
    1823             : /*
    1824             :  * An entity with multiple names would have multiple SYSDB_NAME attributes
    1825             :  * after being translated into sysdb names using a map.
    1826             :  * Given a primary name returned by sysdb_attrs_primary_name(), this function
    1827             :  * returns the other SYSDB_NAME attribute values so they can be saved as
    1828             :  * SYSDB_NAME_ALIAS into cache.
    1829             :  *
    1830             :  * If lowercase is set, all aliases are duplicated in lowercase as well.
    1831             :  */
    1832           0 : errno_t sysdb_attrs_get_aliases(TALLOC_CTX *mem_ctx,
    1833             :                                 struct sysdb_attrs *attrs,
    1834             :                                 const char *primary,
    1835             :                                 bool lowercase,
    1836             :                                 const char ***_aliases)
    1837             : {
    1838           0 :     TALLOC_CTX *tmp_ctx = NULL;
    1839             :     struct ldb_message_element *sysdb_name_el;
    1840             :     size_t i, j, ai;
    1841             :     errno_t ret;
    1842           0 :     const char **aliases = NULL;
    1843             :     const char *name;
    1844             :     char *lower;
    1845             : 
    1846           0 :     if (_aliases == NULL) return EINVAL;
    1847             : 
    1848           0 :     tmp_ctx = talloc_new(NULL);
    1849           0 :     if (!tmp_ctx) {
    1850           0 :         return ENOMEM;
    1851             :     }
    1852             : 
    1853           0 :     ret = sysdb_attrs_get_el(attrs,
    1854             :                              SYSDB_NAME,
    1855             :                              &sysdb_name_el);
    1856           0 :     if (ret != EOK || sysdb_name_el->num_values == 0) {
    1857           0 :         ret = EINVAL;
    1858           0 :         goto done;
    1859             :     }
    1860             : 
    1861           0 :     aliases = talloc_array(tmp_ctx, const char *,
    1862             :                            sysdb_name_el->num_values + 1);
    1863           0 :     if (!aliases) {
    1864           0 :         ret = ENOMEM;
    1865           0 :         goto done;
    1866             :     }
    1867             : 
    1868           0 :     if (lowercase) {
    1869           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    1870             :               "Domain is case-insensitive; will add lowercased aliases\n");
    1871             :     }
    1872             : 
    1873           0 :     ai = 0;
    1874           0 :     for (i=0; i < sysdb_name_el->num_values; i++) {
    1875           0 :         name = (const char *)sysdb_name_el->values[i].data;
    1876             : 
    1877           0 :         if (lowercase) {
    1878             :             /* Domain is case-insensitive. Save the lower-cased version */
    1879           0 :             lower = sss_tc_utf8_str_tolower(tmp_ctx, name);
    1880           0 :             if (!lower) {
    1881           0 :                 ret = ENOMEM;
    1882           0 :                 goto done;
    1883             :             }
    1884             : 
    1885           0 :             for (j=0; j < ai; j++) {
    1886           0 :                 if (sss_utf8_case_eq((const uint8_t *) aliases[j],
    1887             :                                      (const uint8_t *) lower) == ENOMATCH) {
    1888           0 :                     break;
    1889             :                 }
    1890             :             }
    1891             : 
    1892           0 :             if (ai == 0 || j < ai) {
    1893           0 :                 aliases[ai] = talloc_strdup(aliases, lower);
    1894           0 :                 if (!aliases[ai]) {
    1895           0 :                     ret = ENOMEM;
    1896           0 :                     goto done;
    1897             :                 }
    1898           0 :                 ai++;
    1899             :             }
    1900             :         } else {
    1901             :             /* Domain is case-sensitive. Save it as-is */
    1902           0 :             if (strcmp(primary, name) != 0) {
    1903           0 :                 aliases[ai] = talloc_strdup(aliases, name);
    1904           0 :                 if (!aliases[ai]) {
    1905           0 :                     ret = ENOMEM;
    1906           0 :                     goto done;
    1907             :                 }
    1908           0 :                 ai++;
    1909             :             }
    1910             :         }
    1911             :     }
    1912             : 
    1913           0 :     aliases[ai] = NULL;
    1914             : 
    1915           0 :     ret = EOK;
    1916             : 
    1917             : done:
    1918           0 :     *_aliases = talloc_steal(mem_ctx, aliases);
    1919           0 :     talloc_free(tmp_ctx);
    1920           0 :     return ret;
    1921             : }
    1922             : 
    1923           0 : errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
    1924             :                                       TALLOC_CTX *mem_ctx,
    1925             :                                       struct sysdb_attrs **attr_list,
    1926             :                                       size_t attr_count,
    1927             :                                       const char *ldap_attr,
    1928             :                                       char ***name_list)
    1929             : {
    1930             :     errno_t ret;
    1931             :     size_t i, j;
    1932             :     char **list;
    1933             :     const char *name;
    1934             : 
    1935             :     /* Assume that every entry has a primary name */
    1936           0 :     list = talloc_array(mem_ctx, char *, attr_count+1);
    1937           0 :     if (!list) {
    1938           0 :         return ENOMEM;
    1939             :     }
    1940             : 
    1941           0 :     j = 0;
    1942           0 :     for (i = 0; i < attr_count; i++) {
    1943           0 :         ret = sysdb_attrs_primary_name(sysdb,
    1944           0 :                                        attr_list[i],
    1945             :                                        ldap_attr,
    1946             :                                        &name);
    1947           0 :         if (ret != EOK) {
    1948           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not determine primary name\n");
    1949             :             /* Skip and continue. Don't advance 'j' */
    1950           0 :             continue;
    1951             :         }
    1952             : 
    1953           0 :         list[j] = talloc_strdup(list, name);
    1954           0 :         if (!list[j]) {
    1955           0 :             ret = ENOMEM;
    1956           0 :             goto done;
    1957             :         }
    1958             : 
    1959           0 :         j++;
    1960             :     }
    1961             : 
    1962             :     /* NULL-terminate the list */
    1963           0 :     list[j] = NULL;
    1964             : 
    1965           0 :     *name_list = list;
    1966             : 
    1967           0 :     ret = EOK;
    1968             : 
    1969             : done:
    1970           0 :     if (ret != EOK) {
    1971           0 :         talloc_free(list);
    1972             :     }
    1973           0 :     return ret;
    1974             : }
    1975             : 
    1976           0 : errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count,
    1977             :                         struct ldb_message **msgs,
    1978             :                         struct sysdb_attrs ***attrs)
    1979             : {
    1980             :     int i;
    1981             :     struct sysdb_attrs **a;
    1982             : 
    1983           0 :     a = talloc_array(mem_ctx, struct sysdb_attrs *, count);
    1984           0 :     if (a == NULL) {
    1985           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
    1986           0 :         return ENOMEM;
    1987             :     }
    1988             : 
    1989           0 :     for (i = 0; i < count; i++) {
    1990           0 :         a[i] = talloc(a, struct sysdb_attrs);
    1991           0 :         if (a[i] == NULL) {
    1992           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
    1993           0 :             talloc_free(a);
    1994           0 :             return ENOMEM;
    1995             :         }
    1996           0 :         a[i]->num = msgs[i]->num_elements;
    1997           0 :         a[i]->a = talloc_steal(a[i], msgs[i]->elements);
    1998             :     }
    1999             : 
    2000           0 :     *attrs = a;
    2001             : 
    2002           0 :     return EOK;
    2003             : }

Generated by: LCOV version 1.10