From 09818693ac251a15df39433ed529b882883cdd44 Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Date: Wed, 22 May 2019 12:58:01 +1200
Subject: [PATCH 1/2] CVE-2019-12435 rpc/dns: avoid NULL deference if zone not
 found in DnssrvOperation

We still want to return DOES_NOT_EXIST when request_filter is not 0.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13922

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
 python/samba/tests/dcerpc/dnsserver.py        | 25 +++++++++++++++++++
 .../rpc_server/dnsserver/dcerpc_dnsserver.c   |  7 +++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py
index 53e1abde042..db9ed156148 100644
--- a/python/samba/tests/dcerpc/dnsserver.py
+++ b/python/samba/tests/dcerpc/dnsserver.py
@@ -28,6 +28,7 @@ from samba.dcerpc import dnsp, dnsserver, security
 from samba.tests import RpcInterfaceTestCase, env_get_var_value
 from samba.netcmd.dns import ARecord, AAAARecord, PTRRecord, CNameRecord, NSRecord, MXRecord, SRVRecord, TXTRecord
 from samba import sd_utils, descriptor
+from samba import WERRORError, werror
 
 class DnsserverTests(RpcInterfaceTestCase):
 
@@ -707,6 +708,30 @@ class DnsserverTests(RpcInterfaceTestCase):
                                                 'ServerInfo')
         self.assertEquals(dnsserver.DNSSRV_TYPEID_SERVER_INFO, typeid)
 
+
+    # This test is to confirm that we do not support multizone operations,
+    # which are designated by a non-zero dwContext value (the 3rd argument
+    # to DnssrvOperation).
+    def test_operation_invalid(self):
+        non_zone = 'a-zone-that-does-not-exist'
+        typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
+        name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
+        name_and_param.pszNodeName = 'AllowUpdate'
+        name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
+        try:
+            res = self.conn.DnssrvOperation(self.server,
+                                            non_zone,
+                                            1,
+                                            'ResetDwordProperty',
+                                            typeid,
+                                            name_and_param)
+        except WERRORError as e:
+            if e.args[0] == werror.WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST:
+                return
+
+        # We should always encounter a DOES_NOT_EXIST error.
+        self.fail()
+
     def test_operation2(self):
         client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
         rev_zone = '1.168.192.in-addr.arpa'
diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
index b42d7c549d1..4e28778c89a 100644
--- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
+++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
@@ -1955,7 +1955,12 @@ static WERROR dcesrv_DnssrvOperation(struct dcesrv_call_state *dce_call, TALLOC_
 						&r->in.pData);
 	} else {
 		z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
-		if (z == NULL && request_filter == 0) {
+		/*
+		 * In the case that request_filter is not 0 and z is NULL,
+		 * the request is for a multizone operation, which we do not
+		 * yet support, so just error on NULL zone name.
+		 */
+		if (z == NULL) {
 			return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
 		}
 
-- 
2.17.1


From c2423655657f3074c80ae06f0b6806fc71c8bb41 Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Date: Wed, 22 May 2019 13:23:25 +1200
Subject: [PATCH 2/2] CVE-2019-12435 rpc/dns: avoid NULL deference if zone not
 found in DnssrvOperation2

We still want to return DOES_NOT_EXIST when request_filter is not 0.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13922

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
 python/samba/tests/dcerpc/dnsserver.py        | 26 +++++++++++++++++++
 .../rpc_server/dnsserver/dcerpc_dnsserver.c   |  7 ++++-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/python/samba/tests/dcerpc/dnsserver.py b/python/samba/tests/dcerpc/dnsserver.py
index db9ed156148..7264a290ef2 100644
--- a/python/samba/tests/dcerpc/dnsserver.py
+++ b/python/samba/tests/dcerpc/dnsserver.py
@@ -732,6 +732,32 @@ class DnsserverTests(RpcInterfaceTestCase):
         # We should always encounter a DOES_NOT_EXIST error.
         self.fail()
 
+    # This test is to confirm that we do not support multizone operations,
+    # which are designated by a non-zero dwContext value (the 5th argument
+    # to DnssrvOperation2).
+    def test_operation2_invalid(self):
+        client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
+        non_zone = 'a-zone-that-does-not-exist'
+        typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
+        name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
+        name_and_param.pszNodeName = 'AllowUpdate'
+        name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
+        try:
+            res = self.conn.DnssrvOperation2(client_version,
+                                             0,
+                                             self.server,
+                                             non_zone,
+                                             1,
+                                             'ResetDwordProperty',
+                                             typeid,
+                                             name_and_param)
+        except WERRORError as e:
+            if e.args[0] == werror.WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST:
+                return
+
+        # We should always encounter a DOES_NOT_EXIST error.
+        self.fail()
+
     def test_operation2(self):
         client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
         rev_zone = '1.168.192.in-addr.arpa'
diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
index 4e28778c89a..353754f9261 100644
--- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
+++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c
@@ -2167,7 +2167,12 @@ static WERROR dcesrv_DnssrvOperation2(struct dcesrv_call_state *dce_call, TALLOC
 						&r->in.pData);
 	} else {
 		z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
-		if (z == NULL && request_filter == 0) {
+		/*
+		 * In the case that request_filter is not 0 and z is NULL,
+		 * the request is for a multizone operation, which we do not
+		 * yet support, so just error on NULL zone name.
+		 */
+		if (z == NULL) {
 			return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
 		}
 
-- 
2.17.1