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

Generated by: LCOV version 1.10