errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, struct ldb_result **res) { int ret; struct ldb_result *orig_obj = NULL; struct ldb_result *override_obj = NULL; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); return ENOMEM; } /* If there are views we first have to search the overrides for matches */ if (DOM_HAS_VIEWS(domain)) { ret = sysdb_search_user_override_by_name(tmp_ctx, domain, name, &override_obj, &orig_obj); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_override_by_name failed.\n"); goto done; } } /* If there are no views or nothing was found in the overrides the * original objects are searched. */ if (orig_obj == NULL) { ret = sysdb_getpwnam(tmp_ctx, domain, name, &orig_obj); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwnam failed.\n"); goto done; } } /* If there are views we have to check if override values must be added to * the original object. */ if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], override_obj == NULL ? NULL : override_obj->msgs[0], NULL); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); goto done; } if (ret == ENOENT) { *res = talloc_zero(mem_ctx, struct ldb_result); if (*res == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); ret = ENOMEM; } else { ret = EOK; } goto done; }
static errno_t cache_req_group_by_name_dpreq_params(TALLOC_CTX *mem_ctx, struct cache_req *cr, struct ldb_result *result, const char **_string, uint32_t *_id, const char **_flag) { const char *name; *_id = 0; *_string = cr->data->name.lookup; *_flag = NULL; if (!DOM_HAS_VIEWS(cr->domain)) { return EOK; } /* We must search with views. */ if (result == NULL || result->count == 0) { *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; return EOK; } /* If domain has views we will try to use original values instead of the * overridden ones. This is a must for the LOCAL view since we can't look * it up otherwise. But it is also a shortcut for non-local views where * we will not fail over to the overridden value. */ name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); if (name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; return EOK; } /* Now we have the original name and id. We don't have to search with * views unless some error occurred. */ *_string = talloc_steal(mem_ctx, name); return EOK; }
static uint32_t nss_get_gid(struct sss_domain_info *domain, struct ldb_message *msg) { uint32_t gid; /* First, try to return overriden gid. */ if (DOM_HAS_VIEWS(domain)) { gid = ldb_msg_find_attr_as_uint64(msg, OVERRIDE_PREFIX SYSDB_GIDNUM, 0); if (gid != 0) { return gid; } } /* Try to return domain gid override. */ if (domain->override_gid != 0) { return domain->override_gid; } /* Return original gid. */ return ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0); }
static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) { TALLOC_CTX *tmp_ctx = NULL; struct sss_domain_info *dom = dctx->domain; struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx; struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx; struct ldb_result *user; time_t cache_expire = 0; struct tevent_req *dpreq; struct dp_callback_ctx *cb_ctx; const char *original_name = NULL; const char *extra_flag = NULL; char *name = NULL; uid_t uid = 0; errno_t ret; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); return ENOMEM; } while (dom) { /* if it is a domainless search, skip domains that require fully * qualified names instead */ while (dom && cmd_ctx->check_next && dom->fqnames) { dom = get_next_domain(dom, false); } if (!dom) break; /* make sure to update the dctx if we changed domain */ dctx->domain = dom; talloc_free(name); name = sss_get_cased_name(tmp_ctx, cmd_ctx->username, dom->case_sensitive); if (name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); ret = ENOMEM; goto done; } name = sss_reverse_replace_space(tmp_ctx, name, cmd_ctx->sudo_ctx->rctx->override_space); if (name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_reverse_replace_whitespaces failed\n"); return ENOMEM; } DEBUG(SSSDBG_FUNC_DATA, "Requesting info about [%s@%s]\n", name, dom->name); ret = sysdb_getpwnam_with_views(dctx, dctx->domain, name, &user); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to make request to our cache!\n"); ret = EIO; goto done; } if (user->count > 1) { DEBUG(SSSDBG_CRIT_FAILURE, "getpwnam call returned more than one result !?!\n"); ret = EIO; goto done; } if (user->count == 0 && !dctx->check_provider) { /* if a multidomain search, try with next */ if (cmd_ctx->check_next) { dctx->check_provider = true; dom = get_next_domain(dom, false); if (dom) continue; } DEBUG(SSSDBG_MINOR_FAILURE, "No results for getpwnam call\n"); ret = ENOENT; goto done; } /* One result found, check cache expiry */ if (user->count == 1) { cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0], SYSDB_CACHE_EXPIRE, 0); } /* If cache miss and we haven't checked DP yet OR the entry is * outdated, go to DP */ if ((user->count == 0 || cache_expire < time(NULL)) && dctx->check_provider) { if (DOM_HAS_VIEWS(dom) && user->count == 0) { extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; } dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx, dom, false, SSS_DP_INITGROUPS, cmd_ctx->username, 0, extra_flag); if (!dpreq) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending data provider request\n"); ret = ENOMEM; goto done; } cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx); if(!cb_ctx) { talloc_zfree(dpreq); ret = ENOMEM; goto done; } cb_ctx->callback = sudosrv_check_user_dp_callback; cb_ctx->ptr = dctx; cb_ctx->cctx = cli_ctx; cb_ctx->mem_ctx = cli_ctx; tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx); /* tell caller we are in an async call */ ret = EAGAIN; goto done; } /* check uid */ uid = sss_view_ldb_msg_find_attr_as_uint64(dom, user->msgs[0], SYSDB_UIDNUM, 0); if (uid != cmd_ctx->uid) { /* if a multidomain search, try with next */ if (cmd_ctx->check_next) { dctx->check_provider = true; dom = get_next_domain(dom, false); if (dom) continue; } DEBUG(SSSDBG_MINOR_FAILURE, "UID does not match\n"); ret = ENOENT; goto done; } /* user is stored in cache, remember cased and original name */ original_name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME, NULL); if (original_name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n"); ret = EFAULT; goto done; } cmd_ctx->cased_username = talloc_move(cmd_ctx, &name); cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name); if (cmd_ctx->orig_username == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); ret = ENOMEM; goto done; } /* and set domain */ cmd_ctx->domain = dom; DEBUG(SSSDBG_TRACE_FUNC, "Returning info for user [%s@%s]\n", cmd_ctx->username, dctx->domain->name); ret = EOK; goto done; } ret = ENOENT; done: talloc_free(tmp_ctx); return ret; }