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); }
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); }
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); }
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); }
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; } }
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); }
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; }
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); }
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); }
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; }
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); }
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); }
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); }
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); }
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); } }