LCOV - code coverage report
Current view: top level - providers/simple - simple_access.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 49 117 41.9 %
Date: 2015-10-19 Functions: 3 5 60.0 %

          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/dp_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             : static void simple_access_check(struct tevent_req *req);
      38             : static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
      39             :                                          struct be_ctx *be_ctx,
      40             :                                          char **list,
      41             :                                          char ***_out);
      42             : 
      43           1 : static int simple_access_obtain_filter_lists(struct simple_ctx *ctx)
      44             : {
      45           1 :     struct be_ctx *bectx = ctx->be_ctx;
      46             :     int ret;
      47             :     int i;
      48             :     struct {
      49             :         const char *name;
      50             :         const char *option;
      51             :         char **orig_list;
      52             :         char ***ctx_list;
      53           1 :     } lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL},
      54             :                  {"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL},
      55             :                  {"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL},
      56             :                  {"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL},
      57             :                  {NULL, NULL, NULL, NULL}};
      58             : 
      59           1 :     lists[0].ctx_list = &ctx->allow_users;
      60           1 :     lists[1].ctx_list = &ctx->deny_users;
      61           1 :     lists[2].ctx_list = &ctx->allow_groups;
      62           1 :     lists[3].ctx_list = &ctx->deny_groups;
      63             : 
      64           1 :     ret = sysdb_master_domain_update(bectx->domain);
      65           1 :     if (ret != EOK) {
      66           0 :         DEBUG(SSSDBG_FUNC_DATA, "Update of master domain failed [%d]: %s.\n",
      67             :                                  ret, sss_strerror(ret));
      68           0 :         goto failed;
      69             :     }
      70             : 
      71           5 :     for (i = 0; lists[i].name != NULL; i++) {
      72           4 :         ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path,
      73             :                                         lists[i].option, &lists[i].orig_list);
      74           4 :         if (ret == ENOENT) {
      75           0 :             DEBUG(SSSDBG_FUNC_DATA, "%s list is empty.\n", lists[i].name);
      76           0 :             *lists[i].ctx_list = NULL;
      77           0 :             continue;
      78           4 :         } else if (ret != EOK) {
      79           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "confdb_get_string_as_list failed.\n");
      80           0 :             goto failed;
      81             :         }
      82             : 
      83           4 :         ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list,
      84             :                                         lists[i].ctx_list);
      85           4 :         if (ret != EOK) {
      86           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse %s list [%d]: %s\n",
      87             :                                         lists[i].name, ret, sss_strerror(ret));
      88           0 :             goto failed;
      89             :         }
      90             :     }
      91             : 
      92           1 :     if (!ctx->allow_users &&
      93           0 :             !ctx->allow_groups &&
      94           0 :             !ctx->deny_users &&
      95           0 :             !ctx->deny_groups) {
      96           0 :         DEBUG(SSSDBG_OP_FAILURE,
      97             :               "No rules supplied for simple access provider. "
      98             :                "Access will be granted for all users.\n");
      99             :     }
     100           1 :     return EOK;
     101             : 
     102             : failed:
     103           0 :     return ret;
     104             : }
     105             : 
     106           0 : void simple_access_handler(struct be_req *be_req)
     107             : {
     108           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
     109             :     struct pam_data *pd;
     110             :     struct tevent_req *req;
     111             :     struct simple_ctx *ctx;
     112             :     int ret;
     113             :     time_t now;
     114             : 
     115           0 :     pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
     116             : 
     117           0 :     pd->pam_status = PAM_SYSTEM_ERR;
     118             : 
     119           0 :     if (pd->cmd != SSS_PAM_ACCT_MGMT) {
     120           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     121             :               "simple access does not handle pam task %d.\n", pd->cmd);
     122           0 :         pd->pam_status = PAM_MODULE_UNKNOWN;
     123           0 :         goto done;
     124             :     }
     125             : 
     126           0 :     ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
     127             :                           struct simple_ctx);
     128             : 
     129             : 
     130           0 :     now = time(NULL);
     131           0 :     if ((now - ctx->last_refresh_of_filter_lists)
     132             :         > TIMEOUT_OF_REFRESH_FILTER_LISTS) {
     133             : 
     134           0 :         ret = simple_access_obtain_filter_lists(ctx);
     135           0 :         if (ret != EOK) {
     136           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to refresh filter lists\n");
     137             :         }
     138           0 :         ctx->last_refresh_of_filter_lists = now;
     139             :     }
     140             : 
     141           0 :     req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user);
     142           0 :     if (!req) {
     143           0 :         pd->pam_status = PAM_SYSTEM_ERR;
     144           0 :         goto done;
     145             :     }
     146           0 :     tevent_req_set_callback(req, simple_access_check, be_req);
     147           0 :     return;
     148             : 
     149             : done:
     150           0 :     be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
     151             : }
     152             : 
     153           0 : static void simple_access_check(struct tevent_req *req)
     154             : {
     155           0 :     bool access_granted = false;
     156             :     errno_t ret;
     157             :     struct pam_data *pd;
     158             :     struct be_req *be_req;
     159             : 
     160           0 :     be_req = tevent_req_callback_data(req, struct be_req);
     161           0 :     pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
     162             : 
     163           0 :     ret = simple_access_check_recv(req, &access_granted);
     164           0 :     talloc_free(req);
     165           0 :     if (ret != EOK) {
     166           0 :         pd->pam_status = PAM_SYSTEM_ERR;
     167           0 :         goto done;
     168             :     }
     169             : 
     170           0 :     if (access_granted) {
     171           0 :         pd->pam_status = PAM_SUCCESS;
     172             :     } else {
     173           0 :         pd->pam_status = PAM_PERM_DENIED;
     174             :     }
     175             : 
     176             : done:
     177           0 :     be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
     178           0 : }
     179             : 
     180           4 : static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
     181             :                                          struct be_ctx *be_ctx,
     182             :                                          char **list,
     183             :                                          char ***_out)
     184             : {
     185           4 :     TALLOC_CTX *tmp_ctx = NULL;
     186           4 :     char **out = NULL;
     187           4 :     char *domain = NULL;
     188           4 :     char *name = NULL;
     189             :     size_t size;
     190             :     size_t i;
     191             :     errno_t ret;
     192             : 
     193           4 :     if (list == NULL) {
     194           0 :         *_out = NULL;
     195           0 :         return EOK;
     196             :     }
     197             : 
     198           4 :     tmp_ctx = talloc_new(NULL);
     199           4 :     if (tmp_ctx == NULL) {
     200           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     201           0 :         ret = ENOMEM;
     202           0 :         goto done;
     203             :     }
     204             : 
     205           4 :     for (size = 0; list[size] != NULL; size++) {
     206             :         /* count size */
     207             :     }
     208             : 
     209           4 :     out = talloc_zero_array(tmp_ctx, char*, size + 1);
     210           4 :     if (out == NULL) {
     211           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
     212           0 :         ret = ENOMEM;
     213           0 :         goto done;
     214             :     }
     215             : 
     216             :     /* Since this is access provider, we should fail on any error so we don't
     217             :      * allow unauthorized access. */
     218          20 :     for (i = 0; i < size; i++) {
     219          16 :         ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i],
     220             :                              &domain, &name);
     221          16 :         if (ret != EOK) {
     222           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
     223             :                                         list[i], ret, sss_strerror(ret));
     224           0 :             goto done;
     225             :         }
     226             : 
     227          16 :         if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 ||
     228           0 :             (be_ctx->domain->flat_name != NULL &&
     229           0 :              strcasecmp(domain, be_ctx->domain->flat_name) == 0)) {
     230             :             /* This object belongs to main SSSD domain. Those users and groups
     231             :              * are stored without domain part, so we will strip it off.
     232             :              * */
     233          16 :             out[i] = talloc_move(out, &name);
     234             :         } else {
     235             :             /* Subdomain users and groups are stored as fully qualified names,
     236             :              * thus we will remember the domain part.
     237             :              *
     238             :              * Since subdomains may come and go, we will look for their
     239             :              * existence later, during each access check.
     240             :              */
     241           0 :             out[i] = talloc_move(out, &list[i]);
     242             :         }
     243             :     }
     244             : 
     245           4 :     *_out = talloc_steal(mem_ctx, out);
     246           4 :     ret = EOK;
     247             : 
     248             : done:
     249           4 :     talloc_free(tmp_ctx);
     250           4 :     return ret;
     251             : }
     252             : 
     253             : struct bet_ops simple_access_ops = {
     254             :     .handler = simple_access_handler,
     255             :     .finalize = NULL
     256             : };
     257             : 
     258           1 : int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops,
     259             :                             void **pvt_data)
     260             : {
     261           1 :     int ret = EINVAL;
     262             :     struct simple_ctx *ctx;
     263           1 :     ctx = talloc_zero(bectx, struct simple_ctx);
     264           1 :     if (ctx == NULL) {
     265           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     266           0 :         return ENOMEM;
     267             :     }
     268             : 
     269           1 :     ctx->domain = bectx->domain;
     270           1 :     ctx->be_ctx = bectx;
     271           1 :     ctx->last_refresh_of_filter_lists = 0;
     272             : 
     273           1 :     ret = simple_access_obtain_filter_lists(ctx);
     274           1 :     if (ret != EOK) {
     275           0 :         goto failed;
     276             :     }
     277             : 
     278           1 :     *ops = &simple_access_ops;
     279           1 :     *pvt_data = ctx;
     280             : 
     281           1 :     return EOK;
     282             : 
     283             : failed:
     284           0 :     talloc_free(ctx);
     285           0 :     return ret;
     286             : }
     287             : 

Generated by: LCOV version 1.10