|
|
f9c044 |
From db644a3a24c123a964129d41934365d8eb2174c7 Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Thu, 30 Jul 2020 12:59:01 +0200
|
|
|
f9c044 |
Subject: [PATCH 1/7] ldap: add support for cldap and udp connections
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit 414593cca65ed09fe4659e2786370a4553664cd0)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/util/sss_ldap.c | 28 ++++++++++++++++++++-----
|
|
|
f9c044 |
src/util/sss_sockets.c | 47 ++++++++++++++++++++++++++++--------------
|
|
|
f9c044 |
src/util/sss_sockets.h | 1 +
|
|
|
f9c044 |
3 files changed, 56 insertions(+), 20 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c
|
|
|
f9c044 |
index 652b08ea7..71fa21f4a 100644
|
|
|
f9c044 |
--- a/src/util/sss_ldap.c
|
|
|
f9c044 |
+++ b/src/util/sss_ldap.c
|
|
|
f9c044 |
@@ -116,6 +116,7 @@ struct sss_ldap_init_state {
|
|
|
f9c044 |
LDAP *ldap;
|
|
|
f9c044 |
int sd;
|
|
|
f9c044 |
const char *uri;
|
|
|
f9c044 |
+ bool use_udp;
|
|
|
f9c044 |
};
|
|
|
f9c044 |
|
|
|
f9c044 |
static int sss_ldap_init_state_destructor(void *data)
|
|
|
f9c044 |
@@ -159,11 +160,13 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
state->ldap = NULL;
|
|
|
f9c044 |
state->sd = -1;
|
|
|
f9c044 |
state->uri = uri;
|
|
|
f9c044 |
+ state->use_udp = strncmp(uri, "cldap", 5) == 0 ? true : false;
|
|
|
f9c044 |
|
|
|
f9c044 |
#ifdef HAVE_LDAP_INIT_FD
|
|
|
f9c044 |
struct tevent_req *subreq;
|
|
|
f9c044 |
|
|
|
f9c044 |
- subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout);
|
|
|
f9c044 |
+ subreq = sssd_async_socket_init_send(state, ev, state->use_udp, addr,
|
|
|
f9c044 |
+ addr_len, timeout);
|
|
|
f9c044 |
if (subreq == NULL) {
|
|
|
f9c044 |
ret = ENOMEM;
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n");
|
|
|
f9c044 |
@@ -246,14 +249,29 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq)
|
|
|
f9c044 |
goto fail;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- ret = unset_fcntl_flags(state->sd, O_NONBLOCK);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- goto fail;
|
|
|
f9c044 |
+ /* openldap < 2.5 does not correctly handle O_NONBLOCK during starttls for
|
|
|
f9c044 |
+ * ldaps, so we need to remove the flag here. This is fine since I/O events
|
|
|
f9c044 |
+ * are handled via tevent so we only read when there is data available.
|
|
|
f9c044 |
+ *
|
|
|
f9c044 |
+ * We need to keep O_NONBLOCK due to a bug in openldap to correctly perform
|
|
|
f9c044 |
+ * a parallel CLDAP pings without timeout. See:
|
|
|
f9c044 |
+ * https://bugs.openldap.org/show_bug.cgi?id=9328
|
|
|
f9c044 |
+ *
|
|
|
f9c044 |
+ * @todo remove this when the bug is fixed and we can put a hard requirement
|
|
|
f9c044 |
+ * on newer openldap.
|
|
|
f9c044 |
+ */
|
|
|
f9c044 |
+ if (!state->use_udp) {
|
|
|
f9c044 |
+ ret = unset_fcntl_flags(state->sd, O_NONBLOCK);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ goto fail;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
/* Initialize LDAP handler */
|
|
|
f9c044 |
|
|
|
f9c044 |
- lret = ldap_init_fd(state->sd, LDAP_PROTO_TCP, state->uri, &state->ldap);
|
|
|
f9c044 |
+ lret = ldap_init_fd(state->sd,
|
|
|
f9c044 |
+ state->use_udp ? LDAP_PROTO_UDP : LDAP_PROTO_TCP,
|
|
|
f9c044 |
+ state->uri, &state->ldap);
|
|
|
f9c044 |
if (lret != LDAP_SUCCESS) {
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
f9c044 |
"ldap_init_fd failed: %s. [%d][%s]\n",
|
|
|
f9c044 |
diff --git a/src/util/sss_sockets.c b/src/util/sss_sockets.c
|
|
|
f9c044 |
index 6f2b71bc8..733360f3b 100644
|
|
|
f9c044 |
--- a/src/util/sss_sockets.c
|
|
|
f9c044 |
+++ b/src/util/sss_sockets.c
|
|
|
f9c044 |
@@ -80,6 +80,18 @@ static errno_t set_fd_common_opts(int fd, int timeout)
|
|
|
f9c044 |
int ret;
|
|
|
f9c044 |
struct timeval tv;
|
|
|
f9c044 |
unsigned int milli;
|
|
|
f9c044 |
+ int type;
|
|
|
f9c044 |
+ socklen_t optlen = sizeof(int);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ /* Get protocol type. */
|
|
|
f9c044 |
+ ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
|
|
|
f9c044 |
+ if (ret != 0) {
|
|
|
f9c044 |
+ ret = errno;
|
|
|
f9c044 |
+ DEBUG(SSSDBG_FUNC_DATA, "Unable to get socket type [%d]: %s.\n",
|
|
|
f9c044 |
+ ret, strerror(ret));
|
|
|
f9c044 |
+ /* Assume TCP. */
|
|
|
f9c044 |
+ type = SOCK_STREAM;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
|
|
|
f9c044 |
/* SO_KEEPALIVE and TCP_NODELAY are set by OpenLDAP client libraries but
|
|
|
f9c044 |
* failures are ignored.*/
|
|
|
f9c044 |
@@ -91,12 +103,14 @@ static errno_t set_fd_common_opts(int fd, int timeout)
|
|
|
f9c044 |
strerror(ret));
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
|
|
|
f9c044 |
- if (ret != 0) {
|
|
|
f9c044 |
- ret = errno;
|
|
|
f9c044 |
- DEBUG(SSSDBG_FUNC_DATA,
|
|
|
f9c044 |
- "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
|
|
|
f9c044 |
- strerror(ret));
|
|
|
f9c044 |
+ if (type == SOCK_STREAM) {
|
|
|
f9c044 |
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
|
|
|
f9c044 |
+ if (ret != 0) {
|
|
|
f9c044 |
+ ret = errno;
|
|
|
f9c044 |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
f9c044 |
+ "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
|
|
|
f9c044 |
+ strerror(ret));
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
if (timeout > 0) {
|
|
|
f9c044 |
@@ -119,14 +133,16 @@ static errno_t set_fd_common_opts(int fd, int timeout)
|
|
|
f9c044 |
strerror(ret));
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- milli = timeout * 1000; /* timeout in milliseconds */
|
|
|
f9c044 |
- ret = setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &milli,
|
|
|
f9c044 |
- sizeof(milli));
|
|
|
f9c044 |
- if (ret != 0) {
|
|
|
f9c044 |
- ret = errno;
|
|
|
f9c044 |
- DEBUG(SSSDBG_FUNC_DATA,
|
|
|
f9c044 |
- "setsockopt TCP_USER_TIMEOUT failed.[%d][%s].\n", ret,
|
|
|
f9c044 |
- strerror(ret));
|
|
|
f9c044 |
+ if (type == SOCK_STREAM) {
|
|
|
f9c044 |
+ milli = timeout * 1000; /* timeout in milliseconds */
|
|
|
f9c044 |
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &milli,
|
|
|
f9c044 |
+ sizeof(milli));
|
|
|
f9c044 |
+ if (ret != 0) {
|
|
|
f9c044 |
+ ret = errno;
|
|
|
f9c044 |
+ DEBUG(SSSDBG_FUNC_DATA,
|
|
|
f9c044 |
+ "setsockopt TCP_USER_TIMEOUT failed.[%d][%s].\n", ret,
|
|
|
f9c044 |
+ strerror(ret));
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
}
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
@@ -271,6 +287,7 @@ static void sssd_async_socket_init_done(struct tevent_req *subreq);
|
|
|
f9c044 |
|
|
|
f9c044 |
struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_context *ev,
|
|
|
f9c044 |
+ bool use_udp,
|
|
|
f9c044 |
struct sockaddr_storage *addr,
|
|
|
f9c044 |
socklen_t addr_len, int timeout)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
@@ -289,7 +306,7 @@ struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
talloc_set_destructor((TALLOC_CTX *)state,
|
|
|
f9c044 |
sssd_async_socket_state_destructor);
|
|
|
f9c044 |
|
|
|
f9c044 |
- state->sd = socket(addr->ss_family, SOCK_STREAM, 0);
|
|
|
f9c044 |
+ state->sd = socket(addr->ss_family, use_udp ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
f9c044 |
if (state->sd == -1) {
|
|
|
f9c044 |
ret = errno;
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE,
|
|
|
f9c044 |
diff --git a/src/util/sss_sockets.h b/src/util/sss_sockets.h
|
|
|
f9c044 |
index ccb05cb84..2758e6ed1 100644
|
|
|
f9c044 |
--- a/src/util/sss_sockets.h
|
|
|
f9c044 |
+++ b/src/util/sss_sockets.h
|
|
|
f9c044 |
@@ -32,6 +32,7 @@ int sssd_async_connect_recv(struct tevent_req *req);
|
|
|
f9c044 |
|
|
|
f9c044 |
struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_context *ev,
|
|
|
f9c044 |
+ bool use_udp,
|
|
|
f9c044 |
struct sockaddr_storage *addr,
|
|
|
f9c044 |
socklen_t addr_len, int timeout);
|
|
|
f9c044 |
int sssd_async_socket_init_recv(struct tevent_req *req, int *sd);
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From 3efae1df18f4bfe7782025a14bcfbb5965496b32 Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Thu, 30 Jul 2020 13:30:50 +0200
|
|
|
f9c044 |
Subject: [PATCH 2/7] ad: use cldap for site and forrest discover (perform
|
|
|
f9c044 |
CLDAP ping)
|
|
|
f9c044 |
|
|
|
f9c044 |
All Windows clients uses CLDAP (UDP) for LDAP ping. Even though AD
|
|
|
f9c044 |
also supports LDAP ping over TCP IPA does not therefore it is crusial
|
|
|
f9c044 |
for us to perform the ping over CLDAP protocol.
|
|
|
f9c044 |
|
|
|
f9c044 |
Resolves:
|
|
|
f9c044 |
https://github.com/SSSD/sssd/issues/5215
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit 8265674a055e5cdb57acebad72d935356408540a)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/providers/ad/ad_init.c | 6 +-----
|
|
|
f9c044 |
src/providers/ad/ad_srv.c | 9 +++------
|
|
|
f9c044 |
src/providers/ad/ad_srv.h | 3 +--
|
|
|
f9c044 |
src/providers/ad/ad_subdomains.c | 2 +-
|
|
|
f9c044 |
src/providers/ipa/ipa_subdomains_server.c | 2 +-
|
|
|
f9c044 |
5 files changed, 7 insertions(+), 15 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
|
|
|
f9c044 |
index fb24a28e1..5abd28b7c 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_init.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_init.c
|
|
|
f9c044 |
@@ -187,14 +187,11 @@ static errno_t ad_init_srv_plugin(struct be_ctx *be_ctx,
|
|
|
f9c044 |
const char *ad_site_override;
|
|
|
f9c044 |
bool sites_enabled;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
- bool ad_use_ldaps;
|
|
|
f9c044 |
|
|
|
f9c044 |
hostname = dp_opt_get_string(ad_options->basic, AD_HOSTNAME);
|
|
|
f9c044 |
ad_domain = dp_opt_get_string(ad_options->basic, AD_DOMAIN);
|
|
|
f9c044 |
ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
|
|
|
f9c044 |
sites_enabled = dp_opt_get_bool(ad_options->basic, AD_ENABLE_DNS_SITES);
|
|
|
f9c044 |
- ad_use_ldaps = dp_opt_get_bool(ad_options->basic, AD_USE_LDAPS);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
|
|
|
f9c044 |
if (!sites_enabled) {
|
|
|
f9c044 |
ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, hostname);
|
|
|
f9c044 |
@@ -210,8 +207,7 @@ static errno_t ad_init_srv_plugin(struct be_ctx *be_ctx,
|
|
|
f9c044 |
srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx, be_ctx->be_res,
|
|
|
f9c044 |
default_host_dbs, ad_options->id,
|
|
|
f9c044 |
hostname, ad_domain,
|
|
|
f9c044 |
- ad_site_override,
|
|
|
f9c044 |
- ad_use_ldaps);
|
|
|
f9c044 |
+ ad_site_override);
|
|
|
f9c044 |
if (srv_ctx == NULL) {
|
|
|
f9c044 |
DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
|
|
|
f9c044 |
return ENOMEM;
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
index ca15d3715..55e8f63f7 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
@@ -335,9 +335,9 @@ static errno_t ad_get_client_site_next_dc(struct tevent_req *req)
|
|
|
f9c044 |
state->be_res->resolv,
|
|
|
f9c044 |
state->be_res->family_order,
|
|
|
f9c044 |
state->host_db,
|
|
|
f9c044 |
- state->ad_use_ldaps ? "ldaps" : "ldap",
|
|
|
f9c044 |
+ "cldap",
|
|
|
f9c044 |
state->dc.host,
|
|
|
f9c044 |
- state->ad_use_ldaps ? 636 : state->dc.port,
|
|
|
f9c044 |
+ state->dc.port,
|
|
|
f9c044 |
false);
|
|
|
f9c044 |
if (subreq == NULL) {
|
|
|
f9c044 |
ret = ENOMEM;
|
|
|
f9c044 |
@@ -497,7 +497,6 @@ struct ad_srv_plugin_ctx {
|
|
|
f9c044 |
const char *ad_domain;
|
|
|
f9c044 |
const char *ad_site_override;
|
|
|
f9c044 |
const char *current_site;
|
|
|
f9c044 |
- bool ad_use_ldaps;
|
|
|
f9c044 |
};
|
|
|
f9c044 |
|
|
|
f9c044 |
struct ad_srv_plugin_ctx *
|
|
|
f9c044 |
@@ -508,8 +507,7 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct sdap_options *opts,
|
|
|
f9c044 |
const char *hostname,
|
|
|
f9c044 |
const char *ad_domain,
|
|
|
f9c044 |
- const char *ad_site_override,
|
|
|
f9c044 |
- bool ad_use_ldaps)
|
|
|
f9c044 |
+ const char *ad_site_override)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
struct ad_srv_plugin_ctx *ctx = NULL;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
@@ -523,7 +521,6 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
ctx->be_res = be_res;
|
|
|
f9c044 |
ctx->host_dbs = host_dbs;
|
|
|
f9c044 |
ctx->opts = opts;
|
|
|
f9c044 |
- ctx->ad_use_ldaps = ad_use_ldaps;
|
|
|
f9c044 |
|
|
|
f9c044 |
ctx->hostname = talloc_strdup(ctx, hostname);
|
|
|
f9c044 |
if (ctx->hostname == NULL) {
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.h b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
index 8e410ec26..e553d594d 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
@@ -31,8 +31,7 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct sdap_options *opts,
|
|
|
f9c044 |
const char *hostname,
|
|
|
f9c044 |
const char *ad_domain,
|
|
|
f9c044 |
- const char *ad_site_override,
|
|
|
f9c044 |
- bool ad_use_ldaps);
|
|
|
f9c044 |
+ const char *ad_site_override);
|
|
|
f9c044 |
|
|
|
f9c044 |
struct tevent_req *ad_srv_plugin_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_context *ev,
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
|
|
|
f9c044 |
index 16aecbc64..9b32196b7 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_subdomains.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_subdomains.c
|
|
|
f9c044 |
@@ -411,7 +411,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
|
|
|
f9c044 |
ad_id_ctx->ad_options->id,
|
|
|
f9c044 |
hostname,
|
|
|
f9c044 |
ad_domain,
|
|
|
f9c044 |
- ad_site_override, ad_use_ldaps);
|
|
|
f9c044 |
+ ad_site_override);
|
|
|
f9c044 |
if (srv_ctx == NULL) {
|
|
|
f9c044 |
DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
|
|
|
f9c044 |
return ENOMEM;
|
|
|
f9c044 |
diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
|
|
|
f9c044 |
index e2037b59d..f0d8a6a20 100644
|
|
|
f9c044 |
--- a/src/providers/ipa/ipa_subdomains_server.c
|
|
|
f9c044 |
+++ b/src/providers/ipa/ipa_subdomains_server.c
|
|
|
f9c044 |
@@ -344,7 +344,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
|
|
|
f9c044 |
ad_id_ctx->ad_options->id,
|
|
|
f9c044 |
id_ctx->server_mode->hostname,
|
|
|
f9c044 |
ad_domain,
|
|
|
f9c044 |
- ad_site_override, false);
|
|
|
f9c044 |
+ ad_site_override);
|
|
|
f9c044 |
if (srv_ctx == NULL) {
|
|
|
f9c044 |
DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
|
|
|
f9c044 |
return ENOMEM;
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From 7e856adefeaa377a50b40d397684e48ba82aa055 Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Tue, 11 Aug 2020 13:27:42 +0200
|
|
|
f9c044 |
Subject: [PATCH 3/7] ad: connect to the first available server for cldap ping
|
|
|
f9c044 |
|
|
|
f9c044 |
Resolves:
|
|
|
f9c044 |
https://github.com/SSSD/sssd/issues/3743
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit 1889ca60a9c642f0cca60b20a5b94de7a66924f6)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
Makefile.am | 5 +-
|
|
|
f9c044 |
src/providers/ad/ad_cldap_ping.c | 586 +++++++++++++++++++++++++++++++
|
|
|
f9c044 |
src/providers/ad/ad_srv.c | 434 +----------------------
|
|
|
f9c044 |
src/providers/ad/ad_srv.h | 14 +
|
|
|
f9c044 |
4 files changed, 613 insertions(+), 426 deletions(-)
|
|
|
f9c044 |
create mode 100644 src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/Makefile.am b/Makefile.am
|
|
|
f9c044 |
index b9ca9a7c6..17e20f1cb 100644
|
|
|
f9c044 |
--- a/Makefile.am
|
|
|
f9c044 |
+++ b/Makefile.am
|
|
|
f9c044 |
@@ -4202,7 +4202,9 @@ libsss_ipa_la_SOURCES = \
|
|
|
f9c044 |
src/providers/ad/ad_pac.c \
|
|
|
f9c044 |
src/providers/ad/ad_pac_common.c \
|
|
|
f9c044 |
src/providers/ad/ad_srv.c \
|
|
|
f9c044 |
- src/providers/ad/ad_domain_info.c
|
|
|
f9c044 |
+ src/providers/ad/ad_domain_info.c \
|
|
|
f9c044 |
+ src/providers/ad/ad_cldap_ping.c \
|
|
|
f9c044 |
+ $(NULL)
|
|
|
f9c044 |
libsss_ipa_la_CFLAGS = \
|
|
|
f9c044 |
$(AM_CFLAGS) \
|
|
|
f9c044 |
$(OPENLDAP_CFLAGS) \
|
|
|
f9c044 |
@@ -4269,6 +4271,7 @@ libsss_ad_la_SOURCES = \
|
|
|
f9c044 |
src/providers/ad/ad_subdomains.c \
|
|
|
f9c044 |
src/providers/ad/ad_domain_info.c \
|
|
|
f9c044 |
src/providers/ad/ad_refresh.c \
|
|
|
f9c044 |
+ src/providers/ad/ad_cldap_ping.c \
|
|
|
f9c044 |
$(NULL)
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_cldap_ping.c b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
new file mode 100644
|
|
|
f9c044 |
index 000000000..5fc1a4d20
|
|
|
f9c044 |
--- /dev/null
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
@@ -0,0 +1,586 @@
|
|
|
f9c044 |
+/*
|
|
|
f9c044 |
+ Authors:
|
|
|
f9c044 |
+ Pavel Březina <pbrezina@redhat.com>
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ Copyright (C) 2020 Red Hat
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ This program is free software; you can redistribute it and/or modify
|
|
|
f9c044 |
+ it under the terms of the GNU General Public License as published by
|
|
|
f9c044 |
+ the Free Software Foundation; either version 3 of the License, or
|
|
|
f9c044 |
+ (at your option) any later version.
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ This program is distributed in the hope that it will be useful,
|
|
|
f9c044 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
f9c044 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
f9c044 |
+ GNU General Public License for more details.
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ You should have received a copy of the GNU General Public License
|
|
|
f9c044 |
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
f9c044 |
+*/
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+#include <string.h>
|
|
|
f9c044 |
+#include <talloc.h>
|
|
|
f9c044 |
+#include <tevent.h>
|
|
|
f9c044 |
+#include <ndr.h>
|
|
|
f9c044 |
+#include <ndr/ndr_nbt.h>
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+#include "util/util.h"
|
|
|
f9c044 |
+#include "util/sss_ldap.h"
|
|
|
f9c044 |
+#include "resolv/async_resolv.h"
|
|
|
f9c044 |
+#include "providers/backend.h"
|
|
|
f9c044 |
+#include "providers/ad/ad_srv.h"
|
|
|
f9c044 |
+#include "providers/ad/ad_common.h"
|
|
|
f9c044 |
+#include "providers/fail_over.h"
|
|
|
f9c044 |
+#include "providers/fail_over_srv.h"
|
|
|
f9c044 |
+#include "providers/ldap/sdap.h"
|
|
|
f9c044 |
+#include "providers/ldap/sdap_async.h"
|
|
|
f9c044 |
+#include "db/sysdb.h"
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct ad_cldap_ping_dc_state {
|
|
|
f9c044 |
+ struct tevent_context *ev;
|
|
|
f9c044 |
+ struct sdap_options *opts;
|
|
|
f9c044 |
+ struct fo_server_info *dc;
|
|
|
f9c044 |
+ struct sdap_handle *sh;
|
|
|
f9c044 |
+ const char *ad_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ char *site;
|
|
|
f9c044 |
+ char *forest;
|
|
|
f9c044 |
+};
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_dc_connect_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+static void ad_cldap_ping_dc_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static struct tevent_req *ad_cldap_ping_dc_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ struct fo_server_info *dc,
|
|
|
f9c044 |
+ const char *ad_domain)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_dc_state *state;
|
|
|
f9c044 |
+ struct tevent_req *subreq;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_create(mem_ctx, &state,
|
|
|
f9c044 |
+ struct ad_cldap_ping_dc_state);
|
|
|
f9c044 |
+ if (req == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
+ return NULL;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->ev = ev;
|
|
|
f9c044 |
+ state->opts = opts;
|
|
|
f9c044 |
+ state->dc = dc;
|
|
|
f9c044 |
+ state->ad_domain = ad_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ subreq = sdap_connect_host_send(state, ev, opts, be_res->resolv,
|
|
|
f9c044 |
+ be_res->family_order, host_db, "cldap",
|
|
|
f9c044 |
+ dc->host, dc->port, false);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_dc_connect_done, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ tevent_req_post(req, ev);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_dc_connect_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ static const char *attrs[] = {AD_AT_NETLOGON, NULL};
|
|
|
f9c044 |
+ struct ad_cldap_ping_dc_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ char *ntver;
|
|
|
f9c044 |
+ char *filter;
|
|
|
f9c044 |
+ int timeout;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_dc_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = sdap_connect_host_recv(state, subreq, &state->sh);
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ntver = sss_ldap_encode_ndr_uint32(state, NETLOGON_NT_VERSION_5EX |
|
|
|
f9c044 |
+ NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
|
|
|
f9c044 |
+ if (ntver == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ filter = talloc_asprintf(state, "(&(%s=%s)(%s=%s))", AD_AT_DNS_DOMAIN,
|
|
|
f9c044 |
+ state->ad_domain, AD_AT_NT_VERSION, ntver);
|
|
|
f9c044 |
+ if (filter == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT);
|
|
|
f9c044 |
+ subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, "",
|
|
|
f9c044 |
+ LDAP_SCOPE_BASE, filter, attrs, NULL,
|
|
|
f9c044 |
+ 0, timeout, false);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_dc_done, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = EOK;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_dc_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_dc_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ struct sysdb_attrs **reply;
|
|
|
f9c044 |
+ size_t reply_count;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_dc_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ talloc_zfree(state->sh);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE, "%s:%d: unable to get netlogon information\n",
|
|
|
f9c044 |
+ state->dc->host, state->dc->port);
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ if (reply_count == 0) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE, "%s:%d: no netlogon information available\n",
|
|
|
f9c044 |
+ state->dc->host, state->dc->port);
|
|
|
f9c044 |
+ ret = ENOENT;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = netlogon_get_domain_info(state, reply[0], true, NULL, &state->site,
|
|
|
f9c044 |
+ &state->forest);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
f9c044 |
+ "%s:%d: unable to retrieve site name [%d]: %s\n",
|
|
|
f9c044 |
+ state->dc->host, state->dc->port, ret, sss_strerror(ret));
|
|
|
f9c044 |
+ ret = ENOENT;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "%s:%d: found site (%s) and forest (%s)\n",
|
|
|
f9c044 |
+ state->dc->host, state->dc->port, state->site, state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = EOK;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static errno_t ad_cldap_ping_dc_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_dc_state *state = NULL;
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_dc_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ *_site = talloc_steal(mem_ctx, state->site);
|
|
|
f9c044 |
+ *_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return EOK;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct ad_cldap_ping_parallel_state {
|
|
|
f9c044 |
+ struct tevent_context *ev;
|
|
|
f9c044 |
+ struct sdap_options *opts;
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
+ enum host_database *host_db;
|
|
|
f9c044 |
+ const char *ad_domain;
|
|
|
f9c044 |
+ struct fo_server_info *dc_list;
|
|
|
f9c044 |
+ size_t dc_count;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ TALLOC_CTX *reqs_ctx;
|
|
|
f9c044 |
+ struct tevent_timer *te;
|
|
|
f9c044 |
+ int active_requests;
|
|
|
f9c044 |
+ size_t next_dc;
|
|
|
f9c044 |
+ int batch;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ const char *site;
|
|
|
f9c044 |
+ const char *forest;
|
|
|
f9c044 |
+};
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_parallel_batch(struct tevent_context *ev,
|
|
|
f9c044 |
+ struct tevent_timer *te,
|
|
|
f9c044 |
+ struct timeval tv,
|
|
|
f9c044 |
+ void *data);
|
|
|
f9c044 |
+static void ad_cldap_ping_parallel_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static struct tevent_req *
|
|
|
f9c044 |
+ad_cldap_ping_parallel_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ struct fo_server_info *dc_list,
|
|
|
f9c044 |
+ size_t dc_count,
|
|
|
f9c044 |
+ const char *ad_domain)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_parallel_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ struct timeval tv = {0, 0};
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_create(mem_ctx, &state,
|
|
|
f9c044 |
+ struct ad_cldap_ping_parallel_state);
|
|
|
f9c044 |
+ if (req == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
+ return NULL;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->ev = ev;
|
|
|
f9c044 |
+ state->opts = opts;
|
|
|
f9c044 |
+ state->be_res = be_res;
|
|
|
f9c044 |
+ state->host_db = host_db;
|
|
|
f9c044 |
+ state->ad_domain = ad_domain;
|
|
|
f9c044 |
+ state->dc_list = dc_list;
|
|
|
f9c044 |
+ state->dc_count = dc_count;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->reqs_ctx = talloc_new(state);
|
|
|
f9c044 |
+ if (state->reqs_ctx == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->next_dc = 0;
|
|
|
f9c044 |
+ state->batch = 1;
|
|
|
f9c044 |
+ ad_cldap_ping_parallel_batch(ev, NULL, tv, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ tevent_req_post(req, ev);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_parallel_batch(struct tevent_context *ev,
|
|
|
f9c044 |
+ struct tevent_timer *te,
|
|
|
f9c044 |
+ struct timeval tv,
|
|
|
f9c044 |
+ void *data)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_parallel_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ struct tevent_req *subreq;
|
|
|
f9c044 |
+ uint32_t delay;
|
|
|
f9c044 |
+ size_t limit;
|
|
|
f9c044 |
+ size_t i;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = talloc_get_type(data, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_parallel_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->te = NULL;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ /* Issue three batches in total to avoid pinging too many domain controllers
|
|
|
f9c044 |
+ * if not necessary. The first batch (5 pings) is issued immediately and we
|
|
|
f9c044 |
+ * will wait 400ms for it to finish. If we don't get a reply in time we
|
|
|
f9c044 |
+ * issue next batch (5 pings) and wait 200ms. If we still have no reply,
|
|
|
f9c044 |
+ * we contact remaining domain controllers.
|
|
|
f9c044 |
+ *
|
|
|
f9c044 |
+ * This follows algorithm described at section 5.4.5.3 of MS-DISO:
|
|
|
f9c044 |
+ * https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/WinArchive/%5bMS-DISO%5d.pdf
|
|
|
f9c044 |
+ */
|
|
|
f9c044 |
+ switch (state->batch) {
|
|
|
f9c044 |
+ case 1:
|
|
|
f9c044 |
+ case 2:
|
|
|
f9c044 |
+ limit = MIN(state->dc_count, 5 + state->next_dc);
|
|
|
f9c044 |
+ delay = 400000 / state->batch;
|
|
|
f9c044 |
+ break;
|
|
|
f9c044 |
+ default:
|
|
|
f9c044 |
+ limit = state->dc_count;
|
|
|
f9c044 |
+ delay = 0;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ for (i = state->next_dc; i < limit; i++) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_ALL, "Batch %d: %s:%d\n", state->batch,
|
|
|
f9c044 |
+ state->dc_list[i].host, state->dc_list[i].port);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ for (; state->next_dc < limit; state->next_dc++) {
|
|
|
f9c044 |
+ subreq = ad_cldap_ping_dc_send(state->reqs_ctx, ev, state->opts,
|
|
|
f9c044 |
+ state->be_res, state->host_db,
|
|
|
f9c044 |
+ &state->dc_list[state->next_dc],
|
|
|
f9c044 |
+ state->ad_domain);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to create new ping request\n");
|
|
|
f9c044 |
+ goto fail;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->active_requests++;
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_parallel_done, req);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->batch++;
|
|
|
f9c044 |
+ if (delay > 0) {
|
|
|
f9c044 |
+ tv = tevent_timeval_current_ofs(0, delay);
|
|
|
f9c044 |
+ state->te = tevent_add_timer(ev, state->reqs_ctx, tv,
|
|
|
f9c044 |
+ ad_cldap_ping_parallel_batch, req);
|
|
|
f9c044 |
+ if (state->te == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule next batch!\n");
|
|
|
f9c044 |
+ goto fail;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+fail:
|
|
|
f9c044 |
+ if (state->active_requests == 0) {
|
|
|
f9c044 |
+ tevent_req_error(req, ENOMEM);
|
|
|
f9c044 |
+ if (state->batch == 1) {
|
|
|
f9c044 |
+ tevent_req_post(req, ev);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_parallel_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_parallel_state *state;
|
|
|
f9c044 |
+ struct timeval tv = {0, 0};
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_parallel_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = ad_cldap_ping_dc_recv(state, subreq, &state->site, &state->forest);
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ state->active_requests--;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ if (ret == EOK) {
|
|
|
f9c044 |
+ /* We have the answer. Terminate other attempts and finish. */
|
|
|
f9c044 |
+ talloc_zfree(state->reqs_ctx);
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
+ } else if (state->active_requests == 0) {
|
|
|
f9c044 |
+ /* There are still servers to try, don't wait for the timer. */
|
|
|
f9c044 |
+ if (state->next_dc < state->dc_count) {
|
|
|
f9c044 |
+ talloc_zfree(state->te);
|
|
|
f9c044 |
+ ad_cldap_ping_parallel_batch(state->ev, NULL, tv, req);
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ /* There is no available server. */
|
|
|
f9c044 |
+ tevent_req_error(req, ENOENT);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ /* Wait for another request to finish. */
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static errno_t ad_cldap_ping_parallel_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_parallel_state *state = NULL;
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_parallel_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ *_site = talloc_steal(mem_ctx, state->site);
|
|
|
f9c044 |
+ *_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return EOK;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct ad_cldap_ping_state {
|
|
|
f9c044 |
+ struct tevent_context *ev;
|
|
|
f9c044 |
+ struct sdap_options *opts;
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
+ enum host_database *host_db;
|
|
|
f9c044 |
+ const char *ad_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ struct fo_server_info *dc_list;
|
|
|
f9c044 |
+ size_t dc_count;
|
|
|
f9c044 |
+ const char *site;
|
|
|
f9c044 |
+ const char *forest;
|
|
|
f9c044 |
+};
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_discovery_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+static void ad_cldap_ping_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ const char *ad_domain,
|
|
|
f9c044 |
+ const char *discovery_domain,
|
|
|
f9c044 |
+ const char *current_site)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *subreq;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ const char **domains;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_create(mem_ctx, &state, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+ if (req == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
+ return NULL;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->ev = ev;
|
|
|
f9c044 |
+ state->opts = opts;
|
|
|
f9c044 |
+ state->be_res = be_res;
|
|
|
f9c044 |
+ state->host_db = host_db;
|
|
|
f9c044 |
+ state->ad_domain = ad_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ domains = talloc_zero_array(state, const char *, 3);
|
|
|
f9c044 |
+ if (domains == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ if (current_site == NULL) {
|
|
|
f9c044 |
+ domains[0] = discovery_domain;
|
|
|
f9c044 |
+ domains[1] = NULL;
|
|
|
f9c044 |
+ } else {
|
|
|
f9c044 |
+ domains[0] = ad_site_dns_discovery_domain(state, current_site,
|
|
|
f9c044 |
+ discovery_domain);
|
|
|
f9c044 |
+ domains[1] = discovery_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ if (domains[0] == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ /* Even though we use CLDAP (UDP) to perform the ping we need to discover
|
|
|
f9c044 |
+ * domain controllers in TCP namespace as they are not automatically
|
|
|
f9c044 |
+ * available under UDP. */
|
|
|
f9c044 |
+ subreq = fo_discover_srv_send(state, ev, be_res->resolv, "ldap",
|
|
|
f9c044 |
+ FO_PROTO_TCP, domains);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_discovery_done, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ tevent_req_post(req, ev);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_discovery_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ char *domain;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = fo_discover_srv_recv(state, subreq, &domain, NULL, &state->dc_list,
|
|
|
f9c044 |
+ &state->dc_count);
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Found %zu domain controllers in domain %s\n",
|
|
|
f9c044 |
+ state->dc_count, domain);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ subreq = ad_cldap_ping_parallel_send(state, state->ev, state->opts,
|
|
|
f9c044 |
+ state->be_res, state->host_db,
|
|
|
f9c044 |
+ state->dc_list, state->dc_count,
|
|
|
f9c044 |
+ state->ad_domain);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_done, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = ad_cldap_ping_parallel_recv(state, subreq, &state->site,
|
|
|
f9c044 |
+ &state->forest);
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
f9c044 |
+ "Unable to get site and forest information [%d]: %s\n",
|
|
|
f9c044 |
+ ret, sss_strerror(ret));
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site);
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+done:
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state = NULL;
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ *_site = talloc_steal(mem_ctx, state->site);
|
|
|
f9c044 |
+ *_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return EOK;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
\ No newline at end of file
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
index 55e8f63f7..d12f0971c 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
@@ -116,378 +116,6 @@ static errno_t ad_sort_servers_by_dns(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
return EOK;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-struct ad_get_dc_servers_state {
|
|
|
f9c044 |
- struct fo_server_info *servers;
|
|
|
f9c044 |
- size_t num_servers;
|
|
|
f9c044 |
-};
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static void ad_get_dc_servers_done(struct tevent_req *subreq);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static struct tevent_req *ad_get_dc_servers_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_context *ev,
|
|
|
f9c044 |
- struct resolv_ctx *resolv_ctx,
|
|
|
f9c044 |
- const char *discovery_domain,
|
|
|
f9c044 |
- const char *site)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_dc_servers_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- struct tevent_req *subreq = NULL;
|
|
|
f9c044 |
- const char **domains = NULL;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_create(mem_ctx, &state,
|
|
|
f9c044 |
- struct ad_get_dc_servers_state);
|
|
|
f9c044 |
- if (req == NULL) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
- return NULL;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- domains = talloc_zero_array(state, const char *, 3);
|
|
|
f9c044 |
- if (domains == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- if (site == NULL) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Looking up domain controllers in domain "
|
|
|
f9c044 |
- "%s\n", discovery_domain);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- domains[0] = talloc_strdup(domains, discovery_domain);
|
|
|
f9c044 |
- if (domains[0] == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
- } else {
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Looking up domain controllers in domain "
|
|
|
f9c044 |
- "%s and site %s\n", discovery_domain, site);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- domains[0] = ad_site_dns_discovery_domain(domains,
|
|
|
f9c044 |
- site, discovery_domain);
|
|
|
f9c044 |
- if (domains[0] == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- domains[1] = talloc_strdup(domains, discovery_domain);
|
|
|
f9c044 |
- if (domains[1] == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- subreq = fo_discover_srv_send(state, ev, resolv_ctx,
|
|
|
f9c044 |
- "ldap", FO_PROTO_TCP, domains);
|
|
|
f9c044 |
- if (subreq == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_get_dc_servers_done, req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return req;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-immediately:
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- tevent_req_post(req, ev);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return req;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static void ad_get_dc_servers_done(struct tevent_req *subreq)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_dc_servers_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- char *domain = NULL;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_dc_servers_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = fo_discover_srv_recv(state, subreq, &domain, NULL,
|
|
|
f9c044 |
- &state->servers, &state->num_servers);
|
|
|
f9c044 |
- talloc_zfree(subreq);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Found %zu domain controllers in domain %s\n",
|
|
|
f9c044 |
- state->num_servers, domain);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-done:
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- return;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static int ad_get_dc_servers_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_req *req,
|
|
|
f9c044 |
- struct fo_server_info **_dcs,
|
|
|
f9c044 |
- size_t *_num_dcs)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_dc_servers_state *state = NULL;
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_dc_servers_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- *_dcs = talloc_steal(mem_ctx, state->servers);
|
|
|
f9c044 |
- *_num_dcs = state->num_servers;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return EOK;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-struct ad_get_client_site_state {
|
|
|
f9c044 |
- struct tevent_context *ev;
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
- enum host_database *host_db;
|
|
|
f9c044 |
- struct sdap_options *opts;
|
|
|
f9c044 |
- const char *ad_domain;
|
|
|
f9c044 |
- bool ad_use_ldaps;
|
|
|
f9c044 |
- struct fo_server_info *dcs;
|
|
|
f9c044 |
- size_t num_dcs;
|
|
|
f9c044 |
- size_t dc_index;
|
|
|
f9c044 |
- struct fo_server_info dc;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- struct sdap_handle *sh;
|
|
|
f9c044 |
- char *site;
|
|
|
f9c044 |
- char *forest;
|
|
|
f9c044 |
-};
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static errno_t ad_get_client_site_next_dc(struct tevent_req *req);
|
|
|
f9c044 |
-static void ad_get_client_site_connect_done(struct tevent_req *subreq);
|
|
|
f9c044 |
-static void ad_get_client_site_done(struct tevent_req *subreq);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-struct tevent_req *ad_get_client_site_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_context *ev,
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
- enum host_database *host_db,
|
|
|
f9c044 |
- struct sdap_options *opts,
|
|
|
f9c044 |
- const char *ad_domain,
|
|
|
f9c044 |
- bool ad_use_ldaps,
|
|
|
f9c044 |
- struct fo_server_info *dcs,
|
|
|
f9c044 |
- size_t num_dcs)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_client_site_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_create(mem_ctx, &state,
|
|
|
f9c044 |
- struct ad_get_client_site_state);
|
|
|
f9c044 |
- if (req == NULL) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
- return NULL;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- if (be_res == NULL || host_db == NULL || opts == NULL) {
|
|
|
f9c044 |
- ret = EINVAL;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- state->ev = ev;
|
|
|
f9c044 |
- state->be_res = be_res;
|
|
|
f9c044 |
- state->host_db = host_db;
|
|
|
f9c044 |
- state->opts = opts;
|
|
|
f9c044 |
- state->ad_domain = ad_domain;
|
|
|
f9c044 |
- state->ad_use_ldaps = ad_use_ldaps;
|
|
|
f9c044 |
- state->dcs = dcs;
|
|
|
f9c044 |
- state->num_dcs = num_dcs;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- state->dc_index = 0;
|
|
|
f9c044 |
- ret = ad_get_client_site_next_dc(req);
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- ret = ENOENT;
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- } else if (ret != EAGAIN) {
|
|
|
f9c044 |
- goto immediately;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return req;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-immediately:
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
- } else {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
- tevent_req_post(req, ev);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return req;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static errno_t ad_get_client_site_next_dc(struct tevent_req *req)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_client_site_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *subreq = NULL;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_client_site_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- if (state->dc_index >= state->num_dcs) {
|
|
|
f9c044 |
- ret = EOK;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- state->dc = state->dcs[state->dc_index];
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- subreq = sdap_connect_host_send(state, state->ev, state->opts,
|
|
|
f9c044 |
- state->be_res->resolv,
|
|
|
f9c044 |
- state->be_res->family_order,
|
|
|
f9c044 |
- state->host_db,
|
|
|
f9c044 |
- "cldap",
|
|
|
f9c044 |
- state->dc.host,
|
|
|
f9c044 |
- state->dc.port,
|
|
|
f9c044 |
- false);
|
|
|
f9c044 |
- if (subreq == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_get_client_site_connect_done, req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- state->dc_index++;
|
|
|
f9c044 |
- ret = EAGAIN;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-done:
|
|
|
f9c044 |
- return ret;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static void ad_get_client_site_connect_done(struct tevent_req *subreq)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_client_site_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- static const char *attrs[] = {AD_AT_NETLOGON, NULL};
|
|
|
f9c044 |
- char *filter = NULL;
|
|
|
f9c044 |
- char *ntver = NULL;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_client_site_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = sdap_connect_host_recv(state, subreq, &state->sh);
|
|
|
f9c044 |
- talloc_zfree(subreq);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to connect to domain controller "
|
|
|
f9c044 |
- "[%s:%d]\n", state->dc.host, state->dc.port);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = ad_get_client_site_next_dc(req);
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- ret = ENOENT;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ntver = sss_ldap_encode_ndr_uint32(state, NETLOGON_NT_VERSION_5EX |
|
|
|
f9c044 |
- NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
|
|
|
f9c044 |
- if (ntver == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- filter = talloc_asprintf(state, "(&(%s=%s)(%s=%s))",
|
|
|
f9c044 |
- AD_AT_DNS_DOMAIN, state->ad_domain,
|
|
|
f9c044 |
- AD_AT_NT_VERSION, ntver);
|
|
|
f9c044 |
- if (filter == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
|
|
|
f9c044 |
- "", LDAP_SCOPE_BASE, filter,
|
|
|
f9c044 |
- attrs, NULL, 0,
|
|
|
f9c044 |
- dp_opt_get_int(state->opts->basic,
|
|
|
f9c044 |
- SDAP_SEARCH_TIMEOUT),
|
|
|
f9c044 |
- false);
|
|
|
f9c044 |
- if (subreq == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_get_client_site_done, req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = EAGAIN;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-done:
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
- } else if (ret != EAGAIN) {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static void ad_get_client_site_done(struct tevent_req *subreq)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_client_site_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- struct sysdb_attrs **reply = NULL;
|
|
|
f9c044 |
- size_t reply_count;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_client_site_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
|
|
|
f9c044 |
- talloc_zfree(subreq);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- /* we're done with this LDAP, close connection */
|
|
|
f9c044 |
- talloc_zfree(state->sh);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_OP_FAILURE, "Unable to get netlogon information\n");
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = ad_get_client_site_next_dc(req);
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- ret = ENOENT;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- if (reply_count == 0) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_OP_FAILURE, "No netlogon information retrieved\n");
|
|
|
f9c044 |
- ret = ENOENT;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = netlogon_get_domain_info(state, reply[0], true, NULL, &state->site,
|
|
|
f9c044 |
- &state->forest);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve site name [%d]: %s\n",
|
|
|
f9c044 |
- ret, strerror(ret));
|
|
|
f9c044 |
- ret = ENOENT;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site);
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-done:
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- return;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-int ad_get_client_site_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_req *req,
|
|
|
f9c044 |
- const char **_site,
|
|
|
f9c044 |
- const char **_forest)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_get_client_site_state *state = NULL;
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_get_client_site_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- *_site = talloc_steal(mem_ctx, state->site);
|
|
|
f9c044 |
- *_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return EOK;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
struct ad_srv_plugin_ctx {
|
|
|
f9c044 |
struct be_ctx *be_ctx;
|
|
|
f9c044 |
struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
@@ -610,8 +238,7 @@ struct ad_srv_plugin_state {
|
|
|
f9c044 |
size_t num_backup_servers;
|
|
|
f9c044 |
};
|
|
|
f9c044 |
|
|
|
f9c044 |
-static void ad_srv_plugin_dcs_done(struct tevent_req *subreq);
|
|
|
f9c044 |
-static void ad_srv_plugin_site_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+static void ad_srv_plugin_ping_done(struct tevent_req *subreq);
|
|
|
f9c044 |
static void ad_srv_plugin_servers_done(struct tevent_req *subreq);
|
|
|
f9c044 |
|
|
|
f9c044 |
/* 1. Do a DNS lookup to find any DC in domain
|
|
|
f9c044 |
@@ -677,15 +304,16 @@ struct tevent_req *ad_srv_plugin_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
|
|
|
f9c044 |
DEBUG(SSSDBG_TRACE_FUNC, "About to find domain controllers\n");
|
|
|
f9c044 |
|
|
|
f9c044 |
- subreq = ad_get_dc_servers_send(state, ev, ctx->be_res->resolv,
|
|
|
f9c044 |
- state->discovery_domain,
|
|
|
f9c044 |
- state->ctx->current_site);
|
|
|
f9c044 |
+ subreq = ad_cldap_ping_send(state, ev, ctx->opts, ctx->be_res,
|
|
|
f9c044 |
+ ctx->host_dbs, ctx->ad_domain,
|
|
|
f9c044 |
+ state->discovery_domain,
|
|
|
f9c044 |
+ state->ctx->current_site);
|
|
|
f9c044 |
if (subreq == NULL) {
|
|
|
f9c044 |
ret = ENOMEM;
|
|
|
f9c044 |
goto immediately;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_srv_plugin_dcs_done, req);
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_srv_plugin_ping_done, req);
|
|
|
f9c044 |
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
|
|
|
f9c044 |
@@ -696,52 +324,7 @@ immediately:
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-static void ad_srv_plugin_dcs_done(struct tevent_req *subreq)
|
|
|
f9c044 |
-{
|
|
|
f9c044 |
- struct ad_srv_plugin_state *state = NULL;
|
|
|
f9c044 |
- struct tevent_req *req = NULL;
|
|
|
f9c044 |
- struct fo_server_info *dcs = NULL;
|
|
|
f9c044 |
- size_t num_dcs = 0;
|
|
|
f9c044 |
- errno_t ret;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_srv_plugin_state);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = ad_get_dc_servers_recv(state, subreq, &dcs, &num_dcs);
|
|
|
f9c044 |
- talloc_zfree(subreq);
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "About to locate suitable site\n");
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- subreq = ad_get_client_site_send(state, state->ev,
|
|
|
f9c044 |
- state->ctx->be_res,
|
|
|
f9c044 |
- state->ctx->host_dbs,
|
|
|
f9c044 |
- state->ctx->opts,
|
|
|
f9c044 |
- state->discovery_domain,
|
|
|
f9c044 |
- state->ctx->ad_use_ldaps,
|
|
|
f9c044 |
- dcs, num_dcs);
|
|
|
f9c044 |
- if (subreq == NULL) {
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_srv_plugin_site_done, req);
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- ret = EAGAIN;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-done:
|
|
|
f9c044 |
- if (ret == EOK) {
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
- } else if (ret != EAGAIN) {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- return;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
-
|
|
|
f9c044 |
-static void ad_srv_plugin_site_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+static void ad_srv_plugin_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
struct ad_srv_plugin_state *state = NULL;
|
|
|
f9c044 |
struct tevent_req *req = NULL;
|
|
|
f9c044 |
@@ -752,8 +335,9 @@ static void ad_srv_plugin_site_done(struct tevent_req *subreq)
|
|
|
f9c044 |
req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
state = tevent_req_data(req, struct ad_srv_plugin_state);
|
|
|
f9c044 |
|
|
|
f9c044 |
- ret = ad_get_client_site_recv(state, subreq, &state->site, &state->forest);
|
|
|
f9c044 |
+ ret = ad_cldap_ping_recv(state, subreq, &state->site, &state->forest);
|
|
|
f9c044 |
talloc_zfree(subreq);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
/* Ignore AD site found by dns discovery if specific site is set in
|
|
|
f9c044 |
* configuration file. */
|
|
|
f9c044 |
if (state->ctx->ad_site_override != NULL) {
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.h b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
index e553d594d..c03ac873f 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
@@ -53,4 +53,18 @@ char *ad_site_dns_discovery_domain(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
const char *site,
|
|
|
f9c044 |
const char *domain);
|
|
|
f9c044 |
|
|
|
f9c044 |
+struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ const char *ad_domain,
|
|
|
f9c044 |
+ const char *discovery_domain,
|
|
|
f9c044 |
+ const char *current_site);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
#endif /* __AD_SRV_H__ */
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From 27f394bb477aadb879c55df8e956fd37fa810109 Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Tue, 25 Aug 2020 12:11:19 +0200
|
|
|
f9c044 |
Subject: [PATCH 4/7] ad: if all in-site dc are unreachable try off-site
|
|
|
f9c044 |
controllers
|
|
|
f9c044 |
|
|
|
f9c044 |
Previous implementation would not fallback to the off-site domain
|
|
|
f9c044 |
controllers. This would cause problems if the site actually changed.
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit fcfd834c9d80d7690f938582335d81231a5f6e60)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/providers/ad/ad_cldap_ping.c | 227 ++++++++++++++++++++++++-------
|
|
|
f9c044 |
1 file changed, 181 insertions(+), 46 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_cldap_ping.c b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
index 5fc1a4d20..7ecdcdbef 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
@@ -415,7 +415,7 @@ static errno_t ad_cldap_ping_parallel_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
return EOK;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-struct ad_cldap_ping_state {
|
|
|
f9c044 |
+struct ad_cldap_ping_domain_state {
|
|
|
f9c044 |
struct tevent_context *ev;
|
|
|
f9c044 |
struct sdap_options *opts;
|
|
|
f9c044 |
struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
@@ -428,25 +428,25 @@ struct ad_cldap_ping_state {
|
|
|
f9c044 |
const char *forest;
|
|
|
f9c044 |
};
|
|
|
f9c044 |
|
|
|
f9c044 |
-static void ad_cldap_ping_discovery_done(struct tevent_req *subreq);
|
|
|
f9c044 |
-static void ad_cldap_ping_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+static void ad_cldap_ping_domain_discovery_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+static void ad_cldap_ping_domain_done(struct tevent_req *subreq);
|
|
|
f9c044 |
|
|
|
f9c044 |
-struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_context *ev,
|
|
|
f9c044 |
- struct sdap_options *opts,
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
- enum host_database *host_db,
|
|
|
f9c044 |
- const char *ad_domain,
|
|
|
f9c044 |
- const char *discovery_domain,
|
|
|
f9c044 |
- const char *current_site)
|
|
|
f9c044 |
+static struct tevent_req *
|
|
|
f9c044 |
+ad_cldap_ping_domain_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ const char *ad_domain,
|
|
|
f9c044 |
+ const char *discovery_domain)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
- struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct ad_cldap_ping_domain_state *state;
|
|
|
f9c044 |
struct tevent_req *subreq;
|
|
|
f9c044 |
struct tevent_req *req;
|
|
|
f9c044 |
const char **domains;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
|
|
|
f9c044 |
- req = tevent_req_create(mem_ctx, &state, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+ req = tevent_req_create(mem_ctx, &state, struct ad_cldap_ping_domain_state);
|
|
|
f9c044 |
if (req == NULL) {
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
return NULL;
|
|
|
f9c044 |
@@ -458,25 +458,18 @@ struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
state->host_db = host_db;
|
|
|
f9c044 |
state->ad_domain = ad_domain;
|
|
|
f9c044 |
|
|
|
f9c044 |
- domains = talloc_zero_array(state, const char *, 3);
|
|
|
f9c044 |
+ domains = talloc_zero_array(state, const char *, 2);
|
|
|
f9c044 |
if (domains == NULL) {
|
|
|
f9c044 |
ret = ENOMEM;
|
|
|
f9c044 |
goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- if (current_site == NULL) {
|
|
|
f9c044 |
- domains[0] = discovery_domain;
|
|
|
f9c044 |
- domains[1] = NULL;
|
|
|
f9c044 |
- } else {
|
|
|
f9c044 |
- domains[0] = ad_site_dns_discovery_domain(state, current_site,
|
|
|
f9c044 |
- discovery_domain);
|
|
|
f9c044 |
- domains[1] = discovery_domain;
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- if (domains[0] == NULL) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
- ret = ENOMEM;
|
|
|
f9c044 |
- goto done;
|
|
|
f9c044 |
- }
|
|
|
f9c044 |
+ domains[0] = discovery_domain;
|
|
|
f9c044 |
+ domains[1] = NULL;
|
|
|
f9c044 |
+ if (domains[0] == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
/* Even though we use CLDAP (UDP) to perform the ping we need to discover
|
|
|
f9c044 |
@@ -489,7 +482,7 @@ struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_cldap_ping_discovery_done, req);
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_domain_discovery_done, req);
|
|
|
f9c044 |
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
|
|
|
f9c044 |
@@ -500,15 +493,15 @@ done:
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-static void ad_cldap_ping_discovery_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+static void ad_cldap_ping_domain_discovery_done(struct tevent_req *subreq)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
- struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct ad_cldap_ping_domain_state *state;
|
|
|
f9c044 |
struct tevent_req *req;
|
|
|
f9c044 |
char *domain;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
|
|
|
f9c044 |
req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_domain_state);
|
|
|
f9c044 |
|
|
|
f9c044 |
ret = fo_discover_srv_recv(state, subreq, &domain, NULL, &state->dc_list,
|
|
|
f9c044 |
&state->dc_count);
|
|
|
f9c044 |
@@ -529,7 +522,7 @@ static void ad_cldap_ping_discovery_done(struct tevent_req *subreq)
|
|
|
f9c044 |
goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- tevent_req_set_callback(subreq, ad_cldap_ping_done, req);
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_domain_done, req);
|
|
|
f9c044 |
|
|
|
f9c044 |
done:
|
|
|
f9c044 |
if (ret != EOK) {
|
|
|
f9c044 |
@@ -538,41 +531,183 @@ done:
|
|
|
f9c044 |
}
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-static void ad_cldap_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+static void ad_cldap_ping_domain_done(struct tevent_req *subreq)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
- struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct ad_cldap_ping_domain_state *state;
|
|
|
f9c044 |
struct tevent_req *req;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
|
|
|
f9c044 |
req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
- state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_domain_state);
|
|
|
f9c044 |
|
|
|
f9c044 |
ret = ad_cldap_ping_parallel_recv(state, subreq, &state->site,
|
|
|
f9c044 |
&state->forest);
|
|
|
f9c044 |
talloc_zfree(subreq);
|
|
|
f9c044 |
if (ret != EOK) {
|
|
|
f9c044 |
- DEBUG(SSSDBG_OP_FAILURE,
|
|
|
f9c044 |
- "Unable to get site and forest information [%d]: %s\n",
|
|
|
f9c044 |
- ret, sss_strerror(ret));
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static errno_t ad_cldap_ping_domain_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_domain_state *state = NULL;
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_domain_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ *_site = talloc_steal(mem_ctx, state->site);
|
|
|
f9c044 |
+ *_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return EOK;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct ad_cldap_ping_state {
|
|
|
f9c044 |
+ struct tevent_context *ev;
|
|
|
f9c044 |
+ struct sdap_options *opts;
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
+ enum host_database *host_db;
|
|
|
f9c044 |
+ const char *ad_domain;
|
|
|
f9c044 |
+ const char *discovery_domain;
|
|
|
f9c044 |
+ bool all_tried;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ const char *site;
|
|
|
f9c044 |
+ const char *forest;
|
|
|
f9c044 |
+};
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static errno_t ad_cldap_ping_step(struct tevent_req *req,
|
|
|
f9c044 |
+ const char *domain);
|
|
|
f9c044 |
+static void ad_cldap_ping_done(struct tevent_req *subreq);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
+ struct tevent_context *ev,
|
|
|
f9c044 |
+ struct sdap_options *opts,
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
+ enum host_database *host_db,
|
|
|
f9c044 |
+ const char *ad_domain,
|
|
|
f9c044 |
+ const char *discovery_domain,
|
|
|
f9c044 |
+ const char *current_site)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ const char *domain;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_create(mem_ctx, &state, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+ if (req == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
|
|
|
f9c044 |
+ return NULL;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state->ev = ev;
|
|
|
f9c044 |
+ state->opts = opts;
|
|
|
f9c044 |
+ state->be_res = be_res;
|
|
|
f9c044 |
+ state->host_db = host_db;
|
|
|
f9c044 |
+ state->ad_domain = ad_domain;
|
|
|
f9c044 |
+ state->discovery_domain = discovery_domain;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ /* If possible, lookup the information in the current site first. */
|
|
|
f9c044 |
+ if (current_site != NULL) {
|
|
|
f9c044 |
+ state->all_tried = false;
|
|
|
f9c044 |
+ domain = ad_site_dns_discovery_domain(state, current_site,
|
|
|
f9c044 |
+ discovery_domain);
|
|
|
f9c044 |
+ if (domain == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ } else {
|
|
|
f9c044 |
+ state->all_tried = true;
|
|
|
f9c044 |
+ domain = discovery_domain;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = ad_cldap_ping_step(req, domain);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site);
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest);
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
|
|
|
f9c044 |
done:
|
|
|
f9c044 |
- if (ret != EOK) {
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ tevent_req_post(req, ev);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return req;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static errno_t ad_cldap_ping_step(struct tevent_req *req,
|
|
|
f9c044 |
+ const char *domain)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *subreq;
|
|
|
f9c044 |
+ struct timeval tv;
|
|
|
f9c044 |
+ int timeout;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ subreq = ad_cldap_ping_domain_send(state, state->ev, state->opts,
|
|
|
f9c044 |
+ state->be_res, state->host_db,
|
|
|
f9c044 |
+ state->ad_domain, domain);
|
|
|
f9c044 |
+ if (subreq == NULL) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
+ return ENOMEM;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_set_callback(subreq, ad_cldap_ping_done, req);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ timeout = dp_opt_get_int(state->be_res->opts,
|
|
|
f9c044 |
+ DP_RES_OPT_RESOLVER_OP_TIMEOUT);
|
|
|
f9c044 |
+ if (timeout > 0) {
|
|
|
f9c044 |
+ tv = tevent_timeval_current_ofs(timeout, 0);
|
|
|
f9c044 |
+ tevent_req_set_endtime(subreq, state->ev, tv);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ return EOK;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+static void ad_cldap_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
+ struct tevent_req *req;
|
|
|
f9c044 |
+ errno_t ret;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ req = tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
f9c044 |
+ state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ret = ad_cldap_ping_domain_recv(state, subreq, &state->site,
|
|
|
f9c044 |
+ &state->forest);
|
|
|
f9c044 |
+ talloc_zfree(subreq);
|
|
|
f9c044 |
+ if (ret == EOK) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site);
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest);
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
return;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- tevent_req_done(req);
|
|
|
f9c044 |
+ if (!state->all_tried) {
|
|
|
f9c044 |
+ state->all_tried = true;
|
|
|
f9c044 |
+ ret = ad_cldap_ping_step(req, state->discovery_domain);
|
|
|
f9c044 |
+ if (ret == EOK) {
|
|
|
f9c044 |
+ return;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
f9c044 |
+ "Unable to get site and forest information [%d]: %s\n",
|
|
|
f9c044 |
+ ret, sss_strerror(ret));
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_req *req,
|
|
|
f9c044 |
- const char **_site,
|
|
|
f9c044 |
- const char **_forest)
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
struct ad_cldap_ping_state *state = NULL;
|
|
|
f9c044 |
state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From 8249161d967a37847f42b62e0e6a384d063884af Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Tue, 25 Aug 2020 13:43:32 +0200
|
|
|
f9c044 |
Subject: [PATCH 5/7] ad: renew site information only when SSSD was previously
|
|
|
f9c044 |
offline
|
|
|
f9c044 |
|
|
|
f9c044 |
Site and forest information is stable not dynamic. To avoid spamming
|
|
|
f9c044 |
network with cldap pings all the time we will renew netlogon information
|
|
|
f9c044 |
only when SSSD starts and when we are recovering from an offline state
|
|
|
f9c044 |
to detect possible change (e.g. user moves to another location with laptop).
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit 9fdf5cfacd1a425691d44db53897096887bb3e6f)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/providers/ad/ad_cldap_ping.c | 45 ++++++++++++++++----------
|
|
|
f9c044 |
src/providers/ad/ad_srv.c | 54 +++++++++++++++++++++-----------
|
|
|
f9c044 |
src/providers/ad/ad_srv.h | 22 ++++++++-----
|
|
|
f9c044 |
3 files changed, 80 insertions(+), 41 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_cldap_ping.c b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
index 7ecdcdbef..dc25f6670 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
@@ -586,12 +586,8 @@ static void ad_cldap_ping_done(struct tevent_req *subreq);
|
|
|
f9c044 |
|
|
|
f9c044 |
struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_context *ev,
|
|
|
f9c044 |
- struct sdap_options *opts,
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
- enum host_database *host_db,
|
|
|
f9c044 |
- const char *ad_domain,
|
|
|
f9c044 |
- const char *discovery_domain,
|
|
|
f9c044 |
- const char *current_site)
|
|
|
f9c044 |
+ struct ad_srv_plugin_ctx *srv_ctx,
|
|
|
f9c044 |
+ const char *discovery_domain)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
struct ad_cldap_ping_state *state;
|
|
|
f9c044 |
struct tevent_req *req;
|
|
|
f9c044 |
@@ -604,17 +600,30 @@ struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
return NULL;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
+ if (!srv_ctx->renew_site) {
|
|
|
f9c044 |
+ state->site = srv_ctx->current_site;
|
|
|
f9c044 |
+ state->forest = srv_ctx->current_forest;
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
f9c044 |
+ "CLDAP ping is not necessary, using site '%s' and forest '%s'\n",
|
|
|
f9c044 |
+ state->site != NULL ? state->site : "unknown",
|
|
|
f9c044 |
+ state->forest != NULL ? state->forest : "unknown");
|
|
|
f9c044 |
+ ret = EOK;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ DEBUG(SSSDBG_TRACE_FUNC, "Sending CLDAP ping\n");
|
|
|
f9c044 |
+
|
|
|
f9c044 |
state->ev = ev;
|
|
|
f9c044 |
- state->opts = opts;
|
|
|
f9c044 |
- state->be_res = be_res;
|
|
|
f9c044 |
- state->host_db = host_db;
|
|
|
f9c044 |
- state->ad_domain = ad_domain;
|
|
|
f9c044 |
+ state->opts = srv_ctx->opts;
|
|
|
f9c044 |
+ state->be_res = srv_ctx->be_res;
|
|
|
f9c044 |
+ state->host_db = srv_ctx->host_dbs;
|
|
|
f9c044 |
+ state->ad_domain = srv_ctx->ad_domain;
|
|
|
f9c044 |
state->discovery_domain = discovery_domain;
|
|
|
f9c044 |
|
|
|
f9c044 |
/* If possible, lookup the information in the current site first. */
|
|
|
f9c044 |
- if (current_site != NULL) {
|
|
|
f9c044 |
+ if (srv_ctx->current_site != NULL) {
|
|
|
f9c044 |
state->all_tried = false;
|
|
|
f9c044 |
- domain = ad_site_dns_discovery_domain(state, current_site,
|
|
|
f9c044 |
+ domain = ad_site_dns_discovery_domain(state, srv_ctx->current_site,
|
|
|
f9c044 |
discovery_domain);
|
|
|
f9c044 |
if (domain == NULL) {
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!");
|
|
|
f9c044 |
@@ -634,7 +643,11 @@ struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
|
|
|
f9c044 |
done:
|
|
|
f9c044 |
- tevent_req_error(req, ret);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ tevent_req_error(req, ret);
|
|
|
f9c044 |
+ } else {
|
|
|
f9c044 |
+ tevent_req_done(req);
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
tevent_req_post(req, ev);
|
|
|
f9c044 |
|
|
|
f9c044 |
return req;
|
|
|
f9c044 |
@@ -705,9 +718,9 @@ static void ad_cldap_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
- struct tevent_req *req,
|
|
|
f9c044 |
- const char **_site,
|
|
|
f9c044 |
- const char **_forest)
|
|
|
f9c044 |
+ struct tevent_req *req,
|
|
|
f9c044 |
+ const char **_site,
|
|
|
f9c044 |
+ const char **_forest)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
struct ad_cldap_ping_state *state = NULL;
|
|
|
f9c044 |
state = tevent_req_data(req, struct ad_cldap_ping_state);
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
index d12f0971c..e58c19aac 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.c
|
|
|
f9c044 |
@@ -116,16 +116,13 @@ static errno_t ad_sort_servers_by_dns(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
return EOK;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
-struct ad_srv_plugin_ctx {
|
|
|
f9c044 |
- struct be_ctx *be_ctx;
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
- enum host_database *host_dbs;
|
|
|
f9c044 |
- struct sdap_options *opts;
|
|
|
f9c044 |
- const char *hostname;
|
|
|
f9c044 |
- const char *ad_domain;
|
|
|
f9c044 |
- const char *ad_site_override;
|
|
|
f9c044 |
- const char *current_site;
|
|
|
f9c044 |
-};
|
|
|
f9c044 |
+static void ad_srv_mark_renew_site(void *pvt)
|
|
|
f9c044 |
+{
|
|
|
f9c044 |
+ struct ad_srv_plugin_ctx *ctx;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ ctx = talloc_get_type(pvt, struct ad_srv_plugin_ctx);
|
|
|
f9c044 |
+ ctx->renew_site = true;
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
|
|
|
f9c044 |
struct ad_srv_plugin_ctx *
|
|
|
f9c044 |
ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
@@ -149,6 +146,7 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
ctx->be_res = be_res;
|
|
|
f9c044 |
ctx->host_dbs = host_dbs;
|
|
|
f9c044 |
ctx->opts = opts;
|
|
|
f9c044 |
+ ctx->renew_site = true;
|
|
|
f9c044 |
|
|
|
f9c044 |
ctx->hostname = talloc_strdup(ctx, hostname);
|
|
|
f9c044 |
if (ctx->hostname == NULL) {
|
|
|
f9c044 |
@@ -181,6 +179,12 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
}
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
+ ret = be_add_offline_cb(ctx, be_ctx, ad_srv_mark_renew_site, ctx, NULL);
|
|
|
f9c044 |
+ if (ret != EOK) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
|
|
|
f9c044 |
+ goto fail;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
return ctx;
|
|
|
f9c044 |
|
|
|
f9c044 |
fail:
|
|
|
f9c044 |
@@ -190,11 +194,26 @@ fail:
|
|
|
f9c044 |
|
|
|
f9c044 |
static errno_t
|
|
|
f9c044 |
ad_srv_plugin_ctx_switch_site(struct ad_srv_plugin_ctx *ctx,
|
|
|
f9c044 |
- const char *new_site)
|
|
|
f9c044 |
+ const char *new_site,
|
|
|
f9c044 |
+ const char *new_forest)
|
|
|
f9c044 |
{
|
|
|
f9c044 |
const char *site;
|
|
|
f9c044 |
+ const char *forest;
|
|
|
f9c044 |
errno_t ret;
|
|
|
f9c044 |
|
|
|
f9c044 |
+ /* Switch forest. */
|
|
|
f9c044 |
+ if (new_forest != NULL
|
|
|
f9c044 |
+ && (ctx->current_forest == NULL
|
|
|
f9c044 |
+ || strcmp(ctx->current_forest, new_forest) != 0)) {
|
|
|
f9c044 |
+ forest = talloc_strdup(ctx, new_forest);
|
|
|
f9c044 |
+ if (forest == NULL) {
|
|
|
f9c044 |
+ return ENOMEM;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ talloc_zfree(ctx->current_forest);
|
|
|
f9c044 |
+ ctx->current_forest = forest;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
if (new_site == NULL) {
|
|
|
f9c044 |
return EOK;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
@@ -302,12 +321,7 @@ struct tevent_req *ad_srv_plugin_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
goto immediately;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
- DEBUG(SSSDBG_TRACE_FUNC, "About to find domain controllers\n");
|
|
|
f9c044 |
-
|
|
|
f9c044 |
- subreq = ad_cldap_ping_send(state, ev, ctx->opts, ctx->be_res,
|
|
|
f9c044 |
- ctx->host_dbs, ctx->ad_domain,
|
|
|
f9c044 |
- state->discovery_domain,
|
|
|
f9c044 |
- state->ctx->current_site);
|
|
|
f9c044 |
+ subreq = ad_cldap_ping_send(state, ev, state->ctx, state->discovery_domain);
|
|
|
f9c044 |
if (subreq == NULL) {
|
|
|
f9c044 |
ret = ENOMEM;
|
|
|
f9c044 |
goto immediately;
|
|
|
f9c044 |
@@ -363,13 +377,17 @@ static void ad_srv_plugin_ping_done(struct tevent_req *subreq)
|
|
|
f9c044 |
/* Remember current site so it can be used during next lookup so
|
|
|
f9c044 |
* we can contact directory controllers within a known reachable
|
|
|
f9c044 |
* site first. */
|
|
|
f9c044 |
- ret = ad_srv_plugin_ctx_switch_site(state->ctx, state->site);
|
|
|
f9c044 |
+ ret = ad_srv_plugin_ctx_switch_site(state->ctx, state->site,
|
|
|
f9c044 |
+ state->forest);
|
|
|
f9c044 |
if (ret != EOK) {
|
|
|
f9c044 |
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set site [%d]: %s\n",
|
|
|
f9c044 |
ret, sss_strerror(ret));
|
|
|
f9c044 |
goto done;
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
+ /* Do not renew the site again unless we go offline. */
|
|
|
f9c044 |
+ state->ctx->renew_site = false;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
if (strcmp(state->service, "gc") == 0) {
|
|
|
f9c044 |
if (state->forest != NULL) {
|
|
|
f9c044 |
if (state->site != NULL) {
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_srv.h b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
index c03ac873f..3c6a779ea 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_srv.h
|
|
|
f9c044 |
@@ -21,7 +21,19 @@
|
|
|
f9c044 |
#ifndef __AD_SRV_H__
|
|
|
f9c044 |
#define __AD_SRV_H__
|
|
|
f9c044 |
|
|
|
f9c044 |
-struct ad_srv_plugin_ctx;
|
|
|
f9c044 |
+struct ad_srv_plugin_ctx {
|
|
|
f9c044 |
+ struct be_ctx *be_ctx;
|
|
|
f9c044 |
+ struct be_resolv_ctx *be_res;
|
|
|
f9c044 |
+ enum host_database *host_dbs;
|
|
|
f9c044 |
+ struct sdap_options *opts;
|
|
|
f9c044 |
+ const char *hostname;
|
|
|
f9c044 |
+ const char *ad_domain;
|
|
|
f9c044 |
+ const char *ad_site_override;
|
|
|
f9c044 |
+ const char *current_site;
|
|
|
f9c044 |
+ const char *current_forest;
|
|
|
f9c044 |
+
|
|
|
f9c044 |
+ bool renew_site;
|
|
|
f9c044 |
+};
|
|
|
f9c044 |
|
|
|
f9c044 |
struct ad_srv_plugin_ctx *
|
|
|
f9c044 |
ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
@@ -55,12 +67,8 @@ char *ad_site_dns_discovery_domain(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
|
|
|
f9c044 |
struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_context *ev,
|
|
|
f9c044 |
- struct sdap_options *opts,
|
|
|
f9c044 |
- struct be_resolv_ctx *be_res,
|
|
|
f9c044 |
- enum host_database *host_db,
|
|
|
f9c044 |
- const char *ad_domain,
|
|
|
f9c044 |
- const char *discovery_domain,
|
|
|
f9c044 |
- const char *current_site);
|
|
|
f9c044 |
+ struct ad_srv_plugin_ctx *srv_ctx,
|
|
|
f9c044 |
+ const char *discovery_domain);
|
|
|
f9c044 |
|
|
|
f9c044 |
errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
struct tevent_req *req,
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From 08fde220baab823f53fd359746c7e75eaeb0580f Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
f9c044 |
Date: Wed, 30 Sep 2020 13:45:43 +0200
|
|
|
f9c044 |
Subject: [PATCH 6/7] tevent: correctly handle req timeout error
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit f0d650799d4390f90890d17c56a4e395e931d8cb)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/util/util.h | 14 +++++++++-----
|
|
|
f9c044 |
1 file changed, 9 insertions(+), 5 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/util/util.h b/src/util/util.h
|
|
|
f9c044 |
index 94c2e6e3b..2cc7f98a3 100644
|
|
|
f9c044 |
--- a/src/util/util.h
|
|
|
f9c044 |
+++ b/src/util/util.h
|
|
|
f9c044 |
@@ -139,13 +139,17 @@ extern int dbus_activated;
|
|
|
f9c044 |
\
|
|
|
f9c044 |
if (tevent_req_is_error(req, &TRROEstate, &TRROEuint64)) { \
|
|
|
f9c044 |
TRROEerr = (errno_t)TRROEuint64; \
|
|
|
f9c044 |
- if (TRROEstate == TEVENT_REQ_USER_ERROR) { \
|
|
|
f9c044 |
- if (TRROEerr == 0) { \
|
|
|
f9c044 |
+ switch (TRROEstate) { \
|
|
|
f9c044 |
+ case TEVENT_REQ_USER_ERROR: \
|
|
|
f9c044 |
+ if (TRROEerr == 0) { \
|
|
|
f9c044 |
+ return ERR_INTERNAL; \
|
|
|
f9c044 |
+ } \
|
|
|
f9c044 |
+ return TRROEerr; \
|
|
|
f9c044 |
+ case TEVENT_REQ_TIMED_OUT: \
|
|
|
f9c044 |
+ return ETIMEDOUT; \
|
|
|
f9c044 |
+ default: \
|
|
|
f9c044 |
return ERR_INTERNAL; \
|
|
|
f9c044 |
- } \
|
|
|
f9c044 |
- return TRROEerr; \
|
|
|
f9c044 |
} \
|
|
|
f9c044 |
- return ERR_INTERNAL; \
|
|
|
f9c044 |
} \
|
|
|
f9c044 |
} while (0)
|
|
|
f9c044 |
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|
|
|
f9c044 |
|
|
|
f9c044 |
From a431a977852dde6af194f9306291d7fcc2624cb6 Mon Sep 17 00:00:00 2001
|
|
|
f9c044 |
From: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
Date: Mon, 5 Oct 2020 10:58:49 +0200
|
|
|
f9c044 |
Subject: [PATCH 7/7] ad: fix handling of current site and forest in cldap ping
|
|
|
f9c044 |
MIME-Version: 1.0
|
|
|
f9c044 |
Content-Type: text/plain; charset=UTF-8
|
|
|
f9c044 |
Content-Transfer-Encoding: 8bit
|
|
|
f9c044 |
|
|
|
f9c044 |
The current site and forest are stored in a long living context and we
|
|
|
f9c044 |
have to make sure that they are not moved to a different talloc parent
|
|
|
f9c044 |
with a shorter lifetime. To achieve this the values are copied at the
|
|
|
f9c044 |
start of a new cldap ping although it is expected that the values won't
|
|
|
f9c044 |
change.
|
|
|
f9c044 |
|
|
|
f9c044 |
Resolves: https://github.com/SSSD/sssd/issues/3743
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
f9c044 |
(cherry picked from commit 37ba37a425453d8222584176ae5975a795422091)
|
|
|
f9c044 |
|
|
|
f9c044 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
f9c044 |
---
|
|
|
f9c044 |
src/providers/ad/ad_cldap_ping.c | 14 +++++++++++---
|
|
|
f9c044 |
1 file changed, 11 insertions(+), 3 deletions(-)
|
|
|
f9c044 |
|
|
|
f9c044 |
diff --git a/src/providers/ad/ad_cldap_ping.c b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
index dc25f6670..ab234f4d7 100644
|
|
|
f9c044 |
--- a/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
+++ b/src/providers/ad/ad_cldap_ping.c
|
|
|
f9c044 |
@@ -601,8 +601,16 @@ struct tevent_req *ad_cldap_ping_send(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
}
|
|
|
f9c044 |
|
|
|
f9c044 |
if (!srv_ctx->renew_site) {
|
|
|
f9c044 |
- state->site = srv_ctx->current_site;
|
|
|
f9c044 |
- state->forest = srv_ctx->current_forest;
|
|
|
f9c044 |
+ state->site = talloc_strdup(state, srv_ctx->current_site);
|
|
|
f9c044 |
+ state->forest = talloc_strdup(state, srv_ctx->current_forest);
|
|
|
f9c044 |
+ if ((srv_ctx->current_site != NULL && state->site == NULL)
|
|
|
f9c044 |
+ || (srv_ctx->current_forest != NULL && state->forest == NULL)) {
|
|
|
f9c044 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
f9c044 |
+ "Failed to copy current site or forest name.\n");
|
|
|
f9c044 |
+ ret = ENOMEM;
|
|
|
f9c044 |
+ goto done;
|
|
|
f9c044 |
+ }
|
|
|
f9c044 |
+
|
|
|
f9c044 |
DEBUG(SSSDBG_TRACE_FUNC,
|
|
|
f9c044 |
"CLDAP ping is not necessary, using site '%s' and forest '%s'\n",
|
|
|
f9c044 |
state->site != NULL ? state->site : "unknown",
|
|
|
f9c044 |
@@ -731,4 +739,4 @@ errno_t ad_cldap_ping_recv(TALLOC_CTX *mem_ctx,
|
|
|
f9c044 |
*_forest = talloc_steal(mem_ctx, state->forest);
|
|
|
f9c044 |
|
|
|
f9c044 |
return EOK;
|
|
|
f9c044 |
-}
|
|
|
f9c044 |
\ No newline at end of file
|
|
|
f9c044 |
+}
|
|
|
f9c044 |
--
|
|
|
f9c044 |
2.26.3
|
|
|
f9c044 |
|