Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
static void ipa_account_info_done(struct tevent_req *req)
{
    struct be_req *breq = tevent_req_callback_data(req, struct be_req);
    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
    struct ipa_id_ctx *ipa_ctx;
    struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq),
                                             struct be_acct_req);
    const char *error_text;
    int ret, dp_error;

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

    if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
        ret = ipa_id_get_netgroup_recv(req, &dp_error);
    } else {
        if (dp_opt_get_bool(ipa_ctx->ipa_options->basic, IPA_SERVER_MODE)) {
            ret = ipa_get_ad_acct_recv(req, &dp_error);
        } else {
            ret = ipa_get_subdom_acct_recv(req, &dp_error);
        }
    }
    talloc_zfree(req);

    error_text = ipa_account_info_error_text(ret, &dp_error,
                                             "Account info lookup failed");
    sdap_handler_done(breq, dp_error, ret, error_text);
}
Ejemplo n.º 3
0
void sdap_pam_access_handler(struct be_req *breq)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
    struct pam_data *pd;
    struct tevent_req *req;
    struct sdap_access_ctx *access_ctx;
    struct sss_domain_info *dom;

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

    access_ctx =
            talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
                            struct sdap_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);
    }

    req = sdap_access_send(breq, be_ctx->ev, be_ctx,
                           dom, access_ctx,
                           access_ctx->id_ctx->conn,
                           pd);
    if (req == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to start sdap_access request\n"));
        sdap_access_reply(breq, PAM_SYSTEM_ERR);
        return;
    }

    tevent_req_set_callback(req, sdap_access_done, breq);
}
Ejemplo n.º 4
0
static void hbac_get_service_info_step(struct tevent_req *req)
{
    errno_t ret;
    struct hbac_ctx *hbac_ctx =
            tevent_req_callback_data(req, struct hbac_ctx);
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);

    ret = ipa_host_info_recv(req, hbac_ctx,
                             &hbac_ctx->host_count,
                             &hbac_ctx->hosts,
                             &hbac_ctx->hostgroup_count,
                             &hbac_ctx->hostgroups);
    talloc_zfree(req);
    if (!hbac_check_step_result(hbac_ctx, ret)) {
        return;
    }

    /* Get services and service groups */
    req = ipa_hbac_service_info_send(hbac_ctx, be_ctx->ev,
                                    sdap_id_op_handle(hbac_ctx->sdap_op),
                                     hbac_ctx->sdap_ctx->opts,
                                    hbac_ctx->search_bases);
    if (req == NULL) {
        DEBUG(1,("Could not get service info\n"));
        goto fail;
    }
    tevent_req_set_callback(req, hbac_get_rule_info_step, hbac_ctx);
    return;

fail:
    ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
Ejemplo n.º 5
0
static struct krb5_ctx *get_krb5_ctx(struct be_req *be_req)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
    struct pam_data *pd;

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

    switch (pd->cmd) {
        case SSS_PAM_AUTHENTICATE:
        case SSS_CMD_RENEW:
            return talloc_get_type(be_ctx->bet_info[BET_AUTH].pvt_bet_data,
                                   struct krb5_ctx);
            break;
        case SSS_PAM_ACCT_MGMT:
            return talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
                                   struct krb5_ctx);
            break;
        case SSS_PAM_CHAUTHTOK:
        case SSS_PAM_CHAUTHTOK_PRELIM:
            return talloc_get_type(be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
                                   struct krb5_ctx);
            break;
        default:
            DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported PAM task.\n");
            return NULL;
    }
}
Ejemplo n.º 6
0
void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);
    errno_t ret;
    struct hbac_rule **hbac_rules;
    struct hbac_eval_req *eval_req;
    enum hbac_eval_result result;
    struct hbac_info *info;

    /* Get HBAC rules from the sysdb */
    ret = hbac_get_cached_rules(hbac_ctx, be_ctx->domain,
                                &hbac_ctx->rule_count, &hbac_ctx->rules);
    if (ret != EOK) {
        DEBUG(1, ("Could not retrieve rules from the cache\n"));
        ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
    }

    ret = hbac_ctx_to_rules(hbac_ctx, hbac_ctx,
                            &hbac_rules, &eval_req);
    if (ret == EPERM) {
        DEBUG(1, ("DENY rules detected. Denying access to all users\n"));
        ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
        return;
    } else if (ret != EOK) {
        DEBUG(1, ("Could not construct HBAC rules\n"));
        ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
        return;
    }

    result = hbac_evaluate(hbac_rules, eval_req, &info);
    if (result == HBAC_EVAL_ALLOW) {
        DEBUG(3, ("Access granted by HBAC rule [%s]\n",
                  info->rule_name));
        hbac_free_info(info);
        ipa_access_reply(hbac_ctx, PAM_SUCCESS);
        return;
    } else if (result == HBAC_EVAL_ERROR) {
        DEBUG(1, ("Error [%s] occurred in rule [%s]\n",
                  hbac_error_string(info->code),
                  info->rule_name));
        hbac_free_info(info);
        ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
        return;
    } else if (result == HBAC_EVAL_OOM) {
        DEBUG(1, ("Insufficient memory\n"));
        ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
        return;
    }

    DEBUG(3, ("Access denied by HBAC rules\n"));
    hbac_free_info(info);
    ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
void sdap_sudo_handler(struct be_req *be_req)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
    struct tevent_req *req = NULL;
    struct be_sudo_req *sudo_req = NULL;
    struct sdap_sudo_ctx *sudo_ctx = NULL;
    struct sdap_id_ctx *id_ctx = NULL;
    int ret = EOK;

    sudo_ctx = talloc_get_type(be_ctx->bet_info[BET_SUDO].pvt_bet_data,
                               struct sdap_sudo_ctx);
    id_ctx = sudo_ctx->id_ctx;

    sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);

    switch (sudo_req->type) {
    case BE_REQ_SUDO_FULL:
        DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
        req = sdap_sudo_full_refresh_send(be_req, sudo_ctx);
        break;
    case BE_REQ_SUDO_RULES:
        DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
        req = sdap_sudo_rules_refresh_send(be_req, sudo_ctx, id_ctx->be,
                                           id_ctx->opts, id_ctx->conn->conn_cache,
                                           sudo_req->rules);
        break;
    default:
        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
                                    sudo_req->type);
        ret = EINVAL;
        goto fail;
    }

    if (req == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n",
                                    sudo_req->type);
        ret = ENOMEM;
        goto fail;
    }

    tevent_req_set_callback(req, sdap_sudo_reply, be_req);

    return;

fail:
    sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
}
Ejemplo n.º 10
0
static int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx)
{
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);
    const char *hostname;
    struct tevent_req *req;

    if (dp_opt_get_bool(hbac_ctx->ipa_options, IPA_HBAC_SUPPORT_SRCHOST)) {
        /* Support srchost
         * -> we don't want any particular host,
         *    we want all hosts
         */
        hostname = NULL;

        /* THIS FEATURE IS DEPRECATED */
        DEBUG(SSSDBG_MINOR_FAILURE, ("WARNING: Using deprecated option "
                    "ipa_hbac_support_srchost.\n"));
        sss_log(SSS_LOG_NOTICE, "WARNING: Using deprecated option "
                    "ipa_hbac_support_srchost.\n");
    } else {
        hostname = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME);
    }

    req = ipa_host_info_send(hbac_ctx, be_ctx->ev,
                             sdap_id_op_handle(hbac_ctx->sdap_op),
                             hbac_ctx->sdap_ctx->opts,
                             hostname,
                             hbac_ctx->access_ctx->host_map,
                             hbac_ctx->access_ctx->hostgroup_map,
                             hbac_ctx->access_ctx->host_search_bases);
    if (req == NULL) {
        DEBUG(1, ("Could not get host info\n"));
        return ENOMEM;
    }
    tevent_req_set_callback(req, hbac_get_service_info_step, hbac_ctx);

    return EOK;
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
0
static void hbac_sysdb_save(struct tevent_req *req)
{
    errno_t ret;
    bool in_transaction = false;
    struct hbac_ctx *hbac_ctx =
            tevent_req_callback_data(req, struct hbac_ctx);
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);
    struct sss_domain_info *domain = be_ctx->domain;
    struct ldb_dn *base_dn;
    struct ipa_access_ctx *access_ctx =
            talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
                            struct ipa_access_ctx);
    TALLOC_CTX *tmp_ctx;

    ret = ipa_hbac_rule_info_recv(req, hbac_ctx,
                                  &hbac_ctx->rule_count,
                                  &hbac_ctx->rules);
    talloc_zfree(req);
    if (ret == ENOENT) {
        /* No rules were found that apply to this
         * host.
         */

        tmp_ctx = talloc_new(NULL);
        if (tmp_ctx == NULL) {
            ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
            return;
        }
        /* Delete any rules in the sysdb so offline logins
         * are also denied.
         */
        base_dn = sysdb_custom_subtree_dn(domain->sysdb, tmp_ctx,
                                          domain, HBAC_RULES_SUBDIR);
        if (base_dn == NULL) {
            talloc_free(tmp_ctx);
            ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
            return;
        }

        ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
        talloc_free(tmp_ctx);
        if (ret != EOK) {
            DEBUG(1, ("sysdb_delete_recursive failed.\n"));
            ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
            return;
        }

        /* If no rules are found, we default to DENY */
        ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
        return;
    }

    if (!hbac_check_step_result(hbac_ctx, ret)) {
        return;
    }

    ret = sysdb_transaction_start(domain->sysdb);
    if (ret != EOK) {
        DEBUG(0, ("Could not start transaction\n"));
        goto fail;
    }
    in_transaction = true;

    /* Save the hosts */
    ret = ipa_hbac_sysdb_save(domain,
                              HBAC_HOSTS_SUBDIR, SYSDB_FQDN,
                              hbac_ctx->host_count, hbac_ctx->hosts,
                              HBAC_HOSTGROUPS_SUBDIR, SYSDB_NAME,
                              hbac_ctx->hostgroup_count,
                              hbac_ctx->hostgroups);
    if (ret != EOK) {
        DEBUG(1, ("Error saving hosts: [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }

    /* Save the services */
    ret = ipa_hbac_sysdb_save(domain,
                              HBAC_SERVICES_SUBDIR, IPA_CN,
                              hbac_ctx->service_count, hbac_ctx->services,
                              HBAC_SERVICEGROUPS_SUBDIR, IPA_CN,
                              hbac_ctx->servicegroup_count,
                              hbac_ctx->servicegroups);
    if (ret != EOK) {
        DEBUG(1, ("Error saving services:  [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }
    /* Save the rules */
    ret = ipa_hbac_sysdb_save(domain,
                              HBAC_RULES_SUBDIR, IPA_UNIQUE_ID,
                              hbac_ctx->rule_count,
                              hbac_ctx->rules,
                              NULL, NULL, 0, NULL);
    if (ret != EOK) {
        DEBUG(1, ("Error saving rules:  [%d][%s]\n",
                  ret, strerror(ret)));
        goto fail;
    }

    ret = sysdb_transaction_commit(domain->sysdb);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
        goto fail;
    }
    in_transaction = false;

    /* We don't need the rule data any longer,
     * the rest of the processing relies on
     * sysdb lookups.
     */
    hbac_clear_rule_data(hbac_ctx);


    access_ctx->last_update = time(NULL);

    /* Now evaluate the request against the rules */
    ipa_hbac_evaluate_rules(hbac_ctx);

    return;

fail:
    if (in_transaction) {
        ret = sysdb_transaction_cancel(domain->sysdb);
        if (ret != EOK) {
            DEBUG(0, ("Could not cancel transaction\n"));
        }
    }
    ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
Ejemplo n.º 14
0
static void hbac_get_rule_info_step(struct tevent_req *req)
{
    errno_t ret;
    size_t i;
    const char *ipa_hostname;
    const char *hostname;
    struct hbac_ctx *hbac_ctx =
            tevent_req_callback_data(req, struct hbac_ctx);
    struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);

    ret = ipa_hbac_service_info_recv(req, hbac_ctx,
                                     &hbac_ctx->service_count,
                                     &hbac_ctx->services,
                                     &hbac_ctx->servicegroup_count,
                                     &hbac_ctx->servicegroups);
    talloc_zfree(req);
    if (!hbac_check_step_result(hbac_ctx, ret)) {
        return;
    }

    /* Get the ipa_host attrs */
    hbac_ctx->ipa_host = NULL;
    ipa_hostname = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
    if (ipa_hostname == NULL) {
        DEBUG(1, ("Missing ipa_hostname, this should never happen.\n"));
        goto fail;
    }

    for (i = 0; i < hbac_ctx->host_count; i++) {
        ret = sysdb_attrs_get_string(hbac_ctx->hosts[i],
                                     SYSDB_FQDN,
                                     &hostname);
        if (ret != EOK) {
            DEBUG(1, ("Could not locate IPA host\n"));
            goto fail;
        }

        if (strcasecmp(hostname, ipa_hostname) == 0) {
            hbac_ctx->ipa_host = hbac_ctx->hosts[i];
            break;
        }
    }
    if (hbac_ctx->ipa_host == NULL) {
        DEBUG(1, ("Could not locate IPA host\n"));
        goto fail;
    }


    /* Get the list of applicable rules */
    req = ipa_hbac_rule_info_send(hbac_ctx,
                                  hbac_ctx->get_deny_rules,
                                  be_ctx->ev,
                                  sdap_id_op_handle(hbac_ctx->sdap_op),
                                  hbac_ctx->sdap_ctx->opts,
                                  hbac_ctx->search_bases,
                                  hbac_ctx->ipa_host);
    if (req == NULL) {
        DEBUG(1, ("Could not get rules\n"));
        goto fail;
    }

    tevent_req_set_callback(req, hbac_sysdb_save, hbac_ctx);
    return;

fail:
    ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
Ejemplo n.º 15
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);
    }
}