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 <[EMAIL PROTECTED]>
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

Reply via email to