summaryrefslogtreecommitdiffstats
path: root/src/providers/ipa/ipa_subdomains_id.c
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 /src/providers/ipa/ipa_subdomains_id.c
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>
Diffstat (limited to 'src/providers/ipa/ipa_subdomains_id.c')
-rw-r--r--src/providers/ipa/ipa_subdomains_id.c258
1 files changed, 215 insertions, 43 deletions
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);