From 1e29e68388c2e9c5da9cb0afe997bc1b4e6933be Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 28 Oct 2010 12:38:28 +0200 Subject: Add infrastructure for Kerberos access provider --- src/providers/krb5/krb5_access.c | 91 ++++++++++++++++++++++++++++++++++ src/providers/krb5/krb5_auth.c | 104 +++++++++++++++++++++++++++++---------- src/providers/krb5/krb5_auth.h | 8 +++ src/providers/krb5/krb5_init.c | 7 +++ 4 files changed, 184 insertions(+), 26 deletions(-) create mode 100644 src/providers/krb5/krb5_access.c (limited to 'src') diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c new file mode 100644 index 00000000..21549336 --- /dev/null +++ b/src/providers/krb5/krb5_access.c @@ -0,0 +1,91 @@ +/* + SSSD + + Kerberos 5 Backend Module - access control + + Authors: + Sumit Bose + + Copyright (C) 2010 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "util/util.h" +#include "providers/krb5/krb5_auth.h" + +struct krb5_access_state { + struct tevent_context *ev; + struct be_ctx *be_ctx; + + struct pam_data *pd; + struct krb5_ctx *krb5_ctx; + const char *upn; + + bool access_allowed; +}; + +struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct pam_data *pd, + struct krb5_ctx *krb5_ctx) +{ + struct krb5_access_state *state; + struct tevent_req *req; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct krb5_access_state); + if (req == NULL) { + DEBUG(1, ("tevent_req_create failed.\n")); + return NULL; + } + + state->ev = ev; + state->be_ctx = be_ctx; + state->pd = pd; + state->krb5_ctx = krb5_ctx; + state->upn = NULL; + state->access_allowed = false; + + if (pd->cmd != SSS_PAM_ACCT_MGMT) { + DEBUG(1, ("Unexpected pam task.\n")); + ret = EINVAL; + goto done; + } + + state->access_allowed = true; + ret = EOK; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, state->ev); + return req; +} + +int krb5_access_recv(struct tevent_req *req, bool *access_allowed) +{ + struct krb5_access_state *state = tevent_req_data(req, + struct krb5_access_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *access_allowed = state->access_allowed; + + return EOK; +} diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index 4299ca89..626df2ff 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -280,12 +280,16 @@ static struct krb5_ctx *get_krb5_ctx(struct be_req *be_req) switch (pd->cmd) { case SSS_PAM_AUTHENTICATE: return talloc_get_type(be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data, - struct krb5_ctx); + struct krb5_ctx); + break; + case SSS_PAM_ACCT_MGMT: + return talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, + struct krb5_ctx); break; case SSS_PAM_CHAUTHTOK: case SSS_PAM_CHAUTHTOK_PRELIM: return talloc_get_type(be_req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data, - struct krb5_ctx); + struct krb5_ctx); break; default: DEBUG(1, ("Unsupported PAM task.\n")); @@ -649,20 +653,11 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, goto done; } break; - case SSS_PAM_ACCT_MGMT: - case SSS_PAM_SETCRED: - case SSS_PAM_OPEN_SESSION: - case SSS_PAM_CLOSE_SESSION: - state->pam_status = PAM_SUCCESS; - state->dp_err = DP_ERR_OK; - ret = EOK; - goto done; - break; default: - DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd)); - state->pam_status = PAM_MODULE_UNKNOWN; - state->dp_err = DP_ERR_OK; - ret = EOK; + DEBUG(4, ("Unexpected pam task %d.\n", pd->cmd)); + state->pam_status = PAM_SYSTEM_ERR; + state->dp_err = DP_ERR_FATAL; + ret = EINVAL; goto done; } @@ -1352,35 +1347,65 @@ static void krb_reply(struct be_req *req, int dp_err, int result) } void krb5_auth_done(struct tevent_req *req); +static void krb5_access_done(struct tevent_req *req); void krb5_pam_handler(struct be_req *be_req) { struct tevent_req *req; struct pam_data *pd; struct krb5_ctx *krb5_ctx; + int dp_err = DP_ERR_FATAL; pd = talloc_get_type(be_req->req_data, struct pam_data); + pd->pam_status = PAM_SYSTEM_ERR; krb5_ctx = get_krb5_ctx(be_req); if (krb5_ctx == NULL) { DEBUG(1, ("Kerberos context not available.\n")); - goto failed; + goto done; } - req = krb5_auth_send(be_req, be_req->be_ctx->ev, be_req->be_ctx, pd, - krb5_ctx); - if (req == NULL) { - DEBUG(1, ("krb5_auth_send failed.\n")); - goto failed; - } + switch (pd->cmd) { + case SSS_PAM_AUTHENTICATE: + case SSS_PAM_CHAUTHTOK_PRELIM: + case SSS_PAM_CHAUTHTOK: + req = krb5_auth_send(be_req, be_req->be_ctx->ev, be_req->be_ctx, pd, + krb5_ctx); + if (req == NULL) { + DEBUG(1, ("krb5_auth_send failed.\n")); + goto done; + } - tevent_req_set_callback(req, krb5_auth_done, be_req); + tevent_req_set_callback(req, krb5_auth_done, be_req); + break; + case SSS_PAM_ACCT_MGMT: + req = krb5_access_send(be_req, be_req->be_ctx->ev, be_req->be_ctx, + pd, krb5_ctx); + if (req == NULL) { + DEBUG(1, ("krb5_access_send failed.\n")); + goto done; + } + + tevent_req_set_callback(req, krb5_access_done, be_req); + break; + case SSS_PAM_SETCRED: + case SSS_PAM_OPEN_SESSION: + case SSS_PAM_CLOSE_SESSION: + pd->pam_status = PAM_SUCCESS; + dp_err = DP_ERR_OK; + goto done; + break; + default: + DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd)); + pd->pam_status = PAM_MODULE_UNKNOWN; + dp_err = DP_ERR_OK; + goto done; + } return; -failed: - pd->pam_status = PAM_SYSTEM_ERR; - krb_reply(be_req, DP_ERR_FATAL, pd->pam_status); +done: + krb_reply(be_req, dp_err, pd->pam_status); } void krb5_auth_done(struct tevent_req *req) @@ -1404,3 +1429,30 @@ void krb5_auth_done(struct tevent_req *req) krb_reply(be_req, dp_err, pd->pam_status); } + +static void krb5_access_done(struct tevent_req *req) +{ + int ret; + struct be_req *be_req = tevent_req_callback_data(req, struct be_req); + bool access_allowed; + struct pam_data *pd; + int dp_err = DP_ERR_OK; + + pd = talloc_get_type(be_req->req_data, struct pam_data); + pd->pam_status = PAM_SYSTEM_ERR; + + ret = krb5_access_recv(req, &access_allowed); + talloc_zfree(req); + if (ret != EOK) { + DEBUG(1, ("krb5_access request failed [%d][%s]\n", ret, strerror(ret))); + goto done; + } + + DEBUG(7, ("Access %s for user [%s].\n", + access_allowed ? "allowed" : "denied", pd->user)); + pd->pam_status = access_allowed ? PAM_SUCCESS : PAM_PERM_DENIED; + dp_err = DP_ERR_OK; + +done: + krb_reply(be_req, dp_err, pd->pam_status); +} diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index 9dbf7c6d..4178082a 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -74,4 +74,12 @@ errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx, errno_t init_delayed_online_authentication(struct krb5_ctx *krb5_ctx, struct be_ctx *be_ctx, struct tevent_context *ev); + +/* krb5_access.c */ +struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct pam_data *pd, + struct krb5_ctx *krb5_ctx); +int krb5_access_recv(struct tevent_req *req, bool *access_allowed); #endif /* __KRB5_AUTH_H__ */ diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c index 0c8d2250..f2b5dd79 100644 --- a/src/providers/krb5/krb5_init.c +++ b/src/providers/krb5/krb5_init.c @@ -189,3 +189,10 @@ int sssm_krb5_chpass_init(struct be_ctx *bectx, { return sssm_krb5_auth_init(bectx, ops, pvt_auth_data); } + +int sssm_krb5_access_init(struct be_ctx *bectx, + struct bet_ops **ops, + void **pvt_auth_data) +{ + return sssm_krb5_auth_init(bectx, ops, pvt_auth_data); +} -- cgit