don't fetch all host groups if this option is set to false
https://fedorahosted.org/sssd/ticket/1078

Jan
From fcf9accd7e0b52d56266c2c6426405b41ce418e2 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzel...@redhat.com>
Date: Fri, 4 Nov 2011 13:16:47 -0400
Subject: [PATCH] Add ipa_hbac_support_srchost option to IPA provider

don't fetch all host groups if this option is false
https://fedorahosted.org/sssd/ticket/1078
---
 src/config/SSSDConfig.py                |    1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf |    1 +
 src/man/sssd-ipa.5.xml                  |   12 +++
 src/providers/ipa/hbac_evaluator.c      |   18 +++--
 src/providers/ipa/ipa_access.c          |    4 +
 src/providers/ipa/ipa_common.c          |    3 +-
 src/providers/ipa/ipa_common.h          |    1 +
 src/providers/ipa/ipa_hbac_common.c     |   10 ++-
 src/providers/ipa/ipa_hbac_hosts.c      |  119 ++++++++++++++++++++++++++++---
 src/providers/ipa/ipa_hbac_private.h    |    2 +
 10 files changed, 148 insertions(+), 23 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 87b1d63413cd914401aeccdc6ad2eec12af92a66..b6d1b6f070afd73dd0a32b1c58c6e312255c82fa 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -102,6 +102,7 @@ option_strings = {
     'ipa_hbac_search_base' : _("Search base for HBAC related objects"),
     'ipa_hbac_refresh' : _("The amount of time between lookups of the HBAC rules against the IPA server"),
     'ipa_hbac_treat_deny_as' : _("If DENY rules are present, either DENY_ALL or IGNORE"),
+    'ipa_hbac_support_srchost' : _("If set to false, host argument given by PAM will be ignored"),
 
     # [provider/krb5]
     'krb5_kdcip' : _('Kerberos server address'),
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 9ea45285ec93c4afe0ea2210c5a27a68de894b3f..697db819cbb165f1c4febeb2c417607444221bbe 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -106,6 +106,7 @@ krb5_fast_principal = str, None, false
 [provider/ipa/access]
 ipa_hbac_refresh = int, None, false
 ipa_hbac_treat_deny_as = str, None, false
+ipa_hbac_support_srchost = bool, None, false
 
 [provider/ipa/chpass]
 
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index 2c1a0ed8c37b4429b1929637807d3cbedcca1d68..105f5c7283f70e3cb6fae978f19d966b02460d75 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -234,6 +234,18 @@
                         </para>
                     </listitem>
                 </varlistentry>
+                <varlistentry>
+                    <term>ipa_hbac_support_srchost (boolean)</term>
+                    <listitem>
+                        <para>
+                            If this is set to false, then srchost as given
+                            to SSSD by PAM will be ignored.
+                        </para>
+                        <para>
+                            Default: false
+                        </para>
+                    </listitem>
+                </varlistentry>
 
             </variablelist>
         </para>
diff --git a/src/providers/ipa/hbac_evaluator.c b/src/providers/ipa/hbac_evaluator.c
index 476ad6482a697a070102a60c1109a46f2f350af8..b0b97edd67683a792fa7c066e1e6fc01f361d871 100644
--- a/src/providers/ipa/hbac_evaluator.c
+++ b/src/providers/ipa/hbac_evaluator.c
@@ -221,14 +221,16 @@ enum hbac_eval_result_int hbac_evaluate_rule(struct hbac_rule *rule,
     }
 
     /* Check source hosts */
-    ret = hbac_evaluate_element(rule->srchosts,
-                                hbac_req->srchost,
-                                &matched);
-    if (ret != EOK) {
-        *error = HBAC_ERROR_UNPARSEABLE_RULE;
-        return HBAC_EVAL_MATCH_ERROR;
-    } else if (!matched) {
-        return HBAC_EVAL_UNMATCHED;
+    if (hbac_req->srchost) {
+        ret = hbac_evaluate_element(rule->srchosts,
+                                    hbac_req->srchost,
+                                    &matched);
+        if (ret != EOK) {
+            *error = HBAC_ERROR_UNPARSEABLE_RULE;
+            return HBAC_EVAL_MATCH_ERROR;
+        } else if (!matched) {
+            return HBAC_EVAL_UNMATCHED;
+        }
     }
     return HBAC_EVAL_MATCHED;
 }
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index 10f1cb7e6e2685b9dc6ac7f05ae53a37ebce345e..657e1169b6dc9539fbd28f9bae48931f8717875a 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -299,6 +299,10 @@ static int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx)
                                     hbac_ctx_be(hbac_ctx)->domain,
                                     sdap_id_op_handle(hbac_ctx->sdap_op),
                                     hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
+                                    dp_opt_get_bool(hbac_ctx->ipa_options,
+                                                    IPA_HBAC_SUPPORT_SRCHOST),
+                                    dp_opt_get_string(hbac_ctx->ipa_options,
+                                                      IPA_HOSTNAME),
                                     hbac_ctx->hbac_search_base);
     if (req == NULL) {
         DEBUG(1, ("Could not get host info\n"));
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 8f9d5d77955cb7b01bfac69fc4ba00b136f866f2..e361b276a769160d9d0ff50a47be819a079f641d 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -39,7 +39,8 @@ struct dp_option ipa_basic_opts[] = {
     { "ipa_hbac_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "ipa_hbac_refresh", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER },
-    { "ipa_hbac_treat_deny_as", DP_OPT_STRING, { "DENY_ALL" }, NULL_STRING }
+    { "ipa_hbac_treat_deny_as", DP_OPT_STRING, { "DENY_ALL" }, NULL_STRING },
+    { "ipa_hbac_support_srchost", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }
 };
 
 struct dp_option ipa_def_ldap_opts[] = {
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 40c5e53205285d761a43f6f0a77764006a5d79ca..65749216ca02ab761d057a10195dda28dbedd43a 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -52,6 +52,7 @@ enum ipa_basic_opt {
     IPA_KRB5_REALM,
     IPA_HBAC_REFRESH,
     IPA_HBAC_DENY_METHOD,
+    IPA_HBAC_SUPPORT_SRCHOST,
 
     IPA_OPTS_BASIC /* opts counter */
 };
diff --git a/src/providers/ipa/ipa_hbac_common.c b/src/providers/ipa/ipa_hbac_common.c
index 8815dae182e9352b321546158ebe535e443f2ab6..1be4d6b6660ad9db7fde3476cefa6526ac9dc17d 100644
--- a/src/providers/ipa/ipa_hbac_common.c
+++ b/src/providers/ipa/ipa_hbac_common.c
@@ -461,9 +461,13 @@ hbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
         rhost = pd->rhost;
     }
 
-    ret = hbac_eval_host_element(eval_req, sysdb, domain,
-                                 rhost, &eval_req->srchost);
-    if (ret != EOK) goto done;
+    if (dp_opt_get_bool(hbac_ctx->ipa_options, IPA_HBAC_SUPPORT_SRCHOST)) {
+        ret = hbac_eval_host_element(eval_req, sysdb, domain,
+                                     rhost, &eval_req->srchost);
+        if (ret != EOK) goto done;
+    } else {
+        eval_req->srchost = NULL;
+    }
 
     /* The target host is always the current machine */
     thost = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
diff --git a/src/providers/ipa/ipa_hbac_hosts.c b/src/providers/ipa/ipa_hbac_hosts.c
index 42a3f5c1b8946341abff1b5a5cafa8a07abfba3c..20bdc3af918d39c28b455ea7743ddaded9692fb7 100644
--- a/src/providers/ipa/ipa_hbac_hosts.c
+++ b/src/providers/ipa/ipa_hbac_hosts.c
@@ -34,12 +34,25 @@ struct ipa_hbac_host_state {
     const char *search_base;
     const char **attrs;
 
+    bool support_srchost;
+    const char *hostname;
+
     /* Return values */
     size_t host_count;
     struct sysdb_attrs **hosts;
 
     size_t hostgroup_count;
     struct sysdb_attrs **hostgroups;
+    struct sdap_attr_map_info *hostgroup_map;
+};
+
+#define HOSTGROUP_MAP_ATTRS_COUNT 5
+static struct sdap_attr_map hostgroup_map[] = {
+    {"objectclass", "ipahostgroup", "hostgroup", NULL},
+    {"name_attr", IPA_CN, IPA_CN, NULL},
+    {"member", IPA_MEMBER, IPA_MEMBER, NULL},
+    {"memberof", IPA_MEMBEROF, IPA_MEMBEROF, NULL},
+    {"ipa_id", IPA_UNIQUE_ID IPA_UNIQUE_ID, NULL}
 };
 
 static void
@@ -55,6 +68,8 @@ ipa_hbac_host_info_send(TALLOC_CTX *mem_ctx,
                         struct sss_domain_info *dom,
                         struct sdap_handle *sh,
                         struct sdap_options *opts,
+                        bool support_srchost,
+                        const char *hostname,
                         const char *search_base)
 {
     errno_t ret;
@@ -73,9 +88,20 @@ ipa_hbac_host_info_send(TALLOC_CTX *mem_ctx,
     state->dom = dom;
     state->sh = sh;
     state->opts = opts;
+    state->support_srchost = support_srchost;
+    state->hostname = hostname;
     state->search_base = search_base;
 
-    host_filter = talloc_asprintf(state, "(objectClass=%s)", IPA_HOST);
+    if (support_srchost) {
+        host_filter = talloc_asprintf(state, "(objectClass=%s)", IPA_HOST);
+    } else {
+        if (hostname == NULL) {
+            ret = EINVAL;
+            goto immediate;
+        }
+        host_filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=%s))",
+                                      IPA_HOST, IPA_HOST_FQDN, hostname);
+    }
     if (host_filter == NULL) {
         ret = ENOMEM;
         goto immediate;
@@ -129,6 +155,8 @@ ipa_hbac_host_info_done(struct tevent_req *subreq)
     struct ipa_hbac_host_state *state =
             tevent_req_data(req, struct ipa_hbac_host_state);
     char *hostgroup_filter;
+    const char *host_dn;
+    int i;
 
     ret = sdap_get_generic_recv(subreq, state,
                                 &state->host_count,
@@ -161,11 +189,46 @@ ipa_hbac_host_info_done(struct tevent_req *subreq)
     }
 
     /* Look up host groups */
-    subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
-                                   state->search_base, LDAP_SCOPE_SUB,
-                                   hostgroup_filter, state->attrs, NULL, 0,
-                                   dp_opt_get_int(state->opts->basic,
-                                                  SDAP_ENUM_SEARCH_TIMEOUT));
+    if (state->support_srchost) {
+        subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
+                                       state->search_base, LDAP_SCOPE_SUB,
+                                       hostgroup_filter, state->attrs, NULL, 0,
+                                       dp_opt_get_int(state->opts->basic,
+                                                      SDAP_ENUM_SEARCH_TIMEOUT));
+    } else {
+        state->hostgroup_map = talloc_zero(state, struct sdap_attr_map_info);
+        if (state->hostgroup_map == NULL) {
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+        state->hostgroup_map->map = hostgroup_map;
+        state->hostgroup_map->num_attrs = HOSTGROUP_MAP_ATTRS_COUNT;
+
+        ret = sysdb_attrs_get_string(state->hosts[0], SYSDB_ORIG_DN, &host_dn);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+
+        /* Complete the map */
+        for (i = 0; i < HOSTGROUP_MAP_ATTRS_COUNT; i++) {
+            /* These are allocated on the state, so the next time they'll
+             * have to be allocated again
+             */
+            hostgroup_map[i].name = talloc_strdup(state,
+                                                  hostgroup_map[i].def_name);
+            if (hostgroup_map[i].name == NULL) {
+                tevent_req_error(req, ret);
+                return;
+            }
+        }
+
+        subreq = sdap_deref_search_send(state, state->ev, state->opts, state->sh,
+                                        host_dn, IPA_MEMBEROF, state->attrs,
+                                        1, state->hostgroup_map,
+                                        dp_opt_get_int(state->opts->basic,
+                                                       SDAP_ENUM_SEARCH_TIMEOUT));
+    }
     if (subreq == NULL) {
         DEBUG(1, ("Error requesting host info\n"));
         tevent_req_error(req, EIO);
@@ -183,11 +246,45 @@ ipa_hbac_hostgroup_info_done(struct tevent_req *subreq)
     struct ipa_hbac_host_state *state =
             tevent_req_data(req, struct ipa_hbac_host_state);
 
-    ret = sdap_get_generic_recv(subreq, state,
-                                &state->hostgroup_count,
-                                &state->hostgroups);
-    talloc_zfree(subreq);
-    if (ret != EOK) goto done;
+    struct sdap_deref_attrs **deref_result;
+    const char *hostgroup_name;
+    int i;
+
+    if (state->support_srchost) {
+        ret = sdap_get_generic_recv(subreq, state,
+                                    &state->hostgroup_count,
+                                    &state->hostgroups);
+        talloc_zfree(subreq);
+        if (ret != EOK) goto done;
+    } else {
+        ret = sdap_deref_search_recv(subreq, state,
+                                     &state->hostgroup_count,
+                                     &deref_result);
+        talloc_zfree(subreq);
+        if (ret != EOK) goto done;
+
+        if (state->hostgroup_count == 0) {
+            DEBUG(SSSDBG_FUNC_DATA, ("No host groups were dereferenced\n"));
+        } else {
+            state->hostgroups = talloc_zero_array(state, struct sysdb_attrs *,
+                                                  state->hostgroup_count);
+            if (state->hostgroups == NULL) {
+                ret = ENOMEM;
+                goto done;
+            }
+
+            for (i = 0; i < state->hostgroup_count; i++) {
+                ret = sysdb_attrs_get_string(deref_result[i]->attrs,
+                                             IPA_CN, &hostgroup_name);
+                if (ret != EOK) goto done;
+
+                DEBUG(SSSDBG_FUNC_DATA, ("Dereferenced host group: %s\n",
+                                        hostgroup_name));
+                state->hostgroups[i] = talloc_steal(state->hostgroups,
+                                                    deref_result[i]->attrs);
+            }
+        }
+    }
 
     ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
                                  state->hostgroup_count,
diff --git a/src/providers/ipa/ipa_hbac_private.h b/src/providers/ipa/ipa_hbac_private.h
index 32b5d70ce8f648378cfbcb3edb36b958cf17f60f..d3d881bf1adae64943beee755abdbd9e0fc5dea7 100644
--- a/src/providers/ipa/ipa_hbac_private.h
+++ b/src/providers/ipa/ipa_hbac_private.h
@@ -106,6 +106,8 @@ ipa_hbac_host_info_send(TALLOC_CTX *mem_ctx,
                         struct sss_domain_info *dom,
                         struct sdap_handle *sh,
                         struct sdap_options *opts,
+                        bool support_srchost,
+                        const char *hostname,
                         const char *search_base);
 
 errno_t
-- 
1.7.6.4

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to