diff options
-rw-r--r-- | src/providers/ipa/ipa_s2n_exop.c | 362 | ||||
-rw-r--r-- | src/providers/ipa/ipa_subdomains_id.c | 258 | ||||
-rw-r--r-- | src/providers/ipa/ipa_views.c | 4 |
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); |