From 3d28e0e560b787b5c57ed7327d184310342a7e38 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Wed, 19 Jun 2013 10:51:19 +0200 Subject: IPA: Look up AD users directly if IPA server mode is on https://fedorahosted.org/sssd/ticket/1962 If the ipa_server_mode is selected IPA subdomain user and group lookups are not done with the help of the extdom plugin but directly against AD using the AD ID code. --- src/providers/ipa/ipa_common.h | 1 + src/providers/ipa/ipa_id.c | 23 +++++-- src/providers/ipa/ipa_id.h | 9 +++ src/providers/ipa/ipa_subdomains_id.c | 126 ++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 4 deletions(-) (limited to 'src/providers/ipa') diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 2af20e1d..1afe20db 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -26,6 +26,7 @@ #include "confdb/confdb.h" #include "providers/ldap/ldap_common.h" #include "providers/krb5/krb5_common.h" +#include "providers/ad/ad_common.h" struct ipa_service { struct sdap_service *sdap; diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c index b11abaa7..6e096440 100644 --- a/src/providers/ipa/ipa_id.c +++ b/src/providers/ipa/ipa_id.c @@ -83,9 +83,15 @@ void ipa_account_info_handler(struct be_req *breq) ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req); if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) { - /* if domain names do not match, this is a subdomain case */ - req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar); - + /* if domain names do not match, this is a subdomain case + * subdomain lookups are handled differently on the server + * and the client + */ + if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) { + req = ipa_get_ad_acct_send(breq, be_ctx->ev, ipa_ctx, breq, ar); + } else { + req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar); + } } else if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { /* netgroups are handled by a separate request function */ if (ar->filter_type != BE_FILTER_NAME) { @@ -110,15 +116,24 @@ void ipa_account_info_handler(struct be_req *breq) static void ipa_account_info_done(struct tevent_req *req) { struct be_req *breq = tevent_req_callback_data(req, struct be_req); + struct be_ctx *be_ctx = be_req_get_be_ctx(breq); + struct ipa_id_ctx *ipa_ctx; struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req); const char *error_text; int ret, dp_error; + ipa_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, + struct ipa_id_ctx); + if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { ret = ipa_id_get_netgroup_recv(req, &dp_error); } else { - ret = ipa_get_subdom_acct_recv(req, &dp_error); + if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) { + ret = ipa_get_ad_acct_recv(req, &dp_error); + } else { + ret = ipa_get_subdom_acct_recv(req, &dp_error); + } } talloc_zfree(req); diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h index 7fa25e92..6c72f6d0 100644 --- a/src/providers/ipa/ipa_id.h +++ b/src/providers/ipa/ipa_id.h @@ -64,4 +64,13 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx, struct be_acct_req *ar); int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out); + +struct tevent_req *ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct be_req *be_req, + struct be_acct_req *ar); + +errno_t ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out); + #endif diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index dc822888..6bf97bec 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -30,6 +30,7 @@ #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" #include "providers/ipa/ipa_id.h" +#include "providers/ad/ad_id.h" #include "providers/ipa/ipa_subdomains.h" struct ipa_get_subdom_acct { @@ -246,3 +247,128 @@ int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out) return EOK; } +/* IPA lookup for server mode. Directly to AD. */ +struct ipa_get_ad_acct_state { + int dp_error; +}; + +static void ipa_get_ad_acct_done(struct tevent_req *subreq); +static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, + struct sss_domain_info *dom); + +struct tevent_req * +ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct be_req *be_req, + struct be_acct_req *ar) +{ + errno_t ret; + struct tevent_req *req; + struct tevent_req *subreq; + struct ipa_get_ad_acct_state *state; + struct sss_domain_info *dom; + struct sdap_domain *sdom; + struct sdap_id_conn_ctx **clist; + struct sdap_id_ctx *sdap_id_ctx;; + struct ad_id_ctx *ad_id_ctx; + + req = tevent_req_create(mem_ctx, &state, struct ipa_get_ad_acct_state); + if (req == NULL) return NULL; + + /* This can only be a subdomain request, verify subdomain */ + dom = find_subdomain_by_name(ipa_ctx->sdap_id_ctx->be->domain, + ar->domain, true); + if (dom == NULL) { + ret = EINVAL; + goto fail; + } + + /* Let's see if this subdomain has a ad_id_ctx */ + ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, dom); + if (ad_id_ctx == NULL) { + ret = EINVAL; + goto fail; + } + sdap_id_ctx = ad_id_ctx->sdap_id_ctx; + + /* Currently only LDAP port for AD is used because POSIX + * attributes are not replicated to GC by default + */ + clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2); + if (clist == NULL) { + ret = ENOMEM; + goto fail; + } + clist[0] = ad_id_ctx->ldap_ctx; + clist[1] = NULL; + + /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */ + sdom = sdap_domain_get(sdap_id_ctx->opts, dom); + if (sdom == NULL) { + ret = EIO; + goto fail; + } + + subreq = ad_handle_acct_info_send(req, be_req, ar, sdap_id_ctx, + sdom, clist); + if (subreq == NULL) { + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, ipa_get_ad_acct_done, req); + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static struct ad_id_ctx * +ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, + struct sss_domain_info *dom) +{ + struct ipa_ad_server_ctx *iter; + + DLIST_FOR_EACH(iter, ipa_ctx->server_mode->trusts) { + if (iter->dom == dom) break; + } + + return iter->ad_id_ctx; +} + +static void +ipa_get_ad_acct_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ipa_get_ad_acct_state *state = tevent_req_data(req, + struct ipa_get_ad_acct_state); + errno_t ret; + + ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("AD lookup failed: %d\n", ret)); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t +ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out) +{ + struct ipa_get_ad_acct_state *state = tevent_req_data(req, + struct ipa_get_ad_acct_state); + + if (dp_error_out) { + *dp_error_out = state->dp_error; + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} -- cgit