示例#1
0
文件: ldap_id_enum.c 项目: nguay/SSSD
static void ldap_id_enumerate_timer(struct tevent_context *ev,
                                    struct tevent_timer *tt,
                                    struct timeval tv, void *pvt)
{
    struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx);
    struct tevent_timer *timeout;
    struct tevent_req *req;
    int delay;
    errno_t ret;

    if (be_is_offline(ctx->be)) {
        DEBUG(4, ("Backend is marked offline, retry later!\n"));
        /* schedule starting from now, not the last run */
        delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
        tv = tevent_timeval_current_ofs(delay, 0);
        ldap_id_enumerate_set_timer(ctx, tv);
        return;
    }

    req = ldap_id_enumerate_send(ev, ctx);
    if (!req) {
        DEBUG(1, ("Failed to schedule enumeration, retrying later!\n"));
        /* schedule starting from now, not the last run */
        delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
        tv = tevent_timeval_current_ofs(delay, 0);
        ret = ldap_id_enumerate_set_timer(ctx, tv);
        if (ret != EOK) {
            DEBUG(1, ("Error setting up enumerate timer\n"));
        }
        return;
    }
    tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx);

    /* if enumeration takes so long, either we try to enumerate too
     * frequently, or something went seriously wrong */
    delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
    tv = tevent_timeval_current_ofs(delay, 0);
    timeout = tevent_add_timer(ctx->be->ev, req, tv,
                               ldap_id_enumerate_timeout, req);
    if (timeout == NULL) {
        /* If we can't guarantee a timeout, we
         * need to cancel the request, to avoid
         * the possibility of starting another
         * concurrently
         */
        talloc_zfree(req);

        DEBUG(1, ("Failed to schedule enumeration, retrying later!\n"));
        /* schedule starting from now, not the last run */
        delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT);
        tv = tevent_timeval_current_ofs(delay, 0);
        ret = ldap_id_enumerate_set_timer(ctx, tv);
        if (ret != EOK) {
            DEBUG(1, ("Error setting up enumerate timer\n"));
        }
        return;
    }
    return;
}
示例#2
0
static int hbac_retry(struct hbac_ctx *hbac_ctx)
{
    struct tevent_req *subreq;
    int ret;
    bool offline;
    time_t now, refresh_interval;
    struct ipa_access_ctx *access_ctx = hbac_ctx->access_ctx;
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);

    offline = be_is_offline(be_ctx);
    DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online"));

    refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options,
                                      IPA_HBAC_REFRESH);

    now = time(NULL);
    if (now < access_ctx->last_update + refresh_interval) {
        /* Simulate offline mode and just go to the cache */
        DEBUG(6, ("Performing cached HBAC evaluation\n"));
        offline = true;
    }

    if (!offline) {
        if (hbac_ctx->sdap_op == NULL) {
            hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx,
                                          hbac_ctx->sdap_ctx->conn->conn_cache);
            if (hbac_ctx->sdap_op == NULL) {
                DEBUG(1, ("sdap_id_op_create failed.\n"));
                return EIO;
            }
        }

        subreq = sdap_id_op_connect_send(hbac_ctx->sdap_op, hbac_ctx, &ret);
        if (!subreq) {
            DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret)));
            talloc_zfree(hbac_ctx->sdap_op);
            return ret;
        }

        tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx);
    } else {
        /* Evaluate the rules based on what we have in the
         * sysdb
         */
        ipa_hbac_evaluate_rules(hbac_ctx);
        return EOK;
    }
    return EOK;
}
示例#3
0
void ipa_account_info_handler(struct be_req *breq)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
    struct ipa_id_ctx *ipa_ctx;
    struct sdap_id_ctx *ctx;
    struct be_acct_req *ar;
    struct tevent_req *req = NULL;

    ipa_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
                              struct ipa_id_ctx);
    ctx = ipa_ctx->sdap_id_ctx;

    if (be_is_offline(ctx->be)) {
        return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
    }

    ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);

    if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
        /* if domain names do not match, this is a subdomain case
         * subdomain lookups are handled differently on the server
         * and the client
         */
        if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) {
            req = ipa_get_ad_acct_send(breq, be_ctx->ev, ipa_ctx, breq, ar);
        } else {
            req = ipa_get_subdom_acct_send(breq, be_ctx->ev, ctx, ar);
        }
    } else if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
        /* netgroups are handled by a separate request function */
        if (ar->filter_type != BE_FILTER_NAME) {
            return sdap_handler_done(breq, DP_ERR_FATAL,
                                     EINVAL, "Invalid filter type");
        }
        req = ipa_id_get_netgroup_send(breq, be_ctx->ev,
                                       ipa_ctx, ar->filter_value);
    } else {
        /* any account request is handled by sdap,
         * any invalid request is caught there. */
        return sdap_handle_account_info(breq, ctx, ctx->conn);
    }

    if (!req) {
        return sdap_handler_done(breq, DP_ERR_FATAL,
                                 ENOMEM, "Out of memory");
    }
    tevent_req_set_callback(req, ipa_account_info_done, breq);
}
示例#4
0
文件: proxy_id.c 项目: abbra/sssd
void proxy_get_account_info(struct be_req *breq)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
    struct be_acct_req *ar;
    struct proxy_id_ctx *ctx;
    struct sysdb_ctx *sysdb;
    struct sss_domain_info *domain;
    uid_t uid;
    gid_t gid;
    int ret;
    char *endptr;

    ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);
    ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
                          struct proxy_id_ctx);
    sysdb = be_ctx->domain->sysdb;
    domain = be_ctx->domain;

    if (be_is_offline(be_ctx)) {
        return be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
    }

    /* for now we support only core attrs */
    if (ar->attr_type != BE_ATTR_CORE) {
        return be_req_terminate(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type");
    }

    /* proxy provider does not support security ID lookups */
    if (ar->filter_type == BE_FILTER_SECID) {
        return be_req_terminate(breq, DP_ERR_FATAL, ENOSYS,
                                "Invalid filter type");
    }

    switch (ar->entry_type & BE_REQ_TYPE_MASK) {
    case BE_REQ_USER: /* user */
        switch (ar->filter_type) {
        case BE_FILTER_ENUM:
            ret = enum_users(breq, ctx, sysdb, domain);
            break;

        case BE_FILTER_NAME:
            ret = get_pw_name(ctx, domain, ar->filter_value);
            break;

        case BE_FILTER_IDNUM:
            uid = (uid_t) strtouint32(ar->filter_value, &endptr, 10);
            if (errno || *endptr || (ar->filter_value == endptr)) {
                return be_req_terminate(breq, DP_ERR_FATAL,
                                        EINVAL, "Invalid attr type");
            }
            ret = get_pw_uid(ctx, domain, uid);
            break;
        default:
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    EINVAL, "Invalid filter type");
        }
        break;

    case BE_REQ_GROUP: /* group */
        switch (ar->filter_type) {
        case BE_FILTER_ENUM:
            ret = enum_groups(breq, ctx, sysdb, domain);
            break;
        case BE_FILTER_NAME:
            ret = get_gr_name(ctx, sysdb, domain, ar->filter_value);
            break;
        case BE_FILTER_IDNUM:
            gid = (gid_t) strtouint32(ar->filter_value, &endptr, 10);
            if (errno || *endptr || (ar->filter_value == endptr)) {
                return be_req_terminate(breq, DP_ERR_FATAL,
                                        EINVAL, "Invalid attr type");
            }
            ret = get_gr_gid(breq, ctx, sysdb, domain, gid, 0);
            break;
        default:
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    EINVAL, "Invalid filter type");
        }
        break;

    case BE_REQ_INITGROUPS: /* init groups for user */
        if (ar->filter_type != BE_FILTER_NAME) {
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    EINVAL, "Invalid filter type");
        }
        if (ctx->ops.initgroups_dyn == NULL) {
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    ENODEV, "Initgroups call not supported");
        }
        ret = get_initgr(breq, ctx, sysdb, domain, ar->filter_value);
        break;

    case BE_REQ_NETGROUP:
        if (ar->filter_type != BE_FILTER_NAME) {
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    EINVAL, "Invalid filter type");
        }
        if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL ||
                ctx->ops.endnetgrent == NULL) {
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    ENODEV, "Netgroups are not supported");
        }

        ret = get_netgroup(ctx, domain, ar->filter_value);
        break;

    case BE_REQ_SERVICES:
        switch (ar->filter_type) {
        case BE_FILTER_NAME:
            if (ctx->ops.getservbyname_r == NULL) {
                return be_req_terminate(breq, DP_ERR_FATAL,
                                        ENODEV, "Services are not supported");
            }
            ret = get_serv_byname(ctx, domain,
                                  ar->filter_value,
                                  ar->extra_value);
            break;
        case BE_FILTER_IDNUM:
            if (ctx->ops.getservbyport_r == NULL) {
                return be_req_terminate(breq, DP_ERR_FATAL,
                                        ENODEV, "Services are not supported");
            }
            ret = get_serv_byport(ctx, domain,
                                  ar->filter_value,
                                  ar->extra_value);
            break;
        case BE_FILTER_ENUM:
            if (!ctx->ops.setservent
                    || !ctx->ops.getservent_r
                    || !ctx->ops.endservent) {
                return be_req_terminate(breq, DP_ERR_FATAL,
                                        ENODEV, "Services are not supported");
            }
            ret = enum_services(ctx, sysdb, domain);
            break;
        default:
            return be_req_terminate(breq, DP_ERR_FATAL,
                                    EINVAL, "Invalid filter type");
        }
        break;

    default: /*fail*/
        return be_req_terminate(breq, DP_ERR_FATAL,
                                EINVAL, "Invalid request type");
    }

    if (ret) {
        if (ret == ENXIO) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "proxy returned UNAVAIL error, going offline!\n");
            be_mark_offline(be_ctx);
        }
        be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
        return;
    }
    be_req_terminate(breq, DP_ERR_OK, EOK, NULL);
}
示例#5
0
文件: dp_ptask.c 项目: abbra/sssd
static void be_ptask_execute(struct tevent_context *ev,
                             struct tevent_timer *tt,
                             struct timeval tv,
                             void *pvt)
{
    struct be_ptask *task = NULL;
    struct tevent_timer *timeout = NULL;

    task = talloc_get_type(pvt, struct be_ptask);
    task->timer = NULL; /* timer is freed by tevent */

    if (be_is_offline(task->be_ctx)) {
        DEBUG(SSSDBG_TRACE_FUNC, "Back end is offline\n");
        switch (task->offline) {
        case BE_PTASK_OFFLINE_SKIP:
            be_ptask_schedule(task, BE_PTASK_PERIOD,
                              BE_PTASK_SCHEDULE_FROM_NOW);
            return;
        case BE_PTASK_OFFLINE_DISABLE:
            /* This case is normally handled by offline callback but we
             * should handle it here as well since we can get here in some
             * special cases for example unit tests or tevent events order. */
            be_ptask_disable(task);
            return;
        case BE_PTASK_OFFLINE_EXECUTE:
            /* continue */
            break;
        }
    }

    DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: executing task, timeout %lu "
                              "seconds\n", task->name, task->timeout);

    task->last_execution = tv.tv_sec;

    task->req = task->send_fn(task, task->ev, task->be_ctx, task, task->pvt);
    if (task->req == NULL) {
        /* skip this iteration and try again later */
        DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to execute task, "
              "will try again later\n", task->name);

        be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW);
        return;
    }

    tevent_req_set_callback(task->req, be_ptask_done, task);

    /* schedule timeout */
    if (task->timeout > 0) {
        tv = tevent_timeval_current_ofs(task->timeout, 0);
        timeout = tevent_add_timer(task->ev, task->req, tv,
                                   be_ptask_timeout, task);
        if (timeout == NULL) {
            /* If we can't guarantee a timeout,
             * we need to cancel the request. */
            talloc_zfree(task->req);

            DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to set timeout, "
                  "the task will be rescheduled\n", task->name);

            be_ptask_schedule(task, BE_PTASK_PERIOD,
                              BE_PTASK_SCHEDULE_FROM_NOW);
        }
    }

    return;
}