summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/providers/ipa/ipa_id.c18
-rw-r--r--src/providers/ipa/ipa_id.h31
-rw-r--r--src/providers/ipa/ipa_s2n_exop.c83
-rw-r--r--src/providers/ipa/ipa_subdomains_id.c389
-rw-r--r--src/providers/ipa/ipa_views.c181
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;