LCOV - code coverage report
Current view: top level - providers/simple - simple_access.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 123 30.1 %
Date: 2016-06-29 Functions: 2 6 33.3 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    Simple access control
       5             : 
       6             :    Copyright (C) Sumit Bose <sbose@redhat.com> 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <security/pam_modules.h>
      23             : 
      24             : #include "providers/simple/simple_access.h"
      25             : #include "util/sss_utf8.h"
      26             : #include "providers/backend.h"
      27             : #include "db/sysdb.h"
      28             : 
      29             : #define CONFDB_SIMPLE_ALLOW_USERS "simple_allow_users"
      30             : #define CONFDB_SIMPLE_DENY_USERS "simple_deny_users"
      31             : 
      32             : #define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups"
      33             : #define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups"
      34             : 
      35             : #define TIMEOUT_OF_REFRESH_FILTER_LISTS 5
      36             : 
      37           4 : static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
      38             :                                          struct be_ctx *be_ctx,
      39             :                                          char **list,
      40             :                                          char ***_out)
      41             : {
      42           4 :     TALLOC_CTX *tmp_ctx = NULL;
      43           4 :     char **out = NULL;
      44           4 :     char *domain = NULL;
      45           4 :     char *name = NULL;
      46             :     size_t size;
      47             :     size_t i;
      48             :     errno_t ret;
      49             : 
      50           4 :     if (list == NULL) {
      51           0 :         *_out = NULL;
      52           0 :         return EOK;
      53             :     }
      54             : 
      55           4 :     tmp_ctx = talloc_new(NULL);
      56           4 :     if (tmp_ctx == NULL) {
      57           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
      58           0 :         ret = ENOMEM;
      59           0 :         goto done;
      60             :     }
      61             : 
      62           4 :     for (size = 0; list[size] != NULL; size++) {
      63             :         /* count size */
      64             :     }
      65             : 
      66           4 :     out = talloc_zero_array(tmp_ctx, char*, size + 1);
      67           4 :     if (out == NULL) {
      68           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
      69           0 :         ret = ENOMEM;
      70           0 :         goto done;
      71             :     }
      72             : 
      73             :     /* Since this is access provider, we should fail on any error so we don't
      74             :      * allow unauthorized access. */
      75          20 :     for (i = 0; i < size; i++) {
      76          16 :         ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i],
      77             :                              &domain, &name);
      78          16 :         if (ret != EOK) {
      79           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
      80             :                                         list[i], ret, sss_strerror(ret));
      81           0 :             goto done;
      82             :         }
      83             : 
      84          16 :         if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 ||
      85           0 :             (be_ctx->domain->flat_name != NULL &&
      86           0 :              strcasecmp(domain, be_ctx->domain->flat_name) == 0)) {
      87             :             /* This object belongs to main SSSD domain. Those users and groups
      88             :              * are stored without domain part, so we will strip it off.
      89             :              * */
      90          16 :             out[i] = talloc_move(out, &name);
      91             :         } else {
      92             :             /* Subdomain users and groups are stored as fully qualified names,
      93             :              * thus we will remember the domain part.
      94             :              *
      95             :              * Since subdomains may come and go, we will look for their
      96             :              * existence later, during each access check.
      97             :              */
      98           0 :             out[i] = talloc_move(out, &list[i]);
      99             :         }
     100             :     }
     101             : 
     102           4 :     *_out = talloc_steal(mem_ctx, out);
     103           4 :     ret = EOK;
     104             : 
     105             : done:
     106           4 :     talloc_free(tmp_ctx);
     107           4 :     return ret;
     108             : }
     109             : 
     110           1 : int simple_access_obtain_filter_lists(struct simple_ctx *ctx)
     111             : {
     112           1 :     struct be_ctx *bectx = ctx->be_ctx;
     113             :     int ret;
     114             :     int i;
     115             :     struct {
     116             :         const char *name;
     117             :         const char *option;
     118             :         char **orig_list;
     119             :         char ***ctx_list;
     120           1 :     } lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL},
     121             :                  {"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL},
     122             :                  {"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL},
     123             :                  {"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL},
     124             :                  {NULL, NULL, NULL, NULL}};
     125             : 
     126           1 :     lists[0].ctx_list = &ctx->allow_users;
     127           1 :     lists[1].ctx_list = &ctx->deny_users;
     128           1 :     lists[2].ctx_list = &ctx->allow_groups;
     129           1 :     lists[3].ctx_list = &ctx->deny_groups;
     130             : 
     131           1 :     ret = sysdb_master_domain_update(bectx->domain);
     132           1 :     if (ret != EOK) {
     133           0 :         DEBUG(SSSDBG_FUNC_DATA, "Update of master domain failed [%d]: %s.\n",
     134             :                                  ret, sss_strerror(ret));
     135           0 :         goto failed;
     136             :     }
     137             : 
     138           5 :     for (i = 0; lists[i].name != NULL; i++) {
     139           4 :         ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path,
     140             :                                         lists[i].option, &lists[i].orig_list);
     141           4 :         if (ret == ENOENT) {
     142           0 :             DEBUG(SSSDBG_FUNC_DATA, "%s list is empty.\n", lists[i].name);
     143           0 :             *lists[i].ctx_list = NULL;
     144           0 :             continue;
     145           4 :         } else if (ret != EOK) {
     146           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "confdb_get_string_as_list failed.\n");
     147           0 :             goto failed;
     148             :         }
     149             : 
     150           4 :         ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list,
     151             :                                         lists[i].ctx_list);
     152           4 :         if (ret != EOK) {
     153           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse %s list [%d]: %s\n",
     154             :                                         lists[i].name, ret, sss_strerror(ret));
     155           0 :             goto failed;
     156             :         }
     157             :     }
     158             : 
     159           1 :     if (!ctx->allow_users &&
     160           0 :             !ctx->allow_groups &&
     161           0 :             !ctx->deny_users &&
     162           0 :             !ctx->deny_groups) {
     163           0 :         DEBUG(SSSDBG_OP_FAILURE,
     164             :               "No rules supplied for simple access provider. "
     165             :                "Access will be granted for all users.\n");
     166             :     }
     167           1 :     return EOK;
     168             : 
     169             : failed:
     170           0 :     return ret;
     171             : }
     172             : 
     173             : struct simple_access_handler_state {
     174             :     struct pam_data *pd;
     175             : };
     176             : 
     177             : static void simple_access_handler_done(struct tevent_req *subreq);
     178             : 
     179             : static struct tevent_req *
     180           0 : simple_access_handler_send(TALLOC_CTX *mem_ctx,
     181             :                            struct simple_ctx *simple_ctx,
     182             :                            struct pam_data *pd,
     183             :                            struct dp_req_params *params)
     184             : {
     185             :     struct simple_access_handler_state *state;
     186             :     struct tevent_req *subreq;
     187             :     struct tevent_req *req;
     188             :     errno_t ret;
     189             :     time_t now;
     190             : 
     191           0 :     req = tevent_req_create(mem_ctx, &state,
     192             :                             struct simple_access_handler_state);
     193           0 :     if (req == NULL) {
     194           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     195           0 :         return NULL;
     196             :     }
     197             : 
     198           0 :     state->pd = pd;
     199             : 
     200           0 :     pd->pam_status = PAM_SYSTEM_ERR;
     201           0 :     if (pd->cmd != SSS_PAM_ACCT_MGMT) {
     202           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     203             :               "simple access does not handle pam task %d.\n", pd->cmd);
     204           0 :         pd->pam_status = PAM_MODULE_UNKNOWN;
     205           0 :         goto immediately;
     206             :     }
     207             : 
     208           0 :     now = time(NULL);
     209           0 :     if ((now - simple_ctx->last_refresh_of_filter_lists)
     210             :         > TIMEOUT_OF_REFRESH_FILTER_LISTS) {
     211             : 
     212           0 :         ret = simple_access_obtain_filter_lists(simple_ctx);
     213           0 :         if (ret != EOK) {
     214           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to refresh filter lists\n");
     215             :         }
     216           0 :         simple_ctx->last_refresh_of_filter_lists = now;
     217             :     }
     218             : 
     219           0 :     subreq = simple_access_check_send(state, params->ev, simple_ctx, pd->user);
     220           0 :     if (subreq == NULL) {
     221           0 :         pd->pam_status = PAM_SYSTEM_ERR;
     222           0 :         goto immediately;
     223             :     }
     224             : 
     225           0 :     tevent_req_set_callback(subreq, simple_access_handler_done, req);
     226             : 
     227           0 :     return req;
     228             : 
     229             : immediately:
     230             :     /* TODO For backward compatibility we always return EOK to DP now. */
     231           0 :     tevent_req_done(req);
     232           0 :     tevent_req_post(req, params->ev);
     233             : 
     234           0 :     return req;
     235             : }
     236             : 
     237           0 : static void simple_access_handler_done(struct tevent_req *subreq)
     238             : {
     239             :     struct simple_access_handler_state *state;
     240             :     struct tevent_req *req;
     241             :     bool access_granted;
     242             :     errno_t ret;
     243             : 
     244           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     245           0 :     state = tevent_req_data(req, struct simple_access_handler_state);
     246             : 
     247           0 :     ret = simple_access_check_recv(subreq, &access_granted);
     248           0 :     talloc_free(subreq);
     249           0 :     if (ret != EOK) {
     250           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     251           0 :         goto done;
     252             :     }
     253             : 
     254           0 :     if (access_granted) {
     255           0 :         state->pd->pam_status = PAM_SUCCESS;
     256             :     } else {
     257           0 :         state->pd->pam_status = PAM_PERM_DENIED;
     258             :     }
     259             : 
     260             : done:
     261             :     /* TODO For backward compatibility we always return EOK to DP now. */
     262           0 :     tevent_req_done(req);
     263           0 : }
     264             : 
     265             : static errno_t
     266           0 : simple_access_handler_recv(TALLOC_CTX *mem_ctx,
     267             :                        struct tevent_req *req,
     268             :                        struct pam_data **_data)
     269             : {
     270           0 :     struct simple_access_handler_state *state = NULL;
     271             : 
     272           0 :     state = tevent_req_data(req, struct simple_access_handler_state);
     273             : 
     274           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     275             : 
     276           0 :     *_data = talloc_steal(mem_ctx, state->pd);
     277             : 
     278           0 :     return EOK;
     279             : }
     280             : 
     281           0 : errno_t sssm_simple_access_init(TALLOC_CTX *mem_ctx,
     282             :                                 struct be_ctx *be_ctx,
     283             :                                 void *module_data,
     284             :                                 struct dp_method *dp_methods)
     285             : {
     286             :     struct simple_ctx *ctx;
     287             :     errno_t ret;
     288             : 
     289           0 :     ctx = talloc_zero(mem_ctx, struct simple_ctx);
     290           0 :     if (ctx == NULL) {
     291           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed.\n");
     292           0 :         return ENOMEM;
     293             :     }
     294             : 
     295           0 :     ctx->domain = be_ctx->domain;
     296           0 :     ctx->be_ctx = be_ctx;
     297           0 :     ctx->last_refresh_of_filter_lists = 0;
     298             : 
     299           0 :     ret = simple_access_obtain_filter_lists(ctx);
     300           0 :     if (ret != EOK) {
     301           0 :         talloc_free(ctx);
     302           0 :         return ret;
     303             :     }
     304             : 
     305           0 :     dp_set_method(dp_methods, DPM_ACCESS_HANDLER,
     306             :                   simple_access_handler_send, simple_access_handler_recv, ctx,
     307             :                   struct simple_ctx, struct pam_data, struct pam_data *);
     308             : 
     309           0 :     return EOK;
     310             : }

Generated by: LCOV version 1.10