def tearDown(self):
super(TestRPCRoundtrip, self).tearDown()
+ def rpc_update(self, fqn=None, data=None, wType=None, delete=False):
+ fqn = fqn or ("rpctestrec." + self.get_dns_domain())
+
+ rec = data_to_dns_record(wType, data)
+ add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
+ add_rec_buf.rec = rec
+
+ add_arg = add_rec_buf
+ del_arg = None
+ if delete:
+ add_arg = None
+ del_arg = add_rec_buf
+
+ self.rpc_conn.DnssrvUpdateRecord2(
+ dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0,
+ self.server_ip,
+ self.get_dns_domain(),
+ fqn,
+ add_arg,
+ del_arg)
+
+ def test_rpc_self_referencing_cname(self):
+ cname = "cnametest2_unqual_rec_loop"
+ cname_fqn = "%s.%s" % (cname, self.get_dns_domain())
+
+ try:
+ self.rpc_update(fqn=cname, data=cname_fqn,
+ wType=dnsp.DNS_TYPE_CNAME, delete=True)
+ except WERRORError as e:
+ if e.args[0] != werror.WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST:
+ self.fail("RPC DNS gaven wrong error on pre-test cleanup "
+ "for self referencing CNAME: %s" % e.args[0])
+
+ try:
+ self.rpc_update(fqn=cname, wType=dnsp.DNS_TYPE_CNAME, data=cname_fqn)
+ except WERRORError as e:
+ if e.args[0] != werror.WERR_DNS_ERROR_CNAME_LOOP:
+ self.fail("RPC DNS gaven wrong error on insertion of "
+ "self referencing CNAME: %s" % e.args[0])
+ return
+
+ self.fail("RPC DNS allowed insertion of self referencing CNAME")
+
def test_update_add_txt_rpc_to_dns(self):
prefix, txt = 'rpctextrec', ['"This is a test"']
samba.tests.dns.__main__.TestRPCRoundtrip.test_update_add_null_padded_txt_record\(rodc:local\)
samba.tests.dns.__main__.TestRPCRoundtrip.test_update_add_slash_txt_record\(rodc:local\)
samba.tests.dns.__main__.TestRPCRoundtrip.test_update_add_two_txt_records\(rodc:local\)
+samba.tests.dns.__main__.TestRPCRoundtrip.test_rpc_self_referencing_cname\(rodc:local\)
samba.tests.dns.__main__.TestDNSUpdates.test_delete_record\(vampire_dc:local\)
samba.tests.dns.__main__.TestDNSUpdates.test_readd_record\(vampire_dc:local\)
samba.tests.dns.__main__.TestDNSUpdates.test_update_add_mx_record\(vampire_dc:local\)
#include "dsdb/samdb/samdb.h"
#include "lib/util/dlinklist.h"
#include "librpc/gen_ndr/ndr_dnsserver.h"
+#include "dns_server/dnsserver_common.h"
#include "dnsserver.h"
#define DCESRV_INTERFACE_DNSSERVER_BIND(call, iface) \
return WERR_OK;
}
+/*
+ * Check str1 + '.' + str2 = name, for example:
+ * ("dc0", "example.com", "dc0.example.com") = true
+ */
+static bool cname_self_reference(const char* node_name,
+ const char* zone_name,
+ struct DNS_RPC_NAME name) {
+ size_t node_len, zone_len;
+
+ if (node_name == NULL || zone_name == NULL) {
+ return false;
+ }
+
+ node_len = strlen(node_name);
+ zone_len = strlen(zone_name);
+
+ if (node_len == 0 ||
+ zone_len == 0 ||
+ (name.len != node_len + zone_len + 1)) {
+ return false;
+ }
+
+ if (strncmp(node_name, name.str, node_len) == 0 &&
+ name.str[node_len] == '.' &&
+ strncmp(zone_name, name.str + node_len + 1, zone_len) == 0) {
+ return true;
+ }
+
+ return false;
+}
+
/* dnsserver update function */
static WERROR dnsserver_update_record(struct dnsserver_state *dsstate,
}
W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
+ /* CNAMEs can't point to themselves */
+ if (add_buf != NULL && add_buf->rec.wType == DNS_TYPE_CNAME) {
+ if (cname_self_reference(node_name, z->name, add_buf->rec.data.name)) {
+ return WERR_DNS_ERROR_CNAME_LOOP;
+ }
+ }
+
if (add_buf != NULL) {
if (del_buf == NULL) {
/* Add record */