The branch, master has been updated
       via  9a68025ad39 s4:rpc_server/netlogon: adjust the valid_flags based on 
dsdb_dc_functional_level()
       via  d9abd7fff58 s4:rpc_server/netlogon: adjust the flags logic to 
MS-NRPC 3.5.4.3.1 DsrGetDcNameEx2
       via  55948433135 dsdb/netlogon: Indicate DC functional level support in 
samlogon response
       via  0e515b3309d dsdb/netlogon: make use of dsdb_dc_functional_level() 
in fill_netlogon_samlogon_response()
       via  e0b47257d9f dsgetdcname: Display new flags in debug output
       via  454e46c467f netlogon.idl: Add flags for indicating directory 
service versions
       via  2926cfb299c s4:rpc_server/dnsserver: make use of 
dsdb_dc_functional_level()
       via  b5f71e25d49 dsdb/common: add dsdb_dc_functional_level() helper
      from  2da538a4585 python:tests: Don't require an emtpy 
'authorization-data' to be present

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


- Log -----------------------------------------------------------------
commit 9a68025ad391b148166c25b7dec06a7ce12fe4a6
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Dec 23 18:32:44 2021 +0100

    s4:rpc_server/netlogon: adjust the valid_flags based on 
dsdb_dc_functional_level()
    
    This allows us to let DS_DIRECTORY_SERVICE_{8,9,10}_REQUIRED through
    based on the manual changed msDS-Behavior-Version of our NTDSA object.
    
    We still need to have tests depending on the msDS-Behavior-Version
    value if the DSGETDC_VALID_FLAGS is really correct at all.
    But for now this allows us to test krb5 FAST from Windows clients.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    
    Autobuild-User(master): Joseph Sutton <jsut...@samba.org>
    Autobuild-Date(master): Fri Dec 24 03:03:50 UTC 2021 on sn-devel-184

commit d9abd7fff58970725fa1375bf0ed210602e45d27
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Wed Dec 22 14:41:50 2021 +1300

    s4:rpc_server/netlogon: adjust the flags logic to MS-NRPC 3.5.4.3.1 
DsrGetDcNameEx2
    
    Note that this doesn't change the logic as we still reject
    DS_DIRECTORY_SERVICE_{8,9,10}_REQUIRED via the initial DSGETDC_VALID_FLAGS
    check. The may change that in future, but may need some tests for it.
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>

commit 55948433135929488fa8370f826afdc02db1bf2a
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Wed Dec 22 14:51:08 2021 +1300

    dsdb/netlogon: Indicate DC functional level support in samlogon response
    
    The DS_SERVER_DS_8 flag is necessary for Windows to detect FAST support.
    
    Note for know we only ever have DS_DOMAIN_FUNCTION_2008_R2 (4) in the
    msDS-Behavior-Version attribute of our own NTDSA object. So
    for now this is only for manual testing. In future we most likely
    want to extend 'samba-tool domain level' to raise the dc level
    manually or let 'samba' autoupgrade the value.
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>

commit 0e515b3309d0c3bbb63447fb712df2279f071551
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Dec 23 11:40:58 2021 +0100

    dsdb/netlogon: make use of dsdb_dc_functional_level() in 
fill_netlogon_samlogon_response()
    
    [MS-ADTS] 6.3.3.2 "Domain Controller Response to an LDAP Ping" indicates
    that the resulting flags depend on the server software (behavior)
    and not the domain wide functional level.
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz>

commit e0b47257d9f004e943da78dcb84f9a4a15552cef
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Wed Dec 22 14:53:44 2021 +1300

    dsgetdcname: Display new flags in debug output
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 454e46c467fbba9814c03c7200c58efb269c326d
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Thu Dec 23 10:57:50 2021 +1300

    netlogon.idl: Add flags for indicating directory service versions
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>

commit 2926cfb299c14a6d80c32059377833d41fd7a32a
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Dec 23 11:34:25 2021 +0100

    s4:rpc_server/dnsserver: make use of dsdb_dc_functional_level()
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz>

commit b5f71e25d49cff27a7f9c48b60a1a0eb70adfeec
Author: Stefan Metzmacher <me...@samba.org>
Date:   Thu Dec 23 11:34:02 2021 +0100

    dsdb/common: add dsdb_dc_functional_level() helper
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz>

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

Summary of changes:
 librpc/idl/netlogon.idl                       |  20 ++++-
 source3/libsmb/dsgetdcname.c                  |  24 +++---
 source4/dsdb/common/util.c                    |  15 ++++
 source4/dsdb/samdb/ldb_modules/netlogon.c     |  16 +++-
 source4/rpc_server/dnsserver/dnsutils.c       |   2 +-
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 112 ++++++++++++++++++++++++--
 6 files changed, 165 insertions(+), 24 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl
index e9a4b192a9f..5832d6862be 100644
--- a/librpc/idl/netlogon.idl
+++ b/librpc/idl/netlogon.idl
@@ -1149,6 +1149,13 @@ interface netlogon
                                         DS_TRY_NEXTCLOSEST_SITE |
                                         DS_DIRECTORY_SERVICE_6_REQUIRED |
                                         DS_WEB_SERVICE_REQUIRED |
+                                        /*
+                                         * For now we skip these until
+                                         * we have test for them:
+                                         * DS_DIRECTORY_SERVICE_8_REQUIRED |
+                                         * DS_DIRECTORY_SERVICE_9_REQUIRED |
+                                         * DS_DIRECTORY_SERVICE_10_REQUIRED |
+                                         */
                                         DS_RETURN_FLAT_NAME |
                                         DS_RETURN_DNS_NAME);
 
@@ -1169,8 +1176,11 @@ interface netlogon
                DS_IS_FLAT_NAME                 = 0x00010000,
                DS_IS_DNS_NAME                  = 0x00020000,
                DS_TRY_NEXTCLOSEST_SITE         = 0x00040000,
-               DS_DIRECTORY_SERVICE_6_REQUIRED = 0x00080000,
+               DS_DIRECTORY_SERVICE_6_REQUIRED = 0x00080000, /* 2008 */
                DS_WEB_SERVICE_REQUIRED         = 0x00100000,
+               DS_DIRECTORY_SERVICE_8_REQUIRED = 0x00200000, /* 2012 */
+               DS_DIRECTORY_SERVICE_9_REQUIRED = 0x00400000, /* 2012R2 */
+               DS_DIRECTORY_SERVICE_10_REQUIRED= 0x00800000, /* 2016 */
                DS_RETURN_DNS_NAME              = 0x40000000,
                DS_RETURN_FLAT_NAME             = 0x80000000
        } netr_DsRGetDCName_flags;
@@ -1191,10 +1201,12 @@ interface netlogon
                DS_SERVER_WRITABLE               = 0x00000100,
                DS_SERVER_GOOD_TIMESERV          = 0x00000200,
                DS_SERVER_NDNC                   = 0x00000400,
-               DS_SERVER_SELECT_SECRET_DOMAIN_6 = 0x00000800,
-               DS_SERVER_FULL_SECRET_DOMAIN_6   = 0x00001000,
+               DS_SERVER_SELECT_SECRET_DOMAIN_6 = 0x00000800, /* 2008 / RODC */
+               DS_SERVER_FULL_SECRET_DOMAIN_6   = 0x00001000, /* 2008 / RWDC */
                DS_SERVER_WEBSERV                = 0x00002000,
-               DS_SERVER_DS_8                   = 0x00004000,
+               DS_SERVER_DS_8                   = 0x00004000, /* 2012 */
+               DS_SERVER_DS_9                   = 0x00008000, /* 2012R2 */
+               DS_SERVER_DS_10                  = 0x00010000, /* 2016 */
                DS_DNS_CONTROLLER                = 0x20000000,
                DS_DNS_DOMAIN                    = 0x40000000,
                DS_DNS_FOREST_ROOT               = 0x80000000
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 5954e48d747..42714fcb2a1 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -89,18 +89,18 @@ static void debug_dsdcinfo_flags(int lvl, uint32_t flags)
                DEBUGADD(lvl,("DS_IS_FLAT_NAME "));
        if (flags & DS_IS_DNS_NAME)
                DEBUGADD(lvl,("DS_IS_DNS_NAME "));
-       if (flags & 0x00040000)
-               DEBUGADD(lvl,("0x00040000 "));
-       if (flags & 0x00080000)
-               DEBUGADD(lvl,("0x00080000 "));
-       if (flags & 0x00100000)
-               DEBUGADD(lvl,("0x00100000 "));
-       if (flags & 0x00200000)
-               DEBUGADD(lvl,("0x00200000 "));
-       if (flags & 0x00400000)
-               DEBUGADD(lvl,("0x00400000 "));
-       if (flags & 0x00800000)
-               DEBUGADD(lvl,("0x00800000 "));
+       if (flags & DS_TRY_NEXTCLOSEST_SITE)
+               DEBUGADD(lvl,("DS_TRY_NEXTCLOSEST_SITE "));
+       if (flags & DS_DIRECTORY_SERVICE_6_REQUIRED)
+               DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_6_REQUIRED "));
+       if (flags & DS_WEB_SERVICE_REQUIRED)
+               DEBUGADD(lvl,("DS_WEB_SERVICE_REQUIRED "));
+       if (flags & DS_DIRECTORY_SERVICE_8_REQUIRED)
+               DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_8_REQUIRED "));
+       if (flags & DS_DIRECTORY_SERVICE_9_REQUIRED)
+               DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_9_REQUIRED "));
+       if (flags & DS_DIRECTORY_SERVICE_10_REQUIRED)
+               DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_10_REQUIRED "));
        if (flags & 0x01000000)
                DEBUGADD(lvl,("0x01000000 "));
        if (flags & 0x02000000)
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 9b4afa45215..5da75f2d28f 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -3841,6 +3841,21 @@ int dsdb_forest_functional_level(struct ldb_context *ldb)
        return *forestFunctionality;
 }
 
+/*
+ * This detects and returns the DC functional level (DS_DOMAIN_FUNCTION_*)
+ */
+int dsdb_dc_functional_level(struct ldb_context *ldb)
+{
+       int *dcFunctionality =
+               talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), 
int);
+       if (!dcFunctionality) {
+               /* this is expected during initial provision */
+               DEBUG(4,(__location__ ": WARNING: domainControllerFunctionality 
not setup\n"));
+               return DS_DOMAIN_FUNCTION_2008_R2;
+       }
+       return *dcFunctionality;
+}
+
 /*
   set a GUID in an extended DN structure
  */
diff --git a/source4/dsdb/samdb/ldb_modules/netlogon.c 
b/source4/dsdb/samdb/ldb_modules/netlogon.c
index 66ab70b6f54..4864ae4740e 100644
--- a/source4/dsdb/samdb/ldb_modules/netlogon.c
+++ b/source4/dsdb/samdb/ldb_modules/netlogon.c
@@ -77,6 +77,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context 
*sam_ctx,
        struct interface *ifaces;
        bool user_known = false, am_rodc = false;
        uint32_t uac = 0;
+       int dc_level;
        NTSTATUS status;
 
        /* the domain parameter could have an optional trailing "." */
@@ -287,7 +288,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context 
*sam_ctx,
                server_type |= DS_SERVER_WRITABLE;
        }
 
-       if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) {
+       dc_level = dsdb_dc_functional_level(sam_ctx);
+       if (dc_level >= DS_DOMAIN_FUNCTION_2008) {
                if (server_type & DS_SERVER_WRITABLE) {
                        server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6;
                } else {
@@ -295,6 +297,18 @@ NTSTATUS fill_netlogon_samlogon_response(struct 
ldb_context *sam_ctx,
                }
        }
 
+       if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
+               server_type |= DS_SERVER_DS_8;
+       }
+
+       if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
+               server_type |= DS_SERVER_DS_9;
+       }
+
+       if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
+               server_type |= DS_SERVER_DS_10;
+       }
+
        if (version & 
(NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
                pdc_name = lpcfg_netbios_name(lp_ctx);
        } else {
diff --git a/source4/rpc_server/dnsserver/dnsutils.c 
b/source4/rpc_server/dnsserver/dnsutils.c
index 94407be0dcf..56b2690aa95 100644
--- a/source4/rpc_server/dnsserver/dnsutils.c
+++ b/source4/rpc_server/dnsserver/dnsutils.c
@@ -148,7 +148,7 @@ struct dnsserver_serverinfo 
*dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
 
        serverinfo->dwDsForestVersion = dsdb_forest_functional_level(samdb);
        serverinfo->dwDsDomainVersion = dsdb_functional_level(samdb);
-       serverinfo->dwDsDsaVersion = 4; /* need to do ldb search here */
+       serverinfo->dwDsDsaVersion = dsdb_dc_functional_level(samdb);
 
        serverinfo->pszDomainName = samdb_dn_to_dns_domain(mem_ctx, domain_dn);
        serverinfo->pszForestName = samdb_dn_to_dns_domain(mem_ctx, forest_dn);
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c 
b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 670f7a46358..269bea7c6fc 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -2990,6 +2990,31 @@ struct dcesrv_netr_DsRGetDCName_base_state {
 
 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
 
+/* Returns a nonzero value if multiple bits in 'val' are set. */
+static bool multiple_bits_set(uint32_t val)
+{
+       /*
+        * Subtracting one from an integer has the effect of flipping all the
+        * bits from the least significant bit up to and including the least
+        * significant '1' bit. For example,
+        *
+        *   0b101000 - 1
+        * = 0b100111
+        *       ====
+        *
+        * If 'val' is zero, all the bits will be flipped and thus the bitwise
+        * AND of 'val' with 'val - 1' will be zero.
+        *
+        * If the integer is nonzero, the least significant '1' bit will be
+        * ANDed with a '0' bit and so will be reset in the final result, but
+        * all other '1' bits will remain set. In other words, the effect of
+        * this expression is to mask off the least significant bit that is
+        * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
+        * must contain multiple set bits.
+        */
+       return val & (val - 1);
+}
+
 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct 
dcesrv_netr_DsRGetDCName_base_state *state)
 {
        struct dcesrv_call_state *dce_call = state->dce_call;
@@ -3012,6 +3037,8 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct 
dcesrv_netr_DsRGetDCName
        const char *domain_name = NULL;
        const char *pdc_ip;
        bool different_domain = true;
+       uint32_t valid_flags;
+       int dc_level;
 
        ZERO_STRUCTP(r->out.info);
 
@@ -3034,28 +3061,100 @@ static WERROR 
dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName
 
        /* "server_unc" is ignored by w2k3 */
 
-       if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
+       /*
+        * With the following flags:
+        * DS_FORCE_REDISCOVERY (Flag A)
+        * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
+        * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
+        * DS_GC_SERVER_REQUIRED (Flag D)
+        * DS_PDC_REQUIRED (Flag E)
+        * DS_BACKGROUND_ONLY (Flag F)
+        * DS_IP_REQUIRED (Flag G)
+        * DS_KDC_REQUIRED (Flag H)
+        * DS_TIMESERV_REQUIRED (Flag I)
+        * DS_WRITABLE_REQUIRED (Flag J)
+        * DS_GOOD_TIMESERV_PREFERRED (Flag K)
+        * DS_AVOID_SELF (Flag L)
+        * DS_ONLY_LDAP_NEEDED (Flag M)
+        * DS_IS_FLAT_NAME (Flag N)
+        * DS_IS_DNS_NAME (Flag O)
+        * DS_TRY_NEXTCLOSEST_SITE (Flag P)
+        * DS_DIRECTORY_SERVICE_6_REQUIRED  (Flag Q)
+        * DS_WEB_SERVICE_REQUIRED (Flag T)
+        * DS_DIRECTORY_SERVICE_8_REQUIRED  (Flag U)
+        * DS_DIRECTORY_SERVICE_9_REQUIRED  (Flag V)
+        * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
+        * DS_RETURN_DNS_NAME (Flag R)
+        * DS_RETURN_FLAT_NAME (Flag S)
+        *
+        * MS-NRPC 3.5.4.3.1 says:
+        * ...
+        * On receiving this call, the server MUST perform the following Flags
+        * parameter validations:
+        * - Flags D, E, and H MUST NOT be combined with each other.
+        * - Flag N MUST NOT be combined with the O flag.
+        * - Flag R MUST NOT be combined with the S flag.
+        * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
+        * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or 
H.
+        * - Flag P MUST NOT be set when the SiteName parameter is provided.
+        * The server MUST return ERROR_INVALID_FLAGS for any of the previously
+        * mentioned conflicting combinations.
+        * ...
+        */
+
+       dc_level = dsdb_dc_functional_level(sam_ctx);
+       valid_flags = DSGETDC_VALID_FLAGS;
+       if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
+               valid_flags |= DS_DIRECTORY_SERVICE_8_REQUIRED;
+       }
+       if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
+               valid_flags |= DS_DIRECTORY_SERVICE_9_REQUIRED;
+       }
+       if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
+               valid_flags |= DS_DIRECTORY_SERVICE_10_REQUIRED;
+       }
+       if (r->in.flags & ~valid_flags) {
+               /*
+                * TODO: add tests to prove this (maybe based on the
+                * msDS-Behavior-Version levels of dc, domain and/or forest
+                */
                return WERR_INVALID_FLAGS;
        }
 
-       if (r->in.flags & DS_GC_SERVER_REQUIRED &&
-           r->in.flags & DS_PDC_REQUIRED &&
-           r->in.flags & DS_KDC_REQUIRED) {
+       /* Flags D, E, and H MUST NOT be combined with each other. */
+#define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
+       if (multiple_bits_set(r->in.flags & _DEH)) {
                return WERR_INVALID_FLAGS;
        }
+
+       /* Flag N MUST NOT be combined with the O flag. */
        if (r->in.flags & DS_IS_FLAT_NAME &&
            r->in.flags & DS_IS_DNS_NAME) {
                return WERR_INVALID_FLAGS;
        }
+
+       /* Flag R MUST NOT be combined with the S flag. */
        if (r->in.flags & DS_RETURN_DNS_NAME &&
            r->in.flags & DS_RETURN_FLAT_NAME) {
                return WERR_INVALID_FLAGS;
        }
-       if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
-           r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
+
+       /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
+#define _BQUVW ( \
+       DS_DIRECTORY_SERVICE_REQUIRED | \
+       DS_DIRECTORY_SERVICE_6_REQUIRED | \
+       DS_DIRECTORY_SERVICE_8_REQUIRED | \
+       DS_DIRECTORY_SERVICE_9_REQUIRED | \
+       DS_DIRECTORY_SERVICE_10_REQUIRED | \
+0)
+       if (multiple_bits_set(r->in.flags & _BQUVW)) {
                return WERR_INVALID_FLAGS;
        }
 
+       /*
+        * Flag K MUST NOT be combined with any of the flags:
+        * B, C, D, E, or H.
+        */
        if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
            r->in.flags &
            (DS_DIRECTORY_SERVICE_REQUIRED |
@@ -3066,6 +3165,7 @@ static WERROR dcesrv_netr_DsRGetDCName_base_call(struct 
dcesrv_netr_DsRGetDCName
                return WERR_INVALID_FLAGS;
        }
 
+       /* Flag P MUST NOT be set when the SiteName parameter is provided. */
        if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
            r->in.site_name) {
                return WERR_INVALID_FLAGS;


-- 
Samba Shared Repository

Reply via email to