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);
}
Exemple #2
0
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;
}
Exemple #3
0
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;
    }
Exemple #4
0
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;
        }
    }