From 8cfa8fd9c06bdc653e9ff4583d526e51ce249324 Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Mon, 3 Nov 2014 11:57:50 +1100 Subject: [PATCH] s4-dns: dlz-bind: Add trailing '.' to all fqdn strings 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 Reviewed-by: Guenter Kukkukk --- source4/dns_server/dlz_bind9.c | 54 +++++++++++++++++++++++++++++++++-------- source4/torture/dns/dlz_bind9.c | 24 ++++++++++-------- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index d43b404..134aeba 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -110,6 +110,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 */ static bool b9_format(struct dlz_bind9_data *state, @@ -133,7 +154,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 +168,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"; + tmp = b9_format_fqdn(mem_ctx, rec->data.srv.nameTarget); + if (tmp == 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); + tmp); break; case DNS_TYPE_MX: *type = "mx"; + tmp = b9_format_fqdn(mem_ctx, rec->data.mx.nameTarget); + if (tmp == NULL) { + return false; + } *data = talloc_asprintf(mem_ctx, "%u %s", - rec->data.mx.wPriority, - rec->data.mx.nameTarget); + rec->data.mx.wPriority, tmp); break; case DNS_TYPE_HINFO: @@ -175,7 +203,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 +214,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 +225,15 @@ static bool b9_format(struct dlz_bind9_data *state, return false; } + tmp = b9_format_fqdn(mem_ctx, rec->data.soa.rname); + if (tmp == 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, tmp, rec->data.soa.serial, rec->data.soa.refresh, rec->data.soa.retry, @@ -957,6 +990,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; diff --git a/source4/torture/dns/dlz_bind9.c b/source4/torture/dns/dlz_bind9.c index 93da21f..de07f67 100644 --- a/source4/torture/dns/dlz_bind9.c +++ b/source4/torture/dns/dlz_bind9.c @@ -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"); -- 1.9.3