Exemplo n.º 1
0
static void sdap_access_reply(struct be_req *be_req, int pam_status)
{
    struct pam_data *pd;
    pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
    pd->pam_status = pam_status;

    if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED
            || pam_status == PAM_ACCT_EXPIRED) {
        be_req_terminate(be_req, DP_ERR_OK, pam_status, NULL);
    } else {
        be_req_terminate(be_req, DP_ERR_FATAL, pam_status, NULL);
    }
}
Exemplo n.º 2
0
void ipa_access_handler(struct be_req *be_req)
{
    struct pam_data *pd;
    struct ipa_access_ctx *ipa_access_ctx;
    struct tevent_req *req;
    struct sss_domain_info *dom;
    struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);

    pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);

    ipa_access_ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
                                     struct ipa_access_ctx);

    dom = be_ctx->domain;
    if (strcasecmp(pd->domain, be_ctx->domain->name) != 0) {
        /* Subdomain request, verify subdomain */
        dom = find_subdomain_by_name(be_ctx->domain, pd->domain, true);
    }

    /* First, verify that this account isn't locked.
     * We need to do this in case the auth phase was
     * skipped (such as during GSSAPI single-sign-on
     * or SSH public key exchange.
     */
    req = sdap_access_send(be_req, be_ctx->ev, be_ctx, dom,
                           ipa_access_ctx->sdap_access_ctx,
                           ipa_access_ctx->sdap_access_ctx->id_ctx->conn,
                           pd);
    if (!req) {
        be_req_terminate(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
        return;
    }
    tevent_req_set_callback(req, ipa_hbac_check, be_req);
}
Exemplo n.º 3
0
static void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status)
{
    struct be_req *be_req = hbac_ctx->be_req;
    struct pam_data *pd;
    pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
    pd->pam_status = pam_status;

    /* destroy HBAC context now to release all used resources and LDAP connection */
    talloc_zfree(hbac_ctx);

    if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED) {
        be_req_terminate(be_req, DP_ERR_OK, pam_status, NULL);
    } else {
        be_req_terminate(be_req, DP_ERR_FATAL, pam_status, NULL);
    }
}
Exemplo n.º 4
0
static void proxy_auth_shutdown(struct be_req *req)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(req);
    talloc_free(be_ctx->bet_info[BET_AUTH].pvt_bet_data);
    be_req_terminate(req, DP_ERR_OK, EOK, NULL);
}
Exemplo n.º 5
0
static void proxy_shutdown(struct be_req *req)
{
    /* TODO: Clean up any internal data */
    be_req_terminate(req, DP_ERR_OK, EOK, NULL);
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
static void ipa_hbac_check(struct tevent_req *req)
{
    struct be_req *be_req;
    struct be_ctx *be_ctx;
    struct pam_data *pd;
    struct hbac_ctx *hbac_ctx = NULL;
    const char *deny_method;
    struct ipa_access_ctx *ipa_access_ctx;
    int ret;

    be_req = tevent_req_callback_data(req, struct be_req);
    be_ctx = be_req_get_be_ctx(be_req);
    pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);

    ret = sdap_access_recv(req);
    talloc_zfree(req);

    switch(ret) {
    case EOK:
        /* Account wasn't locked. Continue below
         * to HBAC processing.
         */
        break;
    case ERR_ACCESS_DENIED:
        /* Account was locked. Return permission denied
         * here.
         */
        pd->pam_status = PAM_PERM_DENIED;
        be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
        return;
    case ERR_ACCOUNT_EXPIRED:
        pd->pam_status = PAM_ACCT_EXPIRED;
        be_req_terminate(be_req, DP_ERR_OK, pd->pam_status, NULL);
        return;
    default:
        /* We got an unexpected error. Return it as-is */
        pd->pam_status = PAM_SYSTEM_ERR;
        be_req_terminate(be_req, DP_ERR_FATAL, pd->pam_status,
                         sss_strerror(ret));
        return;
    }

    hbac_ctx = talloc_zero(be_req, struct hbac_ctx);
    if (hbac_ctx == NULL) {
        DEBUG(1, ("talloc failed.\n"));
        ret = ENOMEM;
        goto fail;
    }

    hbac_ctx->be_req = be_req;
    hbac_ctx->pd = pd;
    ipa_access_ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
                                     struct ipa_access_ctx);
    hbac_ctx->access_ctx = ipa_access_ctx;
    hbac_ctx->sdap_ctx = ipa_access_ctx->sdap_ctx;
    hbac_ctx->ipa_options = ipa_access_ctx->ipa_options;
    hbac_ctx->tr_ctx = ipa_access_ctx->tr_ctx;
    hbac_ctx->search_bases = ipa_access_ctx->hbac_search_bases;
    if (hbac_ctx->search_bases == NULL) {
        DEBUG(1, ("No HBAC search base found.\n"));
        ret = EINVAL;
        goto fail;
    }

    deny_method = dp_opt_get_string(hbac_ctx->ipa_options,
                                    IPA_HBAC_DENY_METHOD);
    if (strcasecmp(deny_method, "IGNORE") == 0) {
        hbac_ctx->get_deny_rules = false;
    } else {
        hbac_ctx->get_deny_rules = true;
    }

    ret = hbac_retry(hbac_ctx);
    if (ret != EOK) {
        goto fail;
    }

    return;

fail:
    if (hbac_ctx) {
        /* Return an proper error */
        ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
    } else {
        be_req_terminate(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
    }
}