static errno_t cache_req_user_by_name_ncache_add(struct sss_nc_ctx *ncache, struct sss_domain_info *domain, struct cache_req_data *data) { return sss_ncache_set_user(ncache, false, domain, data->name.lookup); }
static int set_user_in_ncache(struct sss_nc_ctx *ctx, bool permanent, struct sss_domain_info *dom, const char *name) { char *fqdn; int ret; fqdn = sss_create_internal_fqname(ctx, name, dom->name); ret = sss_ncache_set_user(ctx, permanent, dom, fqdn); talloc_free(fqdn); return ret; }
static int pam_check_user_search(struct pam_auth_req *preq) { struct sss_domain_info *dom = preq->domain; char *name = NULL; time_t cacheExpire; int ret; struct tevent_req *dpreq; struct dp_callback_ctx *cb_ctx; struct pam_ctx *pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); while (dom) { /* if it is a domainless search, skip domains that require fully * qualified names instead */ while (dom && !preq->pd->domain && dom->fqnames) { dom = get_next_domain(dom, false); } if (!dom) break; if (dom != preq->domain) { /* make sure we reset the check_provider flag when we check * a new domain */ preq->check_provider = NEED_CHECK_PROVIDER(dom->provider); } /* make sure to update the preq if we changed domain */ preq->domain = dom; talloc_free(name); name = sss_get_cased_name(preq, preq->pd->user, dom->case_sensitive); if (!name) { return ENOMEM; } name = sss_reverse_replace_space(preq, name, pctx->rctx->override_space); if (name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_reverse_replace_space failed\n"); return ENOMEM; } /* Refresh the user's cache entry on any PAM query * We put a timeout in the client context so that we limit * the number of updates within a reasonable timeout */ if (preq->check_provider) { ret = pam_initgr_check_timeout(pctx->id_table, name); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, "Could not look up initgroup timout\n"); return EIO; } else if (ret == ENOENT) { /* Call provider first */ break; } /* Entry is still valid, get it from the sysdb */ } DEBUG(SSSDBG_CONF_SETTINGS, "Requesting info for [%s@%s]\n", name, dom->name); if (dom->sysdb == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Fatal: Sysdb CTX not found for this domain!\n"); preq->pd->pam_status = PAM_SYSTEM_ERR; return EFAULT; } ret = sysdb_getpwnam(preq, dom, name, &preq->res); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n"); return EIO; } if (preq->res->count > 1) { DEBUG(SSSDBG_FATAL_FAILURE, "getpwnam call returned more than one result !?!\n"); return ENOENT; } if (preq->res->count == 0) { if (preq->check_provider == false) { /* set negative cache only if not result of cache check */ ret = sss_ncache_set_user(pctx->ncache, false, dom, name); if (ret != EOK) { /* Should not be fatal, just slower next time */ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set ncache for [%s@%s]\n", name, dom->name); } } /* if a multidomain search, try with next */ if (!preq->pd->domain) { dom = get_next_domain(dom, false); continue; } DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n"); /* TODO: store negative cache ? */ return ENOENT; } /* One result found */ /* if we need to check the remote account go on */ if (preq->check_provider) { cacheExpire = ldb_msg_find_attr_as_uint64(preq->res->msgs[0], SYSDB_CACHE_EXPIRE, 0); if (cacheExpire < time(NULL)) { break; } } DEBUG(SSSDBG_TRACE_FUNC, "Returning info for user [%s@%s]\n", name, dom->name); /* We might have searched by alias. Pass on the primary name */ ret = pd_set_primary_name(preq->res->msgs[0], preq->pd); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not canonicalize username\n"); return ret; } return EOK; } if (!dom) { /* Ensure that we don't try to check a provider without a domain, * since this will cause a NULL-dereference below. */ preq->check_provider = false; } if (preq->check_provider) { /* dont loop forever :-) */ preq->check_provider = false; dpreq = sss_dp_get_account_send(preq, preq->cctx->rctx, dom, false, SSS_DP_INITGROUPS, name, 0, NULL); if (!dpreq) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending data provider request\n"); return ENOMEM; } cb_ctx = talloc_zero(preq, struct dp_callback_ctx); if(!cb_ctx) { talloc_zfree(dpreq); return ENOMEM; } cb_ctx->callback = pam_check_user_dp_callback; cb_ctx->ptr = preq; cb_ctx->cctx = preq->cctx; cb_ctx->mem_ctx = preq; tevent_req_set_callback(dpreq, pam_dp_send_acct_req_done, cb_ctx); /* tell caller we are in an async call */ return EAGAIN; }
errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, struct confdb_ctx *cdb, struct resp_ctx *rctx) { errno_t ret; bool filter_set = false; char **filter_list = NULL; char *name = NULL; struct sss_domain_info *dom = NULL; struct sss_domain_info *domain_list = rctx->domains; char *domainname = NULL; char *conf_path = NULL; TALLOC_CTX *tmpctx = talloc_new(NULL); int i; /* Populate domain-specific negative cache entries */ for (dom = domain_list; dom; dom = get_next_domain(dom, false)) { conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, dom->name); if (!conf_path) { ret = ENOMEM; goto done; } talloc_zfree(filter_list); ret = confdb_get_string_as_list(cdb, tmpctx, conf_path, CONFDB_NSS_FILTER_USERS, &filter_list); if (ret == ENOENT) continue; if (ret != EOK) goto done; filter_set = true; for (i = 0; (filter_list && filter_list[i]); i++) { ret = sss_parse_name_for_domains(tmpctx, domain_list, rctx->default_domain, filter_list[i], &domainname, &name); if (ret != EOK) { DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n", filter_list[i], ret)); continue; } if (domainname && strcmp(domainname, dom->name)) { DEBUG(1, ("Mismatch between domain name (%s) and name " "set in FQN (%s), skipping user %s\n", dom->name, domainname, name)); continue; } ret = sss_ncache_set_user(ncache, true, dom, name); if (ret != EOK) { DEBUG(1, ("Failed to store permanent user filter for [%s]" " (%d [%s])\n", filter_list[i], ret, strerror(ret))); continue; } } } ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY, CONFDB_NSS_FILTER_USERS, &filter_list); if (ret == ENOENT) { if (!filter_set) { filter_list = talloc_array(tmpctx, char *, 2); if (!filter_list) { ret = ENOMEM; goto done; } filter_list[0] = talloc_strdup(tmpctx, "root"); if (!filter_list[0]) { ret = ENOMEM; goto done; } filter_list[1] = NULL; } }