diff options
-rw-r--r-- | src/providers/data_provider.h | 1 | ||||
-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 |
6 files changed, 602 insertions, 101 deletions
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index ec5b79d83..e1cb4befa 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -148,6 +148,7 @@ #define DP_SEC_ID_LEN (sizeof(DP_SEC_ID) - 1) #define EXTRA_NAME_IS_UPN "U" +#define EXTRA_INPUT_MAYBE_WITH_VIEW "V" /* AUTH related common data and functions */ 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; |