[SCM] Samba Shared Repository - branch v3-3-test updated - release-3-2-0pre2-3038-gf4c37db

Gerald Carter jerry at samba.org
Fri Jun 27 14:26:47 GMT 2008


The branch, v3-3-test has been updated
       via  f4c37dbe2c986fb7bfe510cdff3b4a9fbc06d079 (commit)
      from  30d181c92463aecd6e649330d3645d86d5a17e43 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-3-test


- Log -----------------------------------------------------------------
commit f4c37dbe2c986fb7bfe510cdff3b4a9fbc06d079
Author: Gerald W. Carter <jerry at samba.org>
Date:   Fri Jun 27 10:22:39 2008 -0400

    libads: Add API call to connect to a global catalog server.
    
    Extends ads_connect() to a new call ads_connect_gc() which connects on port
    3268 rather than port 389.  Also makes ads_try_connect() static and
    only used internally to ldap.c

-----------------------------------------------------------------------

Summary of changes:
 source/include/ads.h          |    4 +-
 source/include/proto.h        |    1 -
 source/include/smb.h          |    1 +
 source/libads/ldap.c          |  145 +++++++++++++++++++++++++++++++++++++++--
 source/winbindd/winbindd_cm.c |    6 +-
 5 files changed, 148 insertions(+), 9 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/include/ads.h b/source/include/ads.h
index d455176..0d464b2 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -53,7 +53,9 @@ typedef struct ads_struct {
 		char *realm;
 		char *workgroup;
 		char *ldap_server;
-		int foreign; /* set to 1 if connecting to a foreign realm */
+		int foreign; /* set to 1 if connecting to a foreign
+			      * realm */
+		bool gc;     /* Is this a global catalog server? */
 	} server;
 
 	/* info needed to authenticate */
diff --git a/source/include/proto.h b/source/include/proto.h
index 6cef348..81cf2db 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -2063,7 +2063,6 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
 
 bool ads_sitename_match(ADS_STRUCT *ads);
 bool ads_closest_dc(ADS_STRUCT *ads);
-bool ads_try_connect(ADS_STRUCT *ads, const char *server );
 ADS_STATUS ads_connect(ADS_STRUCT *ads);
 ADS_STATUS ads_connect_user_creds(ADS_STRUCT *ads);
 void ads_disconnect(ADS_STRUCT *ads);
diff --git a/source/include/smb.h b/source/include/smb.h
index 7ae66f1..7fcae51 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1847,6 +1847,7 @@ typedef struct _smb_iconv_t {
 #ifndef LDAP_PORT
 #define LDAP_PORT	389
 #endif
+#define LDAP_GC_PORT    3268
 
 /* used by the IP comparison function */
 struct ip_service {
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index 7c64082..b59dab1 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -173,7 +173,7 @@ bool ads_closest_dc(ADS_STRUCT *ads)
   try a connection to a given ldap server, returning True and setting the servers IP
   in the ads struct if successful
  */
-bool ads_try_connect(ADS_STRUCT *ads, const char *server )
+static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
 {
 	char *srv;
 	struct nbt_cldap_netlogon_5 cldap_reply;
@@ -238,7 +238,7 @@ bool ads_try_connect(ADS_STRUCT *ads, const char *server )
 	}
 	ads->server.workgroup          = SMB_STRDUP(cldap_reply.domain);
 
-	ads->ldap.port = LDAP_PORT;
+	ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
 	if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
 		DEBUG(1,("ads_try_connect: unable to convert %s "
 			"to an address\n",
@@ -358,7 +358,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 			}
 		}
 
-		if ( ads_try_connect(ads, server) ) {
+		if ( ads_try_connect(ads, server, false) ) {
 			SAFE_FREE(ip_list);
 			SAFE_FREE(sitename);
 			return NT_STATUS_OK;
@@ -385,6 +385,141 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 	return NT_STATUS_NO_LOGON_SERVERS;
 }
 
+/*********************************************************************
+ *********************************************************************/
+
+static NTSTATUS ads_lookup_site(void)
+{
+	ADS_STRUCT *ads = NULL;
+	ADS_STATUS ads_status;
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	struct nbt_cldap_netlogon_5 cldap_reply;
+
+	ZERO_STRUCT(cldap_reply);
+
+	ads = ads_init(lp_realm(), NULL, NULL);
+	if (!ads) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/* The NO_BIND here will find a DC and set the client site
+	   but not establish the TCP connection */
+
+	ads->auth.flags = ADS_AUTH_NO_BIND;
+	ads_status = ads_connect(ads);
+	if (!ADS_ERR_OK(ads_status)) {
+		DEBUG(4, ("ads_lookup_site: ads_connect to our realm failed! (%s)\n",
+			  ads_errstr(ads_status)));
+	}
+	nt_status = ads_ntstatus(ads_status);
+
+	if (ads) {
+		ads_destroy(&ads);
+	}
+
+	return nt_status;
+}
+
+/*********************************************************************
+ *********************************************************************/
+
+static const char* host_dns_domain(const char *fqdn)
+{
+	const char *p = fqdn;
+
+	/* go to next char following '.' */
+
+	if ((p = strchr_m(fqdn, '.')) != NULL) {
+		p++;
+	}
+
+	return p;
+}
+
+
+/**
+ * Connect to the Global Catalog server
+ * @param ads Pointer to an existing ADS_STRUCT
+ * @return status of connection
+ *
+ * Simple wrapper around ads_connect() that fills in the
+ * GC ldap server information
+ **/
+
+ADS_STATUS ads_connect_gc(ADS_STRUCT *ads)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct dns_rr_srv *gcs_list;
+	int num_gcs;
+	char *realm = ads->server.realm;
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+	ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+	int i;
+	bool done = false;
+	char *sitename = NULL;
+
+	if (!realm)
+		realm = lp_realm();
+
+	if ((sitename = sitename_fetch(realm)) == NULL) {
+		ads_lookup_site();
+		sitename = sitename_fetch(realm);
+	}
+
+	do {
+		/* We try once with a sitename and once without
+		   (unless we don't have a sitename and then we're
+		   done */
+
+		if (sitename == NULL)
+			done = true;
+
+		nt_status = ads_dns_query_gcs(frame, realm, sitename,
+					      &gcs_list, &num_gcs);
+
+		SAFE_FREE(sitename);
+
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			ads_status = ADS_ERROR_NT(nt_status);
+			goto done;
+		}
+
+		/* Loop until we get a successful connection or have gone
+		   through them all.  When connecting a GC server, make sure that
+		   the realm is the server's DNS name and not the forest root */
+
+		for (i=0; i<num_gcs; i++) {
+			ads->server.gc = true;
+			ads->server.ldap_server = SMB_STRDUP(gcs_list[i].hostname);
+			ads->server.realm = SMB_STRDUP(host_dns_domain(ads->server.ldap_server));
+			ads_status = ads_connect(ads);
+			if (ADS_ERR_OK(ads_status)) {
+				/* Reset the bind_dn to "".  A Global Catalog server
+				   may host  multiple domain trees in a forest.
+				   Windows 2003 GC server will accept "" as the search
+				   path to imply search all domain trees in the forest */
+
+				SAFE_FREE(ads->config.bind_path);
+				ads->config.bind_path = SMB_STRDUP("");
+
+
+				goto done;
+			}
+			SAFE_FREE(ads->server.ldap_server);
+			SAFE_FREE(ads->server.realm);
+		}
+
+	        TALLOC_FREE(gcs_list);
+		num_gcs = 0;
+	} while (!done);
+
+done:
+	SAFE_FREE(sitename);
+	talloc_destroy(frame);
+
+	return ads_status;
+}
+
 
 /**
  * Connect to the LDAP server
@@ -412,7 +547,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
 	}
 
 	if (ads->server.ldap_server &&
-	    ads_try_connect(ads, ads->server.ldap_server)) {
+	    ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) {
 		goto got_connection;
 	}
 
@@ -472,7 +607,7 @@ got_connection:
 	/* Otherwise setup the TCP LDAP session */
 
 	ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
-					      LDAP_PORT, lp_ldap_timeout());
+					      ads->ldap.port, lp_ldap_timeout());
 	if (ads->ldap.ld == NULL) {
 		status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
 		goto out;
diff --git a/source/winbindd/winbindd_cm.c b/source/winbindd/winbindd_cm.c
index 1f1544e..51ef14b 100644
--- a/source/winbindd/winbindd_cm.c
+++ b/source/winbindd/winbindd_cm.c
@@ -1043,14 +1043,16 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
 
 	if (lp_security() == SEC_ADS) {
 		ADS_STRUCT *ads;
+		ADS_STATUS ads_status;
 		char addr[INET6_ADDRSTRLEN];
 
 		print_sockaddr(addr, sizeof(addr), pss);
 
-		ads = ads_init(domain->alt_name, domain->name, NULL);
+		ads = ads_init(domain->alt_name, domain->name, addr);
 		ads->auth.flags |= ADS_AUTH_NO_BIND;
 
-		if (ads_try_connect(ads, addr)) {
+		ads_status = ads_connect(ads);
+		if (ADS_ERR_OK(ads_status)) {
 			/* We got a cldap packet. */
 			fstrcpy(name, ads->config.ldap_server_name);
 			namecache_store(name, 0x20, 1, &ip_list);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list