diff options
author | Yassir Elley <yelley@redhat.com> | 2014-01-20 11:17:06 -0500 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-05-13 22:17:14 +0200 |
commit | 60cab26b12df9a2153823972cde0c38ca86e01b9 (patch) | |
tree | cc10c6da23140859116510f50cfa7dedbff48277 /src/providers/ad/ad_access.c | |
parent | 66e1502f956ee71de6cd51c37f7752f8aa14f5f5 (diff) | |
download | sssd-60cab26b12df9a2153823972cde0c38ca86e01b9.tar.gz sssd-60cab26b12df9a2153823972cde0c38ca86e01b9.tar.xz sssd-60cab26b12df9a2153823972cde0c38ca86e01b9.zip |
Implemented LDAP component of GPO-based access control
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/providers/ad/ad_access.c')
-rw-r--r-- | src/providers/ad/ad_access.c | 137 |
1 files changed, 96 insertions, 41 deletions
diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c index cae075d42..06ad47417 100644 --- a/src/providers/ad/ad_access.c +++ b/src/providers/ad/ad_access.c @@ -25,14 +25,10 @@ #include "src/providers/data_provider.h" #include "src/providers/dp_backend.h" #include "src/providers/ad/ad_access.h" +#include "providers/ad/ad_gpo.h" #include "src/providers/ad/ad_common.h" #include "src/providers/ldap/sdap_access.h" -static void -ad_access_done(struct tevent_req *req); -static errno_t -ad_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn); - /* * More advanced format can be used to restrict the filter to a specific * domain or a specific forest. This format is KEYWORD:NAME:FILTER @@ -168,6 +164,7 @@ ad_parse_access_filter(TALLOC_CTX *mem_ctx, char *spec; int flags; TALLOC_CTX *tmp_ctx; + int i = 0; if (_filter == NULL) return EINVAL; @@ -193,7 +190,7 @@ ad_parse_access_filter(TALLOC_CTX *mem_ctx, best_match = NULL; best_flags = 0; - for (int i=0; i < nfilters; i++) { + for (i=0; i < nfilters; i++) { ret = parse_filter(tmp_ctx, filters[i], &filter, &spec, &flags); if (ret != EOK) { /* Skip the faulty filter. At worst, the user won't be @@ -243,6 +240,11 @@ struct ad_access_state { int cindex; }; +static errno_t +ad_sdap_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn); +static void +ad_sdap_access_done(struct tevent_req *req); + static struct tevent_req * ad_access_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -280,7 +282,7 @@ ad_access_send(TALLOC_CTX *mem_ctx, goto done; } - ret = ad_access_step(req, state->clist[state->cindex]); + ret = ad_sdap_access_step(req, state->clist[state->cindex]); if (ret != EOK) { goto done; } @@ -289,13 +291,14 @@ ad_access_send(TALLOC_CTX *mem_ctx, done: if (ret != EOK) { tevent_req_error(req, ret); + tevent_req_post(req, ev); } return req; } static errno_t -ad_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn) +ad_sdap_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn) { struct tevent_req *subreq; struct ad_access_state *state; @@ -313,19 +316,22 @@ ad_access_step(struct tevent_req *req, struct sdap_id_conn_ctx *conn) state->ctx->sdap_access_ctx->access_rule, sizeof(int) * LDAP_ACCESS_LAST); - subreq = sdap_access_send(req, state->ev, state->be_ctx, + subreq = sdap_access_send(state, state->ev, state->be_ctx, state->domain, req_ctx, conn, state->pd); if (req == NULL) { talloc_free(req_ctx); return ENOMEM; } - tevent_req_set_callback(subreq, ad_access_done, req); + tevent_req_set_callback(subreq, ad_sdap_access_done, req); return EOK; } static void -ad_access_done(struct tevent_req *subreq) +ad_gpo_access_done(struct tevent_req *subreq); + +static void +ad_sdap_access_done(struct tevent_req *subreq) { struct tevent_req *req; struct ad_access_state *state; @@ -336,44 +342,93 @@ ad_access_done(struct tevent_req *subreq) ret = sdap_access_recv(subreq); talloc_zfree(subreq); - switch (ret) { - case EOK: - tevent_req_done(req); - return; - case ERR_ACCOUNT_EXPIRED: - tevent_req_error(req, ret); + if (ret != EOK) { + switch (ret) { + case ERR_ACCOUNT_EXPIRED: + tevent_req_error(req, ret); + return; + + case ERR_ACCESS_DENIED: + /* Retry on ACCESS_DENIED, too, to make sure that we don't + * miss out any attributes not present in GC + * FIXME - this is slow. We should retry only if GC failed + * and LDAP succeeded after the first ACCESS_DENIED + */ + break; + + default: + break; + } + + /* If possible, retry with LDAP */ + state->cindex++; + if (state->clist[state->cindex] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "Error retrieving access check result: %s\n", + sss_strerror(ret)); + tevent_req_error(req, ret); + return; + } + + ret = ad_sdap_access_step(req, state->clist[state->cindex]); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + /* Another check in progress */ + return; + } - case ERR_ACCESS_DENIED: - /* Retry on ACCESS_DENIED, too, to make sure that we don't - * miss out any attributes not present in GC - * FIXME - this is slow. We should retry only if GC failed - * and LDAP succeeded after the first ACCESS_DENIED - */ + switch (state->ctx->gpo_access_control_mode) { + case GPO_ACCESS_CONTROL_DISABLED: + /* do not evaluate gpos; mark request done */ + tevent_req_done(req); + return; + case GPO_ACCESS_CONTROL_PERMISSIVE: + case GPO_ACCESS_CONTROL_ENFORCING: + /* continue on to evaluate gpos */ break; - default: - break; + tevent_req_error(req, EINVAL); + return; } - /* If possible, retry with LDAP */ - state->cindex++; - if (state->clist[state->cindex] == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "Error retrieving access check result: %s\n", - sss_strerror(ret)); - tevent_req_error(req, ret); + subreq = ad_gpo_access_send(state, + state->be_ctx->ev, + state->domain, + state->ctx, + state->pd->user); + + if (!subreq) { + tevent_req_error(req, ENOMEM); return; } - ret = ad_access_step(req, state->clist[state->cindex]); - if (ret != EOK) { + tevent_req_set_callback(subreq, ad_gpo_access_done, req); + +} + +static void +ad_gpo_access_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + + ret = ad_gpo_access_recv(subreq); + talloc_zfree(subreq); + + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "GPO-based access control successful.\n"); + tevent_req_done(req); + } else { + DEBUG(SSSDBG_OP_FAILURE, "GPO-based access control failed.\n"); tevent_req_error(req, ret); - return; } - - /* Another check in progress */ } static errno_t @@ -385,7 +440,7 @@ ad_access_recv(struct tevent_req *req) } static void -ad_access_check_done(struct tevent_req *req); +ad_access_done(struct tevent_req *req); void ad_access_handler(struct be_req *breq) @@ -411,18 +466,18 @@ ad_access_handler(struct be_req *breq) domain = be_ctx->domain; } - /* Verify that the account is not locked */ + /* Verify access control: locked accounts, ldap policies, GPOs, etc */ req = ad_access_send(breq, be_ctx->ev, be_ctx, domain, access_ctx, pd); if (!req) { be_req_terminate(breq, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL); return; } - tevent_req_set_callback(req, ad_access_check_done, breq); + tevent_req_set_callback(req, ad_access_done, breq); } static void -ad_access_check_done(struct tevent_req *req) +ad_access_done(struct tevent_req *req) { errno_t ret; struct be_req *breq = |