91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina Pavel Březina <pbrezina@redhat.com>
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina Copyright (C) 2013 Red Hat
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina This program is free software; you can redistribute it and/or modify
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina it under the terms of the GNU General Public License as published by
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina the Free Software Foundation; either version 3 of the License, or
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina (at your option) any later version.
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina This program is distributed in the hope that it will be useful,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina GNU General Public License for more details.
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina You should have received a copy of the GNU General Public License
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic errno_t ad_sort_servers_by_dns(TALLOC_CTX *mem_ctx,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina out = talloc_zero_array(mem_ctx, struct fo_server_info, num);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* When several servers share priority, we will prefer the one that
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * is located in the same domain as client (e.g. child domain instead
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * of forest root) but obey their weight. We will use the fact that
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * the servers are already sorted by priority. */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina for (i = 0; i < num; i++) {
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* this is a preferred server, push it to the in domain list */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* this is a normal server, push it to the out domain list */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina if (i + 1 == num || srv[i].priority != srv[i + 1].priority) {
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* priority has changed or we have reached the end of the srv list,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * we will merge the list into final list and start over with
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * next priority */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina for (j = 0; j < in_index; j++) {
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina for (j = 0; j < out_index; j++) {
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březinastatic void ad_get_dc_servers_done(struct tevent_req *subreq);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březinastatic struct tevent_req *ad_get_dc_servers_send(TALLOC_CTX *mem_ctx,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina domains = talloc_zero_array(state, const char *, 3);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Looking up domain controllers in domain "
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina domains[0] = talloc_strdup(domains, discovery_domain);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Looking up domain controllers in domain "
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina domains[0] = talloc_asprintf(state, AD_SITE_DOMAIN_FMT,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina domains[1] = talloc_strdup(domains, discovery_domain);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina subreq = fo_discover_srv_send(state, ev, resolv_ctx,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina tevent_req_set_callback(subreq, ad_get_dc_servers_done, req);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březinastatic void ad_get_dc_servers_done(struct tevent_req *subreq)
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina state = tevent_req_data(req, struct ad_get_dc_servers_state);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina ret = fo_discover_srv_recv(state, subreq, &domain, NULL,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Found %zu domain controllers in domain %s\n",
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březinastatic int ad_get_dc_servers_recv(TALLOC_CTX *mem_ctx,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina state = tevent_req_data(req, struct ad_get_dc_servers_state);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina *_dcs = talloc_steal(mem_ctx, state->servers);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic errno_t ad_get_client_site_next_dc(struct tevent_req *req);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_get_client_site_connect_done(struct tevent_req *subreq);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_get_client_site_done(struct tevent_req *subreq);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastruct tevent_req *ad_get_client_site_send(TALLOC_CTX *mem_ctx,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina struct ad_get_client_site_state *state = NULL;
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina if (be_res == NULL || host_db == NULL || opts == NULL) {
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic errno_t ad_get_client_site_next_dc(struct tevent_req *req)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina struct ad_get_client_site_state *state = NULL;
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state = tevent_req_data(req, struct ad_get_client_site_state);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina subreq = sdap_connect_host_send(state, state->ev, state->opts,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina tevent_req_set_callback(subreq, ad_get_client_site_connect_done, req);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_get_client_site_connect_done(struct tevent_req *subreq)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina struct ad_get_client_site_state *state = NULL;
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina static const char *attrs[] = {AD_AT_NETLOGON, NULL};
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state = tevent_req_data(req, struct ad_get_client_site_state);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ret = sdap_connect_host_recv(state, subreq, &state->sh);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "Unable to connect to domain controller "
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ntver = sss_ldap_encode_ndr_uint32(state, NETLOGON_NT_VERSION_5EX |
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina filter = talloc_asprintf(state, "(&(%s=%s)(%s=%s))",
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina tevent_req_set_callback(subreq, ad_get_client_site_done, req);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březinastatic void ad_get_client_site_done(struct tevent_req *subreq)
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina struct ad_get_client_site_state *state = NULL;
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina state = tevent_req_data(req, struct ad_get_client_site_state);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina /* we're done with this LDAP, close connection */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Unable to get netlogon information\n");
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_OP_FAILURE, "No netlogon information retrieved\n");
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina ret = netlogon_get_domain_info(state, reply[0], true, NULL, &state->site,
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve site name [%d]: %s\n",
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinaint ad_get_client_site_recv(TALLOC_CTX *mem_ctx,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina const char **_site,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina const char **_forest)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina struct ad_get_client_site_state *state = NULL;
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state = tevent_req_data(req, struct ad_get_client_site_state);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina *_forest = talloc_steal(mem_ctx, state->forest);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ctx = talloc_zero(mem_ctx, struct ad_srv_plugin_ctx);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ctx->ad_domain = talloc_strdup(ctx, ad_domain);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ctx->ad_site_override = talloc_strdup(ctx, ad_site_override);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ctx->current_site = talloc_strdup(ctx, ad_site_override);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ret = sysdb_get_site(ctx, be_ctx->domain, &ctx->current_site);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* Not fatal. */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina "Unable to get current site from cache [%d]: %s\n",
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinaad_srv_plugin_ctx_switch_site(struct ad_srv_plugin_ctx *ctx,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina if (ctx->current_site != NULL && strcmp(ctx->current_site, new_site) == 0) {
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ret = sysdb_set_site(ctx->be_ctx->domain, ctx->current_site);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina /* Not fatal. */
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "Unable to store site information "
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_srv_plugin_dcs_done(struct tevent_req *subreq);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_srv_plugin_site_done(struct tevent_req *subreq);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_srv_plugin_servers_done(struct tevent_req *subreq);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina/* 1. Do a DNS lookup to find any DC in domain
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * _ldap._tcp.domain.name
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * 2. Send a CLDAP ping to the found DC to get the desirable site
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * 3. Do a DNS lookup to find SRV in the site (a)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * _service._protocol.site-name._sites.domain.name
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * 4. Do a DNS lookup to find global SRV records (b)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * _service._protocol.domain.name
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * 5. If the site is found, use (a) as primary and (b) as backup servers,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina * otherwise use (b) as primary servers
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastruct tevent_req *ad_srv_plugin_send(TALLOC_CTX *mem_ctx,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ctx = talloc_get_type(pvt, struct ad_srv_plugin_ctx);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state->service = talloc_strdup(state, service);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state->protocol = talloc_strdup(state, protocol);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state->discovery_domain = talloc_strdup(state, discovery_domain);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state->discovery_domain = talloc_strdup(state, ctx->ad_domain);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "About to find domain controllers\n");
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina subreq = ad_get_dc_servers_send(state, ev, ctx->be_res->resolv,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina tevent_req_set_callback(subreq, ad_srv_plugin_dcs_done, req);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březinastatic void ad_srv_plugin_dcs_done(struct tevent_req *subreq)
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina state = tevent_req_data(req, struct ad_srv_plugin_state);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina ret = ad_get_dc_servers_recv(state, subreq, &dcs, &num_dcs);
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "About to locate suitable site\n");
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina subreq = ad_get_client_site_send(state, state->ev,
91cf6f4c6069d6aff01aab171825e83a1a669e2fPavel Březina tevent_req_set_callback(subreq, ad_srv_plugin_site_done, req);
goto done;
goto done;
goto done;
goto done;
goto done;
done:
char **_dns_domain,
if (_primary_servers) {
if (_num_primary_servers) {
if (_backup_servers) {
if (_num_backup_servers) {
if (_dns_domain) {
if (_ttl) {
return EOK;