diff options
-rw-r--r-- | src/providers/ad/ad_id.c | 19 | ||||
-rw-r--r-- | src/providers/ad/ad_init.c | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_groups.c | 62 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 50 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups_ad.c | 157 |
6 files changed, 261 insertions, 30 deletions
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c index 19bc65825..cf71b172d 100644 --- a/src/providers/ad/ad_id.c +++ b/src/providers/ad/ad_id.c @@ -199,6 +199,8 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, case BE_REQ_USER: /* user */ case BE_REQ_BY_SECID: /* by SID */ case BE_REQ_USER_AND_GROUP: /* get SID */ + case BE_REQ_GROUP: /* group */ + case BE_REQ_INITGROUPS: /* init groups for user */ /* Always try GC first */ clist[0] = ad_ctx->gc_ctx; if (IS_SUBDOMAIN(dom) == true) { @@ -215,23 +217,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, */ clist[1] = ad_ctx->ldap_ctx; break; - - case BE_REQ_GROUP: /* group */ - case BE_REQ_INITGROUPS: /* init groups for user */ - if (IS_SUBDOMAIN(dom)) { - sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom); - if (sdom == NULL || sdom->pvt == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", - dom->name)); - return NULL; - } - subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - clist[0] = subdom_id_ctx->ldap_ctx; - } else { - clist[0] = ad_ctx->ldap_ctx; - } - break; - default: clist[0] = ad_ctx->ldap_ctx; break; diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index d06efbd08..332bfda38 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -214,6 +214,8 @@ sssm_ad_id_init(struct be_ctx *bectx, goto done; } + ad_ctx->sdap_id_ctx->opts->sdom->pvt = ad_ctx; + /* Set up the ID mapping object */ ret = sdap_idmap_init(ad_ctx->sdap_id_ctx, ad_ctx->sdap_id_ctx, &ad_ctx->sdap_id_ctx->opts->idmap_ctx); diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index f47437553..33e8708ab 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -297,6 +297,7 @@ struct tevent_req * sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 33648c5da..9eece9a6e 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -26,6 +26,7 @@ #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_idmap.h" +#include "providers/ad/ad_common.h" /* ==Group-Parsing Routines=============================================== */ @@ -1540,9 +1541,13 @@ struct sdap_get_groups_state { size_t base_iter; struct sdap_search_base **search_bases; + + struct sdap_handle *ldap_sh; + struct sdap_id_op *op; }; static errno_t sdap_get_groups_next_base(struct tevent_req *req); +static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq); static void sdap_get_groups_process(struct tevent_req *subreq); static void sdap_get_groups_done(struct tevent_req *subreq); @@ -1558,7 +1563,9 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, { errno_t ret; struct tevent_req *req; + struct tevent_req *subreq; struct sdap_get_groups_state *state; + struct ad_id_ctx *subdom_id_ctx; req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); if (!req) return NULL; @@ -1586,6 +1593,30 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, goto done; } + /* With AD by default the Global Catalog is used for lookup. But the GC + * group object might not have full group membership data. To make sure we + * connect to an LDAP server of the group's domain. */ + if (state->opts->schema_type == SDAP_SCHEMA_AD && sdom->pvt != NULL) { + subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); + state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); + if (!state->op) { + DEBUG(2, ("sdap_id_op_create failed\n")); + ret = ENOMEM; + goto done; + } + + subreq = sdap_id_op_connect_send(state->op, state, &ret); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, + sdap_get_groups_ldap_connect_done, + req); + return req; + } + ret = sdap_get_groups_next_base(req); done: @@ -1597,6 +1628,34 @@ done: return req; } +static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_get_groups_state *state; + int ret; + int dp_error; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_get_groups_state); + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + state->ldap_sh = sdap_id_op_handle(state->op); + + ret = sdap_get_groups_next_base(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } + + return; +} + static errno_t sdap_get_groups_next_base(struct tevent_req *req) { struct tevent_req *subreq; @@ -1617,7 +1676,8 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) state->search_bases[state->base_iter]->basedn)); subreq = sdap_get_generic_send( - state, state->ev, state->opts, state->sh, + state, state->ev, state->opts, + state->ldap_sh != NULL ? state->ldap_sh : state->sh, state->search_bases[state->base_iter]->basedn, state->search_bases[state->base_iter]->scope, state->filter, state->attrs, diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 1b865af0a..aba7ba42d 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2749,6 +2749,10 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) const char *orig_dn; const char *cname; bool in_transaction = false; + char *expected_basedn; + size_t expected_basedn_len; + size_t dn_len; + size_t c = 0; DEBUG(9, ("Receiving info for the user\n")); @@ -2788,11 +2792,50 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) } else if (count != 1) { DEBUG(SSSDBG_OP_FAILURE, ("Expected one user entry and got %zu\n", count)); - tevent_req_error(req, EINVAL); - return; + + ret = domain_to_basedn(state, state->dom->name, &expected_basedn); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("domain_to_basedn failed.\n")); + tevent_req_error(req, ret); + return; + } + expected_basedn = talloc_asprintf(state, "%s%s", + "cn=users,", expected_basedn); + if (expected_basedn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_append failed.\n")); + tevent_req_error(req, ENOMEM); + return; + } + + DEBUG(SSSDBG_TRACE_ALL, ("Expected BaseDN is [%s].\n", expected_basedn)); + expected_basedn_len = strlen(expected_basedn); + + for (c = 0; c < count; c++) { + ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); + tevent_req_error(req, ret); + return; + } + dn_len = strlen(orig_dn); + + if (dn_len > expected_basedn_len + && strcasecmp(orig_dn + (dn_len - expected_basedn_len), + expected_basedn) == 0) { + DEBUG(SSSDBG_TRACE_ALL, + ("Found matching dn [%s].\n", orig_dn)); + break; + } + } + + if (c == count) { + DEBUG(SSSDBG_OP_FAILURE, ("No matching DN found.\n")); + tevent_req_error(req, EINVAL); + return; + } } - state->orig_user = usr_attrs[0]; + state->orig_user = usr_attrs[c]; ret = sysdb_transaction_start(state->sysdb); if (ret) { @@ -2858,6 +2901,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) */ subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, state->id_ctx, + state->conn, state->opts, state->sysdb, state->dom, diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index f1bf77e86..8f8f0a4cc 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -25,6 +25,7 @@ #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/sdap_idmap.h" +#include "providers/ad/ad_common.h" #include "lib/idmap/sss_idmap.h" struct sdap_ad_match_rule_initgr_state { @@ -528,6 +529,7 @@ done: struct sdap_ad_resolve_sids_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; + struct sdap_id_conn_ctx *conn; struct sdap_options *opts; struct sss_domain_info *domain; char **sids; @@ -543,6 +545,7 @@ static struct tevent_req * sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, struct sdap_options *opts, struct sss_domain_info *domain, char **sids) @@ -560,6 +563,7 @@ sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; + state->conn = conn; state->opts = opts; state->domain = get_domains_head(domain); state->sids = sids; @@ -618,7 +622,7 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req) } subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain, - state->id_ctx->conn, state->current_sid, + state->conn, state->current_sid, BE_FILTER_SECID, BE_ATTR_CORE, false); if (subreq == NULL) { return ENOMEM; @@ -673,12 +677,21 @@ static errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req) struct sdap_ad_tokengroups_initgr_mapping_state { + struct tevent_context *ev; + struct sdap_options *opts; + struct sdap_handle *sh; struct sdap_idmap_ctx *idmap_ctx; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; + const char *orig_dn; + int timeout; const char *username; + + struct sdap_id_op *op; }; +static void +sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq); static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq); static struct tevent_req * @@ -695,6 +708,8 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; + struct sdap_domain *sdom; + struct ad_id_ctx *subdom_id_ctx; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -704,23 +719,43 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, return NULL; } + state->ev = ev; + state->opts = opts; + state->sh = sh; state->idmap_ctx = opts->idmap_ctx; state->sysdb = sysdb; state->domain = domain; + state->timeout = timeout; + state->orig_dn = orig_dn; state->username = talloc_strdup(state, name); if (state->username == NULL) { ret = ENOMEM; goto immediately; } - subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, - timeout); + sdom = sdap_domain_get(opts, domain); + if (sdom == NULL || sdom->pvt == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", + domain->name)); + ret = EINVAL; + goto immediately; + } + subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); + state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); + if (!state->op) { + DEBUG(2, ("sdap_id_op_create failed\n")); + ret = ENOMEM; + goto immediately; + } + + subreq = sdap_id_op_connect_send(state->op, state, &ret); if (subreq == NULL) { ret = ENOMEM; goto immediately; } - tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done, + tevent_req_set_callback(subreq, + sdap_ad_tokengroups_initgr_mapping_connect_done, req); return req; @@ -736,6 +771,42 @@ immediately: return req; } +static void +sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq) +{ + struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; + struct tevent_req *req = NULL; + int ret; + int dp_error = DP_ERR_FATAL; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, + struct sdap_ad_tokengroups_initgr_mapping_state); + + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, + sdap_id_op_handle(state->op), + state->username, + state->orig_dn, state->timeout); + if (subreq == NULL) { + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done, + req); + + return; +} + static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq) { TALLOC_CTX *tmp_ctx = NULL; @@ -896,22 +967,31 @@ static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req) struct sdap_ad_tokengroups_initgr_posix_state { struct tevent_context *ev; struct sdap_id_ctx *id_ctx; + struct sdap_id_conn_ctx *conn; struct sdap_options *opts; + struct sdap_handle *sh; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; + const char *orig_dn; + int timeout; const char *username; + + struct sdap_id_op *op; }; static void sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq); static void +sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq); +static void sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq); static struct tevent_req * sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, @@ -923,6 +1003,8 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; + struct sdap_domain *sdom; + struct ad_id_ctx *subdom_id_ctx; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -934,23 +1016,42 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->id_ctx = id_ctx; + state->conn = conn; state->opts = opts; + state->sh = sh; state->sysdb = sysdb; state->domain = domain; + state->orig_dn = orig_dn; + state->timeout = timeout; state->username = talloc_strdup(state, name); if (state->username == NULL) { ret = ENOMEM; goto immediately; } - subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, - timeout); + sdom = sdap_domain_get(opts, domain); + if (sdom == NULL || sdom->pvt == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", + domain->name)); + ret = EINVAL; + goto immediately; + } + subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); + state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); + if (!state->op) { + DEBUG(2, ("sdap_id_op_create failed\n")); + ret = ENOMEM; + goto immediately; + } + + subreq = sdap_id_op_connect_send(state->op, state, &ret); if (subreq == NULL) { ret = ENOMEM; goto immediately; } - tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done, + tevent_req_set_callback(subreq, + sdap_ad_tokengroups_initgr_posix_sids_connect_done, req); return req; @@ -967,6 +1068,42 @@ immediately: } static void +sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq) +{ + struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; + struct tevent_req *req = NULL; + int ret; + int dp_error = DP_ERR_FATAL; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, + struct sdap_ad_tokengroups_initgr_posix_state); + + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, + sdap_id_op_handle(state->op), + state->username, state->orig_dn, + state->timeout); + if (subreq == NULL) { + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done, + req); + + return; +} + +static void sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq) { TALLOC_CTX *tmp_ctx = NULL; @@ -1089,6 +1226,7 @@ sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq) /* download missing SIDs */ missing_sids = talloc_steal(state, missing_sids); subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx, + state->conn, state->opts, state->domain, missing_sids); if (subreq == NULL) { @@ -1154,6 +1292,7 @@ struct tevent_req * sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, struct sdap_options *opts, struct sysdb_ctx *sysdb, struct sss_domain_info *domain, @@ -1184,8 +1323,8 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, name, orig_dn, timeout); } else { - subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, opts, - sysdb, domain, sh, + subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn, + opts, sysdb, domain, sh, name, orig_dn, timeout); } |