summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/dns.c45
-rw-r--r--source3/libads/kerberos.c51
2 files changed, 86 insertions, 10 deletions
diff --git a/source3/libads/dns.c b/source3/libads/dns.c
index 579296ea1f..d5c851d5ca 100644
--- a/source3/libads/dns.c
+++ b/source3/libads/dns.c
@@ -649,18 +649,20 @@ BOOL stored_sitename_changed(const char *sitename)
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,17 +675,44 @@ NTSTATUS ads_dns_query_dcs_internal(TALLOC_CTX *ctx,
********************************************************************/
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;
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 4801aec23e..c872508fe8 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -465,6 +465,46 @@ int kerberos_kinit_password(const char *principal,
}
/************************************************************************
+ 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 @@ BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *do
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 @@ BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *do
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);