From 2a2f642aae37e3f41cbbda162a74c2b946a4521f Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Mon, 20 Dec 2010 16:05:14 -0500 Subject: Add authorizedService support https://fedorahosted.org/sssd/ticket/670 --- src/providers/ldap/ldap_common.c | 6 +- src/providers/ldap/ldap_init.c | 2 + src/providers/ldap/sdap.h | 1 + src/providers/ldap/sdap_access.c | 135 +++++++++++++++++++++++++++++++++++++++ src/providers/ldap/sdap_access.h | 2 + 5 files changed, 144 insertions(+), 2 deletions(-) (limited to 'src/providers/ldap') diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index a38d5cc20..f0db53f22 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -118,7 +118,8 @@ struct sdap_attr_map rfc2307_user_map[] = { { "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL }, { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, - { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL } + { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }, + { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL } }; struct sdap_attr_map rfc2307_group_map[] = { @@ -157,7 +158,8 @@ struct sdap_attr_map rfc2307bis_user_map[] = { { "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL }, { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, - { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL } + { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }, + { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL } }; struct sdap_attr_map rfc2307bis_group_map[] = { diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index a1d8f05d7..d5dad3607 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -352,6 +352,8 @@ int sssm_ldap_access_init(struct be_ctx *bectx, goto done; } } + } else if (strcasecmp(order_list[c], LDAP_ACCESS_SERVICE_NAME) == 0) { + access_ctx->access_rule[c] = LDAP_ACCESS_SERVICE; } else { DEBUG(1, ("Unexpected access rule name [%s].\n", order_list[c])); ret = EINVAL; diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 8c629a3b4..57865fe09 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -229,6 +229,7 @@ enum sdap_user_attrs { SDAP_AT_KP_LASTCHANGE, SDAP_AT_KP_EXPIRATION, SDAP_AT_PWD_ATTRIBUTE, + SDAP_AT_AUTH_SVC, SDAP_OPTS_USER /* attrs counter */ }; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index fa3f522a1..4767812c0 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -72,6 +72,17 @@ static struct tevent_req *sdap_account_expired_send(TALLOC_CTX *mem_ctx, struct sdap_access_ctx *access_ctx, const char *username, struct ldb_message *user_entry); +static errno_t sdap_access_service_recv(struct tevent_req *req, + int *pam_status); +static void sdap_access_service_done(struct tevent_req *subreq); + +static struct tevent_req *sdap_access_service_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_access_ctx *access_ctx, + struct pam_data *pd, + struct ldb_message *user_entry); + static void sdap_account_expired_done(struct tevent_req *subreq); static void sdap_access_done(struct tevent_req *req); @@ -235,6 +246,19 @@ static errno_t select_next_rule(struct tevent_req *req) tevent_req_set_callback(subreq, sdap_account_expired_done, req); return EOK; + + case LDAP_ACCESS_SERVICE: + subreq = sdap_access_service_send(state, state->ev, + state->access_ctx, + state->pd, + state->user_entry); + if (subreq == NULL) { + DEBUG(1, ("sdap_access_service_send failed.\n")); + return ENOMEM; + } + tevent_req_set_callback(subreq, sdap_access_service_done, req); + return EOK; + default: DEBUG(1, ("Unexpected access rule type. Access denied.\n")); } @@ -759,6 +783,117 @@ static void sdap_access_filter_done(struct tevent_req *subreq) return; } + +struct sdap_access_service_ctx { + int pam_status; +}; + +static struct tevent_req *sdap_access_service_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_access_ctx *access_ctx, + struct pam_data *pd, + struct ldb_message *user_entry) +{ + errno_t ret; + struct tevent_req *req; + struct sdap_access_service_ctx *state; + struct ldb_message_element *el; + unsigned int i; + char *service; + + req = tevent_req_create(mem_ctx, &state, struct sdap_access_service_ctx); + if (!req) { + return NULL; + } + + state->pam_status = PAM_PERM_DENIED; + + el = ldb_msg_find_element(user_entry, SYSDB_AUTHORIZED_SERVICE); + if (!el || el->num_values == 0) { + DEBUG(1, ("Missing authorized services. Access denied\n")); + ret = EOK; + goto done; + } + + for (i = 0; i < el->num_values; i++) { + service = (char *)el->values[i].data; + if (service[0] == '!' && + strcasecmp(pd->service, service+1) == 0) { + /* This service is explicitly denied */ + state->pam_status = PAM_PERM_DENIED; + DEBUG(4, ("Access denied by [%s]\n", service)); + /* A denial trumps all. Break here */ + break; + + } else if (strcasecmp(pd->service, service) == 0) { + /* This service is explicitly allowed */ + state->pam_status = PAM_SUCCESS; + DEBUG(4, ("Access granted for [%s]\n", service)); + /* We still need to loop through to make sure + * that it's not also explicitly denied + */ + } else if (strcmp("*", service) == 0) { + /* This user has access to all services */ + state->pam_status = PAM_SUCCESS; + DEBUG(4, ("Access granted to all services\n")); + /* We still need to loop through to make sure + * that it's not also explicitly denied + */ + } + } + + if (state->pam_status != PAM_SUCCESS) { + DEBUG(4, ("No matching service rule found\n")); + } + + ret = EOK; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + + return req; +} + +static errno_t sdap_access_service_recv(struct tevent_req *req, + int *pam_status) +{ + struct sdap_access_service_ctx *state = + tevent_req_data(req, struct sdap_access_service_ctx); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *pam_status = state->pam_status; + + return EOK; +} + +static void sdap_access_service_done(struct tevent_req *subreq) +{ + errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct sdap_access_req_ctx *state = + tevent_req_data(req, struct sdap_access_req_ctx); + + ret = sdap_access_service_recv(subreq, &state->pam_status); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(1, ("Error retrieving access check result.\n")); + state->pam_status = PAM_SYSTEM_ERR; + tevent_req_error(req, ret); + return; + } + + next_access_rule(req); + + return; +} + static errno_t sdap_access_recv(struct tevent_req *req, int *pam_status) { struct sdap_access_req_ctx *state = diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h index 9b8e45bdd..66193a6dd 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -31,6 +31,7 @@ #define LDAP_ACCESS_FILTER_NAME "filter" #define LDAP_ACCESS_EXPIRE_NAME "expire" +#define LDAP_ACCESS_SERVICE_NAME "authorized_service" #define LDAP_ACCOUNT_EXPIRE_SHADOW "shadow" @@ -38,6 +39,7 @@ enum ldap_access_rule { LDAP_ACCESS_EMPTY = -1, LDAP_ACCESS_FILTER = 0, LDAP_ACCESS_EXPIRE, + LDAP_ACCESS_SERVICE, LDAP_ACCESS_LAST }; -- cgit