diff options
-rw-r--r-- | src/confdb/confdb.h | 1 | ||||
-rw-r--r-- | src/config/SSSDConfig.py | 1 | ||||
-rwxr-xr-x | src/config/SSSDConfigTest.py | 2 | ||||
-rw-r--r-- | src/config/etc/sssd.api.conf | 1 | ||||
-rw-r--r-- | src/config/upgrade_config.py | 26 | ||||
-rw-r--r-- | src/man/include/service_discovery.xml | 9 | ||||
-rw-r--r-- | src/man/sssd.conf.5.xml | 13 | ||||
-rw-r--r-- | src/providers/data_provider_fo.c | 13 | ||||
-rw-r--r-- | src/providers/dp_backend.h | 3 | ||||
-rw-r--r-- | src/providers/fail_over.c | 198 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.c | 2 | ||||
-rw-r--r-- | src/providers/krb5/krb5_common.c | 2 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.c | 1 |
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")); |