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 */