summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2014-09-23 13:13:37 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-10-16 17:56:14 +0200
commit9c8db0a17a66c58c36966b17d004142a4aaace8d (patch)
tree3ff36aa7a42a65c6fc4e35e7039294836e8208d6
parent9da27cbc7532f775afc411d809735760dd5294a7 (diff)
downloadsssd-9c8db0a17a66c58c36966b17d004142a4aaace8d.tar.gz
sssd-9c8db0a17a66c58c36966b17d004142a4aaace8d.tar.xz
sssd-9c8db0a17a66c58c36966b17d004142a4aaace8d.zip
views: get overrides during user and group lookups
With this patch the IPA provider will check if overrides exists for the given view during the lookup of users and groups from trusted domains. In ipa-server-mode the default view is automatically applied and written to the cache. On IPA clients which use the extdom plugin for user and group lookups the override data is saved separately and the original object and the override data are linked with DN attributes for faster reference. Related to https://fedorahosted.org/sssd/ticket/2375 Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-rw-r--r--src/providers/ipa/ipa_s2n_exop.c362
-rw-r--r--src/providers/ipa/ipa_subdomains_id.c258
-rw-r--r--src/providers/ipa/ipa_views.c4
3 files changed, 522 insertions, 102 deletions
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 6f5fac337..1ee9c238b 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -674,7 +674,9 @@ done:
static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
struct req_input *req_input,
struct resp_attrs *attrs,
- struct resp_attrs *simple_attrs);
+ struct resp_attrs *simple_attrs,
+ const char *view_name,
+ struct sysdb_attrs *override_attrs);
static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
char *retoid,
@@ -881,9 +883,11 @@ struct ipa_s2n_get_groups_state {
char **group_list;
size_t group_idx;
int exop_timeout;
+ struct resp_attrs *attrs;
};
static errno_t ipa_s2n_get_groups_step(struct tevent_req *req);
+static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq);
static void ipa_s2n_get_groups_next(struct tevent_req *subreq);
static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
@@ -912,6 +916,7 @@ static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
state->req_input.type = REQ_INP_NAME;
state->req_input.inp.name = NULL;
state->exop_timeout = exop_timeout;
+ state->attrs = NULL;
ret = ipa_s2n_get_groups_step(req);
if (ret != EOK) {
@@ -988,7 +993,7 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
struct ipa_s2n_get_groups_state);
char *retoid = NULL;
struct berval *retdata = NULL;
- struct resp_attrs *attrs;
+ const char *sid_str;
ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata);
talloc_zfree(subreq);
@@ -997,13 +1002,59 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
goto fail;
}
- ret = s2n_response_to_attrs(state, retoid, retdata, &attrs);
+ talloc_zfree(state->attrs);
+ ret = s2n_response_to_attrs(state, retoid, retdata, &state->attrs);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "s2n_response_to_attrs failed.\n");
goto fail;
}
- ret = ipa_s2n_save_objects(state->dom, &state->req_input, attrs, NULL);
+ ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
+ &sid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string 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);
+ 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_groups_get_override_done, req);
+
+ return;
+
+fail:
+ tevent_req_error(req,ret);
+ return;
+}
+
+static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq)
+{
+ int ret;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
+ struct ipa_s2n_get_groups_state);
+ struct sysdb_attrs *override_attrs = NULL;
+
+ ret = ipa_get_ad_override_recv(subreq, NULL, state, &override_attrs);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
+ goto fail;
+ }
+
+ ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
+ NULL, state->ipa_ctx->view_name, override_attrs);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
goto fail;
@@ -1046,6 +1097,7 @@ 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;
int exop_timeout;
};
@@ -1273,6 +1325,7 @@ done:
}
static void ipa_s2n_get_groups_done(struct tevent_req *subreq);
+static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq);
static void ipa_s2n_get_user_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -1286,6 +1339,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
struct berval *bv_req = NULL;
char **missing_groups = NULL;
struct ldb_dn **group_dn_list = NULL;
+ const char *sid_str;
ret = ipa_s2n_exop_recv(subreq, state, &retoid, &retdata);
talloc_zfree(subreq);
@@ -1392,10 +1446,44 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
goto done;
}
- ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
- state->simple_attrs);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
+ if (state->simple_attrs != NULL
+ && state->simple_attrs->response_type == RESP_SID) {
+ sid_str = state->simple_attrs->a.sid_str;
+ ret = EOK;
+ } else if (state->attrs->sysdb_attrs != NULL) {
+ ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
+ &sid_str);
+ } else {
+ DEBUG(SSSDBG_TRACE_FUNC, "No SID available.\n");
+ ret = ENOENT;
+ }
+
+ if (ret == ENOENT) {
+ ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
+ state->simple_attrs, NULL, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
+ goto done;
+ }
+ } else if (ret == EOK) {
+ 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 done;
+ }
+ tevent_req_set_callback(subreq, ipa_s2n_get_user_get_override_done,
+ req);
+
+ return;
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
goto done;
}
@@ -1411,17 +1499,23 @@ done:
static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
struct req_input *req_input,
struct resp_attrs *attrs,
- struct resp_attrs *simple_attrs)
+ struct resp_attrs *simple_attrs,
+ const char *view_name,
+ struct sysdb_attrs *override_attrs)
{
int ret;
time_t now;
uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */
struct sss_nss_homedir_ctx homedir_ctx;
- char *name;
+ char *name = NULL;
char *realm;
- char *upn;
+ char *upn = NULL;
gid_t gid;
TALLOC_CTX *tmp_ctx;
+ const char *sid_str;
+ const char *tmp_str;
+ struct ldb_result *res;
+ enum sysdb_member_type type;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
@@ -1440,9 +1534,59 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
}
}
+ if (attrs->sysdb_attrs != NULL) {
+ ret = sysdb_attrs_get_string(attrs->sysdb_attrs,
+ ORIGINALAD_PREFIX SYSDB_NAME, &tmp_str);
+ if (ret == EOK) {
+ name = talloc_strdup(tmp_ctx, tmp_str);
+ if (name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_ALL, "Found original AD name [%s].\n", name);
+ } else if (ret == ENOENT) {
+ name = NULL;
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+ goto done;
+ }
+
+ ret = sysdb_attrs_get_string(attrs->sysdb_attrs,
+ SYSDB_DEFAULT_OVERRIDE_NAME, &tmp_str);
+ if (ret == EOK) {
+ ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, tmp_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sysdb_attrs_add_lc_name_alias failed.\n");
+ goto done;
+ }
+ } else if (ret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+ goto done;
+ }
+
+ ret = sysdb_attrs_get_string(attrs->sysdb_attrs, SYSDB_UPN, &tmp_str);
+ if (ret == EOK) {
+ upn = talloc_strdup(tmp_ctx, tmp_str);
+ if (upn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_ALL, "Found original AD upn [%s].\n", upn);
+ } else if (ret == ENOENT) {
+ upn = NULL;
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+ goto done;
+ }
+ }
+
switch (attrs->response_type) {
case RESP_USER:
case RESP_USER_GROUPLIST:
+ type = SYSDB_MEMBER_USER;
if (dom->subdomain_homedir
&& attrs->a.user.pw_dir == NULL) {
ZERO_STRUCT(homedir_ctx);
@@ -1461,13 +1605,15 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
}
}
- /* we always use the fully qualified name for subdomain users */
- name = sss_tc_fqname(tmp_ctx, dom->names, dom,
- attrs->a.user.pw_name);
- if (!name) {
- DEBUG(SSSDBG_OP_FAILURE, "failed to format user name.\n");
- ret = ENOMEM;
- goto done;
+ if (name == NULL) {
+ /* we always use the fully qualified name for subdomain users */
+ name = sss_tc_fqname(tmp_ctx, dom->names, dom,
+ attrs->a.user.pw_name);
+ if (!name) {
+ DEBUG(SSSDBG_OP_FAILURE, "failed to format user name.\n");
+ ret = ENOMEM;
+ goto done;
+ }
}
ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, name);
@@ -1477,35 +1623,43 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
goto done;
}
- /* We also have to store a fake UPN here, because otherwise the
- * krb5 child later won't be able to properly construct one as
- * the username is fully qualified but the child doesn't have
- * access to the regex to deconstruct it */
- /* FIXME: The real UPN is available from the PAC, we should get
- * it from there. */
- realm = get_uppercase_realm(tmp_ctx, dom->name);
- if (!realm) {
- DEBUG(SSSDBG_OP_FAILURE, "failed to get realm.\n");
- ret = ENOMEM;
- goto done;
- }
- upn = talloc_asprintf(tmp_ctx, "%s@%s",
- attrs->a.user.pw_name, realm);
- if (!upn) {
- DEBUG(SSSDBG_OP_FAILURE, "failed to format UPN.\n");
- ret = ENOMEM;
- goto done;
- }
+ if (upn == NULL) {
+ /* We also have to store a fake UPN here, because otherwise the
+ * krb5 child later won't be able to properly construct one as
+ * the username is fully qualified but the child doesn't have
+ * access to the regex to deconstruct it */
+ /* FIXME: The real UPN is available from the PAC, we should get
+ * it from there. */
+ realm = get_uppercase_realm(tmp_ctx, dom->name);
+ if (!realm) {
+ DEBUG(SSSDBG_OP_FAILURE, "failed to get realm.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ upn = talloc_asprintf(tmp_ctx, "%s@%s",
+ attrs->a.user.pw_name, realm);
+ if (!upn) {
+ DEBUG(SSSDBG_OP_FAILURE, "failed to format UPN.\n");
+ ret = ENOMEM;
+ goto done;
+ }
- ret = sysdb_attrs_add_string(attrs->sysdb_attrs, SYSDB_UPN, upn);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
- goto done;
+ /* We might already have the SID or the UPN from other sources
+ * hence sysdb_attrs_add_string_safe is used to avoid double
+ * entries. */
+ ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs, SYSDB_UPN,
+ upn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sysdb_attrs_add_string failed.\n");
+ goto done;
+ }
}
if (req_input->type == REQ_INP_SECID) {
- ret = sysdb_attrs_add_string(attrs->sysdb_attrs, SYSDB_SID_STR,
- req_input->inp.secid);
+ ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
+ SYSDB_SID_STR,
+ req_input->inp.secid);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_string failed.\n");
@@ -1515,8 +1669,9 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
if (simple_attrs != NULL
&& simple_attrs->response_type == RESP_SID) {
- ret = sysdb_attrs_add_string(attrs->sysdb_attrs, SYSDB_SID_STR,
- simple_attrs->a.sid_str);
+ ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
+ SYSDB_SID_STR,
+ simple_attrs->a.sid_str);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_string failed.\n");
@@ -1535,16 +1690,24 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
attrs->a.user.pw_dir, attrs->a.user.pw_shell,
NULL, attrs->sysdb_attrs, NULL,
timeout, now);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n");
+ goto done;
+ }
break;
case RESP_GROUP:
case RESP_GROUP_MEMBERS:
- /* we always use the fully qualified name for subdomain users */
- name = sss_tc_fqname(tmp_ctx, dom->names, dom,
- attrs->a.group.gr_name);
- if (!name) {
- DEBUG(SSSDBG_OP_FAILURE, "failed to format user name,\n");
- ret = ENOMEM;
- goto done;
+ type = SYSDB_MEMBER_GROUP;
+
+ if (name == NULL) {
+ /* we always use the fully qualified name for subdomain users */
+ name = sss_tc_fqname(tmp_ctx, dom->names, dom,
+ attrs->a.group.gr_name);
+ if (!name) {
+ DEBUG(SSSDBG_OP_FAILURE, "failed to format user name,\n");
+ ret = ENOMEM;
+ goto done;
+ }
}
ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, name);
@@ -1554,9 +1717,12 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
goto done;
}
+ /* We might already have the SID from other sources hence
+ * sysdb_attrs_add_string_safe is used to avoid double entries. */
if (req_input->type == REQ_INP_SECID) {
- ret = sysdb_attrs_add_string(attrs->sysdb_attrs, SYSDB_SID_STR,
- req_input->inp.secid);
+ ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
+ SYSDB_SID_STR,
+ req_input->inp.secid);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_string failed.\n");
@@ -1566,8 +1732,9 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
if (simple_attrs != NULL
&& simple_attrs->response_type == RESP_SID) {
- ret = sysdb_attrs_add_string(attrs->sysdb_attrs, SYSDB_SID_STR,
- simple_attrs->a.sid_str);
+ ret = sysdb_attrs_add_string_safe(attrs->sysdb_attrs,
+ SYSDB_SID_STR,
+ simple_attrs->a.sid_str);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"sysdb_attrs_add_string failed.\n");
@@ -1584,6 +1751,10 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
ret = sysdb_store_group(dom, name, attrs->a.group.gr_gid,
attrs->sysdb_attrs, timeout, now);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_group failed.\n");
+ goto done;
+ }
break;
default:
DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n",
@@ -1592,6 +1763,27 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
goto done;
}
+ ret = sysdb_attrs_get_string(attrs->sysdb_attrs, SYSDB_SID_STR, &sid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Cannot find SID of object with override.\n");
+ goto done;
+ }
+
+ ret = sysdb_search_object_by_sid(tmp_ctx, dom, sid_str, NULL, &res);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Cannot find object with override with SID [%s].\n", sid_str);
+ goto done;
+ }
+
+ ret = sysdb_store_override(dom, view_name, type, override_attrs,
+ res->msgs[0]->dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
+ goto done;
+ }
+
done:
talloc_free(tmp_ctx);
@@ -1605,6 +1797,7 @@ static void ipa_s2n_get_groups_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_s2n_get_user_state *state = tevent_req_data(req,
struct ipa_s2n_get_user_state);
+ const char *sid_str;
ret = ipa_s2n_get_groups_recv(subreq);
talloc_zfree(subreq);
@@ -1614,8 +1807,63 @@ static void ipa_s2n_get_groups_done(struct tevent_req *subreq)
return;
}
+ ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
+ &sid_str);
+ if (ret == ENOENT) {
+ ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
+ state->simple_attrs, NULL, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
+ goto fail;
+ }
+ tevent_req_done(req);
+ return;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string 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);
+ 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);
+
+ return;
+
+fail:
+ tevent_req_error(req, ret);
+ return;
+}
+
+static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq)
+{
+ int ret;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct ipa_s2n_get_user_state *state = tevent_req_data(req,
+ struct ipa_s2n_get_user_state);
+ struct sysdb_attrs *override_attrs = NULL;
+
+ ret = ipa_get_ad_override_recv(subreq, NULL, state, &override_attrs);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
+ tevent_req_error(req, ret);
+ return;
+ }
+
ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
- state->simple_attrs);
+ state->simple_attrs, state->ipa_ctx->view_name,
+ override_attrs);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
tevent_req_error(req, ret);
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index d1bd08d6e..f6cc92e3d 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -259,9 +259,12 @@ struct ipa_get_ad_acct_state {
struct be_req *be_req;
struct be_acct_req *ar;
struct sss_domain_info *user_dom;
+ char *object_sid;
+ 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 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);
@@ -290,6 +293,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
state->ipa_ctx = ipa_ctx;
state->be_req = be_req;
state->ar = ar;
+ state->obj_msg = NULL;
/* This can only be a subdomain request, verify subdomain */
state->user_dom = find_domain_by_name(ipa_ctx->sdap_id_ctx->be->domain,
@@ -491,67 +495,50 @@ done:
static errno_t
apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
- int filter_type, const char *filter_value)
+ struct ldb_message *msg)
{
errno_t ret;
uint32_t uid;
const char *fqname;
const char *homedir = NULL;
- struct ldb_result *res = NULL;
- struct ldb_message *msg = NULL;
- const char *attrs[] = { SYSDB_NAME,
- SYSDB_UIDNUM,
- NULL };
+ struct ldb_message_element *msg_el = NULL;
+ size_t c;
- if (filter_type == BE_FILTER_NAME) {
- ret = sysdb_getpwnam(mem_ctx, dom, filter_value, &res);
- if (res && res->count == 0) {
- ret = ENOENT;
- }
- } else if (filter_type == BE_FILTER_IDNUM) {
- errno = 0;
- uid = strtouint32(filter_value, NULL, 10);
- if (errno != 0) {
- ret = errno;
- goto done;
- }
- ret = sysdb_getpwuid(mem_ctx, dom, uid, &res);
- if (res && res->count == 0) {
- ret = ENOENT;
- }
- } else if (filter_type == BE_FILTER_SECID) {
- ret = sysdb_search_user_by_sid_str(mem_ctx, dom, filter_value,
- attrs, &msg);
- } else {
- DEBUG(SSSDBG_OP_FAILURE,
- "Unsupported filter type: [%d].\n", filter_type);
- ret = EINVAL;
+ msg_el = ldb_msg_find_element(msg, SYSDB_OBJECTCLASS);
+ if (msg_el == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_find_element failed.\n");
+ ret = ENOENT;
goto done;
}
- if (ret != EOK && ret != ENOENT) {
- DEBUG(SSSDBG_OP_FAILURE,
- "Failed to make request to our cache: [%d]: [%s]\n",
- ret, sss_strerror(ret));
- goto done;
- } else if (ret == ENOENT) {
- DEBUG(SSSDBG_TRACE_FUNC, "Cannot find [%s] with search type [%d]\n",
- filter_value, filter_type);
+ for (c = 0; c < msg_el->num_values; c++) {
+ if (strncmp(SYSDB_USER_CLASS, (const char *)msg_el->values[c].data,
+ msg_el->values[c].length) == 0) {
+ break;
+ }
+ }
+ if (c == msg_el->num_values) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "User objectclass not found, object is not a user.\n");
+ ret = ENOENT;
goto done;
}
- if (res != NULL) {
- msg = res->msgs[0];
- }
/*
* Homedir is always overriden by subdomain_homedir even if it was
* explicitly set by user.
*/
fqname = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ if (fqname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing user name.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
if (uid == 0) {
DEBUG(SSSDBG_OP_FAILURE, "UID for user [%s] is not known.\n",
- filter_value);
+ fqname);
ret = ENOENT;
goto done;
}
@@ -576,6 +563,115 @@ done:
return ret;
}
+static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ struct be_acct_req *ar,
+ struct ldb_message **_msg)
+{
+ errno_t ret;
+ uint32_t id;
+ struct ldb_message *msg = NULL;
+ struct ldb_result *res = NULL;
+ const char *attrs[] = { SYSDB_NAME,
+ SYSDB_UIDNUM,
+ SYSDB_SID_STR,
+ SYSDB_OBJECTCLASS,
+ NULL };
+ char *name;
+
+ if (ar->filter_type == BE_FILTER_SECID) {
+ ret = sysdb_search_object_by_sid(mem_ctx, dom, ar->filter_value, attrs,
+ &res);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to make request to our cache: [%d]: [%s]\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ *_msg = res->msgs[0];
+
+ ret = EOK;
+ goto done;
+ }
+
+ if (ar->filter_type == BE_FILTER_IDNUM) {
+ errno = 0;
+ id = strtouint32(ar->filter_value, NULL, 10);
+ if (errno != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_OP_FAILURE, "strtouint32 failed.\n");
+ goto done;
+ }
+
+ switch (ar->entry_type & BE_REQ_TYPE_MASK) {
+ case BE_REQ_GROUP:
+ ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg);
+ break;
+ case BE_REQ_INITGROUPS:
+ case BE_REQ_USER:
+ case BE_REQ_USER_AND_GROUP:
+ ret = sysdb_search_user_by_uid(mem_ctx, dom, id, attrs, &msg);
+ if (ret == ENOENT && (ar->entry_type & BE_REQ_TYPE_MASK)
+ == BE_REQ_USER_AND_GROUP) {
+ ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg);
+ }
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d].\n",
+ (ar->entry_type & BE_REQ_TYPE_MASK));
+ ret = EINVAL;
+ goto done;
+ }
+ } else if (ar->filter_type == BE_FILTER_NAME) {
+ name = sss_get_domain_name(mem_ctx, ar->filter_value, dom);
+ if (name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_name failed\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ switch (ar->entry_type & BE_REQ_TYPE_MASK) {
+ case BE_REQ_GROUP:
+ ret = sysdb_search_group_by_name(mem_ctx, dom, name, attrs, &msg);
+ break;
+ case BE_REQ_INITGROUPS:
+ case BE_REQ_USER:
+ case BE_REQ_USER_AND_GROUP:
+ ret = sysdb_search_user_by_name(mem_ctx, dom, name, attrs, &msg);
+ if (ret == ENOENT && (ar->entry_type & BE_REQ_TYPE_MASK)
+ == BE_REQ_USER_AND_GROUP) {
+ ret = sysdb_search_group_by_name(mem_ctx, dom, name,
+ attrs, &msg);
+ }
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type [%d].\n",
+ (ar->entry_type & BE_REQ_TYPE_MASK));
+ ret = EINVAL;
+ goto done;
+ }
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected filter type.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to make request to our cache: [%d]: [%s]\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ *_msg = msg;
+
+ ret = EOK;
+
+done:
+ return ret;
+}
+
static void
ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
{
@@ -584,6 +680,7 @@ ipa_get_ad_acct_ad_part_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;
+ const char *sid;
ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
talloc_zfree(subreq);
@@ -593,9 +690,15 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
return;
}
+ ret = get_object_from_cache(state, state->user_dom, state->ar,
+ &state->obj_msg);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
+ goto fail;
+ }
+
ret = apply_subdomain_homedir(state, state->user_dom,
- state->ar->filter_type,
- state->ar->filter_value);
+ state->obj_msg);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
"apply_subdomain_homedir failed: [%d]: [%s].\n",
@@ -603,6 +706,74 @@ 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;
+ }
+
+ 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;
+ }
+ tevent_req_set_callback(subreq, ipa_get_ad_override_done, req);
+
+ return;
+
+fail:
+ state->dp_error = DP_ERR_FATAL;
+ tevent_req_error(req, ret);
+ return;
+}
+
+
+static void
+ipa_get_ad_override_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct ipa_get_ad_acct_state *state = tevent_req_data(req,
+ struct ipa_get_ad_acct_state);
+ errno_t ret;
+ struct sysdb_attrs *override_attrs = NULL;
+
+ ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state,
+ &override_attrs);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
+ tevent_req_error(req, ret);
+ return;
+
+ }
+
+ if (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->obj_msg->dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_apply_default_override failed.\n");
+ goto fail;
+ }
+ }
+
if ((state->ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS) {
tevent_req_done(req);
return;
@@ -645,6 +816,7 @@ ipa_get_ad_acct_done(struct tevent_req *subreq)
ret);
tevent_req_error(req, ret);
return;
+
}
tevent_req_done(req);
diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
index 0b71ffc12..86b141110 100644
--- a/src/providers/ipa/ipa_views.c
+++ b/src/providers/ipa/ipa_views.c
@@ -191,8 +191,8 @@ static void ipa_get_ad_override_done(struct tevent_req *subreq)
struct ipa_get_ad_override_state *state = tevent_req_data(req,
struct ipa_get_ad_override_state);
int ret;
- size_t reply_count;
- struct sysdb_attrs **reply;
+ size_t reply_count = 0;
+ struct sysdb_attrs **reply = NULL;
ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
talloc_zfree(subreq);