From 2a2dd6ff5e057b1dec37a212b0a5eeb2a8392c36 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 12 Oct 2011 19:41:45 +0200 Subject: s3: Before adding KDC's to the krb5.conf, cldap ping them Some Kerberos libraries don't do proper failover. This fixes the situation where a KDC exists in DNS but is not reachable for some reason. Ported to master by Stefan Metzmacher Autobuild-User: Stefan Metzmacher Autobuild-Date: Mon Oct 17 11:25:37 CEST 2011 on sn-devel-104 --- source3/libads/kerberos.c | 148 +++++++++++++++++++++++++++++++--------------- 1 file changed, 101 insertions(+), 47 deletions(-) (limited to 'source3/libads') diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 5c62ead689..d111d018e0 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -26,7 +26,9 @@ #include "smb_krb5.h" #include "../librpc/gen_ndr/ndr_misc.h" #include "libads/kerberos_proto.h" +#include "libads/cldap.h" #include "secrets.h" +#include "../lib/tsocket/tsocket.h" #ifdef HAVE_KRB5 @@ -735,17 +737,40 @@ static char *print_kdc_line(char *mem_ctx, ************************************************************************/ +static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs, + const struct sockaddr_storage *addr) +{ + int i; + + for (i=0; i<*num_addrs; i++) { + if (sockaddr_equal((const struct sockaddr *)&addrs[i], + (const struct sockaddr *)addr)) { + return; + } + } + addrs[i] = *addr; + *num_addrs += 1; +} + static char *get_kdc_ip_string(char *mem_ctx, const char *realm, const char *sitename, const struct sockaddr_storage *pss, const char *kdc_name) { + TALLOC_CTX *frame = talloc_stackframe(); int i; struct ip_service *ip_srv_site = NULL; struct ip_service *ip_srv_nonsite = NULL; int count_site = 0; int count_nonsite; + int num_dcs; + struct sockaddr_storage *dc_addrs; + struct tsocket_address **dc_addrs2 = NULL; + const struct tsocket_address * const *dc_addrs3 = NULL; + char *result = NULL; + struct netlogon_samlogon_response **responses = NULL; + NTSTATUS status; char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name); if (kdc_str == NULL) { @@ -758,73 +783,102 @@ static char *get_kdc_ip_string(char *mem_ctx, */ if (sitename) { - get_kdc_list(realm, sitename, &ip_srv_site, &count_site); - - for (i = 0; i < count_site; i++) { - if (sockaddr_equal((struct sockaddr *)&ip_srv_site[i].ss, - (struct sockaddr *)pss)) { - continue; - } - /* Append to the string - inefficient - * but not done often. */ - kdc_str = print_kdc_line(mem_ctx, - kdc_str, - &ip_srv_site[i].ss, - NULL); - if (!kdc_str) { - SAFE_FREE(ip_srv_site); - return NULL; - } - } } /* Get all KDC's. */ get_kdc_list(realm, NULL, &ip_srv_nonsite, &count_nonsite); - for (i = 0; i < count_nonsite; i++) { - int j; + dc_addrs = talloc_array(talloc_tos(), struct sockaddr_storage, + 1 + count_site + count_nonsite); + if (dc_addrs == NULL) { + goto fail; + } - if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss, (struct sockaddr *)pss)) { - continue; - } + dc_addrs[0] = *pss; + num_dcs = 1; - /* Ensure this isn't an IP already seen (YUK! this is n*n....) */ - for (j = 0; j < count_site; j++) { - if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss, - (struct sockaddr *)&ip_srv_site[j].ss)) { - break; - } - /* As the lists are sorted we can break early if nonsite > site. */ - if (ip_service_compare(&ip_srv_nonsite[i], &ip_srv_site[j]) > 0) { - break; - } + for (i=0; i