simple_access.c revision eb2ec2c35742caf164b49b660b5045d08cac7623
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa/*
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa SSSD
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa Simple access control
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa Copyright (C) Sumit Bose <sbose@redhat.com> 2010
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa This program is free software; you can redistribute it and/or modify
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa it under the terms of the GNU General Public License as published by
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa the Free Software Foundation; either version 3 of the License, or
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa (at your option) any later version.
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa This program is distributed in the hope that it will be useful,
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa but WITHOUT ANY WARRANTY; without even the implied warranty of
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa GNU General Public License for more details.
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa You should have received a copy of the GNU General Public License
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa along with this program. If not, see <http://www.gnu.org/licenses/>.
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa*/
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#include <security/pam_modules.h>
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#include "providers/simple/simple_access.h"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#include "util/sss_utf8.h"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#include "providers/dp_backend.h"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#include "db/sysdb.h"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#define CONFDB_SIMPLE_ALLOW_USERS "simple_allow_users"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#define CONFDB_SIMPLE_DENY_USERS "simple_deny_users"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa#define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups"
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksastatic void simple_access_check(struct tevent_req *req);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksavoid simple_access_handler(struct be_req *be_req)
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa{
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct pam_data *pd;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct tevent_req *req;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct simple_ctx *ctx;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa pd->pam_status = PAM_SYSTEM_ERR;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa if (pd->cmd != SSS_PAM_ACCT_MGMT) {
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd));
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa pd->pam_status = PAM_MODULE_UNKNOWN;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa goto done;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa }
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct simple_ctx);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa if (!req) {
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa pd->pam_status = PAM_SYSTEM_ERR;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa goto done;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa }
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa tevent_req_set_callback(req, simple_access_check, be_req);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa return;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksadone:
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa}
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksastatic void simple_access_check(struct tevent_req *req)
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa{
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa bool access_granted = false;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa errno_t ret;
39eaacfe933c39700a6edbfa72b83255cd868822Eugen Kuksa struct pam_data *pd;
struct be_req *be_req;
be_req = tevent_req_callback_data(req, struct be_req);
pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
ret = simple_access_check_recv(req, &access_granted);
talloc_free(req);
if (ret != EOK) {
pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
if (access_granted) {
pd->pam_status = PAM_SUCCESS;
} else {
pd->pam_status = PAM_PERM_DENIED;
}
done:
be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
}
static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
char **list,
char ***_out)
{
TALLOC_CTX *tmp_ctx = NULL;
char **out = NULL;
char *domain = NULL;
char *name = NULL;
size_t size;
size_t i;
errno_t ret;
if (list == NULL) {
*_out = NULL;
return EOK;
}
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
ret = ENOMEM;
goto done;
}
for (size = 0; list[size] != NULL; size++) {
/* count size */
}
out = talloc_zero_array(tmp_ctx, char*, size + 1);
if (out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero_array() failed\n"));
ret = ENOMEM;
goto done;
}
/* Since this is access provider, we should fail on any error so we don't
* allow unauthorized access. */
for (i = 0; i < size; i++) {
ret = sss_parse_name(tmp_ctx, be_ctx->domain->names, list[i],
&domain, &name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to parse name '%s' [%d]: %s\n",
list[i], ret, sss_strerror(ret)));
goto done;
}
if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 ||
(be_ctx->domain->flat_name != NULL &&
strcasecmp(domain, be_ctx->domain->flat_name) == 0)) {
/* This object belongs to main SSSD domain. Those users and groups
* are stored without domain part, so we will strip it off.
* */
out[i] = talloc_move(out, &name);
} else {
/* Subdomain users and groups are stored as fully qualified names,
* thus we will remember the domain part.
*
* Since subdomains may come and go, we will look for their
* existence later, during each access check.
*/
out[i] = talloc_move(out, &list[i]);
}
}
*_out = talloc_steal(mem_ctx, out);
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
struct bet_ops simple_access_ops = {
.handler = simple_access_handler,
.finalize = NULL
};
int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops,
void **pvt_data)
{
int ret = EINVAL;
struct simple_ctx *ctx;
int i;
struct {
const char *name;
const char *option;
char **orig_list;
char ***ctx_list;
} lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL},
{"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL},
{"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL},
{"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL},
{NULL, NULL, NULL, NULL}};
ctx = talloc_zero(bectx, struct simple_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
return ENOMEM;
}
ctx->domain = bectx->domain;
ctx->be_ctx = bectx;
lists[0].ctx_list = &ctx->allow_users;
lists[1].ctx_list = &ctx->deny_users;
lists[2].ctx_list = &ctx->allow_groups;
lists[3].ctx_list = &ctx->deny_groups;
for (i = 0; lists[i].name != NULL; i++) {
ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path,
lists[i].option, &lists[i].orig_list);
if (ret == ENOENT) {
DEBUG(SSSDBG_FUNC_DATA, ("%s list is empty.\n", lists[i].name));
*lists[i].ctx_list = NULL;
continue;
} else if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("confdb_get_string_as_list failed.\n"));
goto failed;
}
ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list,
lists[i].ctx_list);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to parse %s list [%d]: %s\n",
lists[i].name, ret, sss_strerror(ret)));
goto failed;
}
}
if (!ctx->allow_users &&
!ctx->allow_groups &&
!ctx->deny_users &&
!ctx->deny_groups) {
DEBUG(SSSDBG_OP_FAILURE, ("No rules supplied for simple access provider. "
"Access will be granted for all users.\n"));
}
*ops = &simple_access_ops;
*pvt_data = ctx;
return EOK;
failed:
talloc_free(ctx);
return ret;
}