LCOV - code coverage report
Current view: top level - providers/ldap - ldap_options.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 109 322 33.9 %
Date: 2016-06-29 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           9 : 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           9 :     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           9 :     opts = talloc_zero(memctx, struct sdap_options);
      57           9 :     if (!opts) return ENOMEM;
      58             : 
      59           9 :     ret = sdap_domain_add(opts, dom, NULL);
      60           9 :     if (ret != EOK) {
      61           0 :         goto done;
      62             :     }
      63             : 
      64           9 :     ret = dp_get_options(opts, cdb, conf_path,
      65             :                          default_basic_opts,
      66             :                          SDAP_OPTS_BASIC,
      67             :                          &opts->basic);
      68           9 :     if (ret != EOK) {
      69           0 :         goto done;
      70             :     }
      71             : 
      72             :     /* Handle search bases */
      73           9 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
      74           9 :     if (search_base != NULL) {
      75             :         /* set user/group/netgroup search bases if they are not */
      76          45 :         for (o = 0; search_base_options[o] != -1; o++) {
      77          36 :             if (NULL == dp_opt_get_string(opts->basic, search_base_options[o])) {
      78          18 :                 ret = dp_opt_set_string(opts->basic, search_base_options[o],
      79             :                                         search_base);
      80          18 :                 if (ret != EOK) {
      81           0 :                     goto done;
      82             :                 }
      83          18 :                 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           9 :     ret = sdap_parse_search_base(opts, opts->basic,
      97             :                                  SDAP_SEARCH_BASE,
      98           9 :                                  &opts->sdom->search_bases);
      99           9 :     if (ret != EOK && ret != ENOENT) goto done;
     100             : 
     101             :     /* User search */
     102           9 :     ret = sdap_parse_search_base(opts, opts->basic,
     103             :                                  SDAP_USER_SEARCH_BASE,
     104           9 :                                  &opts->sdom->user_search_bases);
     105           9 :     if (ret != EOK && ret != ENOENT) goto done;
     106             : 
     107             :     /* Group search base */
     108           9 :     ret = sdap_parse_search_base(opts, opts->basic,
     109             :                                  SDAP_GROUP_SEARCH_BASE,
     110           9 :                                  &opts->sdom->group_search_bases);
     111           9 :     if (ret != EOK && ret != ENOENT) goto done;
     112             : 
     113             :     /* Netgroup search */
     114           9 :     ret = sdap_parse_search_base(opts, opts->basic,
     115             :                                  SDAP_NETGROUP_SEARCH_BASE,
     116           9 :                                  &opts->sdom->netgroup_search_bases);
     117           9 :     if (ret != EOK && ret != ENOENT) goto done;
     118             : 
     119             :     /* Service search */
     120           9 :     ret = sdap_parse_search_base(opts, opts->basic,
     121             :                                  SDAP_SERVICE_SEARCH_BASE,
     122           9 :                                  &opts->sdom->service_search_bases);
     123           9 :     if (ret != EOK && ret != ENOENT) goto done;
     124             : 
     125           9 :     pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY);
     126           9 :     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           9 :     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           9 :     ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
     143             :                          CONFDB_PAM_CRED_TIMEOUT, 0,
     144             :                          &offline_credentials_expiration);
     145           9 :     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           9 :     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           9 :     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           9 :     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           9 :     ldap_deref = dp_opt_get_string(opts->basic, SDAP_DEREF);
     185           9 :     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             :         if (ret != EOK) {
     203             :             DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
     204             :             goto done;
     205             :         }
     206             :     }
     207             : #endif
     208             : 
     209             :     /* schema type */
     210           9 :     schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA);
     211           9 :     if (strcasecmp(schema, "rfc2307") == 0) {
     212           0 :         opts->schema_type = SDAP_SCHEMA_RFC2307;
     213           0 :         default_attr_map = generic_attr_map;
     214           0 :         default_user_map = rfc2307_user_map;
     215           0 :         default_group_map = rfc2307_group_map;
     216           0 :         default_netgroup_map = netgroup_map;
     217           0 :         default_service_map = service_map;
     218             :     } else
     219           9 :     if (strcasecmp(schema, "rfc2307bis") == 0) {
     220           9 :         opts->schema_type = SDAP_SCHEMA_RFC2307BIS;
     221           9 :         default_attr_map = generic_attr_map;
     222           9 :         default_user_map = rfc2307bis_user_map;
     223           9 :         default_group_map = rfc2307bis_group_map;
     224           9 :         default_netgroup_map = netgroup_map;
     225           9 :         default_service_map = service_map;
     226             :     } else
     227           0 :     if (strcasecmp(schema, "IPA") == 0) {
     228           0 :         opts->schema_type = SDAP_SCHEMA_IPA_V1;
     229           0 :         default_attr_map = gen_ipa_attr_map;
     230           0 :         default_user_map = rfc2307bis_user_map;
     231           0 :         default_group_map = rfc2307bis_group_map;
     232           0 :         default_netgroup_map = netgroup_map;
     233           0 :         default_service_map = service_map;
     234             :     } else
     235           0 :     if (strcasecmp(schema, "AD") == 0) {
     236           0 :         opts->schema_type = SDAP_SCHEMA_AD;
     237           0 :         default_attr_map = gen_ad_attr_map;
     238           0 :         default_user_map = gen_ad2008r2_user_map;
     239           0 :         default_group_map = gen_ad2008r2_group_map;
     240           0 :         default_netgroup_map = netgroup_map;
     241           0 :         default_service_map = service_map;
     242             :     } else {
     243           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized schema type: %s\n", schema);
     244           0 :         ret = EINVAL;
     245           0 :         goto done;
     246             :     }
     247             : 
     248           9 :     ret = sdap_get_map(opts, cdb, conf_path,
     249             :                        default_attr_map,
     250             :                        SDAP_AT_GENERAL,
     251             :                        &opts->gen_map);
     252           9 :     if (ret != EOK) {
     253           0 :         goto done;
     254             :     }
     255             : 
     256           9 :     ret = sdap_get_map(opts, cdb, conf_path,
     257             :                        default_user_map,
     258             :                        SDAP_OPTS_USER,
     259             :                        &opts->user_map);
     260           9 :     if (ret != EOK) {
     261           0 :         goto done;
     262             :     }
     263             : 
     264           9 :     ret = sdap_extend_map_with_list(opts, opts, SDAP_USER_EXTRA_ATTRS,
     265             :                                     opts->user_map, SDAP_OPTS_USER,
     266             :                                     &opts->user_map, &opts->user_map_cnt);
     267           9 :     if (ret != EOK) {
     268           0 :         goto done;
     269             :     }
     270             : 
     271           9 :     ret = sdap_get_map(opts, cdb, conf_path,
     272             :                        default_group_map,
     273             :                        SDAP_OPTS_GROUP,
     274             :                        &opts->group_map);
     275           9 :     if (ret != EOK) {
     276           0 :         goto done;
     277             :     }
     278             : 
     279           9 :     ret = sdap_get_map(opts, cdb, conf_path,
     280             :                        default_netgroup_map,
     281             :                        SDAP_OPTS_NETGROUP,
     282             :                        &opts->netgroup_map);
     283           9 :     if (ret != EOK) {
     284           0 :         goto done;
     285             :     }
     286             : 
     287           9 :     ret = sdap_get_map(opts, cdb, conf_path,
     288             :                        default_service_map,
     289             :                        SDAP_OPTS_SERVICES,
     290             :                        &opts->service_map);
     291           9 :     if (ret != EOK) {
     292           0 :         goto done;
     293             :     }
     294             : 
     295             :     /* If there is no KDC, try the deprecated krb5_kdcip option, too */
     296             :     /* FIXME - this can be removed in a future version */
     297           9 :     ret = krb5_try_kdcip(cdb, conf_path, opts->basic, SDAP_KRB5_KDC);
     298           9 :     if (ret != EOK) {
     299           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sss_krb5_try_kdcip failed.\n");
     300           0 :         goto done;
     301             :     }
     302             : 
     303           9 :     authtok_type = dp_opt_get_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE);
     304          18 :     if (authtok_type != NULL &&
     305           9 :         strcasecmp(authtok_type,"obfuscated_password") == 0) {
     306           0 :         DEBUG(SSSDBG_TRACE_ALL, "Found obfuscated password, "
     307             :                   "trying to convert to cleartext.\n");
     308             : 
     309           0 :         authtok_blob = dp_opt_get_blob(opts->basic, SDAP_DEFAULT_AUTHTOK);
     310           0 :         if (authtok_blob.data == NULL || authtok_blob.length == 0) {
     311           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Missing obfuscated password string.\n");
     312           0 :             ret = EINVAL;
     313           0 :             goto done;
     314             :         }
     315             : 
     316           0 :         ret = sss_password_decrypt(memctx, (char *) authtok_blob.data,
     317             :                                    &cleartext);
     318           0 :         if (ret != EOK) {
     319           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Cannot convert the obfuscated "
     320             :                       "password back to cleartext\n");
     321           0 :             goto done;
     322             :         }
     323             : 
     324           0 :         authtok_blob.data = (uint8_t *) cleartext;
     325           0 :         authtok_blob.length = strlen(cleartext);
     326           0 :         ret = dp_opt_set_blob(opts->basic, SDAP_DEFAULT_AUTHTOK, authtok_blob);
     327           0 :         talloc_free(cleartext);
     328           0 :         if (ret != EOK) {
     329           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
     330           0 :             goto done;
     331             :         }
     332             : 
     333           0 :         ret = dp_opt_set_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE,
     334             :                                 "password");
     335           0 :         if (ret != EOK) {
     336           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n");
     337           0 :             goto done;
     338             :         }
     339             :     }
     340             : 
     341           9 :     ret = EOK;
     342           9 :     *_opts = opts;
     343             : 
     344             : done:
     345           9 :     if (ret != EOK) {
     346           0 :         talloc_zfree(opts);
     347             :     }
     348           9 :     return ret;
     349             : }
     350             : 
     351           0 : int ldap_get_sudo_options(struct confdb_ctx *cdb,
     352             :                           const char *conf_path,
     353             :                           struct sdap_options *opts,
     354             :                           bool *use_host_filter,
     355             :                           bool *include_regexp,
     356             :                           bool *include_netgroups)
     357             : {
     358             :     const char *search_base;
     359             :     int ret;
     360             : 
     361             :     /* search base */
     362           0 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
     363           0 :     if (search_base != NULL) {
     364             :         /* set sudo search bases if they are not */
     365           0 :         if (dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE) == NULL) {
     366           0 :             ret = dp_opt_set_string(opts->basic, SDAP_SUDO_SEARCH_BASE,
     367             :                                     search_base);
     368           0 :             if (ret != EOK) {
     369           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Could not set SUDO search base"
     370             :                       "to default value\n");
     371           0 :                 return ret;
     372             :             }
     373             : 
     374           0 :             DEBUG(SSSDBG_FUNC_DATA, "Option %s set to %s\n",
     375             :                   opts->basic[SDAP_SUDO_SEARCH_BASE].opt_name,
     376             :                   dp_opt_get_string(opts->basic, SDAP_SUDO_SEARCH_BASE));
     377             :         }
     378             :     } else {
     379           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Search base not set, trying to discover it later "
     380             :               "connecting to the LDAP server.\n");
     381             :     }
     382             : 
     383           0 :     ret = sdap_parse_search_base(opts, opts->basic,
     384             :                                  SDAP_SUDO_SEARCH_BASE,
     385           0 :                                  &opts->sdom->sudo_search_bases);
     386           0 :     if (ret != EOK && ret != ENOENT) {
     387           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not parse SUDO search base\n");
     388           0 :         return ret;
     389             :     }
     390             : 
     391             :     /* attrs map */
     392           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     393             :                        native_sudorule_map,
     394             :                        SDAP_OPTS_SUDO,
     395             :                        &opts->sudorule_map);
     396           0 :     if (ret != EOK) {
     397           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not get SUDO attribute map\n");
     398           0 :         return ret;
     399             :     }
     400             : 
     401             :     /* host filter */
     402           0 :     *use_host_filter = dp_opt_get_bool(opts->basic, SDAP_SUDO_USE_HOST_FILTER);
     403           0 :     *include_netgroups = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_NETGROUPS);
     404           0 :     *include_regexp = dp_opt_get_bool(opts->basic, SDAP_SUDO_INCLUDE_REGEXP);
     405             : 
     406           0 :     return EOK;
     407             : }
     408             : 
     409           0 : int ldap_get_autofs_options(TALLOC_CTX *memctx,
     410             :                             struct confdb_ctx *cdb,
     411             :                             const char *conf_path,
     412             :                             struct sdap_options *opts)
     413             : {
     414             :     const char *search_base;
     415             :     struct sdap_attr_map *default_entry_map;
     416             :     struct sdap_attr_map *default_mobject_map;
     417             :     int ret;
     418             : 
     419             :     /* search base */
     420           0 :     search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
     421           0 :     if (search_base != NULL) {
     422             :         /* set autofs search bases if they are not */
     423           0 :         if (dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE) == NULL) {
     424           0 :             ret = dp_opt_set_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE,
     425             :                                     search_base);
     426           0 :             if (ret != EOK) {
     427           0 :                 DEBUG(SSSDBG_OP_FAILURE, "Could not set autofs search base"
     428             :                       "to default value\n");
     429           0 :                 return ret;
     430             :             }
     431             : 
     432           0 :             DEBUG(SSSDBG_FUNC_DATA, "Option %s set to %s\n",
     433             :                   opts->basic[SDAP_AUTOFS_SEARCH_BASE].opt_name,
     434             :                   dp_opt_get_string(opts->basic, SDAP_AUTOFS_SEARCH_BASE));
     435             :         }
     436             :     } else {
     437           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Search base not set, trying to discover it later "
     438             :               "connecting to the LDAP server.\n");
     439             :     }
     440             : 
     441           0 :     ret = sdap_parse_search_base(opts, opts->basic,
     442             :                                  SDAP_AUTOFS_SEARCH_BASE,
     443           0 :                                  &opts->sdom->autofs_search_bases);
     444           0 :     if (ret != EOK && ret != ENOENT) {
     445           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not parse autofs search base\n");
     446           0 :         return ret;
     447             :     }
     448             : 
     449             :     /* attribute maps */
     450           0 :     switch (opts->schema_type) {
     451             :         case SDAP_SCHEMA_RFC2307:
     452           0 :             default_mobject_map = rfc2307_autofs_mobject_map;
     453           0 :             default_entry_map = rfc2307_autofs_entry_map;
     454           0 :             break;
     455             :         case SDAP_SCHEMA_RFC2307BIS:
     456             :         case SDAP_SCHEMA_IPA_V1:
     457             :         case SDAP_SCHEMA_AD:
     458           0 :             default_mobject_map = rfc2307bis_autofs_mobject_map;
     459           0 :             default_entry_map = rfc2307bis_autofs_entry_map;
     460           0 :             break;
     461             :         default:
     462           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown LDAP schema!\n");
     463           0 :             return EINVAL;
     464             :     }
     465             : 
     466           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     467             :                        default_mobject_map,
     468             :                        SDAP_OPTS_AUTOFS_MAP,
     469             :                        &opts->autofs_mobject_map);
     470           0 :     if (ret != EOK) {
     471           0 :         DEBUG(SSSDBG_OP_FAILURE,
     472             :               "Could not get autofs map object attribute map\n");
     473           0 :         return ret;
     474             :     }
     475             : 
     476           0 :     ret = sdap_get_map(opts, cdb, conf_path,
     477             :                        default_entry_map,
     478             :                        SDAP_OPTS_AUTOFS_ENTRY,
     479             :                        &opts->autofs_entry_map);
     480           0 :     if (ret != EOK) {
     481           0 :         DEBUG(SSSDBG_OP_FAILURE,
     482             :               "Could not get autofs entry object attribute map\n");
     483           0 :         return ret;
     484             :     }
     485             : 
     486           0 :     return EOK;
     487             : }
     488             : 
     489          45 : errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx,
     490             :                                struct dp_option *opts, int class,
     491             :                                struct sdap_search_base ***_search_bases)
     492             : {
     493             :     const char *class_name;
     494             :     char *unparsed_base;
     495          45 :     const char *old_filter = NULL;
     496             : 
     497          45 :     *_search_bases = NULL;
     498             : 
     499          45 :     switch (class) {
     500             :     case SDAP_SEARCH_BASE:
     501           9 :         class_name = "DEFAULT";
     502           9 :         break;
     503             :     case SDAP_USER_SEARCH_BASE:
     504           9 :         class_name = "USER";
     505           9 :         old_filter = dp_opt_get_string(opts, SDAP_USER_SEARCH_FILTER);
     506           9 :         break;
     507             :     case SDAP_GROUP_SEARCH_BASE:
     508           9 :         class_name = "GROUP";
     509           9 :         old_filter = dp_opt_get_string(opts, SDAP_GROUP_SEARCH_FILTER);
     510           9 :         break;
     511             :     case SDAP_NETGROUP_SEARCH_BASE:
     512           9 :         class_name = "NETGROUP";
     513           9 :         break;
     514             :     case SDAP_SUDO_SEARCH_BASE:
     515           0 :         class_name = "SUDO";
     516           0 :         break;
     517             :     case SDAP_SERVICE_SEARCH_BASE:
     518           9 :         class_name = "SERVICE";
     519           9 :         break;
     520             :     case SDAP_AUTOFS_SEARCH_BASE:
     521           0 :         class_name = "AUTOFS";
     522           0 :         break;
     523             :     default:
     524           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     525             :               "Unknown search base type: [%d]\n", class);
     526           0 :         class_name = "UNKNOWN";
     527             :         /* Non-fatal */
     528           0 :         break;
     529             :     }
     530             : 
     531          45 :     unparsed_base = dp_opt_get_string(opts, class);
     532          45 :     if (!unparsed_base || unparsed_base[0] == '\0') return ENOENT;
     533             : 
     534          45 :     return common_parse_search_base(mem_ctx, unparsed_base,
     535             :                                     class_name, old_filter,
     536             :                                     _search_bases);
     537             : }
     538             : 
     539          45 : errno_t common_parse_search_base(TALLOC_CTX *mem_ctx,
     540             :                                  const char *unparsed_base,
     541             :                                  const char *class_name,
     542             :                                  const char *old_filter,
     543             :                                  struct sdap_search_base ***_search_bases)
     544             : {
     545             :     errno_t ret;
     546             :     struct sdap_search_base **search_bases;
     547             :     TALLOC_CTX *tmp_ctx;
     548             :     struct ldb_context *ldb;
     549             :     struct ldb_dn *ldn;
     550             :     struct ldb_parse_tree *tree;
     551             :     char **split_bases;
     552             :     char *filter;
     553             :     int count;
     554             :     int i, c;
     555             : 
     556          45 :     tmp_ctx = talloc_new(NULL);
     557          45 :     if (!tmp_ctx) {
     558           0 :         ret = ENOMEM;
     559           0 :         goto done;
     560             :     }
     561             : 
     562             :     /* Create a throwaway LDB context for validating the DN */
     563          45 :     ldb = ldb_init(tmp_ctx, NULL);
     564          45 :     if (!ldb) {
     565           0 :         ret = ENOMEM;
     566           0 :         goto done;
     567             :     }
     568             : 
     569          45 :     ret = split_on_separator(tmp_ctx, unparsed_base, '?', false, false,
     570             :                              &split_bases, &count);
     571          45 :     if (ret != EOK) goto done;
     572             : 
     573             :     /* The split must be either exactly one value or a multiple of
     574             :      * three in order to be valid.
     575             :      * One value: just a base, backwards-compatible with pre-1.7.0 versions
     576             :      * Multiple: search_base?scope?filter[?search_base?scope?filter]*
     577             :      */
     578          45 :     if (count > 1 && (count % 3)) {
     579           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     580             :               "Unparseable search base: [%s][%d]\n", unparsed_base, count);
     581           0 :         ret = EINVAL;
     582           0 :         goto done;
     583             :     }
     584             : 
     585          45 :     if (count == 1) {
     586          45 :         search_bases = talloc_array(tmp_ctx, struct sdap_search_base *, 2);
     587          45 :         if (!search_bases) {
     588           0 :             ret = ENOMEM;
     589           0 :             goto done;
     590             :         }
     591             : 
     592          45 :         if (old_filter != NULL) {
     593             :             /* Using a deprecated ldap_{user,group}_search_filter */
     594           0 :             DEBUG(SSSDBG_IMPORTANT_INFO, "WARNING: Using a deprecated filter "
     595             :                   "option for %s. Please see the documentation on LDAP search "
     596             :                   "bases to see how the obsolete option can be migrated\n",
     597             :                   class_name);
     598           0 :             sss_log(SSS_LOG_NOTICE, "WARNING: Using a deprecated filter option"
     599             :                     "for %s. Please see the documentation on LDAP search bases "
     600             :                     "to see how the obsolete option can be migrated\n",
     601             :                     class_name);
     602             :         }
     603             : 
     604          45 :         ret = sdap_create_search_base(search_bases, unparsed_base,
     605             :                                       LDAP_SCOPE_SUBTREE, old_filter,
     606             :                                       &search_bases[0]);
     607          45 :         if (ret != EOK) {
     608           0 :             DEBUG(SSSDBG_OP_FAILURE, "Cannot create new sdap search base\n");
     609           0 :             goto done;
     610             :         }
     611             : 
     612          45 :         DEBUG(SSSDBG_CONF_SETTINGS,
     613             :               "Search base added: [%s][%s][%s][%s]\n",
     614             :                class_name,
     615             :                search_bases[0]->basedn,
     616             :                "SUBTREE",
     617             :                search_bases[0]->filter ? search_bases[0]->filter : "");
     618             : 
     619          45 :         search_bases[1] = NULL;
     620             :     } else {
     621           0 :         search_bases = talloc_array(tmp_ctx, struct sdap_search_base *,
     622             :                                     (count / 3) + 1);
     623           0 :         if (!search_bases) {
     624           0 :             ret = ENOMEM;
     625           0 :             goto done;
     626             :         }
     627             : 
     628           0 :         i = 0;
     629           0 :         for (c = 0; c < count; c += 3) {
     630           0 :             search_bases[i] = talloc_zero(search_bases,
     631             :                                           struct sdap_search_base);
     632           0 :             if (!search_bases[i]) {
     633           0 :                 ret = ENOMEM;
     634           0 :                 goto done;
     635             :             }
     636             : 
     637           0 :             if (split_bases[c][0] == '\0') {
     638           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     639             :                       "Zero-length search base: [%s]\n", unparsed_base);
     640           0 :                 ret = EINVAL;
     641           0 :                 goto done;
     642             :             }
     643             : 
     644             :             /* Validate the basedn */
     645           0 :             ldn = ldb_dn_new(tmp_ctx, ldb, split_bases[c]);
     646           0 :             if (!ldn) {
     647           0 :                 ret = ENOMEM;
     648           0 :                 goto done;
     649             :             }
     650             : 
     651           0 :             if (!ldb_dn_validate(ldn)) {
     652           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     653             :                       "Invalid base DN [%s]\n",
     654             :                        split_bases[c]);
     655           0 :                 ret = EINVAL;
     656           0 :                 goto done;
     657             :             }
     658           0 :             talloc_zfree(ldn);
     659             : 
     660             :             /* Set the search base DN */
     661           0 :             search_bases[i]->basedn = talloc_strdup(search_bases[i],
     662           0 :                                                     split_bases[c]);
     663           0 :             if (!search_bases[i]->basedn) {
     664           0 :                 ret = ENOMEM;
     665           0 :                 goto done;
     666             :             }
     667             : 
     668             :             /* Set the search scope for this base DN */
     669           0 :             if ((split_bases[c+1][0] == '\0')
     670           0 :                     || strcasecmp(split_bases[c+1], "sub") == 0
     671           0 :                     || strcasecmp(split_bases[c+1], "subtree") == 0) {
     672             :                 /* If unspecified, default to subtree */
     673           0 :                 search_bases[i]->scope = LDAP_SCOPE_SUBTREE;
     674           0 :             } else if (strcasecmp(split_bases[c+1], "one") == 0
     675           0 :                     || strcasecmp(split_bases[c+1], "onelevel") == 0) {
     676           0 :                 search_bases[i]->scope = LDAP_SCOPE_ONELEVEL;
     677           0 :             } else if (strcasecmp(split_bases[c+1], "base") == 0) {
     678           0 :                 search_bases[i]->scope = LDAP_SCOPE_BASE;
     679             :             } else {
     680           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     681             :                       "Unknown search scope: [%s]\n", split_bases[c+1]);
     682           0 :                 ret = EINVAL;
     683           0 :                 goto done;
     684             :             }
     685             : 
     686             :             /* Get a specialized filter if provided */
     687           0 :             if (split_bases[c+2][0] == '\0') {
     688           0 :                 search_bases[i]->filter = NULL;
     689             :             } else {
     690           0 :                 if (split_bases[c+2][0] != '(') {
     691             :                     /* Filters need to be enclosed in parentheses
     692             :                      * to be validated properly by ldb_parse_tree()
     693             :                      */
     694           0 :                     filter = talloc_asprintf(tmp_ctx, "(%s)",
     695           0 :                                              split_bases[c+2]);
     696             :                 } else {
     697           0 :                     filter = talloc_strdup(tmp_ctx, split_bases[c+2]);
     698             :                 }
     699           0 :                 if (!filter) {
     700           0 :                     ret = ENOMEM;
     701           0 :                     goto done;
     702             :                 }
     703             : 
     704           0 :                 tree = ldb_parse_tree(tmp_ctx, filter);
     705           0 :                 if(!tree) {
     706           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     707             :                           "Invalid search filter: [%s]\n", filter);
     708           0 :                     ret = EINVAL;
     709           0 :                     goto done;
     710             :                 }
     711           0 :                 talloc_zfree(tree);
     712             : 
     713           0 :                 search_bases[i]->filter = talloc_steal(search_bases[i],
     714             :                                                        filter);
     715             :             }
     716             : 
     717           0 :             DEBUG(SSSDBG_CONF_SETTINGS,
     718             :                   "Search base added: [%s][%s][%s][%s]\n",
     719             :                    class_name,
     720             :                    search_bases[i]->basedn,
     721             :                    split_bases[c+1][0] ? split_bases[c+1] : "SUBTREE",
     722             :                    search_bases[i]->filter ? search_bases[i]->filter : "");
     723             : 
     724           0 :             i++;
     725             :         }
     726           0 :         search_bases[i] = NULL;
     727             :     }
     728             : 
     729          45 :     *_search_bases = talloc_steal(mem_ctx, search_bases);
     730          45 :     ret = EOK;
     731             : 
     732             : done:
     733          45 :     talloc_free(tmp_ctx);
     734          45 :     return ret;
     735             : }

Generated by: LCOV version 1.10