From 7048844f9a8734b5dfa2158464d3d2fe57c2fcfa Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 23 2020 06:09:32 +0000 Subject: Apply patch 0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch patch_name: 0001-Make-adcli-info-DC-location-mechanism-more-compliant.patch present_in_specfile: true location_in_specfile: 63 --- diff --git a/library/addisco.c b/library/addisco.c index bf38e71..0ff07c7 100644 --- a/library/addisco.c +++ b/library/addisco.c @@ -41,8 +41,10 @@ #include #include -/* Number of servers to do discovery against */ -#define DISCO_COUNT 5 +/* Number of servers to do discovery against. + * For AD DS maximum number of DCs is 1200. + */ +#define DISCO_COUNT 1200 /* The time period in which to do rapid requests */ #define DISCO_FEVER 1 @@ -446,6 +448,51 @@ parse_disco (LDAP *ldap, } static int +ldap_disco_poller (LDAP **ldap, + LDAPMessage **message, + adcli_disco **results, + const char **addrs) +{ + int found = ADCLI_DISCO_UNUSABLE; + int close_ldap; + int parsed; + int ret = 0; + struct timeval tvpoll = { 0, 0 }; + + switch (ldap_result (*ldap, LDAP_RES_ANY, 1, &tvpoll, message)) { + case LDAP_RES_SEARCH_ENTRY: + case LDAP_RES_SEARCH_RESULT: + parsed = parse_disco (*ldap, *addrs, *message, results); + if (parsed > found) + found = parsed; + ldap_msgfree (*message); + close_ldap = 1; + break; + case -1: + ldap_get_option (*ldap, LDAP_OPT_RESULT_CODE, &ret); + close_ldap = 1; + break; + default: + ldap_msgfree (*message); + close_ldap = 0; + break; + } + + if (ret != LDAP_SUCCESS) { + _adcli_ldap_handle_failure (*ldap, ADCLI_ERR_CONFIG, + "Couldn't perform discovery search"); + } + + /* Done with this connection */ + if (close_ldap) { + ldap_unbind_ext_s (*ldap, NULL, NULL); + *ldap = NULL; + } + + return found; +} + +static int ldap_disco (const char *domain, srvinfo *srv, adcli_disco **results) @@ -469,6 +516,7 @@ ldap_disco (const char *domain, int num, i; int ret; int have_any = 0; + struct timeval interval; if (domain) { value = _adcli_ldap_escape_filter (domain); @@ -532,7 +580,6 @@ ldap_disco (const char *domain, version = LDAP_VERSION3; ldap_set_option (ldap[num], LDAP_OPT_PROTOCOL_VERSION, &version); ldap_set_option (ldap[num], LDAP_OPT_REFERRALS , 0); - _adcli_info ("Sending netlogon pings to domain controller: %s", url); addrs[num] = srv->hostname; have_any = 1; num++; @@ -547,70 +594,65 @@ ldap_disco (const char *domain, freeaddrinfo (res); } - /* Wait for the first response. Poor mans fd watch */ - for (started = now = time (NULL); - have_any && found != ADCLI_DISCO_USABLE && now < started + DISCO_TIME; - now = time (NULL)) { + /* Initial send and short time wait */ + interval.tv_sec = 0; + for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) { + int parsed; + + if (NULL == ldap[i]) + continue; - struct timeval tvpoll = { 0, 0 }; - struct timeval interval; + have_any = 1; + _adcli_info ("Sending NetLogon ping to domain controller: %s", addrs[i]); - /* If in the initial period, send feverishly */ - if (now < started + DISCO_FEVER) { - interval.tv_sec = 0; - interval.tv_usec = 100 * 1000; + ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE, + filter, attrs, 0, NULL, NULL, NULL, + -1, &msgidp); + + if (ret != LDAP_SUCCESS) { + _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG, + "Couldn't perform discovery search"); + ldap_unbind_ext_s (ldap[i], NULL, NULL); + ldap[i] = NULL; + } + + /* From https://msdn.microsoft.com/en-us/library/ff718294.aspx first + * five DCs are given 0.4 seconds timeout, next five are given 0.2 + * seconds, and the rest are given 0.1 seconds + */ + if (i < 5) { + interval.tv_usec = 400000; + } else if (i < 10) { + interval.tv_usec = 200000; } else { - interval.tv_sec = 1; - interval.tv_usec = 0; + interval.tv_usec = 100000; } + select (0, NULL, NULL, NULL, &interval); + + parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i])); + if (parsed > found) + found = parsed; + } + + /* Wait some more until LDAP timeout (DISCO_TIME) */ + for (started = now = time (NULL); + have_any && ADCLI_DISCO_UNUSABLE == found && now < started + DISCO_TIME; + now = time (NULL)) { select (0, NULL, NULL, NULL, &interval); have_any = 0; - for (i = 0; found != ADCLI_DISCO_USABLE && i < num; i++) { - int close_ldap; + for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) { int parsed; if (ldap[i] == NULL) continue; - ret = 0; have_any = 1; - switch (ldap_result (ldap[i], LDAP_RES_ANY, 1, &tvpoll, &message)) { - case LDAP_RES_SEARCH_ENTRY: - case LDAP_RES_SEARCH_RESULT: - parsed = parse_disco (ldap[i], addrs[i], message, results); - if (parsed > found) - found = parsed; - ldap_msgfree (message); - close_ldap = 1; - break; - case 0: - ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE, - filter, attrs, 0, NULL, NULL, NULL, - -1, &msgidp); - close_ldap = (ret != 0); - break; - case -1: - ldap_get_option (ldap[i], LDAP_OPT_RESULT_CODE, &ret); - close_ldap = 1; - break; - default: - ldap_msgfree (message); - close_ldap = 0; - break; - } - - if (ret != LDAP_SUCCESS) { - _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG, - "Couldn't perform discovery search"); - } - /* Done with this connection */ - if (close_ldap) { - ldap_unbind_ext_s (ldap[i], NULL, NULL); - ldap[i] = NULL; - } + parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i])); + if (parsed > found) + found = parsed; } }