LCOV - code coverage report
Current view: top level - providers/data_provider - dp_targets.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 223 6.3 %
Date: 2016-06-29 Functions: 2 14 14.3 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2016 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 <talloc.h>
      22             : #include <dlfcn.h>
      23             : 
      24             : #include "config.h"
      25             : #include "providers/data_provider/dp.h"
      26             : #include "providers/data_provider/dp_private.h"
      27             : #include "providers/data_provider/dp_builtin.h"
      28             : #include "providers/backend.h"
      29             : #include "util/util.h"
      30             : 
      31             : #define DP_TARGET_INIT_FN "sssm_%s_%s_init"
      32             : 
      33             : #define DP_PROVIDER_OPT "%s_provider"
      34             : #define DP_ACCESS_PERMIT "permit"
      35             : #define DP_ACCESS_DENY "deny"
      36             : #define DP_NO_PROVIDER "none"
      37             : 
      38           0 : bool _dp_target_enabled(struct data_provider *provider,
      39             :                         const char *module_name,
      40             :                         ...)
      41             : {
      42             :     struct dp_target *target;
      43             :     enum dp_targets type;
      44             :     va_list ap;
      45             :     bool bret;
      46             : 
      47           0 :     if (provider == NULL || provider->targets == NULL) {
      48           0 :         return false;
      49             :     }
      50             : 
      51           0 :     bret = false;
      52           0 :     va_start(ap, module_name);
      53           0 :     while ((type = va_arg(ap, enum dp_targets)) != DP_TARGET_SENTINEL) {
      54           0 :         target = provider->targets[type];
      55           0 :         if (target == NULL || target->module_name == NULL) {
      56           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Uninitialized target %s\n",
      57             :                   dp_target_to_string(type));
      58           0 :             continue;
      59             :         }
      60             : 
      61           0 :         if (module_name == NULL) {
      62           0 :             bret = true;
      63           0 :             goto done;
      64             :         }
      65             : 
      66           0 :         if (strcmp(target->module_name, module_name) == 0) {
      67           0 :             bret = true;
      68           0 :             goto done;
      69             :         }
      70             :     }
      71             : 
      72             : done:
      73           0 :     va_end(ap);
      74           0 :     return bret;
      75             : }
      76             : 
      77           0 : struct dp_module *dp_target_module(struct data_provider *provider,
      78             :                                    enum dp_targets target)
      79             : {
      80           0 :     if (provider == NULL || provider->targets == NULL) {
      81           0 :         return NULL;
      82             :     }
      83             : 
      84           0 :     if (target >= DP_TARGET_SENTINEL || provider->targets[target] == NULL) {
      85           0 :         return NULL;
      86             :     }
      87             : 
      88           0 :     return provider->targets[target]->module;
      89             : }
      90             : 
      91          36 : const char *dp_target_to_string(enum dp_targets target)
      92             : {
      93          36 :     switch (target) {
      94             :     case DPT_ID:
      95           4 :         return "id";
      96             :     case DPT_AUTH:
      97           4 :         return "auth";
      98             :     case DPT_ACCESS:
      99           4 :         return "access";
     100             :     case DPT_CHPASS:
     101           4 :         return "chpass";
     102             :     case DPT_SUDO:
     103           4 :         return "sudo";
     104             :     case DPT_AUTOFS:
     105           4 :         return "autofs";
     106             :     case DPT_SELINUX:
     107           4 :         return "selinux";
     108             :     case DPT_HOSTID:
     109           4 :         return "hostid";
     110             :     case DPT_SUBDOMAINS:
     111           4 :         return "subdomains";
     112             :     case DP_TARGET_SENTINEL:
     113           0 :         return NULL;
     114             :     }
     115             : 
     116           0 :     return NULL;
     117             : }
     118             : 
     119           5 : bool dp_target_initialized(struct dp_target **targets, enum dp_targets type)
     120             : {
     121           5 :     if (targets == NULL || targets[type] == NULL) {
     122           0 :         return false;
     123             :     }
     124             : 
     125           5 :     return targets[type]->initialized;
     126             : }
     127             : 
     128           0 : static bool dp_target_sudo_enabled(struct be_ctx *be_ctx)
     129             : {
     130             :     TALLOC_CTX *tmp_ctx;
     131             :     char **services;
     132             :     char *module;
     133             :     bool responder_enabled;
     134             :     bool enable;
     135             :     errno_t ret;
     136             :     int i;
     137             : 
     138             :     /* Do not disable it in case of error. */
     139           0 :     enable = true;
     140             : 
     141           0 :     tmp_ctx = talloc_new(NULL);
     142           0 :     if (tmp_ctx == NULL) {
     143           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     144           0 :         return enable;
     145             :     }
     146             : 
     147           0 :     ret = confdb_get_string_as_list(be_ctx->cdb, tmp_ctx,
     148             :                                     CONFDB_MONITOR_CONF_ENTRY,
     149             :                                     CONFDB_MONITOR_ACTIVE_SERVICES, &services);
     150           0 :     if (ret != EOK) {
     151           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to read from confdb [%d]: %s\n",
     152             :               ret, sss_strerror(ret));
     153           0 :         goto done;
     154             :     }
     155             : 
     156           0 :     responder_enabled = false;
     157           0 :     for (i = 0; services[i] != NULL; i++) {
     158           0 :         if (strcmp(services[i], "sudo") == 0) {
     159           0 :             responder_enabled = true;
     160           0 :             break;
     161             :         }
     162             :     }
     163             : 
     164           0 :     ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
     165             :                             CONFDB_DOMAIN_SUDO_PROVIDER, NULL, &module);
     166           0 :     if (ret != EOK) {
     167           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to read from confdb [%d]: %s\n",
     168             :               ret, sss_strerror(ret));
     169           0 :         goto done;
     170             :     }
     171             : 
     172           0 :     if (!responder_enabled) {
     173           0 :         if (module == NULL) {
     174           0 :             DEBUG(SSSDBG_TRACE_FUNC, "SUDO is not listed in services, "
     175             :                   "disabling SUDO module.\n");
     176           0 :             enable = false;
     177           0 :             goto done;
     178           0 :         } else if (strcmp(module, DP_NO_PROVIDER) != 0) {
     179           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "SUDO provider is set, but it is not "
     180             :                   "listed in active services. SUDO support will not work!\n");
     181           0 :             enable = true;
     182           0 :             goto done;
     183             :         }
     184             :     }
     185             : 
     186           0 :     enable = true;
     187             : 
     188             : done:
     189           0 :     talloc_free(tmp_ctx);
     190           0 :     return enable;
     191             : }
     192             : 
     193           0 : static const char *dp_target_module_name(struct dp_target **targets,
     194             :                                          enum dp_targets type)
     195             : {
     196           0 :     if (targets[type] == NULL) {
     197           0 :         return NULL;
     198             :     }
     199             : 
     200           0 :     return targets[type]->module_name;
     201             : }
     202             : 
     203           0 : static const char *dp_target_default_module(struct dp_target **targets,
     204             :                                             enum dp_targets target)
     205             : {
     206           0 :     switch (target) {
     207             :     case DPT_ID:
     208           0 :         return NULL;
     209             :     case DPT_ACCESS:
     210           0 :         return "permit";
     211             :     case DPT_CHPASS:
     212           0 :         return dp_target_module_name(targets, DPT_AUTH);
     213             :     case DP_TARGET_SENTINEL:
     214           0 :         return NULL;
     215             :     default:
     216           0 :         return dp_target_module_name(targets, DPT_ID);
     217             :     }
     218             : }
     219             : 
     220           0 : static errno_t dp_target_run_constructor(struct dp_target *target,
     221             :                                          struct be_ctx *be_ctx)
     222             : {
     223           0 :     char *fn_name = NULL;
     224             :     dp_target_init_fn fn;
     225             :     char *error;
     226             :     errno_t ret;
     227             : 
     228           0 :     fn_name = talloc_asprintf(target, DP_TARGET_INIT_FN,
     229           0 :                               target->module->name, target->name);
     230           0 :     if (fn_name == NULL) {
     231           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
     232           0 :         return ENOMEM;
     233             :     }
     234             : 
     235           0 :     dlerror(); /* clear any error */
     236           0 :     fn = (dp_target_init_fn)dlsym(target->module->libhandle, fn_name);
     237           0 :     if (fn != NULL) {
     238           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Executing target [%s] constructor\n",
     239             :               target->name);
     240             : 
     241           0 :         ret = fn(target, be_ctx, target->module->module_data, target->methods);
     242           0 :         if (ret != EOK) {
     243           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Target [%s] constructor failed "
     244             :                   "[%d]: %s\n", target->name, ret, sss_strerror(ret));
     245           0 :             goto done;
     246             :         }
     247             :     } else {
     248           0 :         error = dlerror();
     249           0 :         if (error == NULL || !target->explicitly_configured) {
     250             :             /* Not found. */
     251           0 :             ret = ELIBBAD;
     252           0 :             goto done;
     253             :         } else {
     254             :             /* Error. */
     255           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load target [%s] "
     256             :                   "constructor: %s\n", target->name, error);
     257           0 :             ret = ELIBBAD;
     258           0 :             goto done;
     259             :         }
     260             :     }
     261             : 
     262           0 :     target->initialized = true;
     263           0 :     ret = EOK;
     264             : 
     265             : done:
     266           0 :     talloc_free(fn_name);
     267           0 :     return ret;
     268             : }
     269             : 
     270           0 : static errno_t dp_target_special(struct be_ctx *be_ctx,
     271             :                                  struct dp_target *target,
     272             :                                  const char *module_name)
     273             : {
     274           0 :     if (strcasecmp(module_name, DP_NO_PROVIDER) == 0) {
     275           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Target [%s] is explicitly disabled.\n",
     276             :               target->name);
     277           0 :         target->initialized = false;
     278           0 :         target->module = NULL;
     279           0 :         return EOK;
     280             :     }
     281             : 
     282           0 :     if (target->target == DPT_ACCESS) {
     283           0 :         if (strcmp(module_name, DP_ACCESS_PERMIT) == 0) {
     284           0 :             dp_set_method(target->methods, DPM_ACCESS_HANDLER,
     285             :                           dp_access_permit_handler_send, dp_access_permit_handler_recv, NULL,
     286             :                           void, struct pam_data, struct pam_data *);
     287           0 :             target->module = NULL;
     288           0 :             target->initialized = true;
     289           0 :             return EOK;
     290             :         }
     291             : 
     292           0 :         if (strcmp(module_name, DP_ACCESS_DENY) == 0) {
     293           0 :             dp_set_method(target->methods, DPM_ACCESS_HANDLER,
     294             :                           dp_access_deny_handler_send, dp_access_deny_handler_recv, NULL,
     295             :                           void, struct pam_data, struct pam_data *);
     296           0 :             target->module = NULL;
     297           0 :             target->initialized = true;
     298           0 :             return EOK;
     299             :         }
     300             :     }
     301             : 
     302           0 :     if (target->target == DPT_SUDO) {
     303           0 :         if (dp_target_sudo_enabled(be_ctx)) {
     304           0 :             return EAGAIN;
     305             :         } else {
     306           0 :             target->module = NULL;
     307           0 :             target->initialized = false;
     308           0 :             return EOK;
     309             :         }
     310             :     }
     311             : 
     312           0 :     return EAGAIN;
     313             : }
     314             : 
     315           0 : static errno_t dp_target_init(struct be_ctx *be_ctx,
     316             :                               struct data_provider *provider,
     317             :                               struct dp_module **modules,
     318             :                               struct dp_target *target)
     319             : {
     320             :     errno_t ret;
     321             : 
     322           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Initializing target [%s] with module [%s]\n",
     323             :           target->name, target->module_name);
     324             : 
     325             :     /* We have already name, module name and target set. We just load
     326             :      * the module and initialize it. */
     327             : 
     328           0 :     target->methods = talloc_zero_array(target, struct dp_method,
     329             :                                         DP_METHOD_SENTINEL + 1);
     330           0 :     if (target->methods == NULL) {
     331           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
     332           0 :         ret = ENOMEM;
     333           0 :         goto done;
     334             :     }
     335             : 
     336             :     /* Handle special cases that do not require opening a module. */
     337           0 :     ret = dp_target_special(be_ctx, target, target->module_name);
     338           0 :     if (ret == EOK || ret != EAGAIN) {
     339             :         goto done;
     340             :     }
     341             : 
     342             :     /* Load module first. Memory context is modules, not target here. */
     343           0 :     target->module = dp_load_module(modules, be_ctx, provider, modules,
     344             :                                     target->module_name);
     345           0 :     if (target->module == NULL) {
     346           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load module %s\n",
     347             :               target->module_name);
     348           0 :         ret = ELIBBAD;
     349           0 :         goto done;
     350             :     }
     351             : 
     352             :     /* Run constructor. */
     353           0 :     ret = dp_target_run_constructor(target, be_ctx);
     354           0 :     if (!target->explicitly_configured && (ret == ELIBBAD || ret == ENOTSUP)) {
     355             :         /* Target not found but it wasn't explicitly
     356             :          * configured so we shall just continue. */
     357           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Target [%s] is not supported by "
     358             :               "module [%s].\n", target->name, target->module_name);
     359           0 :         ret = EOK;
     360           0 :         goto done;
     361           0 :     } else if (ret != EOK) {
     362           0 :         goto done;
     363             :     }
     364             : 
     365           0 :     ret = EOK;
     366             : 
     367             : done:
     368           0 :     if (ret != EOK) {
     369           0 :         talloc_free(target->methods);
     370             :     }
     371             : 
     372           0 :     return ret;
     373             : }
     374             : 
     375           0 : static char *dp_get_module_name(TALLOC_CTX *mem_ctx,
     376             :                                 struct confdb_ctx *confdb_ctx,
     377             :                                 const char *conf_path,
     378             :                                 struct dp_target **targets,
     379             :                                 enum dp_targets type,
     380             :                                 bool *_is_default)
     381             : {
     382             :     const char *name;
     383             :     const char *default_module;
     384             :     char *module;
     385             :     char *option;
     386             :     errno_t ret;
     387             : 
     388           0 :     name = dp_target_to_string(type);
     389           0 :     if (name == NULL) {
     390           0 :         return NULL;
     391             :     }
     392             : 
     393           0 :     option = talloc_asprintf(mem_ctx, DP_PROVIDER_OPT, name);
     394           0 :     if (option == NULL) {
     395           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
     396           0 :         return NULL;
     397             :     }
     398             : 
     399           0 :     ret = confdb_get_string(confdb_ctx, mem_ctx, conf_path,
     400             :                             option, NULL, &module);
     401           0 :     talloc_free(option);
     402           0 :     if (ret != EOK) {
     403           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read provider value "
     404             :               "[%d]: %s\n", ret, sss_strerror(ret));
     405           0 :         return NULL;
     406             :     }
     407             : 
     408           0 :     if (module != NULL) {
     409           0 :         *_is_default = false;
     410           0 :         return module;
     411             :     }
     412             : 
     413           0 :     *_is_default = true;
     414           0 :     default_module = dp_target_default_module(targets, type);
     415             : 
     416           0 :     return talloc_strdup(mem_ctx, default_module);
     417             : }
     418             : 
     419           0 : static errno_t dp_load_configuration(struct confdb_ctx *cdb,
     420             :                                      const char *conf_path,
     421             :                                      struct dp_target **targets)
     422             : {
     423             :     enum dp_targets type;
     424             :     const char *name;
     425             :     bool is_default;
     426             :     char *module;
     427             :     errno_t ret;
     428             : 
     429           0 :     for (type = 0; type < DP_TARGET_SENTINEL; type++) {
     430           0 :         name = dp_target_to_string(type);
     431           0 :         if (name == NULL) {
     432           0 :             ret = ERR_INTERNAL;
     433           0 :             goto done;
     434             :         }
     435             : 
     436           0 :         module = dp_get_module_name(NULL, cdb, conf_path, targets,
     437             :                                     type, &is_default);
     438           0 :         if (module == NULL) {
     439           0 :             DEBUG(SSSDBG_CONF_SETTINGS, "No provider is specified for"
     440             :                   " [%s]\n", name);
     441           0 :             continue;
     442             :         } else {
     443           0 :             DEBUG(SSSDBG_CONF_SETTINGS, "Using [%s] provider for [%s]\n",
     444             :                   module, name);
     445             :         }
     446             : 
     447           0 :         targets[type]->explicitly_configured = is_default == false;
     448           0 :         targets[type]->name = name;
     449           0 :         targets[type]->target = type;
     450           0 :         targets[type]->module_name = talloc_steal(targets[type], module);
     451             :     }
     452             : 
     453           0 :     ret = EOK;
     454             : 
     455             : done:
     456           0 :     return ret;
     457             : }
     458             : 
     459           0 : static errno_t dp_load_targets(struct be_ctx *be_ctx,
     460             :                                struct data_provider *provider,
     461             :                                struct dp_target **targets,
     462             :                                struct dp_module **modules)
     463             : {
     464             :     enum dp_targets type;
     465             :     errno_t ret;
     466             : 
     467             :     /* We load the configuration first and store module name to each target.
     468             :      * This way we ensure that we have this information available during
     469             :      * module initialization. */
     470             : 
     471           0 :     ret = dp_load_configuration(be_ctx->cdb, be_ctx->conf_path, targets);
     472           0 :     if (ret != EOK) {
     473           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to load DP configuration "
     474             :               "[%d]: %s\n", ret, sss_strerror(ret));
     475           0 :         goto done;
     476             :     }
     477             : 
     478           0 :     for (type = 0; type < DP_TARGET_SENTINEL; type++) {
     479           0 :         ret = dp_target_init(be_ctx, provider, modules, targets[type]);
     480           0 :         if (ret != EOK) {
     481           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to load target [%s] "
     482             :                   "[%d]: %s.\n", targets[type]->name, ret, sss_strerror(ret));
     483           0 :             ret = ERR_INTERNAL;
     484           0 :             goto done;
     485             :         }
     486             :     }
     487             : 
     488           0 :     ret = EOK;
     489             : 
     490             : done:
     491           0 :     return ret;
     492             : }
     493             : 
     494           0 : errno_t dp_init_targets(TALLOC_CTX *mem_ctx,
     495             :                         struct be_ctx *be_ctx,
     496             :                         struct data_provider *provider,
     497             :                         struct dp_module **modules)
     498             : {
     499             :     struct dp_target **targets;
     500             :     enum dp_targets type;
     501             :     errno_t ret;
     502             : 
     503             :     /* Even though we know the exact number of targets we will allocate
     504             :      * them all dynamically so we can have correct talloc hierarchy where
     505             :      * all private data are attached to the target they belong to. */
     506             : 
     507           0 :     targets = talloc_zero_array(mem_ctx, struct dp_target *,
     508             :                                 DP_TARGET_SENTINEL + 1);
     509           0 :     if (targets == NULL) {
     510           0 :         ret = ENOMEM;
     511           0 :         goto done;
     512             :     }
     513             : 
     514           0 :     for (type = 0; type != DP_TARGET_SENTINEL; type++) {
     515           0 :         targets[type] = talloc_zero(targets, struct dp_target);
     516           0 :         if (targets[type] == NULL) {
     517           0 :             ret = ENOMEM;
     518           0 :             goto done;
     519             :         }
     520             :     }
     521             : 
     522             :     /* We want this to be already available. */
     523           0 :     provider->targets = targets;
     524             : 
     525           0 :     ret = dp_load_targets(be_ctx, provider, targets, modules);
     526             : 
     527             : done:
     528           0 :     if (ret != EOK) {
     529           0 :         provider->targets = NULL;
     530           0 :         talloc_free(targets);
     531             :     }
     532             : 
     533           0 :     return ret;
     534             : }

Generated by: LCOV version 1.10