summaryrefslogtreecommitdiff
path: root/source4/dns_server
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2017-04-11 12:43:22 +1200
committerAndrew Bartlett <abartlet@samba.org>2017-06-10 21:48:21 +0200
commitc1bf6d24936b5255b9a714f8f252e281b7f82c9f (patch)
tree4124e8d64cc23be412bd52173dcdd987df200729 /source4/dns_server
parent21e76e2379934e55a4e9fc3b9cbea890a8fb535f (diff)
downloadsamba-c1bf6d24936b5255b9a714f8f252e281b7f82c9f.tar.gz
dns_server: clobber MNAME in the SOA
Otherwise, we always report the first server we created/provisioned the AD domain on which does not match AD behaviour. AD is multi-master so all RW servers are a master. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'source4/dns_server')
-rw-r--r--source4/dns_server/dlz_bind9.c2
-rw-r--r--source4/dns_server/dnsserver_common.c53
-rw-r--r--source4/dns_server/dnsserver_common.h3
-rw-r--r--source4/dns_server/pydns.c8
4 files changed, 59 insertions, 7 deletions
diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c
index 897699a6317..7096f4749b2 100644
--- a/source4/dns_server/dlz_bind9.c
+++ b/source4/dns_server/dlz_bind9.c
@@ -997,7 +997,7 @@ _PUBLIC_ isc_result_t dlz_allnodes(const char *zone, void *dbdata,
return ISC_R_NOMEMORY;
}
- werr = dns_common_extract(el, el_ctx, &recs, &num_recs);
+ werr = dns_common_extract(state->samdb, el, el_ctx, &recs, &num_recs);
if (!W_ERROR_IS_OK(werr)) {
state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s, %s",
ldb_dn_get_linearized(dn), win_errstr(werr));
diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c
index fbfa5fa4eae..d0c0a2fdbb4 100644
--- a/source4/dns_server/dnsserver_common.c
+++ b/source4/dns_server/dnsserver_common.c
@@ -69,7 +69,8 @@ uint8_t werr_to_dns_err(WERROR werr)
return DNS_RCODE_SERVFAIL;
}
-WERROR dns_common_extract(const struct ldb_message_element *el,
+WERROR dns_common_extract(struct ldb_context *samdb,
+ const struct ldb_message_element *el,
TALLOC_CTX *mem_ctx,
struct dnsp_DnssrvRpcRecord **records,
uint16_t *num_records)
@@ -86,9 +87,13 @@ WERROR dns_common_extract(const struct ldb_message_element *el,
return WERR_NOT_ENOUGH_MEMORY;
}
for (ri = 0; ri < el->num_values; ri++) {
+ bool am_rodc;
+ int ret;
+ const char *attrs[] = { "dnsHostName", NULL };
+ const char *dnsHostName;
struct ldb_val *v = &el->values[ri];
enum ndr_err_code ndr_err;
-
+ struct ldb_result *res = NULL;
ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
(ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -96,7 +101,49 @@ WERROR dns_common_extract(const struct ldb_message_element *el,
DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
return DNS_ERR(SERVER_FAILURE);
}
+
+ /*
+ * In AD, except on an RODC (where we should list a random RWDC,
+ * we should over-stamp the MNAME with our own hostname
+ */
+ if (recs[ri].wType != DNS_TYPE_SOA) {
+ continue;
+ }
+
+ ret = samdb_rodc(samdb, &am_rodc);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to confirm we are not an RODC: %s\n",
+ ldb_errstring(samdb)));
+ return DNS_ERR(SERVER_FAILURE);
+ }
+
+ if (am_rodc) {
+ continue;
+ }
+
+ ret = dsdb_search_dn(samdb, mem_ctx, &res, NULL,
+ attrs, 0);
+
+ if (res->count != 1 || ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to get rootDSE for dnsHostName: %s",
+ ldb_errstring(samdb)));
+ return DNS_ERR(SERVER_FAILURE);
+ }
+
+ dnsHostName
+ = ldb_msg_find_attr_as_string(res->msgs[0],
+ "dnsHostName",
+ NULL);
+
+ if (dnsHostName == NULL) {
+ DEBUG(0, ("Failed to get dnsHostName from rootDSE"));
+ return DNS_ERR(SERVER_FAILURE);
+ }
+
+ recs[ri].data.soa.mname
+ = talloc_steal(recs, dnsHostName);
}
+
*records = recs;
*num_records = el->num_values;
return WERR_OK;
@@ -189,7 +236,7 @@ WERROR dns_common_lookup(struct ldb_context *samdb,
}
}
- werr = dns_common_extract(el, mem_ctx, records, num_records);
+ werr = dns_common_extract(samdb, el, mem_ctx, records, num_records);
TALLOC_FREE(msg);
if (!W_ERROR_IS_OK(werr)) {
return werr;
diff --git a/source4/dns_server/dnsserver_common.h b/source4/dns_server/dnsserver_common.h
index 293831f0acb..b615e2dcfae 100644
--- a/source4/dns_server/dnsserver_common.h
+++ b/source4/dns_server/dnsserver_common.h
@@ -35,7 +35,8 @@ struct dns_server_zone {
struct ldb_dn *dn;
};
-WERROR dns_common_extract(const struct ldb_message_element *el,
+WERROR dns_common_extract(struct ldb_context *samdb,
+ const struct ldb_message_element *el,
TALLOC_CTX *mem_ctx,
struct dnsp_DnssrvRpcRecord **records,
uint16_t *num_records);
diff --git a/source4/dns_server/pydns.c b/source4/dns_server/pydns.c
index cb41faa1441..63fa80e92b3 100644
--- a/source4/dns_server/pydns.c
+++ b/source4/dns_server/pydns.c
@@ -160,17 +160,21 @@ static PyObject *py_dsdb_dns_lookup(PyObject *self,
static PyObject *py_dsdb_dns_extract(PyObject *self, PyObject *args)
{
+ struct ldb_context *samdb;
PyObject *py_dns_el, *ret;
+ PyObject *py_ldb = NULL;
TALLOC_CTX *frame;
WERROR werr;
struct ldb_message_element *dns_el;
struct dnsp_DnssrvRpcRecord *records;
uint16_t num_records;
- if (!PyArg_ParseTuple(args, "O", &py_dns_el)) {
+ if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dns_el)) {
return NULL;
}
+ PyErr_LDB_OR_RAISE(py_ldb, samdb);
+
if (!py_check_dcerpc_type(py_dns_el, "ldb", "MessageElement")) {
PyErr_SetString(PyExc_TypeError,
"ldb MessageElement object required");
@@ -180,7 +184,7 @@ static PyObject *py_dsdb_dns_extract(PyObject *self, PyObject *args)
frame = talloc_stackframe();
- werr = dns_common_extract(dns_el,
+ werr = dns_common_extract(samdb, dns_el,
frame,
&records,
&num_records);