s4-dns: dlz-bind: Add trailing '.' to all fqdn strings
authorAmitay Isaacs <amitay@gmail.com>
Mon, 3 Nov 2014 00:57:50 +0000 (11:57 +1100)
committerAmitay Isaacs <amitay@samba.org>
Fri, 21 Nov 2014 05:14:55 +0000 (06:14 +0100)
BIND 9.10.x is strict when sending records via putrr and putnamedrr.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=10620

Thanks to Guenter Kukkukk for identifying the problem and resolution.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Guenter Kukkukk <kukks@samba.org>
Autobuild-User(master): Amitay Isaacs <amitay@samba.org>
Autobuild-Date(master): Fri Nov 21 06:14:55 CET 2014 on sn-devel-104

source4/dns_server/dlz_bind9.c
source4/torture/dns/dlz_bind9.c

index d43b40478a6ee95b6146a49759265b78856e6cee..b7f5e5816eef69772783902350a806cad254a55d 100644 (file)
@@ -109,6 +109,27 @@ static void b9_add_helper(struct dlz_bind9_data *state, const char *helper_name,
        }
 }
 
+/*
+ * Add a trailing '.' if it's missing
+ */
+static const char *b9_format_fqdn(TALLOC_CTX *mem_ctx, const char *str)
+{
+       size_t len;
+       const char *tmp;
+
+       if (str == NULL || str[0] == '\0') {
+               return str;
+       }
+
+       len = strlen(str);
+       if (str[len-1] != '.') {
+               tmp = talloc_asprintf(mem_ctx, "%s.", str);
+       } else {
+               tmp = str;
+       }
+       return tmp;
+}
+
 /*
   format a record for bind9
  */
@@ -119,6 +140,7 @@ static bool b9_format(struct dlz_bind9_data *state,
 {
        uint32_t i;
        char *tmp;
+       const char *fqdn;
 
        switch (rec->wType) {
        case DNS_TYPE_A:
@@ -133,7 +155,7 @@ static bool b9_format(struct dlz_bind9_data *state,
 
        case DNS_TYPE_CNAME:
                *type = "cname";
-               *data = rec->data.cname;
+               *data = b9_format_fqdn(mem_ctx, rec->data.cname);
                break;
 
        case DNS_TYPE_TXT:
@@ -147,23 +169,30 @@ static bool b9_format(struct dlz_bind9_data *state,
 
        case DNS_TYPE_PTR:
                *type = "ptr";
-               *data = rec->data.ptr;
+               *data = b9_format_fqdn(mem_ctx, rec->data.ptr);
                break;
 
        case DNS_TYPE_SRV:
                *type = "srv";
+               fqdn = b9_format_fqdn(mem_ctx, rec->data.srv.nameTarget);
+               if (fqdn == NULL) {
+                       return false;
+               }
                *data = talloc_asprintf(mem_ctx, "%u %u %u %s",
                                        rec->data.srv.wPriority,
                                        rec->data.srv.wWeight,
                                        rec->data.srv.wPort,
-                                       rec->data.srv.nameTarget);
+                                       fqdn);
                break;
 
        case DNS_TYPE_MX:
                *type = "mx";
+               fqdn = b9_format_fqdn(mem_ctx, rec->data.mx.nameTarget);
+               if (fqdn == NULL) {
+                       return false;
+               }
                *data = talloc_asprintf(mem_ctx, "%u %s",
-                                       rec->data.mx.wPriority,
-                                       rec->data.mx.nameTarget);
+                                       rec->data.mx.wPriority, fqdn);
                break;
 
        case DNS_TYPE_HINFO:
@@ -175,7 +204,7 @@ static bool b9_format(struct dlz_bind9_data *state,
 
        case DNS_TYPE_NS:
                *type = "ns";
-               *data = rec->data.ns;
+               *data = b9_format_fqdn(mem_ctx, rec->data.ns);
                break;
 
        case DNS_TYPE_SOA: {
@@ -186,8 +215,9 @@ static bool b9_format(struct dlz_bind9_data *state,
                 * point at ourselves. This is how AD DNS servers
                 * force clients to send updates to the right local DC
                 */
-               mname = talloc_asprintf(mem_ctx, "%s.%s",
-                                       lpcfg_netbios_name(state->lp), lpcfg_dnsdomain(state->lp));
+               mname = talloc_asprintf(mem_ctx, "%s.%s.",
+                                       lpcfg_netbios_name(state->lp),
+                                       lpcfg_dnsdomain(state->lp));
                if (mname == NULL) {
                        return false;
                }
@@ -196,11 +226,15 @@ static bool b9_format(struct dlz_bind9_data *state,
                        return false;
                }
 
+               fqdn = b9_format_fqdn(mem_ctx, rec->data.soa.rname);
+               if (fqdn == NULL) {
+                       return false;
+               }
+
                state->soa_serial = rec->data.soa.serial;
 
                *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u",
-                                       mname,
-                                       rec->data.soa.rname,
+                                       mname, fqdn,
                                        rec->data.soa.serial,
                                        rec->data.soa.refresh,
                                        rec->data.soa.retry,
@@ -957,6 +991,7 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata,
                } else {
                        name = talloc_asprintf(el_ctx, "%s.%s", rdn, zone);
                }
+               name = b9_format_fqdn(el_ctx, name);
                if (name == NULL) {
                        talloc_free(tmp_ctx);
                        return ISC_R_NOMEMORY;
index 93da21f51c9a49d6a7a81268a849108b5827459e..de07f67e8140e5a57fac4b6838484a126c96032d 100644 (file)
@@ -353,7 +353,7 @@ static bool test_dlz_bind9_lookup(struct torture_context *tctx)
        expected1->records[0].type = "soa";
        expected1->records[0].ttl = 3600;
        expected1->records[0].data = talloc_asprintf(expected1->records,
-                               "%s.%s hostmaster.%s 1 900 600 86400 3600",
+                               "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx),
                                lpcfg_dnsdomain(tctx->lp_ctx));
@@ -362,7 +362,7 @@ static bool test_dlz_bind9_lookup(struct torture_context *tctx)
        expected1->records[1].name = expected1->query_name;
        expected1->records[1].type = "ns";
        expected1->records[1].ttl = 900;
-       expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s",
+       expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx));
        torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
@@ -471,40 +471,44 @@ static bool test_dlz_bind9_zonedump(struct torture_context *tctx)
                                               expected1->num_records);
        torture_assert(tctx, expected1->records != NULL, "talloc failed");
 
-       expected1->records[0].name = lpcfg_dnsdomain(tctx->lp_ctx);
+       expected1->records[0].name = talloc_asprintf(expected1->records,
+                               "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
        expected1->records[0].type = "soa";
        expected1->records[0].ttl = 3600;
        expected1->records[0].data = talloc_asprintf(expected1->records,
-                               "%s.%s hostmaster.%s 1 900 600 86400 3600",
+                               "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx),
                                lpcfg_dnsdomain(tctx->lp_ctx));
        torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
 
-       expected1->records[1].name = lpcfg_dnsdomain(tctx->lp_ctx);
+       expected1->records[1].name = talloc_asprintf(expected1->records,
+                               "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
        expected1->records[1].type = "ns";
        expected1->records[1].ttl = 900;
-       expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s",
+       expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx));
        torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
 
-       expected1->records[2].name = lpcfg_dnsdomain(tctx->lp_ctx);
+       expected1->records[2].name = talloc_asprintf(expected1->records,
+                               "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
        expected1->records[2].type = "aaaa";
        expected1->records[2].ttl = 900;
 
-       expected1->records[3].name = lpcfg_dnsdomain(tctx->lp_ctx);
+       expected1->records[3].name = talloc_asprintf(expected1->records,
+                               "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
        expected1->records[3].type = "a";
        expected1->records[3].ttl = 900;
 
-       expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s",
+       expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx));
        torture_assert(tctx, expected1->records[4].name != NULL, "unknown host");
        expected1->records[4].type = "aaaa";
        expected1->records[4].ttl = 900;
 
-       expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s",
+       expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.",
                                torture_setting_string(tctx, "host", NULL),
                                lpcfg_dnsdomain(tctx->lp_ctx));
        torture_assert(tctx, expected1->records[5].name != NULL, "unknown host");