LCOV - code coverage report
Current view: top level - providers/ldap - ldap_options.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 109 321 34.0 %
Date: 2015-10-19 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Simo Sorce <ssorce@redhat.com>
       4             : 
       5             :     Copyright (C) 2008-2010 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "providers/ldap/ldap_common.h"
      22             : #include "providers/ldap/ldap_opts.h"
      23             : #include "providers/ldap/sdap_async_private.h"
      24             : #include "util/crypto/sss_crypto.h"
      25             : 
      26           7 : int ldap_get_options(TALLOC_CTX *memctx,
      27             :                      struct sss_domain_info *dom,
      28             :                      struct confdb_ctx *cdb,
      29             :                      const char *conf_path,
      30             :                      struct sdap_options **_opts)
      31             : {
      32             :     struct sdap_attr_map *default_attr_map;
      33             :     struct sdap_attr_map *default_user_map;
      34             :     struct sdap_attr_map *default_group_map;
      35             :     struct sdap_attr_map *default_netgroup_map;
      36             :     struct sdap_attr_map *default_service_map;
      37             :     struct sdap_options *opts;
      38             :     char *schema;
      39             :     const char *search_base;
      40             :     const char *pwd_policy;
      41             :     int ret;
      42             :     int account_cache_expiration;
      43             :     int offline_credentials_expiration;
      44             :     const char *ldap_deref;
      45             :     int ldap_deref_val;
      46             :     int o;
      47             :     const char *authtok_type;
      48             :     struct dp_opt_blob authtok_blob;
      49             :     char *cleartext;
      50           7 :     const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
      51             :                                         SDAP_GROUP_SEARCH_BASE,
      52             :                                         SDAP_NETGROUP_SEARCH_BASE,
      53             :                                         SDAP_SERVICE_SEARCH_BASE,
      54             :                                         -1 };
      55             : 
      56           7 :     opts = talloc_zero(memctx, struct sdap_options);
      57           7 :     if (!opts) return ENOMEM;
      58             : 
      59           7 :     ret = sdap_domain_add(opts, dom, NULL);
      60           7 :     if (ret != EOK) {
      61           0 :         goto done;
      62             :     }
      63             : 
      64           7 :     ret = dp_get_options(opts, cdb, conf_path,
      65             :                          default_basic_opts,
      66             :                          SDAP_OPTS_BASIC,
      67             :                          &opts->basic);
      68           7 :     if (ret != EOK) {
      69           0 :         goto done;
      70             :     }
      71             : 
      72             :     /* Handle search bases */
      73           7 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
      74           7 :     if (search_base != NULL) {
      75             :         /* set user/group/netgroup search bases if they are not */
      76          35 :         for (o = 0; search_base_options[o] != -1; o++) {
      77          28 :             if (NULL == dp_opt_get_string(opts->basic, search_base_options[o])) {
      78          14 :                 ret = dp_opt_set_string(opts->basic, search_base_options[o],
      79             :                                         search_base);
      80          14 :                 if (ret != EOK) {
      81           0 :                     goto done;
      82             :                 }
      83          14 :                 DEBUG(SSSDBG_TRACE_FUNC, "Option %s set to %s\n",
      84             :                           opts->basic[search_base_options[o]].opt_name,
      85             :                           dp_opt_get_string(opts->basic,
      86             :                                             search_base_options[o]));
      87             :             }
      88             :         }
      89             :     } else {
      90           0 :         DEBUG(SSSDBG_FUNC_DATA,
      91             :               "Search base not set, trying to discover it later when "
      92             :                   "connecting to the LDAP server.\n");
      93             :     }
      94             : 
      95             :     /* Default search */
      96           7 :     ret = sdap_parse_search_base(opts, opts->basic,
      97             :                                  SDAP_SEARCH_BASE,
      98           7 :                                  &opts->sdom->search_bases);
      99           7 :     if (ret != EOK && ret != ENOENT) goto done;
     100             : 
     101             :     /* User search */
     102           7 :     ret = sdap_parse_search_base(opts, opts->basic,
     103             :                                  SDAP_USER_SEARCH_BASE,
     104           7 :                                  &opts->sdom->user_search_bases);
     105           7 :     if (ret != EOK && ret != ENOENT) goto done;
     106             : 
     107             :     /* Group search base */
     108           7 :     ret = sdap_parse_search_base(opts, opts->basic,
     109             :                                  SDAP_GROUP_SEARCH_BASE,
     110           7 :                                  &opts->sdom->group_search_bases);
     111           7 :     if (ret != EOK && ret != ENOENT) goto done;
     112             : 
     113             :     /* Netgroup search */
     114           7 :     ret = sdap_parse_search_base(opts, opts->basic,
     115             :                                  SDAP_NETGROUP_SEARCH_BASE,
     116           7 :                                  &opts->sdom->netgroup_search_bases);
     117           7 :     if (ret != EOK && ret != ENOENT) goto done;
     118             : 
     119             :     /* Service search */
     120           7 :     ret = sdap_parse_search_base(opts, opts->basic,
     121             :                                  SDAP_SERVICE_SEARCH_BASE,
     122           7 :                                  &opts->sdom->service_search_bases);
     123           7 :     if (ret != EOK && ret != ENOENT) goto done;
     124             : 
     125           7 :     pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY);
     126           7 :     if (pwd_policy == NULL) {
     127           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     128             :               "Missing password policy, this may not happen.\n");
     129           0 :         ret = EINVAL;
     130           0 :         goto done;
     131             :     }
     132           7 :     if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) != 0 &&
     133           0 :         strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) != 0 &&
     134           0 :         strcasecmp(pwd_policy, PWD_POL_OPT_MIT) != 0) {
     135           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     136             :               "Unsupported password policy [%s].\n", pwd_policy);
     137           0 :         ret = EINVAL;
     138           0 :         goto done;
     139             :     }
     140             : 
     141             :     /* account_cache_expiration must be >= than offline_credentials_expiration */
     142           7 :     ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
     143             :                          CONFDB_PAM_CRED_TIMEOUT, 0,
     144             :                          &offline_credentials_expiration);
     145           7 :     if (ret != EOK) {
     146           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get value of %s from confdb \n",
     147             :                   CONFDB_PAM_CRED_TIMEOUT);
     148           0 :         goto done;
     149             :     }
     150             : 
     151           7 :     account_cache_expiration = dp_opt_get_int(opts->basic,
     152             :                                               SDAP_ACCOUNT_CACHE_EXPIRATION);
     153             : 
     154             :     /* account cache_expiration must not be smaller than
     155             :      * offline_credentials_expiration to prevent deleting entries that
     156             :      * still contain credentials valid for offline login.
     157             :      *
     158             :      * offline_credentials_expiration == 0 is a special case that says
     159             :      * that the cached credentials are valid forever. Therefore, the cached
     160             :      * entries must not be purged from cache.
     161             :      */
     162           7 :     if (!offline_credentials_expiration && account_cache_expiration) {
     163           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     164             :               "Conflicting values for options %s (unlimited) "
     165             :                   "and %s (%d)\n",
     166             :                   opts->basic[SDAP_ACCOUNT_CACHE_EXPIRATION].opt_name,
     167             :                   CONFDB_PAM_CRED_TIMEOUT,
     168             :                   offline_credentials_expiration);
     169           0 :         ret = EINVAL;
     170           0 :         goto done;
     171             :     }
     172           7 :     if (offline_credentials_expiration && account_cache_expiration &&
     173           0 :         offline_credentials_expiration > account_cache_expiration) {
     174           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Value of %s (now %d) must be larger "
     175             :                   "than value of %s (now %d)\n",
     176             :                   opts->basic[SDAP_ACCOUNT_CACHE_EXPIRATION].opt_name,
     177             :                   account_cache_expiration,
     178             :                   CONFDB_PAM_CRED_TIMEOUT,
     179             :                   offline_credentials_expiration);
     180           0 :         ret = EINVAL;
     181           0 :         goto done;
     182             :     }
     183             : 
     184           7 :     ldap_deref = dp_opt_get_string(opts->basic, SDAP_DEREF);
     185           7 :     if (ldap_deref != NULL) {
     186           0 :         ret = deref_string_to_val(ldap_deref, &ldap_deref_val);
     187           0 :         if (ret != EOK) {
     188           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to verify ldap_deref option.\n");
     189           0 :             goto done;
     190             :         }
     191             :     }
     192             : 
     193             : #ifndef HAVE_LDAP_CONNCB
     194             :     bool ldap_referrals;
     195             : 
     196             :     ldap_referrals = dp_opt_get_bool(opts->basic, SDAP_REFERRALS);
     197             :     if (ldap_referrals) {
     198             :         DEBUG(SSSDBG_CRIT_FAILURE,
     199             :               "LDAP referrals are not supported, because the LDAP library "
     200             :                   "is too old, see sssd-ldap(5) for details.\n");
     201             :         ret = dp_opt_set_bool(opts->basic, SDAP_REFERRALS, false);
     202             :     }
     203             : #endif
     204             : 
     205             :     /* schema type */
     206           7 :     schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA);
     207           7 :     if (strcasecmp(schema, "rfc2307") == 0) {
     208           0 :         opts->schema_type = SDAP_SCHEMA_RFC2307;
     209           0 :         default_attr_map = generic_attr_map;
     210           0 :         default_user_map = rfc2307_user_map;
     211           0 :         default_group_map = rfc2307_group_map;
     212           0 :         default_netgroup_map = netgroup_map;
     213           0 :         default_service_map = service_map;
     214             :     } else
     215           7 :     if (strcasecmp(schema, "rfc2307bis") == 0) {
     216           7 :         opts->schema_type = SDAP_SCHEMA_RFC2307BIS;
     217           7 :         default_attr_map = generic_attr_map;
     218           7 :         default_user_map = rfc2307bis_user_map;
     219           7 :         default_group_map = rfc2307bis_group_map;
     220           7 :         default_netgroup_map = netgroup_map;
     221           7 :         default_service_map = service_map;
     222             :     } else
     223           0 :     if (strcasecmp(schema, "IPA") == 0) {
     224           0 :         opts->schema_type = SDAP_SCHEMA_IPA_V1;
     225           0 :         default_attr_map = gen_ipa_attr_map;
     226           0 :         default_user_map = rfc2307bis_user_map;
     227           0 :         default_group_map = rfc2307bis_group_map;
     228           0 :         default_netgroup_map = netgroup_map;
     229           0 :         default_service_map = service_map;
     230             :     } else
     231           0 :     if (strcasecmp(schema, "AD") == 0) {
     232           0 :         opts->schema_type = SDAP_SCHEMA_AD;
     233           0 :         default_attr_map = gen_ad_attr_map;
     234           0 :         default_user_map = gen_ad2008r2_user_map;
     235           0 :         default_group_map = gen_ad2008r2_group_map;
     236           0 :         default_netgroup_map = netgroup_map;
     237           0 :         default_service_map = service_map;
     238             :     } else {
     239           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized schema type: %s\n", schema);
     240           0 :         ret = EINVAL;
     241           0 :         goto done;
     242             :     }
     243             : 
     244           7 :     ret = sdap_get_map(opts, cdb, conf_path,
     245             :                        default_attr_map,
     246             :                        SDAP_AT_GENERAL,
     247             :                        &opts->gen_map);
     248           7 :     if (ret != EOK) {
     249           0 :         goto done;
     250             :     }
     251             : 
     252           7 :     ret = sdap_get_map(opts, cdb, conf_path,
     253             :                        default_user_map,
     254             :                        SDAP_OPTS_USER,
     255             :                        &opts->user_map);
     256           7 :     if (ret != EOK) {
     257           0 :         goto done;
     258             :     }
     259             : 
     260           7 :     ret = sdap_extend_map_with_list(opts, opts, SDAP_USER_EXTRA_ATTRS,
     261             :                                     opts->user_map, SDAP_OPTS_USER,
     262             :                                     &opts->user_map, &opts->user_map_cnt);
     263           7 :     if (ret != EOK) {
     264           0 :         goto done;
     265             :     }
     266             : 
     267           7 :     ret = sdap_get_map(opts, cdb, conf_path,
     268             :                        default_group_map,
     269             :                        SDAP_OPTS_GROUP,
     270             :                        &opts->group_map);
     271           7 :     if (ret != EOK) {
     272           0 :         goto done;
     273             :     }
     274             : 
     275           7 :     ret = sdap_get_map(opts, cdb, conf_path,
     276             :                        default_netgroup_map,
     277             :                        SDAP_OPTS_NETGROUP,
     278             :                        &opts->netgroup_map);
     279           7 :     if (ret != EOK) {
     280           0 :         goto done;
     281             :     }
     282             : 
     283           7 :     ret = sdap_get_map(opts, cdb, conf_path,
     284             :                        default_service_map,
     285             :                        SDAP_OPTS_SERVICES,
     286             :                        &opts->service_map);
     287           7 :     if (ret != EOK) {
     288           0 :         goto done;
     289             :     }
     290             : 
     291             :     /* If there is no KDC, try the deprecated krb5_kdcip option, too */
     292             :     /* FIXME - this can be removed in a future version */
     293           7 :     ret = krb5_try_kdcip(cdb, conf_path, opts->basic, SDAP_KRB5_KDC);
     294           7 :     if (ret != EOK) {
     295           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sss_krb5_try_kdcip failed.\n");
     296           0 :         goto done;
     297             :     }
     298             : 
     299           7 :     authtok_type = dp_opt_get_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE);
     300          14 :     if (authtok_type != NULL &&
     301           7 :         strcasecmp(authtok_type,"obfuscated_password") == 0) {
     302           0 :         DEBUG(SSSDBG_TRACE_ALL, "Found obfuscated password, "
     303             :                   "trying to convert to cleartext.\n");
     304             : 
     305           0 :         authtok_blob = dp_opt_get_blob(opts->basic, SDAP_DEFAULT_AUTHTOK);
     306           0 :         if (authtok_blob.data == NULL || authtok_blob.length == 0) {
     307           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Missing obfuscated password string.\n");
     308           0 :             return EINVAL;
     309             :         }
     310             : 
     311           0 :         ret = sss_password_decrypt(memctx, (char *) authtok_blob.data,
     312             :                                    &cleartext);
     313           0 :         if (ret != EOK) {
     314           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Cannot convert the obfuscated "
     315             :                       "password back to cleartext\n");
     316           0 :             return ret;
     317             :         }
     318             : 
     319           0 :         authtok_blob.data = (uint8_t *) cleartext;
     320           0 :         authtok_blob.length = strlen(cleartext);
     321           0 :         ret = dp_opt_set_blob(opts->basic, SDAP_DEFAULT_AUTHTOK, authtok_blob);
     322           0 :         talloc_free(cleartext);
     323           0 :         if (ret != EOK) {
     324           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
     325           0 :             return ret;
     326             :         }
     327             : 
     328           0 :         ret = dp_opt_set_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE,
     329             :                                 "password");
     330           0 :         if (ret != EOK) {
     331           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
     332           0 :             return ret;
     333             :         }
     334             :     }
     335             : 
     336           7 :     ret = EOK;
     337           7 :     *_opts = opts;
     338             : 
     339             : done:
     340           7 :     if (ret != EOK) {
     341           0 :         talloc_zfree(opts);
     342             :     }
     343           7 :     return ret;
     344             : }
     345             : 
     346           0 : int ldap_get_sudo_options(struct confdb_ctx *cdb,
     347             :                           const char *conf_path,
     348             :                           struct sdap_options *opts,
     349             :                           bool *use_host_filter,
     350             :                           bool *include_regexp,
     351             :                           bool *include_netgroups)
     352             : {
     353             :     const char *search_base;
     354             :     int ret;
     355             : 
     356             :     /* search base */
     357           0 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
     358           0 :     if (search_base != NULL) {
     359             :         /* set sudo search bases if they are not */
     360           0 :         if (dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE) == NULL) {
     361           0 :             ret = dp_opt_set_string(opts->basic, SDAP_SUDO_SEARCH_BASE,
     362             :                                     search_base);
     363           0 :             if (ret != EOK) {
     364           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Could not set SUDO search base"
     365             :                       "to default value\n");
     366           0 :                 return ret;
     367             :             }
     368             : 
     369           0 :             DEBUG(SSSDBG_FUNC_DATA, "Option %s set to %s\n",
     370             :                   opts->basic[SDAP_SUDO_SEARCH_BASE].opt_name,
     371             :                   dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE));
     372             :         }
     373             :     } else {
     374           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Search base not set, trying to discover it later "
     375             :               "connecting to the LDAP server.\n");
     376             :     }
     377             : 
     378           0 :     ret = sdap_parse_search_base(opts, opts->basic,
     379             :                                  SDAP_SUDO_SEARCH_BASE,
     380           0 :                                  &opts->sdom->sudo_search_bases);
     381           0 :     if (ret != EOK && ret != ENOENT) {
     382           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not parse SUDO search base\n");
     383           0 :         return ret;
     384             :     }
     385             : 
     386             :     /* attrs map */
     387           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     388             :                        native_sudorule_map,
     389             :                        SDAP_OPTS_SUDO,
     390             :                        &opts->sudorule_map);
     391           0 :     if (ret != EOK) {
     392           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not get SUDO attribute map\n");
     393           0 :         return ret;
     394             :     }
     395             : 
     396             :     /* host filter */
     397           0 :     *use_host_filter = dp_opt_get_bool(opts->basic, SDAP_SUDO_USE_HOST_FILTER);
     398           0 :     *include_netgroups = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_NETGROUPS);
     399           0 :     *include_regexp = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_REGEXP);
     400             : 
     401           0 :     return EOK;
     402             : }
     403             : 
     404           0 : int ldap_get_autofs_options(TALLOC_CTX *memctx,
     405             :                             struct confdb_ctx *cdb,
     406             :                             const char *conf_path,
     407             :                             struct sdap_options *opts)
     408             : {
     409             :     const char *search_base;
     410             :     struct sdap_attr_map *default_entry_map;
     411             :     struct sdap_attr_map *default_mobject_map;
     412             :     int ret;
     413             : 
     414             :     /* search base */
     415           0 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
     416           0 :     if (search_base != NULL) {
     417             :         /* set autofs search bases if they are not */
     418           0 :         if (dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE) == NULL) {
     419           0 :             ret = dp_opt_set_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE,
     420             :                                     search_base);
     421           0 :             if (ret != EOK) {
     422           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Could not set autofs search base"
     423             :                       "to default value\n");
     424           0 :                 return ret;
     425             :             }
     426             : 
     427           0 :             DEBUG(SSSDBG_FUNC_DATA, "Option %s set to %s\n",
     428             :                   opts->basic[SDAP_AUTOFS_SEARCH_BASE].opt_name,
     429             :                   dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE));
     430             :         }
     431             :     } else {
     432           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Search base not set, trying to discover it later "
     433             :               "connecting to the LDAP server.\n");
     434             :     }
     435             : 
     436           0 :     ret = sdap_parse_search_base(opts, opts->basic,
     437             :                                  SDAP_AUTOFS_SEARCH_BASE,
     438           0 :                                  &opts->sdom->autofs_search_bases);
     439           0 :     if (ret != EOK && ret != ENOENT) {
     440           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not parse autofs search base\n");
     441           0 :         return ret;
     442             :     }
     443             : 
     444             :     /* attribute maps */
     445           0 :     switch (opts->schema_type) {
     446             :         case SDAP_SCHEMA_RFC2307:
     447           0 :             default_mobject_map = rfc2307_autofs_mobject_map;
     448           0 :             default_entry_map = rfc2307_autofs_entry_map;
     449           0 :             break;
     450             :         case SDAP_SCHEMA_RFC2307BIS:
     451             :         case SDAP_SCHEMA_IPA_V1:
     452             :         case SDAP_SCHEMA_AD:
     453           0 :             default_mobject_map = rfc2307bis_autofs_mobject_map;
     454           0 :             default_entry_map = rfc2307bis_autofs_entry_map;
     455           0 :             break;
     456             :         default:
     457           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown LDAP schema!\n");
     458           0 :             return EINVAL;
     459             :     }
     460             : 
     461           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     462             :                        default_mobject_map,
     463             :                        SDAP_OPTS_AUTOFS_MAP,
     464             :                        &opts->autofs_mobject_map);
     465           0 :     if (ret != EOK) {
     466           0 :         DEBUG(SSSDBG_OP_FAILURE,
     467             :               "Could not get autofs map object attribute map\n");
     468           0 :         return ret;
     469             :     }
     470             : 
     471           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     472             :                        default_entry_map,
     473             :                        SDAP_OPTS_AUTOFS_ENTRY,
     474             :                        &opts->autofs_entry_map);
     475           0 :     if (ret != EOK) {
     476           0 :         DEBUG(SSSDBG_OP_FAILURE,
     477             :               "Could not get autofs entry object attribute map\n");
     478           0 :         return ret;
     479             :     }
     480             : 
     481           0 :     return EOK;
     482             : }
     483             : 
     484          35 : errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx,
     485             :                                struct dp_option *opts, int class,
     486             :                                struct sdap_search_base ***_search_bases)
     487             : {
     488             :     const char *class_name;
     489             :     char *unparsed_base;
     490          35 :     const char *old_filter = NULL;
     491             : 
     492          35 :     *_search_bases = NULL;
     493             : 
     494          35 :     switch (class) {
     495             :     case SDAP_SEARCH_BASE:
     496           7 :         class_name = "DEFAULT";
     497           7 :         break;
     498             :     case SDAP_USER_SEARCH_BASE:
     499           7 :         class_name = "USER";
     500           7 :         old_filter = dp_opt_get_string(opts, SDAP_USER_SEARCH_FILTER);
     501           7 :         break;
     502             :     case SDAP_GROUP_SEARCH_BASE:
     503           7 :         class_name = "GROUP";
     504           7 :         old_filter = dp_opt_get_string(opts, SDAP_GROUP_SEARCH_FILTER);
     505           7 :         break;
     506             :     case SDAP_NETGROUP_SEARCH_BASE:
     507           7 :         class_name = "NETGROUP";
     508           7 :         break;
     509             :     case SDAP_SUDO_SEARCH_BASE:
     510           0 :         class_name = "SUDO";
     511           0 :         break;
     512             :     case SDAP_SERVICE_SEARCH_BASE:
     513           7 :         class_name = "SERVICE";
     514           7 :         break;
     515             :     case SDAP_AUTOFS_SEARCH_BASE:
     516           0 :         class_name = "AUTOFS";
     517           0 :         break;
     518             :     default:
     519           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     520             :               "Unknown search base type: [%d]\n", class);
     521           0 :         class_name = "UNKNOWN";
     522             :         /* Non-fatal */
     523           0 :         break;
     524             :     }
     525             : 
     526          35 :     unparsed_base = dp_opt_get_string(opts, class);
     527          35 :     if (!unparsed_base || unparsed_base[0] == '\0') return ENOENT;
     528             : 
     529          35 :     return common_parse_search_base(mem_ctx, unparsed_base,
     530             :                                     class_name, old_filter,
     531             :                                     _search_bases);
     532             : }
     533             : 
     534          35 : errno_t common_parse_search_base(TALLOC_CTX *mem_ctx,
     535             :                                  const char *unparsed_base,
     536             :                                  const char *class_name,
     537             :                                  const char *old_filter,
     538             :                                  struct sdap_search_base ***_search_bases)
     539             : {
     540             :     errno_t ret;
     541             :     struct sdap_search_base **search_bases;
     542             :     TALLOC_CTX *tmp_ctx;
     543             :     struct ldb_context *ldb;
     544             :     struct ldb_dn *ldn;
     545             :     struct ldb_parse_tree *tree;
     546             :     char **split_bases;
     547             :     char *filter;
     548             :     int count;
     549             :     int i, c;
     550             : 
     551          35 :     tmp_ctx = talloc_new(NULL);
     552          35 :     if (!tmp_ctx) {
     553           0 :         ret = ENOMEM;
     554           0 :         goto done;
     555             :     }
     556             : 
     557             :     /* Create a throwaway LDB context for validating the DN */
     558          35 :     ldb = ldb_init(tmp_ctx, NULL);
     559          35 :     if (!ldb) {
     560           0 :         ret = ENOMEM;
     561           0 :         goto done;
     562             :     }
     563             : 
     564          35 :     ret = split_on_separator(tmp_ctx, unparsed_base, '?', false, false,
     565             :                              &split_bases, &count);
     566          35 :     if (ret != EOK) goto done;
     567             : 
     568             :     /* The split must be either exactly one value or a multiple of
     569             :      * three in order to be valid.
     570             :      * One value: just a base, backwards-compatible with pre-1.7.0 versions
     571             :      * Multiple: search_base?scope?filter[?search_base?scope?filter]*
     572             :      */
     573          35 :     if (count > 1 && (count % 3)) {
     574           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     575             :               "Unparseable search base: [%s][%d]\n", unparsed_base, count);
     576           0 :         ret = EINVAL;
     577           0 :         goto done;
     578             :     }
     579             : 
     580          35 :     if (count == 1) {
     581          35 :         search_bases = talloc_array(tmp_ctx, struct sdap_search_base *, 2);
     582          35 :         if (!search_bases) {
     583           0 :             ret = ENOMEM;
     584           0 :             goto done;
     585             :         }
     586             : 
     587          35 :         if (old_filter != NULL) {
     588             :             /* Using a deprecated ldap_{user,group}_search_filter */
     589           0 :             DEBUG(SSSDBG_IMPORTANT_INFO, "WARNING: Using a deprecated filter "
     590             :                   "option for %s. Please see the documentation on LDAP search "
     591             :                   "bases to see how the obsolete option can be migrated\n",
     592             :                   class_name);
     593           0 :             sss_log(SSS_LOG_NOTICE, "WARNING: Using a deprecated filter option"
     594             :                     "for %s. Please see the documentation on LDAP search bases "
     595             :                     "to see how the obsolete option can be migrated\n",
     596             :                     class_name);
     597             :         }
     598             : 
     599          35 :         ret = sdap_create_search_base(search_bases, unparsed_base,
     600             :                                       LDAP_SCOPE_SUBTREE, old_filter,
     601             :                                       &search_bases[0]);
     602          35 :         if (ret != EOK) {
     603           0 :             DEBUG(SSSDBG_OP_FAILURE, "Cannot create new sdap search base\n");
     604           0 :             goto done;
     605             :         }
     606             : 
     607          35 :         DEBUG(SSSDBG_CONF_SETTINGS,
     608             :               "Search base added: [%s][%s][%s][%s]\n",
     609             :                class_name,
     610             :                search_bases[0]->basedn,
     611             :                "SUBTREE",
     612             :                search_bases[0]->filter ? search_bases[0]->filter : "");
     613             : 
     614          35 :         search_bases[1] = NULL;
     615             :     } else {
     616           0 :         search_bases = talloc_array(tmp_ctx, struct sdap_search_base *,
     617             :                                     (count / 3) + 1);
     618           0 :         if (!search_bases) {
     619           0 :             ret = ENOMEM;
     620           0 :             goto done;
     621             :         }
     622             : 
     623           0 :         i = 0;
     624           0 :         for (c = 0; c < count; c += 3) {
     625           0 :             search_bases[i] = talloc_zero(search_bases,
     626             :                                           struct sdap_search_base);
     627           0 :             if (!search_bases[i]) {
     628           0 :                 ret = ENOMEM;
     629           0 :                 goto done;
     630             :             }
     631             : 
     632           0 :             if (split_bases[c][0] == '\0') {
     633           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     634             :                       "Zero-length search base: [%s]\n", unparsed_base);
     635           0 :                 ret = EINVAL;
     636           0 :                 goto done;
     637             :             }
     638             : 
     639             :             /* Validate the basedn */
     640           0 :             ldn = ldb_dn_new(tmp_ctx, ldb, split_bases[c]);
     641           0 :             if (!ldn) {
     642           0 :                 ret = ENOMEM;
     643           0 :                 goto done;
     644             :             }
     645             : 
     646           0 :             if (!ldb_dn_validate(ldn)) {
     647           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     648             :                       "Invalid base DN [%s]\n",
     649             :                        split_bases[c]);
     650           0 :                 ret = EINVAL;
     651           0 :                 goto done;
     652             :             }
     653           0 :             talloc_zfree(ldn);
     654             : 
     655             :             /* Set the search base DN */
     656           0 :             search_bases[i]->basedn = talloc_strdup(search_bases[i],
     657           0 :                                                     split_bases[c]);
     658           0 :             if (!search_bases[i]->basedn) {
     659           0 :                 ret = ENOMEM;
     660           0 :                 goto done;
     661             :             }
     662             : 
     663             :             /* Set the search scope for this base DN */
     664           0 :             if ((split_bases[c+1][0] == '\0')
     665           0 :                     || strcasecmp(split_bases[c+1], "sub") == 0
     666           0 :                     || strcasecmp(split_bases[c+1], "subtree") == 0) {
     667             :                 /* If unspecified, default to subtree */
     668           0 :                 search_bases[i]->scope = LDAP_SCOPE_SUBTREE;
     669           0 :             } else if (strcasecmp(split_bases[c+1], "one") == 0
     670           0 :                     || strcasecmp(split_bases[c+1], "onelevel") == 0) {
     671           0 :                 search_bases[i]->scope = LDAP_SCOPE_ONELEVEL;
     672           0 :             } else if (strcasecmp(split_bases[c+1], "base") == 0) {
     673           0 :                 search_bases[i]->scope = LDAP_SCOPE_BASE;
     674             :             } else {
     675           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     676             :                       "Unknown search scope: [%s]\n", split_bases[c+1]);
     677           0 :                 ret = EINVAL;
     678           0 :                 goto done;
     679             :             }
     680             : 
     681             :             /* Get a specialized filter if provided */
     682           0 :             if (split_bases[c+2][0] == '\0') {
     683           0 :                 search_bases[i]->filter = NULL;
     684             :             } else {
     685           0 :                 if (split_bases[c+2][0] != '(') {
     686             :                     /* Filters need to be enclosed in parentheses
     687             :                      * to be validated properly by ldb_parse_tree()
     688             :                      */
     689           0 :                     filter = talloc_asprintf(tmp_ctx, "(%s)",
     690           0 :                                              split_bases[c+2]);
     691             :                 } else {
     692           0 :                     filter = talloc_strdup(tmp_ctx, split_bases[c+2]);
     693             :                 }
     694           0 :                 if (!filter) {
     695           0 :                     ret = ENOMEM;
     696           0 :                     goto done;
     697             :                 }
     698             : 
     699           0 :                 tree = ldb_parse_tree(tmp_ctx, filter);
     700           0 :                 if(!tree) {
     701           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     702             :                           "Invalid search filter: [%s]\n", filter);
     703           0 :                     ret = EINVAL;
     704           0 :                     goto done;
     705             :                 }
     706           0 :                 talloc_zfree(tree);
     707             : 
     708           0 :                 search_bases[i]->filter = talloc_steal(search_bases[i],
     709             :                                                        filter);
     710             :             }
     711             : 
     712           0 :             DEBUG(SSSDBG_CONF_SETTINGS,
     713             :                   "Search base added: [%s][%s][%s][%s]\n",
     714             :                    class_name,
     715             :                    search_bases[i]->basedn,
     716             :                    split_bases[c+1][0] ? split_bases[c+1] : "SUBTREE",
     717             :                    search_bases[i]->filter ? search_bases[i]->filter : "");
     718             : 
     719           0 :             i++;
     720             :         }
     721           0 :         search_bases[i] = NULL;
     722             :     }
     723             : 
     724          35 :     *_search_bases = talloc_steal(mem_ctx, search_bases);
     725          35 :     ret = EOK;
     726             : 
     727             : done:
     728          35 :     talloc_free(tmp_ctx);
     729          35 :     return ret;
     730             : }

Generated by: LCOV version 1.10