URL: https://github.com/SSSD/sssd/pull/237
Author: hvenev
 Title: #237: providers: Move hostid from ipa to sdap
Action: opened

PR body:
"""
This just makes sss_ssh_knownhostsproxy work. There is no support for 
hostgroups (although hostgroups in `ipa` should continue working).

I've been using this for a few days with the `ldap` and `krb5` providers and I 
haven't noticed any regressions. I haven't tested `ipa` and `ad` but all tests 
seem to pass.
"""

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/237/head:pr237
git checkout pr237
From 9c64cf9f0595925986aad64424f47a9a4d092b2f Mon Sep 17 00:00:00 2001
From: Hristo Venev <hri...@venev.name>
Date: Tue, 11 Apr 2017 13:43:53 +0300
Subject: [PATCH] providers: Move hostid from ipa to sdap

In the ldap provider, all option names are renamed to ldap_host_*. In
the ipa provider the names are still ipa_host_*.

Hostgroups are disabled in the ldap provider. sss_ssh_knownhostsproxy
works.

For now, there is no struct sdap_hostid_ctx as all information is
contained in struct sdap_id_ctx. There is no struct ipa_hostid_ctx
either.

I've also added some documentation for the ldap provider.
---
 Makefile.am                             |   9 +-
 src/man/sssd-ipa.5.xml                  |  20 +-
 src/man/sssd-ldap.5.xml                 | 109 ++++++++
 src/providers/ad/ad_opts.c              |   1 +
 src/providers/ipa/ipa_access.c          |  15 +-
 src/providers/ipa/ipa_common.c          |  37 +--
 src/providers/ipa/ipa_common.h          |  31 +--
 src/providers/ipa/ipa_hostid.c          | 301 +--------------------
 src/providers/ipa/ipa_hostid.h          |  42 ---
 src/providers/ipa/ipa_hosts.c           | 457 -------------------------------
 src/providers/ipa/ipa_hosts.h           |  44 ---
 src/providers/ipa/ipa_init.c            |  26 +-
 src/providers/ipa/ipa_netgroups.c       |  14 +-
 src/providers/ipa/ipa_opts.c            |   1 +
 src/providers/ipa/ipa_selinux.c         |  19 +-
 src/providers/ipa/ipa_subdomains.c      |   9 +-
 src/providers/ipa/ipa_sudo_async.c      |  20 +-
 src/providers/ipa/ipa_sudo_conversion.c |   4 +-
 src/providers/ldap/ldap_init.c          |  21 ++
 src/providers/ldap/ldap_options.c       |  26 ++
 src/providers/ldap/ldap_opts.c          |  12 +
 src/providers/ldap/ldap_opts.h          |   4 +
 src/providers/ldap/sdap.c               |  12 +
 src/providers/ldap/sdap.h               |  25 ++
 src/providers/ldap/sdap_async.h         |  18 ++
 src/providers/ldap/sdap_async_hosts.c   | 459 ++++++++++++++++++++++++++++++++
 src/providers/ldap/sdap_hostid.c        | 325 ++++++++++++++++++++++
 src/providers/ldap/sdap_hostid.h        |  41 +++
 src/tests/ipa_ldap_opt-tests.c          |   4 +-
 29 files changed, 1146 insertions(+), 960 deletions(-)
 delete mode 100644 src/providers/ipa/ipa_hostid.h
 delete mode 100644 src/providers/ipa/ipa_hosts.c
 delete mode 100644 src/providers/ipa/ipa_hosts.h
 create mode 100644 src/providers/ldap/sdap_async_hosts.c
 create mode 100644 src/providers/ldap/sdap_hostid.c
 create mode 100644 src/providers/ldap/sdap_hostid.h

diff --git a/Makefile.am b/Makefile.am
index c947e31..b5ba22e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -791,13 +791,11 @@ dist_noinst_HEADERS = \
     src/providers/ipa/ipa_config.h \
     src/providers/ipa/ipa_access.h \
     src/providers/ipa/ipa_selinux.h \
-    src/providers/ipa/ipa_hosts.h \
     src/providers/ipa/ipa_selinux_maps.h \
     src/providers/ipa/ipa_auth.h \
     src/providers/ipa/ipa_dyndns.h \
     src/providers/ipa/ipa_subdomains.h \
     src/providers/ipa/ipa_id.h \
-    src/providers/ipa/ipa_hostid.h \
     src/providers/ipa/ipa_opts.h \
     src/providers/ipa/ipa_srv.h \
     src/providers/ipa/ipa_dn.h \
@@ -3682,11 +3680,13 @@ libsss_ldap_common_la_SOURCES = \
     src/providers/ldap/sdap_async_initgroups_ad.c \
     src/providers/ldap/sdap_async_connection.c \
     src/providers/ldap/sdap_async_netgroups.c \
+    src/providers/ldap/sdap_async_hosts.c \
     src/providers/ldap/sdap_async_services.c \
     src/providers/ldap/sdap_online_check.c \
     src/providers/ldap/sdap_ad_groups.c \
     src/providers/ldap/sdap_child_helpers.c \
     src/providers/ldap/sdap_fd_events.c \
+    src/providers/ldap/sdap_hostid.h \
     src/providers/ldap/sdap_id_op.c \
     src/providers/ldap/sdap_idmap.c \
     src/providers/ldap/sdap_idmap.h \
@@ -3721,6 +3721,10 @@ if BUILD_SYSTEMTAP
 libsss_ldap_common_la_LIBADD += stap_generated_probes.lo
 endif
 
+if BUILD_SSH
+libsss_ldap_common_la_SOURCES += src/providers/ldap/sdap_hostid.c
+endif
+
 if BUILD_SUDO
 libsss_ldap_common_la_SOURCES += \
     src/providers/ldap/sdap_async_sudo.c \
@@ -3846,7 +3850,6 @@ libsss_ipa_la_SOURCES = \
     src/providers/ipa/ipa_auth.c \
     src/providers/ipa/ipa_access.c \
     src/providers/ipa/ipa_dyndns.c \
-    src/providers/ipa/ipa_hosts.c \
     src/providers/ipa/ipa_subdomains.c \
     src/providers/ipa/ipa_subdomains_id.c \
     src/providers/ipa/ipa_subdomains_server.c \
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index fee6441..de768b6 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -307,33 +307,23 @@
                 </varlistentry>
 
                 <varlistentry>
-                    <term>ipa_hbac_search_base (string)</term>
+                    <term>ipa_host_search_base (string)</term>
                     <listitem>
                         <para>
-                            Optional. Use the given string as search base for
-                            HBAC related objects.
-                        </para>
-                        <para>
-                            Default: Use base DN
+                            Deprecated. Use ldap_host_search_base instead.
                         </para>
                     </listitem>
                 </varlistentry>
 
                 <varlistentry>
-                    <term>ipa_host_search_base (string)</term>
+                    <term>ipa_hbac_search_base (string)</term>
                     <listitem>
                         <para>
                             Optional. Use the given string as search base for
-                            host objects.
-                        </para>
-                        <para>
-                            See <quote>ldap_search_base</quote> for
-                            information about configuring multiple search
-                            bases.
+                            HBAC related objects.
                         </para>
                         <para>
-                            Default: the value of
-                            <emphasis>ldap_search_base</emphasis>
+                            Default: Use base DN
                         </para>
                     </listitem>
                 </varlistentry>
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index fae669a..b47a664 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1177,6 +1177,115 @@
                 </varlistentry>
 
                 <varlistentry>
+                    <term>ldap_host_object_class (string)</term>
+                    <listitem>
+                        <para>
+                            The object class of a host entry in LDAP.
+                        </para>
+                        <para>
+                            Default: ipService
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_name (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that corresponds to the host's
+                            name.
+                        </para>
+                        <para>
+                            Default: cn
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_fqdn (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that corresponds to the host's
+                            fully-qualified domain name.
+                        </para>
+                        <para>
+                            Default: fqdn
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_serverhostname (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that corresponds to the host's
+                            name.
+                        </para>
+                        <para>
+                            Default: serverHostname
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_member_of (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that lists the host's group
+                            memberships.
+                        </para>
+                        <para>
+                            Default: memberOf
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_search_base (string)</term>
+                    <listitem>
+                        <para>
+                            Optional. Use the given string as search base for
+                            host objects.
+                        </para>
+                        <para>
+                            See <quote>ldap_search_base</quote> for
+                            information about configuring multiple search
+                            bases.
+                        </para>
+                        <para>
+                            Default: the value of
+                            <emphasis>ldap_search_base</emphasis>
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry condition="with_ssh">
+                    <term>ldap_host_ssh_public_key (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that contains the host's SSH
+                            public keys.
+                        </para>
+                        <para>
+                            Default: sshPublicKey
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>ldap_host_uuid (string)</term>
+                    <listitem>
+                        <para>
+                            The LDAP attribute that contains the UUID/GUID of
+                            an LDAP host object.
+                        </para>
+                        <para>
+                            Default: not set
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
                     <term>ldap_service_object_class (string)</term>
                     <listitem>
                         <para>
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index fc1dc67..3980aba 100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -72,6 +72,7 @@ struct dp_option ad_def_ldap_opts[] = {
     { "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
     { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_service_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER }, /* 360 mins */
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index bebb47b..4dda0a4 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -30,7 +30,6 @@
 #include "providers/ldap/sdap_access.h"
 #include "providers/ipa/ipa_common.h"
 #include "providers/ipa/ipa_access.h"
-#include "providers/ipa/ipa_hosts.h"
 #include "providers/ipa/ipa_hbac_private.h"
 #include "providers/ipa/ipa_hbac_rules.h"
 
@@ -273,12 +272,12 @@ static errno_t ipa_fetch_hbac_hostinfo(struct tevent_req *req)
         hostname = dp_opt_get_string(state->ipa_options, IPA_HOSTNAME);
     }
 
-    subreq = ipa_host_info_send(state, state->ev,
-                                sdap_id_op_handle(state->sdap_op),
-                                state->sdap_ctx->opts, hostname,
-                                state->access_ctx->host_map,
-                                state->access_ctx->hostgroup_map,
-                                state->access_ctx->host_search_bases);
+    subreq = sdap_host_info_send(state, state->ev,
+                                 sdap_id_op_handle(state->sdap_op),
+                                 state->sdap_ctx->opts, hostname,
+                                 state->access_ctx->host_map,
+                                 state->access_ctx->hostgroup_map,
+                                 state->access_ctx->host_search_bases);
     if (subreq == NULL) {
         return ENOMEM;
     }
@@ -297,7 +296,7 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq)
     req = tevent_req_callback_data(subreq, struct tevent_req);
     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
 
-    ret = ipa_host_info_recv(subreq, state,
+    ret = sdap_host_info_recv(subreq, state,
                              &state->host_count, &state->hosts,
                              &state->hostgroup_count, &state->hostgroups);
     talloc_zfree(subreq);
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 6579945..b020329 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -134,9 +134,6 @@ static errno_t ipa_parse_search_base(TALLOC_CTX *mem_ctx,
     case IPA_HBAC_SEARCH_BASE:
         class_name = "IPA_HBAC";
         break;
-    case IPA_HOST_SEARCH_BASE:
-        class_name = "IPA_HOST";
-        break;
     case IPA_SELINUX_SEARCH_BASE:
         class_name = "IPA_SELINUX";
         break;
@@ -333,23 +330,27 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
                                  &ipa_opts->id->sdom->netgroup_search_bases);
     if (ret != EOK) goto done;
 
-    if (NULL == dp_opt_get_string(ipa_opts->basic,
-                                  IPA_HOST_SEARCH_BASE)) {
-        ret = dp_opt_set_string(ipa_opts->basic, IPA_HOST_SEARCH_BASE,
-                                dp_opt_get_string(ipa_opts->id->basic,
-                                                  SDAP_SEARCH_BASE));
+    if (NULL == dp_opt_get_string(ipa_opts->id->basic,
+                                  SDAP_HOST_SEARCH_BASE)) {
+
+        value = dp_opt_get_string(ipa_opts->basic, IPA_HOST_SEARCH_BASE);
+        if (!value) {
+            value = dp_opt_get_string(ipa_opts->id->basic, SDAP_SEARCH_BASE);
+        }
+
+        ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_HOST_SEARCH_BASE,
+                                value);
         if (ret != EOK) {
             goto done;
         }
 
         DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
-                  ipa_opts->basic[IPA_HOST_SEARCH_BASE].opt_name,
-                  dp_opt_get_string(ipa_opts->basic,
-                                    IPA_HOST_SEARCH_BASE));
+              ipa_opts->id->basic[SDAP_HOST_SEARCH_BASE].opt_name,
+              value);
     }
-    ret = ipa_parse_search_base(ipa_opts->basic, ipa_opts->basic,
-                                IPA_HOST_SEARCH_BASE,
-                                &ipa_opts->host_search_bases);
+    ret = sdap_parse_search_base(ipa_opts->id->basic, ipa_opts->id->basic,
+                                SDAP_HOST_SEARCH_BASE,
+                                &ipa_opts->id->sdom->host_search_bases);
     if (ret != EOK) goto done;
 
     if (NULL == dp_opt_get_string(ipa_opts->basic,
@@ -566,8 +567,8 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
     ret = sdap_get_map(ipa_opts->id,
                        cdb, conf_path,
                        ipa_host_map,
-                       IPA_OPTS_HOST,
-                       &ipa_opts->host_map);
+                       SDAP_OPTS_HOST,
+                       &ipa_opts->id->host_map);
     if (ret != EOK) {
         goto done;
     }
@@ -575,8 +576,8 @@ int ipa_get_id_options(struct ipa_options *ipa_opts,
     ret = sdap_get_map(ipa_opts->id,
                        cdb, conf_path,
                        ipa_hostgroup_map,
-                       IPA_OPTS_HOSTGROUP,
-                       &ipa_opts->hostgroup_map);
+                       SDAP_OPTS_HOSTGROUP,
+                       &ipa_opts->id->hostgroup_map);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index add9df8..2b0147a 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -41,8 +41,8 @@ enum ipa_basic_opt {
     IPA_SERVER,
     IPA_BACKUP_SERVER,
     IPA_HOSTNAME,
+    IPA_HOST_SEARCH_BASE, /* only used if ldap_host_search_base is not set */
     IPA_HBAC_SEARCH_BASE,
-    IPA_HOST_SEARCH_BASE,
     IPA_SELINUX_SEARCH_BASE,
     IPA_SUBDOMAINS_SEARCH_BASE,
     IPA_MASTER_DOMAIN_SEARCH_BASE,
@@ -74,27 +74,6 @@ enum ipa_netgroup_attrs {
     IPA_OPTS_NETGROUP /* attrs counter */
 };
 
-enum ipa_host_attrs {
-    IPA_OC_HOST = 0,
-    IPA_AT_HOST_NAME,
-    IPA_AT_HOST_FQDN,
-    IPA_AT_HOST_SERVERHOSTNAME,
-    IPA_AT_HOST_MEMBER_OF,
-    IPA_AT_HOST_SSH_PUBLIC_KEY,
-    IPA_AT_HOST_UUID,
-
-    IPA_OPTS_HOST /* attrs counter */
-};
-
-enum ipa_hostgroup_attrs {
-    IPA_OC_HOSTGROUP = 0,
-    IPA_AT_HOSTGROUP_NAME,
-    IPA_AT_HOSTGROUP_MEMBER_OF,
-    IPA_AT_HOSTGROUP_UUID,
-
-    IPA_OPTS_HOSTGROUP /* attrs counter */
-};
-
 enum ipa_selinux_usermap_attrs {
     IPA_OC_SELINUX_USERMAP = 0,
     IPA_AT_SELINUX_USERMAP_NAME,
@@ -205,13 +184,10 @@ struct ipa_id_ctx {
 struct ipa_options {
     struct dp_option *basic;
 
-    struct sdap_attr_map *host_map;
-    struct sdap_attr_map *hostgroup_map;
     struct sdap_attr_map *selinuxuser_map;
     struct sdap_attr_map *view_map;
     struct sdap_attr_map *override_map;
 
-    struct sdap_search_base **host_search_bases;
     struct sdap_search_base **hbac_search_bases;
     struct sdap_search_base **selinux_search_bases;
     struct sdap_search_base **subdomains_search_bases;
@@ -260,6 +236,11 @@ int ipa_get_autofs_options(struct ipa_options *ipa_opts,
 errno_t ipa_get_dyndns_options(struct be_ctx *be_ctx,
                                struct ipa_options *ctx);
 
+errno_t ipa_hostid_init(TALLOC_CTX *mem_ctx,
+                        struct be_ctx *be_ctx,
+                        struct ipa_id_ctx *id_ctx,
+                        struct dp_method *dp_methods);
+
 errno_t ipa_autofs_init(TALLOC_CTX *mem_ctx,
                         struct be_ctx *be_ctx,
                         struct ipa_id_ctx *id_ctx,
diff --git a/src/providers/ipa/ipa_hostid.c b/src/providers/ipa/ipa_hostid.c
index 87a3616..891536f 100644
--- a/src/providers/ipa/ipa_hostid.c
+++ b/src/providers/ipa/ipa_hostid.c
@@ -1,8 +1,8 @@
 /*
     Authors:
-        Jan Cholasta <jchol...@redhat.com>
+        Hristo Venev <hri...@venev.name>
 
-    Copyright (C) 2012 Red Hat
+    Copyright (C) 2017 Red Hat
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -18,298 +18,13 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "util/util.h"
-#include "util/crypto/sss_crypto.h"
-#include "db/sysdb_ssh.h"
-#include "providers/ldap/ldap_common.h"
 #include "providers/ipa/ipa_common.h"
-#include "providers/ipa/ipa_hostid.h"
-#include "providers/ipa/ipa_hosts.h"
+#include "providers/ldap/sdap_hostid.h"
 
-struct hosts_get_state {
-    struct tevent_context *ev;
-    struct ipa_hostid_ctx *ctx;
-    struct sdap_id_op *op;
-    struct sss_domain_info *domain;
-    const char *name;
-    const char *alias;
-
-    size_t count;
-    struct sysdb_attrs **hosts;
-    int dp_error;
-};
-
-static errno_t
-hosts_get_retry(struct tevent_req *req);
-static void
-hosts_get_connect_done(struct tevent_req *subreq);
-static void
-hosts_get_done(struct tevent_req *subreq);
-
-struct tevent_req *
-hosts_get_send(TALLOC_CTX *memctx,
-               struct tevent_context *ev,
-               struct ipa_hostid_ctx *hostid_ctx,
-               const char *name,
-               const char *alias)
-{
-    struct tevent_req *req;
-    struct hosts_get_state *state;
-    struct sdap_id_ctx *ctx;
-    errno_t ret;
-
-    ctx = hostid_ctx->sdap_id_ctx;
-
-    req = tevent_req_create(memctx, &state, struct hosts_get_state);
-    if (!req) return NULL;
-
-    state->ev = ev;
-    state->ctx = hostid_ctx;
-    state->dp_error = DP_ERR_FATAL;
-
-    state->op = sdap_id_op_create(state, ctx->conn->conn_cache);
-    if (!state->op) {
-        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
-        ret = ENOMEM;
-        goto fail;
-    }
-
-    state->domain = ctx->be->domain;
-    state->name = name;
-    state->alias = alias;
-
-    ret = hosts_get_retry(req);
-    if (ret != EOK) {
-        goto fail;
-    }
-
-    return req;
-
-fail:
-    tevent_req_error(req, ret);
-    tevent_req_post(req, ev);
-    return req;
-}
-
-static errno_t
-hosts_get_retry(struct tevent_req *req)
-{
-    struct hosts_get_state *state = tevent_req_data(req,
-                                                    struct hosts_get_state);
-    struct tevent_req *subreq;
-    errno_t ret = EOK;
-
-    subreq = sdap_id_op_connect_send(state->op, state, &ret);
-    if (!subreq) {
-        return ret;
-    }
-
-    tevent_req_set_callback(subreq, hosts_get_connect_done, req);
-    return EOK;
-}
-
-static void
-hosts_get_connect_done(struct tevent_req *subreq)
-{
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct hosts_get_state *state = tevent_req_data(req,
-                                                    struct hosts_get_state);
-    int dp_error = DP_ERR_FATAL;
-    errno_t ret;
-
-    ret = sdap_id_op_connect_recv(subreq, &dp_error);
-    talloc_zfree(subreq);
-
-    if (ret != EOK) {
-        state->dp_error = dp_error;
-        tevent_req_error(req, ret);
-        return;
-    }
-
-    subreq = ipa_host_info_send(state, state->ev,
-                                sdap_id_op_handle(state->op),
-                                state->ctx->sdap_id_ctx->opts, state->name,
-                                state->ctx->ipa_opts->host_map, NULL,
-                                state->ctx->host_search_bases);
-    if (!subreq) {
-        tevent_req_error(req, ENOMEM);
-        return;
-    }
-    tevent_req_set_callback(subreq, hosts_get_done, req);
-}
-
-static void
-hosts_get_done(struct tevent_req *subreq)
-{
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct hosts_get_state *state = tevent_req_data(req,
-                                                    struct hosts_get_state);
-    int dp_error = DP_ERR_FATAL;
-    errno_t ret;
-    struct sysdb_attrs *attrs;
-    time_t now = time(NULL);
-
-    ret = ipa_host_info_recv(subreq, state,
-                             &state->count, &state->hosts,
-                             NULL, NULL);
-    talloc_zfree(subreq);
-
-    ret = sdap_id_op_done(state->op, ret, &dp_error);
-    if (dp_error == DP_ERR_OK && ret != EOK) {
-        /* retry */
-        ret = hosts_get_retry(req);
-        if (ret != EOK) {
-            goto done;
-        }
-        return;
-    }
-
-    if (ret != EOK && ret != ENOENT) {
-        goto done;
-    }
-
-    if (state->count == 0) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "No host with name [%s] found.\n", state->name);
-
-        ret = sysdb_delete_ssh_host(state->domain, state->name);
-        if (ret != EOK && ret != ENOENT) {
-            goto done;
-        }
-
-        ret = EINVAL;
-        goto done;
-    }
-
-    if (state->count > 1) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Found more than one host with name [%s].\n", state->name);
-        ret = EINVAL;
-        goto done;
-    }
-
-    attrs = sysdb_new_attrs(state);
-    if (!attrs) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    /* we are interested only in the host keys */
-    ret = sysdb_attrs_copy_values(state->hosts[0], attrs, SYSDB_SSH_PUBKEY);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    ret = sysdb_store_ssh_host(state->domain, state->name, state->alias,
-                               state->domain->ssh_host_timeout, now, attrs);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    dp_error = DP_ERR_OK;
-
-done:
-    state->dp_error = dp_error;
-    if (ret == EOK) {
-        tevent_req_done(req);
-    } else {
-        tevent_req_error(req, ret);
-    }
-}
-
-static errno_t
-hosts_get_recv(struct tevent_req *req,
-               int *dp_error_out)
-{
-    struct hosts_get_state *state = tevent_req_data(req,
-                                                    struct hosts_get_state);
-
-    if (dp_error_out) {
-        *dp_error_out = state->dp_error;
-    }
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    return EOK;
-}
-
-struct ipa_hostid_handler_state {
-    struct dp_reply_std reply;
-};
-
-static void ipa_hostid_handler_done(struct tevent_req *subreq);
-
-struct tevent_req *
-ipa_hostid_handler_send(TALLOC_CTX *mem_ctx,
-                       struct ipa_hostid_ctx *hostid_ctx,
-                       struct dp_hostid_data *data,
-                       struct dp_req_params *params)
-{
-    struct ipa_hostid_handler_state *state;
-    struct tevent_req *subreq;
-    struct tevent_req *req;
-    errno_t ret;
-
-    req = tevent_req_create(mem_ctx, &state, struct ipa_hostid_handler_state);
-    if (req == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
-        return NULL;
-    }
-
-    subreq = hosts_get_send(state, params->ev, hostid_ctx,
-                            data->name, data->alias);
-    if (subreq == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request\n");
-        ret = ENOMEM;
-        goto immediately;
-    }
-
-    tevent_req_set_callback(subreq, ipa_hostid_handler_done, req);
-
-    return req;
-
-immediately:
-    dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
-
-    /* TODO For backward compatibility we always return EOK to DP now. */
-    tevent_req_done(req);
-    tevent_req_post(req, params->ev);
-
-    return req;
-}
-
-static void ipa_hostid_handler_done(struct tevent_req *subreq)
+errno_t ipa_hostid_init(TALLOC_CTX *mem_ctx,
+                        struct be_ctx *be_ctx,
+                        struct ipa_id_ctx *id_ctx,
+                        struct dp_method *dp_methods)
 {
-    struct ipa_hostid_handler_state *state;
-    struct tevent_req *req;
-    int dp_error;
-    errno_t ret;
-
-    req = tevent_req_callback_data(subreq, struct tevent_req);
-    state = tevent_req_data(req, struct ipa_hostid_handler_state);
-
-    ret = hosts_get_recv(subreq, &dp_error);
-    talloc_zfree(subreq);
-
-    /* TODO For backward compatibility we always return EOK to DP now. */
-    dp_reply_std_set(&state->reply, dp_error, ret, NULL);
-    tevent_req_done(req);
-}
-
-errno_t
-ipa_hostid_handler_recv(TALLOC_CTX *mem_ctx,
-                       struct tevent_req *req,
-                       struct dp_reply_std *data)
-{
-    struct ipa_hostid_handler_state *state = NULL;
-
-    state = tevent_req_data(req, struct ipa_hostid_handler_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *data = state->reply;
-
-    return EOK;
+    return sdap_hostid_init(mem_ctx, be_ctx, id_ctx->sdap_id_ctx, dp_methods);
 }
diff --git a/src/providers/ipa/ipa_hostid.h b/src/providers/ipa/ipa_hostid.h
deleted file mode 100644
index 2611e45..0000000
--- a/src/providers/ipa/ipa_hostid.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-    Authors:
-        Jan Cholasta <jchol...@redhat.com>
-
-    Copyright (C) 2012 Red Hat
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _IPA_HOSTID_H_
-#define _IPA_HOSTID_H_
-
-struct ipa_hostid_ctx {
-    struct sdap_id_ctx *sdap_id_ctx;
-    struct ipa_options *ipa_opts;
-
-    struct sdap_search_base **host_search_bases;
-};
-
-struct tevent_req *
-ipa_hostid_handler_send(TALLOC_CTX *mem_ctx,
-                       struct ipa_hostid_ctx *hostid_ctx,
-                       struct dp_hostid_data *data,
-                       struct dp_req_params *params);
-
-errno_t
-ipa_hostid_handler_recv(TALLOC_CTX *mem_ctx,
-                       struct tevent_req *req,
-                       struct dp_reply_std *data);
-
-#endif /* _IPA_HOSTID_H_ */
diff --git a/src/providers/ipa/ipa_hosts.c b/src/providers/ipa/ipa_hosts.c
deleted file mode 100644
index 5966e3c..0000000
--- a/src/providers/ipa/ipa_hosts.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
-    SSSD
-
-    Authors:
-        Jan Zeleny <jzel...@redhat.com>
-
-    Copyright (C) 2012 Red Hat
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "providers/ldap/sdap_async.h"
-#include "providers/ipa/ipa_hosts.h"
-#include "providers/ipa/ipa_common.h"
-
-struct ipa_host_state {
-    struct tevent_context *ev;
-    struct sysdb_ctx *sysdb;
-    struct sdap_handle *sh;
-    struct sdap_options *opts;
-    const char **attrs;
-    struct sdap_attr_map *host_map;
-    struct sdap_attr_map *hostgroup_map;
-
-    struct sdap_search_base **search_bases;
-    int search_base_iter;
-
-    char *cur_filter;
-    char *host_filter;
-
-    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 *ipa_hostgroup_map;
-};
-
-static void
-ipa_host_info_done(struct tevent_req *subreq);
-
-static void
-ipa_hostgroup_info_done(struct tevent_req *subreq);
-
-static errno_t
-ipa_host_info_next(struct tevent_req *req,
-                        struct ipa_host_state *state);
-static errno_t
-ipa_hostgroup_info_next(struct tevent_req *req,
-                             struct ipa_host_state *state);
-
-/**
- * hostname == NULL -> look up all hosts / host groups
- * hostname != NULL -> look up only given host and groups
- *                     it's member of
- * hostgroup_map == NULL -> skip looking up hostgroups
- */
-struct tevent_req *
-ipa_host_info_send(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sdap_handle *sh,
-                   struct sdap_options *opts,
-                   const char *hostname,
-                   struct sdap_attr_map *host_map,
-                   struct sdap_attr_map *hostgroup_map,
-                   struct sdap_search_base **search_bases)
-{
-    errno_t ret;
-    struct ipa_host_state *state;
-    struct tevent_req *req;
-
-    req = tevent_req_create(mem_ctx, &state, struct ipa_host_state);
-    if (req == NULL) {
-        return NULL;
-    }
-
-    state->ev = ev;
-    state->sh = sh;
-    state->opts = opts;
-    state->hostname = hostname;
-    state->search_bases = search_bases;
-    state->search_base_iter = 0;
-    state->cur_filter = NULL;
-    state->host_map = host_map;
-    state->hostgroup_map = hostgroup_map;
-
-    ret = build_attrs_from_map(state, host_map, IPA_OPTS_HOST,
-                               NULL, &state->attrs, NULL);
-    if (ret != EOK) {
-        goto immediate;
-    }
-
-    if (hostname == NULL) {
-        state->host_filter = talloc_asprintf(state, "(objectClass=%s)",
-                                             host_map[IPA_OC_HOST].name);
-    } else {
-        state->host_filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=%s))",
-                                             host_map[IPA_OC_HOST].name,
-                                             host_map[IPA_AT_HOST_FQDN].name,
-                                             hostname);
-    }
-    if (state->host_filter == NULL) {
-        ret = ENOMEM;
-        goto immediate;
-    }
-
-    ret = ipa_host_info_next(req, state);
-    if (ret == EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "No host search base configured?\n");
-        ret = EINVAL;
-    }
-
-    if (ret != EAGAIN) {
-        goto immediate;
-    }
-
-    return req;
-
-immediate:
-    if (ret == EOK) {
-        tevent_req_done(req);
-    } else {
-        tevent_req_error(req, ret);
-    }
-    tevent_req_post(req, ev);
-    return req;
-}
-
-static errno_t ipa_host_info_next(struct tevent_req *req,
-                                       struct ipa_host_state *state)
-{
-    struct sdap_search_base *base;
-    struct tevent_req *subreq;
-
-    base = state->search_bases[state->search_base_iter];
-    if (base == NULL) {
-        return EOK;
-    }
-
-    talloc_zfree(state->cur_filter);
-    state->cur_filter = sdap_combine_filters(state, state->host_filter,
-                                             base->filter);
-    if (state->cur_filter == NULL) {
-        return ENOMEM;
-    }
-
-    subreq = sdap_get_generic_send(state, state->ev, state->opts,
-                                   state->sh, base->basedn,
-                                   base->scope, state->cur_filter,
-                                   state->attrs, state->host_map,
-                                   IPA_OPTS_HOST,
-                                   dp_opt_get_int(state->opts->basic,
-                                                  SDAP_ENUM_SEARCH_TIMEOUT),
-                                   true);
-    if (subreq == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting host info\n");
-        talloc_zfree(state->cur_filter);
-        return EIO;
-    }
-    tevent_req_set_callback(subreq, ipa_host_info_done, req);
-
-    return EAGAIN;
-}
-
-static void
-ipa_host_info_done(struct tevent_req *subreq)
-{
-    errno_t ret;
-    struct tevent_req *req =
-            tevent_req_callback_data(subreq, struct tevent_req);
-    struct ipa_host_state *state =
-            tevent_req_data(req, struct ipa_host_state);
-    const char *host_dn;
-
-    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 (state->host_count == 0) {
-        state->search_base_iter++;
-        ret = ipa_host_info_next(req, state);
-        if (ret == EOK) {
-            /* No more search bases to try */
-            tevent_req_error(req, ENOENT);
-        } else if (ret != EAGAIN) {
-            tevent_req_error(req, ret);
-        }
-        return;
-    }
-
-    if (state->hostgroup_map) {
-        talloc_free(state->attrs);
-        ret = build_attrs_from_map(state, state->hostgroup_map,
-                                   IPA_OPTS_HOSTGROUP, NULL,
-                                   &state->attrs, NULL);
-        if (ret != EOK) {
-            tevent_req_error(req, ret);
-            return;
-        }
-
-        /* Look up host groups */
-        if (state->hostname == NULL) {
-            talloc_zfree(state->host_filter);
-            state->host_filter = talloc_asprintf(state, "(objectClass=%s)",
-                                    state->hostgroup_map[IPA_OC_HOSTGROUP].name);
-            if (state->host_filter == NULL) {
-                tevent_req_error(req, ENOMEM);
-                return;
-            }
-            state->search_base_iter = 0;
-
-            ret = ipa_hostgroup_info_next(req, state);
-            if (ret == EOK) {
-                DEBUG(SSSDBG_CRIT_FAILURE, "No host search base configured?\n");
-                tevent_req_error(req, EINVAL);
-                return;
-            } else if (ret != EAGAIN) {
-                tevent_req_error(req, ret);
-                return;
-            }
-        } else {
-            state->ipa_hostgroup_map = talloc_zero(state, struct sdap_attr_map_info);
-            if (state->ipa_hostgroup_map == NULL) {
-                tevent_req_error(req, ENOMEM);
-                return;
-            }
-            state->ipa_hostgroup_map->map = state->hostgroup_map;
-            state->ipa_hostgroup_map->num_attrs = IPA_OPTS_HOSTGROUP;
-
-            ret = sysdb_attrs_get_string(state->hosts[0], SYSDB_ORIG_DN, &host_dn);
-            if (ret != EOK) {
-                tevent_req_error(req, ret);
-                return;
-            }
-
-            if (!sdap_has_deref_support(state->sh, state->opts)) {
-                DEBUG(SSSDBG_CRIT_FAILURE, "Server does not support deref\n");
-                tevent_req_error(req, EIO);
-                return;
-            }
-
-            subreq = sdap_deref_search_send(state, state->ev, state->opts, state->sh,
-                                            host_dn,
-                                            state->hostgroup_map[IPA_AT_HOSTGROUP_MEMBER_OF].name,
-                                            state->attrs,
-                                            1, state->ipa_hostgroup_map,
-                                            dp_opt_get_int(state->opts->basic,
-                                                           SDAP_ENUM_SEARCH_TIMEOUT));
-            if (subreq == NULL) {
-                DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting host info\n");
-                tevent_req_error(req, EIO);
-                return;
-            }
-            tevent_req_set_callback(subreq, ipa_hostgroup_info_done, req);
-        }
-    } else {
-        /* Nothing else to do, just complete the req */
-        tevent_req_done(req);
-    }
-}
-
-static errno_t ipa_hostgroup_info_next(struct tevent_req *req,
-                                            struct ipa_host_state *state)
-{
-    struct sdap_search_base *base;
-    struct tevent_req *subreq;
-
-    base = state->search_bases[state->search_base_iter];
-    if (base == NULL) {
-        return EOK;
-    }
-
-    talloc_zfree(state->cur_filter);
-    state->cur_filter = sdap_combine_filters(state, state->host_filter,
-                                             base->filter);
-    if (state->cur_filter == NULL) {
-        return ENOMEM;
-    }
-
-    subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
-                                   base->basedn, base->scope,
-                                   state->cur_filter, state->attrs,
-                                   state->hostgroup_map,
-                                   IPA_OPTS_HOSTGROUP,
-                                   dp_opt_get_int(state->opts->basic,
-                                                  SDAP_ENUM_SEARCH_TIMEOUT),
-                                   true);
-    if (subreq == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting hostgroup info\n");
-        talloc_zfree(state->cur_filter);
-        return EIO;
-    }
-    tevent_req_set_callback(subreq, ipa_hostgroup_info_done, req);
-
-    return EAGAIN;
-}
-
-static void
-ipa_hostgroup_info_done(struct tevent_req *subreq)
-{
-    errno_t ret;
-    struct tevent_req *req =
-            tevent_req_callback_data(subreq, struct tevent_req);
-    struct ipa_host_state *state =
-            tevent_req_data(req, struct ipa_host_state);
-
-    size_t hostgroups_total;
-    size_t hostgroup_count;
-    struct sysdb_attrs **hostgroups;
-    struct sdap_deref_attrs **deref_result;
-    const char *hostgroup_name;
-    const char *hostgroup_dn;
-    int i, j;
-
-    if (state->hostname == NULL) {
-        ret = sdap_get_generic_recv(subreq, state,
-                                    &hostgroup_count,
-                                    &hostgroups);
-        talloc_zfree(subreq);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                  "sdap_get_generic_recv failed: [%d]\n", ret);
-            tevent_req_error(req, ret);
-            return;
-        }
-
-        /* Merge the two arrays */
-        if (hostgroup_count > 0) {
-            hostgroups_total = hostgroup_count + state->hostgroup_count;
-            state->hostgroups = talloc_realloc(state, state->hostgroups,
-                                               struct sysdb_attrs *,
-                                               hostgroups_total);
-            if (state->hostgroups == NULL) {
-                tevent_req_error(req, ENOMEM);
-                return;
-            }
-
-            i = 0;
-            while(state->hostgroup_count < hostgroups_total) {
-                state->hostgroups[state->hostgroup_count] =
-                    talloc_steal(state->hostgroups, hostgroups[i]);
-                state->hostgroup_count++;
-                i++;
-            }
-        }
-
-        /* Now look in the next base */
-        state->search_base_iter++;
-        ret = ipa_hostgroup_info_next(req, state);
-        if (ret != EOK && ret != EAGAIN) {
-            tevent_req_error(req, ret);
-        }
-
-        if (ret != EOK) {
-            /* Only continue if no error occurred
-             * and no req was created */
-            return;
-        }
-    } 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;
-            }
-
-            j = 0;
-            for (i = 0; i < state->hostgroup_count; i++) {
-                ret = sysdb_attrs_get_string(deref_result[i]->attrs,
-                                             SYSDB_ORIG_DN, &hostgroup_dn);
-                if (ret != EOK) goto done;
-
-                if (!sss_ldap_dn_in_search_bases(state, hostgroup_dn,
-                                                 state->search_bases,
-                                                 NULL)) {
-                    continue;
-                }
-
-                ret = sysdb_attrs_get_string(deref_result[i]->attrs,
-                             state->hostgroup_map[IPA_AT_HOSTGROUP_NAME].sys_name,
-                             &hostgroup_name);
-                if (ret != EOK) goto done;
-
-                DEBUG(SSSDBG_FUNC_DATA, "Dereferenced host group: %s\n",
-                                        hostgroup_name);
-                state->hostgroups[j] = talloc_steal(state->hostgroups,
-                                                    deref_result[i]->attrs);
-                j++;
-            }
-            state->hostgroup_count = j;
-        }
-    }
-
-done:
-    if (ret == EOK) {
-        tevent_req_done(req);
-    } else {
-        DEBUG(SSSDBG_OP_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
-        tevent_req_error(req, ret);
-    }
-}
-
-errno_t ipa_host_info_recv(struct tevent_req *req,
-                           TALLOC_CTX *mem_ctx,
-                           size_t *host_count,
-                           struct sysdb_attrs ***hosts,
-                           size_t *hostgroup_count,
-                           struct sysdb_attrs ***hostgroups)
-{
-    size_t c;
-    struct ipa_host_state *state =
-            tevent_req_data(req, struct ipa_host_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *host_count = state->host_count;
-    *hosts = talloc_steal(mem_ctx, state->hosts);
-    for (c = 0; c < state->host_count; c++) {
-        /* Guarantee the memory heirarchy of the list */
-        talloc_steal(state->hosts, state->hosts[c]);
-    }
-
-    if (hostgroup_count) *hostgroup_count = state->hostgroup_count;
-    if (hostgroups) *hostgroups = talloc_steal(mem_ctx, state->hostgroups);
-
-    return EOK;
-}
diff --git a/src/providers/ipa/ipa_hosts.h b/src/providers/ipa/ipa_hosts.h
deleted file mode 100644
index a1ea7a2..0000000
--- a/src/providers/ipa/ipa_hosts.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    SSSD
-
-    Authors:
-        Jan Zeleny <jzel...@redhat.com>
-
-    Copyright (C) 2012 Red Hat
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef IPA_HOSTS_H_
-#define IPA_HOSTS_H_
-
-struct tevent_req *
-ipa_host_info_send(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sdap_handle *sh,
-                   struct sdap_options *opts,
-                   const char *hostname,
-                   struct sdap_attr_map *host_map,
-                   struct sdap_attr_map *hostgroup_map,
-                   struct sdap_search_base **search_bases);
-
-errno_t
-ipa_host_info_recv(struct tevent_req *req,
-                   TALLOC_CTX *mem_ctx,
-                   size_t *host_count,
-                   struct sysdb_attrs ***hosts,
-                   size_t *hostgroup_count,
-                   struct sysdb_attrs ***hostgroups);
-
-#endif /* IPA_HOSTS_H_ */
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 7dec4d1..228e2bf 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -34,7 +34,6 @@
 #include "providers/ipa/ipa_id.h"
 #include "providers/ipa/ipa_auth.h"
 #include "providers/ipa/ipa_access.h"
-#include "providers/ipa/ipa_hostid.h"
 #include "providers/ipa/ipa_dyndns.h"
 #include "providers/ipa/ipa_selinux.h"
 #include "providers/ldap/sdap_access.h"
@@ -783,9 +782,9 @@ errno_t sssm_ipa_access_init(TALLOC_CTX *mem_ctx,
     }
 
     access_ctx->sdap_ctx = id_ctx->sdap_id_ctx;
-    access_ctx->host_map = id_ctx->ipa_options->host_map;
-    access_ctx->hostgroup_map = id_ctx->ipa_options->hostgroup_map;
-    access_ctx->host_search_bases = id_ctx->ipa_options->host_search_bases;
+    access_ctx->host_map = id_ctx->ipa_options->id->host_map;
+    access_ctx->hostgroup_map = id_ctx->ipa_options->id->hostgroup_map;
+    access_ctx->host_search_bases = id_ctx->ipa_options->id->sdom->host_search_bases;
     access_ctx->hbac_search_bases = id_ctx->ipa_options->hbac_search_bases;
 
     ret = dp_copy_options(access_ctx, id_ctx->ipa_options->basic,
@@ -842,7 +841,7 @@ errno_t sssm_ipa_selinux_init(TALLOC_CTX *mem_ctx,
 
     selinux_ctx->id_ctx = init_ctx->id_ctx;
     selinux_ctx->hbac_search_bases = opts->hbac_search_bases;
-    selinux_ctx->host_search_bases = opts->host_search_bases;
+    selinux_ctx->host_search_bases = opts->id->sdom->host_search_bases;
     selinux_ctx->selinux_search_bases = opts->selinux_search_bases;
 
     dp_set_method(dp_methods, DPM_SELINUX_HANDLER,
@@ -863,26 +862,13 @@ errno_t sssm_ipa_hostid_init(TALLOC_CTX *mem_ctx,
                              struct dp_method *dp_methods)
 {
 #ifdef BUILD_SSH
-    struct ipa_hostid_ctx *hostid_ctx;
     struct ipa_init_ctx *init_ctx;
 
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing IPA host handler\n");
     init_ctx = talloc_get_type(module_data, struct ipa_init_ctx);
 
-    hostid_ctx = talloc_zero(mem_ctx, struct ipa_hostid_ctx);
-    if (hostid_ctx == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
-        return ENOMEM;
-    }
-
-    hostid_ctx->sdap_id_ctx = init_ctx->id_ctx->sdap_id_ctx;
-    hostid_ctx->host_search_bases = init_ctx->options->host_search_bases;
-    hostid_ctx->ipa_opts = init_ctx->options;
+    return ipa_hostid_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods);
 
-    dp_set_method(dp_methods, DPM_HOSTID_HANDLER,
-                  ipa_hostid_handler_send, ipa_hostid_handler_recv, hostid_ctx,
-                  struct ipa_hostid_ctx, struct dp_hostid_data, struct dp_reply_std);
-
-    return EOK;
 #else
     DEBUG(SSSDBG_MINOR_FAILURE, "HostID init handler called but SSSD is "
                                 "built without SSH support, ignoring\n");
diff --git a/src/providers/ipa/ipa_netgroups.c b/src/providers/ipa/ipa_netgroups.c
index 17b11af..8991313 100644
--- a/src/providers/ipa/ipa_netgroups.c
+++ b/src/providers/ipa/ipa_netgroups.c
@@ -516,7 +516,7 @@ static int ipa_netgr_fetch_hosts(struct ipa_get_netgroups_state *state,
     int ret;
     struct sdap_search_base **bases;
 
-    bases = state->ipa_opts->host_search_bases;
+    bases = state->ipa_opts->id->sdom->host_search_bases;
     if (bases[state->host_base_iter] == NULL) {
         return ENOENT;
     }
@@ -525,12 +525,12 @@ static int ipa_netgr_fetch_hosts(struct ipa_get_netgroups_state *state,
     filter = talloc_asprintf(state, "(&%s%s(objectclass=%s))",
                              state->filter,
                              base_filter?base_filter:"",
-                             state->ipa_opts->host_map[IPA_OC_HOST].name);
+                             state->ipa_opts->id->host_map[SDAP_OC_HOST].name);
     if (filter == NULL)
         return ENOMEM;
 
-    ret = build_attrs_from_map(state, state->ipa_opts->host_map,
-                               IPA_OPTS_HOST, NULL, &attrs, NULL);
+    ret = build_attrs_from_map(state, state->ipa_opts->id->host_map,
+                               SDAP_OPTS_HOST, NULL, &attrs, NULL);
     if (ret != EOK) {
         talloc_free(filter);
         return ret;
@@ -539,8 +539,8 @@ static int ipa_netgr_fetch_hosts(struct ipa_get_netgroups_state *state,
     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
                                    bases[state->host_base_iter]->basedn,
                                    bases[state->host_base_iter]->scope,
-                                   filter, attrs, state->ipa_opts->host_map,
-                                   IPA_OPTS_HOST, state->timeout, true);
+                                   filter, attrs, state->ipa_opts->id->host_map,
+                                   SDAP_OPTS_HOST, state->timeout, true);
 
     state->current_entity = ENTITY_HOST;
     if (subreq == NULL) {
@@ -918,7 +918,7 @@ static int ipa_netgr_process_all(struct ipa_get_netgroups_state *state)
         DEBUG(SSSDBG_TRACE_ALL, "Extracting host members of netgroup %d\n", i);
         ret = extract_members(state, state->netgroups[i],
                               SYSDB_ORIG_MEMBER_HOST,
-                              state->ipa_opts->host_map[IPA_AT_HOST_MEMBER_OF].sys_name,
+                              state->ipa_opts->id->host_map[SDAP_AT_HOST_MEMBER_OF].sys_name,
                               state->new_hosts,
                               &hosts, &hosts_count);
         if (ret != EOK) {
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
index cd3fe9a..a680d2a 100644
--- a/src/providers/ipa/ipa_opts.c
+++ b/src/providers/ipa/ipa_opts.c
@@ -81,6 +81,7 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
     { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_service_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER },
diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
index 6d0778d..cf5e8dd 100644
--- a/src/providers/ipa/ipa_selinux.c
+++ b/src/providers/ipa/ipa_selinux.c
@@ -30,7 +30,6 @@
 #include "providers/ipa/ipa_common.h"
 #include "providers/ipa/ipa_config.h"
 #include "providers/ipa/ipa_selinux.h"
-#include "providers/ipa/ipa_hosts.h"
 #include "providers/ipa/ipa_hbac_rules.h"
 #include "providers/ipa/ipa_hbac_private.h"
 #include "providers/ipa/ipa_access.h"
@@ -974,13 +973,13 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq)
         goto fail;
     }
 
-    subreq = ipa_host_info_send(state, state->be_ctx->ev,
-                                sdap_id_op_handle(state->op),
-                                id_ctx->sdap_id_ctx->opts,
-                                hostname,
-                                id_ctx->ipa_options->host_map,
-                                NULL,
-                                state->selinux_ctx->host_search_bases);
+    subreq = sdap_host_info_send(state, state->be_ctx->ev,
+                                 sdap_id_op_handle(state->op),
+                                 id_ctx->sdap_id_ctx->opts,
+                                 hostname,
+                                 id_ctx->ipa_options->id->host_map,
+                                 NULL,
+                                 state->selinux_ctx->host_search_bases);
     if (subreq == NULL) {
         ret = ENOMEM;
         goto fail;
@@ -1087,8 +1086,8 @@ static void ipa_get_selinux_hosts_done(struct tevent_req *subreq)
     struct sysdb_attrs **hostgroups;
     struct sysdb_attrs **host;
 
-    ret = ipa_host_info_recv(subreq, state, &host_count, &host,
-                             &hostgroup_count, &hostgroups);
+    ret = sdap_host_info_recv(subreq, state, &host_count, &host,
+                              &hostgroup_count, &hostgroups);
     talloc_free(subreq);
     if (ret != EOK) {
         goto done;
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index ef348ad..4e5c7b8 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -1571,8 +1571,8 @@ ipa_subdomains_view_name_send(TALLOC_CTX *mem_ctx,
     maps->num_attrs = IPA_OPTS_VIEW;
 
     filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=%s))",
-                        ipa_options->host_map[IPA_OC_HOST].name,
-                        ipa_options->host_map[IPA_AT_HOST_FQDN].name,
+                        ipa_options->id->host_map[SDAP_OC_HOST].name,
+                        ipa_options->id->host_map[SDAP_AT_HOST_FQDN].name,
                         dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME));
     if (filter == NULL) {
         ret = ENOMEM;
@@ -1582,7 +1582,8 @@ ipa_subdomains_view_name_send(TALLOC_CTX *mem_ctx,
     /* We add SDAP_DEREF_FLG_SILENT because old IPA servers don't have
      * the attribute we dereference, causing the deref call to fail. */
     subreq = sdap_deref_bases_return_first_send(state, ev,
-                 sd_ctx->sdap_id_ctx->opts, sh, sd_ctx->host_search_bases,
+                 sd_ctx->sdap_id_ctx->opts, sh,
+                 sd_ctx->host_search_bases,
                  maps, filter, attrs, IPA_ASSIGNED_ID_VIEW,
                  SDAP_DEREF_FLG_SILENT, 0);
     if (subreq == NULL) {
@@ -2418,7 +2419,7 @@ errno_t ipa_subdomains_init(TALLOC_CTX *mem_ctx,
     sd_ctx->search_bases = ipa_options->subdomains_search_bases;
     sd_ctx->master_search_bases = ipa_options->master_domain_search_bases;
     sd_ctx->ranges_search_bases = ipa_options->ranges_search_bases;
-    sd_ctx->host_search_bases = ipa_options->host_search_bases;
+    sd_ctx->host_search_bases = ipa_options->id->sdom->host_search_bases;
 
     dp_set_method(dp_methods, DPM_DOMAINS_HANDLER,
                   ipa_subdomains_handler_send, ipa_subdomains_handler_recv, sd_ctx,
diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c
index 9ed1218..e09fbdf 100644
--- a/src/providers/ipa/ipa_sudo_async.c
+++ b/src/providers/ipa/ipa_sudo_async.c
@@ -24,8 +24,8 @@
 
 #include "providers/ldap/sdap_ops.h"
 #include "providers/ldap/sdap_sudo_shared.h"
+#include "providers/ldap/sdap_async.h"
 #include "providers/ipa/ipa_common.h"
-#include "providers/ipa/ipa_hosts.h"
 #include "providers/ipa/ipa_sudo.h"
 #include "providers/ipa/ipa_dn.h"
 #include "db/sysdb.h"
@@ -976,11 +976,11 @@ ipa_sudo_refresh_connect_done(struct tevent_req *subreq)
     /* Obtain host information. */
     hostname = dp_opt_get_string(state->ipa_opts->basic, IPA_HOSTNAME);
 
-    subreq = ipa_host_info_send(state, state->ev,
-                                state->sh, state->sdap_opts, hostname,
-                                state->ipa_opts->host_map,
-                                state->ipa_opts->hostgroup_map,
-                                state->ipa_opts->host_search_bases);
+    subreq = sdap_host_info_send(state, state->ev,
+                                 state->sh, state->sdap_opts, hostname,
+                                 state->ipa_opts->id->host_map,
+                                 state->ipa_opts->id->hostgroup_map,
+                                 state->ipa_opts->id->sdom->host_search_bases);
     if (subreq == NULL) {
         state->dp_error = DP_ERR_FATAL;
         tevent_req_error(req, ENOMEM);
@@ -1008,8 +1008,8 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
         return;
     }
 
-    ret = ipa_host_info_recv(subreq, host, &host->num_hosts, &host->hosts,
-                             &host->num_hostgroups, &host->hostgroups);
+    ret = sdap_host_info_recv(subreq, host, &host->num_hosts, &host->hosts,
+                              &host->num_hostgroups, &host->hostgroups);
     talloc_zfree(subreq);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve host information "
@@ -1023,8 +1023,8 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
                                  state->sudo_ctx, host,
                                  state->sdap_opts->user_map,
                                  state->sdap_opts->group_map,
-                                 state->ipa_opts->host_map,
-                                 state->ipa_opts->hostgroup_map, state->sh,
+                                 state->ipa_opts->id->host_map,
+                                 state->ipa_opts->id->hostgroup_map, state->sh,
                                  state->cmdgroups_filter, state->search_filter);
     if (subreq == NULL) {
         state->dp_error = DP_ERR_FATAL;
diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c
index f6d17d8..701de52 100644
--- a/src/providers/ipa/ipa_sudo_conversion.c
+++ b/src/providers/ipa/ipa_sudo_conversion.c
@@ -43,8 +43,8 @@
 
 #define MATCHRDN_USER(map)      (map)[SDAP_AT_USER_NAME].name, "cn", "users", "cn", "accounts"
 #define MATCHRDN_GROUP(map)     (map)[SDAP_AT_GROUP_NAME].name, "cn", "groups", "cn", "accounts"
-#define MATCHRDN_HOST(map)      (map)[IPA_AT_HOST_FQDN].name, "cn", "computers", "cn", "accounts"
-#define MATCHRDN_HOSTGROUP(map) (map)[IPA_AT_HOSTGROUP_NAME].name, "cn", "hostgroups", "cn", "accounts"
+#define MATCHRDN_HOST(map)      (map)[SDAP_AT_HOST_FQDN].name, "cn", "computers", "cn", "accounts"
+#define MATCHRDN_HOSTGROUP(map) (map)[SDAP_AT_HOSTGROUP_NAME].name, "cn", "hostgroups", "cn", "accounts"
 
 struct ipa_sudo_conv {
     struct sss_domain_info *dom;
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index b7102ad..7433701 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -26,6 +26,7 @@
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async_private.h"
 #include "providers/ldap/sdap_access.h"
+#include "providers/ldap/sdap_hostid.h"
 #include "providers/ldap/sdap_sudo.h"
 #include "providers/ldap/sdap_autofs.h"
 #include "providers/ldap/sdap_idmap.h"
@@ -618,6 +619,26 @@ errno_t sssm_ldap_access_init(TALLOC_CTX *mem_ctx,
     return ret;
 }
 
+errno_t sssm_ldap_hostid_init(TALLOC_CTX *mem_ctx,
+                             struct be_ctx *be_ctx,
+                             void *module_data,
+                             struct dp_method *dp_methods)
+{
+#ifdef BUILD_SSH
+    struct ldap_init_ctx *init_ctx;
+
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing LDAP host handler\n");
+    init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
+
+    return sdap_hostid_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods);
+
+#else
+    DEBUG(SSSDBG_MINOR_FAILURE, "HostID init handler called but SSSD is "
+                                "built without SSH support, ignoring\n");
+    return EOK;
+#endif
+}
+
 errno_t sssm_ldap_autofs_init(TALLOC_CTX *mem_ctx,
                               struct be_ctx *be_ctx,
                               void *module_data,
diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c
index 15a2609..5999146 100644
--- a/src/providers/ldap/ldap_options.c
+++ b/src/providers/ldap/ldap_options.c
@@ -33,6 +33,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
     struct sdap_attr_map *default_user_map;
     struct sdap_attr_map *default_group_map;
     struct sdap_attr_map *default_netgroup_map;
+    struct sdap_attr_map *default_host_map;
     struct sdap_attr_map *default_service_map;
     struct sdap_options *opts;
     char *schema;
@@ -50,6 +51,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
     const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
                                         SDAP_GROUP_SEARCH_BASE,
                                         SDAP_NETGROUP_SEARCH_BASE,
+                                        SDAP_HOST_SEARCH_BASE,
                                         SDAP_SERVICE_SEARCH_BASE,
                                         -1 };
 
@@ -116,6 +118,12 @@ int ldap_get_options(TALLOC_CTX *memctx,
                                  &opts->sdom->netgroup_search_bases);
     if (ret != EOK && ret != ENOENT) goto done;
 
+    /* Netgroup search */
+    ret = sdap_parse_search_base(opts, opts->basic,
+                                 SDAP_HOST_SEARCH_BASE,
+                                 &opts->sdom->host_search_bases);
+    if (ret != EOK && ret != ENOENT) goto done;
+
     /* Service search */
     ret = sdap_parse_search_base(opts, opts->basic,
                                  SDAP_SERVICE_SEARCH_BASE,
@@ -214,6 +222,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
         default_user_map = rfc2307_user_map;
         default_group_map = rfc2307_group_map;
         default_netgroup_map = netgroup_map;
+        default_host_map = host_map;
         default_service_map = service_map;
     } else
     if (strcasecmp(schema, "rfc2307bis") == 0) {
@@ -222,6 +231,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
         default_user_map = rfc2307bis_user_map;
         default_group_map = rfc2307bis_group_map;
         default_netgroup_map = netgroup_map;
+        default_host_map = host_map;
         default_service_map = service_map;
     } else
     if (strcasecmp(schema, "IPA") == 0) {
@@ -230,6 +240,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
         default_user_map = rfc2307bis_user_map;
         default_group_map = rfc2307bis_group_map;
         default_netgroup_map = netgroup_map;
+        default_host_map = host_map;
         default_service_map = service_map;
     } else
     if (strcasecmp(schema, "AD") == 0) {
@@ -238,6 +249,7 @@ int ldap_get_options(TALLOC_CTX *memctx,
         default_user_map = gen_ad2008r2_user_map;
         default_group_map = gen_ad2008r2_group_map;
         default_netgroup_map = netgroup_map;
+        default_host_map = host_map;
         default_service_map = service_map;
     } else {
         DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized schema type: %s\n", schema);
@@ -285,6 +297,17 @@ int ldap_get_options(TALLOC_CTX *memctx,
     }
 
     ret = sdap_get_map(opts, cdb, conf_path,
+                       default_host_map,
+                       SDAP_OPTS_HOST,
+                       &opts->host_map);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* Host groups are only available in IPA */
+    opts->hostgroup_map = NULL;
+
+    ret = sdap_get_map(opts, cdb, conf_path,
                        default_service_map,
                        SDAP_OPTS_SERVICES,
                        &opts->service_map);
@@ -598,6 +621,9 @@ errno_t sdap_parse_search_base(TALLOC_CTX *mem_ctx,
     case SDAP_NETGROUP_SEARCH_BASE:
         class_name = "NETGROUP";
         break;
+    case SDAP_HOST_SEARCH_BASE:
+        class_name = "HOST";
+        break;
     case SDAP_SUDO_SEARCH_BASE:
         class_name = "SUDO";
         break;
diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c
index c6efe33..fbd527e 100644
--- a/src/providers/ldap/ldap_opts.c
+++ b/src/providers/ldap/ldap_opts.c
@@ -45,6 +45,7 @@ struct dp_option default_basic_opts[] = {
     { "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING },
     { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ldap_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_service_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sudo_full_refresh_interval", DP_OPT_NUMBER, { .number = 21600 }, NULL_NUMBER }, /* 360 mins */
@@ -325,6 +326,17 @@ struct sdap_attr_map netgroup_map[] = {
     SDAP_ATTR_MAP_TERMINATOR
 };
 
+struct sdap_attr_map host_map[] = {
+    { "ldap_host_object_class", "ipHost", SYSDB_HOST_CLASS, NULL },
+    { "ldap_host_name", "cn", SYSDB_NAME, NULL },
+    { "ldap_host_fqdn", "fqdn", SYSDB_FQDN, NULL },
+    { "ldap_host_serverhostname", "serverHostname", SYSDB_SERVERHOSTNAME, NULL },
+    { "ldap_host_member_of", "memberOf", SYSDB_ORIG_MEMBEROF, NULL },
+    { "ldap_host_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_host_uuid", NULL, SYSDB_UUID, NULL},
+    SDAP_ATTR_MAP_TERMINATOR
+};
+
 struct sdap_attr_map native_sudorule_map[] = {
     { "ldap_sudorule_object_class", "sudoRole", SYSDB_SUDO_CACHE_OC, NULL },
     { "ldap_sudorule_name", "cn", SYSDB_SUDO_CACHE_AT_CN, NULL },
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index ef09a02..d812554 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -48,6 +48,10 @@ extern struct sdap_attr_map gen_ad2008r2_group_map[];
 
 extern struct sdap_attr_map netgroup_map[];
 
+extern struct sdap_attr_map host_map[];
+
+extern struct sdap_attr_map hostgroup_map[];
+
 extern struct sdap_attr_map native_sudorule_map[];
 
 extern struct sdap_attr_map service_map[];
diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index d562a96..b690660 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -1136,6 +1136,9 @@ static errno_t sdap_set_search_base(struct sdap_options *opts,
     case SDAP_NETGROUP_SEARCH_BASE:
         bases = &sdom->netgroup_search_bases;
         break;
+    case SDAP_HOST_SEARCH_BASE:
+        bases = &sdom->host_search_bases;
+        break;
     case SDAP_SUDO_SEARCH_BASE:
         bases = &sdom->sudo_search_bases;
         break;
@@ -1178,6 +1181,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
             || !sdom->user_search_bases
             || !sdom->group_search_bases
             || !sdom->netgroup_search_bases
+            || !sdom->host_search_bases
             || !sdom->sudo_search_bases
             || !sdom->autofs_search_bases) {
         naming_context = get_naming_context(opts->basic, rootdse);
@@ -1225,6 +1229,14 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
         if (ret != EOK) goto done;
     }
 
+    /* Hosts */
+    if (!sdom->host_search_bases) {
+        ret = sdap_set_search_base(opts, sdom,
+                                   SDAP_HOST_SEARCH_BASE,
+                                   naming_context);
+        if (ret != EOK) goto done;
+    }
+
     /* Sudo */
     if (!sdom->sudo_search_bases) {
        ret = sdap_set_search_base(opts, sdom,
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index afdc019..5665c72 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -162,6 +162,7 @@ enum sdap_basic_opt {
     SDAP_GROUP_SEARCH_BASE,
     SDAP_GROUP_SEARCH_SCOPE,
     SDAP_GROUP_SEARCH_FILTER,
+    SDAP_HOST_SEARCH_BASE,
     SDAP_SERVICE_SEARCH_BASE,
     SDAP_SUDO_SEARCH_BASE,
     SDAP_SUDO_FULL_REFRESH_INTERVAL,
@@ -339,6 +340,27 @@ enum sdap_sudorule_attrs {
     SDAP_OPTS_SUDO  /* attrs counter */
 };
 
+enum sdap_host_attrs {
+    SDAP_OC_HOST = 0,
+    SDAP_AT_HOST_NAME,
+    SDAP_AT_HOST_FQDN,
+    SDAP_AT_HOST_SERVERHOSTNAME,
+    SDAP_AT_HOST_MEMBER_OF,
+    SDAP_AT_HOST_SSH_PUBLIC_KEY,
+    SDAP_AT_HOST_UUID,
+
+    SDAP_OPTS_HOST /* attrs counter */
+};
+
+enum sdap_hostgroup_attrs {
+    SDAP_OC_HOSTGROUP = 0,
+    SDAP_AT_HOSTGROUP_NAME,
+    SDAP_AT_HOSTGROUP_MEMBER_OF,
+    SDAP_AT_HOSTGROUP_UUID,
+
+    SDAP_OPTS_HOSTGROUP /* attrs counter */
+};
+
 enum sdap_service_attrs {
     SDAP_OC_SERVICE = 0,
     SDAP_AT_SERVICE_NAME,
@@ -406,6 +428,7 @@ struct sdap_domain {
     struct sdap_search_base **user_search_bases;
     struct sdap_search_base **group_search_bases;
     struct sdap_search_base **netgroup_search_bases;
+    struct sdap_search_base **host_search_bases;
     struct sdap_search_base **sudo_search_bases;
     struct sdap_search_base **service_search_bases;
     struct sdap_search_base **autofs_search_bases;
@@ -453,6 +476,8 @@ struct sdap_options {
     size_t user_map_cnt;
     struct sdap_attr_map *group_map;
     struct sdap_attr_map *netgroup_map;
+    struct sdap_attr_map *host_map;
+    struct sdap_attr_map *hostgroup_map;
     struct sdap_attr_map *service_map;
 
     /* ID-mapping support */
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 6e5800b..a1101cb 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -123,6 +123,24 @@ int sdap_get_netgroups_recv(struct tevent_req *req,
                             size_t *reply_count,
                             struct sysdb_attrs ***reply);
 
+struct tevent_req *
+sdap_host_info_send(TALLOC_CTX *mem_ctx,
+                   struct tevent_context *ev,
+                   struct sdap_handle *sh,
+                   struct sdap_options *opts,
+                   const char *hostname,
+                   struct sdap_attr_map *host_map,
+                   struct sdap_attr_map *hostgroup_map,
+                   struct sdap_search_base **search_bases);
+
+errno_t
+sdap_host_info_recv(struct tevent_req *req,
+                   TALLOC_CTX *mem_ctx,
+                   size_t *host_count,
+                   struct sysdb_attrs ***hosts,
+                   size_t *hostgroup_count,
+                   struct sysdb_attrs ***hostgroups);
+
 struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
                                   struct tevent_context *ev,
                                   struct sdap_handle *sh,
diff --git a/src/providers/ldap/sdap_async_hosts.c b/src/providers/ldap/sdap_async_hosts.c
new file mode 100644
index 0000000..75579f4
--- /dev/null
+++ b/src/providers/ldap/sdap_async_hosts.c
@@ -0,0 +1,459 @@
+/*
+    SSSD
+
+    Authors:
+        Jan Zeleny <jzel...@redhat.com>
+
+    Copyright (C) 2012 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "db/sysdb.h"
+#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/ldap_common.h"
+
+struct sdap_host_state {
+    struct tevent_context *ev;
+    struct sysdb_ctx *sysdb;
+    struct sdap_handle *sh;
+    struct sdap_options *opts;
+    const char **attrs;
+    struct sdap_attr_map *host_map;
+    struct sdap_attr_map *hostgroup_map;
+
+    struct sdap_search_base **search_bases;
+    int search_base_iter;
+
+    char *cur_filter;
+    char *host_filter;
+
+    const char *hostname;
+
+    /* Return values */
+    size_t host_count;
+    struct sysdb_attrs **hosts;
+
+    size_t hostgroup_count;
+    struct sysdb_attrs **hostgroups;
+};
+
+static void
+sdap_host_info_done(struct tevent_req *subreq);
+
+static void
+sdap_hostgroup_info_done(struct tevent_req *subreq);
+
+static errno_t
+sdap_host_info_next(struct tevent_req *req,
+                        struct sdap_host_state *state);
+static errno_t
+sdap_hostgroup_info_next(struct tevent_req *req,
+                             struct sdap_host_state *state);
+
+/**
+ * hostname == NULL -> look up all hosts / host groups
+ * hostname != NULL -> look up only given host and groups
+ *                     it's member of
+ * hostgroup_map == NULL -> skip looking up hostgroups
+ */
+struct tevent_req *
+sdap_host_info_send(TALLOC_CTX *mem_ctx,
+                   struct tevent_context *ev,
+                   struct sdap_handle *sh,
+                   struct sdap_options *opts,
+                   const char *hostname,
+                   struct sdap_attr_map *host_map,
+                   struct sdap_attr_map *hostgroup_map,
+                   struct sdap_search_base **search_bases)
+{
+    errno_t ret;
+    struct sdap_host_state *state;
+    struct tevent_req *req;
+
+    req = tevent_req_create(mem_ctx, &state, struct sdap_host_state);
+    if (req == NULL) {
+        return NULL;
+    }
+
+    state->ev = ev;
+    state->sh = sh;
+    state->opts = opts;
+    state->hostname = hostname;
+    state->search_bases = search_bases;
+    state->search_base_iter = 0;
+    state->cur_filter = NULL;
+    state->host_map = host_map;
+    state->hostgroup_map = hostgroup_map;
+
+    ret = build_attrs_from_map(state, host_map, SDAP_OPTS_HOST,
+                               NULL, &state->attrs, NULL);
+    if (ret != EOK) {
+        goto immediate;
+    }
+
+    if (hostname == NULL) {
+        state->host_filter = talloc_asprintf(state, "(objectClass=%s)",
+                                             host_map[SDAP_OC_HOST].name);
+    } else {
+        state->host_filter = talloc_asprintf(state, "(&(objectClass=%s)(%s=%s))",
+                                             host_map[SDAP_OC_HOST].name,
+                                             host_map[SDAP_AT_HOST_FQDN].name,
+                                             hostname);
+    }
+    if (state->host_filter == NULL) {
+        ret = ENOMEM;
+        goto immediate;
+    }
+
+    ret = sdap_host_info_next(req, state);
+    if (ret == EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "No host search base configured?\n");
+        ret = EINVAL;
+    }
+
+    if (ret != EAGAIN) {
+        goto immediate;
+    }
+
+    return req;
+
+immediate:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
+    }
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static errno_t sdap_host_info_next(struct tevent_req *req,
+                                   struct sdap_host_state *state)
+{
+    struct sdap_search_base *base;
+    struct tevent_req *subreq;
+
+    base = state->search_bases[state->search_base_iter];
+    if (base == NULL) {
+        return EOK;
+    }
+
+    talloc_zfree(state->cur_filter);
+    state->cur_filter = sdap_combine_filters(state, state->host_filter,
+                                             base->filter);
+    if (state->cur_filter == NULL) {
+        return ENOMEM;
+    }
+
+    subreq = sdap_get_generic_send(state, state->ev, state->opts,
+                                   state->sh, base->basedn,
+                                   base->scope, state->cur_filter,
+                                   state->attrs, state->host_map,
+                                   SDAP_OPTS_HOST,
+                                   dp_opt_get_int(state->opts->basic,
+                                                  SDAP_ENUM_SEARCH_TIMEOUT),
+                                   true);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting host info\n");
+        talloc_zfree(state->cur_filter);
+        return EIO;
+    }
+    tevent_req_set_callback(subreq, sdap_host_info_done, req);
+
+    return EAGAIN;
+}
+
+static void
+sdap_host_info_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req =
+            tevent_req_callback_data(subreq, struct tevent_req);
+    struct sdap_host_state *state =
+            tevent_req_data(req, struct sdap_host_state);
+    const char *host_dn;
+    struct sdap_attr_map_info *maps;
+    const int num_maps = 1;
+
+    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 (state->host_count == 0) {
+        state->search_base_iter++;
+        ret = sdap_host_info_next(req, state);
+        if (ret == EOK) {
+            /* No more search bases to try */
+            tevent_req_error(req, ENOENT);
+        } else if (ret != EAGAIN) {
+            tevent_req_error(req, ret);
+        }
+        return;
+    }
+
+    if (state->hostgroup_map) {
+        talloc_free(state->attrs);
+        ret = build_attrs_from_map(state, state->hostgroup_map,
+                                   SDAP_OPTS_HOSTGROUP, NULL,
+                                   &state->attrs, NULL);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+
+        /* Look up host groups */
+        if (state->hostname == NULL) {
+            talloc_zfree(state->host_filter);
+            state->host_filter = talloc_asprintf(state, "(objectClass=%s)",
+                                    state->hostgroup_map[SDAP_OC_HOSTGROUP].name);
+            if (state->host_filter == NULL) {
+                tevent_req_error(req, ENOMEM);
+                return;
+            }
+            state->search_base_iter = 0;
+
+            ret = sdap_hostgroup_info_next(req, state);
+            if (ret == EOK) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "No host search base configured?\n");
+                tevent_req_error(req, EINVAL);
+                return;
+            } else if (ret != EAGAIN) {
+                tevent_req_error(req, ret);
+                return;
+            }
+        } else {
+            ret = sysdb_attrs_get_string(state->hosts[0], SYSDB_ORIG_DN, &host_dn);
+            if (ret != EOK) {
+                tevent_req_error(req, ret);
+                return;
+            }
+
+            if (!sdap_has_deref_support(state->sh, state->opts)) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "Server does not support deref\n");
+                tevent_req_error(req, EIO);
+                return;
+            }
+
+            maps = talloc_array(state, struct sdap_attr_map_info, num_maps+1);
+            if (maps == NULL) {
+                tevent_req_error(req, ENOMEM);
+                return;
+            }
+            maps[0].map = state->hostgroup_map;
+            maps[0].num_attrs = SDAP_OPTS_HOSTGROUP;
+            maps[1].map = NULL;
+
+            subreq = sdap_deref_search_send(state, state->ev, state->opts, state->sh,
+                                            host_dn,
+                                            state->hostgroup_map[SDAP_AT_HOSTGROUP_MEMBER_OF].name,
+                                            state->attrs,
+                                            num_maps, maps,
+                                            dp_opt_get_int(state->opts->basic,
+                                                           SDAP_ENUM_SEARCH_TIMEOUT));
+            if (subreq == NULL) {
+                talloc_free(maps);
+                DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting host info\n");
+                tevent_req_error(req, EIO);
+                return;
+            }
+            tevent_req_set_callback(subreq, sdap_hostgroup_info_done, req);
+        }
+    } else {
+        /* Nothing else to do, just complete the req */
+        tevent_req_done(req);
+    }
+}
+
+static errno_t sdap_hostgroup_info_next(struct tevent_req *req,
+                                        struct sdap_host_state *state)
+{
+    struct sdap_search_base *base;
+    struct tevent_req *subreq;
+
+    base = state->search_bases[state->search_base_iter];
+    if (base == NULL) {
+        return EOK;
+    }
+
+    talloc_zfree(state->cur_filter);
+    state->cur_filter = sdap_combine_filters(state, state->host_filter,
+                                             base->filter);
+    if (state->cur_filter == NULL) {
+        return ENOMEM;
+    }
+
+    subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
+                                   base->basedn, base->scope,
+                                   state->cur_filter, state->attrs,
+                                   state->hostgroup_map,
+                                   SDAP_OPTS_HOSTGROUP,
+                                   dp_opt_get_int(state->opts->basic,
+                                                  SDAP_ENUM_SEARCH_TIMEOUT),
+                                   true);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting hostgroup info\n");
+        talloc_zfree(state->cur_filter);
+        return EIO;
+    }
+    tevent_req_set_callback(subreq, sdap_hostgroup_info_done, req);
+
+    return EAGAIN;
+}
+
+static void
+sdap_hostgroup_info_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req =
+            tevent_req_callback_data(subreq, struct tevent_req);
+    struct sdap_host_state *state =
+            tevent_req_data(req, struct sdap_host_state);
+
+    size_t hostgroups_total;
+    size_t hostgroup_count;
+    struct sysdb_attrs **hostgroups;
+    struct sdap_deref_attrs **deref_result;
+    const char *hostgroup_name;
+    const char *hostgroup_dn;
+    int i, j;
+
+    if (state->hostname == NULL) {
+        ret = sdap_get_generic_recv(subreq, state,
+                                    &hostgroup_count,
+                                    &hostgroups);
+        talloc_zfree(subreq);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sdap_get_generic_recv failed: [%d]\n", ret);
+            tevent_req_error(req, ret);
+            return;
+        }
+
+        /* Merge the two arrays */
+        if (hostgroup_count > 0) {
+            hostgroups_total = hostgroup_count + state->hostgroup_count;
+            state->hostgroups = talloc_realloc(state, state->hostgroups,
+                                               struct sysdb_attrs *,
+                                               hostgroups_total);
+            if (state->hostgroups == NULL) {
+                tevent_req_error(req, ENOMEM);
+                return;
+            }
+
+            i = 0;
+            while(state->hostgroup_count < hostgroups_total) {
+                state->hostgroups[state->hostgroup_count] =
+                    talloc_steal(state->hostgroups, hostgroups[i]);
+                state->hostgroup_count++;
+                i++;
+            }
+        }
+
+        /* Now look in the next base */
+        state->search_base_iter++;
+        ret = sdap_hostgroup_info_next(req, state);
+        if (ret != EOK && ret != EAGAIN) {
+            tevent_req_error(req, ret);
+        }
+
+        if (ret != EOK) {
+            /* Only continue if no error occurred
+             * and no req was created */
+            return;
+        }
+    } 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;
+            }
+
+            j = 0;
+            for (i = 0; i < state->hostgroup_count; i++) {
+                ret = sysdb_attrs_get_string(deref_result[i]->attrs,
+                                             SYSDB_ORIG_DN, &hostgroup_dn);
+                if (ret != EOK) goto done;
+
+                if (!sss_ldap_dn_in_search_bases(state, hostgroup_dn,
+                                                 state->search_bases,
+                                                 NULL)) {
+                    continue;
+                }
+
+                ret = sysdb_attrs_get_string(deref_result[i]->attrs,
+                             state->hostgroup_map[SDAP_AT_HOSTGROUP_NAME].sys_name,
+                             &hostgroup_name);
+                if (ret != EOK) goto done;
+
+                DEBUG(SSSDBG_FUNC_DATA, "Dereferenced host group: %s\n",
+                                        hostgroup_name);
+                state->hostgroups[j] = talloc_steal(state->hostgroups,
+                                                    deref_result[i]->attrs);
+                j++;
+            }
+            state->hostgroup_count = j;
+        }
+    }
+
+done:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        DEBUG(SSSDBG_OP_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
+        tevent_req_error(req, ret);
+    }
+}
+
+errno_t sdap_host_info_recv(struct tevent_req *req,
+                           TALLOC_CTX *mem_ctx,
+                           size_t *host_count,
+                           struct sysdb_attrs ***hosts,
+                           size_t *hostgroup_count,
+                           struct sysdb_attrs ***hostgroups)
+{
+    size_t c;
+    struct sdap_host_state *state =
+            tevent_req_data(req, struct sdap_host_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *host_count = state->host_count;
+    *hosts = talloc_steal(mem_ctx, state->hosts);
+    for (c = 0; c < state->host_count; c++) {
+        /* Guarantee the memory heirarchy of the list */
+        talloc_steal(state->hosts, state->hosts[c]);
+    }
+
+    if (hostgroup_count) *hostgroup_count = state->hostgroup_count;
+    if (hostgroups) *hostgroups = talloc_steal(mem_ctx, state->hostgroups);
+
+    return EOK;
+}
diff --git a/src/providers/ldap/sdap_hostid.c b/src/providers/ldap/sdap_hostid.c
new file mode 100644
index 0000000..b3cd676
--- /dev/null
+++ b/src/providers/ldap/sdap_hostid.c
@@ -0,0 +1,325 @@
+/*
+    Authors:
+        Jan Cholasta <jchol...@redhat.com>
+
+    Copyright (C) 2012 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "util/crypto/sss_crypto.h"
+#include "db/sysdb_ssh.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_hostid.h"
+
+struct hosts_get_state {
+    struct tevent_context *ev;
+    struct sdap_id_ctx *id_ctx;
+    struct sdap_id_op *op;
+    struct sss_domain_info *domain;
+    const char *name;
+    const char *alias;
+
+    size_t count;
+    struct sysdb_attrs **hosts;
+    int dp_error;
+};
+
+static errno_t
+hosts_get_retry(struct tevent_req *req);
+static void
+hosts_get_connect_done(struct tevent_req *subreq);
+static void
+hosts_get_done(struct tevent_req *subreq);
+
+struct tevent_req *
+hosts_get_send(TALLOC_CTX *memctx,
+               struct tevent_context *ev,
+               struct sdap_id_ctx *id_ctx,
+               const char *name,
+               const char *alias)
+{
+    struct tevent_req *req;
+    struct hosts_get_state *state;
+    errno_t ret;
+
+    req = tevent_req_create(memctx, &state, struct hosts_get_state);
+    if (!req) return NULL;
+
+    state->ev = ev;
+    state->id_ctx = id_ctx;
+    state->dp_error = DP_ERR_FATAL;
+
+    state->op = sdap_id_op_create(state, id_ctx->conn->conn_cache);
+    if (!state->op) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
+        ret = ENOMEM;
+        goto fail;
+    }
+
+    state->domain = id_ctx->be->domain;
+    state->name = name;
+    state->alias = alias;
+
+    ret = hosts_get_retry(req);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    return req;
+
+fail:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static errno_t
+hosts_get_retry(struct tevent_req *req)
+{
+    struct hosts_get_state *state = tevent_req_data(req,
+                                                    struct hosts_get_state);
+    struct tevent_req *subreq;
+    errno_t ret = EOK;
+
+    subreq = sdap_id_op_connect_send(state->op, state, &ret);
+    if (!subreq) {
+        return ret;
+    }
+
+    tevent_req_set_callback(subreq, hosts_get_connect_done, req);
+    return EOK;
+}
+
+static void
+hosts_get_connect_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct hosts_get_state *state = tevent_req_data(req,
+                                                    struct hosts_get_state);
+    int dp_error = DP_ERR_FATAL;
+    errno_t ret;
+
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+
+    if (ret != EOK) {
+        state->dp_error = dp_error;
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    subreq = sdap_host_info_send(state, state->ev,
+                                 sdap_id_op_handle(state->op),
+                                 state->id_ctx->opts, state->name,
+                                 state->id_ctx->opts->host_map, NULL,
+                                 state->id_ctx->opts->sdom->host_search_bases);
+    if (!subreq) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+    tevent_req_set_callback(subreq, hosts_get_done, req);
+}
+
+static void
+hosts_get_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct hosts_get_state *state = tevent_req_data(req,
+                                                    struct hosts_get_state);
+    int dp_error = DP_ERR_FATAL;
+    errno_t ret;
+    struct sysdb_attrs *attrs;
+    time_t now = time(NULL);
+
+    ret = sdap_host_info_recv(subreq, state,
+                              &state->count, &state->hosts,
+                              NULL, NULL);
+    talloc_zfree(subreq);
+
+    ret = sdap_id_op_done(state->op, ret, &dp_error);
+    if (dp_error == DP_ERR_OK && ret != EOK) {
+        /* retry */
+        ret = hosts_get_retry(req);
+        if (ret != EOK) {
+            goto done;
+        }
+        return;
+    }
+
+    if (ret != EOK && ret != ENOENT) {
+        goto done;
+    }
+
+    if (state->count == 0) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "No host with name [%s] found.\n", state->name);
+
+        ret = sysdb_delete_ssh_host(state->domain, state->name);
+        if (ret != EOK && ret != ENOENT) {
+            goto done;
+        }
+
+        ret = EINVAL;
+        goto done;
+    }
+
+    if (state->count > 1) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Found more than one host with name [%s].\n", state->name);
+        ret = EINVAL;
+        goto done;
+    }
+
+    attrs = sysdb_new_attrs(state);
+    if (!attrs) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* we are interested only in the host keys */
+    ret = sysdb_attrs_copy_values(state->hosts[0], attrs, SYSDB_SSH_PUBKEY);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    ret = sysdb_store_ssh_host(state->domain, state->name, state->alias,
+                               state->domain->ssh_host_timeout, now, attrs);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    dp_error = DP_ERR_OK;
+
+done:
+    state->dp_error = dp_error;
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
+    }
+}
+
+static errno_t
+hosts_get_recv(struct tevent_req *req,
+               int *dp_error_out)
+{
+    struct hosts_get_state *state = tevent_req_data(req,
+                                                    struct hosts_get_state);
+
+    if (dp_error_out) {
+        *dp_error_out = state->dp_error;
+    }
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    return EOK;
+}
+
+struct sdap_hostid_handler_state {
+    struct dp_reply_std reply;
+};
+
+static void sdap_hostid_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sdap_hostid_handler_send(TALLOC_CTX *mem_ctx,
+                         struct sdap_id_ctx *id_ctx,
+                         struct dp_hostid_data *data,
+                         struct dp_req_params *params)
+{
+    struct sdap_hostid_handler_state *state;
+    struct tevent_req *subreq;
+    struct tevent_req *req;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state, struct sdap_hostid_handler_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+        return NULL;
+    }
+
+    subreq = hosts_get_send(state, params->ev, id_ctx,
+                            data->name, data->alias);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request\n");
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    tevent_req_set_callback(subreq, sdap_hostid_handler_done, req);
+
+    return req;
+
+immediately:
+    dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+
+    /* TODO For backward compatibility we always return EOK to DP now. */
+    tevent_req_done(req);
+    tevent_req_post(req, params->ev);
+
+    return req;
+}
+
+static void sdap_hostid_handler_done(struct tevent_req *subreq)
+{
+    struct sdap_hostid_handler_state *state;
+    struct tevent_req *req;
+    int dp_error;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_hostid_handler_state);
+
+    ret = hosts_get_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+
+    /* TODO For backward compatibility we always return EOK to DP now. */
+    dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+    tevent_req_done(req);
+}
+
+errno_t
+sdap_hostid_handler_recv(TALLOC_CTX *mem_ctx,
+                         struct tevent_req *req,
+                         struct dp_reply_std *data)
+{
+    struct sdap_hostid_handler_state *state = NULL;
+
+    state = tevent_req_data(req, struct sdap_hostid_handler_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *data = state->reply;
+
+    return EOK;
+}
+
+errno_t sdap_hostid_init(TALLOC_CTX *mem_ctx,
+                         struct be_ctx *be_ctx,
+                         struct sdap_id_ctx *id_ctx,
+                         struct dp_method *dp_methods)
+{
+    (void)be_ctx;
+
+    dp_set_method(dp_methods, DPM_HOSTID_HANDLER,
+                  sdap_hostid_handler_send, sdap_hostid_handler_recv, id_ctx,
+                  struct sdap_id_ctx, struct dp_hostid_data, struct dp_reply_std);
+
+    return EOK;
+}
diff --git a/src/providers/ldap/sdap_hostid.h b/src/providers/ldap/sdap_hostid.h
new file mode 100644
index 0000000..6968cbd
--- /dev/null
+++ b/src/providers/ldap/sdap_hostid.h
@@ -0,0 +1,41 @@
+/*
+    Authors:
+        Jan Cholasta <jchol...@redhat.com>
+
+    Copyright (C) 2012 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _SDAP_HOSTID_H_
+#define _SDAP_HOSTID_H_
+
+errno_t sdap_hostid_init(TALLOC_CTX *mem_ctx,
+                         struct be_ctx *be_ctx,
+                         struct sdap_id_ctx *id_ctx,
+                         struct dp_method *dp_methods);
+
+struct tevent_req *
+sdap_hostid_handler_send(TALLOC_CTX *mem_ctx,
+                         struct sdap_id_ctx *id_ctx,
+                         struct dp_hostid_data *data,
+                         struct dp_req_params *params);
+
+errno_t
+sdap_hostid_handler_recv(TALLOC_CTX *mem_ctx,
+                         struct tevent_req *req,
+                         struct dp_reply_std *data);
+
+#endif /* _SDAP_HOSTID_H_ */
+
diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c
index 30e09f7..339406d 100644
--- a/src/tests/ipa_ldap_opt-tests.c
+++ b/src/tests/ipa_ldap_opt-tests.c
@@ -230,8 +230,8 @@ START_TEST(test_sdap_opt_sentinel)
     fail_unless_sdap_opt_is_terminator(&ad_netgroup_map[SDAP_OPTS_NETGROUP]);
     fail_unless_sdap_opt_is_terminator(&ipa_netgroup_map[IPA_OPTS_NETGROUP]);
 
-    fail_unless_sdap_opt_is_terminator(&ipa_host_map[IPA_OPTS_HOST]);
-    fail_unless_sdap_opt_is_terminator(&ipa_hostgroup_map[IPA_OPTS_HOSTGROUP]);
+    fail_unless_sdap_opt_is_terminator(&ipa_host_map[SDAP_OPTS_HOST]);
+    fail_unless_sdap_opt_is_terminator(&ipa_hostgroup_map[SDAP_OPTS_HOSTGROUP]);
     fail_unless_sdap_opt_is_terminator(&ipa_selinux_user_map[IPA_OPTS_SELINUX_USERMAP]);
     fail_unless_sdap_opt_is_terminator(&ipa_view_map[IPA_OPTS_VIEW]);
     fail_unless_sdap_opt_is_terminator(&ipa_override_map[IPA_OPTS_OVERRIDE]);
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to