On 04/08/2013 12:28 PM, Pavel Březina wrote:
This has to be applied atop the first way.

Feel free to ping me for testing environment.

Addressed some review issues raised in other thread.

From 28e137ab41b348052a676c99bc6e99385cd59c3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <[email protected]>
Date: Tue, 9 Apr 2013 13:16:23 +0200
Subject: [PATCH] DNS sites support - add IPA SRV plugin

https://fedorahosted.org/sssd/ticket/1032
---
 Makefile.am                             |   2 +
 src/config/SSSDConfig/__init__.py.in    |   1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf |   1 +
 src/man/sssd-ipa.5.xml                  |  21 +++
 src/providers/ipa/ipa_common.h          |   1 +
 src/providers/ipa/ipa_init.c            |  29 ++-
 src/providers/ipa/ipa_opts.h            |   1 +
 src/providers/ipa/ipa_srv.c             | 300 ++++++++++++++++++++++++++++++++
 src/providers/ipa/ipa_srv.h             |  47 +++++
 9 files changed, 398 insertions(+), 5 deletions(-)
 create mode 100644 src/providers/ipa/ipa_srv.c
 create mode 100644 src/providers/ipa/ipa_srv.h

diff --git a/Makefile.am b/Makefile.am
index dc9a7be59f41d4b667495d5ec89a3935e612ca33..01114aae9ff51cc041638a7b0567a39b4f07826a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -463,6 +463,7 @@ dist_noinst_HEADERS = \
     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/proxy/proxy.h \
     src/tools/tools_util.h \
     src/tools/sss_sync_ops.h \
@@ -1485,6 +1486,7 @@ libsss_ipa_la_SOURCES = \
     src/providers/ipa/ipa_selinux.c \
     src/providers/ipa/ipa_selinux_maps.c \
     src/providers/ipa/ipa_selinux_common.c \
+    src/providers/ipa/ipa_srv.c \
     src/util/user_info_msg.c \
     src/util/find_uid.c \
     src/util/sss_ldap.c \
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index a1f223956b2d1a009c57ea5834e4d53c41d8c055..1f997f23813d3e6e3f7360ae8d9e0b8aea391345 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -142,6 +142,7 @@ option_strings = {
     'ipa_automount_location' : _("The automounter location this IPA client is using"),
     'ipa_master_domain_search_base': _("Search base for object containing info about IPA domain"),
     'ipa_ranges_search_base': _("Search base for objects containing info about ID ranges"),
+    'ipa_enable_dns_sites': _("Enable DNS sites - location based service discovery"),
 
     # [provider/ad]
     'ad_domain' : _('Active Directory domain'),
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index a165bc23afdfb6e691acddbb07c74d4e4672bb14..04855d6cece3876e4fa191ae02747b6d88048f8d 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -10,6 +10,7 @@ ipa_hbac_search_base = str, None, false
 ipa_host_search_base = str, None, false
 ipa_master_domain_search_base = str, None, false
 ipa_ranges_search_base = str, None, false
+ipa_enable_dns_sites = bool, None, false
 ldap_uri = str, None, false
 ldap_backup_uri = str, None, false
 ldap_search_base = str, None, false
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index c4227da23c3c4adafc529919d930a2ea02796f82..758e7999370a5ba96afb444738af9fdbea357ca8 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -158,6 +158,27 @@
                         </para>
                     </listitem>
                 </varlistentry>
+                
+                <varlistentry>
+                    <term>ipa_enable_dns_sites (boolean)</term>
+                    <listitem>
+                        <para>
+                            Enables/disables DNS sites - location based
+                            service discovery.
+                        </para>
+                        <para>
+                            If true and _srv_ is present in ipa_server,
+                            SSSD will search for SRV records in
+                            (1) _location.hostname.example.com, (2) example.com.
+                            If (1) exists, it is expected to contain primary
+                            servers and (2) is treated as backup servers. If (1)
+                            does not exist, (2) is treated as primary servers.
+                        </para>
+                        <para>
+                            Default: true
+                        </para>
+                    </listitem>
+                </varlistentry>
 
                 <varlistentry>
                     <term>ipa_hbac_search_base (string)</term>
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index e3915bebc21d88459cf5574264b901e6bd3657ff..ae1c91731e9637c06dad555d1a87ef2e0cf53184 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -52,6 +52,7 @@ enum ipa_basic_opt {
     IPA_HBAC_SUPPORT_SRCHOST,
     IPA_AUTOMOUNT_LOCATION,
     IPA_RANGES_SEARCH_BASE,
+    IPA_ENABLE_DNS_SITES,
 
     IPA_OPTS_BASIC /* opts counter */
 };
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 7d97dc0c2b02c4f5f22ccdce47a2381bb8158333..b65a6cea1ddd05272a8ae522be5c8b070a93ac1e 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -39,6 +39,7 @@
 #include "providers/ipa/ipa_selinux.h"
 #include "providers/ldap/sdap_access.h"
 #include "providers/ipa/ipa_subdomains.h"
+#include "providers/ipa/ipa_srv.h"
 
 struct ipa_options *ipa_options = NULL;
 
@@ -111,6 +112,8 @@ int sssm_ipa_id_init(struct be_ctx *bectx,
     struct sdap_id_ctx *sdap_ctx;
     struct stat stat_buf;
     const char *hostname;
+    const char *ipa_domain;
+    struct ipa_srv_plugin_ctx *srv_ctx;
     errno_t err;
     int ret;
 
@@ -210,11 +213,27 @@ int sssm_ipa_id_init(struct be_ctx *bectx,
 
     /* setup SRV lookup plugin */
     hostname = dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME);
-    ret = be_fo_set_standard_srv_lookup_plugin(bectx, hostname);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to set SRV lookup plugin "
-                                    "[%d]: %s\n", ret, strerror(ret)));
-        goto done;
+    if (dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES)) {
+        /* use IPA plugin */
+        ipa_domain = dp_opt_get_string(ipa_options->basic, IPA_DOMAIN);
+        srv_ctx = ipa_srv_plugin_ctx_init(bectx, bectx->be_res->resolv,
+                                          hostname, ipa_domain);
+        if (srv_ctx == NULL) {
+            DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n"));
+            ret = ENOMEM;
+            goto done;
+        }
+
+        be_fo_set_srv_lookup_plugin(bectx, ipa_srv_plugin_send,
+                                    ipa_srv_plugin_recv, srv_ctx, "IPA");
+    } else {
+        /* fall back to standard plugin */
+        ret = be_fo_set_dns_srv_lookup_plugin(bectx, hostname);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to set SRV lookup plugin "
+                                        "[%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
     }
 
     *ops = &ipa_id_ops;
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 970d05b3921463f33c860f70c2a5b75f6b5f4e7d..f479d3d0abbc11cf42216312765ac61e06afe2ab 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -50,6 +50,7 @@ struct dp_option ipa_basic_opts[] = {
     { "ipa_hbac_support_srchost", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ipa_automount_location", DP_OPT_STRING, { "default" }, NULL_STRING },
     { "ipa_ranges_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "ipa_enable_dns_sites", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/providers/ipa/ipa_srv.c b/src/providers/ipa/ipa_srv.c
new file mode 100644
index 0000000000000000000000000000000000000000..3854bf94b030521634d727e34d433fdb6fa9ebec
--- /dev/null
+++ b/src/providers/ipa/ipa_srv.c
@@ -0,0 +1,300 @@
+/*
+    Authors:
+        Pavel Březina <[email protected]>
+
+    Copyright (C) 2013 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 <string.h>
+#include <talloc.h>
+#include <tevent.h>
+
+#include "util/util.h"
+#include "resolv/async_resolv.h"
+#include "providers/fail_over_srv.h"
+
+#define IPA_DNS_LOCATION "_location"
+
+struct ipa_srv_plugin_ctx {
+    struct resolv_ctx *resolv_ctx;
+    const char *hostname;
+    const char *ipa_domain;
+};
+
+struct ipa_srv_plugin_ctx *
+ipa_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
+                        struct resolv_ctx *resolv_ctx,
+                        const char *hostname,
+                        const char *ipa_domain)
+{
+    struct ipa_srv_plugin_ctx *ctx = NULL;
+
+    ctx = talloc_zero(mem_ctx, struct ipa_srv_plugin_ctx);
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+    ctx->resolv_ctx = resolv_ctx;
+
+    ctx->hostname = talloc_strdup(ctx, hostname);
+    if (ctx->hostname == NULL) {
+        goto fail;
+    }
+
+    ctx->ipa_domain = talloc_strdup(ctx, ipa_domain);
+    if (ctx->ipa_domain == NULL) {
+        goto fail;
+    }
+
+    return ctx;
+
+fail:
+    talloc_free(ctx);
+    return NULL;
+}
+
+struct ipa_srv_plugin_state {
+    struct tevent_context *ev;
+    struct ipa_srv_plugin_ctx *ctx;
+    const char *service;
+    const char *protocol;
+    const char *discovery_domain;
+
+    char *dns_domain;
+    struct fo_server_info *primary_servers;
+    size_t num_primary_servers;
+    struct fo_server_info *backup_servers;
+    size_t num_backup_servers;
+};
+
+static void ipa_srv_plugin_primary_done(struct tevent_req *subreq);
+static void ipa_srv_plugin_backup_done(struct tevent_req *subreq);
+
+/* If IPA server supports sites, we will use
+ * _locations.hostname.discovery_domain for primary servers and
+ * discovery_domain for backup servers. If the server does not support sites or
+ * client's SRV record is not found, we will use the latter for primary
+ * servers, setting backup servers to NULL */
+struct tevent_req *ipa_srv_plugin_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       const char *service,
+                                       const char *protocol,
+                                       const char *discovery_domain,
+                                       void *pvt)
+{
+    struct ipa_srv_plugin_state *state = NULL;
+    struct ipa_srv_plugin_ctx *ctx = NULL;
+    struct tevent_req *req = NULL;
+    struct tevent_req *subreq = NULL;
+    const char **domains = NULL;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct ipa_srv_plugin_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
+        return NULL;
+    }
+
+    ctx = talloc_get_type(pvt, struct ipa_srv_plugin_ctx);
+    if (ctx == NULL) {
+        ret = EINVAL;
+        goto immediately;
+    }
+
+    state->ev = ev;
+    state->ctx = ctx;
+    state->service = service;
+    state->protocol = protocol;
+    if (state->protocol == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    if (discovery_domain != NULL) {
+        state->discovery_domain = discovery_domain;
+    } else {
+        state->discovery_domain = ctx->ipa_domain;
+    }
+    if (state->discovery_domain == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Looking up primary servers\n"));
+
+    domains = talloc_zero_array(state, const char *, 3);
+    if (domains == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    if (strchr(ctx->hostname, '.') == NULL) {
+        /* not FQDN, append domain name */
+        domains[0] = talloc_asprintf(domains, IPA_DNS_LOCATION ".%s.%s",
+                                     ctx->hostname, state->discovery_domain);
+    } else {
+        domains[0] = talloc_asprintf(domains, IPA_DNS_LOCATION ".%s",
+                                     ctx->hostname);
+    }
+    if (domains[0] == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+    domains[1] = state->discovery_domain;
+
+    subreq = fo_discover_srv_send(state, ev, ctx->resolv_ctx,
+                                  state->service, state->protocol, domains);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    tevent_req_set_callback(subreq, ipa_srv_plugin_primary_done, req);
+
+    return req;
+
+immediately:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+
+    return req;
+}
+
+static void ipa_srv_plugin_primary_done(struct tevent_req *subreq)
+{
+    struct ipa_srv_plugin_state *state = NULL;
+    struct tevent_req *req = NULL;
+    const char **domains = NULL;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct ipa_srv_plugin_state);
+
+    ret = fo_discover_srv_recv(state, subreq,
+                               &state->dns_domain,
+                               &state->primary_servers,
+                               &state->num_primary_servers);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    if (strcmp(state->dns_domain, state->discovery_domain) == 0) {
+        /* IPA server does not support sites or this host is in default site */
+        state->backup_servers = NULL;
+        state->num_backup_servers = 0;
+
+        ret = EOK;
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Looking up backup servers\n"));
+
+    domains = talloc_zero_array(state, const char *, 3);
+    if (domains == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    domains[0] = state->discovery_domain;
+
+    subreq = fo_discover_srv_send(state, state->ev, state->ctx->resolv_ctx,
+                                  state->service, state->protocol, domains);
+    if (subreq == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    tevent_req_set_callback(subreq, ipa_srv_plugin_backup_done, req);
+
+    ret = EAGAIN;
+
+done:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else if (ret != EAGAIN) {
+        tevent_req_error(req, ret);
+    }
+
+    return;
+}
+
+static void ipa_srv_plugin_backup_done(struct tevent_req *subreq)
+{
+    struct ipa_srv_plugin_state *state = NULL;
+    struct tevent_req *req = NULL;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct ipa_srv_plugin_state);
+
+    ret = fo_discover_srv_recv(state, subreq, NULL,
+                               &state->backup_servers,
+                               &state->num_backup_servers);
+    talloc_zfree(subreq);
+    if (ret == ERR_SRV_NOT_FOUND || ret == ERR_SRV_LOOKUP_ERROR) {
+        /* we have successfully fetched primary servers, so we will
+         * finish the request normally */
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Unable to retrieve backup servers "
+                                     "[%d]: %s\n", ret, sss_strerror(ret)));
+        ret = EOK;
+    }
+
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t ipa_srv_plugin_recv(TALLOC_CTX *mem_ctx,
+                            struct tevent_req *req,
+                            char **_dns_domain,
+                            struct fo_server_info **_primary_servers,
+                            size_t *_num_primary_servers,
+                            struct fo_server_info **_backup_servers,
+                            size_t *_num_backup_servers)
+{
+    struct ipa_srv_plugin_state *state = NULL;
+    state = tevent_req_data(req, struct ipa_srv_plugin_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    if (_primary_servers) {
+        *_primary_servers = talloc_steal(mem_ctx, state->primary_servers);
+    }
+
+    if (_num_primary_servers) {
+        *_num_primary_servers = state->num_primary_servers;
+    }
+
+    if (_backup_servers) {
+        *_backup_servers = talloc_steal(mem_ctx, state->backup_servers);
+    }
+
+    if (_num_backup_servers) {
+        *_num_backup_servers = state->num_backup_servers;
+    }
+
+    if (_dns_domain) {
+        *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
+    }
+
+
+    return EOK;
+}
diff --git a/src/providers/ipa/ipa_srv.h b/src/providers/ipa/ipa_srv.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bfd2eeaebec6ae9d2826aa76060746a32a634fc
--- /dev/null
+++ b/src/providers/ipa/ipa_srv.h
@@ -0,0 +1,47 @@
+/*
+    Authors:
+        Pavel Březina <[email protected]>
+
+    Copyright (C) 2013 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_SRV_H__
+#define __IPA_SRV_H__
+
+struct ipa_srv_plugin_ctx;
+
+struct ipa_srv_plugin_ctx *
+ipa_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
+                        struct resolv_ctx *resolv_ctx,
+                        const char *hostname,
+                        const char *ipa_domain);
+
+struct tevent_req *ipa_srv_plugin_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       const char *service,
+                                       const char *protocol,
+                                       const char *discovery_domain,
+                                       void *pvt);
+
+errno_t ipa_srv_plugin_recv(TALLOC_CTX *mem_ctx,
+                            struct tevent_req *req,
+                            char **_dns_domain,
+                            struct fo_server_info **_primary_servers,
+                            size_t *_num_primary_servers,
+                            struct fo_server_info **_backup_servers,
+                            size_t *_num_backup_servers);
+
+#endif /* __IPA_SRV_H__ */
-- 
1.7.11.7

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to