Author: gd
Date: 2007-08-28 14:27:48 +0000 (Tue, 28 Aug 2007)
New Revision: 24739

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

Log:
With resolve_ads() allow to query for PDCs as well.
Also add dns query functions to find GCs and DCs by GUID.

Guenther

Modified:
   branches/SAMBA_3_2/source/libads/dns.c
   branches/SAMBA_3_2/source/libsmb/namequery.c
   branches/SAMBA_3_2_0/source/libads/dns.c
   branches/SAMBA_3_2_0/source/libsmb/namequery.c


Changeset:
Modified: branches/SAMBA_3_2/source/libads/dns.c
===================================================================
--- branches/SAMBA_3_2/source/libads/dns.c      2007-08-28 14:25:46 UTC (rev 
24738)
+++ branches/SAMBA_3_2/source/libads/dns.c      2007-08-28 14:27:48 UTC (rev 
24739)
@@ -740,21 +740,23 @@
  Query with optional sitename.
 ********************************************************************/
 
-NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
-                               const char *servicename,
-                               const char *realm,
-                               const char *sitename,
-                               struct dns_rr_srv **dclist,
-                               int *numdcs )
+static NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
+                                      const char *servicename,
+                                      const char *dc_pdc_gc_domains,
+                                      const char *realm,
+                                      const char *sitename,
+                                      struct dns_rr_srv **dclist,
+                                      int *numdcs )
 {
        char *name;
        if (sitename) {
-               name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
-                               servicename, sitename, realm );
-       } else {
-               name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
-                               servicename, realm );
-       }
+               name = talloc_asprintf(ctx, "%s._tcp.%s._sites.%s._msdcs.%s",
+                                      servicename, sitename,
+                                      dc_pdc_gc_domains, realm);
+       } else {
+               name = talloc_asprintf(ctx, "%s._tcp.%s._msdcs.%s",
+                               servicename, dc_pdc_gc_domains, realm);
+       }
        if (!name) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -766,14 +768,14 @@
 ********************************************************************/
 
 NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
-                       const char *realm,
-                       const char *sitename,
-                       struct dns_rr_srv **dclist,
-                       int *numdcs )
+                          const char *realm,
+                          const char *sitename,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
 {
        NTSTATUS status;
 
-       status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
+       status = ads_dns_query_internal(ctx, "_ldap", "dc", realm, sitename,
                                        dclist, numdcs);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
@@ -781,40 +783,119 @@
                return status;
        }
 
-       if (sitename && !NT_STATUS_IS_OK(status)) {
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
                /* Sitename DNS query may have failed. Try without. */
-               status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
-                                               dclist, numdcs);
+               status = ads_dns_query_internal(ctx, "_ldap", "dc", realm,
+                                               NULL, dclist, numdcs);
        }
        return status;
 }
 
 /********************************************************************
+ Query for AD GC's.
+********************************************************************/
+
+NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx,
+                          const char *realm,
+                          const char *sitename,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
+{
+       NTSTATUS status;
+
+       status = ads_dns_query_internal(ctx, "_ldap", "gc", realm, sitename,
+                                       dclist, numdcs);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
+               return status;
+       }
+
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
+               /* Sitename DNS query may have failed. Try without. */
+               status = ads_dns_query_internal(ctx, "_ldap", "gc", realm,
+                                               NULL, dclist, numdcs);
+       }
+       return status;
+}
+
+/********************************************************************
  Query for AD KDC's.
  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,
-                       const char *sitename,
-                       struct dns_rr_srv **dclist,
-                       int *numdcs )
+                           const char *dns_forest_name,
+                           const char *sitename,
+                           struct dns_rr_srv **dclist,
+                           int *numdcs )
 {
        NTSTATUS status;
 
-       status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
-                                       dclist, numdcs);
+       status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+                                       dns_forest_name, sitename, dclist,
+                                       numdcs);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
            NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
                return status;
        }
 
-       if (sitename && !NT_STATUS_IS_OK(status)) {
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
                /* Sitename DNS query may have failed. Try without. */
-               status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
+               status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+                                               dns_forest_name, NULL,
                                                dclist, numdcs);
        }
        return status;
 }
+
+/********************************************************************
+ Query for AD PDC. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx,
+                          const char *dns_domain_name,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
+{
+       return ads_dns_query_internal(ctx, "_ldap", "pdc", dns_domain_name,
+                                     NULL, dclist, numdcs);
+}
+
+/********************************************************************
+ Query for AD DC by guid. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx,
+                               const char *dns_forest_name,
+                               const struct GUID *domain_guid,
+                               struct dns_rr_srv **dclist,
+                               int *numdcs )
+{
+       /*_ldap._tcp.DomainGuid.domains._msdcs.DnsForestName */
+
+       const char *domains;
+       const char *guid_string;
+
+       guid_string = GUID_string(ctx, domain_guid);
+       if (!guid_string) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* little hack */
+       domains = talloc_asprintf(ctx, "%s.domains", guid_string);
+       if (!domains) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return ads_dns_query_internal(ctx, "_ldap", domains, dns_forest_name,
+                                     NULL, dclist, numdcs);
+}

Modified: branches/SAMBA_3_2/source/libsmb/namequery.c
===================================================================
--- branches/SAMBA_3_2/source/libsmb/namequery.c        2007-08-28 14:25:46 UTC 
(rev 24738)
+++ branches/SAMBA_3_2/source/libsmb/namequery.c        2007-08-28 14:27:48 UTC 
(rev 24739)
@@ -1059,7 +1059,8 @@
        int                     numdcs = 0;
        int                     numaddrs = 0;
 
-       if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE)) {
+       if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE) &&
+           (name_type != 0x1b)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -1069,6 +1070,12 @@
        }
 
        switch (name_type) {
+               case 0x1b:
+                       DEBUG(5,("resolve_ads: Attempting to resolve "
+                                "PDC for %s using DNS\n", name));
+                       status = ads_dns_query_pdc(ctx, name, &dcs, &numdcs);
+                       break;
+
                case 0x1c:
                        DEBUG(5,("resolve_ads: Attempting to resolve "
                                 "DCs for %s using DNS\n", name));
@@ -1419,13 +1426,20 @@
 
        /* Look up #1B name */
 
-       status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
-                                      &count,
-                                      lp_name_resolve_order());
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
+       if (lp_security() == SEC_ADS) {
+               status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
+                                              &count, "ads");
        }
 
+       if (!NT_STATUS_IS_OK(status) || count == 0) {
+               status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
+                                              &count,
+                                              lp_name_resolve_order());
+               if (!NT_STATUS_IS_OK(status)) {
+                       return False;
+               }
+       }
+
        /* if we get more than 1 IP back we have to assume it is a
           multi-homed PDC and not a mess up */
 

Modified: branches/SAMBA_3_2_0/source/libads/dns.c
===================================================================
--- branches/SAMBA_3_2_0/source/libads/dns.c    2007-08-28 14:25:46 UTC (rev 
24738)
+++ branches/SAMBA_3_2_0/source/libads/dns.c    2007-08-28 14:27:48 UTC (rev 
24739)
@@ -740,21 +740,23 @@
  Query with optional sitename.
 ********************************************************************/
 
-NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
-                               const char *servicename,
-                               const char *realm,
-                               const char *sitename,
-                               struct dns_rr_srv **dclist,
-                               int *numdcs )
+static NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
+                                      const char *servicename,
+                                      const char *dc_pdc_gc_domains,
+                                      const char *realm,
+                                      const char *sitename,
+                                      struct dns_rr_srv **dclist,
+                                      int *numdcs )
 {
        char *name;
        if (sitename) {
-               name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
-                               servicename, sitename, realm );
-       } else {
-               name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
-                               servicename, realm );
-       }
+               name = talloc_asprintf(ctx, "%s._tcp.%s._sites.%s._msdcs.%s",
+                                      servicename, sitename,
+                                      dc_pdc_gc_domains, realm);
+       } else {
+               name = talloc_asprintf(ctx, "%s._tcp.%s._msdcs.%s",
+                               servicename, dc_pdc_gc_domains, realm);
+       }
        if (!name) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -766,14 +768,14 @@
 ********************************************************************/
 
 NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
-                       const char *realm,
-                       const char *sitename,
-                       struct dns_rr_srv **dclist,
-                       int *numdcs )
+                          const char *realm,
+                          const char *sitename,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
 {
        NTSTATUS status;
 
-       status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
+       status = ads_dns_query_internal(ctx, "_ldap", "dc", realm, sitename,
                                        dclist, numdcs);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
@@ -781,40 +783,119 @@
                return status;
        }
 
-       if (sitename && !NT_STATUS_IS_OK(status)) {
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
                /* Sitename DNS query may have failed. Try without. */
-               status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
-                                               dclist, numdcs);
+               status = ads_dns_query_internal(ctx, "_ldap", "dc", realm,
+                                               NULL, dclist, numdcs);
        }
        return status;
 }
 
 /********************************************************************
+ Query for AD GC's.
+********************************************************************/
+
+NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx,
+                          const char *realm,
+                          const char *sitename,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
+{
+       NTSTATUS status;
+
+       status = ads_dns_query_internal(ctx, "_ldap", "gc", realm, sitename,
+                                       dclist, numdcs);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
+               return status;
+       }
+
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
+               /* Sitename DNS query may have failed. Try without. */
+               status = ads_dns_query_internal(ctx, "_ldap", "gc", realm,
+                                               NULL, dclist, numdcs);
+       }
+       return status;
+}
+
+/********************************************************************
  Query for AD KDC's.
  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,
-                       const char *sitename,
-                       struct dns_rr_srv **dclist,
-                       int *numdcs )
+                           const char *dns_forest_name,
+                           const char *sitename,
+                           struct dns_rr_srv **dclist,
+                           int *numdcs )
 {
        NTSTATUS status;
 
-       status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
-                                       dclist, numdcs);
+       status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+                                       dns_forest_name, sitename, dclist,
+                                       numdcs);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
            NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
                return status;
        }
 
-       if (sitename && !NT_STATUS_IS_OK(status)) {
+       if (sitename &&
+           ((!NT_STATUS_IS_OK(status)) ||
+            (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
                /* Sitename DNS query may have failed. Try without. */
-               status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
+               status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+                                               dns_forest_name, NULL,
                                                dclist, numdcs);
        }
        return status;
 }
+
+/********************************************************************
+ Query for AD PDC. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx,
+                          const char *dns_domain_name,
+                          struct dns_rr_srv **dclist,
+                          int *numdcs )
+{
+       return ads_dns_query_internal(ctx, "_ldap", "pdc", dns_domain_name,
+                                     NULL, dclist, numdcs);
+}
+
+/********************************************************************
+ Query for AD DC by guid. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx,
+                               const char *dns_forest_name,
+                               const struct GUID *domain_guid,
+                               struct dns_rr_srv **dclist,
+                               int *numdcs )
+{
+       /*_ldap._tcp.DomainGuid.domains._msdcs.DnsForestName */
+
+       const char *domains;
+       const char *guid_string;
+
+       guid_string = GUID_string(ctx, domain_guid);
+       if (!guid_string) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* little hack */
+       domains = talloc_asprintf(ctx, "%s.domains", guid_string);
+       if (!domains) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return ads_dns_query_internal(ctx, "_ldap", domains, dns_forest_name,
+                                     NULL, dclist, numdcs);
+}

Modified: branches/SAMBA_3_2_0/source/libsmb/namequery.c
===================================================================
--- branches/SAMBA_3_2_0/source/libsmb/namequery.c      2007-08-28 14:25:46 UTC 
(rev 24738)
+++ branches/SAMBA_3_2_0/source/libsmb/namequery.c      2007-08-28 14:27:48 UTC 
(rev 24739)
@@ -1059,7 +1059,8 @@
        int                     numdcs = 0;
        int                     numaddrs = 0;
 
-       if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE)) {
+       if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE) &&
+           (name_type != 0x1b)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -1069,6 +1070,12 @@
        }
 
        switch (name_type) {
+               case 0x1b:
+                       DEBUG(5,("resolve_ads: Attempting to resolve "
+                                "PDC for %s using DNS\n", name));
+                       status = ads_dns_query_pdc(ctx, name, &dcs, &numdcs);
+                       break;
+
                case 0x1c:
                        DEBUG(5,("resolve_ads: Attempting to resolve "
                                 "DCs for %s using DNS\n", name));
@@ -1419,13 +1426,20 @@
 
        /* Look up #1B name */
 
-       status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
-                                      &count,
-                                      lp_name_resolve_order());
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
+       if (lp_security() == SEC_ADS) {
+               status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
+                                              &count, "ads");
        }
 
+       if (!NT_STATUS_IS_OK(status) || count == 0) {
+               status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
+                                              &count,
+                                              lp_name_resolve_order());
+               if (!NT_STATUS_IS_OK(status)) {
+                       return False;
+               }
+       }
+
        /* if we get more than 1 IP back we have to assume it is a
           multi-homed PDC and not a mess up */
 

Reply via email to