summaryrefslogtreecommitdiffstats
path: root/src/providers/simple/simple_access.c
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2013-02-23 10:44:54 +0100
committerJakub Hrozek <jhrozek@redhat.com>2013-03-05 23:28:04 +0100
commite8e943fac5b8759d6f6d6535309c994bba370cb5 (patch)
tree1a1b59f96dc4fbf1d3ca13bdf5e6129a90871859 /src/providers/simple/simple_access.c
parentc99a359e4499f2669bb14b7971383cbbc4a29c69 (diff)
downloadsssd-rhel6.4.tar.gz
sssd-rhel6.4.tar.xz
sssd-rhel6.4.zip
Resolve GIDs in the simple access providerrhel6.4
Changes the simple access provider's interface to be asynchronous. When the simple access provider encounters a group that has gid, but no meaningful name, it attempts to resolve the name using the be_file_account_request function. Some providers (like the AD provider) might perform initgroups without resolving the group names. In order for the simple access provider to work correctly, we need to resolve the groups before performing the access check. In AD provider, the situation is even more tricky b/c the groups HAVE name, but their name attribute is set to SID and they are set as non-POSIX
Diffstat (limited to 'src/providers/simple/simple_access.c')
-rw-r--r--src/providers/simple/simple_access.c228
1 files changed, 27 insertions, 201 deletions
diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c
index 70d1f0728..d53a04b4d 100644
--- a/src/providers/simple/simple_access.c
+++ b/src/providers/simple/simple_access.c
@@ -35,227 +35,52 @@
#define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups"
#define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups"
-errno_t simple_access_check(struct simple_ctx *ctx, const char *username,
- bool *access_granted)
-{
- int i, j;
- errno_t ret;
- TALLOC_CTX *tmp_ctx = NULL;
- const char *user_attrs[] = { SYSDB_MEMBEROF,
- SYSDB_GIDNUM,
- NULL };
- const char *group_attrs[] = { SYSDB_NAME,
- NULL };
- struct ldb_message *msg;
- struct ldb_message_element *el;
- char **groups;
- const char *primary_group;
- gid_t gid;
- bool matched;
- bool cs = ctx->domain->case_sensitive;
-
- *access_granted = false;
-
- /* First, check whether the user is in the allowed users list */
- if (ctx->allow_users != NULL) {
- for(i = 0; ctx->allow_users[i] != NULL; i++) {
- if (sss_string_equal(cs, username, ctx->allow_users[i])) {
- DEBUG(9, ("User [%s] found in allow list, access granted.\n",
- username));
-
- /* Do not return immediately on explicit allow
- * We need to make sure none of the user's groups
- * are denied.
- */
- *access_granted = true;
- }
- }
- } else if (!ctx->allow_groups) {
- /* If neither allow rule is in place, we'll assume allowed
- * unless a deny rule disables us below.
- */
- *access_granted = true;
- }
+static void simple_access_check(struct tevent_req *req);
- /* Next check whether this user has been specifically denied */
- if (ctx->deny_users != NULL) {
- for(i = 0; ctx->deny_users[i] != NULL; i++) {
- if (sss_string_equal(cs, username, ctx->deny_users[i])) {
- DEBUG(9, ("User [%s] found in deny list, access denied.\n",
- username));
-
- /* Return immediately on explicit denial */
- *access_granted = false;
- return EOK;
- }
- }
- }
+void simple_access_handler(struct be_req *be_req)
+{
+ struct be_ctx *be_ctx = be_req->be_ctx;
+ struct pam_data *pd;
+ struct tevent_req *req;
+ struct simple_ctx *ctx;
- if (!ctx->allow_groups && !ctx->deny_groups) {
- /* There are no group restrictions, so just return
- * here with whatever we've decided.
- */
- return EOK;
- }
+ pd = talloc_get_type(be_req->req_data, struct pam_data);
- /* Now get a list of this user's groups and check those against the
- * simple_allow_groups list.
- */
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- ret = ENOMEM;
- goto done;
- }
+ pd->pam_status = PAM_SYSTEM_ERR;
- ret = sysdb_search_user_by_name(tmp_ctx, ctx->sysdb,
- username, user_attrs, &msg);
- if (ret != EOK) {
- DEBUG(1, ("Could not look up username [%s]: [%d][%s]\n",
- username, ret, strerror(ret)));
+ if (pd->cmd != SSS_PAM_ACCT_MGMT) {
+ DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd));
+ pd->pam_status = PAM_MODULE_UNKNOWN;
goto done;
}
- /* Construct a list of the user's groups */
- el = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
- if (el && el->num_values) {
- /* Get the groups from the memberOf entries
- * Allocate the array with room for both the NULL
- * terminator and the primary group
- */
- groups = talloc_array(tmp_ctx, char *, el->num_values + 2);
- if (!groups) {
- ret = ENOMEM;
- goto done;
- }
-
- for (j = 0; j < el->num_values; j++) {
- ret = sysdb_group_dn_name(
- ctx->sysdb, tmp_ctx,
- (char *)el->values[j].data,
- &groups[j]);
- if (ret != EOK) {
- goto done;
- }
- }
- } else {
- /* User is not a member of any groups except primary */
- groups = talloc_array(tmp_ctx, char *, 2);
- if (!groups) {
- ret = ENOMEM;
- goto done;
- }
- j = 0;
- }
+ ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
+ struct simple_ctx);
- /* Get the user's primary group */
- gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
- if (!gid) {
- ret = EINVAL;
+ req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user);
+ if (!req) {
+ pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
- talloc_zfree(msg);
-
- ret = sysdb_search_group_by_gid(tmp_ctx, ctx->sysdb,
- gid, group_attrs, &msg);
- if (ret != EOK) {
- DEBUG(1, ("Could not look up primary group [%lu]: [%d][%s]\n",
- gid, ret, strerror(ret)));
- /* We have to treat this as non-fatal, because the primary
- * group may be local to the machine and not available in
- * our ID provider.
- */
- } else {
- primary_group = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- if (!primary_group) {
- ret = EINVAL;
- goto done;
- }
-
- groups[j] = talloc_strdup(tmp_ctx, primary_group);
- if (!groups[j]) {
- ret = ENOMEM;
- goto done;
- }
- j++;
-
- talloc_zfree(msg);
- }
-
- groups[j] = NULL;
-
- /* Now process allow and deny group rules
- * If access was already granted above, we'll skip
- * this redundant rule check
- */
- if (ctx->allow_groups && !*access_granted) {
- matched = false;
- for (i = 0; ctx->allow_groups[i]; i++) {
- for(j = 0; groups[j]; j++) {
- if (sss_string_equal(cs, groups[j], ctx->allow_groups[i])) {
- matched = true;
- break;
- }
- }
-
- /* If any group has matched, we can skip out on the
- * processing early
- */
- if (matched) {
- *access_granted = true;
- break;
- }
- }
- }
-
- /* Finally, process the deny group rules */
- if (ctx->deny_groups) {
- matched = false;
- for (i = 0; ctx->deny_groups[i]; i++) {
- for(j = 0; groups[j]; j++) {
- if (sss_string_equal(cs, groups[j], ctx->deny_groups[i])) {
- matched = true;
- break;
- }
- }
-
- /* If any group has matched, we can skip out on the
- * processing early
- */
- if (matched) {
- *access_granted = false;
- break;
- }
- }
- }
-
- ret = EOK;
+ tevent_req_set_callback(req, simple_access_check, be_req);
+ return;
done:
- talloc_free(tmp_ctx);
- return ret;
+ be_req->fn(be_req, DP_ERR_OK, pd->pam_status, NULL);
}
-void simple_access_handler(struct be_req *be_req)
+static void simple_access_check(struct tevent_req *req)
{
- int ret;
bool access_granted = false;
+ errno_t ret;
struct pam_data *pd;
- struct simple_ctx *ctx;
+ struct be_req *be_req;
+ be_req = tevent_req_callback_data(req, struct be_req);
pd = talloc_get_type(be_req->req_data, struct pam_data);
- pd->pam_status = PAM_SYSTEM_ERR;
-
- if (pd->cmd != SSS_PAM_ACCT_MGMT) {
- DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- goto done;
- }
-
- ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
- struct simple_ctx);
-
- ret = simple_access_check(ctx, pd->user, &access_granted);
+ ret = simple_access_check_recv(req, &access_granted);
+ talloc_free(req);
if (ret != EOK) {
pd->pam_status = PAM_SYSTEM_ERR;
goto done;
@@ -290,6 +115,7 @@ int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops,
ctx->sysdb = bectx->sysdb;
ctx->domain = bectx->domain;
+ ctx->be_ctx = bectx;
/* Users */
ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path,