LCOV - code coverage report
Current view: top level - providers/ldap - sdap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 347 777 44.7 %
Date: 2016-06-29 Functions: 19 35 54.3 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     LDAP Helper routines
       5             : 
       6             :     Copyright (C) Simo Sorce <ssorce@redhat.com>
       7             : 
       8             :     This program is free software; you can redistribute it and/or modify
       9             :     it under the terms of the GNU General Public License as published by
      10             :     the Free Software Foundation; either version 3 of the License, or
      11             :     (at your option) any later version.
      12             : 
      13             :     This program is distributed in the hope that it will be useful,
      14             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :     GNU General Public License for more details.
      17             : 
      18             :     You should have received a copy of the GNU General Public License
      19             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "util/util.h"
      23             : #include "util/crypto/sss_crypto.h"
      24             : #include "confdb/confdb.h"
      25             : #include "providers/ldap/ldap_common.h"
      26             : #include "providers/ldap/sdap.h"
      27             : #include "providers/ldap/sdap_range.h"
      28             : 
      29             : /* =Retrieve-Options====================================================== */
      30             : 
      31           3 : errno_t sdap_copy_map_entry(const struct sdap_attr_map *src_map,
      32             :                             struct sdap_attr_map *dst_map,
      33             :                             int entry_index)
      34             : {
      35           3 :     if (src_map[entry_index].name != NULL) {
      36           4 :         dst_map[entry_index].name = talloc_strdup(dst_map,
      37           2 :                                                   src_map[entry_index].name);
      38           2 :         if (dst_map[entry_index].name == NULL) {
      39           0 :             return ENOMEM;
      40             :         }
      41             :     } else {
      42           1 :         dst_map->name = NULL;
      43             :     }
      44             : 
      45           3 :     return EOK;
      46             : }
      47             : 
      48          43 : int sdap_copy_map(TALLOC_CTX *memctx,
      49             :                  struct sdap_attr_map *src_map,
      50             :                  int num_entries,
      51             :                  struct sdap_attr_map **_map)
      52             : {
      53             :     struct sdap_attr_map *map;
      54             :     int i;
      55             : 
      56          43 :     map = talloc_array(memctx, struct sdap_attr_map, num_entries + 1);
      57          43 :     if (!map) {
      58           0 :         return ENOMEM;
      59             :     }
      60             : 
      61        1460 :     for (i = 0; i < num_entries; i++) {
      62        1417 :         map[i].opt_name = talloc_strdup(map, src_map[i].opt_name);
      63        1417 :         map[i].sys_name = talloc_strdup(map, src_map[i].sys_name);
      64        1417 :         if (map[i].opt_name == NULL || map[i].sys_name == NULL) {
      65           0 :             return ENOMEM;
      66             :         }
      67             : 
      68        1417 :         if (src_map[i].def_name != NULL) {
      69        1165 :             map[i].def_name = talloc_strdup(map, src_map[i].def_name);
      70        1165 :             map[i].name = talloc_strdup(map, src_map[i].def_name);
      71        1165 :             if (map[i].def_name == NULL || map[i].name == NULL) {
      72           0 :                 return ENOMEM;
      73             :             }
      74             :         } else {
      75         252 :             map[i].def_name = NULL;
      76         252 :             map[i].name = NULL;
      77             :         }
      78             : 
      79        1417 :         DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
      80             :               map[i].opt_name, map[i].name ? "" : " no",
      81             :               map[i].name ? map[i].name : "");
      82             :     }
      83             : 
      84             :     /* Include the sentinel */
      85          43 :     memset(&map[num_entries], 0, sizeof(struct sdap_attr_map));
      86             : 
      87          43 :     *_map = map;
      88          43 :     return EOK;
      89             : }
      90             : 
      91           5 : static errno_t split_extra_attr(TALLOC_CTX *mem_ctx,
      92             :                                 char *conf_attr,
      93             :                                 char **_sysdb_attr,
      94             :                                 char **_ldap_attr)
      95             : {
      96             :     char *ldap_attr;
      97             :     char *sysdb_attr;
      98             :     char *sep;
      99             : 
     100           5 :     ldap_attr = conf_attr;
     101             : 
     102           5 :     sep = strchr(conf_attr, ':');
     103           5 :     if (sep == NULL) {
     104           1 :         sysdb_attr = talloc_strdup(mem_ctx, conf_attr);
     105           1 :         ldap_attr = talloc_strdup(mem_ctx, conf_attr);
     106             :     } else {
     107           4 :         if (sep == conf_attr || *(sep + 1) == '\0') {
     108           2 :             return ERR_INVALID_EXTRA_ATTR;
     109             :         }
     110             : 
     111           2 :         sysdb_attr = talloc_strndup(mem_ctx, ldap_attr,
     112           2 :                                     sep - ldap_attr);
     113           2 :         ldap_attr = talloc_strdup(mem_ctx, sep+1);
     114             :     }
     115             : 
     116           3 :     if (sysdb_attr == NULL || ldap_attr == NULL) {
     117           0 :         return ENOMEM;
     118             :     }
     119             : 
     120           3 :     *_sysdb_attr = sysdb_attr;
     121           3 :     *_ldap_attr = ldap_attr;
     122           3 :     return EOK;
     123             : }
     124             : 
     125           3 : static bool is_sysdb_duplicate(struct sdap_attr_map *map,
     126             :                                int num_entries,
     127             :                                const char *sysdb_attr)
     128             : {
     129             :     int i;
     130             : 
     131          78 :     for (i = 0; i < num_entries; i++) {
     132          76 :         if (strcmp(map[i].sys_name, sysdb_attr) == 0) {
     133           1 :             return true;
     134             :         }
     135             :     }
     136             : 
     137           2 :     return false;
     138             : }
     139             : 
     140           4 : int sdap_extend_map(TALLOC_CTX *memctx,
     141             :                     struct sdap_attr_map *src_map,
     142             :                     size_t num_entries,
     143             :                     char **extra_attrs,
     144             :                     struct sdap_attr_map **_map,
     145             :                     size_t *_new_size)
     146             : {
     147             :     struct sdap_attr_map *map;
     148           4 :     size_t nextra = 0;
     149             :     size_t i;
     150             :     char *ldap_attr;
     151             :     char *sysdb_attr;
     152             :     errno_t ret;
     153             : 
     154           4 :     if (extra_attrs == NULL) {
     155           1 :         DEBUG(SSSDBG_FUNC_DATA, "No extra attributes\n");
     156           1 :         *_map = src_map;
     157           1 :         *_new_size = num_entries;
     158           1 :         return EOK;
     159             :     }
     160             : 
     161           3 :     for (nextra = 0; extra_attrs[nextra]; nextra++) ;
     162           3 :     DEBUG(SSSDBG_FUNC_DATA, "%zu extra attributes\n", nextra);
     163             : 
     164           3 :     map = talloc_realloc(memctx, src_map, struct sdap_attr_map,
     165             :                          num_entries + nextra + 1);
     166           3 :     if (map == NULL) {
     167           0 :         return ENOMEM;
     168             :     }
     169             : 
     170           7 :     for (i = 0; extra_attrs[i]; i++) {
     171           5 :         ret = split_extra_attr(map, extra_attrs[i], &sysdb_attr, &ldap_attr);
     172           5 :         if (ret != EOK) {
     173           2 :             DEBUG(SSSDBG_MINOR_FAILURE, "Cannot split %s\n", extra_attrs[i]);
     174           2 :             continue;
     175             :         }
     176             : 
     177           3 :         if (is_sysdb_duplicate(map, num_entries, sysdb_attr)) {
     178           1 :             DEBUG(SSSDBG_FATAL_FAILURE,
     179             :                   "Attribute %s (%s in LDAP) is already used by SSSD, please "
     180             :                   "choose a different cache name\n", sysdb_attr, ldap_attr);
     181           1 :             return ERR_DUP_EXTRA_ATTR;
     182             :         }
     183             : 
     184           2 :         map[num_entries+i].name = ldap_attr;
     185           2 :         map[num_entries+i].sys_name = sysdb_attr;
     186           4 :         map[num_entries+i].opt_name = talloc_strdup(map,
     187           2 :                                                 map[num_entries+i].name);
     188           4 :         map[num_entries+i].def_name = talloc_strdup(map,
     189           2 :                                                 map[num_entries+i].name);
     190           4 :         if (map[num_entries+i].opt_name == NULL ||
     191           4 :             map[num_entries+i].sys_name == NULL ||
     192           4 :             map[num_entries+i].name == NULL ||
     193           2 :             map[num_entries+i].def_name == NULL) {
     194           0 :             return ENOMEM;
     195             :         }
     196           2 :         DEBUG(SSSDBG_TRACE_FUNC, "Extending map with %s\n", extra_attrs[i]);
     197             :     }
     198             : 
     199             :     /* Sentinel */
     200           2 :     memset(&map[num_entries+nextra], 0, sizeof(struct sdap_attr_map));
     201             : 
     202           2 :     *_map = map;
     203           2 :     *_new_size = num_entries + nextra;
     204           2 :     return EOK;
     205             : }
     206             : 
     207           9 : int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
     208             :                               struct sdap_options *opts,
     209             :                               int extra_attr_index,
     210             :                               struct sdap_attr_map *src_map,
     211             :                               size_t num_entries,
     212             :                               struct sdap_attr_map **_map,
     213             :                               size_t *_new_size)
     214             : {
     215             :     const char *extra_attrs;
     216             :     char **extra_attrs_list;
     217             :     errno_t ret;
     218             : 
     219           9 :     extra_attrs = dp_opt_get_string(opts->basic, extra_attr_index);
     220           9 :     if (extra_attrs == NULL) {
     221           9 :         *_map = src_map;
     222           9 :         *_new_size = num_entries;
     223           9 :         return EOK;
     224             :     }
     225             : 
     226             :     /* split server parm into a list */
     227           0 :     ret = split_on_separator(mem_ctx, extra_attrs, ',', true, true,
     228             :                              &extra_attrs_list, NULL);
     229           0 :     if (ret != EOK) {
     230           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to parse server list!\n");
     231           0 :         return ret;
     232             :     }
     233             : 
     234             : 
     235           0 :     ret = sdap_extend_map(mem_ctx, src_map,
     236             :                           num_entries, extra_attrs_list,
     237             :                           _map, _new_size);
     238           0 :     talloc_free(extra_attrs_list);
     239           0 :     if (ret != EOK) {
     240           0 :         return ret;
     241             :     }
     242             : 
     243           0 :     return EOK;
     244             : }
     245             : 
     246           4 : static void sdap_inherit_basic_options(char **inherit_opt_list,
     247             :                                        struct dp_option *parent_opts,
     248             :                                        struct dp_option *subdom_opts)
     249             : {
     250           4 :     int inherit_options[] = {
     251             :         SDAP_PURGE_CACHE_TIMEOUT,
     252             :         SDAP_AD_USE_TOKENGROUPS,
     253             :         SDAP_KRB5_KEYTAB,
     254             :         SDAP_OPTS_BASIC     /* sentinel */
     255             :     };
     256             :     int i;
     257             : 
     258          16 :     for (i = 0; inherit_options[i] != SDAP_OPTS_BASIC; i++) {
     259          12 :         dp_option_inherit(inherit_opt_list,
     260             :                           inherit_options[i],
     261             :                           parent_opts,
     262             :                           subdom_opts);
     263             :     }
     264           4 : }
     265             : 
     266           4 : static void sdap_inherit_user_options(char **inherit_opt_list,
     267             :                                       struct sdap_attr_map *parent_user_map,
     268             :                                       struct sdap_attr_map *child_user_map)
     269             : {
     270           4 :     int inherit_options[] = {
     271             :         SDAP_AT_USER_PRINC,
     272             :         SDAP_OPTS_USER          /* sentinel */
     273             :     };
     274             :     int i;
     275             :     int opt_index;
     276             :     bool inherit_option;
     277             : 
     278           8 :     for (i = 0; inherit_options[i] != SDAP_OPTS_USER; i++) {
     279           4 :         opt_index = inherit_options[i];
     280             : 
     281           4 :         inherit_option = string_in_list(parent_user_map[opt_index].opt_name,
     282             :                                         inherit_opt_list,
     283             :                                         false);
     284           4 :         if (inherit_option == false) {
     285           3 :             continue;
     286             :         }
     287             : 
     288           1 :         sdap_copy_map_entry(parent_user_map, child_user_map, opt_index);
     289             :     }
     290           4 : }
     291             : 
     292           4 : void sdap_inherit_options(char **inherit_opt_list,
     293             :                           struct sdap_options *parent_sdap_opts,
     294             :                           struct sdap_options *child_sdap_opts)
     295             : {
     296           4 :     sdap_inherit_basic_options(inherit_opt_list,
     297             :                                parent_sdap_opts->basic,
     298             :                                child_sdap_opts->basic);
     299             : 
     300           4 :     sdap_inherit_user_options(inherit_opt_list,
     301             :                               parent_sdap_opts->user_map,
     302             :                               child_sdap_opts->user_map);
     303           4 : }
     304             : 
     305          45 : int sdap_get_map(TALLOC_CTX *memctx,
     306             :                  struct confdb_ctx *cdb,
     307             :                  const char *conf_path,
     308             :                  struct sdap_attr_map *def_map,
     309             :                  int num_entries,
     310             :                  struct sdap_attr_map **_map)
     311             : {
     312             :     struct sdap_attr_map *map;
     313             :     char *name;
     314             :     int i, ret;
     315             : 
     316          45 :     map = talloc_zero_array(memctx, struct sdap_attr_map, num_entries + 1);
     317          45 :     if (!map) {
     318           0 :         return ENOMEM;
     319             :     }
     320             : 
     321         594 :     for (i = 0; i < num_entries; i++) {
     322             : 
     323         549 :         map[i].opt_name = def_map[i].opt_name;
     324         549 :         map[i].def_name = def_map[i].def_name;
     325         549 :         map[i].sys_name = def_map[i].sys_name;
     326             : 
     327        1098 :         ret = confdb_get_string(cdb, map, conf_path,
     328         549 :                                 map[i].opt_name,
     329         549 :                                 map[i].def_name,
     330             :                                 &name);
     331         549 :         if (ret != EOK) {
     332           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     333             :                   "Failed to retrieve value for %s\n", map[i].opt_name);
     334           0 :             talloc_zfree(map);
     335           0 :             return EINVAL;
     336             :         }
     337             : 
     338         549 :         if (name) {
     339         414 :             ret = sss_filter_sanitize(map, name, &map[i].name);
     340         414 :             if (ret != EOK) {
     341           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     342             :                       "Could not sanitize attribute [%s]\n", name);
     343           0 :                 talloc_zfree(map);
     344           0 :                 return EINVAL;
     345             :             }
     346         414 :             talloc_zfree(name);
     347             :         } else {
     348         135 :             map[i].name = NULL;
     349             :         }
     350             : 
     351         549 :         if (map[i].def_name && !map[i].name) {
     352           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     353             :                   "Failed to retrieve value for %s\n", map[i].opt_name);
     354           0 :             talloc_zfree(map);
     355           0 :             return EINVAL;
     356             :         }
     357             : 
     358         549 :         DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
     359             :               map[i].opt_name, map[i].name ? "" : " no",
     360             :               map[i].name ? map[i].name : "");
     361             :     }
     362             : 
     363          45 :     *_map = map;
     364          45 :     return EOK;
     365             : }
     366             : 
     367             : /* =Parse-msg============================================================= */
     368             : 
     369             : static bool objectclass_matched(struct sdap_attr_map *map,
     370             :                                 const char *objcl, int len);
     371           8 : int sdap_parse_entry(TALLOC_CTX *memctx,
     372             :                      struct sdap_handle *sh, struct sdap_msg *sm,
     373             :                      struct sdap_attr_map *map, int attrs_num,
     374             :                      struct sysdb_attrs **_attrs,
     375             :                      bool disable_range_retrieval)
     376             : {
     377             :     struct sysdb_attrs *attrs;
     378           8 :     BerElement *ber = NULL;
     379             :     struct berval **vals;
     380             :     struct ldb_val v;
     381             :     char *str;
     382             :     int lerrno;
     383             :     int i, ret, ai;
     384           8 :     int base_attr_idx = 0;
     385             :     const char *name;
     386             :     bool store;
     387             :     bool base64;
     388             :     char *base_attr;
     389             :     uint32_t range_offset;
     390           8 :     TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     391           8 :     if (!tmp_ctx) return ENOMEM;
     392             : 
     393           8 :     lerrno = 0;
     394           8 :     ret = ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
     395           8 :     if (ret != LDAP_OPT_SUCCESS) {
     396           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "ldap_set_option failed [%s], ignored.\n",
     397             :               sss_ldap_err2string(ret));
     398             :     }
     399             : 
     400           8 :     attrs = sysdb_new_attrs(tmp_ctx);
     401           8 :     if (!attrs) {
     402           0 :         ret = ENOMEM;
     403           0 :         goto done;
     404             :     }
     405             : 
     406           8 :     str = ldap_get_dn(sh->ldap, sm->msg);
     407           8 :     if (!str) {
     408           1 :         ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
     409           1 :         DEBUG(SSSDBG_CRIT_FAILURE, "ldap_get_dn failed: %d(%s)\n",
     410             :               lerrno, sss_ldap_err2string(lerrno));
     411           1 :         ret = EIO;
     412           1 :         goto done;
     413             :     }
     414             : 
     415           7 :     DEBUG(SSSDBG_TRACE_LIBS, "OriginalDN: [%s].\n", str);
     416           7 :     ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str);
     417           7 :     ldap_memfree(str);
     418           7 :     if (ret) goto done;
     419             : 
     420           7 :     if (map) {
     421           6 :         vals = ldap_get_values_len(sh->ldap, sm->msg, "objectClass");
     422           6 :         if (!vals) {
     423           1 :             DEBUG(SSSDBG_CRIT_FAILURE,
     424             :                   "Unknown entry type, no objectClasses found!\n");
     425           1 :             ret = EINVAL;
     426           1 :             goto done;
     427             :         }
     428             : 
     429           6 :         for (i = 0; vals[i]; i++) {
     430           5 :             if (objectclass_matched(map, vals[i]->bv_val, vals[i]->bv_len)) {
     431             :                 /* ok it's an entry of the right type */
     432           4 :                 break;
     433             :             }
     434             :         }
     435           5 :         if (!vals[i]) {
     436           1 :             DEBUG(SSSDBG_CRIT_FAILURE, "objectClass not matching: %s\n",
     437             :                   map[0].name);
     438           1 :             ldap_value_free_len(vals);
     439           1 :             ret = EINVAL;
     440           1 :             goto done;
     441             :         }
     442           4 :         ldap_value_free_len(vals);
     443             :     }
     444             : 
     445           5 :     str = ldap_first_attribute(sh->ldap, sm->msg, &ber);
     446           5 :     if (!str) {
     447           0 :         ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
     448           0 :         DEBUG(lerrno == LDAP_SUCCESS
     449             :               ? SSSDBG_TRACE_LIBS
     450             :               : SSSDBG_MINOR_FAILURE,
     451             :               "Entry has no attributes [%d(%s)]!?\n",
     452             :                lerrno, sss_ldap_err2string(lerrno));
     453           0 :         if (map) {
     454           0 :             ret = EINVAL;
     455           0 :             goto done;
     456             :         }
     457             :     }
     458          22 :     while (str) {
     459          12 :         base64 = false;
     460             : 
     461          12 :         ret = sdap_parse_range(tmp_ctx, str, &base_attr, &range_offset,
     462             :                                disable_range_retrieval);
     463          12 :         switch(ret) {
     464             :         case EAGAIN:
     465             :             /* This attribute contained range values and needs more to
     466             :              * be retrieved
     467             :              */
     468             :             /* TODO: return the set of attributes that need additional retrieval
     469             :              * For now, we'll continue below and treat it as regular values.
     470             :              */
     471             :             /* FALLTHROUGH */
     472             :         case ECANCELED:
     473             :             /* FALLTHROUGH */
     474             :         case EOK:
     475          12 :             break;
     476             :         default:
     477           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     478             :                   "Could not determine if attribute [%s] was ranged\n", str);
     479           0 :             goto done;
     480             :         }
     481             : 
     482          12 :         if (map) {
     483         236 :             for (i = 1; i < attrs_num; i++) {
     484             :                 /* check if this attr is valid with the chosen schema */
     485         230 :                 if (!map[i].name) continue;
     486             :                 /* check if it is an attr we are interested in */
     487         198 :                 if (strcasecmp(base_attr, map[i].name) == 0) break;
     488             :             }
     489             :             /* interesting attr */
     490          10 :             if (i < attrs_num) {
     491           4 :                 store = true;
     492           4 :                 name = map[i].sys_name;
     493           4 :                 base_attr_idx = i;
     494           4 :                 if (strcmp(name, SYSDB_SSH_PUBKEY) == 0) {
     495           1 :                     base64 = true;
     496             :                 }
     497             :             } else {
     498           6 :                 store = false;
     499           6 :                 name = NULL;
     500             :             }
     501             :         } else {
     502           2 :             name = base_attr;
     503           2 :             store = true;
     504             :         }
     505             : 
     506          12 :         if (ret == ECANCELED) {
     507           0 :             ret = EOK;
     508           0 :             store = false;
     509             :         }
     510             : 
     511          12 :         if (store) {
     512           6 :             vals = ldap_get_values_len(sh->ldap, sm->msg, str);
     513           6 :             if (!vals) {
     514           0 :                 ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
     515           0 :                 if (lerrno != LDAP_SUCCESS) {
     516           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "LDAP Library error: %d(%s)\n",
     517             :                           lerrno, sss_ldap_err2string(lerrno));
     518           0 :                     ret = EIO;
     519           0 :                     goto done;
     520             :                 }
     521             : 
     522           0 :                 DEBUG(SSSDBG_TRACE_LIBS,
     523             :                       "Attribute [%s] has no values, skipping.\n", str);
     524             : 
     525             :             } else {
     526           6 :                 if (!vals[0]) {
     527           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     528             :                           "Missing value after ldap_get_values() ??\n");
     529           0 :                     ldap_value_free_len(vals);
     530           0 :                     ret = EINVAL;
     531           0 :                     goto done;
     532             :                 }
     533          14 :                 for (i = 0; vals[i]; i++) {
     534           8 :                     if (vals[i]->bv_len == 0) {
     535           0 :                         DEBUG(SSSDBG_TRACE_LIBS,
     536             :                               "Value of attribute [%s] is empty. "
     537             :                                "Skipping this value.\n", str);
     538           0 :                         continue;
     539             :                     }
     540           8 :                     if (base64) {
     541           2 :                         v.data = (uint8_t *) sss_base64_encode(attrs,
     542           2 :                                  (uint8_t *) vals[i]->bv_val, vals[i]->bv_len);
     543           1 :                         if (!v.data) {
     544           0 :                             ldap_value_free_len(vals);
     545           0 :                             ret = ENOMEM;
     546           0 :                             goto done;
     547             :                         }
     548           1 :                         v.length = strlen((const char *)v.data);
     549             :                     } else {
     550           7 :                         v.data = (uint8_t *)vals[i]->bv_val;
     551           7 :                         v.length = vals[i]->bv_len;
     552             :                     }
     553             : 
     554           8 :                     if (map) {
     555             :                         /* The same LDAP attr might be used for more sysdb
     556             :                          * attrs in case there is a map. Find all that match
     557             :                          * and copy the value
     558             :                          */
     559         100 :                         for (ai = base_attr_idx; ai < attrs_num; ai++) {
     560             :                             /* check if this attr is valid with the chosen
     561             :                              * schema */
     562          95 :                             if (!map[ai].name) continue;
     563             : 
     564             :                             /* check if it is an attr we are interested in */
     565          86 :                             if (strcasecmp(base_attr, map[ai].name) == 0) {
     566           6 :                                 ret = sysdb_attrs_add_val(attrs,
     567           6 :                                                           map[ai].sys_name,
     568             :                                                           &v);
     569           6 :                                 if (ret) {
     570           0 :                                     ldap_value_free_len(vals);
     571           0 :                                     goto done;
     572             :                                 }
     573             :                             }
     574             :                         }
     575             :                     } else {
     576             :                         /* No map, just store the attribute */
     577           3 :                         ret = sysdb_attrs_add_val(attrs, name, &v);
     578           3 :                         if (ret) {
     579           0 :                             ldap_value_free_len(vals);
     580           0 :                             goto done;
     581             :                         }
     582             :                     }
     583             :                 }
     584           6 :                 ldap_value_free_len(vals);
     585             :             }
     586             :         }
     587             : 
     588          12 :         ldap_memfree(str);
     589          12 :         str = ldap_next_attribute(sh->ldap, sm->msg, ber);
     590             :     }
     591           5 :     ber_free(ber, 0);
     592           5 :     ber = NULL;
     593             : 
     594           5 :     ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
     595           5 :     if (lerrno) {
     596           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "LDAP Library error: %d(%s)\n",
     597             :               lerrno, sss_ldap_err2string(lerrno));
     598           0 :         ret = EIO;
     599           0 :         goto done;
     600             :     }
     601             : 
     602           5 :     *_attrs = talloc_steal(memctx, attrs);
     603           5 :     ret = EOK;
     604             : 
     605             : done:
     606           8 :     if (ber) ber_free(ber, 0);
     607           8 :     talloc_free(tmp_ctx);
     608           8 :     return ret;
     609             : }
     610             : 
     611           7 : static bool objectclass_matched(struct sdap_attr_map *map,
     612             :                                 const char *objcl, int len)
     613             : {
     614           7 :     if (len == 0) {
     615           2 :         len = strlen(objcl) + 1;
     616             :     }
     617             : 
     618           7 :     if (strncasecmp(map[SDAP_OC_GROUP].name, objcl, len) == 0) {
     619           4 :         return true;
     620             :     }
     621             : 
     622           3 :     if (map[SDAP_OC_GROUP_ALT].name != NULL
     623           2 :         && strncasecmp(map[SDAP_OC_GROUP_ALT].name, objcl, len) == 0) {
     624           1 :         return true;
     625             :     }
     626             : 
     627           2 :     return false;
     628             : }
     629             : 
     630             : /* Parses an LDAPDerefRes into sdap_deref_attrs structure */
     631           3 : errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx,
     632             :                          struct sdap_attr_map_info *minfo,
     633             :                          size_t num_maps,
     634             :                          LDAPDerefRes *dref,
     635             :                          struct sdap_deref_attrs ***_deref_res)
     636             : {
     637             :     TALLOC_CTX *tmp_ctx;
     638             :     LDAPDerefVal *dval;
     639             :     const char *orig_dn;
     640             :     const char **ocs;
     641             :     struct sdap_attr_map *map;
     642             :     int num_attrs;
     643             :     int ret, i, a, mi;
     644             :     const char *name;
     645             :     size_t len;
     646             :     struct sdap_deref_attrs **res;
     647             : 
     648           3 :     if (!dref || !minfo) return EINVAL;
     649             : 
     650           3 :     tmp_ctx = talloc_new(NULL);
     651           3 :     if (!tmp_ctx) return ENOMEM;
     652             : 
     653           3 :     res = talloc_array(tmp_ctx, struct sdap_deref_attrs *, num_maps);
     654           3 :     if (!res) {
     655           0 :         ret = ENOMEM;
     656           0 :         goto done;
     657             :     }
     658             : 
     659           6 :     for (i=0; i < num_maps; i++) {
     660           3 :         res[i] = talloc_zero(res, struct sdap_deref_attrs);
     661           3 :         if (!res[i]) {
     662           0 :             ret = ENOMEM;
     663           0 :             goto done;
     664             :         }
     665             : 
     666           3 :         res[i]->map = minfo[i].map;
     667             :     }
     668             : 
     669           3 :     if (!dref->derefVal.bv_val) {
     670           0 :         DEBUG(SSSDBG_OP_FAILURE, "Entry has no DN?\n");
     671           0 :         ret = EINVAL;
     672           0 :         goto done;
     673             :     }
     674             : 
     675           3 :     orig_dn = dref->derefVal.bv_val;
     676           3 :     DEBUG(SSSDBG_TRACE_LIBS,
     677             :           "Dereferenced DN: %s\n", orig_dn);
     678             : 
     679           3 :     if (!dref->attrVals) {
     680           1 :         DEBUG(SSSDBG_FUNC_DATA,
     681             :               "Dereferenced entry [%s] has no attributes, skipping\n",
     682             :               orig_dn);
     683           1 :         *_deref_res = NULL;
     684           1 :         ret = EOK;
     685           1 :         goto done;
     686             :     }
     687             : 
     688           2 :     ocs = NULL;
     689           2 :     for (dval = dref->attrVals; dval != NULL; dval = dval->next) {
     690           2 :         if (strcasecmp("objectClass", dval->type) == 0) {
     691           2 :             if (dval->vals == NULL) {
     692           0 :                 DEBUG(SSSDBG_CONF_SETTINGS,
     693             :                       "No value for objectClass, skipping\n");
     694           0 :                 continue;
     695             :             }
     696             : 
     697           2 :             for(len=0; dval->vals[len].bv_val; len++);
     698             : 
     699           2 :             ocs = talloc_array(tmp_ctx, const char *, len+1);
     700           2 :             if (!ocs) {
     701           0 :                 ret = ENOMEM;
     702           0 :                 goto done;
     703             :             }
     704             : 
     705           4 :             for (i=0; i<len; i++) {
     706           2 :                 DEBUG(SSSDBG_TRACE_ALL, "Dereferenced objectClass value: %s\n",
     707             :                           dval->vals[i].bv_val);
     708           2 :                 ocs[i] = talloc_strdup(ocs, dval->vals[i].bv_val);
     709           2 :                 if (!ocs[i]) {
     710           0 :                     ret = ENOMEM;
     711           0 :                     goto done;
     712             :                 }
     713             :             }
     714           2 :             ocs[i] = NULL;
     715           2 :             break;
     716             :         }
     717             :     }
     718           2 :     if (!ocs) {
     719           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     720             :               "Unknown entry type, no objectClasses found!\n");
     721           0 :         ret = EINVAL;
     722           0 :         goto done;
     723             :     }
     724             : 
     725           4 :     for (mi = 0; mi < num_maps; mi++) {
     726           2 :         map = NULL;
     727             : 
     728           3 :         for (i=0; ocs[i]; i++) {
     729             :             /* the objectclass is always the first name in the map */
     730           2 :             if (objectclass_matched(minfo[mi].map, ocs[i], 0)) {
     731           1 :                 DEBUG(SSSDBG_TRACE_ALL,
     732             :                       "Found map for objectclass '%s'\n", ocs[i]);
     733           1 :                 map = minfo[mi].map;
     734           1 :                 num_attrs = minfo[mi].num_attrs;
     735           1 :                 break;
     736             :             }
     737             :         }
     738           2 :         if (!map) continue;
     739             : 
     740           1 :         res[mi]->attrs = sysdb_new_attrs(res[mi]);
     741           1 :         if (!res[mi]->attrs) {
     742           0 :             ret = ENOMEM;
     743           0 :             goto done;
     744             :         }
     745             : 
     746           1 :         ret = sysdb_attrs_add_string(res[mi]->attrs, SYSDB_ORIG_DN,
     747             :                                      orig_dn);
     748           1 :         if (ret) {
     749           0 :             goto done;
     750             :         }
     751             : 
     752           4 :         for (dval = dref->attrVals; dval != NULL; dval = dval->next) {
     753           3 :             DEBUG(SSSDBG_TRACE_INTERNAL,
     754             :                   "Dereferenced attribute: %s\n", dval->type);
     755             : 
     756          75 :             for (a = 1; a < num_attrs; a++) {
     757             :                 /* check if this attr is valid with the chosen schema */
     758          73 :                 if (!map[a].name) continue;
     759             :                 /* check if it is an attr we are interested in */
     760          59 :                 if (strcasecmp(dval->type, map[a].name) == 0) break;
     761             :             }
     762             : 
     763             :             /* interesting attr */
     764           3 :             if (a < num_attrs) {
     765           1 :                 name = map[a].sys_name;
     766             :             } else {
     767           2 :                 continue;
     768             :             }
     769             : 
     770           1 :             if (dval->vals == NULL) {
     771           0 :                 DEBUG(SSSDBG_CONF_SETTINGS,
     772             :                       "No value for attribute %s, skipping\n", name);
     773           0 :                 continue;
     774             :             }
     775             : 
     776           2 :             for (i=0; dval->vals[i].bv_val; i++) {
     777           1 :                 DEBUG(SSSDBG_TRACE_ALL, "Dereferenced attribute value: %s\n",
     778             :                           dval->vals[i].bv_val);
     779           2 :                 ret = sysdb_attrs_add_mem(res[mi]->attrs, name,
     780           1 :                                           dval->vals[i].bv_val,
     781           1 :                                           dval->vals[i].bv_len);
     782           1 :                 if (ret) goto done;
     783             :             }
     784             :         }
     785             :     }
     786             : 
     787             : 
     788           2 :     *_deref_res = talloc_steal(mem_ctx, res);
     789           2 :     ret = EOK;
     790             : done:
     791           3 :     talloc_zfree(tmp_ctx);
     792           3 :     return ret;
     793             : }
     794             : 
     795           0 : errno_t setup_tls_config(struct dp_option *basic_opts)
     796             : {
     797             :     int ret;
     798             :     int ldap_opt_x_tls_require_cert;
     799             :     const char *tls_opt;
     800           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_REQCERT);
     801           0 :     if (tls_opt) {
     802           0 :         if (strcasecmp(tls_opt, "never") == 0) {
     803           0 :             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_NEVER;
     804             :         }
     805           0 :         else if (strcasecmp(tls_opt, "allow") == 0) {
     806           0 :             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_ALLOW;
     807             :         }
     808           0 :         else if (strcasecmp(tls_opt, "try") == 0) {
     809           0 :             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_TRY;
     810             :         }
     811           0 :         else if (strcasecmp(tls_opt, "demand") == 0) {
     812           0 :             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_DEMAND;
     813             :         }
     814           0 :         else if (strcasecmp(tls_opt, "hard") == 0) {
     815           0 :             ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_HARD;
     816             :         }
     817             :         else {
     818           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown value for tls_reqcert.\n");
     819           0 :             return EINVAL;
     820             :         }
     821             :         /* LDAP_OPT_X_TLS_REQUIRE_CERT has to be set as a global option,
     822             :          * because the SSL/TLS context is initialized from this value. */
     823           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
     824             :                               &ldap_opt_x_tls_require_cert);
     825           0 :         if (ret != LDAP_OPT_SUCCESS) {
     826           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     827             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     828           0 :             return EIO;
     829             :         }
     830             :     }
     831             : 
     832           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERT);
     833           0 :     if (tls_opt) {
     834           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_opt);
     835           0 :         if (ret != LDAP_OPT_SUCCESS) {
     836           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     837             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     838           0 :             return EIO;
     839             :         }
     840             :     }
     841             : 
     842           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERTDIR);
     843           0 :     if (tls_opt) {
     844           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, tls_opt);
     845           0 :         if (ret != LDAP_OPT_SUCCESS) {
     846           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     847             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     848           0 :             return EIO;
     849             :         }
     850             :     }
     851             : 
     852           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CERT);
     853           0 :     if (tls_opt) {
     854           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, tls_opt);
     855           0 :         if (ret != LDAP_OPT_SUCCESS) {
     856           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     857             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     858           0 :             return EIO;
     859             :         }
     860             :     }
     861             : 
     862           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_KEY);
     863           0 :     if (tls_opt) {
     864           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE, tls_opt);
     865           0 :         if (ret != LDAP_OPT_SUCCESS) {
     866           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     867             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     868           0 :             return EIO;
     869             :         }
     870             :     }
     871             : 
     872           0 :     tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CIPHER_SUITE);
     873           0 :     if (tls_opt) {
     874           0 :         ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, tls_opt);
     875           0 :         if (ret != LDAP_OPT_SUCCESS) {
     876           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     877             :                   "ldap_set_option failed: %s\n", sss_ldap_err2string(ret));
     878           0 :             return EIO;
     879             :         }
     880             :     }
     881             : 
     882           0 :     return EOK;
     883             : }
     884             : 
     885             : 
     886           0 : bool sdap_check_sup_list(struct sup_list *l, const char *val)
     887             : {
     888             :     int i;
     889             : 
     890           0 :     if (!val) {
     891           0 :         return false;
     892             :     }
     893             : 
     894           0 :     for (i = 0; i < l->num_vals; i++) {
     895           0 :         if (strcasecmp(val, (char *)l->vals[i])) {
     896           0 :             continue;
     897             :         }
     898           0 :         return true;
     899             :     }
     900             : 
     901           0 :     return false;
     902             : }
     903             : 
     904           0 : static int sdap_init_sup_list(TALLOC_CTX *memctx,
     905             :                               struct sup_list *list,
     906             :                               int num, struct ldb_val *vals)
     907             : {
     908             :     int i;
     909             : 
     910           0 :     list->vals = talloc_array(memctx, char *, num);
     911           0 :     if (!list->vals) {
     912           0 :         return ENOMEM;
     913             :     }
     914             : 
     915           0 :     for (i = 0; i < num; i++) {
     916           0 :         list->vals[i] = talloc_strndup(list->vals,
     917           0 :                                        (char *)vals[i].data, vals[i].length);
     918           0 :         if (!list->vals[i]) {
     919           0 :             return ENOMEM;
     920             :         }
     921             :     }
     922             : 
     923           0 :     list->num_vals = num;
     924             : 
     925           0 :     return EOK;
     926             : }
     927             : 
     928           0 : int sdap_set_rootdse_supported_lists(struct sysdb_attrs *rootdse,
     929             :                                      struct sdap_handle *sh)
     930             : {
     931           0 :     struct ldb_message_element *el = NULL;
     932             :     int ret;
     933             :     int i;
     934             : 
     935           0 :     for (i = 0; i < rootdse->num; i++) {
     936           0 :         el = &rootdse->a[i];
     937           0 :         if (strcasecmp(el->name, "supportedControl") == 0) {
     938             : 
     939           0 :             ret = sdap_init_sup_list(sh, &sh->supported_controls,
     940           0 :                                      el->num_values, el->values);
     941           0 :             if (ret) {
     942           0 :                 return ret;
     943             :             }
     944           0 :         } else if (strcasecmp(el->name, "supportedExtension") == 0) {
     945             : 
     946           0 :             ret = sdap_init_sup_list(sh, &sh->supported_extensions,
     947           0 :                                      el->num_values, el->values);
     948           0 :             if (ret) {
     949           0 :                 return ret;
     950             :             }
     951           0 :         } else if (strcasecmp(el->name, "supportedSASLMechanisms") == 0) {
     952             : 
     953           0 :             ret = sdap_init_sup_list(sh, &sh->supported_saslmechs,
     954           0 :                                      el->num_values, el->values);
     955           0 :             if (ret) {
     956           0 :                 return ret;
     957             :             }
     958             :         }
     959             :     }
     960             : 
     961           0 :     return EOK;
     962             : 
     963             : }
     964             : 
     965           0 : static char *get_single_value_as_string(TALLOC_CTX *mem_ctx,
     966             :                                         struct ldb_message_element *el)
     967             : {
     968           0 :     char *str = NULL;
     969             : 
     970           0 :     if (el->num_values == 0) {
     971           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Missing value.\n");
     972           0 :     } else if (el->num_values == 1) {
     973           0 :         str = talloc_strndup(mem_ctx, (char *) el->values[0].data,
     974           0 :                              el->values[0].length);
     975           0 :         if (str == NULL) {
     976           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strndup failed.\n");
     977             :         }
     978             :     } else {
     979           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "More than one value found.\n");
     980             :     }
     981             : 
     982           0 :     return str;
     983             : }
     984             : 
     985           0 : static char *get_naming_context(TALLOC_CTX *mem_ctx,
     986             :                                 struct sysdb_attrs *rootdse)
     987             : {
     988           0 :     struct ldb_message_element *nc = NULL;
     989           0 :     struct ldb_message_element *dnc = NULL;
     990             :     int i;
     991           0 :     char *naming_context = NULL;
     992             : 
     993           0 :     for (i = 0; i < rootdse->num; i++) {
     994           0 :         if (strcasecmp(rootdse->a[i].name,
     995             :                        SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS) == 0) {
     996           0 :             nc = &rootdse->a[i];
     997           0 :         } else if (strcasecmp(rootdse->a[i].name,
     998             :                               SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT) == 0) {
     999           0 :             dnc = &rootdse->a[i];
    1000             :         }
    1001             :     }
    1002             : 
    1003           0 :     if (dnc == NULL && nc == NULL) {
    1004           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    1005             :               "No attributes [%s] or [%s] found in rootDSE.\n",
    1006             :                   SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS,
    1007             :                   SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT);
    1008             :     } else {
    1009           0 :         if (dnc != NULL) {
    1010           0 :             DEBUG(SSSDBG_FUNC_DATA,
    1011             :                   "Using value from [%s] as naming context.\n",
    1012             :                       SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT);
    1013           0 :             naming_context = get_single_value_as_string(mem_ctx, dnc);
    1014             :         }
    1015             : 
    1016           0 :         if (naming_context == NULL && nc != NULL) {
    1017           0 :             DEBUG(SSSDBG_FUNC_DATA,
    1018             :                   "Using value from [%s] as naming context.\n",
    1019             :                       SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS);
    1020           0 :             naming_context = get_single_value_as_string(mem_ctx, nc);
    1021             :         }
    1022             :     }
    1023             : 
    1024             :     /* Some directory servers such as Novell eDirectory will return
    1025             :      * a zero-length namingContexts value in some situations. In this
    1026             :      * case, we should return it as NULL so things fail gracefully.
    1027             :      */
    1028           0 :     if (naming_context && naming_context[0] == '\0') {
    1029           0 :         talloc_zfree(naming_context);
    1030             :     }
    1031             : 
    1032           0 :     return naming_context;
    1033             : }
    1034             : 
    1035             : errno_t
    1036          60 : sdap_create_search_base(TALLOC_CTX *mem_ctx,
    1037             :                         const char *unparsed_base,
    1038             :                         int scope,
    1039             :                         const char *filter,
    1040             :                         struct sdap_search_base **_base)
    1041             : {
    1042             :     struct sdap_search_base *base;
    1043             :     TALLOC_CTX *tmp_ctx;
    1044             :     errno_t ret;
    1045             :     struct ldb_dn *ldn;
    1046             :     struct ldb_context *ldb;
    1047             : 
    1048          60 :     tmp_ctx = talloc_new(NULL);
    1049          60 :     if (!tmp_ctx) {
    1050           0 :         ret = ENOMEM;
    1051           0 :         goto done;
    1052             :     }
    1053             : 
    1054             :     /* Create a throwaway LDB context for validating the DN */
    1055          60 :     ldb = ldb_init(tmp_ctx, NULL);
    1056          60 :     if (!ldb) {
    1057           0 :         ret = ENOMEM;
    1058           0 :         goto done;
    1059             :     }
    1060             : 
    1061          60 :     base = talloc_zero(tmp_ctx, struct sdap_search_base);
    1062          60 :     if (base == NULL) {
    1063           0 :         ret = ENOMEM;
    1064           0 :         goto done;
    1065             :     }
    1066             : 
    1067          60 :     base->basedn = talloc_strdup(base, unparsed_base);
    1068          60 :     if (base->basedn == NULL) {
    1069           0 :         ret = ENOMEM;
    1070           0 :         goto done;
    1071             :     }
    1072             : 
    1073             :     /* Validate the basedn */
    1074          60 :     ldn = ldb_dn_new(tmp_ctx, ldb, unparsed_base);
    1075          60 :     if (!ldn) {
    1076           0 :         ret = ENOMEM;
    1077           0 :         goto done;
    1078             :     }
    1079             : 
    1080          60 :     if (!ldb_dn_validate(ldn)) {
    1081           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid base DN [%s]\n", unparsed_base);
    1082           0 :         ret = EINVAL;
    1083           0 :         goto done;
    1084             :     }
    1085             : 
    1086          60 :     base->scope = scope;
    1087          60 :     base->filter = filter;
    1088             : 
    1089          60 :     *_base = talloc_steal(mem_ctx, base);
    1090          60 :     ret = EOK;
    1091             : done:
    1092          60 :     talloc_free(tmp_ctx);
    1093          60 :     return ret;
    1094             : }
    1095             : 
    1096           0 : static errno_t sdap_set_search_base(struct sdap_options *opts,
    1097             :                                     struct sdap_domain *sdom,
    1098             :                                     enum sdap_basic_opt class,
    1099             :                                     char *naming_context)
    1100             : {
    1101             :     errno_t ret;
    1102             :     struct sdap_search_base ***bases;
    1103             : 
    1104           0 :     switch(class) {
    1105             :     case SDAP_SEARCH_BASE:
    1106           0 :         bases = &sdom->search_bases;
    1107           0 :         break;
    1108             :     case SDAP_USER_SEARCH_BASE:
    1109           0 :         bases = &sdom->user_search_bases;
    1110           0 :         break;
    1111             :     case SDAP_GROUP_SEARCH_BASE:
    1112           0 :         bases = &sdom->group_search_bases;
    1113           0 :         break;
    1114             :     case SDAP_NETGROUP_SEARCH_BASE:
    1115           0 :         bases = &sdom->netgroup_search_bases;
    1116           0 :         break;
    1117             :     case SDAP_SUDO_SEARCH_BASE:
    1118           0 :         bases = &sdom->sudo_search_bases;
    1119           0 :         break;
    1120             :     case SDAP_SERVICE_SEARCH_BASE:
    1121           0 :         bases = &sdom->service_search_bases;
    1122           0 :         break;
    1123             :     case SDAP_AUTOFS_SEARCH_BASE:
    1124           0 :         bases = &sdom->autofs_search_bases;
    1125           0 :         break;
    1126             :     default:
    1127           0 :         return EINVAL;
    1128             :     }
    1129             : 
    1130           0 :     DEBUG(SSSDBG_CONF_SETTINGS,
    1131             :           "Setting option [%s] to [%s].\n",
    1132             :             opts->basic[class].opt_name, naming_context);
    1133             : 
    1134           0 :     ret = dp_opt_set_string(opts->basic, class, naming_context);
    1135           0 :     if (ret != EOK) {
    1136           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
    1137           0 :         goto done;
    1138             :     }
    1139             : 
    1140           0 :     ret = sdap_parse_search_base(opts, opts->basic, class, bases);
    1141           0 :     if (ret != EOK) goto done;
    1142             : 
    1143           0 :     ret = EOK;
    1144             : done:
    1145           0 :     return ret;
    1146             : }
    1147             : 
    1148           0 : errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
    1149             :                                              struct sdap_options *opts,
    1150             :                                              struct sdap_domain *sdom)
    1151             : {
    1152             :     int ret;
    1153           0 :     char *naming_context = NULL;
    1154             : 
    1155           0 :     if (!sdom->search_bases
    1156           0 :             || !sdom->user_search_bases
    1157           0 :             || !sdom->group_search_bases
    1158           0 :             || !sdom->netgroup_search_bases
    1159           0 :             || !sdom->sudo_search_bases
    1160           0 :             || !sdom->autofs_search_bases) {
    1161           0 :         naming_context = get_naming_context(opts->basic, rootdse);
    1162           0 :         if (naming_context == NULL) {
    1163           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "get_naming_context failed.\n");
    1164             : 
    1165             :             /* This has to be non-fatal, since some servers offer
    1166             :              * multiple namingContexts entries. We will just
    1167             :              * add NULL checks for the search bases in the lookups.
    1168             :              */
    1169           0 :             ret = EOK;
    1170           0 :             goto done;
    1171             :         }
    1172             :     }
    1173             : 
    1174             :     /* Default */
    1175           0 :     if (!sdom->search_bases) {
    1176           0 :         ret = sdap_set_search_base(opts, sdom,
    1177             :                                    SDAP_SEARCH_BASE,
    1178             :                                    naming_context);
    1179           0 :         if (ret != EOK) goto done;
    1180             :     }
    1181             : 
    1182             :     /* Users */
    1183           0 :     if (!sdom->user_search_bases) {
    1184           0 :         ret = sdap_set_search_base(opts, sdom,
    1185             :                                    SDAP_USER_SEARCH_BASE,
    1186             :                                    naming_context);
    1187           0 :         if (ret != EOK) goto done;
    1188             :     }
    1189             : 
    1190             :     /* Groups */
    1191           0 :     if (!sdom->group_search_bases) {
    1192           0 :         ret = sdap_set_search_base(opts, sdom,
    1193             :                                    SDAP_GROUP_SEARCH_BASE,
    1194             :                                    naming_context);
    1195           0 :         if (ret != EOK) goto done;
    1196             :     }
    1197             : 
    1198             :     /* Netgroups */
    1199           0 :     if (!sdom->netgroup_search_bases) {
    1200           0 :         ret = sdap_set_search_base(opts, sdom,
    1201             :                                    SDAP_NETGROUP_SEARCH_BASE,
    1202             :                                    naming_context);
    1203           0 :         if (ret != EOK) goto done;
    1204             :     }
    1205             : 
    1206             :     /* Sudo */
    1207           0 :     if (!sdom->sudo_search_bases) {
    1208           0 :        ret = sdap_set_search_base(opts, sdom,
    1209             :                                    SDAP_SUDO_SEARCH_BASE,
    1210             :                                    naming_context);
    1211           0 :         if (ret != EOK) goto done;
    1212             :     }
    1213             : 
    1214             :     /* Services */
    1215           0 :     if (!sdom->service_search_bases) {
    1216           0 :        ret = sdap_set_search_base(opts, sdom,
    1217             :                                   SDAP_SERVICE_SEARCH_BASE,
    1218             :                                   naming_context);
    1219           0 :         if (ret != EOK) goto done;
    1220             :     }
    1221             : 
    1222             :     /* autofs */
    1223           0 :     if (!sdom->autofs_search_bases) {
    1224           0 :        ret = sdap_set_search_base(opts, sdom,
    1225             :                                   SDAP_AUTOFS_SEARCH_BASE,
    1226             :                                   naming_context);
    1227           0 :         if (ret != EOK) goto done;
    1228             :     }
    1229             : 
    1230           0 :     ret = EOK;
    1231             : 
    1232             : done:
    1233           0 :     talloc_free(naming_context);
    1234           0 :     return ret;
    1235             : }
    1236             : 
    1237           0 : int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
    1238             :                                       const char *server,
    1239             :                                       struct sysdb_attrs *rootdse,
    1240             :                                       struct sdap_options *opts,
    1241             :                                       struct sdap_server_opts **srv_opts)
    1242             : {
    1243             :     struct sdap_server_opts *so;
    1244             :     struct {
    1245             :         const char *last_name;
    1246             :         const char *entry_name;
    1247           0 :     } usn_attrs[] = { { SDAP_IPA_LAST_USN, SDAP_IPA_USN },
    1248             :                       { SDAP_AD_LAST_USN, SDAP_AD_USN },
    1249             :                       { NULL, NULL } };
    1250             :     const char *last_usn_name;
    1251             :     const char *last_usn_value;
    1252             :     const char *entry_usn_name;
    1253           0 :     char *endptr = NULL;
    1254             :     int ret;
    1255             :     int i;
    1256             :     uint32_t dc_level;
    1257             : 
    1258           0 :     so = talloc_zero(memctx, struct sdap_server_opts);
    1259           0 :     if (!so) {
    1260           0 :         return ENOMEM;
    1261             :     }
    1262           0 :     so->server_id = talloc_strdup(so, server);
    1263           0 :     if (!so->server_id) {
    1264           0 :         talloc_zfree(so);
    1265           0 :         return ENOMEM;
    1266             :     }
    1267             : 
    1268           0 :     last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
    1269           0 :     entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
    1270           0 :     if (rootdse) {
    1271           0 :         if (last_usn_name) {
    1272           0 :             ret = sysdb_attrs_get_string(rootdse,
    1273             :                                           last_usn_name, &last_usn_value);
    1274           0 :             if (ret != EOK) {
    1275           0 :                 switch (ret) {
    1276             :                 case ENOENT:
    1277           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
    1278             :                           "%s configured but not found in rootdse!\n",
    1279             :                               opts->gen_map[SDAP_AT_LAST_USN].opt_name);
    1280           0 :                     break;
    1281             :                 case ERANGE:
    1282           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
    1283             :                           "Multiple values of %s found in rootdse!\n",
    1284             :                               opts->gen_map[SDAP_AT_LAST_USN].opt_name);
    1285           0 :                     break;
    1286             :                 default:
    1287           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
    1288             :                           "Unknown error (%d) checking rootdse!\n", ret);
    1289             :                 }
    1290             :             } else {
    1291           0 :                 if (!entry_usn_name) {
    1292           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
    1293             :                           "%s found in rootdse but %s is not set!\n",
    1294             :                               last_usn_name,
    1295             :                               opts->gen_map[SDAP_AT_ENTRY_USN].opt_name);
    1296             :                 } else {
    1297           0 :                     so->supports_usn = true;
    1298           0 :                     so->last_usn = strtoul(last_usn_value, &endptr, 10);
    1299           0 :                     if (endptr != NULL && (*endptr != '\0' || endptr == last_usn_value)) {
    1300           0 :                         DEBUG(SSSDBG_MINOR_FAILURE,
    1301             :                               "USN is not valid (value: %s)\n", last_usn_value);
    1302           0 :                         so->last_usn = 0;
    1303             :                     } else {
    1304           0 :                         DEBUG(SSSDBG_TRACE_ALL,
    1305             :                               "USN value: %s (int: %lu)\n", last_usn_value, so->last_usn);
    1306             :                     }
    1307             :                 }
    1308             :             }
    1309             :         } else {
    1310             :             /* no usn option configure, let's try to autodetect. */
    1311           0 :             for (i = 0; usn_attrs[i].last_name; i++) {
    1312           0 :                 ret = sysdb_attrs_get_string(rootdse,
    1313             :                                              usn_attrs[i].last_name,
    1314             :                                              &last_usn_value);
    1315           0 :                 if (ret == EOK) {
    1316             :                     /* Fixate discovered configuration */
    1317           0 :                     opts->gen_map[SDAP_AT_LAST_USN].name =
    1318           0 :                         talloc_strdup(opts->gen_map, usn_attrs[i].last_name);
    1319           0 :                     opts->gen_map[SDAP_AT_ENTRY_USN].name =
    1320           0 :                         talloc_strdup(opts->gen_map, usn_attrs[i].entry_name);
    1321           0 :                     so->supports_usn = true;
    1322           0 :                     so->last_usn = strtoul(last_usn_value, &endptr, 10);
    1323           0 :                     if (endptr != NULL && (*endptr != '\0' || endptr == last_usn_value)) {
    1324           0 :                         DEBUG(SSSDBG_MINOR_FAILURE,
    1325             :                               "USN is not valid (value: %s)\n", last_usn_value);
    1326           0 :                         so->last_usn = 0;
    1327             :                     } else {
    1328           0 :                         DEBUG(SSSDBG_TRACE_ALL,
    1329             :                               "USN value: %s (int: %lu)\n", last_usn_value, so->last_usn);
    1330             :                     }
    1331           0 :                     last_usn_name = usn_attrs[i].last_name;
    1332           0 :                     break;
    1333             :                 }
    1334             :             }
    1335             :         }
    1336             : 
    1337             :         /* Detect Active Directory version if available */
    1338           0 :         ret = sysdb_attrs_get_uint32_t(rootdse,
    1339             :                                        SDAP_ROOTDSE_ATTR_AD_VERSION,
    1340             :                                        &dc_level);
    1341           0 :         if (ret == EOK) {
    1342             :             /* Validate that the DC level matches an expected value */
    1343           0 :             switch(dc_level) {
    1344             :             case DS_BEHAVIOR_WIN2000:
    1345             :             case DS_BEHAVIOR_WIN2003:
    1346             :             case DS_BEHAVIOR_WIN2008:
    1347             :             case DS_BEHAVIOR_WIN2008R2:
    1348             :             case DS_BEHAVIOR_WIN2012:
    1349             :             case DS_BEHAVIOR_WIN2012R2:
    1350             :             case DS_BEHAVIOR_WIN2016:
    1351           0 :                 opts->dc_functional_level = dc_level;
    1352           0 :                 DEBUG(SSSDBG_CONF_SETTINGS,
    1353             :                       "Setting AD compatibility level to [%d]\n",
    1354             :                        opts->dc_functional_level);
    1355           0 :                 break;
    1356             :             default:
    1357           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
    1358             :                       "Received invalid value [%d] for AD compatibility level. "
    1359             :                       "Using the lowest-common compatibility level\n",
    1360             :                       dc_level);
    1361           0 :                 opts->dc_functional_level = DS_BEHAVIOR_WIN2003;
    1362             :             }
    1363           0 :         } else if (ret != ENOENT) {
    1364           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
    1365             :                   "Error detecting Active Directory compatibility level "
    1366             :                    "(%s). Continuing without AD performance enhancements\n",
    1367             :                    strerror(ret));
    1368             :         }
    1369             :     }
    1370             : 
    1371           0 :     if (!last_usn_name) {
    1372           0 :         DEBUG(SSSDBG_FUNC_DATA,
    1373             :               "No known USN scheme is supported by this server!\n");
    1374           0 :         if (!entry_usn_name) {
    1375           0 :             DEBUG(SSSDBG_FUNC_DATA,
    1376             :                   "Will use modification timestamp as usn!\n");
    1377           0 :             opts->gen_map[SDAP_AT_ENTRY_USN].name =
    1378           0 :                 talloc_strdup(opts->gen_map, "modifyTimestamp");
    1379             :         }
    1380             :     }
    1381             : 
    1382           0 :     if (!opts->user_map[SDAP_AT_USER_USN].name) {
    1383           0 :         opts->user_map[SDAP_AT_USER_USN].name =
    1384           0 :                     talloc_strdup(opts->user_map,
    1385           0 :                                   opts->gen_map[SDAP_AT_ENTRY_USN].name);
    1386             :     }
    1387           0 :     if (!opts->group_map[SDAP_AT_GROUP_USN].name) {
    1388           0 :         opts->group_map[SDAP_AT_GROUP_USN].name =
    1389           0 :                     talloc_strdup(opts->group_map,
    1390           0 :                                   opts->gen_map[SDAP_AT_ENTRY_USN].name);
    1391             :     }
    1392           0 :     if (!opts->service_map[SDAP_AT_SERVICE_USN].name) {
    1393           0 :         opts->service_map[SDAP_AT_SERVICE_USN].name =
    1394           0 :                     talloc_strdup(opts->service_map,
    1395           0 :                                   opts->gen_map[SDAP_AT_ENTRY_USN].name);
    1396             :     }
    1397           0 :     if (opts->sudorule_map &&
    1398           0 :         !opts->sudorule_map[SDAP_AT_SUDO_USN].name) {
    1399           0 :         opts->sudorule_map[SDAP_AT_SUDO_USN].name =
    1400           0 :                     talloc_strdup(opts->sudorule_map,
    1401           0 :                                   opts->gen_map[SDAP_AT_ENTRY_USN].name);
    1402             :     }
    1403             : 
    1404           0 :     *srv_opts = so;
    1405           0 :     return EOK;
    1406             : }
    1407             : 
    1408           0 : void sdap_steal_server_opts(struct sdap_id_ctx *id_ctx,
    1409             :                             struct sdap_server_opts **srv_opts)
    1410             : {
    1411           0 :     if (!id_ctx || !srv_opts || !*srv_opts) {
    1412           0 :         return;
    1413             :     }
    1414             : 
    1415           0 :     if (!id_ctx->srv_opts) {
    1416           0 :         id_ctx->srv_opts = talloc_move(id_ctx, srv_opts);
    1417           0 :         return;
    1418             :     }
    1419             : 
    1420             :     /* discard if same as previous so we do not reset max usn values
    1421             :      * unnecessarily */
    1422           0 :     if (strcmp(id_ctx->srv_opts->server_id, (*srv_opts)->server_id) == 0) {
    1423           0 :         talloc_zfree(*srv_opts);
    1424           0 :         return;
    1425             :     }
    1426             : 
    1427           0 :     talloc_zfree(id_ctx->srv_opts);
    1428           0 :     id_ctx->srv_opts = talloc_move(id_ctx, srv_opts);
    1429             : }
    1430             : 
    1431          55 : static bool attr_is_filtered(const char *attr, const char **filter)
    1432             : {
    1433             :     int i;
    1434             : 
    1435          55 :     if (filter) {
    1436           0 :         i = 0;
    1437           0 :         while (filter[i]) {
    1438           0 :             if (filter[i] == attr ||
    1439           0 :                 strcasecmp(filter[i], attr) == 0) {
    1440           0 :                 return true;
    1441             :             }
    1442           0 :             i++;
    1443             :         }
    1444             :     }
    1445             : 
    1446          55 :     return false;
    1447             : }
    1448             : 
    1449          11 : int build_attrs_from_map(TALLOC_CTX *memctx,
    1450             :                          struct sdap_attr_map *map,
    1451             :                          size_t size,
    1452             :                          const char **filter,
    1453             :                          const char ***_attrs,
    1454             :                          size_t *attr_count)
    1455             : {
    1456             :     errno_t ret;
    1457             :     const char **attrs;
    1458             :     int i, j;
    1459          11 :     TALLOC_CTX *tmp_ctx = talloc_new(NULL);
    1460          11 :     if (!tmp_ctx) return ENOMEM;
    1461             : 
    1462             :     /* Assume that all entries in the map have values */
    1463          11 :     attrs = talloc_zero_array(tmp_ctx, const char *, size + 1);
    1464          11 :     if (!attrs) {
    1465           0 :         ret = ENOMEM;
    1466           0 :         goto done;
    1467             :     }
    1468             : 
    1469             :     /* first attribute is "objectclass" not the specifc one */
    1470          11 :     attrs[0] = talloc_strdup(memctx, "objectClass");
    1471          11 :     if (!attrs[0]) return ENOMEM;
    1472             : 
    1473             :     /* add the others */
    1474         132 :     for (i = j = 1; i < size; i++) {
    1475         121 :         if (map[i].name && !attr_is_filtered(map[i].name, filter)) {
    1476          55 :             attrs[j] = map[i].name;
    1477          55 :             j++;
    1478             :         }
    1479             :     }
    1480          11 :     attrs[j] = NULL;
    1481             : 
    1482             :     /* Trim down the used memory if some attributes were NULL */
    1483          11 :     attrs = talloc_realloc(tmp_ctx, attrs, const char *, j + 1);
    1484          11 :     if (!attrs) {
    1485           0 :         ret = ENOMEM;
    1486           0 :         goto done;
    1487             :     }
    1488             : 
    1489          11 :     *_attrs = talloc_steal(memctx, attrs);
    1490          11 :     if (attr_count) *attr_count = j;
    1491             : 
    1492          11 :     ret = EOK;
    1493             : 
    1494             : done:
    1495          11 :     talloc_free(tmp_ctx);
    1496          11 :     return ret;
    1497             : }
    1498             : 
    1499           0 : int sdap_control_create(struct sdap_handle *sh, const char *oid, int iscritical,
    1500             :                         struct berval *value, int dupval, LDAPControl **ctrlp)
    1501             : {
    1502             :     int ret;
    1503             : 
    1504           0 :     if (sdap_is_control_supported(sh, oid)) {
    1505           0 :         ret = sss_ldap_control_create(oid, iscritical, value, dupval, ctrlp);
    1506           0 :         if (ret != LDAP_SUCCESS) {
    1507           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    1508             :                   "sss_ldap_control_create failed [%d][%s].\n",
    1509             :                       ret, sss_ldap_err2string(ret));
    1510             :         }
    1511             :     } else {
    1512           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    1513             :               "Server does not support the requested control [%s].\n", oid);
    1514           0 :         ret = LDAP_NOT_SUPPORTED;
    1515             :     }
    1516             : 
    1517           0 :     return ret;
    1518             : }
    1519             : 
    1520           0 : int sdap_replace_id(struct sysdb_attrs *entry, const char *attr, id_t val)
    1521             : {
    1522             :     char *str;
    1523             :     errno_t ret;
    1524             :     struct ldb_message_element *el;
    1525             : 
    1526           0 :     ret = sysdb_attrs_get_el_ext(entry, attr, false, &el);
    1527           0 :     if (ret == ENOENT) {
    1528           0 :         return sysdb_attrs_add_uint32(entry, attr, val);
    1529           0 :     } else if (ret) {
    1530           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot get attribute [%s]\n", attr);
    1531           0 :         return ret;
    1532             :     }
    1533             : 
    1534           0 :     if (el->num_values != 1) {
    1535           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1536             :               "Expected 1 value for %s, got %d\n", attr, el->num_values);
    1537           0 :         return EINVAL;
    1538             :     }
    1539             : 
    1540           0 :     str = talloc_asprintf(entry, "%llu", (unsigned long long) val);
    1541           0 :     if (!str) {
    1542           0 :         return ENOMEM;
    1543             :     }
    1544             : 
    1545           0 :     el->values[0].data = (uint8_t *) str;
    1546           0 :     el->values[0].length = strlen(str);
    1547             : 
    1548           0 :     return EOK;
    1549             : }
    1550             : 
    1551             : static errno_t
    1552           0 : sdap_get_primary_name(TALLOC_CTX *memctx,
    1553             :                       const char *attr_name,
    1554             :                       struct sysdb_attrs *attrs,
    1555             :                       struct sss_domain_info *dom,
    1556             :                       const char **_primary_name)
    1557             : {
    1558             :     errno_t ret;
    1559           0 :     const char *orig_name = NULL;
    1560             :     char *name;
    1561             : 
    1562           0 :     ret = sysdb_attrs_primary_name(dom->sysdb, attrs, attr_name, &orig_name);
    1563           0 :     if (ret != EOK) {
    1564           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "The object has no name attribute\n");
    1565           0 :         return EINVAL;
    1566             :     }
    1567             : 
    1568           0 :     name = sss_get_domain_name(memctx, orig_name, dom);
    1569           0 :     if (name == NULL) {
    1570           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1571             :               "Failed to format original name [%s]\n", orig_name);
    1572           0 :         return ENOMEM;
    1573             :     }
    1574           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Processing object %s\n", name);
    1575             : 
    1576           0 :     *_primary_name = name;
    1577           0 :     return EOK;
    1578             : }
    1579             : 
    1580           0 : errno_t sdap_get_user_primary_name(TALLOC_CTX *memctx,
    1581             :                                    struct sdap_options *opts,
    1582             :                                    struct sysdb_attrs *attrs,
    1583             :                                    struct sss_domain_info *dom,
    1584             :                                    const char **_user_name)
    1585             : {
    1586           0 :     return sdap_get_primary_name(memctx,
    1587           0 :                                  opts->user_map[SDAP_AT_USER_NAME].name,
    1588             :                                  attrs, dom, _user_name);
    1589             : }
    1590             : 
    1591           0 : errno_t sdap_get_group_primary_name(TALLOC_CTX *memctx,
    1592             :                                     struct sdap_options *opts,
    1593             :                                     struct sysdb_attrs *attrs,
    1594             :                                     struct sss_domain_info *dom,
    1595             :                                     const char **_group_name)
    1596             : {
    1597           0 :     return sdap_get_primary_name(memctx,
    1598           0 :                                  opts->group_map[SDAP_AT_GROUP_NAME].name,
    1599             :                                  attrs, dom, _group_name);
    1600             : }
    1601             : 
    1602           0 : errno_t sdap_get_netgroup_primary_name(TALLOC_CTX *memctx,
    1603             :                                        struct sdap_options *opts,
    1604             :                                        struct sysdb_attrs *attrs,
    1605             :                                        struct sss_domain_info *dom,
    1606             :                                        const char **_netgroup_name)
    1607             : {
    1608           0 :     return sdap_get_primary_name(memctx,
    1609           0 :                                  opts->netgroup_map[SDAP_AT_NETGROUP_NAME].name,
    1610             :                                  attrs, dom, _netgroup_name);
    1611             : }
    1612             : 
    1613          11 : char *sdap_make_oc_list(TALLOC_CTX *mem_ctx, struct sdap_attr_map *map)
    1614             : {
    1615          11 :     if (map[SDAP_OC_GROUP_ALT].name == NULL) {
    1616          11 :         return talloc_asprintf(mem_ctx, "objectClass=%s",
    1617             :                                map[SDAP_OC_GROUP].name);
    1618             :     } else {
    1619           0 :         return talloc_asprintf(mem_ctx,
    1620             :                                "|(objectClass=%s)(objectClass=%s)",
    1621             :                                map[SDAP_OC_GROUP].name,
    1622           0 :                                map[SDAP_OC_GROUP_ALT].name);
    1623             :     }
    1624             : }
    1625             : 
    1626           4 : static bool sdap_object_in_domain(struct sdap_options *opts,
    1627             :                                   struct sysdb_attrs *obj,
    1628             :                                   struct sss_domain_info *dom)
    1629             : {
    1630             :     errno_t ret;
    1631           4 :     const char *original_dn = NULL;
    1632           4 :     struct sdap_domain *sdmatch = NULL;
    1633             : 
    1634           4 :     ret = sysdb_attrs_get_string(obj, SYSDB_ORIG_DN, &original_dn);
    1635           4 :     if (ret) {
    1636           0 :         DEBUG(SSSDBG_FUNC_DATA,
    1637             :               "The group has no original DN, assuming our domain\n");
    1638           0 :         return true;
    1639             :     }
    1640             : 
    1641           4 :     sdmatch = sdap_domain_get_by_dn(opts, original_dn);
    1642           4 :     if (sdmatch == NULL) {
    1643           0 :         DEBUG(SSSDBG_FUNC_DATA,
    1644             :               "The group has no original DN, assuming our domain\n");
    1645           0 :         return true;
    1646             :     }
    1647             : 
    1648           4 :     return (sdmatch->dom == dom);
    1649             : }
    1650             : 
    1651           3 : size_t sdap_steal_objects_in_dom(struct sdap_options *opts,
    1652             :                                  struct sysdb_attrs **dom_objects,
    1653             :                                  size_t offset,
    1654             :                                  struct sss_domain_info *dom,
    1655             :                                  struct sysdb_attrs **all_objects,
    1656             :                                  size_t count,
    1657             :                                  bool filter)
    1658             : {
    1659           3 :     size_t copied = 0;
    1660             : 
    1661             :     /* Own objects from all_objects by dom_objects in case they belong
    1662             :      * to domain dom.
    1663             :      *
    1664             :      * Don't copy objects from other domains in case
    1665             :      * the search was for parent domain but a child domain would match,
    1666             :      * too, such as:
    1667             :      *  dc=example,dc=com
    1668             :      *  dc=child,dc=example,dc=com
    1669             :      * while searching for an object from dc=example.
    1670             :      */
    1671           9 :     for (size_t i = 0; i < count; i++) {
    1672          10 :         if (filter &&
    1673           4 :                 sdap_object_in_domain(opts, all_objects[i], dom) == false) {
    1674           2 :             continue;
    1675             :         }
    1676             : 
    1677           8 :         dom_objects[offset + copied] =
    1678           4 :             talloc_steal(dom_objects, all_objects[i]);
    1679           4 :         copied++;
    1680             :     }
    1681             : 
    1682           3 :     return copied;
    1683             : }

Generated by: LCOV version 1.10