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_erro r, $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