From 1ab242911622d838590873d7e76347cb5f42512e Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Thu, 8 Mar 2012 15:10:31 -0500 Subject: IPA: Check nsAccountLock during PAM_ACCT_MGMT https://fedorahosted.org/sssd/ticket/1227 --- Makefile.am | 1 + src/providers/ipa/ipa_access.c | 56 ++++++++++++++++++++++++++++++++++++++++ src/providers/ipa/ipa_access.h | 1 + src/providers/ipa/ipa_common.c | 2 +- src/providers/ipa/ipa_init.c | 11 ++++++++ src/providers/ldap/sdap_access.c | 20 ++++++-------- src/providers/ldap/sdap_access.h | 9 +++++++ 7 files changed, 87 insertions(+), 13 deletions(-) diff --git a/Makefile.am b/Makefile.am index 815816585..f44296580 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1146,6 +1146,7 @@ libsss_ipa_la_SOURCES = \ src/providers/ldap/ldap_id_services.c \ src/providers/ldap/ldap_auth.c \ src/providers/ldap/ldap_common.c \ + src/providers/ldap/sdap_access.c \ src/providers/ldap/sdap_async.c \ src/providers/ldap/sdap_async_users.c \ src/providers/ldap/sdap_async_groups.c \ diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index 1eed86c33..475ddade2 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -27,6 +27,7 @@ #include "util/util.h" #include "providers/ldap/sdap_async.h" +#include "providers/ldap/sdap_access.h" #include "providers/ipa/ipa_common.h" #include "providers/ipa/ipa_access.h" #include "providers/ipa/ipa_hbac.h" @@ -63,6 +64,7 @@ enum check_result { RULE_ERROR }; +static void ipa_hbac_check(struct tevent_req *req); static int hbac_retry(struct hbac_ctx *hbac_ctx); static void hbac_connect_done(struct tevent_req *subreq); static bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret); @@ -73,6 +75,36 @@ static void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx); void ipa_access_handler(struct be_req *be_req) { + struct pam_data *pd; + struct ipa_access_ctx *ipa_access_ctx; + struct tevent_req *req; + + pd = talloc_get_type(be_req->req_data, struct pam_data); + + ipa_access_ctx = talloc_get_type( + be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, + struct ipa_access_ctx); + + /* First, verify that this account isn't locked. + * We need to do this in case the auth phase was + * skipped (such as during GSSAPI single-sign-on + * or SSH public key exchange. + */ + req = sdap_access_send(be_req, + be_req->be_ctx->ev, + be_req->be_ctx, + ipa_access_ctx->sdap_access_ctx, + pd); + if (!req) { + be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL); + return; + } + tevent_req_set_callback(req, ipa_hbac_check, be_req); +} + +static void ipa_hbac_check(struct tevent_req *req) +{ + struct be_req *be_req; struct pam_data *pd; struct hbac_ctx *hbac_ctx; const char *deny_method; @@ -80,8 +112,32 @@ void ipa_access_handler(struct be_req *be_req) struct ipa_access_ctx *ipa_access_ctx; int ret; + be_req = tevent_req_callback_data(req, struct be_req); pd = talloc_get_type(be_req->req_data, struct pam_data); + ret = sdap_access_recv(req, &pam_status); + if (ret != EOK) goto fail; + + switch(pam_status) { + case PAM_SUCCESS: + /* Account wasn't locked. Continue below + * to HBAC processing. + */ + break; + case PAM_PERM_DENIED: + /* Account was locked. Return permission denied + * here. + */ + pd->pam_status = PAM_PERM_DENIED; + be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL); + return; + default: + /* We got an unexpected error. Return it as-is */ + pd->pam_status = PAM_SYSTEM_ERR; + be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL); + return; + } + hbac_ctx = talloc_zero(be_req, struct hbac_ctx); if (hbac_ctx == NULL) { DEBUG(1, ("talloc failed.\n")); diff --git a/src/providers/ipa/ipa_access.h b/src/providers/ipa/ipa_access.h index ddfb2cf56..5234e9319 100644 --- a/src/providers/ipa/ipa_access.h +++ b/src/providers/ipa/ipa_access.h @@ -37,6 +37,7 @@ struct ipa_access_ctx { struct dp_option *ipa_options; struct time_rules_ctx *tr_ctx; time_t last_update; + struct sdap_access_ctx *sdap_access_ctx; struct sdap_search_base **host_search_bases; struct sdap_search_base **hbac_search_bases; diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index e95eeab77..375b02016 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -100,7 +100,7 @@ struct dp_option ipa_def_ldap_opts[] = { { "ldap_netgroup_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_group_nesting_level", DP_OPT_NUMBER, { .number = 2 }, NULL_NUMBER }, { "ldap_deref", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_account_expire_policy", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_account_expire_policy", DP_OPT_STRING, { "ipa" }, NULL_STRING }, { "ldap_access_order", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_chpass_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_chpass_dns_service_name", DP_OPT_STRING, NULL_STRING, NULL_STRING }, diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index 20745c11f..f02a84bfe 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -36,6 +36,7 @@ #include "providers/ipa/ipa_hostid.h" #include "providers/ipa/ipa_dyndns.h" #include "providers/ipa/ipa_session.h" +#include "providers/ldap/sdap_access.h" struct ipa_options *ipa_options = NULL; @@ -396,6 +397,16 @@ int sssm_ipa_access_init(struct be_ctx *bectx, goto done; } + /* Set up an sdap_access_ctx for checking expired/locked + * accounts. + */ + ipa_access_ctx->sdap_access_ctx = + talloc_zero(ipa_access_ctx, struct sdap_access_ctx); + + ipa_access_ctx->sdap_access_ctx->id_ctx = ipa_access_ctx->sdap_ctx; + ipa_access_ctx->sdap_access_ctx->access_rule[0] = LDAP_ACCESS_EXPIRE; + ipa_access_ctx->sdap_access_ctx->access_rule[1] = LDAP_ACCESS_EMPTY; + *ops = &ipa_access_ops; *pvt_data = ipa_access_ctx; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 1e923fd32..9df087894 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -55,12 +55,6 @@ static void sdap_access_reply(struct be_req *be_req, int pam_status) } } -static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct be_ctx *be_ctx, - struct sdap_access_ctx *access_ctx, - struct pam_data *pd); - static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct be_ctx *be_ctx, @@ -133,11 +127,12 @@ struct sdap_access_req_ctx { }; static errno_t select_next_rule(struct tevent_req *req); -static struct tevent_req *sdap_access_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct be_ctx *be_ctx, - struct sdap_access_ctx *access_ctx, - struct pam_data *pd) +struct tevent_req * +sdap_access_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct sdap_access_ctx *access_ctx, + struct pam_data *pd) { errno_t ret; struct sdap_access_req_ctx *state; @@ -1366,7 +1361,8 @@ static void sdap_access_host_done(struct tevent_req *subreq) return; } -static errno_t sdap_access_recv(struct tevent_req *req, int *pam_status) +errno_t +sdap_access_recv(struct tevent_req *req, int *pam_status) { struct sdap_access_req_ctx *state = tevent_req_data(req, struct sdap_access_req_ctx); diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h index 013645b9b..0cbee41f9 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -56,4 +56,13 @@ struct sdap_access_ctx { int access_rule[LDAP_ACCESS_LAST + 1]; }; +struct tevent_req * +sdap_access_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct sdap_access_ctx *access_ctx, + struct pam_data *pd); +errno_t +sdap_access_recv(struct tevent_req *req, int *pam_status); + #endif /* SDAP_ACCESS_H_ */ -- cgit