summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2010-06-01 15:36:56 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-06-30 07:35:31 -0400
commit780ffc9f6d5e1fcd4df3d390b56cb98878223cc0 (patch)
treee0d94ce0260b4435f5ea882f356adeac41c8fee7
parent2dd3faebcd3cfd00efda38ffd2585d675e696b12 (diff)
downloadsssd-780ffc9f6d5e1fcd4df3d390b56cb98878223cc0.tar.gz
sssd-780ffc9f6d5e1fcd4df3d390b56cb98878223cc0.tar.bz2
sssd-780ffc9f6d5e1fcd4df3d390b56cb98878223cc0.zip
Add dns_discovery_domain option
The service discovery used to use the SSSD domain name to perform DNS queries. This is not an optimal solution, for example from the point of view of authconfig. This patch introduces a new option "dns_discovery_domain" that allows to set the domain part of a DNS SRV query. If this option is not set, the default behavior is to use the domain part of the machine's hostname. Fixes: #479
-rw-r--r--src/confdb/confdb.h1
-rw-r--r--src/config/SSSDConfig.py1
-rwxr-xr-xsrc/config/SSSDConfigTest.py2
-rw-r--r--src/config/etc/sssd.api.conf1
-rw-r--r--src/config/upgrade_config.py26
-rw-r--r--src/man/include/service_discovery.xml9
-rw-r--r--src/man/sssd.conf.5.xml13
-rw-r--r--src/providers/data_provider_fo.c13
-rw-r--r--src/providers/dp_backend.h3
-rw-r--r--src/providers/fail_over.c198
-rw-r--r--src/providers/ipa/ipa_common.c2
-rw-r--r--src/providers/krb5/krb5_common.c2
-rw-r--r--src/providers/ldap/ldap_common.c1
13 files changed, 242 insertions, 30 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index ae7502f8..e5a0d9ab 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -101,6 +101,7 @@
#define CONFDB_DOMAIN_FQ "use_fully_qualified_names"
#define CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT "entry_cache_timeout"
#define CONFDB_DOMAIN_RESOLV_TIMEOUT "dns_resolver_timeout"
+#define CONFDB_DOMAIN_DNS_DISCOVERY_NAME "dns_discovery_domain"
#define CONFDB_DOMAIN_FAMILY_ORDER "lookup_family_order"
#define CONFDB_DOMAIN_ACCOUNT_CACHE_EXPIRATION "account_cache_expiration"
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index f1ff02aa..22013eeb 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -82,6 +82,7 @@ option_strings = {
'lookup_family_order' : _('Restrict or prefer a specific address family when performing DNS lookups'),
'account_cache_expiration' : _('How long to keep cached entries after last successful login (days)'),
'dns_resolver_timeout' : _('How long to wait for replies from DNS when resolving servers (seconds)'),
+ 'dns_discovery_domain' : _('The domain part of service discovery DNS query'),
# [provider/ipa]
'ipa_domain' : _('IPA domain'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 63d1ad11..e99a7876 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -478,6 +478,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'lookup_family_order',
'account_cache_expiration',
'dns_resolver_timeout',
+ 'dns_discovery_domain',
'id_provider',
'auth_provider',
'access_provider',
@@ -795,6 +796,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'account_cache_expiration',
'lookup_family_order',
'dns_resolver_timeout',
+ 'dns_discovery_domain',
'id_provider',
'auth_provider',
'access_provider',
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index f0ef4114..ca85ed70 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -59,6 +59,7 @@ account_cache_expiration = int, None, false
filter_users = list, str, false
filter_groups = list, str, false
dns_resolver_timeout = int, None, false
+dns_discovery_domain = str, None, false
# Special providers
[provider/permit]
diff --git a/src/config/upgrade_config.py b/src/config/upgrade_config.py
index d47fcd38..ff22b489 100644
--- a/src/config/upgrade_config.py
+++ b/src/config/upgrade_config.py
@@ -59,6 +59,28 @@ class SSSDConfigFile(SSSDChangeConf):
if item:
item['name'] = new_name
+ def _add_dns_domain_name(self, domain):
+ id_provider = self.findOpts(domain['value'], 'option', 'id_provider')[1]
+ dns_domain_name = { 'type' : 'option',
+ 'name' : 'dns_discovery_domain',
+ 'value' : domain['name'].lstrip('domain/') }
+ if id_provider['value'] == 'ldap':
+ server = self.findOpts(domain['value'], 'option', 'ldap_uri')[1]
+ if not server or "__srv__" in server['value']:
+ domain['value'].insert(0, dns_domain_name)
+ return
+ elif id_provider['value'] == 'ipa':
+ server = self.findOpts(domain['value'], 'option', 'ipa_server')[1]
+ if not server or "__srv__" in server['value']:
+ domain['value'].insert(0, dns_domain_name)
+ return
+
+ auth_provider = self.findOpts(domain['value'], 'option', 'auth_provider')[1]
+ if auth_provider and auth_provider['value'] == 'krb5':
+ server = self.findOpts(domain['value'], 'option', 'krb5_kdcip')[1]
+ if not server or "__srv__" in server['value']:
+ domain['value'].insert(0, dns_domain_name)
+
def _do_v2_changes(self):
# remove Data Provider
srvlist = self.get_option_index('sssd', 'services')[1]
@@ -69,9 +91,11 @@ class SSSDConfigFile(SSSDChangeConf):
srvlist['value'] = ", ".join([srv for srv in services])
self.delete_option('section', 'dp')
- # remove magic_private_groups from all domains
for domain in [ s for s in self.sections() if s['name'].startswith("domain/") ]:
+ # remove magic_private_groups from all domains
self.delete_option_subtree(domain['value'], 'option', 'magic_private_groups')
+ # check if we need to add dns_domain
+ self._add_dns_domain_name(domain)
def _update_option(self, to_section_name, from_section_name, opts):
to_section = [ s for s in self.sections() if s['name'].strip() == to_section_name ]
diff --git a/src/man/include/service_discovery.xml b/src/man/include/service_discovery.xml
index 16d016ea..d33b4c21 100644
--- a/src/man/include/service_discovery.xml
+++ b/src/man/include/service_discovery.xml
@@ -22,8 +22,13 @@
<refsect2 id='domain_name'>
<title>The domain name</title>
<para>
- The name of the SSSD domain is used as the domain part of the
- service discovery DNS query.
+ Please refer to the <quote>dns_discovery_domain</quote>
+ parameter in the
+ <citerefentry>
+ <refentrytitle>sssd.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>
+ manual page for more defails.
</para>
</refsect2>
<refsect2 id='reference'>
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 497fae63..3bc3efdc 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -682,6 +682,19 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>dns_discovery_domain (string)</term>
+ <listitem>
+ <para>
+ If service discovery is used in the back end, specifies
+ the domain part of the service discovery DNS query.
+ </para>
+ <para>
+ Default: Use the domain part of machine's hostname
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 56a072ae..1654e222 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -243,9 +243,10 @@ int be_fo_service_add_callback(TALLOC_CTX *memctx,
int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name,
const char *query_service, const char *proto,
- const char *domain, void *user_data)
+ void *user_data)
{
struct be_svc_data *svc;
+ char *domain;
int ret;
DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
@@ -257,6 +258,15 @@ int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name,
return ENOENT;
}
+ ret = confdb_get_string(ctx->cdb, svc, ctx->conf_path,
+ CONFDB_DOMAIN_DNS_DISCOVERY_NAME,
+ NULL, &domain);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed reading %s from confdb\n",
+ CONFDB_DOMAIN_DNS_DISCOVERY_NAME));
+ return ret;
+ }
+
ret = fo_add_srv_server(svc->fo_service, query_service,
domain, proto, user_data);
if (ret && ret != EEXIST) {
@@ -461,3 +471,4 @@ int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
return EOK;
}
+
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 0668859b..61917b99 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -167,7 +167,7 @@ int be_fo_service_add_callback(TALLOC_CTX *memctx,
be_svc_callback_fn_t *fn, void *private_data);
int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name,
const char *query_service, const char *proto,
- const char *domain, void *user_data);
+ void *user_data);
int be_fo_add_server(struct be_ctx *ctx, const char *service_name,
const char *server, int port, void *user_data);
@@ -179,4 +179,5 @@ int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
const char *service_name);
+
#endif /* __DP_BACKEND_H___ */
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index 4fb05c1f..c965c0e3 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -97,7 +97,7 @@ struct server_common {
};
struct srv_data {
- char *domain;
+ char *dns_domain;
char *proto;
char *srv;
@@ -212,7 +212,7 @@ get_srv_query(TALLOC_CTX *mem_ctx, struct fo_server *server)
query = talloc_asprintf(mem_ctx, "_%s._%s.%s", server->srv_data->srv,
server->srv_data->proto,
- server->srv_data->domain);
+ server->srv_data->dns_domain);
return query;
}
@@ -222,7 +222,7 @@ collapse_srv_lookup(struct fo_server *server)
struct fo_server *tmp, *meta;
meta = server->srv_data->meta;
- DEBUG(4, ("Need to refresh SRV lookup for domain %s\n", meta->srv_data->domain))
+ DEBUG(4, ("Need to refresh SRV lookup for domain %s\n", meta->srv_data->dns_domain))
if (server != meta) {
while (server->prev && server->prev->srv_data == meta->srv_data) {
@@ -498,19 +498,20 @@ create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
int
fo_add_srv_server(struct fo_service *service, const char *srv,
- const char *domain, const char *proto, void *user_data)
+ const char *dns_domain, const char *proto, void *user_data)
{
struct fo_server *server;
DEBUG(3, ("Adding new SRV server in domain '%s', to service '%s'\n",
- domain, service->name));
+ dns_domain ? dns_domain : "unknown", service->name));
DLIST_FOR_EACH(server, service->server_list) {
if (server->user_data != user_data)
continue;
if (fo_is_srv_lookup(server)) {
- if (strcasecmp(server->srv_data->domain, domain) == 0 &&
+ if (((dns_domain == NULL && server->srv_data->dns_domain == NULL) ||
+ strcasecmp(server->srv_data->dns_domain, dns_domain) == 0) &&
strcasecmp(server->srv_data->proto, proto) == 0) {
return EEXIST;
}
@@ -530,14 +531,18 @@ fo_add_srv_server(struct fo_service *service, const char *srv,
if (server->srv_data == NULL)
return ENOMEM;
- server->srv_data->domain = talloc_strdup(server->srv_data, domain);
server->srv_data->proto = talloc_strdup(server->srv_data, proto);
server->srv_data->srv = talloc_strdup(server->srv_data, srv);
- if (server->srv_data->domain == NULL ||
- server->srv_data->proto == NULL ||
+ if (server->srv_data->proto == NULL ||
server->srv_data->srv == NULL)
return ENOMEM;
+ if (dns_domain) {
+ server->srv_data->dns_domain = talloc_strdup(server->srv_data, dns_domain);
+ if (server->srv_data->dns_domain == NULL)
+ return ENOMEM;
+ }
+
server->srv_data->meta = server;
server->srv_data->srv_lookup_status = DEFAULT_SRV_STATUS;
server->srv_data->last_status_change.tv_sec = 0;
@@ -895,6 +900,17 @@ fo_resolve_service_recv(struct tevent_req *req, struct fo_server **server)
*******************************************************************/
static void resolve_srv_done(struct tevent_req *subreq);
+static void resolve_srv_cont(struct tevent_req *req);
+
+struct tevent_req *resolve_get_domain_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct fo_ctx *foctx,
+ struct resolv_ctx *resolv);
+
+static void resolve_getsrv_domain_done(struct tevent_req *req);
+int resolve_get_domain_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ char **dns_domain);
struct resolve_srv_state {
struct fo_server *meta;
@@ -913,7 +929,6 @@ resolve_srv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
struct fo_server *server)
{
int ret;
- char *query;
struct tevent_req *req;
struct tevent_req *subreq;
struct resolve_srv_state *state;
@@ -937,19 +952,18 @@ resolve_srv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
state->meta = collapse_srv_lookup(server);
/* FALLTHROUGH */
case SRV_NEUTRAL: /* Request SRV lookup */
- query = get_srv_query(state, state->meta);
- if (!query) {
- ret = ENOMEM;
- goto done;
- }
- DEBUG(4, ("Searching for servers via SRV query '%s'\n", query));
-
- subreq = resolv_getsrv_send(state, ev, resolv, query);
- if (subreq == NULL) {
- ret = ENOMEM;
- goto done;
+ if (server->srv_data->dns_domain == NULL) {
+ /* we need to look up our DNS domain first */
+ subreq = resolve_get_domain_send(state, ev, ctx, resolv);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(subreq, resolve_getsrv_domain_done, req);
+ break;
}
- tevent_req_set_callback(subreq, resolve_srv_done, req);
+ /* we know the DNS domain, just do the lookup */
+ resolve_srv_cont(req);
break;
case SRV_NOT_RESOLVED: /* query could not be resolved but don't retry yet */
ret = EIO;
@@ -975,6 +989,49 @@ done:
}
static void
+resolve_getsrv_domain_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct resolve_srv_state *state = tevent_req_data(req,
+ struct resolve_srv_state);
+ int ret;
+
+ ret = resolve_get_domain_recv(subreq, state->meta->srv_data,
+ &state->meta->srv_data->dns_domain);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ resolve_srv_cont(req);
+}
+
+static void
+resolve_srv_cont(struct tevent_req *req)
+{
+ struct resolve_srv_state *state = tevent_req_data(req,
+ struct resolve_srv_state);
+ char *query;
+ struct tevent_req *subreq;
+
+ query = get_srv_query(state, state->meta);
+ if (!query) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ DEBUG(4, ("Searching for servers via SRV query '%s'\n", query));
+
+ subreq = resolv_getsrv_send(state, state->ev, state->resolv, query);
+ if (subreq == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, resolve_srv_done, req);
+}
+
+static void
resolve_srv_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -1072,6 +1129,103 @@ resolve_srv_recv(struct tevent_req *req, struct fo_server **server)
return EOK;
}
+/*******************************************************************
+ * Get Fully Qualified Domain Name of the host machine *
+ *******************************************************************/
+struct resolve_get_domain_state {
+ char *fqdn;
+ char hostname[HOST_NAME_MAX];
+};
+
+static void resolve_get_domain_done(struct tevent_req *subreq);
+
+struct tevent_req *
+resolve_get_domain_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct fo_ctx *foctx,
+ struct resolv_ctx *resolv)
+{
+ int ret;
+ struct resolve_get_domain_state *state;
+ struct tevent_req *req, *subreq;
+
+ req = tevent_req_create(mem_ctx, &state, struct resolve_get_domain_state);
+ if (!req) {
+ return NULL;
+ }
+
+ ret = gethostname(state->hostname, HOST_NAME_MAX);
+ if (ret) {
+ DEBUG(2, ("gethostname() failed: [%d]: %s\n",ret, strerror(ret)));
+ return NULL;
+ }
+ state->hostname[HOST_NAME_MAX-1] = '\0';
+ DEBUG(7, ("Host name is: %s\n", state->hostname));
+
+ subreq = resolv_gethostbyname_send(mem_ctx, ev, resolv,
+ state->hostname,
+ foctx->opts->family_order);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, resolve_get_domain_done, req);
+
+ return req;
+}
+
+static void resolve_get_domain_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct resolve_get_domain_state *state = tevent_req_data(req,
+ struct resolve_get_domain_state);
+ struct hostent *hostent;
+ int ret;
+
+ ret = resolv_gethostbyname_recv(subreq, req, NULL, NULL, &hostent);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(2, ("Could not get fully qualified name for host name %s "
+ "resolver returned: [%d]: %s\n",
+ state->hostname, ret, strerror(ret)));
+ /* We'll proceed with hostname in this case */
+ } else {
+ DEBUG(7, ("The full FQDN is: %s\n", hostent->h_name));
+ state->fqdn = hostent->h_name;
+ }
+ tevent_req_done(req);
+}
+
+int resolve_get_domain_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ char **dns_domain)
+{
+ struct resolve_get_domain_state *state = tevent_req_data(req,
+ struct resolve_get_domain_state);
+ char *fqdn;
+ char *domptr;
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ fqdn = state->fqdn ? state->fqdn : state->hostname;
+ domptr = strchr(fqdn, '.');
+
+ if (!domptr || (*(domptr+1) == '\0')) {
+ /* If the FQDN did not contain a dot or the dot was the last character
+ * (broken DNS server perhaps */
+ *dns_domain = talloc_strdup(mem_ctx, fqdn);
+ } else {
+ domptr++;
+ *dns_domain = talloc_strdup(mem_ctx, domptr);
+ }
+
+ if (*dns_domain == NULL) {
+ return ENOMEM;
+ }
+
+ return EOK;
+}
+
static void
set_server_common_status(struct server_common *common,
enum server_status status)
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 3ada423e..99b1508f 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -570,7 +570,7 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
if (be_fo_is_srv_identifier(list[i])) {
ret = be_fo_add_srv_server(ctx, "IPA", "ldap",
- FO_PROTO_TCP, ctx->domain->name, NULL);
+ FO_PROTO_TCP, NULL);
if (ret) {
DEBUG(0, ("Failed to add server\n"));
goto done;
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 57d7b1d0..e5471e3f 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -338,7 +338,7 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
if (be_fo_is_srv_identifier(server_spec)) {
ret = be_fo_add_srv_server(ctx, service_name, service_name,
- FO_PROTO_TCP, ctx->domain->name, NULL);
+ FO_PROTO_TCP, NULL);
if (ret) {
DEBUG(0, ("Failed to add server\n"));
goto done;
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 4f1dc067..978e2327 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -638,7 +638,6 @@ int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
ret = be_fo_add_srv_server(ctx, service_name,
dns_service_name, FO_PROTO_TCP,
- ctx->domain->name,
srv_user_data);
if (ret) {
DEBUG(0, ("Failed to add server\n"));