dns-update-register-AD-style-name [plain text]
Index: samba/source/utils/net_ads.c
===================================================================
--- samba/source/utils/net_ads.c.orig
+++ samba/source/utils/net_ads.c
@@ -1285,28 +1285,83 @@ DNS_ERROR DoDNSUpdate(char *pszServerNam
const char *pszHostName,
const struct in_addr *iplist, int num_addrs );
+/* XXX this symbol is currently private. We are asking MIT about making
+ * it public -- jpeach Thu Jun 28 12:36:36 PDT 2007
+ */
+extern krb5_error_code KRB5_CALLCONV krb5_get_realm_domain
+ (krb5_context, const char *, char ** );
+
+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 %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;
+}
+
+ const char *dns_errstr(DNS_ERROR err)
+{
+ if (ERR_DNS_EQUAL(err, ERROR_DNS_SUCCESS)) {
+ return "success";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_RECORD_NOT_FOUND)) {
+ return "DNS record not found";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_BAD_RESPONSE)) {
+ return "bad DNS response";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_INVALID_PARAMETER)) {
+ return "invalid DNS parameter";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_NO_MEMORY)) {
+ return "out of memory";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_INVALID_NAME_SERVER)) {
+ return "invalild name server";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_CONNECTION_FAILED)) {
+ return "connection failed";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_GSS_ERROR)) {
+ return "GSS error";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_INVALID_NAME)) {
+ return "invalid DNS name";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_INVALID_MESSAGE)) {
+ return "invalid DNS message";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_SOCKET_ERROR)) {
+ return "socket error";
+ } else if (ERR_DNS_EQUAL(err, ERROR_DNS_UPDATE_FAILED)) {
+ return "DNS update failed";
+ } else {
+ return "invalid DNS error code";
+ }
+}
static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
const char *machine_name,
+ const char *dnsdomain,
const struct in_addr *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
@@ -1348,13 +1403,11 @@ static NTSTATUS net_update_dns_internal(
status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
- DEBUG(3,("net_ads_join: Failed to find name server for the %s "
+ DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
"realm\n", ads->config.realm));
- goto done;
- }
+ goto done;
+ }
- dnsdomain = root_domain;
-
}
/* Now perform the dns update - we'll try non-secure and if we fail,
@@ -1362,13 +1415,27 @@ static NTSTATUS net_update_dns_internal(
fstrcpy( dns_server, nameservers[0].hostname );
- dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
+ dns_err = DoDNSUpdate(dns_server,
+ root_domain ? root_domain : dnsdomain,
+ machine_name, addrs, num_addrs);
if (!ERR_DNS_IS_OK(dns_err)) {
status = NT_STATUS_UNSUCCESSFUL;
}
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;
@@ -1378,25 +1445,45 @@ static NTSTATUS net_update_dns(TALLOC_CT
{
int num_addrs;
struct in_addr *iplist = NULL;
- fstring machine_fqdn;
+ char * machine_fqdn = NULL;
+ char * dnsdomain = NULL;
NTSTATUS status;
- machine_fqdn[0] = '\0';
- get_mydnsfullname(machine_fqdn);
- strlower_m( machine_fqdn );
+ /* 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) */
num_addrs = get_my_ip_address( &iplist );
if ( num_addrs <= 0 ) {
- DEBUG(4,("net_ads_join: Failed to find my non-loopback IP "
+ 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_fqdn,
- iplist, num_addrs);
+ dnsdomain, iplist, num_addrs);
+done:
+ SAFE_FREE(dnsdomain);
SAFE_FREE( iplist );
return status;
}
Index: samba/source/libaddns/dnsutils.c
===================================================================
--- samba/source/libaddns/dnsutils.c.orig
+++ samba/source/libaddns/dnsutils.c
@@ -35,17 +35,15 @@ static DNS_ERROR LabelList( TALLOC_CTX *
const char *dot;
for (dot = name; *dot != '\0'; dot += 1) {
- char c = *dot;
-
- if (c == '.')
+ /* Don't bother checking for legal hostname characters here.
+ * RFC 1034 says that the "preferred" syntax for a hostname
+ * consists only of alphanumerics and '-'. I interpret the work
+ * "preferred" as "throw it at the server and let it pick up
+ * the pieces" --jpeach
+ */
+ if (*dot == '.') {
break;
-
- if (c == '-') continue;
- if ((c >= 'a') && (c <= 'z')) continue;
- if ((c >= 'A') && (c <= 'Z')) continue;
- if ((c >= '0') && (c <= '9')) continue;
-
- return ERROR_DNS_INVALID_NAME;
+ }
}
if ((dot - name) > 63) {