diff options
-rw-r--r-- | src/providers/ipa/ipa_access.c | 77 |
1 files changed, 68 insertions, 9 deletions
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c index 42731f244..895bd76d4 100644 --- a/src/providers/ipa/ipa_access.c +++ b/src/providers/ipa/ipa_access.c @@ -326,7 +326,7 @@ static void hbac_services_get_done(struct tevent_req *subreq) return; } - if (state->services_reply_count == 0 || state->offline) { + if (state->offline) { tevent_req_done(req); return; } @@ -687,23 +687,39 @@ static void hbac_get_host_memberof_done(struct tevent_req *subreq) hbac_get_host_memberof(req, false); } +static bool hbac_is_known_host(struct hbac_host_info **hhi, const char *fqdn) +{ + if (!hhi || !fqdn) { + return false; + } + + int i; + for (i = 0; hhi[i] != NULL; i++) { + if(strcmp(hhi[i]->fqdn, fqdn) == 0) { + return true; + } + } + + return false; +} + static void hbac_get_host_memberof(struct tevent_req *req, bool offline) { struct hbac_get_host_info_state *state = tevent_req_data(req, struct hbac_get_host_info_state); struct sysdb_ctx *sysdb; + struct sss_domain_info *domain; bool in_transaction = false; int ret; int i; struct ldb_message_element *el; struct hbac_host_info **hhi; char *object_name; + const char *fqdn_attrs[] = { IPA_HOST_FQDN, NULL }; + const char *fqdn; - if (state->host_reply_count == 0) { - DEBUG(1, ("No hosts not found in IPA server.\n")); - ret = ENOENT; - goto fail; - } + size_t cached_count; + struct ldb_message **cached_entries = 0; hhi = talloc_array(state, struct hbac_host_info *, state->host_reply_count + 1); if (hhi == NULL) { @@ -714,6 +730,10 @@ static void hbac_get_host_memberof(struct tevent_req *req, bool offline) memset(hhi, 0, sizeof(struct hbac_host_info *) * (state->host_reply_count + 1)); + if (state->host_reply_count == 0) { + DEBUG(1, ("No hosts not found in IPA server.\n")); + } + for (i = 0; i < state->host_reply_count; i++) { hhi[i] = talloc_zero(hhi, struct hbac_host_info); if (hhi[i] == NULL) { @@ -805,6 +825,7 @@ static void hbac_get_host_memberof(struct tevent_req *req, bool offline) } sysdb = hbac_ctx_sysdb(state->hbac_ctx); + domain = hbac_ctx_be(state->hbac_ctx)->domain; ret = sysdb_transaction_start(sysdb); if (ret != EOK) { @@ -813,6 +834,41 @@ static void hbac_get_host_memberof(struct tevent_req *req, bool offline) } in_transaction = true; + ret = sysdb_search_custom(state, sysdb, domain, + state->host_filter, HBAC_HOSTS_SUBDIR, + fqdn_attrs, + &cached_count, + &cached_entries); + + if (ret == ENOENT) { + cached_count = 0; + ret = EOK; + } + + if (ret) { + DEBUG(1, ("sysdb_search_custom failed: [%d](%s)\n", ret, strerror(ret))); + goto fail; + } + + for (i = 0; i < cached_count; i++) { + fqdn = ldb_msg_find_attr_as_string(cached_entries[i], IPA_HOST_FQDN, NULL); + if (!fqdn) { + DEBUG(1, ("missing FQDN in cached HBAC host record\n")); + } else if (hbac_is_known_host(hhi, fqdn)) { + continue; + } else { + DEBUG(9, ("deleting obsolete HBAC host record for %s\n", fqdn)); + } + + ret = sysdb_delete_entry(sysdb, cached_entries[i]->dn, true); + if (ret) { + DEBUG(1, ("sysdb_delete_entry failed: [%d](%s)\n", ret, strerror(ret))); + goto fail; + } + } + + talloc_zfree(cached_entries); + for (i = 0; i < state->host_reply_count; i++) { ret = sysdb_attrs_get_el(state->host_reply_list[i], @@ -834,7 +890,7 @@ static void hbac_get_host_memberof(struct tevent_req *req, bool offline) DEBUG(9, ("Fqdn [%s].\n", object_name)); ret = sysdb_store_custom(state, sysdb, - hbac_ctx_be(state->hbac_ctx)->domain, + domain, object_name, HBAC_HOSTS_SUBDIR, state->host_reply_list[i]); @@ -856,6 +912,8 @@ static void hbac_get_host_memberof(struct tevent_req *req, bool offline) return; fail: + talloc_zfree(cached_entries); + if (in_transaction) { sysdb_transaction_cancel(sysdb); } @@ -1080,7 +1138,7 @@ static void hbac_rule_get(struct tevent_req *req, bool offline) DEBUG(9, ("OriginalDN: [%s].\n", (const char *)el->values[0].data)); } - if (state->hbac_reply_count == 0 || offline) { + if (offline) { tevent_req_done(req); return; } @@ -1886,7 +1944,8 @@ static void hbac_get_host_info_done(struct tevent_req *req) } if (local_hhi == NULL) { DEBUG(1, ("Missing host info for [%s].\n", ipa_hostname)); - ret = EINVAL; + ret = EOK; + pam_status = PAM_PERM_DENIED; goto fail; } req = hbac_get_rules_send(hbac_ctx, hbac_ctx, |