The branch, master has been updated
       via  0ec865d9795 Fix for https://bugzilla.samba.org/show_bug.cgi?id=9634
      from  4f20d310af2 s3: smbd: Remove erroneous 
TALLOC_FREE(smb_fname_parent) in change_file_owner_to_parent() error path.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0ec865d979540a63362a2014358c8bb27efc0081
Author: Julien ROPÉ <[email protected]>
Date:   Fri Nov 23 15:56:59 2018 +0100

    Fix for https://bugzilla.samba.org/show_bug.cgi?id=9634
    
    Add an option to smb.conf to list authorized zone transfer clients.
    Implement restriction in dlz_bind9 module to allow transfers only to 
selected IPs.
    Deny zone transfer by default in dlz_bind9.
    
    Adds test for the restriction in DNZ zone transfer clients.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9634
    
    Signed-off-by: Julien ROPÉ <[email protected]>
    Reviewed-by: Jeremy Allison <[email protected]>
    Reviewed-by: Andrew Bartlett <[email protected]>
    
    Autobuild-User(master): Jeremy Allison <[email protected]>
    Autobuild-Date(master): Fri Jun 11 19:28:10 UTC 2021 on sn-devel-184

-----------------------------------------------------------------------

Summary of changes:
 WHATSNEW.txt                                       |  9 +++
 .../domain/dnszonetransferclientsallow.xml         | 26 ++++++++
 .../domain/dnszonetransferclientsdeny.xml          | 26 ++++++++
 source4/dns_server/dlz_bind9.c                     | 55 ++++++++++++++++-
 source4/torture/dns/dlz_bind9.c                    | 71 ++++++++++++++++++++++
 5 files changed, 185 insertions(+), 2 deletions(-)
 create mode 100644 docs-xml/smbdotconf/domain/dnszonetransferclientsallow.xml
 create mode 100644 docs-xml/smbdotconf/domain/dnszonetransferclientsdeny.xml


Changeset truncated at 500 lines:

diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 1e407da422e..b28722c6f92 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -36,6 +36,15 @@ See also GPG_AA99442FB680B620_replaces_6F33915B6568B7EA.txt
 
 NEW FEATURES/CHANGES
 ====================
+- bind DLZ: Added the ability to set allow/deny lists for zone
+  transfer clients.
+  Up to now, any client could use a DNS zone transfer request
+  to the bind server, and get an answer from Samba.
+  Now the default behaviour will be to deny those request.
+  Two new options have been added to manage the list of
+  authorized/denied clients for zone transfer requests.
+  In order to be accepted, the request must be issued by a client
+  that is in the allow list and NOT in the deny list.
 
 
 
diff --git a/docs-xml/smbdotconf/domain/dnszonetransferclientsallow.xml 
b/docs-xml/smbdotconf/domain/dnszonetransferclientsallow.xml
new file mode 100644
index 00000000000..902b6082379
--- /dev/null
+++ b/docs-xml/smbdotconf/domain/dnszonetransferclientsallow.xml
@@ -0,0 +1,26 @@
+<samba:parameter name="dns zone transfer clients allow"
+                 context="G"
+                 type="cmdlist"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc";>
+<description>
+       <para>This option specifies the list IPs authorized to ask for dns zone
+           transfer from bind DLZ module.
+       </para>
+
+       <para>The IP list is comma and space separated and specified in the same
+           syntax as used in <smbconfoption name="hosts allow"/>, specifically
+           including IP address, IP prefixes and IP address masks.
+       </para>
+
+       <para>As this is a DNS server option, hostnames are naturally not 
permitted.
+       </para>
+
+       <para>The default behaviour is to deny any request.
+              A request will be authorized only if the emitting client is 
identified
+              in this list, and not in <smbconfoption name="dns zone transfer 
clients deny"/>
+       </para>
+</description>
+
+<value type="default"></value>
+<value type="example">192.168.0.1</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/domain/dnszonetransferclientsdeny.xml 
b/docs-xml/smbdotconf/domain/dnszonetransferclientsdeny.xml
new file mode 100644
index 00000000000..f88b15bf1ca
--- /dev/null
+++ b/docs-xml/smbdotconf/domain/dnszonetransferclientsdeny.xml
@@ -0,0 +1,26 @@
+<samba:parameter name="dns zone transfer clients deny"
+                 context="G"
+                 type="cmdlist"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc";>
+<description>
+       <para>This option specifies the list IPs denied to ask for dns zone
+           transfer from bind DLZ module.
+       </para>
+
+       <para>The IP list is comma and space separated and specified in the same
+           syntax as used in <smbconfoption name="hosts allow"/>, specifically
+           including IP address, IP prefixes and IP address masks.
+       </para>
+
+       <para>As this is a DNS server option, hostnames are naturally not 
permitted.
+       </para>
+
+       <para>If a client identified in this list sends a zone transfer 
request, it will always
+              be denied, even if they are in <smbconfoption name="dns zone 
transfer clients allow"/>.
+             This allows the definition of sepcific denied clients within an 
authorized subnet.
+       </para>
+</description>
+
+<value type="default"></value>
+<value type="example">192.168.0.1</value>
+</samba:parameter>
diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c
index 78f69a4d635..a9946041206 100644
--- a/source4/dns_server/dlz_bind9.c
+++ b/source4/dns_server/dlz_bind9.c
@@ -40,6 +40,7 @@
 #include "dlz_minimal.h"
 #include "dnsserver_common.h"
 #include "lib/util/smb_strtox.h"
+#include "lib/util/access.h"
 
 #undef strcasecmp
 
@@ -1085,10 +1086,60 @@ _PUBLIC_ isc_result_t dlz_lookup(const char *zone, 
const char *name,
  */
 _PUBLIC_ isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const 
char *client)
 {
-       /* just say yes for all our zones for now */
        struct dlz_bind9_data *state = talloc_get_type(
                dbdata, struct dlz_bind9_data);
-       return b9_find_zone_dn(state, name, NULL, NULL);
+       isc_result_t ret;
+       const char **authorized_clients, **denied_clients;
+       const char *cname="";
+
+       /* check that the zone is known */
+       ret = b9_find_zone_dn(state, name, NULL, NULL);
+       if (ret != ISC_R_SUCCESS) {
+               return ret;
+       }
+
+       /* default is to deny all transfers */
+
+       authorized_clients = lpcfg_dns_zone_transfer_clients_allow(state->lp);
+       denied_clients = lpcfg_dns_zone_transfer_clients_deny(state->lp);
+
+       /* The logic of allow_access() when both allow and deny lists are given
+        * does not match our expectation here: it would allow clients thar are
+        * neither allowed nor denied.
+        * Here, we want to deny clients by default.
+        * Using the allow_access() function is still useful as it takes care of
+        * parsing IP adresses and subnets in a consistent way with other 
options
+        * from smb.conf.
+        *
+        * We will then check the deny list first, then the allow list, so that
+        * we accept only clients that are explicitely allowed AND not 
explicitely
+        * denied.
+        */
+       if ((authorized_clients == NULL) && (denied_clients == NULL)) {
+               /* No "allow" or "deny" lists given. Deny by default. */
+               return ISC_R_NOPERM;
+       }
+
+       if (denied_clients != NULL) {
+               bool ok = allow_access(denied_clients, NULL, cname, client);
+               if (!ok) {
+                       /* client on deny list. Deny. */
+                       return ISC_R_NOPERM;
+               }
+       }
+
+       if (authorized_clients != NULL) {
+               bool ok = allow_access(NULL, authorized_clients, cname, client);
+               if (ok) {
+                       /*
+                        * client is not on deny list and is on allow list.
+                        * This is the only place we should return "allow".
+                        */
+                       return ISC_R_SUCCESS;
+               }
+       }
+       /* We shouldn't get here, but deny by default. */
+       return ISC_R_NOPERM;
 }
 
 /*
diff --git a/source4/torture/dns/dlz_bind9.c b/source4/torture/dns/dlz_bind9.c
index 1e1f1e8bef9..9ec2702dc1d 100644
--- a/source4/torture/dns/dlz_bind9.c
+++ b/source4/torture/dns/dlz_bind9.c
@@ -1200,6 +1200,76 @@ cancel_version:
        return ret;
 }
 
+/*
+ * Test zone transfer requests restrictions
+ *
+ * 1: test that zone transfer is denied by default
+ * 2: with an authorized list of IPs set in smb.conf, test that zone transfer
+ *    is accepted only for selected IPs.
+ */
+static bool test_dlz_bind9_allowzonexfr(struct torture_context *tctx)
+{
+       void *dbdata;
+       const char *argv[] = {
+               "samba_dlz",
+               "-H",
+               test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
+               NULL
+       };
+       isc_result_t ret;
+       dns_dlzdb_t *dlzdb = NULL;
+       bool ok;
+
+       tctx_static = tctx;
+       torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
+                                                 "log", dlz_bind9_log_wrapper,
+                                                 "writeable_zone", 
dlz_bind9_writeable_zone_hook,
+                                                 "putrr", dlz_bind9_putrr_hook,
+                                                 "putnamedrr", 
dlz_bind9_putnamedrr_hook,
+                                                 NULL),
+                                ISC_R_SUCCESS,
+                                "Failed to create samba_dlz");
+
+       torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, 
dbdata),
+                                                    ISC_R_SUCCESS,
+                                            "Failed to configure samba_dlz");
+
+    /* Ask for zone transfer with no specific config => expect denied */
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
+    torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
+                            "Zone transfer accepted with default settings");
+
+    /* Ask for zone transfer with authorizations set */
+    ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients 
allow=127.0.0.1,1234:5678::1,192.168.0.");
+    torture_assert(tctx, ok, "Failed to set dns zone transfer clients allow 
option.");
+
+    ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients 
deny=192.168.0.2");
+    torture_assert(tctx, ok, "Failed to set dns zone transfer clients deny 
option.");
+
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
+    torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
+                            "Zone transfer refused for authorized IPv4 
address");
+
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), 
"1234:5678::1");
+    torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
+                             "Zone transfer refused for authorized IPv6 
address.");
+
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "10.0.0.1");
+    torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
+                            "Zone transfer accepted for unauthorized IP");
+
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), 
"192.168.0.1");
+    torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
+                             "Zone transfer refused for address in authorized 
IPv4 subnet.");
+
+    ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), 
"192.168.0.2");
+    torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
+                            "Zone transfer allowed for denied client.");
+
+    dlz_destroy(dbdata);
+    return true;
+}
+
 static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx)
 {
        struct torture_suite *suite = torture_suite_create(ctx, "dlz_bind9");
@@ -1221,6 +1291,7 @@ static struct torture_suite *dlz_bind9_suite(TALLOC_CTX 
*ctx)
        torture_suite_add_simple_test(suite, "lookup", test_dlz_bind9_lookup);
        torture_suite_add_simple_test(suite, "zonedump", 
test_dlz_bind9_zonedump);
        torture_suite_add_simple_test(suite, "update01", 
test_dlz_bind9_update01);
+       torture_suite_add_simple_test(suite, "allowzonexfr", 
test_dlz_bind9_allowzonexfr);
        return suite;
 }
 


-- 
Samba Shared Repository

Reply via email to