From 3b275b8e9840c91ed53609e5d1b22c08fcb3e30b Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@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

Convert deref searches to parallel searches
---
 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/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     |   3 +
 src/providers/ipa/ipa_hbac_hosts.c      | 427 ++++++++++++++++++++++++++++----
 src/providers/ipa/ipa_hbac_private.h    |   3 +
 9 files changed, 401 insertions(+), 54 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index b78d8e766f1af520a76b0124bf7e1ce5aea4b0bc..fea225d0d056502a30a20668c9db46c399b26075 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 543262d5841e0990560a4cd7e531a7494bb2c77f..e79919066d1b37dab080a516f1060974d34244da 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -103,6 +103,7 @@ krb5_use_fast = 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 01d116df7f20e4504d6c6bebf02bcbeee1ddb124..c754313c62edb04dff0c9e4e0e00d3a47bebb9d0 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -222,6 +222,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/ipa_access.c b/src/providers/ipa/ipa_access.c
index 7232c5355fb36e9cb312630797ab2d25d4969300..be7f954d26c93f9d3aa9ab7e1e90a6fb8c61d801 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -355,6 +355,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 b59c2b1c537572ff7d3b0c1703bbeb7f24a6bd92..bf0018c80452a0c71825058dff332757d6e0b410 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -38,7 +38,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 2ace8a58451d44db817b107a5e213d42ea1274bf..0bfe054b4bb2be163ae52797409a1c2531035579 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 e362606e9c7cc92b2dc2f4a53fabc45a3265caf5..265b35f165e623058ceb81a28726486416a43172 100644
--- a/src/providers/ipa/ipa_hbac_common.c
+++ b/src/providers/ipa/ipa_hbac_common.c
@@ -346,11 +346,14 @@ hbac_attrs_to_rule(TALLOC_CTX *mem_ctx,
     }
 
     /* Get the source hosts */
+
     ret = hbac_shost_attrs_to_rule(new_rule,
                                    hbac_ctx_sysdb(hbac_ctx),
                                    hbac_ctx_be(hbac_ctx)->domain,
                                    new_rule->name,
                                    hbac_ctx->rules[idx],
+                                   dp_opt_get_bool(hbac_ctx->ipa_options,
+                                                   IPA_HBAC_SUPPORT_SRCHOST),
                                    &new_rule->srchosts);
     if (ret != EOK) {
         DEBUG(1, ("Could not parse source hosts for rule [%s]\n",
diff --git a/src/providers/ipa/ipa_hbac_hosts.c b/src/providers/ipa/ipa_hbac_hosts.c
index aff8766e1bb3cc72ec879ec3771888e9c3914519..0896fb6f00d3f4d50574c5099469ad7fddde5b36 100644
--- a/src/providers/ipa/ipa_hbac_hosts.c
+++ b/src/providers/ipa/ipa_hbac_hosts.c
@@ -34,6 +34,9 @@ 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;
@@ -42,6 +45,15 @@ struct ipa_hbac_host_state {
     struct sysdb_attrs **hostgroups;
 };
 
+#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, SYSDB_ORIG_MEMBER, NULL},
+    {"memberof", IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF, NULL},
+    {"ipa_id", IPA_UNIQUE_ID, IPA_UNIQUE_ID, NULL}
+};
+
 static void
 ipa_hbac_host_info_done(struct tevent_req *subreq);
 
@@ -55,6 +67,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 +87,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;
@@ -120,6 +145,20 @@ immediate:
     return req;
 }
 
+static errno_t
+ipa_hbac_get_hostgroups_recv(struct tevent_req *subreq,
+                             TALLOC_CTX *mem_ctx,
+                             size_t *count,
+                             struct sysdb_attrs ***parents);
+
+static struct tevent_req *
+ipa_hbac_get_hostgroups_send(TALLOC_CTX *mem_ctx,
+                             struct tevent_context *ev,
+                             struct sdap_options *opts,
+                             struct sdap_handle *sh,
+                             size_t queue_len,
+                             char **queued_parents);
+
 static void
 ipa_hbac_host_info_done(struct tevent_req *subreq)
 {
@@ -129,49 +168,320 @@ 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 *parent_dn;
+    struct ldb_message_element *parent_el;
+    char **queued_parents;
+    size_t queue_len;
+    int i;
 
     ret = sdap_get_generic_recv(subreq, state,
                                 &state->host_count,
                                 &state->hosts);
     talloc_zfree(subreq);
-    if (ret != EOK) {
-        tevent_req_error(req, ret);
-        return;
-    }
+    if (ret != EOK) goto error;
 
-    if (state->host_count == 0) {
-        tevent_req_error(req, ENOENT);
-        return;
-    }
+    if (state->host_count == 0) goto error;
 
     ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
                                  state->host_count,
                                  state->hosts);
     if (ret != EOK) {
         DEBUG(1, ("Could not replace attribute names\n"));
-        tevent_req_error(req, ret);
-        return;
+        goto error;
     }
 
-    hostgroup_filter = talloc_asprintf(state, "(objectClass=%s)",
-                                              IPA_HOSTGROUP);
-    if (hostgroup_filter == NULL) {
-        tevent_req_error(req, ENOMEM);
-        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) goto error;
     }
 
     /* 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 (subreq == NULL) {
-        DEBUG(1, ("Error requesting host info\n"));
-        tevent_req_error(req, EIO);
+    if (state->support_srchost) {
+        hostgroup_filter = talloc_asprintf(state, "(objectClass=%s)",
+                                                  IPA_HOSTGROUP);
+        if (hostgroup_filter == NULL) goto error;
+
+        subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
+                                       state->search_base, LDAP_SCOPE_SUB,
+                                       hostgroup_filter, state->attrs, hostgroup_map,
+                                       HOSTGROUP_MAP_ATTRS_COUNT,
+                                       dp_opt_get_int(state->opts->basic,
+                                                      SDAP_ENUM_SEARCH_TIMEOUT));
+        if (subreq == NULL) {
+            DEBUG(1, ("Error requesting host info\n"));
+            goto error;
+        }
+        tevent_req_set_callback(subreq, ipa_hbac_hostgroup_info_done, req);
         return;
     }
+
+    /* Source host processing is disabled */
+
+    ret = sysdb_attrs_get_el(state->hosts[0],
+                             SYSDB_ORIG_MEMBEROF,
+                             &parent_el);
+    if (ret != EOK) goto error;
+
+    /* Iterate through the memberOf DNs and retrieve
+     * the hostgroup entries in parallel
+     */
+
+    /* We'll assume that all parents are hostgroups for efficiency */
+    queued_parents = talloc_array(state, char *,
+                                  parent_el->num_values);
+    if (!queued_parents) {
+        ret = ENOMEM;
+        goto error;
+    }
+    queue_len = 0;
+
+    for (i=0; i < parent_el->num_values; i++) {
+        parent_dn = (char *)parent_el->values[i].data;
+
+        ret = get_ipa_hostgroupname(NULL, state->sysdb, parent_dn, NULL);
+        if (ret == ENOENT) {
+            /* Skip this entry, it's not a hostgroup */
+            continue;
+        } else if (ret != EOK) goto error;
+
+        /* Enqueue this hostgroup for lookup */
+        queued_parents[queue_len] =
+                talloc_strdup(queued_parents, parent_dn);
+        if (!queued_parents[queue_len]) {
+            ret = ENOMEM;
+            goto error;
+        }
+        queue_len++;
+    }
+
+    subreq = ipa_hbac_get_hostgroups_send(state,
+                                          state->ev,
+                                          state->opts,
+                                          state->sh,
+                                          queue_len,
+                                          queued_parents);
+    if (!subreq) {
+        ret = ENOMEM;
+        goto error;
+    }
+
     tevent_req_set_callback(subreq, ipa_hbac_hostgroup_info_done, req);
+    return;
+
+error:
+    DEBUG(3, ("Error: [%s]\n", strerror(ret)));
+    tevent_req_error(req, ret);
+}
+
+#define HOSTGROUP_REQ_PARALLEL 50
+
+struct ipa_hbac_get_hostgroups_state {
+    struct tevent_context *ev;
+    struct sdap_options *opts;
+    struct sdap_handle *sh;
+
+    const char **attrs;
+
+    char **queued_parents;
+    size_t queue_len;
+    size_t queue_iter;
+    size_t running;
+
+    /* Results */
+    struct sysdb_attrs **parents;
+    size_t parent_count;
+};
+
+static void
+ipa_hbac_get_hostgroups_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+ipa_hbac_get_hostgroups_send(TALLOC_CTX *mem_ctx,
+                             struct tevent_context *ev,
+                             struct sdap_options *opts,
+                             struct sdap_handle *sh,
+                             size_t queue_len,
+                             char **queued_parents)
+{
+    errno_t ret;
+    struct tevent_req *req;
+    struct tevent_req *subreq;
+    struct ipa_hbac_get_hostgroups_state *state;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct ipa_hbac_get_hostgroups_state);
+    if (!req) return NULL;
+
+    if (queue_len == 0) {
+        /* This host is not in any hostgroups */
+        ret = ENOMEM;
+        goto error;
+    }
+
+    state->ev = ev;
+    state->opts = opts;
+    state->sh = sh;
+
+    state->queued_parents = queued_parents;
+    state->queue_len = queue_len;
+    state->queue_iter = 0;
+    state->running = 0;
+
+    state->attrs = talloc_array(state, const char *, 6);
+    if (state->attrs == NULL) {
+        DEBUG(1, ("Failed to allocate hostgroup attribute list.\n"));
+        ret = ENOMEM;
+        goto error;
+    }
+    state->attrs[0] = "objectClass";
+    state->attrs[1] = IPA_UNIQUE_ID;
+    state->attrs[2] = IPA_MEMBER;
+    state->attrs[3] = IPA_MEMBEROF;
+    state->attrs[4] = IPA_CN;
+    state->attrs[5] = NULL;
+
+    /* Pre-create the result array assuming that all values
+     * return results (which they should, since FreeIPA is
+     * memberOf-guaranteed.
+     */
+    state->parents = talloc_array(state, struct sysdb_attrs *,
+                                  state->queue_len);
+    if (!state->parents) {
+        ret = ENOMEM;
+        goto error;
+    }
+    state->parent_count = 0;
+
+    /* Process the parents in parallel */
+    while (state->queue_iter < state->queue_len
+            && state->running < HOSTGROUP_REQ_PARALLEL) {
+        subreq = sdap_get_generic_send(
+                    state, state->ev, state->opts, state->sh,
+                    state->queued_parents[state->queue_iter],
+                    LDAP_SCOPE_BASE, NULL, state->attrs,
+                    hostgroup_map, HOSTGROUP_MAP_ATTRS_COUNT,
+                    dp_opt_get_int(state->opts->basic,
+                                   SDAP_ENUM_SEARCH_TIMEOUT));
+        if (!subreq) {
+            ret = ENOMEM;
+            goto error;
+        }
+        tevent_req_set_callback(subreq, ipa_hbac_get_hostgroups_done, req);
+        state->queue_iter++;
+        state->running++;
+    }
+
+    return req;
+
+error:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static void
+ipa_hbac_get_hostgroups_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req =
+            tevent_req_callback_data(subreq, struct tevent_req);
+    struct ipa_hbac_get_hostgroups_state *state =
+            tevent_req_data(req, struct ipa_hbac_get_hostgroups_state);
+    size_t count;
+    struct sysdb_attrs **hostgroup_attrs = NULL;
+
+    /* Get the results and add them to the result array */
+    state->running--;
+
+    ret = sdap_get_generic_recv(subreq, NULL, &count, &hostgroup_attrs);
+    talloc_zfree(subreq);
+    if (ret != EOK || count != 1) {
+        /* We got an error retrieving the host group.
+         * We'll log it and continue. The worst-case
+         * here is that we'll deny too aggressively.
+         */
+        if (ret == EOK) {
+            /* We got back something other than a single entry on a
+             * base search?
+             */
+            ret = ENOENT;
+        }
+
+        DEBUG(1, ("Error [%s] while processing hostgroups. Skipping.\n",
+                  strerror(ret)));
+        goto next;
+    }
+
+    /* Add this hostgroup to the array */
+    state->parents[state->parent_count] =
+            talloc_steal(state->parents, hostgroup_attrs[0]);
+    state->parent_count++;
+
+next:
+    /* Check if there are more hostgroups to process */
+    if (state->queue_iter < state->queue_len) {
+        subreq = sdap_get_generic_send(
+                    state, state->ev, state->opts, state->sh,
+                    state->queued_parents[state->queue_iter],
+                    LDAP_SCOPE_BASE, NULL, state->attrs,
+                    hostgroup_map, HOSTGROUP_MAP_ATTRS_COUNT,
+                    dp_opt_get_int(state->opts->basic,
+                                   SDAP_ENUM_SEARCH_TIMEOUT));
+        if (!subreq) {
+            ret = ENOMEM;
+            goto done;
+        }
+        tevent_req_set_callback(subreq, ipa_hbac_get_hostgroups_done, req);
+        state->queue_iter++;
+        state->running++;
+    }
+
+    /* Continue processing until all parallel searches have
+     * completed successfully.
+     */
+    if (state->running != 0) {
+        /* There are still pending parallel requests.
+         * Re-enter the mainloop.
+         */
+        talloc_free(hostgroup_attrs);
+        return;
+    }
+
+    /* All searches are complete. Return the results */
+    ret = EOK;
+
+done:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        DEBUG(3, ("Error [%d][%s]\n", ret, strerror(ret)));
+        tevent_req_error(req, ret);
+    }
+
+    talloc_free(hostgroup_attrs);
+    return;
+}
+
+static errno_t
+ipa_hbac_get_hostgroups_recv(struct tevent_req *req,
+                             TALLOC_CTX *mem_ctx,
+                             size_t *reply_count,
+                             struct sysdb_attrs ***parents)
+{
+    struct ipa_hbac_get_hostgroups_state *state =
+            tevent_req_data(req, struct ipa_hbac_get_hostgroups_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *reply_count = state->parent_count;
+    *parents = talloc_steal(mem_ctx, state->parents);
+
+    return EOK;
 }
 
 static void
@@ -183,29 +493,17 @@ 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);
+    if (state->support_srchost) {
+        ret = sdap_get_generic_recv(subreq, state,
+                                    &state->hostgroup_count,
+                                    &state->hostgroups);
+    } else {
+        ret = ipa_hbac_get_hostgroups_recv(subreq, state,
+                                           &state->hostgroup_count,
+                                           &state->hostgroups);
+    }
     talloc_zfree(subreq);
-    if (ret != EOK) goto done;
 
-    ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
-                                 state->hostgroup_count,
-                                 state->hostgroups);
-    if (ret != EOK) {
-        DEBUG(1, ("Could not replace attribute names\n"));
-        goto done;
-    }
-
-    ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
-                                 state->hostgroup_count,
-                                 state->hostgroups);
-    if (ret != EOK) {
-        DEBUG(1, ("Could not replace attribute names\n"));
-        goto done;
-    }
-
-done:
     if (ret == EOK) {
         tevent_req_done(req);
     } else {
@@ -460,17 +758,34 @@ hbac_shost_attrs_to_rule(TALLOC_CTX *mem_ctx,
                          struct sss_domain_info *domain,
                          const char *rule_name,
                          struct sysdb_attrs *rule_attrs,
+                         bool support_srchost,
                          struct hbac_rule_element **source_hosts)
 {
     errno_t ret;
     size_t host_count;
-    TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+    TALLOC_CTX *tmp_ctx;
     size_t idx;
     struct ldb_message_element *el;
     struct hbac_rule_element *shosts;
 
+    tmp_ctx = talloc_new(mem_ctx);
+    if (tmp_ctx == NULL) return ENOMEM;
+
     DEBUG(7, ("Processing source hosts for rule [%s]\n", rule_name));
 
+    if (!support_srchost) {
+        DEBUG(8, ("Source hosts disabled, setting ALL\n"));
+        shosts = talloc_zero(tmp_ctx, struct hbac_rule_element);
+        if (shosts == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        shosts->category = HBAC_CATEGORY_ALL;
+        ret = EOK;
+        goto done;
+    }
+
     ret = hbac_host_attrs_to_rule(tmp_ctx, sysdb, domain,
                                   rule_name, rule_attrs,
                                   IPA_SOURCE_HOST_CATEGORY, IPA_SOURCE_HOST,
@@ -543,7 +858,10 @@ get_ipa_hostgroupname(TALLOC_CTX *mem_ctx,
      * be changed if SSSD ever supports HBAC on
      * a non-IPA server.
      */
-    *hostgroupname = NULL;
+
+    if (hostgroupname) {
+        *hostgroupname = NULL;
+    }
 
     dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), host_dn);
     if (dn == NULL) {
@@ -617,12 +935,15 @@ get_ipa_hostgroupname(TALLOC_CTX *mem_ctx,
 
     /* Then the value of the RDN is the group name */
     rdn_val = ldb_dn_get_rdn_val(dn);
-    *hostgroupname = talloc_strndup(mem_ctx,
-                                    (const char *)rdn_val->data,
-                                    rdn_val->length);
-    if (*hostgroupname == NULL) {
-        ret = ENOMEM;
-        goto done;
+
+    if (hostgroupname) {
+        *hostgroupname = talloc_strndup(mem_ctx,
+                                        (const char *)rdn_val->data,
+                                        rdn_val->length);
+        if (*hostgroupname == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
     }
 
     ret = EOK;
diff --git a/src/providers/ipa/ipa_hbac_private.h b/src/providers/ipa/ipa_hbac_private.h
index 32b5d70ce8f648378cfbcb3edb36b958cf17f60f..65488a2833557be1e710978687ffe4e6458ccc41 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
@@ -130,6 +132,7 @@ hbac_shost_attrs_to_rule(TALLOC_CTX *mem_ctx,
                          struct sss_domain_info *domain,
                          const char *rule_name,
                          struct sysdb_attrs *rule_attrs,
+                         bool support_srchost,
                          struct hbac_rule_element **source_hosts);
 errno_t
 get_ipa_hostgroupname(TALLOC_CTX *mem_ctx,
-- 
1.7.11.2

