diff options
author | Sumit Bose <sbose@redhat.com> | 2014-10-01 17:04:44 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-10-16 17:56:18 +0200 |
commit | ed4a9bd4d0f7fb359bed66a8d63a92e7be633aae (patch) | |
tree | 4ab1fcf529bf170722810c5833d68f89c5b363a1 /src/providers/ipa | |
parent | 9c8db0a17a66c58c36966b17d004142a4aaace8d (diff) | |
download | sssd-ed4a9bd4d0f7fb359bed66a8d63a92e7be633aae.tar.gz sssd-ed4a9bd4d0f7fb359bed66a8d63a92e7be633aae.tar.xz sssd-ed4a9bd4d0f7fb359bed66a8d63a92e7be633aae.zip |
views: search overrides for user and group requests
If the name or the POSIX ID of a user or a group is overridden the
search request for those objects have to check the overide objects first
before looking up the original objects.
This patch adds a new request for the IPA sub-domain users which checks
the overrides first if
- SSSD is running in ipa-server-mode and a name or a POSIX ID is
searched, since we do not override the SIDs we can skip the search in
the override tree here
- if the responder indicates it has not found the corresponding object
in the cache and the input might be an override name or ID and not the
original one of an object.
If an override object was found the SID is extracted from the anchor
attribute and the original object is search by its SID. If no override
object was found the original object is search with the original input
and finally it is checked if an override object exits for the found
object.
Relates to https://fedorahosted.org/sssd/ticket/2375
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/providers/ipa')
-rw-r--r-- | src/providers/ipa/ipa_id.c | 18 | ||||
-rw-r--r-- | src/providers/ipa/ipa_id.h | 31 | ||||
-rw-r--r-- | src/providers/ipa/ipa_s2n_exop.c | 83 | ||||
-rw-r--r-- | src/providers/ipa/ipa_subdomains_id.c | 389 | ||||
-rw-r--r-- | src/providers/ipa/ipa_views.c | 181 |
5 files changed, 601 insertions, 101 deletions
diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c index 942feb19e..cd65f5b46 100644 --- a/src/providers/ipa/ipa_id.c +++ b/src/providers/ipa/ipa_id.c @@ -87,11 +87,8 @@ void ipa_account_info_handler(struct be_req *breq) * 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, ipa_ctx, ar); - } + req = ipa_subdomain_account_send(breq, be_ctx->ev, ipa_ctx, breq, 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) { @@ -116,24 +113,15 @@ 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 { - 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); - } + ret = ipa_subdomain_account_recv(req, &dp_error); } talloc_zfree(req); diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h index b1d68dee6..e13aded21 100644 --- a/src/providers/ipa/ipa_id.h +++ b/src/providers/ipa/ipa_id.h @@ -53,18 +53,20 @@ int ipa_get_netgroups_recv(struct tevent_req *req, void ipa_check_online(struct be_req *be_req); struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ipa_id_ctx *ipa_ctx, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sdap_handle *sh, - int entry_type, - struct req_input *req_input); + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct sdap_options *opts, + struct sss_domain_info *dom, + struct sysdb_attrs *override_attrs, + struct sdap_handle *sh, + int entry_type, + struct req_input *req_input); int ipa_s2n_get_acct_info_recv(struct tevent_req *req); struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_id_ctx *ipa_ctx, + struct sysdb_attrs *override_attrs, struct be_acct_req *ar); int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out); @@ -72,20 +74,33 @@ 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 sysdb_attrs *override_attrs, struct be_acct_req *ar); errno_t ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out); +errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid, + const char *domain_name, + struct be_acct_req **_ar); + struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sdap_id_ctx *sdap_id_ctx, struct ipa_options *ipa_options, const char *ipa_realm, const char *view_name, - const char *obj_sid); + struct be_acct_req *ar); errno_t ipa_get_ad_override_recv(struct tevent_req *req, int *dp_error_out, TALLOC_CTX *mem_ctx, struct sysdb_attrs **override_attrs); +struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct be_req *be_req, + struct be_acct_req *ar); + +errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out); + #endif diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c index 1ee9c238b..96528816a 100644 --- a/src/providers/ipa/ipa_s2n_exop.c +++ b/src/providers/ipa/ipa_s2n_exop.c @@ -884,6 +884,7 @@ struct ipa_s2n_get_groups_state { size_t group_idx; int exop_timeout; struct resp_attrs *attrs; + struct sss_domain_info *obj_domain; }; static errno_t ipa_s2n_get_groups_step(struct tevent_req *req); @@ -940,7 +941,6 @@ static errno_t ipa_s2n_get_groups_step(struct tevent_req *req) struct ipa_s2n_get_groups_state); struct berval *bv_req; struct tevent_req *subreq; - struct sss_domain_info *obj_domain; struct sss_domain_info *parent_domain; char *group_name = NULL; char *domain_name = NULL; @@ -957,15 +957,15 @@ static errno_t ipa_s2n_get_groups_step(struct tevent_req *req) return ret; } - obj_domain = find_domain_by_name(parent_domain, domain_name, true); - if (obj_domain == NULL) { + state->obj_domain = find_domain_by_name(parent_domain, domain_name, true); + if (state->obj_domain == NULL) { DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n"); return ENOMEM; } state->req_input.inp.name = group_name; - ret = s2n_encode_request(state, obj_domain->name, BE_REQ_GROUP, + ret = s2n_encode_request(state, state->obj_domain->name, BE_REQ_GROUP, REQ_FULL_WITH_MEMBERS, &state->req_input, &bv_req); if (ret != EOK) { @@ -994,6 +994,7 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq) char *retoid = NULL; struct berval *retdata = NULL; const char *sid_str; + struct be_acct_req *ar; ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata); talloc_zfree(subreq); @@ -1016,13 +1017,19 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq) goto fail; } + ret = get_be_acct_req_for_sid(state, sid_str, state->obj_domain->name, &ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n"); + goto fail; + } + subreq = ipa_get_ad_override_send(state, state->ev, state->ipa_ctx->sdap_id_ctx, state->ipa_ctx->ipa_options, dp_opt_get_string(state->ipa_ctx->ipa_options->basic, IPA_KRB5_REALM), state->ipa_ctx->view_name, - sid_str); + ar); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); ret = ENOMEM; @@ -1097,20 +1104,21 @@ struct ipa_s2n_get_user_state { enum request_types request_type; struct resp_attrs *attrs; struct resp_attrs *simple_attrs; - struct resp_attrs *override_attrs; + struct sysdb_attrs *override_attrs; int exop_timeout; }; static void ipa_s2n_get_user_done(struct tevent_req *subreq); struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ipa_id_ctx *ipa_ctx, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sdap_handle *sh, - int entry_type, - struct req_input *req_input) + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct sdap_options *opts, + struct sss_domain_info *dom, + struct sysdb_attrs *override_attrs, + struct sdap_handle *sh, + int entry_type, + struct req_input *req_input) { struct ipa_s2n_get_user_state *state; struct tevent_req *req; @@ -1134,6 +1142,7 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, state->attrs = NULL; state->simple_attrs = NULL; state->exop_timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT); + state->override_attrs = override_attrs; if (sdap_is_extension_supported(sh, EXOP_SID2NAME_V1_OID)) { state->request_type = REQ_FULL_WITH_MEMBERS; @@ -1340,6 +1349,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) char **missing_groups = NULL; struct ldb_dn **group_dn_list = NULL; const char *sid_str; + struct be_acct_req *ar; ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata); talloc_zfree(subreq); @@ -1453,6 +1463,9 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) } else if (state->attrs->sysdb_attrs != NULL) { ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR, &sid_str); + } else if (state->req_input->type == REQ_INP_SECID) { + sid_str = state->req_input->inp.secid; + ret = EOK; } else { DEBUG(SSSDBG_TRACE_FUNC, "No SID available.\n"); ret = ENOENT; @@ -1466,13 +1479,19 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) goto done; } } else if (ret == EOK) { + ret = get_be_acct_req_for_sid(state, sid_str, state->dom->name, &ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n"); + goto done; + } + subreq = ipa_get_ad_override_send(state, state->ev, state->ipa_ctx->sdap_id_ctx, state->ipa_ctx->ipa_options, dp_opt_get_string(state->ipa_ctx->ipa_options->basic, IPA_KRB5_REALM), state->ipa_ctx->view_name, - sid_str); + ar); if (subreq == NULL) { DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); ret = ENOMEM; @@ -1798,6 +1817,7 @@ static void ipa_s2n_get_groups_done(struct tevent_req *subreq) struct ipa_s2n_get_user_state *state = tevent_req_data(req, struct ipa_s2n_get_user_state); const char *sid_str; + struct be_acct_req *ar; ret = ipa_s2n_get_groups_recv(subreq); talloc_zfree(subreq); @@ -1823,19 +1843,40 @@ static void ipa_s2n_get_groups_done(struct tevent_req *subreq) goto fail; } - subreq = ipa_get_ad_override_send(state, state->ev, + ret = get_be_acct_req_for_sid(state, sid_str, state->dom->name, &ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n"); + goto fail; + } + + if (state->override_attrs == NULL) { + subreq = ipa_get_ad_override_send(state, state->ev, state->ipa_ctx->sdap_id_ctx, state->ipa_ctx->ipa_options, dp_opt_get_string(state->ipa_ctx->ipa_options->basic, IPA_KRB5_REALM), state->ipa_ctx->view_name, - sid_str); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); - ret = ENOMEM; - goto fail; + ar); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, ipa_s2n_get_user_get_override_done, + req); + } else { + ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs, + state->simple_attrs, + state->ipa_ctx->view_name, + state->override_attrs); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); } - tevent_req_set_callback(subreq, ipa_s2n_get_user_get_override_done, req); return; diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index f6cc92e3d..36f8b2392 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -34,6 +34,281 @@ #include "providers/ad/ad_id.h" #include "providers/ipa/ipa_subdomains.h" +struct ipa_subdomain_account_state { + struct tevent_context *ev; + struct ipa_id_ctx *ipa_ctx; + struct sdap_id_ctx *ctx; + struct sdap_id_op *op; + struct sysdb_ctx *sysdb; + struct sss_domain_info *domain; + struct be_req *be_req; + struct be_acct_req *ar; + + bool ipa_server_mode; + int entry_type; + const char *filter; + int filter_type; + struct sysdb_attrs *override_attrs; + + int dp_error; +}; + +static void ipa_subdomain_account_connected(struct tevent_req *subreq); +static void ipa_subdomain_account_got_override(struct tevent_req *subreq); +static void ipa_subdomain_account_done(struct tevent_req *subreq); +static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req, + struct be_acct_req *ar); + +struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + struct be_req *be_req, + struct be_acct_req *ar) +{ + struct tevent_req *req; + struct ipa_subdomain_account_state *state; + struct tevent_req *subreq; + int ret; + + req = tevent_req_create(memctx, &state, struct ipa_subdomain_account_state); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n"); + return NULL; + } + + state->ev = ev; + state->ipa_ctx = ipa_ctx; + state->ctx = ipa_ctx->sdap_id_ctx; + state->dp_error = DP_ERR_FATAL; + + state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); + if (!state->op) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); + ret = ENOMEM; + goto fail; + } + + state->domain = find_domain_by_name(state->ctx->be->domain, + ar->domain, true); + if (state->domain == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n"); + ret = ENOMEM; + goto fail; + } + state->sysdb = state->domain->sysdb; + state->be_req = be_req; + state->ar = ar; + state->ipa_server_mode = dp_opt_get_bool(state->ipa_ctx->ipa_options->basic, + IPA_SERVER_MODE); + state->override_attrs = NULL; + + /* With views we cannot got directly to the look up the AD objects but + * have to check first if the request matches an override in the given + * view. But there are cases where this can be skipped and the AD object + * can be searched directly: + * - searches by SID: because we do not override the SID + * - if the responder does not send the EXTRA_INPUT_MAYBE_WITH_VIEW flags, + * because in this case the entry was found in the cache and the + * original value is used for the search (e.g. during cache updates) */ + if (state->ar->filter_type == BE_FILTER_SECID + || (!state->ipa_server_mode + && state->ar->extra_value != NULL + && strcmp(state->ar->extra_value, + EXTRA_INPUT_MAYBE_WITH_VIEW) != 0 )) { + ret = ipa_subdomain_account_get_original_step(req, state->ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "ipa_subdomain_account_get_original_step failed.\n"); + goto fail; + } + + return req; + } + + subreq = sdap_id_op_connect_send(state->op, state, &ret); + if (!subreq) { + goto fail; + } + tevent_req_set_callback(subreq, ipa_subdomain_account_connected, req); + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void ipa_subdomain_account_connected(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ipa_subdomain_account_state *state = tevent_req_data(req, + struct ipa_subdomain_account_state); + int dp_error = DP_ERR_FATAL; + int ret; + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n"); + goto fail; + } + + subreq = ipa_get_ad_override_send(state, state->ev, state->ctx, + state->ipa_ctx->ipa_options, + dp_opt_get_string(state->ipa_ctx->ipa_options->basic, + IPA_KRB5_REALM), + state->ipa_ctx->view_name, state->ar); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); + ret = ENOMEM; + goto fail; + } + + tevent_req_set_callback(subreq, ipa_subdomain_account_got_override, req); + + return; + +fail: + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; +} + +#define OVERRIDE_ANCHOR_SID_PREFIX ":SID:" +#define OVERRIDE_ANCHOR_SID_PREFIX_LEN (sizeof(OVERRIDE_ANCHOR_SID_PREFIX) -1 ) + +static void ipa_subdomain_account_got_override(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ipa_subdomain_account_state *state = tevent_req_data(req, + struct ipa_subdomain_account_state); + int dp_error = DP_ERR_FATAL; + int ret; + const char *anchor = NULL; + struct be_acct_req *ar; + + ret = ipa_get_ad_override_recv(subreq, &dp_error, state, + &state->override_attrs); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); + goto fail; + } + + if (state->override_attrs != NULL) { + ret = sysdb_attrs_get_string(state->override_attrs, + SYSDB_OVERRIDE_ANCHOR_UUID, + &anchor); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); + goto fail; + } + if (anchor != NULL && strncmp(OVERRIDE_ANCHOR_SID_PREFIX, anchor, + OVERRIDE_ANCHOR_SID_PREFIX_LEN) == 0) { + + ret = get_be_acct_req_for_sid(state, + anchor + OVERRIDE_ANCHOR_SID_PREFIX_LEN, + state->ar->domain, + &ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n"); + goto fail; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unsupported override anchor type [%s].\n", anchor); + ret = EINVAL; + goto fail; + } + } else { + ar = state->ar; + } + + ret = ipa_subdomain_account_get_original_step(req, ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "ipa_subdomain_account_get_original_step failed.\n"); + goto fail; + } + + return; + +fail: + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; +} + +static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req, + struct be_acct_req *ar) +{ + struct ipa_subdomain_account_state *state = tevent_req_data(req, + struct ipa_subdomain_account_state); + struct tevent_req *subreq; + + if (state->ipa_server_mode) { + subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx, + state->be_req, state->override_attrs, ar); + } else { + subreq = ipa_get_subdom_acct_send(state, state->ev, state->ipa_ctx, + state->override_attrs, ar); + } + + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct_send failed.\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, ipa_subdomain_account_done, req); + + return EOK; +} + + +static void ipa_subdomain_account_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ipa_subdomain_account_state *state = tevent_req_data(req, + struct ipa_subdomain_account_state); + int dp_error = DP_ERR_FATAL; + int ret; + + if (state->ipa_server_mode) { + ret = ipa_get_ad_acct_recv(subreq, &dp_error); + } else { + ret = ipa_get_subdom_acct_recv(subreq, &dp_error); + } + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: %d\n", ret); + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + + state->dp_error = DP_ERR_OK; + tevent_req_done(req); + return; +} + +errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out) +{ + struct ipa_subdomain_account_state *state = tevent_req_data(req, + struct ipa_subdomain_account_state); + + if (dp_error_out) { + *dp_error_out = state->dp_error; + } + + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + struct ipa_get_subdom_acct { struct tevent_context *ev; struct ipa_id_ctx *ipa_ctx; @@ -41,6 +316,7 @@ struct ipa_get_subdom_acct { struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; + struct sysdb_attrs *override_attrs; int entry_type; const char *filter; @@ -55,6 +331,7 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq); struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_id_ctx *ipa_ctx, + struct sysdb_attrs *override_attrs, struct be_acct_req *ar) { struct tevent_req *req; @@ -69,6 +346,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, state->ipa_ctx = ipa_ctx; state->ctx = ipa_ctx->sdap_id_ctx; state->dp_error = DP_ERR_FATAL; + state->override_attrs = override_attrs; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); if (!state->op) { @@ -189,6 +467,7 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) state->ipa_ctx, state->ctx->opts, state->domain, + state->override_attrs, sdap_id_op_handle(state->op), state->entry_type, req_input); @@ -260,11 +539,13 @@ struct ipa_get_ad_acct_state { struct be_acct_req *ar; struct sss_domain_info *user_dom; char *object_sid; + struct sysdb_attrs *override_attrs; struct ldb_message *obj_msg; }; static void ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq); static void ipa_get_ad_override_done(struct tevent_req *subreq); +static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req); 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); @@ -274,6 +555,7 @@ 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 sysdb_attrs *override_attrs, struct be_acct_req *ar) { errno_t ret; @@ -294,6 +576,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, state->be_req = be_req; state->ar = ar; state->obj_msg = NULL; + state->override_attrs = override_attrs; /* This can only be a subdomain request, verify subdomain */ state->user_dom = find_domain_by_name(ipa_ctx->sdap_id_ctx->be->domain, @@ -681,6 +964,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) struct ipa_get_ad_acct_state); errno_t ret; const char *sid; + struct be_acct_req *ar; ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL); talloc_zfree(subreq); @@ -706,32 +990,48 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) goto fail; } - sid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_SID_STR, NULL); - if (sid == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a SID.\n"); - ret = EINVAL; - goto fail; - } + if (state->override_attrs == NULL) { + sid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_SID_STR, NULL); + if (sid == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a SID.\n"); + ret = EINVAL; + goto fail; + } - state->object_sid = talloc_strdup(state, sid); - if (state->object_sid == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); - ret = ENOMEM; - goto fail; - } + state->object_sid = talloc_strdup(state, sid); + if (state->object_sid == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto fail; + } - subreq = ipa_get_ad_override_send(state, state->ev, - state->ipa_ctx->sdap_id_ctx, - state->ipa_ctx->ipa_options, - state->ipa_ctx->server_mode->realm, - state->ipa_ctx->view_name, - state->object_sid); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); - ret = ENOMEM; - goto fail; + ret = get_be_acct_req_for_sid(state, state->object_sid, + state->user_dom->name, &ar); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n"); + goto fail; + } + + subreq = ipa_get_ad_override_send(state, state->ev, + state->ipa_ctx->sdap_id_ctx, + state->ipa_ctx->ipa_options, + state->ipa_ctx->server_mode->realm, + state->ipa_ctx->view_name, + ar); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n"); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, ipa_get_ad_override_done, req); + } else { + ret = ipa_get_ad_apply_override_step(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "ipa_get_ad_apply_override_step failed.\n"); + goto fail; + } } - tevent_req_set_callback(subreq, ipa_get_ad_override_done, req); return; @@ -750,10 +1050,9 @@ ipa_get_ad_override_done(struct tevent_req *subreq) struct ipa_get_ad_acct_state *state = tevent_req_data(req, struct ipa_get_ad_acct_state); errno_t ret; - struct sysdb_attrs *override_attrs = NULL; ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state, - &override_attrs); + &state->override_attrs); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret); @@ -762,21 +1061,42 @@ ipa_get_ad_override_done(struct tevent_req *subreq) } - if (override_attrs != NULL) { + ret = ipa_get_ad_apply_override_step(req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_apply_override_step failed.\n"); + goto fail; + } + + return; + +fail: + state->dp_error = DP_ERR_FATAL; + tevent_req_error(req, ret); + return; +} + +static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) +{ + struct ipa_get_ad_acct_state *state = tevent_req_data(req, + struct ipa_get_ad_acct_state); + errno_t ret; + struct tevent_req *subreq; + + if (state->override_attrs != NULL) { /* We are in ipa-server-mode, so the view is the default view by * definition. */ ret = sysdb_apply_default_override(state->user_dom, - override_attrs, + state->override_attrs, state->obj_msg->dn); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_apply_default_override failed.\n"); - goto fail; + return ret; } } if ((state->ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS) { tevent_req_done(req); - return; + return EOK; } /* For initgroups request we have to check IPA group memberships of AD @@ -787,17 +1107,12 @@ ipa_get_ad_override_done(struct tevent_req *subreq) state->ipa_ctx->sdap_id_ctx, state->ipa_ctx->server_mode->realm); if (subreq == NULL) { - ret = ENOMEM; - goto fail; + DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_memberships_send failed.\n"); + return ENOMEM; } tevent_req_set_callback(subreq, ipa_get_ad_acct_done, req); - return; - -fail: - state->dp_error = DP_ERR_FATAL; - tevent_req_error(req, ret); - return; + return EOK; } static void diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c index 86b141110..33dbf7b1c 100644 --- a/src/providers/ipa/ipa_views.c +++ b/src/providers/ipa/ipa_views.c @@ -23,20 +23,163 @@ */ #include "util/util.h" +#include "util/strtonum.h" #include "providers/ldap/sdap_async.h" #include "providers/ipa/ipa_id.h" +static errno_t be_acct_req_to_override_filter(TALLOC_CTX *mem_ctx, + struct ipa_options *ipa_opts, + struct be_acct_req *ar, + char **override_filter) +{ + char *filter; + uint32_t id; + char *endptr; + + switch (ar->filter_type) { + case BE_FILTER_NAME: + switch ((ar->entry_type & BE_REQ_TYPE_MASK)) { + case BE_REQ_USER: + case BE_REQ_INITGROUPS: + filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))", + ipa_opts->override_map[IPA_OC_OVERRIDE_USER].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_USER_NAME].name, + ar->filter_value); + break; + + case BE_REQ_GROUP: + filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))", + ipa_opts->override_map[IPA_OC_OVERRIDE_GROUP].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_NAME].name, + ar->filter_value); + break; + + case BE_REQ_USER_AND_GROUP: + filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", + ipa_opts->override_map[IPA_OC_OVERRIDE].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_USER_NAME].name, + ar->filter_value, + ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_NAME].name, + ar->filter_value); + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d] for name filter.\n", + ar->entry_type); + return EINVAL; + } + break; + + case BE_FILTER_IDNUM: + errno = 0; + id = strtouint32(ar->filter_value, &endptr, 10); + if (errno != 0|| *endptr != '\0' || (ar->filter_value == endptr)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid id value [%s].\n", + ar->filter_value); + return EINVAL; + } + switch ((ar->entry_type & BE_REQ_TYPE_MASK)) { + case BE_REQ_USER: + case BE_REQ_INITGROUPS: + filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%"PRIu32"))", + ipa_opts->override_map[IPA_OC_OVERRIDE_USER].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_UID_NUMBER].name, + id); + break; + + case BE_REQ_GROUP: + filter = talloc_asprintf(mem_ctx, + "(&(objectClass=%s)(%s=%"PRIu32"))", + ipa_opts->override_map[IPA_OC_OVERRIDE_GROUP].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_GID_NUMBER].name, + id); + break; + + case BE_REQ_USER_AND_GROUP: + filter = talloc_asprintf(mem_ctx, + "(&(objectClass=%s)(|(%s=%"PRIu32")(%s=%"PRIu32")))", + ipa_opts->override_map[IPA_OC_OVERRIDE].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_UID_NUMBER].name, + id, + ipa_opts->override_map[IPA_AT_OVERRIDE_GROUP_GID_NUMBER].name, + id); + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected entry type [%d] for id filter.\n", + ar->entry_type); + return EINVAL; + } + break; + + case BE_FILTER_SECID: + if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_SECID) { + filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=:SID:%s))", + ipa_opts->override_map[IPA_OC_OVERRIDE].name, + ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name, + ar->filter_value); + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected entry type [%d] for SID filter.\n", + ar->entry_type); + return EINVAL; + } + break; + + default: + DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n"); + return EINVAL; + } + + if (filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + return ENOMEM; + } + + *override_filter = filter; + + return EOK; +} + +errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid, + const char *domain_name, + struct be_acct_req **_ar) +{ + struct be_acct_req *ar; + + ar = talloc_zero(mem_ctx, struct be_acct_req); + if (ar == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + return ENOMEM; + } + + ar->entry_type = BE_REQ_BY_SECID; + ar->filter_type = BE_FILTER_SECID; + ar->filter_value = talloc_strdup(ar, sid); + ar->domain = talloc_strdup(ar, domain_name); + if (ar->filter_value == NULL || ar->domain == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + talloc_free(ar); + return ENOMEM; + } + + + *_ar = ar; + + return EOK; +} + struct ipa_get_ad_override_state { struct tevent_context *ev; struct sdap_id_ctx *sdap_id_ctx; struct ipa_options *ipa_options; const char *ipa_realm; const char *ipa_view_name; - const char *obj_sid; + struct be_acct_req *ar; struct sdap_id_op *sdap_op; int dp_error; struct sysdb_attrs *override_attrs; + char *filter; }; static void ipa_get_ad_override_connect_done(struct tevent_req *subreq); @@ -48,7 +191,7 @@ struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx, struct ipa_options *ipa_options, const char *ipa_realm, const char *view_name, - const char *obj_sid) + struct be_acct_req *ar) { int ret; struct tevent_req *req; @@ -70,9 +213,10 @@ struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx, } else { state->ipa_view_name = view_name; } - state->obj_sid = obj_sid; + state->ar = ar; state->dp_error = -1; state->override_attrs = NULL; + state->filter = NULL; state->sdap_op = sdap_id_op_create(state, state->sdap_id_ctx->conn->conn_cache); @@ -115,7 +259,6 @@ static void ipa_get_ad_override_connect_done(struct tevent_req *subreq) int ret; char *basedn; char *search_base; - char *filter; struct ipa_options *ipa_opts = state->ipa_options; ret = sdap_id_op_connect_recv(subreq, &state->dp_error); @@ -147,24 +290,22 @@ static void ipa_get_ad_override_connect_done(struct tevent_req *subreq) goto fail; } - filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=:SID:%s))", - ipa_opts->override_map[IPA_OC_OVERRIDE].name, - ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name, - state->obj_sid); - if (filter == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); - ret = ENOMEM; + ret = be_acct_req_to_override_filter(state, state->ipa_options, state->ar, + &state->filter); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "be_acct_req_to_override_filter failed.\n"); goto fail; } DEBUG(SSSDBG_TRACE_ALL, - "Searching for overrides in view [%s] for object with SID [%s].\n", - state->ipa_view_name, state->obj_sid); + "Searching for overrides in view [%s] with filter [%s].\n", + state->ipa_view_name, state->filter); subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts, sdap_id_op_handle(state->sdap_op), search_base, LDAP_SCOPE_SUBTREE, - filter, NULL, state->ipa_options->override_map, + state->filter, NULL, + state->ipa_options->override_map, IPA_OPTS_OVERRIDE, dp_opt_get_int(state->sdap_id_ctx->opts->basic, SDAP_ENUM_SEARCH_TIMEOUT), @@ -202,21 +343,21 @@ static void ipa_get_ad_override_done(struct tevent_req *subreq) } if (reply_count == 0) { - DEBUG(SSSDBG_TRACE_ALL, "No override found for SID [%s].\n", - state->obj_sid); + DEBUG(SSSDBG_TRACE_ALL, "No override found with filter [%s].\n", + state->filter); state->dp_error = DP_ERR_OK; tevent_req_done(req); return; } else if (reply_count > 1) { DEBUG(SSSDBG_CRIT_FAILURE, - "Found [%zu] overrides for SID [%s], expected only 1.\n", - reply_count, state->obj_sid); + "Found [%zu] overrides with filter [%s], expected only 1.\n", + reply_count, state->filter); ret = EINVAL; goto fail; } - DEBUG(SSSDBG_TRACE_ALL, "Found override for object with SID [%s].\n", - state->obj_sid); + DEBUG(SSSDBG_TRACE_ALL, "Found override for object with filter [%s].\n", + state->filter); state->override_attrs = reply[0]; state->dp_error = DP_ERR_OK; |