summaryrefslogtreecommitdiffstats
path: root/src
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 /src
parent2dd3faebcd3cfd00efda38ffd2585d675e696b12 (diff)
downloadsssd-780ffc9f6d5e1fcd4df3d390b56cb98878223cc0.tar.gz
sssd-780ffc9f6d5e1fcd4df3d390b56cb98878223cc0.tar.xz
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
Diffstat (limited to 'src')
-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 ae7502f8d..e5a0d9ab9 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 f1ff02aaa..22013eebb 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 63d1ad11f..e99a7876f 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 f0ef41149..ca85ed709 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 d47fcd38c..ff22b489b 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 16d016eaf..d33b4c218 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 497fae630..3bc3efdc2 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 56a072aee..1654e2227 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 0668859b7..61917b99d 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 4fb05c1f6..c965c0e3a 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 3ada423e8..99b1508f9 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 57d7b1d0c..e5471e3f1 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 4f1dc067a..978e23276 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"));