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