summaryrefslogtreecommitdiff
path: root/src/providers/ipa
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ipa')
-rw-r--r--src/providers/ipa/ipa_common.h1
-rw-r--r--src/providers/ipa/ipa_init.c29
-rw-r--r--src/providers/ipa/ipa_opts.h1
-rw-r--r--src/providers/ipa/ipa_srv.c296
-rw-r--r--src/providers/ipa/ipa_srv.h47
5 files changed, 369 insertions, 5 deletions
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index e3915beb..ae1c9173 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 cdca706d..b65a6cea 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_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;
+ 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 970d05b3..a3d0210a 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_FALSE, BOOL_FALSE },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/ipa/ipa_srv.c b/src/providers/ipa/ipa_srv.c
new file mode 100644
index 00000000..34a85b56
--- /dev/null
+++ b/src/providers/ipa/ipa_srv.c
@@ -0,0 +1,296 @@
+/*
+ Authors:
+ Pavel B??ezina <pbrezina@redhat.com>
+
+ 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 (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 00000000..e92479aa
--- /dev/null
+++ b/src/providers/ipa/ipa_srv.h
@@ -0,0 +1,47 @@
+/*
+ Authors:
+ Pavel B??ezina <pbrezina@redhat.com>
+
+ 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__ */