[PATCH 2/4] dns updates: Register name.dnsdomain instead of gethostbyname(name).

James Peach jpeach at apple.com
Fri May 30 17:43:42 GMT 2008


Previously, we would register the fqdn that is returned as an alias
from doing a gethostbyname on our name. This is generally not going
to work since it relies on DNS, which is exactly what we are trying
dynamically configure. So we statically construct a DNS name using
our machine name and the realm -> DNS domain mapping and register
that.
---
  source/configure.in    |    1 +
  source/utils/net_ads.c |  102 +++++++++++++++++++++++++++++++++++++++ 
+-------
  2 files changed, 87 insertions(+), 16 deletions(-)

diff --git a/source/configure.in b/source/configure.in
index 5176dc1..b9d113f 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -3382,6 +3382,7 @@ if test x"$with_ads_support" != x"no"; then
    AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_free, $KRB5_LIBS)
    AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_get_error, $KRB5_LIBS)
    AC_CHECK_FUNC_EXT(krb5_enctype_to_string, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_get_realm_domain, $KRB5_LIBS)

    LIBS="$KRB5_LIBS $LIBS"

diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 96fa6ba..1add13f 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -956,27 +956,62 @@ DNS_ERROR DoDNSUpdate(char *pszServerName,
  		      const struct sockaddr_storage *sslist,
  		      size_t num_addrs );

+/* XXX  The krb5_get_realm_domain symbol is currently a private MIT  
symbol.
+ * We have asked for it to be make public or for an alternative API  
to be
+ * provided.
+ */
+extern krb5_error_code KRB5_CALLCONV krb5_get_realm_domain
+         (krb5_context, const char *, char ** );
+
+#ifndef HAVE_KRB5_GET_REALM_DOMAIN
+extern krb5_error_code KRB5_CALLCONV krb5_get_realm_domain
+         (krb5_context ctx, const char * dns, char ** realm)
+{
+	return KRB5_ERR_HOST_REALM_UNKNOWN;
+}
+#endif
+
+static NTSTATUS map_krb_realm_to_dns_domain(ADS_STRUCT *ads,
+			    char ** dnsdomain)
+{
+	krb5_error_code rc = 0;
+	krb5_context	kctx = 0;
+
+	rc = krb5_init_context(&kctx);
+	if (rc) {
+		DEBUG(1,("krb5_init_context failed (%s)\n",
+			 error_message(rc)));
+		return krb5_to_nt_status(rc);
+	}
+
+	/* Map the KRB5 realm to the DNS domain. */
+	rc = krb5_get_realm_domain(kctx, ads->config.realm, dnsdomain);
+	if (rc) {
+		d_printf("Unable to find DNS domain for the %s realm: %s\n",
+		    ads->config.realm, error_message(rc));
+
+		krb5_free_context(kctx);
+		return krb5_to_nt_status(rc);
+	}
+
+	krb5_free_context(kctx);
+	return NT_STATUS_OK;
+}
+
+
  static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT  
*ads,
  					const char *machine_name,
+					const char *dnsdomain,
  					const struct sockaddr_storage *addrs,
  					int num_addrs)
  {
  	struct dns_rr_ns *nameservers = NULL;
  	int ns_count = 0;
  	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-	DNS_ERROR dns_err;
+	DNS_ERROR dns_err = ERROR_DNS_SUCCESS;
  	fstring dns_server;
-	const char *dnsdomain = NULL;
  	char *root_domain = NULL;

-	if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
-		d_printf("No DNS domain configured for %s. "
-			 "Unable to perform DNS Update.\n", machine_name);
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto done;
-	}
-	dnsdomain++;
-
  	status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers,  
&ns_count );
  	if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
  		/* Child domains often do not have NS records.  Look
@@ -1041,6 +1076,19 @@ static NTSTATUS  
net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,

  done:

+	if (!NT_STATUS_IS_OK(status)) {
+		if (!ERR_DNS_IS_OK(dns_err)) {
+			d_printf("DNS update for %s failed: %s\n",
+				machine_name,
+				dns_errstr(dns_err));
+		} else {
+			d_printf("DNS update for %s failed: %s\n",
+				machine_name,
+				get_friendly_nt_error_msg(status));
+		}
+	}
+
+
  	SAFE_FREE( root_domain );

  	return status;
@@ -1050,11 +1098,30 @@ static NTSTATUS net_update_dns(TALLOC_CTX  
*mem_ctx, ADS_STRUCT *ads)
  {
  	int num_addrs;
  	struct sockaddr_storage *iplist = NULL;
-	fstring machine_name;
+	char * machine_fqdn = NULL;
+	char * dnsdomain = NULL;
  	NTSTATUS status;

-	name_to_fqdn( machine_name, global_myname() );
-	strlower_m( machine_name );
+	/* The name we register should be the computer name with the
+	 * DNS domain appended. See http://support.microsoft.com/kb/317590.
+	 * We derive the DNS domain from the KRB5 realm because we can't rely
+	 * on the domain being configured correctly (or at all).
+	 */
+	status = map_krb_realm_to_dns_domain(ads, &dnsdomain);
+	if (!NT_STATUS_IS_OK(status)) {
+		goto done;
+	}
+
+	machine_fqdn = talloc_asprintf(mem_ctx, "%s.%s",
+			    global_myname(), dnsdomain);
+	if (machine_fqdn == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
+
+	strlower_m(machine_fqdn);
+	DEBUG(4, ("updating DNS registration for name '%s'\n",
+			    machine_fqdn));

  	/* Get our ip address (not the 127.0.0.x address but a real ip
  	 * address) */
@@ -1063,11 +1130,14 @@ static NTSTATUS net_update_dns(TALLOC_CTX  
*mem_ctx, ADS_STRUCT *ads)
  	if ( num_addrs <= 0 ) {
  		DEBUG(4,("net_update_dns: Failed to find my non-loopback IP "
  			 "addresses!\n"));
-		return NT_STATUS_INVALID_PARAMETER;
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto done;
  	}

-	status = net_update_dns_internal(mem_ctx, ads, machine_name,
-					 iplist, num_addrs);
+	status = net_update_dns_internal(mem_ctx, ads, machine_fqdn,
+				     dnsdomain, iplist, num_addrs);
+
+done:
  	SAFE_FREE( iplist );
  	return status;
  }
-- 
1.5.5.1




More information about the samba-technical mailing list