svn commit: samba r18006 - in branches/SAMBA_3_0/source: include libads libsmb

jra at samba.org jra at samba.org
Sat Sep 2 19:27:45 GMT 2006


Author: jra
Date: 2006-09-02 19:27:44 +0000 (Sat, 02 Sep 2006)
New Revision: 18006

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=18006

Log:
Actually a smaller change than it looks. Leverage
the get_dc_list code to get the _kerberos. names
for site support. This way we don't depend on one
KDC to do ticket refresh. Even though we know it's
up when we add it, it may go down when we're trying
to refresh.
Jeremy.

Modified:
   branches/SAMBA_3_0/source/include/smb.h
   branches/SAMBA_3_0/source/libads/dns.c
   branches/SAMBA_3_0/source/libads/kerberos.c
   branches/SAMBA_3_0/source/libsmb/namecache.c
   branches/SAMBA_3_0/source/libsmb/namequery.c


Changeset:
Modified: branches/SAMBA_3_0/source/include/smb.h
===================================================================
--- branches/SAMBA_3_0/source/include/smb.h	2006-09-02 19:18:49 UTC (rev 18005)
+++ branches/SAMBA_3_0/source/include/smb.h	2006-09-02 19:27:44 UTC (rev 18006)
@@ -1789,6 +1789,9 @@
 	unsigned port;
 };
 
+/* Special name type used to cause a _kerberos DNS lookup. */
+#define KDC_NAME_TYPE 0xDCDC
+
 /* Used by the SMB signing functions. */
 
 typedef struct smb_sign_info {

Modified: branches/SAMBA_3_0/source/libads/dns.c
===================================================================
--- branches/SAMBA_3_0/source/libads/dns.c	2006-09-02 19:18:49 UTC (rev 18005)
+++ branches/SAMBA_3_0/source/libads/dns.c	2006-09-02 19:27:44 UTC (rev 18006)
@@ -649,18 +649,20 @@
  Query with optional sitename.
 ********************************************************************/
 
-NTSTATUS ads_dns_query_dcs_internal(TALLOC_CTX *ctx,
-				const char *domain,
+NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
+				const char *servicename,
+				const char *realm,
 				const char *sitename,
 				struct dns_rr_srv **dclist,
 				int *numdcs )
 {
 	char *name;
 	if (sitename) {
-		name = talloc_asprintf(ctx, "_ldap._tcp.%s._sites.dc._msdcs.%s",
-				sitename, domain );
+		name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
+				servicename, sitename, realm );
 	} else {
-		name = talloc_asprintf(ctx, "_ldap._tcp.dc._msdcs.%s", domain );
+		name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
+				servicename, realm );
 	}
 	if (!name) {
 		return NT_STATUS_NO_MEMORY;
@@ -673,18 +675,45 @@
 ********************************************************************/
 
 NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
-			const char *domain,
+			const char *realm,
 			struct dns_rr_srv **dclist,
 			int *numdcs )
 {
 	NTSTATUS status;
 	char *sitename = sitename_fetch();
 
-	status = ads_dns_query_dcs_internal(ctx, domain, sitename, dclist, numdcs);
+	status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
+					dclist, numdcs);
 	if (sitename && !NT_STATUS_IS_OK(status)) {
 		/* Sitename DNS query may have failed. Try without. */
-		status = ads_dns_query_dcs_internal(ctx, domain, NULL, dclist, numdcs);
+		status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
+						dclist, numdcs);
 	}
 	SAFE_FREE(sitename);
 	return status;
 }
+
+/********************************************************************
+ Query for AD KDC's. Transparently use sitename.
+ Even if our underlying kerberos libraries are UDP only, this
+ is pretty safe as it's unlikely that a KDC supports TCP and not UDP.
+********************************************************************/
+
+NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx,
+			const char *realm,
+			struct dns_rr_srv **dclist,
+			int *numdcs )
+{
+	NTSTATUS status;
+	char *sitename = sitename_fetch();
+
+	status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
+					dclist, numdcs);
+	if (sitename && !NT_STATUS_IS_OK(status)) {
+		/* Sitename DNS query may have failed. Try without. */
+		status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
+						dclist, numdcs);
+	}
+	SAFE_FREE(sitename);
+	return status;
+}

Modified: branches/SAMBA_3_0/source/libads/kerberos.c
===================================================================
--- branches/SAMBA_3_0/source/libads/kerberos.c	2006-09-02 19:18:49 UTC (rev 18005)
+++ branches/SAMBA_3_0/source/libads/kerberos.c	2006-09-02 19:27:44 UTC (rev 18006)
@@ -465,6 +465,46 @@
 }
 
 /************************************************************************
+ Create a string list of available kdc's, possibly searching by sitename.
+ Does DNS queries.
+************************************************************************/
+
+static char *get_kdc_ip_string(char *mem_ctx, const char *realm, struct in_addr primary_ip)
+{
+	struct ip_service *ip_srv;
+	int count, i;
+	char *kdc_str = talloc_asprintf(mem_ctx, "\tkdc = %s\n",
+					inet_ntoa(primary_ip));
+
+	if (kdc_str == NULL) {
+		return NULL;
+	}
+
+	if (!NT_STATUS_IS_OK(get_kdc_list(realm, &ip_srv, &count))) {
+		DEBUG(10,("get_kdc_ip_string: get_kdc_list failed. Returning %s\n",
+			kdc_str ));
+		return kdc_str;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (ip_equal(ip_srv[i].ip, primary_ip)) {
+			continue;
+		}
+		/* Append to the string - inefficient but not done often. */
+		kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
+			kdc_str, inet_ntoa(ip_srv[i].ip));
+		if (!kdc_str) {
+			return NULL;
+		}
+	}
+
+	DEBUG(10,("get_kdc_ip_string: Returning %s\n",
+		kdc_str ));
+
+	return kdc_str;
+}
+
+/************************************************************************
  Create  a specific krb5.conf file in the private directory pointing
  at a specific kdc for a realm. Keyed off domain name. Sets
  KRB5_CONFIG environment variable to point to this file. Must be
@@ -477,6 +517,7 @@
 	char *dname = talloc_asprintf(NULL, "%s/smb_krb5", lp_lockdir());
 	char *fname = NULL;
 	char *file_contents = NULL;
+	char *kdc_ip_string;
 	size_t flen = 0;
 	size_t ret;
 	char *realm_upper = NULL;
@@ -505,10 +546,16 @@
 	realm_upper = talloc_strdup(fname, realm);
 	strupper_m(realm_upper);
 
+	kdc_ip_string = get_kdc_ip_string(dname, realm, ip);
+	if (!kdc_ip_string) {
+		TALLOC_FREE(dname);
+		return False;
+	}
+		
 	file_contents = talloc_asprintf(fname, "[libdefaults]\n\tdefault_realm = %s\n\n"
 				"[realms]\n\t%s = {\n"
-				"\t\tkdc = %s\n\t}\n",
-				realm_upper, realm_upper, inet_ntoa(ip));
+				"\t\t%s\t}\n",
+				realm_upper, realm_upper, kdc_ip_string);
 
 	if (!file_contents) {
 		TALLOC_FREE(dname);

Modified: branches/SAMBA_3_0/source/libsmb/namecache.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/namecache.c	2006-09-02 19:18:49 UTC (rev 18005)
+++ branches/SAMBA_3_0/source/libsmb/namecache.c	2006-09-02 19:27:44 UTC (rev 18006)
@@ -126,6 +126,10 @@
 	 */
 	if (!gencache_init()) return False;
 
+	if (name_type > 255) {
+		return False; /* Don't store non-real name types. */
+	}
+
 	if ( DEBUGLEVEL >= 5 ) {
 		DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
 			num_names, num_names == 1 ? "": "es", name, name_type));
@@ -184,6 +188,10 @@
 	if (!gencache_init())
 		return False;
 
+	if (name_type > 255) {
+		return False; /* Don't fetch non-real name types. */
+	}
+
 	*num_names = 0;
 
 	/* 

Modified: branches/SAMBA_3_0/source/libsmb/namequery.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/namequery.c	2006-09-02 19:18:49 UTC (rev 18005)
+++ branches/SAMBA_3_0/source/libsmb/namequery.c	2006-09-02 19:27:44 UTC (rev 18006)
@@ -1030,7 +1030,7 @@
 	int			numdcs = 0;
 	int			numaddrs = 0;
 
-	if ( name_type != 0x1c )
+	if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
 		return False;
 		
 	DEBUG(5,("resolve_hosts: Attempting to resolve DC's for %s using DNS\n",
@@ -1040,8 +1040,12 @@
 		DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
 		return False;
 	}
-		
-	status = ads_dns_query_dcs( ctx, name, &dcs, &numdcs );
+
+	if (name_type == KDC_NAME_TYPE) {
+		status = ads_dns_query_kdcs(ctx, name, &dcs, &numdcs);
+	} else {
+		status = ads_dns_query_dcs(ctx, name, &dcs, &numdcs);
+	}
 	if ( !NT_STATUS_IS_OK( status ) ) {
 		talloc_destroy(ctx);
 		return False;
@@ -1188,6 +1192,13 @@
 				result = True;
 				goto done;
 			}
+		} else if(strequal( tok, "kdc")) {
+			/* deal with KDC_NAME_TYPE names here.  This will result in a
+				SRV record lookup */
+			if (resolve_ads(name, KDC_NAME_TYPE, return_iplist, return_count)) {
+				result = True;
+				goto done;
+			}
 		} else if(strequal( tok, "ads")) {
 			/* deal with 0x1c names here.  This will result in a
 				SRV record lookup */
@@ -1355,13 +1366,17 @@
 	return True;
 }
 
+/* Private enum type for lookups. */
+
+enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
+
 /********************************************************
  Get the IP address list of the domain controllers for
  a domain.
 *********************************************************/
 
 static NTSTATUS get_dc_list(const char *domain, struct ip_service **ip_list, 
-                            int *count, BOOL ads_only, int *ordered)
+                            int *count, enum dc_lookup_type lookup_type, int *ordered)
 {
 	fstring resolve_order;
 	char *saf_servername;
@@ -1387,7 +1402,7 @@
 
 	fstrcpy( resolve_order, lp_name_resolve_order() );
 	strlower_m( resolve_order );
-	if ( ads_only )  {
+	if ( lookup_type == DC_ADS_ONLY)  {
 		if ( strstr( resolve_order, "host" ) ) {
 			fstrcpy( resolve_order, "ads" );
 
@@ -1397,6 +1412,11 @@
 		} else {
                         fstrcpy( resolve_order, "NULL" );
 		}
+	} else if (lookup_type == DC_KDC_ONLY) {
+		/* DNS SRV lookups used by the ads/kdc resolver
+		   are already sorted by priority and weight */
+		*ordered = True;
+		fstrcpy( resolve_order, "kdc" );
 	}
 
 	/* fetch the server we have affinity for.  Add the 
@@ -1558,11 +1578,16 @@
 {
 	BOOL ordered;
 	NTSTATUS status;
-	
+	enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
+
 	DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
 		(ads_only ? "ads" : lp_name_resolve_order())));
 	
-	status = get_dc_list(domain, ip_list, count, ads_only, &ordered);
+	if (ads_only) {
+		lookup_type = DC_ADS_ONLY;
+	}
+
+	status = get_dc_list(domain, ip_list, count, lookup_type, &ordered);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status; 
 	}
@@ -1574,3 +1599,29 @@
 		
 	return NT_STATUS_OK;
 }
+
+/*********************************************************************
+ Get the KDC list - re-use all the logic in get_dc_list.
+*********************************************************************/
+
+NTSTATUS get_kdc_list( const char *realm, struct ip_service **ip_list, int *count)
+{
+	BOOL ordered;
+	NTSTATUS status;
+
+	*count = 0;
+	*ip_list = NULL;
+
+	status = get_dc_list(realm, ip_list, count, DC_KDC_ONLY, &ordered);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		return status; 
+	}
+
+	/* only sort if we don't already have an ordered list */
+	if ( !ordered ) {
+		sort_ip_list2( *ip_list, *count );
+	}
+
+	return NT_STATUS_OK;
+}



More information about the samba-cvs mailing list