From a4cce2c98eedecb5d3b47da62104634cae268434 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Mon, 2 Jul 2012 10:34:52 -0400 Subject: AD: Add AD access-control provider This patch adds support for checking whether a user is expired or disabled in AD. --- Makefile.am | 2 + src/providers/ad/ad_access.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/providers/ad/ad_access.h | 35 ++++++++++++++++ src/providers/ad/ad_init.c | 56 ++++++++++++++++++++++++++ src/providers/ad/ad_opts.h | 2 +- 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/providers/ad/ad_access.c create mode 100644 src/providers/ad/ad_access.h diff --git a/Makefile.am b/Makefile.am index c638f0223..359306211 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1353,6 +1353,8 @@ libsss_ad_la_SOURCES = \ src/providers/ad/ad_init.c \ src/providers/ad/ad_id.c \ src/providers/ad/ad_id.h \ + src/providers/ad/ad_access.c \ + src/providers/ad/ad_access.h \ src/providers/ad/ad_opts.h \ src/util/find_uid.c \ src/util/user_info_msg.c \ diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c new file mode 100644 index 000000000..314cdcfad --- /dev/null +++ b/src/providers/ad/ad_access.c @@ -0,0 +1,96 @@ +/* + SSSD + + Authors: + Stephen Gallagher + + Copyright (C) 2012 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 +#include "src/util/util.h" +#include "src/providers/data_provider.h" +#include "src/providers/dp_backend.h" +#include "src/providers/ad/ad_access.h" +#include "src/providers/ldap/sdap_access.h" + +static void +ad_access_done(struct tevent_req *req); + +void +ad_access_handler(struct be_req *breq) +{ + struct tevent_req *req; + struct ad_access_ctx *access_ctx = + talloc_get_type(breq->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, + struct ad_access_ctx); + + struct pam_data *pd = talloc_get_type(breq->req_data, struct pam_data); + + /* Handle subdomains */ + if (strcasecmp(pd->domain, breq->be_ctx->domain->name) != 0) { + breq->domain = new_subdomain(breq, breq->be_ctx->domain, pd->domain, + NULL, NULL); + if (breq->domain == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n")); + breq->fn(breq, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL); + return; + } + breq->sysdb = breq->domain->sysdb; + } + + /* Verify that the account is not locked */ + req = sdap_access_send(breq, + breq->be_ctx->ev, + breq, + access_ctx->sdap_access_ctx, + pd); + if (!req) { + breq->fn(breq, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL); + return; + } + tevent_req_set_callback(req, ad_access_done, breq); +} + +static void +ad_access_done(struct tevent_req *req) +{ + errno_t ret; + int pam_status; + struct be_req *breq = + tevent_req_callback_data(req, struct be_req); + struct pam_data *pd = talloc_get_type(breq->req_data, struct pam_data); + + ret = sdap_access_recv(req, &pam_status); + talloc_zfree(req); + if (ret != EOK) { + breq->fn(breq, DP_ERR_FATAL, PAM_SYSTEM_ERR, strerror(ret)); + return; + } + + pd->pam_status = pam_status; + + if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED) { + /* We got the proper approval or denial */ + breq->fn(breq, DP_ERR_OK, pam_status, NULL); + return; + } + + /* Something went wrong */ + pd->pam_status = PAM_SYSTEM_ERR; + breq->fn(breq, DP_ERR_FATAL, pam_status, pam_strerror(NULL, pam_status)); + return; +} diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h new file mode 100644 index 000000000..62259265d --- /dev/null +++ b/src/providers/ad/ad_access.h @@ -0,0 +1,35 @@ +/* + SSSD + + Authors: + Stephen Gallagher + + Copyright (C) 2012 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 . +*/ + +#ifndef AD_ACCESS_H_ +#define AD_ACCESS_H_ + +struct ad_access_ctx { + struct sdap_id_ctx *sdap_ctx; + struct dp_option *ad_options; + struct sdap_access_ctx *sdap_access_ctx; +}; + +void +ad_access_handler(struct be_req *breq); + +#endif /* AD_ACCESS_H_ */ diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index 89101a5b1..6baae0ce5 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -28,7 +28,9 @@ #include "util/util.h" #include "providers/ad/ad_common.h" +#include "providers/ad/ad_access.h" #include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_access.h" #include "providers/ldap/sdap_idmap.h" #include "providers/krb5/krb5_auth.h" #include "providers/krb5/krb5_init_shared.h" @@ -55,6 +57,11 @@ struct bet_ops ad_chpass_ops = { .finalize = NULL }; +struct bet_ops ad_access_ops = { + .handler = ad_access_handler, + .finalize = NULL +}; + static errno_t common_ad_init(struct be_ctx *bectx) { @@ -261,6 +268,55 @@ sssm_ad_chpass_init(struct be_ctx *bectx, return ret; } +int +sssm_ad_access_init(struct be_ctx *bectx, + struct bet_ops **ops, + void **pvt_data) +{ + errno_t ret; + struct ad_access_ctx *access_ctx; + struct ad_id_ctx *ad_id_ctx; + + access_ctx = talloc_zero(bectx, struct ad_access_ctx); + if (!access_ctx) return ENOMEM; + + ret = sssm_ad_id_init(bectx, ops, (void **)&ad_id_ctx); + if (ret != EOK) { + goto fail; + } + access_ctx->sdap_ctx = ad_id_ctx->sdap_id_ctx; + + ret = dp_copy_options(access_ctx, ad_options->basic, AD_OPTS_BASIC, + &access_ctx->ad_options); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Could not initialize access provider options: [%s]\n", + strerror(ret))); + goto fail; + } + + /* Set up an sdap_access_ctx for checking expired/locked accounts */ + access_ctx->sdap_access_ctx = + talloc_zero(access_ctx, struct sdap_access_ctx); + if (!access_ctx->sdap_access_ctx) { + ret = ENOMEM; + goto fail; + } + + access_ctx->sdap_access_ctx->id_ctx = access_ctx->sdap_ctx; + access_ctx->sdap_access_ctx->access_rule[0] = LDAP_ACCESS_EXPIRE; + access_ctx->sdap_access_ctx->access_rule[1] = LDAP_ACCESS_EMPTY; + + *ops = &ad_access_ops; + *pvt_data = access_ctx; + + return EOK; + +fail: + talloc_free(access_ctx); + return ret; +} + static void ad_shutdown(struct be_req *req) { diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h index 178d097f6..b3df14c92 100644 --- a/src/providers/ad/ad_opts.h +++ b/src/providers/ad/ad_opts.h @@ -92,7 +92,7 @@ struct dp_option ad_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, { "ad" }, NULL_STRING }, { "ldap_access_order", DP_OPT_STRING, { "filter" }, NULL_STRING }, { "ldap_chpass_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_chpass_dns_service_name", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -- cgit