diff options
-rw-r--r-- | server/providers/ipa/ipa_access.c | 144 | ||||
-rw-r--r-- | server/providers/ipa/ipa_access.h | 8 |
2 files changed, 97 insertions, 55 deletions
diff --git a/server/providers/ipa/ipa_access.c b/server/providers/ipa/ipa_access.c index 8be91a61..230cabc1 100644 --- a/server/providers/ipa/ipa_access.c +++ b/server/providers/ipa/ipa_access.c @@ -56,14 +56,6 @@ #define HBAC_RULES_SUBDIR "hbac_rules" #define HBAC_HOSTS_SUBDIR "hbac_hosts" -struct hbac_host_info { - const char *fqdn; - const char *serverhostname; - const char *dn; - const char **memberof; -}; - - static void ipa_access_reply(struct be_req *be_req, int pam_status) { struct pam_data *pd; @@ -297,7 +289,6 @@ struct hbac_get_host_info_state { struct sysdb_ctx *sysdb; struct sysdb_handle *handle; - const char *hostname; char *host_filter; char *host_search_base; const char **host_attrs; @@ -319,15 +310,16 @@ static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, struct sdap_id_ctx *sdap_ctx, struct sysdb_ctx *sysdb, const char *ipa_domain, - const char *hostname) + const char **hostnames) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct hbac_get_host_info_state *state; int ret; + int i; - if (hostname == NULL || ipa_domain == NULL) { - DEBUG(1, ("Missing fqdn or domain.\n")); + if (hostnames == NULL || ipa_domain == NULL) { + DEBUG(1, ("Missing hostnames or domain.\n")); return NULL; } @@ -341,20 +333,33 @@ static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx, state->sdap_ctx = sdap_ctx; state->sysdb = sysdb; state->handle = NULL; - state->hostname= hostname; state->host_reply_list = NULL; state->host_reply_count = 0; state->current_item = 0; + state->hbac_host_info = NULL; - state->host_filter = talloc_asprintf(state, - "(&(|(fqdn=%s)(serverhostname=%s))(objectclass=ipaHost))", - hostname, hostname); + state->host_filter = talloc_asprintf(state, "(|"); if (state->host_filter == NULL) { DEBUG(1, ("Failed to create filter.\n")); ret = ENOMEM; goto fail; } + for (i = 0; hostnames[i] != NULL; i++) { + state->host_filter = talloc_asprintf_append(state->host_filter, + "(&(objectclass=ipaHost)" + "(|(fqdn=%s)(serverhostname=%s)))", + hostnames[i], hostnames[i]); + if (state->host_filter == NULL) { + ret = ENOMEM; + goto fail; + } + } + state->host_filter = talloc_asprintf_append(state->host_filter, ")"); + if (state->host_filter == NULL) { + ret = ENOMEM; + goto fail; + } state->host_search_base = talloc_asprintf(state, IPA_HOST_BASE_TMPL, ipa_domain); @@ -477,8 +482,8 @@ static void host_get_host_memberof_done(struct tevent_req *subreq) return; } - if (state->host_reply_list == NULL) { - DEBUG(1, ("Host [%s] not found in IPA server.\n", state->hostname)); + if (state->host_reply_count == 0) { + DEBUG(1, ("No hosts not found in IPA server.\n")); ret = ENOENT; goto fail; } @@ -493,7 +498,7 @@ static void host_get_host_memberof_done(struct tevent_req *subreq) sizeof(struct hbac_host_info *) * (state->host_reply_count + 1)); for (i = 0; i < state->host_reply_count; i++) { - hhi[i] = talloc_zero(state, struct hbac_host_info); + hhi[i] = talloc_zero(hhi, struct hbac_host_info); if (hhi[i] == NULL) { ret = ENOMEM; goto fail; @@ -1302,30 +1307,22 @@ enum check_result check_user(struct hbac_ctx *hbac_ctx, return RULE_ERROR; } -enum check_result check_remote_hosts(struct pam_data *pd, +enum check_result check_remote_hosts(const char *rhost, + struct hbac_host_info *hhi, struct sysdb_attrs *rule_attrs) { int ret; int i; + int m; struct ldb_message_element *cat_el; struct ldb_message_element *src_el; struct ldb_message_element *ext_el; - const char *remote_hostname; - if (pd->rhost == NULL && pd->tty == NULL) { - DEBUG(1, ("Neither remote host nor tty specified in pam data, " - "assuming error.\n")); + if (hhi == NULL && (rhost == NULL || *rhost == '\0')) { + DEBUG(1, ("No remote host information specified, assuming error.\n")); return RULE_ERROR; } - if (pd->rhost == NULL) { - DEBUG(5, ("No remote host specified, but tty is set [%s], " - "assuming 'localhost'.\n", pd->tty)); - remote_hostname = "localhost"; - } else { - remote_hostname = pd->rhost; - } - ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST_CATEGORY, &cat_el); if (ret != EOK) { DEBUG(1, ("sysdb_attrs_get_el failed.\n")); @@ -1347,7 +1344,6 @@ enum check_result check_remote_hosts(struct pam_data *pd, } } - ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST, &src_el); if (ret != EOK) { DEBUG(1, ("sysdb_attrs_get_el failed.\n")); @@ -1360,25 +1356,37 @@ enum check_result check_remote_hosts(struct pam_data *pd, } if (src_el->num_values == 0 && ext_el->num_values == 0) { - DEBUG(9, ("No remote host specified, rule does not apply.\n")); + DEBUG(9, ("No remote host specified in rule, rule does not apply.\n")); return RULE_NOT_APPLICABLE; } else { - for (i = 0; i < src_el->num_values; i++) { - if (strncasecmp(remote_hostname, - (const char *) src_el->values[i].data, - src_el->values[i].length) == 0) { - DEBUG(9, ("Source host [%s] found, rule applies.\n", - remote_hostname)); - return RULE_APPLICABLE; + if (hhi != NULL) { + for (i = 0; i < src_el->num_values; i++) { + if (strncasecmp(hhi->dn, (const char *) src_el->values[i].data, + src_el->values[i].length) == 0) { + DEBUG(9, ("Source host [%s] found, rule applies.\n", + hhi->dn)); + return RULE_APPLICABLE; + } + for (m = 0; hhi->memberof[m] != NULL; m++) { + if (strncasecmp(hhi->memberof[m], + (const char *) src_el->values[i].data, + src_el->values[i].length) == 0) { + DEBUG(9, ("Source host group [%s] found, rule applies.\n", + hhi->memberof[m])); + return RULE_APPLICABLE; + } + } } } - for (i = 0; i < ext_el->num_values; i++) { - if (strncasecmp(remote_hostname, - (const char *) ext_el->values[i].data, - ext_el->values[i].length) == 0) { - DEBUG(9, ("External host [%s] found, rule applies.\n", - remote_hostname)); - return RULE_APPLICABLE; + + if (rhost != NULL && *rhost != '\0') { + for (i = 0; i < ext_el->num_values; i++) { + if (strncasecmp(rhost, (const char *) ext_el->values[i].data, + ext_el->values[i].length) == 0) { + DEBUG(9, ("External host [%s] found, rule applies.\n", + rhost)); + return RULE_APPLICABLE; + } } } DEBUG(9, ("No matching remote host found.\n")); @@ -1452,7 +1460,7 @@ static errno_t check_if_rule_applies(enum hbac_result *result, goto not_applicable; } - ret = check_remote_hosts(pd, rule_attrs); + ret = check_remote_hosts(pd->rhost, hbac_ctx->remote_hhi, rule_attrs); if (ret != RULE_APPLICABLE) { goto not_applicable; } @@ -1520,6 +1528,7 @@ void ipa_access_handler(struct be_req *be_req) struct hbac_ctx *hbac_ctx; int pam_status = PAM_SYSTEM_ERR; struct ipa_access_ctx *ipa_access_ctx; + const char *hostlist[3]; pd = talloc_get_type(be_req->req_data, struct pam_data); @@ -1537,12 +1546,29 @@ void ipa_access_handler(struct be_req *be_req) hbac_ctx->ipa_options = ipa_access_ctx->ipa_options; hbac_ctx->tr_ctx = ipa_access_ctx->tr_ctx; + + hostlist[0] = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME); + if (hostlist[0] == NULL) { + DEBUG(1, ("ipa_hostname not available.\n")); + goto fail; + } + if (pd->rhost != NULL && *pd->rhost != '\0') { + hostlist[1] = pd->rhost; + } else { + hostlist[1] = NULL; + pd->rhost = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME); + if (pd->rhost == NULL) { + DEBUG(1, ("ipa_hostname not available.\n")); + goto fail; + } + } + hostlist[2] = NULL; + req = hbac_get_host_info_send(hbac_ctx, be_req->be_ctx->ev, hbac_ctx->sdap_ctx, be_req->be_ctx->sysdb, dp_opt_get_string(hbac_ctx->ipa_options, IPA_DOMAIN), - dp_opt_get_string(hbac_ctx->ipa_options, - IPA_HOSTNAME)); + hostlist); if (req == NULL) { DEBUG(1, ("hbac_get_host_info_send failed.\n")); goto fail; @@ -1562,6 +1588,7 @@ static void hbac_get_host_info_done(struct tevent_req *req) int ret; int pam_status = PAM_SYSTEM_ERR; const char *ipa_hostname; + struct hbac_host_info *local_hhi = NULL; int i; ret = hbac_get_host_info_recv(req, hbac_ctx, &hbac_ctx->hbac_host_info); @@ -1581,10 +1608,18 @@ static void hbac_get_host_info_done(struct tevent_req *req) if (strcmp(hbac_ctx->hbac_host_info[i]->fqdn, ipa_hostname) == 0 || strcmp(hbac_ctx->hbac_host_info[i]->serverhostname, ipa_hostname) == 0) { - break; + local_hhi = hbac_ctx->hbac_host_info[i]; + } + if (hbac_ctx->pd->rhost != NULL && *hbac_ctx->pd->rhost != '\0') { + if (strcmp(hbac_ctx->hbac_host_info[i]->fqdn, + hbac_ctx->pd->rhost) == 0 || + strcmp(hbac_ctx->hbac_host_info[i]->serverhostname, + hbac_ctx->pd->rhost) == 0) { + hbac_ctx->remote_hhi = hbac_ctx->hbac_host_info[i]; + } } } - if (hbac_ctx->hbac_host_info[i] == NULL) { + if (local_hhi == NULL) { DEBUG(1, ("Missing host info for [%s].\n", ipa_hostname)); ret = EINVAL; goto fail; @@ -1593,8 +1628,7 @@ static void hbac_get_host_info_done(struct tevent_req *req) be_req->be_ctx->sysdb, dp_opt_get_string(hbac_ctx->ipa_options, IPA_DOMAIN), - hbac_ctx->hbac_host_info[i]->dn, - hbac_ctx->hbac_host_info[i]->memberof); + local_hhi->dn, local_hhi->memberof); if (req == NULL) { DEBUG(1, ("hbac_get_rules_send failed.\n")); goto fail; diff --git a/server/providers/ipa/ipa_access.h b/server/providers/ipa/ipa_access.h index 1b01e9fe..486dac69 100644 --- a/server/providers/ipa/ipa_access.h +++ b/server/providers/ipa/ipa_access.h @@ -32,6 +32,13 @@ enum ipa_access_mode { IPA_ACCESS_ALLOW }; +struct hbac_host_info { + const char *fqdn; + const char *serverhostname; + const char *dn; + const char **memberof; +}; + struct ipa_access_ctx { struct sdap_id_ctx *sdap_ctx; struct dp_option *ipa_options; @@ -45,6 +52,7 @@ struct hbac_ctx { struct be_req *be_req; struct pam_data *pd; struct hbac_host_info **hbac_host_info; + struct hbac_host_info *remote_hhi; struct sysdb_attrs **hbac_rule_list; size_t hbac_rule_count; const char *user_dn; |