changeset 21439:ee46bbf8eb49

11006 idmap fall-back to DC discovery is broken Reviewed by: Evan Layton <evan.layton@nexenta.com> Reviewed by: Matt Barden <matt.barden@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Gordon Ross <gwr@nexenta.com>
date Fri, 19 Apr 2019 12:08:05 -0400
parents 90c979f55037
children 6e83b56a703d
files usr/src/cmd/idmap/test-getdc/getdc_main.c usr/src/lib/libadutils/common/addisc.c
diffstat 2 files changed, 170 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/idmap/test-getdc/getdc_main.c	Thu Feb 07 16:43:45 2019 -0500
+++ b/usr/src/cmd/idmap/test-getdc/getdc_main.c	Fri Apr 19 12:08:05 2019 -0400
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  */
 
 
@@ -23,6 +23,7 @@
 
 int debug;
 char *domainname = NULL;
+char *sitename = NULL;
 
 void print_ds(ad_disc_ds_t *);
 void mylogger(int pri, const char *format, ...);
@@ -48,7 +49,9 @@
 	}
 
 	if (optind < argc)
-		domainname = argv[optind];
+		domainname = argv[optind++];
+	if (optind < argc)
+		sitename = argv[optind++];
 
 	adutils_set_logger(mylogger);
 	adutils_set_debug(AD_DEBUG_ALL, debug);
@@ -58,6 +61,8 @@
 
 	if (domainname)
 		(void) ad_disc_set_DomainName(ad_ctx, domainname);
+	if (sitename)
+		(void) ad_disc_set_SiteName(ad_ctx, sitename);
 
 	ad_disc_refresh(ad_ctx);
 
--- a/usr/src/lib/libadutils/common/addisc.c	Thu Feb 07 16:43:45 2019 -0500
+++ b/usr/src/lib/libadutils/common/addisc.c	Fri Apr 19 12:08:05 2019 -0400
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -157,7 +157,7 @@
 #define	is_fixed(item)					\
 	((item)->state == AD_STATE_FIXED)
 
-#define	is_changed(item, num, param) 			\
+#define	is_changed(item, num, param)			\
 	((item)->param_version[num] != (param)->version)
 
 void * uuid_dup(void *);
@@ -641,13 +641,13 @@
 LDAP *
 ldap_lookup_init(ad_disc_ds_t *ds)
 {
-	int 	i;
+	int	i;
 	int	rc, ldversion;
 	int	zero = 0;
-	int 	timeoutms = 5 * 1000;
-	char 	*saslmech = "GSSAPI";
+	int	timeoutms = 5 * 1000;
+	char	*saslmech = "GSSAPI";
 	uint32_t saslflags = LDAP_SASL_INTERACTIVE;
-	LDAP 	*ld = NULL;
+	LDAP	*ld = NULL;
 
 	for (i = 0; ds[i].host[0] != '\0'; i++) {
 		if (DBG(LDAP, 2)) {
@@ -861,7 +861,7 @@
 		struct berval	**sid_ber;
 		adutils_sid_t	sid;
 		char		*sid_str;
-		char 		*name;
+		char		*name;
 		char		*dn;
 
 		sid_ber = ldap_get_values_len(*ld, entry,
@@ -1222,8 +1222,10 @@
 		return (&ctx->domain_controller);
 
 	domain_name_item = validate_DomainName(ctx);
-	if (domain_name_item == NULL)
+	if (domain_name_item == NULL) {
+		DEBUG1STATUS(ctx, "(no domain name)");
 		return (NULL);
+	}
 	domain_name = (char *)domain_name_item->value;
 
 	/* Get (optional) preferred DC. */
@@ -1236,10 +1238,74 @@
 	else {
 		if (is_fixed(&ctx->site_name))
 			validate_site = B_TRUE;
-		else if (req == AD_DISC_PREFER_SITE)
+		if (req == AD_DISC_PREFER_SITE)
 			validate_global = B_TRUE;
 	}
 
+	/*
+	 * If we're trying both site-specific and global,
+	 * try the site-specific first, then fall-back.
+	 */
+	if (validate_site) {
+		site_name_item = &ctx->site_name;
+		site_name = (char *)site_name_item->value;
+
+		if (!is_valid(&ctx->site_domain_controller) ||
+		    is_changed(&ctx->site_domain_controller, PARAM1,
+		    domain_name_item) ||
+		    is_changed(&ctx->site_domain_controller, PARAM2,
+		    site_name_item)) {
+			char rr_name[DNS_MAX_NAME];
+
+			/*
+			 * Lookup DNS SRV RR named
+			 * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
+			 */
+			DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
+			    domain_name, site_name);
+			(void) snprintf(rr_name, sizeof (rr_name),
+			    LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
+			    site_name);
+			DO_RES_NINIT(ctx);
+			cdc = srv_query(&ctx->res_state, rr_name,
+			    domain_name, prefer_dc);
+
+			if (cdc == NULL) {
+				DEBUG1STATUS(ctx, "(no DNS response)");
+				goto try_global;
+			}
+			log_cds(ctx, cdc);
+
+			/*
+			 * Filter out unresponsive servers, and
+			 * save the domain info we get back.
+			 */
+			dc = ldap_ping(
+			    ctx,
+			    cdc,
+			    domain_name,
+			    DS_DS_FLAG);
+			srv_free(cdc);
+			cdc = NULL;
+
+			if (dc == NULL) {
+				DEBUG1STATUS(ctx, "(no LDAP response)");
+				goto try_global;
+			}
+			log_ds(ctx, dc);
+
+			update_item(&ctx->site_domain_controller, dc,
+			    AD_STATE_AUTO, dc->ttl);
+			update_version(&ctx->site_domain_controller, PARAM1,
+			    domain_name_item);
+			update_version(&ctx->site_domain_controller, PARAM2,
+			    site_name_item);
+		}
+		return (&ctx->site_domain_controller);
+	}
+
+try_global:
+
 	if (validate_global) {
 		if (!is_valid(&ctx->domain_controller) ||
 		    is_changed(&ctx->domain_controller, PARAM1,
@@ -1288,63 +1354,6 @@
 		return (&ctx->domain_controller);
 	}
 
-	if (validate_site) {
-		site_name_item = &ctx->site_name;
-		site_name = (char *)site_name_item->value;
-
-		if (!is_valid(&ctx->site_domain_controller) ||
-		    is_changed(&ctx->site_domain_controller, PARAM1,
-		    domain_name_item) ||
-		    is_changed(&ctx->site_domain_controller, PARAM2,
-		    site_name_item)) {
-			char rr_name[DNS_MAX_NAME];
-
-			/*
-			 * Lookup DNS SRV RR named
-			 * _ldap._tcp.<SiteName>._sites.dc._msdcs.<DomainName>
-			 */
-			DEBUG1STATUS(ctx, "DNS SRV query, dom=%s, site=%s",
-			    domain_name, site_name);
-			(void) snprintf(rr_name, sizeof (rr_name),
-			    LDAP_SRV_HEAD SITE_SRV_MIDDLE DC_SRV_TAIL,
-			    site_name);
-			DO_RES_NINIT(ctx);
-			cdc = srv_query(&ctx->res_state, rr_name,
-			    domain_name, prefer_dc);
-
-			if (cdc == NULL) {
-				DEBUG1STATUS(ctx, "(no DNS response)");
-				return (NULL);
-			}
-			log_cds(ctx, cdc);
-
-			/*
-			 * Filter out unresponsive servers, and
-			 * save the domain info we get back.
-			 */
-			dc = ldap_ping(
-			    ctx,
-			    cdc,
-			    domain_name,
-			    DS_DS_FLAG);
-			srv_free(cdc);
-			cdc = NULL;
-
-			if (dc == NULL) {
-				DEBUG1STATUS(ctx, "(no LDAP response)");
-				return (NULL);
-			}
-			log_ds(ctx, dc);
-
-			update_item(&ctx->site_domain_controller, dc,
-			    AD_STATE_AUTO, dc->ttl);
-			update_version(&ctx->site_domain_controller, PARAM1,
-			    domain_name_item);
-			update_version(&ctx->site_domain_controller, PARAM2,
-			    site_name_item);
-		}
-		return (&ctx->site_domain_controller);
-	}
 	return (NULL);
 }
 
@@ -1516,8 +1525,10 @@
 		return (&ctx->global_catalog);
 
 	forest_name_item = validate_ForestName(ctx);
-	if (forest_name_item == NULL)
+	if (forest_name_item == NULL) {
+		DEBUG1STATUS(ctx, "(no forrest name)");
 		return (NULL);
+	}
 	forest_name = (char *)forest_name_item->value;
 
 	if (req == AD_DISC_GLOBAL)
@@ -1525,10 +1536,94 @@
 	else {
 		if (is_fixed(&ctx->site_name))
 			validate_site = B_TRUE;
-		else if (req == AD_DISC_PREFER_SITE)
+		if (req == AD_DISC_PREFER_SITE)
 			validate_global = B_TRUE;
 	}
 
+	/*
+	 * If we're trying both site-specific and global,
+	 * try the site-specific first, then fall-back.
+	 */
+	if (validate_site) {
+		site_name_item = &ctx->site_name;
+		site_name = (char *)site_name_item->value;
+
+		if (!is_valid(&ctx->site_global_catalog) ||
+		    is_changed(&ctx->site_global_catalog, PARAM1,
+		    forest_name_item) ||
+		    is_changed(&ctx->site_global_catalog, PARAM2,
+		    site_name_item)) {
+			char rr_name[DNS_MAX_NAME];
+
+			/*
+			 * See if our DC is also a GC.
+			 */
+			dc_item = validate_DomainController(ctx, req);
+			if (dc_item != NULL) {
+				ad_disc_ds_t *ds = dc_item->value;
+				if ((ds->flags & DS_GC_FLAG) != 0) {
+					DEBUG1STATUS(ctx,
+					    "DC is also a GC for %s in %s",
+					    forest_name, site_name);
+					gc = ds_dup(ds);
+					if (gc != NULL) {
+						gc->port = GC_PORT;
+						goto update_site;
+					}
+				}
+			}
+
+			/*
+			 * Lookup DNS SRV RR named:
+			 * _ldap._tcp.<siteName>._sites.gc.
+			 *	_msdcs.<ForestName>
+			 */
+			DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
+			    forest_name, site_name);
+			(void) snprintf(rr_name, sizeof (rr_name),
+			    LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
+			    site_name);
+			DO_RES_NINIT(ctx);
+			cgc = srv_query(&ctx->res_state, rr_name,
+			    forest_name, NULL);
+
+			if (cgc == NULL) {
+				DEBUG1STATUS(ctx, "(no DNS response)");
+				goto try_global;
+			}
+			log_cds(ctx, cgc);
+
+			/*
+			 * Filter out unresponsive servers, and
+			 * save the domain info we get back.
+			 */
+			gc = ldap_ping(
+			    NULL,
+			    cgc,
+			    forest_name,
+			    DS_GC_FLAG);
+			srv_free(cgc);
+			cgc = NULL;
+
+			if (gc == NULL) {
+				DEBUG1STATUS(ctx, "(no LDAP response)");
+				goto try_global;
+			}
+			log_ds(ctx, gc);
+
+		update_site:
+			update_item(&ctx->site_global_catalog, gc,
+			    AD_STATE_AUTO, gc->ttl);
+			update_version(&ctx->site_global_catalog, PARAM1,
+			    forest_name_item);
+			update_version(&ctx->site_global_catalog, PARAM2,
+			    site_name_item);
+		}
+		return (&ctx->site_global_catalog);
+	}
+
+try_global:
+
 	if (validate_global) {
 		if (!is_valid(&ctx->global_catalog) ||
 		    is_changed(&ctx->global_catalog, PARAM1,
@@ -1595,84 +1690,6 @@
 		}
 		return (&ctx->global_catalog);
 	}
-
-	if (validate_site) {
-		site_name_item = &ctx->site_name;
-		site_name = (char *)site_name_item->value;
-
-		if (!is_valid(&ctx->site_global_catalog) ||
-		    is_changed(&ctx->site_global_catalog, PARAM1,
-		    forest_name_item) ||
-		    is_changed(&ctx->site_global_catalog, PARAM2,
-		    site_name_item)) {
-			char rr_name[DNS_MAX_NAME];
-
-			/*
-			 * See if our DC is also a GC.
-			 */
-			dc_item = validate_DomainController(ctx, req);
-			if (dc_item != NULL) {
-				ad_disc_ds_t *ds = dc_item->value;
-				if ((ds->flags & DS_GC_FLAG) != 0) {
-					DEBUG1STATUS(ctx,
-					    "DC is also a GC for %s in %s",
-					    forest_name, site_name);
-					gc = ds_dup(ds);
-					if (gc != NULL) {
-						gc->port = GC_PORT;
-						goto update_site;
-					}
-				}
-			}
-
-			/*
-			 * Lookup DNS SRV RR named:
-			 * _ldap._tcp.<siteName>._sites.gc.
-			 *	_msdcs.<ForestName>
-			 */
-			DEBUG1STATUS(ctx, "DNS SRV query, forest=%s, site=%s",
-			    forest_name, site_name);
-			(void) snprintf(rr_name, sizeof (rr_name),
-			    LDAP_SRV_HEAD SITE_SRV_MIDDLE GC_SRV_TAIL,
-			    site_name);
-			DO_RES_NINIT(ctx);
-			cgc = srv_query(&ctx->res_state, rr_name,
-			    forest_name, NULL);
-
-			if (cgc == NULL) {
-				DEBUG1STATUS(ctx, "(no DNS response)");
-				return (NULL);
-			}
-			log_cds(ctx, cgc);
-
-			/*
-			 * Filter out unresponsive servers, and
-			 * save the domain info we get back.
-			 */
-			gc = ldap_ping(
-			    NULL,
-			    cgc,
-			    forest_name,
-			    DS_GC_FLAG);
-			srv_free(cgc);
-			cgc = NULL;
-
-			if (gc == NULL) {
-				DEBUG1STATUS(ctx, "(no LDAP response)");
-				return (NULL);
-			}
-			log_ds(ctx, gc);
-
-		update_site:
-			update_item(&ctx->site_global_catalog, gc,
-			    AD_STATE_AUTO, gc->ttl);
-			update_version(&ctx->site_global_catalog, PARAM1,
-			    forest_name_item);
-			update_version(&ctx->site_global_catalog, PARAM2,
-			    site_name_item);
-		}
-		return (&ctx->site_global_catalog);
-	}
 	return (NULL);
 }