diff --git a/SOURCES/CVE-2022-38023-for-s3-v4-16.patch b/SOURCES/CVE-2022-38023-for-s3-v4-16.patch new file mode 100644 index 0000000..904db99 --- /dev/null +++ b/SOURCES/CVE-2022-38023-for-s3-v4-16.patch @@ -0,0 +1,2413 @@ +From f7c26ead133ab9b67c6802a2303a22fd98e3c41a Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Wed, 21 Dec 2022 15:53:04 +0100 +Subject: [PATCH 1/9] CVE-2022-38023 s3:rpc_server/netlogon: 'server schannel + != yes' warning to dcesrv_interface_netlogon_bind + +Follow s4 netlogon server changes and move the checks to the RPC bind +hook. Next commits will remove the s3 netr_creds_server_step_check() +function. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit 8141eae47aad849741beb138fae866c772e4ec4c) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 39 +++++++++++++++------ + 1 file changed, 28 insertions(+), 11 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 5906464a9f3..a3853d482df 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1081,7 +1081,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + uint16_t opnum = dce_call->pkt.u.request.opnum; + const char *opname = ""; +- static bool warned_global_once = false; + + if (creds_out != NULL) { + *creds_out = NULL; +@@ -1143,16 +1142,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + return NT_STATUS_ACCESS_DENIED; + } + +- if (!schannel_global_required && !warned_global_once) { +- /* +- * We want admins to notice their misconfiguration! +- */ +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "Please configure 'server schannel = yes', " +- "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); +- warned_global_once = true; +- } +- + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) WITH schannel from " +@@ -2997,5 +2986,33 @@ NTSTATUS _netr_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p, + return NT_STATUS_NOT_IMPLEMENTED; + } + ++/* ++ * Define the bind function that will be used by ndr_netlogon_scompat.c, ++ * included at the bottom of this file. ++ */ ++#define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \ ++ dcesrv_interface_netlogon_bind(context, iface) ++ ++static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context, ++ const struct dcesrv_interface *iface) ++{ ++ struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; ++ int schannel = lpcfg_server_schannel(lp_ctx); ++ bool schannel_global_required = (schannel == true); ++ static bool warned_global_schannel_once = false; ++ ++ if (!schannel_global_required && !warned_global_schannel_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2020-1472(ZeroLogon): " ++ "Please configure 'server schannel = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); ++ warned_global_schannel_once = true; ++ } ++ ++ return NT_STATUS_OK; ++} ++ + /* include the generated boilerplate */ + #include "librpc/gen_ndr/ndr_netlogon_scompat.c" +-- +2.39.0 + + +From 1790cc254c10dfc0deb5ff84ff18a5f24bfd3f44 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 16:46:15 +0100 +Subject: [PATCH 2/9] CVE-2022-38023 selftest:Samba3: avoid global 'server + schannel = auto' + +Instead of using the generic deprecated option use the specific +server require schannel:COMPUTERACCOUNT = no in order to allow +legacy tests for pass. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit 3cd18690f83d2f85e847fc703ac127b4b04189fc) +--- + selftest/target/Samba3.pm | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index 0b720a68927..b58f3d45118 100755 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -271,9 +271,23 @@ sub setup_nt4_dc + lanman auth = yes + ntlm auth = yes + raw NTLMv2 auth = yes +- server schannel = auto + rpc start on demand helpers = false + ++ CVE_2020_1472:warn_about_unused_debug_level = 3 ++ server require schannel:schannel0\$ = no ++ server require schannel:schannel1\$ = no ++ server require schannel:schannel2\$ = no ++ server require schannel:schannel3\$ = no ++ server require schannel:schannel4\$ = no ++ server require schannel:schannel5\$ = no ++ server require schannel:schannel6\$ = no ++ server require schannel:schannel7\$ = no ++ server require schannel:schannel8\$ = no ++ server require schannel:schannel9\$ = no ++ server require schannel:schannel10\$ = no ++ server require schannel:schannel11\$ = no ++ server require schannel:torturetest\$ = no ++ + fss: sequence timeout = 1 + check parent directory delete on close = yes + "; +-- +2.39.0 + + +From 0e7e7ddbf5524b8aec595227a04cb09599c61a81 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 5 Jan 2023 18:13:09 +0100 +Subject: [PATCH 3/9] CVE-2022-38023 s4:rpc_server:wscript: Reformat following + pycodestyle + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit d9e6b490db3ead7e79bb3ff0c1f9ef8ab8bdc65b) +--- + source4/rpc_server/wscript_build | 290 ++++++++++++++++++------------- + 1 file changed, 168 insertions(+), 122 deletions(-) + +diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build +index 8c756721232..e7bb773d719 100644 +--- a/source4/rpc_server/wscript_build ++++ b/source4/rpc_server/wscript_build +@@ -1,174 +1,220 @@ + #!/usr/bin/env python + + bld.SAMBA_SUBSYSTEM('DCERPC_SHARE', +- source='common/share_info.c', +- autoproto='common/share.h', +- deps='ldb share', +- enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER'), +- ) ++ source='common/share_info.c', ++ autoproto='common/share.h', ++ deps='ldb share', ++ enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER'), ++ ) + + bld.SAMBA_SUBSYSTEM('DCERPC_COMMON', +- source='common/server_info.c common/forward.c common/loadparm.c', +- autoproto='common/proto.h', +- deps='ldb DCERPC_SHARE', +- enabled=bld.AD_DC_BUILD_IS_ENABLED() +- ) ++ source=''' ++ common/server_info.c ++ common/forward.c ++ common/loadparm.c ++ ''', ++ autoproto='common/proto.h', ++ deps='ldb DCERPC_SHARE', ++ enabled=bld.AD_DC_BUILD_IS_ENABLED() ++ ) + + bld.SAMBA_LIBRARY('dcerpc_server', +- source='dcerpc_server.c', +- pc_files='dcerpc_server.pc', +- deps='LIBCLI_AUTH ndr samba_server_gensec service auth', +- public_deps='dcerpc dcerpc-server-core', +- autoproto='dcerpc_server_proto.h', +- public_headers='dcerpc_server.h', +- vnum='0.0.1', +- enabled=bld.AD_DC_BUILD_IS_ENABLED() +- ) ++ source='dcerpc_server.c', ++ pc_files='dcerpc_server.pc', ++ deps='LIBCLI_AUTH ndr samba_server_gensec service auth', ++ public_deps='dcerpc dcerpc-server-core', ++ autoproto='dcerpc_server_proto.h', ++ public_headers='dcerpc_server.h', ++ vnum='0.0.1', ++ enabled=bld.AD_DC_BUILD_IS_ENABLED() ++ ) + + bld.SAMBA_MODULE('dcerpc_rpcecho', +- source='echo/rpc_echo.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_rpcecho_init', +- deps='ndr-standard events' +- ) ++ source='echo/rpc_echo.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_rpcecho_init', ++ deps='ndr-standard events' ++ ) + + + bld.SAMBA_MODULE('dcerpc_epmapper', +- source='epmapper/rpc_epmapper.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_epmapper_init', +- deps='NDR_EPMAPPER' +- ) ++ source='epmapper/rpc_epmapper.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_epmapper_init', ++ deps='NDR_EPMAPPER' ++ ) + + + bld.SAMBA_MODULE('dcerpc_remote', +- source='remote/dcesrv_remote.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_remote_init', +- deps='LIBCLI_SMB ndr-table' +- ) ++ source='remote/dcesrv_remote.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_remote_init', ++ deps='LIBCLI_SMB ndr-table' ++ ) + + + bld.SAMBA_MODULE('dcerpc_srvsvc', +- source='srvsvc/dcesrv_srvsvc.c srvsvc/srvsvc_ntvfs.c', +- autoproto='srvsvc/proto.h', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_srvsvc_init', +- deps='DCERPC_COMMON NDR_SRVSVC share ntvfs', +- enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER') +- ) ++ source='srvsvc/dcesrv_srvsvc.c srvsvc/srvsvc_ntvfs.c', ++ autoproto='srvsvc/proto.h', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_srvsvc_init', ++ deps='DCERPC_COMMON NDR_SRVSVC share ntvfs', ++ enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER') ++ ) + + + bld.SAMBA_MODULE('dcerpc_wkssvc', +- source='wkssvc/dcesrv_wkssvc.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_wkssvc_init', +- deps='DCERPC_COMMON ndr-standard' +- ) ++ source='wkssvc/dcesrv_wkssvc.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_wkssvc_init', ++ deps='DCERPC_COMMON ndr-standard' ++ ) + + + bld.SAMBA_MODULE('dcerpc_unixinfo', +- source='unixinfo/dcesrv_unixinfo.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_unixinfo_init', +- deps='DCERPC_COMMON samdb NDR_UNIXINFO LIBWBCLIENT_OLD' +- ) ++ source='unixinfo/dcesrv_unixinfo.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_unixinfo_init', ++ deps='DCERPC_COMMON samdb NDR_UNIXINFO LIBWBCLIENT_OLD' ++ ) + + + bld.SAMBA_MODULE('dcesrv_samr', +- source='samr/dcesrv_samr.c samr/samr_password.c', +- autoproto='samr/proto.h', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_samr_init', +- deps='samdb DCERPC_COMMON ndr-standard auth4_sam GNUTLS_HELPERS DCERPC_HELPER' +- ) ++ source='samr/dcesrv_samr.c samr/samr_password.c', ++ autoproto='samr/proto.h', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_samr_init', ++ deps=''' ++ samdb ++ DCERPC_COMMON ++ ndr-standard ++ auth4_sam ++ GNUTLS_HELPERS ++ DCERPC_HELPER ++ ''' ++ ) + + + bld.SAMBA_MODULE('dcerpc_winreg', +- source='winreg/rpc_winreg.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_winreg_init', +- deps='registry ndr-standard', +- internal_module=True, +- enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER') +- ) ++ source='winreg/rpc_winreg.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_winreg_init', ++ deps='registry ndr-standard', ++ internal_module=True, ++ enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER') ++ ) + + + bld.SAMBA_MODULE('dcerpc_netlogon', +- source='netlogon/dcerpc_netlogon.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_netlogon_init', +- deps='''DCERPC_COMMON RPC_NDR_IRPC COMMON_SCHANNEL ndr-standard auth4_sam samba-hostconfig DSDB_MODULE_HELPERS +- util_str_escape''' +- ) ++ source='netlogon/dcerpc_netlogon.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_netlogon_init', ++ deps=''' ++ DCERPC_COMMON ++ RPC_NDR_IRPC ++ COMMON_SCHANNEL ++ ndr-standard ++ auth4_sam ++ samba-hostconfig ++ DSDB_MODULE_HELPERS ++ util_str_escape ++ ''' ++ ) + + + bld.SAMBA_MODULE('dcerpc_lsarpc', +- source='lsa/dcesrv_lsa.c lsa/lsa_init.c lsa/lsa_lookup.c', +- autoproto='lsa/proto.h', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_lsa_init', +- deps='samdb DCERPC_COMMON ndr-standard LIBCLI_AUTH NDR_DSSETUP com_err samba-security UTIL_LSARPC' +- ) ++ source='lsa/dcesrv_lsa.c lsa/lsa_init.c lsa/lsa_lookup.c', ++ autoproto='lsa/proto.h', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_lsa_init', ++ deps=''' ++ samdb ++ DCERPC_COMMON ++ ndr-standard ++ LIBCLI_AUTH ++ NDR_DSSETUP ++ com_err ++ samba-security ++ UTIL_LSARPC ++ ''' ++ ) + + + bld.SAMBA_MODULE('dcerpc_backupkey', +- source='backupkey/dcesrv_backupkey.c ', +- autoproto='backupkey/proto.h', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_backupkey_init', +- deps='samdb DCERPC_COMMON NDR_BACKUPKEY RPC_NDR_BACKUPKEY gnutls GNUTLS_HELPERS', +- ) ++ source='backupkey/dcesrv_backupkey.c ', ++ autoproto='backupkey/proto.h', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_backupkey_init', ++ deps=''' ++ samdb ++ DCERPC_COMMON ++ NDR_BACKUPKEY ++ RPC_NDR_BACKUPKEY ++ gnutls ++ GNUTLS_HELPERS ++ ''', ++ ) + + + bld.SAMBA_MODULE('dcerpc_drsuapi', +- source='drsuapi/dcesrv_drsuapi.c drsuapi/updaterefs.c drsuapi/getncchanges.c drsuapi/addentry.c drsuapi/writespn.c drsuapi/drsutil.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_drsuapi_init', +- deps='samdb DCERPC_COMMON NDR_DRSUAPI samba-security' +- ) ++ source=''' ++ drsuapi/dcesrv_drsuapi.c ++ drsuapi/updaterefs.c ++ drsuapi/getncchanges.c ++ drsuapi/addentry.c ++ drsuapi/writespn.c ++ drsuapi/drsutil.c ++ ''', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_drsuapi_init', ++ deps='samdb DCERPC_COMMON NDR_DRSUAPI samba-security' ++ ) + + + bld.SAMBA_MODULE('dcerpc_browser', +- source='browser/dcesrv_browser.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_browser_init', +- deps='DCERPC_COMMON NDR_BROWSER' +- ) ++ source='browser/dcesrv_browser.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_browser_init', ++ deps='DCERPC_COMMON NDR_BROWSER' ++ ) + + bld.SAMBA_MODULE('dcerpc_eventlog', +- source='eventlog/dcesrv_eventlog6.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_eventlog6_init', +- deps='DCERPC_COMMON' +- ) ++ source='eventlog/dcesrv_eventlog6.c', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_eventlog6_init', ++ deps='DCERPC_COMMON' ++ ) + + bld.SAMBA_MODULE('dcerpc_dnsserver', +- source='dnsserver/dcerpc_dnsserver.c dnsserver/dnsutils.c dnsserver/dnsdata.c dnsserver/dnsdb.c', +- subsystem='dcerpc_server', +- init_function='dcerpc_server_dnsserver_init', +- deps='DCERPC_COMMON dnsserver_common netif' +- ) ++ source=''' ++ dnsserver/dcerpc_dnsserver.c ++ dnsserver/dnsutils.c ++ dnsserver/dnsdata.c ++ dnsserver/dnsdb.c ++ ''', ++ subsystem='dcerpc_server', ++ init_function='dcerpc_server_dnsserver_init', ++ deps='DCERPC_COMMON dnsserver_common netif' ++ ) + + + bld.SAMBA_MODULE('service_dcerpc', +- source='service_rpc.c', +- autoproto='service_rpc.h', +- subsystem='service', +- init_function='server_service_rpc_init', +- internal_module=False, +- deps='dcerpc_server' +- ) +- +-bld.SAMBA_BINARY( +- 'test_rpc_dns_server_dnsutils', +- source='tests/rpc_dns_server_dnsutils_test.c', +- deps=''' +- dnsserver_common +- dcerpc_server +- cmocka +- talloc +- ''', +- for_selftest=True, +- enabled=bld.AD_DC_BUILD_IS_ENABLED() +-) ++ source='service_rpc.c', ++ autoproto='service_rpc.h', ++ subsystem='service', ++ init_function='server_service_rpc_init', ++ internal_module=False, ++ deps='dcerpc_server' ++ ) ++ ++bld.SAMBA_BINARY('test_rpc_dns_server_dnsutils', ++ source='tests/rpc_dns_server_dnsutils_test.c', ++ deps=''' ++ dnsserver_common ++ dcerpc_server ++ cmocka ++ talloc ++ ''', ++ for_selftest=True, ++ enabled=bld.AD_DC_BUILD_IS_ENABLED() ++ ) +-- +2.39.0 + + +From 740422fb6609dac3b0e2c1bb91d61b87e99c64aa Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 14:03:23 +0100 +Subject: [PATCH 4/9] CVE-2022-38023 s4:rpc_server/netlogon: Move schannel and + credentials check functions to librpc + +Will be used later by s3 netlogon server. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit 121e7b0e39478c5291100652ac92c263f406076b) +--- + librpc/rpc/server/netlogon/schannel_util.c | 576 ++++++++++++++++++ + librpc/rpc/server/netlogon/schannel_util.h | 54 ++ + librpc/wscript_build | 12 + + source4/rpc_server/netlogon/dcerpc_netlogon.c | 546 +---------------- + source4/rpc_server/wscript_build | 2 +- + 5 files changed, 644 insertions(+), 546 deletions(-) + create mode 100644 librpc/rpc/server/netlogon/schannel_util.c + create mode 100644 librpc/rpc/server/netlogon/schannel_util.h + +diff --git a/librpc/rpc/server/netlogon/schannel_util.c b/librpc/rpc/server/netlogon/schannel_util.c +new file mode 100644 +index 00000000000..9b2a88a2628 +--- /dev/null ++++ b/librpc/rpc/server/netlogon/schannel_util.c +@@ -0,0 +1,576 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ netlogon schannel utility functions ++ ++ Copyright (C) Andrew Bartlett 2004-2008 ++ Copyright (C) Stefan Metzmacher 2005 ++ Copyright (C) Matthias Dieter Wallnöfer 2009-2010 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "includes.h" ++#include "schannel_util.h" ++#include "param/param.h" ++#include "libcli/security/dom_sid.h" ++#include "libcli/auth/schannel.h" ++#include "librpc/rpc/dcesrv_core.h" ++#include "librpc/gen_ndr/ndr_netlogon.h" ++#include "lib/util/util_str_escape.h" ++ ++struct dcesrv_netr_check_schannel_state { ++ struct dom_sid account_sid; ++ enum dcerpc_AuthType auth_type; ++ enum dcerpc_AuthLevel auth_level; ++ ++ bool schannel_global_required; ++ bool schannel_required; ++ bool schannel_explicitly_set; ++ ++ bool seal_global_required; ++ bool seal_required; ++ bool seal_explicitly_set; ++ ++ NTSTATUS result; ++}; ++ ++static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ struct dcesrv_netr_check_schannel_state **_s) ++{ ++ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; ++ int schannel = lpcfg_server_schannel(lp_ctx); ++ bool schannel_global_required = (schannel == true); ++ bool schannel_required = schannel_global_required; ++ const char *explicit_opt = NULL; ++ bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); ++ bool require_seal = global_require_seal; ++ const char *explicit_seal_opt = NULL; ++#define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) ++ struct dcesrv_netr_check_schannel_state *s = NULL; ++ NTSTATUS status; ++ ++ *_s = NULL; ++ ++ s = dcesrv_iface_state_find_conn(dce_call, ++ DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, ++ struct dcesrv_netr_check_schannel_state); ++ if (s != NULL) { ++ if (!dom_sid_equal(&s->account_sid, creds->sid)) { ++ goto new_state; ++ } ++ if (s->auth_type != auth_type) { ++ goto new_state; ++ } ++ if (s->auth_level != auth_level) { ++ goto new_state; ++ } ++ ++ *_s = s; ++ return NT_STATUS_OK; ++ } ++ ++new_state: ++ TALLOC_FREE(s); ++ s = talloc_zero(dce_call, ++ struct dcesrv_netr_check_schannel_state); ++ if (s == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ s->account_sid = *creds->sid; ++ s->auth_type = auth_type; ++ s->auth_level = auth_level; ++ s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; ++ ++ /* ++ * We don't use lpcfg_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ explicit_seal_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "server schannel require seal", ++ creds->account_name); ++ if (explicit_seal_opt != NULL) { ++ require_seal = lp_bool(explicit_seal_opt); ++ } ++ ++ /* ++ * We don't use lpcfg_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ explicit_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "server require schannel", ++ creds->account_name); ++ if (explicit_opt != NULL) { ++ schannel_required = lp_bool(explicit_opt); ++ } ++ ++ s->schannel_global_required = schannel_global_required; ++ s->schannel_required = schannel_required; ++ s->schannel_explicitly_set = explicit_opt != NULL; ++ ++ s->seal_global_required = global_require_seal; ++ s->seal_required = require_seal; ++ s->seal_explicitly_set = explicit_seal_opt != NULL; ++ ++ status = dcesrv_iface_state_store_conn(dce_call, ++ DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, ++ s); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ *_s = s; ++ return NT_STATUS_OK; ++} ++ ++static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call, ++ struct dcesrv_netr_check_schannel_state *s, ++ const struct netlogon_creds_CredentialState *creds, ++ uint16_t opnum) ++{ ++ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; ++ int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); ++ int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); ++ int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); ++ int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); ++ TALLOC_CTX *frame = talloc_stackframe(); ++ unsigned int dbg_lvl = DBGLVL_DEBUG; ++ const char *opname = ""; ++ const char *reason = ""; ++ ++ if (opnum < ndr_table_netlogon.num_calls) { ++ opname = ndr_table_netlogon.calls[opnum].name; ++ } ++ ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { ++ reason = "WITH SEALED"; ++ } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { ++ reason = "WITH SIGNED"; ++ } else { ++ reason = "WITH INVALID"; ++ dbg_lvl = DBGLVL_ERR; ++ s->result = NT_STATUS_INTERNAL_ERROR; ++ } ++ } else { ++ reason = "WITHOUT"; ++ } ++ ++ if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) { ++ if (!NT_STATUS_IS_OK(s->result)) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && ++ s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) ++ { ++ s->result = NT_STATUS_OK; ++ ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); ++ } else if (!s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); ++ } else if (!s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Option 'server require schannel:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ if (s->seal_explicitly_set && !s->seal_required) { ++ DEBUG(CVE_2022_38023_warn_level, ( ++ "CVE-2022-38023: " ++ "Option 'server schannel require seal:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (s->seal_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; ++ ++ if (s->seal_explicitly_set) { ++ dbg_lvl = DBGLVL_NOTICE; ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "from client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->seal_explicitly_set) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = no' " ++ "not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ s->result = NT_STATUS_OK; ++ ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); ++ } else if (!s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } else if (!s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Option 'server require schannel:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ D_INFO("CVE-2022-38023: " ++ "Option 'server schannel require seal:%s = no' still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else if (!s->seal_required) { ++ /* ++ * admins should set ++ * server schannel require seal:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: " ++ "Please use 'server schannel require seal:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->seal_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; ++ ++ if (s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ if (!s->schannel_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } else if (s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "from client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->seal_explicitly_set) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ if (!s->schannel_explicitly_set) { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): Check if option " ++ "'server require schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } else if (s->schannel_required) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server require schannel:%s = yes' " ++ "also rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->schannel_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; ++ ++ if (s->schannel_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } ++ if (!s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->schannel_explicitly_set) { ++ D_NOTICE("CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): Check if option " ++ "'server require schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ if (!s->seal_explicitly_set) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ s->result = NT_STATUS_OK; ++ ++ if (s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ ++ if (s->schannel_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ ++ if (s->seal_explicitly_set) { ++ D_INFO("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = no' " ++ "still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else { ++ /* ++ * admins should set ++ * server schannel require seal:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Please use " ++ "'server schannel require seal:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ if (s->schannel_explicitly_set) { ++ D_INFO("CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = no' " ++ "still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else { ++ /* ++ * admins should set ++ * server require schannel:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Please use 'server require schannel:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ TALLOC_FREE(frame); ++ return s->result; ++} ++ ++NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ uint16_t opnum) ++{ ++ struct dcesrv_netr_check_schannel_state *s = NULL; ++ NTSTATUS status; ++ ++ status = dcesrv_netr_check_schannel_get_state(dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ &s); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ ++/* ++ * NOTE: The following functions are nearly identical to the ones available in ++ * source3/rpc_server/srv_nelog_nt.c ++ * The reason we keep 2 copies is that they use different structures to ++ * represent the auth_info and the decrpc pipes. ++ */ ++NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, ++ TALLOC_CTX *mem_ctx, ++ const char *computer_name, ++ struct netr_Authenticator *received_authenticator, ++ struct netr_Authenticator *return_authenticator, ++ struct netlogon_creds_CredentialState **creds_out) ++{ ++ NTSTATUS nt_status; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; ++ ++ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); ++ ++ nt_status = schannel_check_creds_state(mem_ctx, ++ dce_call->conn->dce_ctx->lp_ctx, ++ computer_name, ++ received_authenticator, ++ return_authenticator, ++ &creds); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ ZERO_STRUCTP(return_authenticator); ++ return nt_status; ++ } ++ ++ nt_status = dcesrv_netr_check_schannel(dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ dce_call->pkt.u.request.opnum); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ TALLOC_FREE(creds); ++ ZERO_STRUCTP(return_authenticator); ++ return nt_status; ++ } ++ ++ *creds_out = creds; ++ return NT_STATUS_OK; ++} +diff --git a/librpc/rpc/server/netlogon/schannel_util.h b/librpc/rpc/server/netlogon/schannel_util.h +new file mode 100644 +index 00000000000..561e2567e02 +--- /dev/null ++++ b/librpc/rpc/server/netlogon/schannel_util.h +@@ -0,0 +1,54 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ netlogon schannel utility functions ++ ++ Copyright (C) Andrew Bartlett 2004-2008 ++ Copyright (C) Stefan Metzmacher 2005 ++ Copyright (C) Matthias Dieter Wallnöfer 2009-2010 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#ifndef __LIBRPC_RPC_SERVER_NETLOGON_SCHANNEL_UTIL_H__ ++#define __LIBRPC_RPC_SERVER_NETLOGON_SCHANNEL_UTIL_H__ ++ ++#include "replace.h" ++#include ++#include "libcli/util/ntstatus.h" ++ ++#define NETLOGON_SERVER_PIPE_STATE_MAGIC 0x4f555358 ++ ++struct dcesrv_call_state; ++struct netlogon_creds_CredentialState; ++struct netr_Authenticator; ++enum dcerpc_AuthType; ++enum dcerpc_AuthLevel; ++ ++NTSTATUS dcesrv_netr_check_schannel( ++ struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ uint16_t opnum); ++ ++NTSTATUS dcesrv_netr_creds_server_step_check( ++ struct dcesrv_call_state *dce_call, ++ TALLOC_CTX *mem_ctx, ++ const char *computer_name, ++ struct netr_Authenticator *received_authenticator, ++ struct netr_Authenticator *return_authenticator, ++ struct netlogon_creds_CredentialState **creds_out); ++ ++#endif /* __LIBRPC_RPC_SERVER_NETLOGON_SCHANNEL_UTIL_H__ */ +diff --git a/librpc/wscript_build b/librpc/wscript_build +index b82209b4299..f22ab2eabae 100644 +--- a/librpc/wscript_build ++++ b/librpc/wscript_build +@@ -678,6 +678,18 @@ bld.SAMBA_LIBRARY('dcerpc-pkt-auth', + ''', + deps='dcerpc-binding gensec') + ++bld.SAMBA_SUBSYSTEM('DCERPC_SERVER_NETLOGON', ++ source=''' ++ rpc/server/netlogon/schannel_util.c ++ ''', ++ deps=''' ++ talloc ++ util_str_escape ++ samba-hostconfig ++ NDR_NETLOGON ++ dcerpc-server-core ++ ''') ++ + bld.SAMBA_LIBRARY('dcerpc-server-core', + source=''' + rpc/dcesrv_core.c +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index ddcb8487a56..6a3e044eb9d 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -42,6 +42,7 @@ + #include "librpc/gen_ndr/ndr_irpc.h" + #include "librpc/gen_ndr/ndr_winbind.h" + #include "librpc/gen_ndr/ndr_winbind_c.h" ++#include "librpc/rpc/server/netlogon/schannel_util.h" + #include "lib/socket/netif.h" + #include "lib/util/util_str_escape.h" + #include "lib/param/loadparm.h" +@@ -889,551 +890,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca + return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); + } + +-struct dcesrv_netr_check_schannel_state { +- struct dom_sid account_sid; +- enum dcerpc_AuthType auth_type; +- enum dcerpc_AuthLevel auth_level; +- +- bool schannel_global_required; +- bool schannel_required; +- bool schannel_explicitly_set; +- +- bool seal_global_required; +- bool seal_required; +- bool seal_explicitly_set; +- +- NTSTATUS result; +-}; +- +-static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call, +- const struct netlogon_creds_CredentialState *creds, +- enum dcerpc_AuthType auth_type, +- enum dcerpc_AuthLevel auth_level, +- struct dcesrv_netr_check_schannel_state **_s) +-{ +- struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; +- int schannel = lpcfg_server_schannel(lp_ctx); +- bool schannel_global_required = (schannel == true); +- bool schannel_required = schannel_global_required; +- const char *explicit_opt = NULL; +- bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); +- bool require_seal = global_require_seal; +- const char *explicit_seal_opt = NULL; +-#define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) +- struct dcesrv_netr_check_schannel_state *s = NULL; +- NTSTATUS status; +- +- *_s = NULL; +- +- s = dcesrv_iface_state_find_conn(dce_call, +- DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, +- struct dcesrv_netr_check_schannel_state); +- if (s != NULL) { +- if (!dom_sid_equal(&s->account_sid, creds->sid)) { +- goto new_state; +- } +- if (s->auth_type != auth_type) { +- goto new_state; +- } +- if (s->auth_level != auth_level) { +- goto new_state; +- } +- +- *_s = s; +- return NT_STATUS_OK; +- } +- +-new_state: +- TALLOC_FREE(s); +- s = talloc_zero(dce_call, +- struct dcesrv_netr_check_schannel_state); +- if (s == NULL) { +- return NT_STATUS_NO_MEMORY; +- } +- +- s->account_sid = *creds->sid; +- s->auth_type = auth_type; +- s->auth_level = auth_level; +- s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; +- +- /* +- * We don't use lpcfg_parm_bool(), as we +- * need the explicit_opt pointer in order to +- * adjust the debug messages. +- */ +- explicit_seal_opt = lpcfg_get_parametric(lp_ctx, +- NULL, +- "server schannel require seal", +- creds->account_name); +- if (explicit_seal_opt != NULL) { +- require_seal = lp_bool(explicit_seal_opt); +- } +- +- /* +- * We don't use lpcfg_parm_bool(), as we +- * need the explicit_opt pointer in order to +- * adjust the debug messages. +- */ +- explicit_opt = lpcfg_get_parametric(lp_ctx, +- NULL, +- "server require schannel", +- creds->account_name); +- if (explicit_opt != NULL) { +- schannel_required = lp_bool(explicit_opt); +- } +- +- s->schannel_global_required = schannel_global_required; +- s->schannel_required = schannel_required; +- s->schannel_explicitly_set = explicit_opt != NULL; +- +- s->seal_global_required = global_require_seal; +- s->seal_required = require_seal; +- s->seal_explicitly_set = explicit_seal_opt != NULL; +- +- status = dcesrv_iface_state_store_conn(dce_call, +- DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, +- s); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- *_s = s; +- return NT_STATUS_OK; +-} +- +-static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call, +- struct dcesrv_netr_check_schannel_state *s, +- const struct netlogon_creds_CredentialState *creds, +- uint16_t opnum) +-{ +- struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; +- int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, +- "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); +- int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, +- "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); +- int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, +- "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); +- int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, +- "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); +- TALLOC_CTX *frame = talloc_stackframe(); +- unsigned int dbg_lvl = DBGLVL_DEBUG; +- const char *opname = ""; +- const char *reason = ""; +- +- if (opnum < ndr_table_netlogon.num_calls) { +- opname = ndr_table_netlogon.calls[opnum].name; +- } +- +- if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { +- reason = "WITH SEALED"; +- } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { +- reason = "WITH SIGNED"; +- } else { +- reason = "WITH INVALID"; +- dbg_lvl = DBGLVL_ERR; +- s->result = NT_STATUS_INTERNAL_ERROR; +- } +- } else { +- reason = "WITHOUT"; +- } +- +- if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) { +- if (!NT_STATUS_IS_OK(s->result)) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- TALLOC_FREE(frame); +- return s->result; +- } +- +- if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && +- s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) +- { +- s->result = NT_STATUS_OK; +- +- if (s->schannel_explicitly_set && !s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); +- } else if (!s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } +- if (s->seal_explicitly_set && !s->seal_required) { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); +- } else if (!s->seal_required) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- +- if (s->schannel_explicitly_set && !s->schannel_required) { +- DEBUG(CVE_2020_1472_warn_level, ( +- "CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' not needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- +- if (s->seal_explicitly_set && !s->seal_required) { +- DEBUG(CVE_2022_38023_warn_level, ( +- "CVE-2022-38023: " +- "Option 'server schannel require seal:%s = no' not needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- +- TALLOC_FREE(frame); +- return s->result; +- } +- +- if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- if (s->seal_required) { +- s->result = NT_STATUS_ACCESS_DENIED; +- +- if (s->seal_explicitly_set) { +- dbg_lvl = DBGLVL_NOTICE; +- } else { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); +- } +- if (s->schannel_explicitly_set && !s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "from client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- if (s->seal_explicitly_set) { +- D_NOTICE("CVE-2022-38023: Option " +- "'server schannel require seal:%s = yes' " +- "rejects access for client.\n", +- log_escape(frame, creds->account_name)); +- } else { +- DEBUG(CVE_2020_1472_error_level, ( +- "CVE-2022-38023: Check if option " +- "'server schannel require seal:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name))); +- } +- if (s->schannel_explicitly_set && !s->schannel_required) { +- DEBUG(CVE_2020_1472_warn_level, ( +- "CVE-2020-1472(ZeroLogon): Option " +- "'server require schannel:%s = no' " +- "not needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- TALLOC_FREE(frame); +- return s->result; +- } +- +- s->result = NT_STATUS_OK; +- +- if (s->schannel_explicitly_set && !s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); +- } else if (!s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } +- if (s->seal_explicitly_set && !s->seal_required) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } else if (!s->seal_required) { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) %s schannel from " +- "client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- if (s->schannel_explicitly_set && !s->schannel_required) { +- DEBUG(CVE_2020_1472_warn_level, ( +- "CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' not needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- if (s->seal_explicitly_set && !s->seal_required) { +- D_INFO("CVE-2022-38023: " +- "Option 'server schannel require seal:%s = no' still needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- } else if (!s->seal_required) { +- /* +- * admins should set +- * server schannel require seal:COMPUTER$ = no +- * in order to avoid the level 0 messages. +- * Over time they can switch the global value +- * to be strict. +- */ +- DEBUG(CVE_2022_38023_error_level, ( +- "CVE-2022-38023: " +- "Please use 'server schannel require seal:%s = no' " +- "for '%s' to avoid this warning!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- +- TALLOC_FREE(frame); +- return s->result; +- } +- +- if (s->seal_required) { +- s->result = NT_STATUS_ACCESS_DENIED; +- +- if (s->seal_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); +- } else { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); +- } +- if (!s->schannel_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); +- } else if (s->schannel_required) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "from client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- if (s->seal_explicitly_set) { +- D_NOTICE("CVE-2022-38023: Option " +- "'server schannel require seal:%s = yes' " +- "rejects access for client.\n", +- log_escape(frame, creds->account_name)); +- } else { +- DEBUG(CVE_2022_38023_error_level, ( +- "CVE-2022-38023: Check if option " +- "'server schannel require seal:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name))); +- } +- if (!s->schannel_explicitly_set) { +- DEBUG(CVE_2020_1472_error_level, ( +- "CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name))); +- } else if (s->schannel_required) { +- D_NOTICE("CVE-2022-38023: Option " +- "'server require schannel:%s = yes' " +- "also rejects access for client.\n", +- log_escape(frame, creds->account_name)); +- } +- TALLOC_FREE(frame); +- return s->result; +- } +- +- if (s->schannel_required) { +- s->result = NT_STATUS_ACCESS_DENIED; +- +- if (s->schannel_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); +- } else { +- dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); +- } +- if (!s->seal_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- if (s->schannel_explicitly_set) { +- D_NOTICE("CVE-2020-1472(ZeroLogon): Option " +- "'server require schannel:%s = yes' " +- "rejects access for client.\n", +- log_escape(frame, creds->account_name)); +- } else { +- DEBUG(CVE_2020_1472_error_level, ( +- "CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name))); +- } +- if (!s->seal_explicitly_set) { +- DEBUG(CVE_2022_38023_error_level, ( +- "CVE-2022-38023: Check if option " +- "'server schannel require seal:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name))); +- } +- TALLOC_FREE(frame); +- return s->result; +- } +- +- s->result = NT_STATUS_OK; +- +- if (s->seal_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } else { +- dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); +- } +- +- if (s->schannel_explicitly_set) { +- dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); +- } else { +- dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); +- } +- +- DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +- "%s request (opnum[%u]) %s schannel from " +- "client_account[%s] client_computer_name[%s] %s\n", +- opname, opnum, reason, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name), +- nt_errstr(s->result))); +- +- if (s->seal_explicitly_set) { +- D_INFO("CVE-2022-38023: Option " +- "'server schannel require seal:%s = no' " +- "still needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- } else { +- /* +- * admins should set +- * server schannel require seal:COMPUTER$ = no +- * in order to avoid the level 0 messages. +- * Over time they can switch the global value +- * to be strict. +- */ +- DEBUG(CVE_2022_38023_error_level, ( +- "CVE-2022-38023: Please use " +- "'server schannel require seal:%s = no' " +- "for '%s' to avoid this warning!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- +- if (s->schannel_explicitly_set) { +- D_INFO("CVE-2020-1472(ZeroLogon): Option " +- "'server require schannel:%s = no' " +- "still needed for '%s'!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- } else { +- /* +- * admins should set +- * server require schannel:COMPUTER$ = no +- * in order to avoid the level 0 messages. +- * Over time they can switch the global value +- * to be strict. +- */ +- DEBUG(CVE_2020_1472_error_level, ( +- "CVE-2020-1472(ZeroLogon): " +- "Please use 'server require schannel:%s = no' " +- "for '%s' to avoid this warning!\n", +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name))); +- } +- +- TALLOC_FREE(frame); +- return s->result; +-} +- +-static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, +- const struct netlogon_creds_CredentialState *creds, +- enum dcerpc_AuthType auth_type, +- enum dcerpc_AuthLevel auth_level, +- uint16_t opnum) +-{ +- struct dcesrv_netr_check_schannel_state *s = NULL; +- NTSTATUS status; +- +- status = dcesrv_netr_check_schannel_get_state(dce_call, +- creds, +- auth_type, +- auth_level, +- &s); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum); +- if (!NT_STATUS_IS_OK(status)) { +- return status; +- } +- +- return NT_STATUS_OK; +-} +- +-/* +- * NOTE: The following functions are nearly identical to the ones available in +- * source3/rpc_server/srv_nelog_nt.c +- * The reason we keep 2 copies is that they use different structures to +- * represent the auth_info and the decrpc pipes. +- */ +-static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, +- TALLOC_CTX *mem_ctx, +- const char *computer_name, +- struct netr_Authenticator *received_authenticator, +- struct netr_Authenticator *return_authenticator, +- struct netlogon_creds_CredentialState **creds_out) +-{ +- NTSTATUS nt_status; +- struct netlogon_creds_CredentialState *creds = NULL; +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; +- enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; +- +- dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); +- +- nt_status = schannel_check_creds_state(mem_ctx, +- dce_call->conn->dce_ctx->lp_ctx, +- computer_name, +- received_authenticator, +- return_authenticator, +- &creds); +- if (!NT_STATUS_IS_OK(nt_status)) { +- ZERO_STRUCTP(return_authenticator); +- return nt_status; +- } +- +- nt_status = dcesrv_netr_check_schannel(dce_call, +- creds, +- auth_type, +- auth_level, +- dce_call->pkt.u.request.opnum); +- if (!NT_STATUS_IS_OK(nt_status)) { +- TALLOC_FREE(creds); +- ZERO_STRUCTP(return_authenticator); +- return nt_status; +- } +- +- *creds_out = creds; +- return NT_STATUS_OK; +-} +- + /* + Change the machine account password for the currently connected + client. Supplies only the NT#. +diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build +index e7bb773d719..0e44a3c2bae 100644 +--- a/source4/rpc_server/wscript_build ++++ b/source4/rpc_server/wscript_build +@@ -118,10 +118,10 @@ bld.SAMBA_MODULE('dcerpc_netlogon', + samba-hostconfig + DSDB_MODULE_HELPERS + util_str_escape ++ DCERPC_SERVER_NETLOGON + ''' + ) + +- + bld.SAMBA_MODULE('dcerpc_lsarpc', + source='lsa/dcesrv_lsa.c lsa/lsa_init.c lsa/lsa_lookup.c', + autoproto='lsa/proto.h', +-- +2.39.0 + + +From 1a1f5c53c217b5336464885a70e7eef94dd0ad5f Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 16:30:26 +0100 +Subject: [PATCH 5/9] CVE-2022-38023 s3:rpc_server/netlogon: Use + dcesrv_netr_creds_server_step_check() + +After s3 and s4 rpc servers merge we can avoid duplicated code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit 25300d354c80995997d552581cd91dddaf4bbf48) +--- + librpc/rpc/server/netlogon/schannel_util.c | 6 - + selftest/target/Samba3.pm | 14 ++ + source3/rpc_server/netlogon/srv_netlog_nt.c | 201 +++++--------------- + source3/rpc_server/wscript_build | 2 +- + 4 files changed, 58 insertions(+), 165 deletions(-) + +diff --git a/librpc/rpc/server/netlogon/schannel_util.c b/librpc/rpc/server/netlogon/schannel_util.c +index 9b2a88a2628..b14497b13ce 100644 +--- a/librpc/rpc/server/netlogon/schannel_util.c ++++ b/librpc/rpc/server/netlogon/schannel_util.c +@@ -529,12 +529,6 @@ NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + return NT_STATUS_OK; + } + +-/* +- * NOTE: The following functions are nearly identical to the ones available in +- * source3/rpc_server/srv_nelog_nt.c +- * The reason we keep 2 copies is that they use different structures to +- * represent the auth_info and the decrpc pipes. +- */ + NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + const char *computer_name, +diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index b58f3d45118..75256db675c 100755 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -288,6 +288,20 @@ sub setup_nt4_dc + server require schannel:schannel11\$ = no + server require schannel:torturetest\$ = no + ++ server schannel require seal:schannel0\$ = no ++ server schannel require seal:schannel1\$ = no ++ server schannel require seal:schannel2\$ = no ++ server schannel require seal:schannel3\$ = no ++ server schannel require seal:schannel4\$ = no ++ server schannel require seal:schannel5\$ = no ++ server schannel require seal:schannel6\$ = no ++ server schannel require seal:schannel7\$ = no ++ server schannel require seal:schannel8\$ = no ++ server schannel require seal:schannel9\$ = no ++ server schannel require seal:schannel10\$ = no ++ server schannel require seal:schannel11\$ = no ++ server schannel require seal:torturetest\$ = no ++ + fss: sequence timeout = 1 + check parent directory delete on close = yes + "; +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index a3853d482df..8e0ea522b6d 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -51,6 +51,7 @@ + #include "libsmb/dsgetdcname.h" + #include "lib/util/util_str_escape.h" + #include "source3/lib/substitute.h" ++#include "librpc/rpc/server/netlogon/schannel_util.h" + + extern userdom_struct current_user_info; + +@@ -1061,129 +1062,6 @@ NTSTATUS _netr_ServerAuthenticate2(struct pipes_struct *p, + return _netr_ServerAuthenticate3(p, &a); + } + +-/************************************************************************* +- *************************************************************************/ +- +-static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, +- TALLOC_CTX *mem_ctx, +- const char *computer_name, +- struct netr_Authenticator *received_authenticator, +- struct netr_Authenticator *return_authenticator, +- struct netlogon_creds_CredentialState **creds_out) +-{ +- struct dcesrv_call_state *dce_call = p->dce_call; +- NTSTATUS status; +- bool schannel_global_required = (lp_server_schannel() == true) ? true:false; +- bool schannel_required = schannel_global_required; +- const char *explicit_opt = NULL; +- struct loadparm_context *lp_ctx; +- struct netlogon_creds_CredentialState *creds = NULL; +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; +- uint16_t opnum = dce_call->pkt.u.request.opnum; +- const char *opname = ""; +- +- if (creds_out != NULL) { +- *creds_out = NULL; +- } +- +- if (opnum < ndr_table_netlogon.num_calls) { +- opname = ndr_table_netlogon.calls[opnum].name; +- } +- +- dcesrv_call_auth_info(dce_call, &auth_type, NULL); +- +- lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers()); +- if (lp_ctx == NULL) { +- DEBUG(0, ("loadparm_init_s3 failed\n")); +- return NT_STATUS_INTERNAL_ERROR; +- } +- +- status = schannel_check_creds_state(mem_ctx, lp_ctx, +- computer_name, received_authenticator, +- return_authenticator, &creds); +- talloc_unlink(mem_ctx, lp_ctx); +- +- if (!NT_STATUS_IS_OK(status)) { +- ZERO_STRUCTP(return_authenticator); +- return status; +- } +- +- /* +- * We don't use lp_parm_bool(), as we +- * need the explicit_opt pointer in order to +- * adjust the debug messages. +- */ +- +- explicit_opt = lp_parm_const_string(GLOBAL_SECTION_SNUM, +- "server require schannel", +- creds->account_name, +- NULL); +- if (explicit_opt != NULL) { +- schannel_required = lp_bool(explicit_opt); +- } +- +- if (schannel_required) { +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- *creds_out = creds; +- return NT_STATUS_OK; +- } +- +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' is needed! \n", +- log_escape(mem_ctx, creds->account_name)); +- TALLOC_FREE(creds); +- ZERO_STRUCTP(return_authenticator); +- return NT_STATUS_ACCESS_DENIED; +- } +- +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) WITH schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' not needed!?\n", +- log_escape(mem_ctx, creds->account_name)); +- +- *creds_out = creds; +- return NT_STATUS_OK; +- } +- +- if (explicit_opt != NULL) { +- DBG_INFO("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); +- DBG_INFO("CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' still needed!\n", +- log_escape(mem_ctx, creds->account_name)); +- } else { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' might be needed!\n", +- log_escape(mem_ctx, creds->account_name)); +- } +- +- *creds_out = creds; +- return NT_STATUS_OK; +-} +- +- + /************************************************************************* + *************************************************************************/ + +@@ -1429,11 +1307,12 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, + DEBUG(5,("_netr_ServerPasswordSet: %d\n", __LINE__)); + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + + if (!NT_STATUS_IS_OK(status)) { +@@ -1493,11 +1372,12 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + bool ok; + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + + if (!NT_STATUS_IS_OK(status)) { +@@ -1644,11 +1524,12 @@ NTSTATUS _netr_LogonSamLogoff(struct pipes_struct *p, + struct netlogon_creds_CredentialState *creds; + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + + return status; +@@ -2061,11 +1942,12 @@ NTSTATUS _netr_LogonSamLogonWithFlags(struct pipes_struct *p, + } + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- &return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ &return_authenticator, ++ &creds); + unbecome_root(); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -2411,11 +2293,12 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, + NTSTATUS status; + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -2775,11 +2658,12 @@ NTSTATUS _netr_GetForestTrustInformation(struct pipes_struct *p, + /* TODO: check server name */ + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + if (!NT_STATUS_IS_OK(status)) { + return status; +@@ -2878,11 +2762,12 @@ NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p, + /* TODO: check server name */ + + become_root(); +- status = netr_creds_server_step_check(p, p->mem_ctx, +- r->in.computer_name, +- r->in.credential, +- r->out.return_authenticator, +- &creds); ++ status = dcesrv_netr_creds_server_step_check(p->dce_call, ++ p->mem_ctx, ++ r->in.computer_name, ++ r->in.credential, ++ r->out.return_authenticator, ++ &creds); + unbecome_root(); + if (!NT_STATUS_IS_OK(status)) { + return status; +diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build +index 83ceca2a45c..341df41a321 100644 +--- a/source3/rpc_server/wscript_build ++++ b/source3/rpc_server/wscript_build +@@ -174,7 +174,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_NETDFS', + + bld.SAMBA3_SUBSYSTEM('RPC_NETLOGON', + source='''netlogon/srv_netlog_nt.c''', +- deps='LIBCLI_AUTH') ++ deps='LIBCLI_AUTH DCERPC_SERVER_NETLOGON') + + bld.SAMBA3_SUBSYSTEM('RPC_NTSVCS', + source='''ntsvcs/srv_ntsvcs_nt.c''', +-- +2.39.0 + + +From 5e8a9c85fe9cd28727c284a7fa5465db00a16cac Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 09:29:04 +0100 +Subject: [PATCH 6/9] CVE-2022-38023 s3:rpc_server/netlogon: make sure all + _netr_LogonSamLogon*() calls go through dcesrv_netr_check_schannel() + +Some checks are also required for _netr_LogonSamLogonEx(). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit ca07f4340ce58a7e940a1123888b7409176412f7) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 45 +++++++++++++-------- + 1 file changed, 28 insertions(+), 17 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 8e0ea522b6d..ba2680668ed 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1632,6 +1632,11 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + struct auth_serversupplied_info *server_info = NULL; + struct auth_context *auth_context = NULL; + const char *fn; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; ++ uint16_t opnum = dce_call->pkt.u.request.opnum; ++ ++ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); + + #ifdef DEBUG_PASSWORD + logon = netlogon_creds_shallow_copy_logon(p->mem_ctx, +@@ -1642,15 +1647,37 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + } + #endif + +- switch (dce_call->pkt.u.request.opnum) { ++ switch (opnum) { + case NDR_NETR_LOGONSAMLOGON: + fn = "_netr_LogonSamLogon"; ++ /* ++ * Already called netr_check_schannel() via ++ * netr_creds_server_step_check() ++ */ + break; + case NDR_NETR_LOGONSAMLOGONWITHFLAGS: + fn = "_netr_LogonSamLogonWithFlags"; ++ /* ++ * Already called netr_check_schannel() via ++ * netr_creds_server_step_check() ++ */ + break; + case NDR_NETR_LOGONSAMLOGONEX: + fn = "_netr_LogonSamLogonEx"; ++ ++ if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ status = dcesrv_netr_check_schannel(p->dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ opnum); ++ if (NT_STATUS_IS_ERR(status)) { ++ return status; ++ } ++ + break; + default: + return NT_STATUS_INTERNAL_ERROR; +@@ -1881,10 +1908,6 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, + r->out.validation->sam3); + break; + case 6: { +- enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; +- +- dcesrv_call_auth_info(dce_call, NULL, &auth_level); +- + /* Only allow this if the pipe is protected. */ + if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) { + DEBUG(0,("netr_Validation6: client %s not using privacy for netlogon\n", +@@ -1997,8 +2020,6 @@ NTSTATUS _netr_LogonSamLogon(struct pipes_struct *p, + NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p, + struct netr_LogonSamLogonEx *r) + { +- struct dcesrv_call_state *dce_call = p->dce_call; +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + NTSTATUS status; + struct netlogon_creds_CredentialState *creds = NULL; + struct loadparm_context *lp_ctx; +@@ -2010,16 +2031,6 @@ NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p, + return status; + } + +- /* Only allow this if the pipe is protected. */ +- +- dcesrv_call_auth_info(dce_call, &auth_type, NULL); +- +- if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { +- DEBUG(0,("_netr_LogonSamLogonEx: client %s not using schannel for netlogon\n", +- get_remote_machine_name() )); +- return NT_STATUS_INVALID_PARAMETER; +- } +- + lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + DEBUG(0, ("loadparm_init_s3 failed\n")); +-- +2.39.0 + + +From f4682b16e9e5bdc4decf6c9d02388d540482b6a7 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 11:05:33 +0100 +Subject: [PATCH 7/9] CVE-2022-38023 s3:rpc_server/netlogon: Check for global + "server schannel require seal" + +By default we'll now require schannel connections with privacy/sealing/encryption. + +But we allow exceptions for specific computer/trust accounts. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit a0b97e262318dc56fe663da89b0ee3172b2e7848) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index ba2680668ed..a6f56a5ca21 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -2895,7 +2895,9 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context + struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); ++ bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); + static bool warned_global_schannel_once = false; ++ static bool warned_global_seal_once = false; + + if (!schannel_global_required && !warned_global_schannel_once) { + /* +@@ -2907,6 +2909,16 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context + warned_global_schannel_once = true; + } + ++ if (!global_require_seal && !warned_global_seal_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'server schannel require seal = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_seal_once = true; ++ } ++ + return NT_STATUS_OK; + } + +-- +2.39.0 + + +From 5ddca0370de470bf1c532a6883e0b9fa0dedf6c4 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Mon, 9 Jan 2023 12:17:48 +0100 +Subject: [PATCH 8/9] CVE-2022-38023 docs-xml/smbdotconf: The "server schannel + require seal[:COMPUTERACCOUNT]" options are also honoured by s3 netlogon + server. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider +(cherry picked from commit 02fba22b8c9e9b33ab430555ef45500c45eaa9d1) +--- + docs-xml/smbdotconf/security/serverschannelrequireseal.xml | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/docs-xml/smbdotconf/security/serverschannelrequireseal.xml b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml +index d4620d1252d..0bec67d2519 100644 +--- a/docs-xml/smbdotconf/security/serverschannelrequireseal.xml ++++ b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml +@@ -12,9 +12,8 @@ + + + +- This option controls whether the netlogon server (currently +- only in 'active directory domain controller' mode), will +- reject the usage of netlogon secure channel without privacy/enryption. ++ This option controls whether the netlogon server, will reject the usage ++ of netlogon secure channel without privacy/enryption. + + + +-- +2.39.0 + + +From 2cb3ecb5c258fd23ca2f1fd2635be90336a0d7e0 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Thu, 22 Dec 2022 16:32:40 +0100 +Subject: [PATCH 9/9] CVE-2022-38023 s3:rpc_server/netlogon: Avoid unnecessary + loadparm_context allocations + +After s3 and s4 rpc servers merge the loadparm_context is available in +the dcesrv_context structure. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Samuel Cabrero +Reviewed-by: Andreas Schneider + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon Jan 9 15:17:14 UTC 2023 on sn-devel-184 + +(cherry picked from commit 56837f3d3169a02d0d92bd085d9c8250415ce29b) +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 21 ++------------------- + 1 file changed, 2 insertions(+), 19 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index a6f56a5ca21..7d17ab79f3d 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -880,7 +880,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, + * so use a copy to avoid destroying the client values. */ + uint32_t in_neg_flags = *r->in.negotiate_flags; + const char *fn; +- struct loadparm_context *lp_ctx; ++ struct loadparm_context *lp_ctx = p->dce_call->conn->dce_ctx->lp_ctx; + struct dom_sid sid; + struct samr_Password mach_pwd; + struct netlogon_creds_CredentialState *creds; +@@ -1009,20 +1009,11 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, + goto out; + } + +- lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers()); +- if (lp_ctx == NULL) { +- DEBUG(10, ("loadparm_init_s3 failed\n")); +- status = NT_STATUS_INTERNAL_ERROR; +- goto out; +- } +- + /* Store off the state so we can continue after client disconnect. */ + become_root(); + status = schannel_save_creds_state(p->mem_ctx, lp_ctx, creds); + unbecome_root(); + +- talloc_unlink(p->mem_ctx, lp_ctx); +- + if (!NT_STATUS_IS_OK(status)) { + ZERO_STRUCTP(r->out.return_credentials); + goto out; +@@ -2022,7 +2013,7 @@ NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p, + { + NTSTATUS status; + struct netlogon_creds_CredentialState *creds = NULL; +- struct loadparm_context *lp_ctx; ++ struct loadparm_context *lp_ctx = p->dce_call->conn->dce_ctx->lp_ctx; + + *r->out.authoritative = true; + +@@ -2031,18 +2022,10 @@ NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p, + return status; + } + +- lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers()); +- if (lp_ctx == NULL) { +- DEBUG(0, ("loadparm_init_s3 failed\n")); +- return NT_STATUS_INTERNAL_ERROR; +- } +- + become_root(); + status = schannel_get_creds_state(p->mem_ctx, lp_ctx, + r->in.computer_name, &creds); + unbecome_root(); +- talloc_unlink(p->mem_ctx, lp_ctx); +- + if (!NT_STATUS_IS_OK(status)) { + return status; + } +-- +2.39.0 + diff --git a/SOURCES/CVE-2022-38023-v4-16.patch b/SOURCES/CVE-2022-38023-v4-16.patch new file mode 100644 index 0000000..54e0604 --- /dev/null +++ b/SOURCES/CVE-2022-38023-v4-16.patch @@ -0,0 +1,4417 @@ +From e39dcc08705f0bf59a57ad835821cef41ec8b1e6 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 6 Dec 2022 16:00:36 +0100 +Subject: [PATCH 01/30] CVE-2022-38023 docs-xml: improve wording for several + options: "takes precedence" -> "overrides" + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Ralph Boehme +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 8ec62694a94c346e6ba8f3144a417c9984a1c8b9) +--- + docs-xml/smbdotconf/logon/rejectmd5clients.xml | 2 +- + docs-xml/smbdotconf/security/serverschannel.xml | 2 +- + docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 2 +- + docs-xml/smbdotconf/winbind/requirestrongkey.xml | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +index 41684ef10805..0bb9f6f6c8ec 100644 +--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml ++++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +@@ -10,7 +10,7 @@ + You can set this to yes if all domain members support aes. + This will prevent downgrade attacks. + +- This option takes precedence to the 'allow nt4 crypto' option. ++ This option overrides the 'allow nt4 crypto' option. + + + no +diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml +index b682d086f76b..79e4e73a95c9 100644 +--- a/docs-xml/smbdotconf/security/serverschannel.xml ++++ b/docs-xml/smbdotconf/security/serverschannel.xml +@@ -59,7 +59,7 @@ + See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 + + +- This option takes precedence to the option. ++ This option overrides the option. + + + server require schannel:LEGACYCOMPUTER1$ = no +diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +index 37656293aa47..151b4676c57b 100644 +--- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml ++++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +@@ -15,7 +15,7 @@ + The behavior can be controlled per netbios domain + by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. + +- This option takes precedence to the option. ++ This option overrides the option. + + + no +diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +index 4db62bfb02db..b17620ec8f1d 100644 +--- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml ++++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +@@ -19,7 +19,7 @@ + + This option yields precedence to the option. + +- This option takes precedence to the option. ++ This option overrides the option. + + + yes +-- +2.34.1 + + +From 75fcaa4792afde7599d23316788ce8bbf780fe8a Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 6 Dec 2022 16:05:26 +0100 +Subject: [PATCH 02/30] CVE-2022-38023 docs-xml: improve wording for several + options: "yields precedence" -> "is over-riden" + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Ralph Boehme +Reviewed-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +(cherry picked from commit 830e865ba5648f6520bc552ffd71b61f754b8251) +--- + docs-xml/smbdotconf/logon/allownt4crypto.xml | 2 +- + docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml | 2 +- + docs-xml/smbdotconf/security/clientschannel.xml | 2 +- + docs-xml/smbdotconf/security/serverschannel.xml | 2 +- + docs-xml/smbdotconf/winbind/requirestrongkey.xml | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml +index 03dc8fa93f72..06afcef73b1b 100644 +--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml ++++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml +@@ -18,7 +18,7 @@ + + "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. + +- This option yields precedence to the 'reject md5 clients' option. ++ This option is over-ridden by the 'reject md5 clients' option. + + + no +diff --git a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml +index 03531adbfb36..8bccab391cc2 100644 +--- a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml ++++ b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml +@@ -15,7 +15,7 @@ + The behavior can be overwritten per interface name (e.g. lsarpc, netlogon, samr, srvsvc, + winreg, wkssvc ...) by using 'allow dcerpc auth level connect:interface = yes' as option. + +- This option yields precedence to the implementation specific restrictions. ++ This option is over-ridden by the implementation specific restrictions. + E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY. + The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY. + +diff --git a/docs-xml/smbdotconf/security/clientschannel.xml b/docs-xml/smbdotconf/security/clientschannel.xml +index 5b07da95050c..d124ad481818 100644 +--- a/docs-xml/smbdotconf/security/clientschannel.xml ++++ b/docs-xml/smbdotconf/security/clientschannel.xml +@@ -23,7 +23,7 @@ + Note that for active directory domains this is hardcoded to + yes. + +- This option yields precedence to the option. ++ This option is over-ridden by the option. + + yes + auto +diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml +index 79e4e73a95c9..3e66df1c2032 100644 +--- a/docs-xml/smbdotconf/security/serverschannel.xml ++++ b/docs-xml/smbdotconf/security/serverschannel.xml +@@ -23,7 +23,7 @@ + If you still have legacy domain members use the option. + + +- This option yields precedence to the option. ++ This option is over-ridden by the option. + + + +diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +index b17620ec8f1d..9c1c1d7af148 100644 +--- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml ++++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml +@@ -17,7 +17,7 @@ + + Note for active directory domain this option is hardcoded to 'yes' + +- This option yields precedence to the option. ++ This option is over-ridden by the option. + + This option overrides the option. + +-- +2.34.1 + + +From cbf7cf691860d92c1890009b639a1fd495cf1cf2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 14:46:59 +0100 +Subject: [PATCH 03/30] CVE-2022-38023 libcli/auth: pass lp_ctx to + netlogon_creds_cli_set_global_db() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 992f39a2c8a58301ceeb965f401e29cd64c5a209) +--- + libcli/auth/netlogon_creds_cli.c | 3 ++- + libcli/auth/netlogon_creds_cli.h | 2 +- + source3/rpc_client/cli_netlogon.c | 2 +- + source3/utils/destroy_netlogon_creds_cli.c | 2 +- + 4 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index e92a042c0120..030191174dca 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -202,7 +202,8 @@ static NTSTATUS netlogon_creds_cli_context_common( + + static struct db_context *netlogon_creds_cli_global_db; + +-NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db) ++NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, ++ struct db_context **db) + { + if (netlogon_creds_cli_global_db != NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; +diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h +index 6f40a46aa0a6..d10197c2d2af 100644 +--- a/libcli/auth/netlogon_creds_cli.h ++++ b/libcli/auth/netlogon_creds_cli.h +@@ -31,7 +31,7 @@ struct messaging_context; + struct dcerpc_binding_handle; + struct db_context; + +-NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db); ++NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struct db_context **db); + NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); + void netlogon_creds_cli_close_global_db(void); + +diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c +index 50dae9d7f3eb..18664e8b91af 100644 +--- a/source3/rpc_client/cli_netlogon.c ++++ b/source3/rpc_client/cli_netlogon.c +@@ -76,7 +76,7 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) + return NT_STATUS_NO_MEMORY; + } + +- status = netlogon_creds_cli_set_global_db(&global_db); ++ status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; +diff --git a/source3/utils/destroy_netlogon_creds_cli.c b/source3/utils/destroy_netlogon_creds_cli.c +index f28cad527dfb..a2e1952e434c 100644 +--- a/source3/utils/destroy_netlogon_creds_cli.c ++++ b/source3/utils/destroy_netlogon_creds_cli.c +@@ -82,7 +82,7 @@ int main(int argc, const char *argv[]) + goto done; + } + +- status = netlogon_creds_cli_set_global_db(&global_db); ++ status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr, + "netlogon_creds_cli_set_global_db failed: %s\n", +-- +2.34.1 + + +From 2c4f9869b208cfd969607248420e36e3bd4aecfa Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 14:47:33 +0100 +Subject: [PATCH 04/30] CVE-2022-38023 libcli/auth: add/use + netlogon_creds_cli_warn_options() + +This warns the admin about insecure options + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme + +(similar to commit 7e7adf86e59e8a673fbe87de46cef0d62221e800) +[jsutton@samba.org Replaced call to tevent_cached_getpid() with one to + getpid()] +--- + libcli/auth/netlogon_creds_cli.c | 66 ++++++++++++++++++++++++++++++++ + libcli/auth/netlogon_creds_cli.h | 2 + + 2 files changed, 68 insertions(+) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 030191174dca..3794d8b6b6ef 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -205,6 +205,8 @@ static struct db_context *netlogon_creds_cli_global_db; + NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, + struct db_context **db) + { ++ netlogon_creds_cli_warn_options(lp_ctx); ++ + if (netlogon_creds_cli_global_db != NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } +@@ -219,6 +221,8 @@ NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) + struct db_context *global_db; + int hash_size, tdb_flags; + ++ netlogon_creds_cli_warn_options(lp_ctx); ++ + if (netlogon_creds_cli_global_db != NULL) { + return NT_STATUS_OK; + } +@@ -259,6 +263,68 @@ void netlogon_creds_cli_close_global_db(void) + TALLOC_FREE(netlogon_creds_cli_global_db); + } + ++void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx) ++{ ++ bool global_reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx); ++ bool global_require_strong_key = lpcfg_require_strong_key(lp_ctx); ++ int global_client_schannel = lpcfg_client_schannel(lp_ctx); ++ bool global_seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx); ++ static bool warned_global_reject_md5_servers = false; ++ static bool warned_global_require_strong_key = false; ++ static bool warned_global_client_schannel = false; ++ static bool warned_global_seal_secure_channel = false; ++ static int warned_global_pid = 0; ++ int current_pid = getpid(); ++ ++ if (warned_global_pid != current_pid) { ++ warned_global_reject_md5_servers = false; ++ warned_global_require_strong_key = false; ++ warned_global_client_schannel = false; ++ warned_global_seal_secure_channel = false; ++ warned_global_pid = current_pid; ++ } ++ ++ if (!global_reject_md5_servers && !warned_global_reject_md5_servers) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ DBG_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'reject md5 servers = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_reject_md5_servers = true; ++ } ++ ++ if (!global_require_strong_key && !warned_global_require_strong_key) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ DBG_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'require strong key = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_require_strong_key = true; ++ } ++ ++ if (global_client_schannel != true && !warned_global_client_schannel) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ DBG_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'client schannel = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_client_schannel = true; ++ } ++ ++ if (!global_seal_secure_channel && !warned_global_seal_secure_channel) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ DBG_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'winbind sealed pipes = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_seal_secure_channel = true; ++ } ++} ++ + NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + struct messaging_context *msg_ctx, + const char *client_account, +diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h +index d10197c2d2af..600242e1aea7 100644 +--- a/libcli/auth/netlogon_creds_cli.h ++++ b/libcli/auth/netlogon_creds_cli.h +@@ -35,6 +35,8 @@ NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struc + NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); + void netlogon_creds_cli_close_global_db(void); + ++void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx); ++ + NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + struct messaging_context *msg_ctx, + const char *client_account, +-- +2.34.1 + + +From 558c68e0915885ed77b3d02e52d93f4c64a0e20e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 16:16:05 +0100 +Subject: [PATCH 05/30] CVE-2022-38023 s3:net: add and use + net_warn_member_options() helper + +This makes sure domain member related 'net' commands print warnings +about unsecure smb.conf options. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 1fdf1d55a5dd550bdb16d037b5dc995c33c1a67a) +--- + source3/utils/net.c | 6 ++++++ + source3/utils/net_ads.c | 14 ++++++++++++++ + source3/utils/net_dom.c | 2 ++ + source3/utils/net_join.c | 2 ++ + source3/utils/net_offlinejoin.c | 2 ++ + source3/utils/net_proto.h | 2 ++ + source3/utils/net_rpc.c | 10 ++++++++++ + source3/utils/net_util.c | 14 ++++++++++++++ + 8 files changed, 52 insertions(+) + +diff --git a/source3/utils/net.c b/source3/utils/net.c +index e1e14743c117..b96d7f5d9d48 100644 +--- a/source3/utils/net.c ++++ b/source3/utils/net.c +@@ -85,6 +85,8 @@ enum netr_SchannelType get_sec_channel_type(const char *param) + + static int net_changetrustpw(struct net_context *c, int argc, const char **argv) + { ++ net_warn_member_options(); ++ + if (net_ads_check_our_domain(c) == 0) + return net_ads_changetrustpw(c, argc, argv); + +@@ -112,6 +114,8 @@ static int net_primarytrust_dumpinfo(struct net_context *c, int argc, + return 1; + } + ++ net_warn_member_options(); ++ + if (c->opt_stdin) { + set_line_buffering(stdin); + set_line_buffering(stdout); +@@ -193,6 +197,8 @@ static int net_changesecretpw(struct net_context *c, int argc, + return 1; + } + ++ net_warn_member_options(); ++ + if(c->opt_force) { + struct secrets_domain_info1 *info = NULL; + struct secrets_domain_info1_change *prev = NULL; +diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c +index d666f7fc3ec9..cc0d4a0d966c 100644 +--- a/source3/utils/net_ads.c ++++ b/source3/utils/net_ads.c +@@ -1306,6 +1306,8 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + if (!ADS_ERR_OK(ads_startup(c, true, &ads))) { + return -1; + } +@@ -1447,6 +1449,8 @@ static NTSTATUS net_ads_join_ok(struct net_context *c) + return NT_STATUS_ACCESS_DENIED; + } + ++ net_warn_member_options(); ++ + net_use_krb_machine_account(c); + + get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip); +@@ -1477,6 +1481,8 @@ int net_ads_testjoin(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + /* Display success or failure */ + status = net_ads_join_ok(c); + if (!NT_STATUS_IS_OK(status)) { +@@ -1571,6 +1577,8 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) + if (c->display_usage) + return net_ads_join_usage(c, argc, argv); + ++ net_warn_member_options(); ++ + if (!modify_config) { + + werr = check_ads_config(); +@@ -2505,6 +2513,8 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) + return -1; + } + ++ net_warn_member_options(); ++ + net_use_krb_machine_account(c); + + use_in_memory_ccache(); +@@ -2778,6 +2788,8 @@ static int net_ads_keytab_add(struct net_context *c, + return 0; + } + ++ net_warn_member_options(); ++ + d_printf(_("Processing principals to add...\n")); + + if (!c->opt_user_specified && c->opt_password == NULL) { +@@ -2822,6 +2834,8 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a + return 0; + } + ++ net_warn_member_options(); ++ + if (!c->opt_user_specified && c->opt_password == NULL) { + net_use_krb_machine_account(c); + } +diff --git a/source3/utils/net_dom.c b/source3/utils/net_dom.c +index 13e65a933142..4b48e1566bc8 100644 +--- a/source3/utils/net_dom.c ++++ b/source3/utils/net_dom.c +@@ -154,6 +154,8 @@ static int net_dom_join(struct net_context *c, int argc, const char **argv) + return net_dom_usage(c, argc, argv); + } + ++ net_warn_member_options(); ++ + if (c->opt_host) { + server_name = c->opt_host; + } +diff --git a/source3/utils/net_join.c b/source3/utils/net_join.c +index 1493dff74d7b..f67f08f79a81 100644 +--- a/source3/utils/net_join.c ++++ b/source3/utils/net_join.c +@@ -39,6 +39,8 @@ int net_join(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + if (net_ads_check_our_domain(c) == 0) { + if (net_ads_join(c, argc, argv) == 0) + return 0; +diff --git a/source3/utils/net_offlinejoin.c b/source3/utils/net_offlinejoin.c +index 03e5df0eace9..0cfd5fdfe235 100644 +--- a/source3/utils/net_offlinejoin.c ++++ b/source3/utils/net_offlinejoin.c +@@ -49,6 +49,8 @@ int net_offlinejoin(struct net_context *c, int argc, const char **argv) + return -1; + } + ++ net_warn_member_options(); ++ + status = libnetapi_net_init(&c->netapi_ctx); + if (status != 0) { + return -1; +diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h +index b6ff639a0941..42096ba218d5 100644 +--- a/source3/utils/net_proto.h ++++ b/source3/utils/net_proto.h +@@ -442,6 +442,8 @@ int net_run_function(struct net_context *c, int argc, const char **argv, + const char *whoami, struct functable *table); + void net_display_usage_from_functable(struct functable *table); + ++void net_warn_member_options(void); ++ + const char *net_share_type_str(int num_type); + + NTSTATUS net_scan_dc(struct net_context *c, +diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c +index 97c0158d612f..16a541413d2e 100644 +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -371,6 +371,8 @@ static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + mem_ctx = talloc_init("net_rpc_oldjoin"); + if (!mem_ctx) { + return -1; +@@ -490,6 +492,8 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + mem_ctx = talloc_init("net_rpc_testjoin"); + if (!mem_ctx) { + return -1; +@@ -564,6 +568,8 @@ static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **a + return 0; + } + ++ net_warn_member_options(); ++ + mem_ctx = talloc_init("net_rpc_join_newstyle"); + if (!mem_ctx) { + return -1; +@@ -685,6 +691,8 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) + return -1; + } + ++ net_warn_member_options(); ++ + if (strlen(lp_netbios_name()) > 15) { + d_printf(_("Our netbios name can be at most 15 chars long, " + "\"%s\" is %u chars long\n"), +@@ -815,6 +823,8 @@ int net_rpc_info(struct net_context *c, int argc, const char **argv) + return 0; + } + ++ net_warn_member_options(); ++ + return run_rpc_command(c, NULL, &ndr_table_samr, + NET_FLAGS_PDC, rpc_info_internals, + argc, argv); +diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c +index 298d9a64dc0c..f3b7755063bf 100644 +--- a/source3/utils/net_util.c ++++ b/source3/utils/net_util.c +@@ -31,6 +31,7 @@ + #include "libsmb/libsmb.h" + #include "lib/param/param.h" + #include "auth/gensec/gensec.h" ++#include "libcli/auth/netlogon_creds_cli.h" + #include "lib/cmdline/cmdline.h" + + NTSTATUS net_rpc_lookup_name(struct net_context *c, +@@ -478,6 +479,19 @@ void net_display_usage_from_functable(struct functable *table) + } + } + ++void net_warn_member_options(void) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct loadparm_context *lp_ctx = NULL; ++ ++ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); ++ if (lp_ctx != NULL) { ++ netlogon_creds_cli_warn_options(lp_ctx); ++ } ++ ++ TALLOC_FREE(frame); ++} ++ + const char *net_share_type_str(int num_type) + { + switch(num_type) { +-- +2.34.1 + + +From 9172fa1fe342a13c773d14c73ffcaa9f9561cdc7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 14:59:36 +0100 +Subject: [PATCH 06/30] CVE-2022-38023 s3:winbindd: also allow per domain + "winbind sealed pipes:DOMAIN" and "require strong key:DOMAIN" + +This avoids advising insecure defaults for the global options. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit d60828f6391307a59abaa02b72b6a8acf66b2fef) +--- + source3/winbindd/winbindd_cm.c | 41 +++++++++++++++++++++++++++------- + 1 file changed, 33 insertions(+), 8 deletions(-) + +diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c +index 6c6dd88a5aa4..5532e0cd0cc8 100644 +--- a/source3/winbindd/winbindd_cm.c ++++ b/source3/winbindd/winbindd_cm.c +@@ -2431,6 +2431,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + bool retry = false; /* allow one retry attempt for expired session */ + const char *remote_name = NULL; + const struct sockaddr_storage *remote_sockaddr = NULL; ++ bool sealed_pipes = true; ++ bool strong_key = true; + + if (sid_check_is_our_sam(&domain->sid)) { + if (domain->rodc == false || need_rw_dc == false) { +@@ -2610,14 +2612,24 @@ retry: + + anonymous: + ++ sealed_pipes = lp_winbind_sealed_pipes(); ++ sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes", ++ domain->name, ++ sealed_pipes); ++ strong_key = lp_require_strong_key(); ++ strong_key = lp_parm_bool(-1, "require strong key", ++ domain->name, ++ strong_key); ++ + /* Finally fall back to anonymous. */ +- if (lp_winbind_sealed_pipes() || lp_require_strong_key()) { ++ if (sealed_pipes || strong_key) { + status = NT_STATUS_DOWNGRADE_DETECTED; + DEBUG(1, ("Unwilling to make SAMR connection to domain %s " + "without connection level security, " +- "must set 'winbind sealed pipes = false' and " +- "'require strong key = false' to proceed: %s\n", +- domain->name, nt_errstr(status))); ++ "must set 'winbind sealed pipes:%s = false' and " ++ "'require strong key:%s = false' to proceed: %s\n", ++ domain->name, domain->name, domain->name, ++ nt_errstr(status))); + goto done; + } + status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr, +@@ -2774,6 +2786,8 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, + bool retry = false; /* allow one retry attempt for expired session */ + const char *remote_name = NULL; + const struct sockaddr_storage *remote_sockaddr = NULL; ++ bool sealed_pipes = true; ++ bool strong_key = true; + + retry: + result = init_dc_connection_rpc(domain, false); +@@ -2935,13 +2949,24 @@ retry: + goto done; + } + +- if (lp_winbind_sealed_pipes() || lp_require_strong_key()) { ++ sealed_pipes = lp_winbind_sealed_pipes(); ++ sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes", ++ domain->name, ++ sealed_pipes); ++ strong_key = lp_require_strong_key(); ++ strong_key = lp_parm_bool(-1, "require strong key", ++ domain->name, ++ strong_key); ++ ++ /* Finally fall back to anonymous. */ ++ if (sealed_pipes || strong_key) { + result = NT_STATUS_DOWNGRADE_DETECTED; + DEBUG(1, ("Unwilling to make LSA connection to domain %s " + "without connection level security, " +- "must set 'winbind sealed pipes = false' and " +- "'require strong key = false' to proceed: %s\n", +- domain->name, nt_errstr(result))); ++ "must set 'winbind sealed pipes:%s = false' and " ++ "'require strong key:%s = false' to proceed: %s\n", ++ domain->name, domain->name, domain->name, ++ nt_errstr(result))); + goto done; + } + +-- +2.34.1 + + +From 434812f94ee12bdb55dbe8072702426f85610c02 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 24 Nov 2022 18:22:23 +0100 +Subject: [PATCH 07/30] CVE-2022-38023 docs-xml/smbdotconf: change 'reject md5 + servers' default to yes + +AES is supported by Windows >= 2008R2 and Samba >= 4.0 so there's no +reason to allow md5 servers by default. + +Note the change in netlogon_creds_cli_context_global() is only cosmetic, +but avoids confusion while reading the code. Check with: + + git show -U35 libcli/auth/netlogon_creds_cli.c + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 1c6c1129905d0c7a60018e7bf0f17a0fd198a584) +--- + docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 7 +++++-- + lib/param/loadparm.c | 1 + + libcli/auth/netlogon_creds_cli.c | 4 ++-- + source3/param/loadparm.c | 1 + + 4 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +index 151b4676c57b..3bc4eaf7b02e 100644 +--- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml ++++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +@@ -13,10 +13,13 @@ + This will prevent downgrade attacks. + + The behavior can be controlled per netbios domain +- by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. ++ by using 'reject md5 servers:NETBIOSDOMAIN = no' as option. ++ ++ The default changed from 'no' to 'yes, with the patches for CVE-2022-38023, ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240 + + This option overrides the option. + + +-no ++yes + +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index d6d845391e6f..e953499efba3 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -2666,6 +2666,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) + lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True"); + lpcfg_do_global_parameter(lp_ctx, "winbind scan trusted domains", "False"); + lpcfg_do_global_parameter(lp_ctx, "require strong key", "True"); ++ lpcfg_do_global_parameter(lp_ctx, "reject md5 servers", "True"); + lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR); + lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); + lpcfg_do_global_parameter_var(lp_ctx, "gpo update command", "%s/samba-gpupdate", dyn_SCRIPTSBINDIR); +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 3794d8b6b6ef..ca5619d38703 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -341,8 +341,8 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + const char *client_computer; + uint32_t proposed_flags; + uint32_t required_flags = 0; +- bool reject_md5_servers = false; +- bool require_strong_key = false; ++ bool reject_md5_servers = true; ++ bool require_strong_key = true; + int require_sign_or_seal = true; + bool seal_secure_channel = true; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 21e061939e3e..91747e09eccd 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -664,6 +664,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) + Globals.client_schannel = true; + Globals.winbind_sealed_pipes = true; + Globals.require_strong_key = true; ++ Globals.reject_md5_servers = true; + Globals.server_schannel = true; + Globals.read_raw = true; + Globals.write_raw = true; +-- +2.34.1 + + +From 8ccaf7d47ad13313c7a80ac5f857425080d5fbab Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 6 Dec 2022 10:56:29 +0100 +Subject: [PATCH 08/30] CVE-2022-38023 s4:rpc_server/netlogon: 'server schannel + != yes' warning to dcesrv_interface_netlogon_bind + +This will simplify the following changes. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit e060ea5b3edbe3cba492062c9605f88fae212ee0) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 +++++++++++-------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index cfd6d148b0a3..f63c3981f749 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -63,6 +63,21 @@ + static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context, + const struct dcesrv_interface *iface) + { ++ struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; ++ int schannel = lpcfg_server_schannel(lp_ctx); ++ bool schannel_global_required = (schannel == true); ++ static bool warned_global_schannel_once = false; ++ ++ if (!schannel_global_required && !warned_global_schannel_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2020-1472(ZeroLogon): " ++ "Please configure 'server schannel = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); ++ warned_global_schannel_once = true; ++ } ++ + return dcesrv_interface_bind_reject_connect(context, iface); + } + +@@ -630,7 +645,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + uint16_t opnum = dce_call->pkt.u.request.opnum; + const char *opname = ""; +- static bool warned_global_once = false; + + if (opnum < ndr_table_netlogon.num_calls) { + opname = ndr_table_netlogon.calls[opnum].name; +@@ -682,16 +696,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + return NT_STATUS_ACCESS_DENIED; + } + +- if (!schannel_global_required && !warned_global_once) { +- /* +- * We want admins to notice their misconfiguration! +- */ +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "Please configure 'server schannel = yes', " +- "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); +- warned_global_once = true; +- } +- + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) WITH schannel from " +-- +2.34.1 + + +From 268d1ac2f8ce3fb92a3433ada5e229d23c18c4f6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 12 Dec 2022 14:03:50 +0100 +Subject: [PATCH 09/30] CVE-2022-38023 s4:rpc_server/netlogon: add a lp_ctx + variable to dcesrv_netr_creds_server_step_check() + +This will simplify the following changes. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 7baabbe9819cd5a2714e7ea4e57a0c23062c0150) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index f63c3981f749..43dcd7271729 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -636,8 +636,9 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) + { ++ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + NTSTATUS nt_status; +- int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx); ++ int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); + bool schannel_required = schannel_global_required; + const char *explicit_opt = NULL; +@@ -653,7 +654,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + dcesrv_call_auth_info(dce_call, &auth_type, NULL); + + nt_status = schannel_check_creds_state(mem_ctx, +- dce_call->conn->dce_ctx->lp_ctx, ++ lp_ctx, + computer_name, + received_authenticator, + return_authenticator, +@@ -668,7 +669,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + * need the explicit_opt pointer in order to + * adjust the debug messages. + */ +- explicit_opt = lpcfg_get_parametric(dce_call->conn->dce_ctx->lp_ctx, ++ explicit_opt = lpcfg_get_parametric(lp_ctx, + NULL, + "server require schannel", + creds->account_name); +-- +2.34.1 + + +From e4d8f31296ab5f2013585039a6e47c1a4b826ea8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 12 Dec 2022 14:03:50 +0100 +Subject: [PATCH 10/30] CVE-2022-38023 s4:rpc_server/netlogon: add + talloc_stackframe() to dcesrv_netr_creds_server_step_check() + +This will simplify the following changes. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 0e6a2ba83ef1be3c6a0f5514c21395121621a145) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 32 +++++++++++-------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 43dcd7271729..95fd1526d5a5 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -637,6 +637,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + struct netlogon_creds_CredentialState **creds_out) + { + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; ++ TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS nt_status; + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); +@@ -680,6 +681,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + if (schannel_required) { + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + *creds_out = creds; ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +@@ -687,13 +689,15 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + "%s request (opnum[%u]) without schannel from " + "client_account[%s] client_computer_name[%s]\n", + opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); + DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' is needed! \n", +- log_escape(mem_ctx, creds->account_name)); ++ "'server require schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name)); + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); ++ TALLOC_FREE(frame); + return NT_STATUS_ACCESS_DENIED; + } + +@@ -702,13 +706,14 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + "%s request (opnum[%u]) WITH schannel from " + "client_account[%s] client_computer_name[%s]\n", + opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' not needed!?\n", +- log_escape(mem_ctx, creds->account_name)); ++ log_escape(frame, creds->account_name)); + + *creds_out = creds; ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +@@ -718,24 +723,25 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + "%s request (opnum[%u]) without schannel from " + "client_account[%s] client_computer_name[%s]\n", + opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); + DBG_INFO("CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' still needed!\n", +- log_escape(mem_ctx, creds->account_name)); ++ log_escape(frame, creds->account_name)); + } else { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) without schannel from " + "client_account[%s] client_computer_name[%s]\n", + opname, opnum, +- log_escape(mem_ctx, creds->account_name), +- log_escape(mem_ctx, creds->computer_name)); ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); + DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " + "'server require schannel:%s = no' might be needed!\n", +- log_escape(mem_ctx, creds->account_name)); ++ log_escape(frame, creds->account_name)); + } + + *creds_out = creds; ++ TALLOC_FREE(frame); + return NT_STATUS_OK; + } + +-- +2.34.1 + + +From 4e129119e3a2e1bfca623eb11d721329e53fba17 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 12:37:03 +0100 +Subject: [PATCH 11/30] CVE-2022-38023 s4:rpc_server/netlogon: re-order + checking in dcesrv_netr_creds_server_step_check() + +This will simplify the following changes. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit ec62151a2fb49ecbeaa3bf924f49a956832b735e) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 41 +++++++++---------- + 1 file changed, 19 insertions(+), 22 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 95fd1526d5a5..33063942e161 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -678,13 +678,27 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + schannel_required = lp_bool(explicit_opt); + } + +- if (schannel_required) { +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- *creds_out = creds; +- TALLOC_FREE(frame); +- return NT_STATUS_OK; ++ if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (!schannel_required) { ++ DBG_ERR("CVE-2020-1472(ZeroLogon): " ++ "%s request (opnum[%u]) WITH schannel from " ++ "client_account[%s] client_computer_name[%s]\n", ++ opname, opnum, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } ++ if (explicit_opt != NULL && !schannel_required) { ++ DBG_ERR("CVE-2020-1472(ZeroLogon): " ++ "Option 'server require schannel:%s = no' not needed!?\n", ++ log_escape(frame, creds->account_name)); + } + ++ *creds_out = creds; ++ TALLOC_FREE(frame); ++ return NT_STATUS_OK; ++ } ++ ++ if (schannel_required) { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) without schannel from " + "client_account[%s] client_computer_name[%s]\n", +@@ -701,23 +715,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + return NT_STATUS_ACCESS_DENIED; + } + +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) WITH schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' not needed!?\n", +- log_escape(frame, creds->account_name)); +- +- *creds_out = creds; +- TALLOC_FREE(frame); +- return NT_STATUS_OK; +- } +- +- + if (explicit_opt != NULL) { + DBG_INFO("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) without schannel from " +-- +2.34.1 + + +From 200da32d3573912098d68fd9b72f491317feb506 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 12:37:03 +0100 +Subject: [PATCH 12/30] CVE-2022-38023 s4:rpc_server/netlogon: improve + CVE-2020-1472(ZeroLogon) debug messages + +In order to avoid generating useless debug messages during make test, +we will use 'CVE_2020_1472:warn_about_unused_debug_level = 3' +and 'CVE_2020_1472:error_debug_level = 2' in order to avoid schannel warnings. + +Review with: git show -w + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 16ee03efc194d9c1c2c746f63236b977a419918d) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 147 +++++++++++++----- + 1 file changed, 106 insertions(+), 41 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 33063942e161..3c77d1302993 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -644,15 +644,34 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + bool schannel_required = schannel_global_required; + const char *explicit_opt = NULL; + struct netlogon_creds_CredentialState *creds = NULL; ++ int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); ++ int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); ++ unsigned int dbg_lvl = DBGLVL_DEBUG; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + uint16_t opnum = dce_call->pkt.u.request.opnum; + const char *opname = ""; ++ const char *reason = ""; + + if (opnum < ndr_table_netlogon.num_calls) { + opname = ndr_table_netlogon.calls[opnum].name; + } + +- dcesrv_call_auth_info(dce_call, &auth_type, NULL); ++ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); ++ ++ if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { ++ reason = "WITH SEALED"; ++ } else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { ++ reason = "WITH SIGNED"; ++ } else { ++ smb_panic("Schannel without SIGN/SEAL"); ++ } ++ } else { ++ reason = "WITHOUT"; ++ } + + nt_status = schannel_check_creds_state(mem_ctx, + lp_ctx, +@@ -679,62 +698,108 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + } + + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- if (!schannel_required) { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) WITH schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); ++ nt_status = NT_STATUS_OK; ++ ++ if (explicit_opt != NULL && !schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); ++ } else if (!schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(nt_status))); ++ + if (explicit_opt != NULL && !schannel_required) { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' not needed!?\n", +- log_escape(frame, creds->account_name)); ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Option 'server require schannel:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); + } + + *creds_out = creds; + TALLOC_FREE(frame); +- return NT_STATUS_OK; ++ return nt_status; + } + + if (schannel_required) { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' " +- "might be needed for a legacy client.\n", +- log_escape(frame, creds->account_name)); ++ nt_status = NT_STATUS_ACCESS_DENIED; ++ ++ if (explicit_opt != NULL) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(nt_status))); ++ if (explicit_opt != NULL) { ++ D_NOTICE("CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): Check if option " ++ "'server require schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + TALLOC_FREE(frame); +- return NT_STATUS_ACCESS_DENIED; ++ return nt_status; + } + ++ nt_status = NT_STATUS_OK; ++ + if (explicit_opt != NULL) { +- DBG_INFO("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- DBG_INFO("CVE-2020-1472(ZeroLogon): " +- "Option 'server require schannel:%s = no' still needed!\n", +- log_escape(frame, creds->account_name)); ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } else { +- DBG_ERR("CVE-2020-1472(ZeroLogon): " +- "%s request (opnum[%u]) without schannel from " +- "client_account[%s] client_computer_name[%s]\n", +- opname, opnum, +- log_escape(frame, creds->account_name), +- log_escape(frame, creds->computer_name)); +- DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " +- "'server require schannel:%s = no' might be needed!\n", +- log_escape(frame, creds->account_name)); ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(nt_status))); ++ ++ if (explicit_opt != NULL) { ++ D_INFO("CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = no' " ++ "still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else { ++ /* ++ * admins should set ++ * server require schannel:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Please use 'server require schannel:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); + } + + *creds_out = creds; +-- +2.34.1 + + +From 0038d0302c807bc76b073de3aeed13a29c1fc458 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 12:26:01 +0100 +Subject: [PATCH 13/30] CVE-2022-38023 selftest:Samba4: avoid global 'server + schannel = auto' + +Instead of using the generic deprecated option use the specific +server require schannel:COMPUTERACCOUNT = no in order to allow +legacy tests for pass. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 63c96ea6c02981795e67336401143f2a8836992c) +--- + selftest/target/Samba4.pm | 40 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 37 insertions(+), 3 deletions(-) + +diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm +index b004042738a7..d26022466c66 100755 +--- a/selftest/target/Samba4.pm ++++ b/selftest/target/Samba4.pm +@@ -1616,10 +1616,27 @@ sub provision_ad_dc_ntvfs($$$) + dsdb event notification = true + dsdb password event notification = true + dsdb group change notification = true +- server schannel = auto + # override the new SMB2 only default + client min protocol = CORE + server min protocol = LANMAN1 ++ ++ CVE_2020_1472:warn_about_unused_debug_level = 3 ++ server require schannel:schannel0\$ = no ++ server require schannel:schannel1\$ = no ++ server require schannel:schannel2\$ = no ++ server require schannel:schannel3\$ = no ++ server require schannel:schannel4\$ = no ++ server require schannel:schannel5\$ = no ++ server require schannel:schannel6\$ = no ++ server require schannel:schannel7\$ = no ++ server require schannel:schannel8\$ = no ++ server require schannel:schannel9\$ = no ++ server require schannel:schannel10\$ = no ++ server require schannel:schannel11\$ = no ++ server require schannel:torturetest\$ = no ++ ++ # needed for 'samba.tests.auth_log' tests ++ server require schannel:LOCALDC\$ = no + "; + push (@{$extra_provision_options}, "--use-ntvfs"); + my $ret = $self->provision($prefix, +@@ -1968,8 +1985,22 @@ sub provision_ad_dc($$$$$$$) + lpq cache time = 0 + print notify backchannel = yes + +- server schannel = auto +- auth event notification = true ++ CVE_2020_1472:warn_about_unused_debug_level = 3 ++ server require schannel:schannel0\$ = no ++ server require schannel:schannel1\$ = no ++ server require schannel:schannel2\$ = no ++ server require schannel:schannel3\$ = no ++ server require schannel:schannel4\$ = no ++ server require schannel:schannel5\$ = no ++ server require schannel:schannel6\$ = no ++ server require schannel:schannel7\$ = no ++ server require schannel:schannel8\$ = no ++ server require schannel:schannel9\$ = no ++ server require schannel:schannel10\$ = no ++ server require schannel:schannel11\$ = no ++ server require schannel:torturetest\$ = no ++ ++ auth event notification = true + dsdb event notification = true + dsdb password event notification = true + dsdb group change notification = true +@@ -2658,6 +2689,9 @@ sub setup_ad_dc_smb1 + [global] + client min protocol = CORE + server min protocol = LANMAN1 ++ ++ # needed for 'samba.tests.auth_log' tests ++ server require schannel:ADDCSMB1\$ = no + "; + return _setup_ad_dc($self, $path, $conf_opts, "addcsmb1", "addom2.samba.example.com"); + } +-- +2.34.1 + + +From 76855044472bf75f75a204e0fe411b457478363c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 28 Nov 2022 15:02:13 +0100 +Subject: [PATCH 14/30] CVE-2022-38023 s4:torture: use + NETLOGON_NEG_SUPPORTS_AES by default + +For generic tests we should use the best available features. + +And AES will be required by default soon. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit cfd55a22cda113fbb2bfa373b54091dde1ea6e66) +--- + source4/torture/ntp/ntp_signd.c | 2 +- + source4/torture/rpc/lsa.c | 4 ++-- + source4/torture/rpc/netlogon.c | 24 ++++++++++++------------ + source4/torture/rpc/samba3rpc.c | 15 ++++++++++++--- + 4 files changed, 27 insertions(+), 18 deletions(-) + +diff --git a/source4/torture/ntp/ntp_signd.c b/source4/torture/ntp/ntp_signd.c +index 124c9604871b..6d482bfdee16 100644 +--- a/source4/torture/ntp/ntp_signd.c ++++ b/source4/torture/ntp/ntp_signd.c +@@ -70,7 +70,7 @@ static bool test_ntp_signd(struct torture_context *tctx, + uint32_t rid; + const char *machine_name; + const struct samr_Password *pwhash = cli_credentials_get_nt_hash(credentials, mem_ctx); +- uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + + struct sign_request sign_req; + struct signed_reply signed_reply; +diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c +index d430ee571081..d22546862d5b 100644 +--- a/source4/torture/rpc/lsa.c ++++ b/source4/torture/rpc/lsa.c +@@ -4408,7 +4408,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, + torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b"); + + ok = check_pw_with_ServerAuthenticate3(p1, tctx, +- NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + server_name, + incoming_creds, &creds); + torture_assert_int_equal(tctx, ok, expected_result, +@@ -4505,7 +4505,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, + torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b"); + + ok = check_pw_with_ServerAuthenticate3(p2, tctx, +- NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + server_name, + incoming_creds, &creds); + torture_assert(tctx, ok, "check_pw_with_ServerAuthenticate3 with changed password"); +diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c +index 11f950d3aab4..2803dd13b467 100644 +--- a/source4/torture/rpc/netlogon.c ++++ b/source4/torture/rpc/netlogon.c +@@ -191,7 +191,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, + + /* This allows the tests to continue against the more fussy windows 2008 */ + if (NT_STATUS_EQUAL(a.out.result, NT_STATUS_DOWNGRADE_DETECTED)) { +- return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + credentials, + cli_credentials_get_secure_channel_type(credentials), + creds_out); +@@ -431,7 +431,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx, + "ServerAuthenticate3 failed"); + torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_DOWNGRADE_DETECTED, "ServerAuthenticate3 should have failed"); + +- negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + creds = netlogon_creds_client_init(tctx, a.in.account_name, + a.in.computer_name, + a.in.secure_channel_type, +@@ -498,7 +498,7 @@ static bool test_ServerReqChallenge( + const char *machine_name; + struct dcerpc_binding_handle *b = p->binding_handle; + struct netr_ServerAuthenticate2 a; +- uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + uint32_t out_negotiate_flags = 0; + const struct samr_Password *mach_password = NULL; + enum netr_SchannelType sec_chan_type = 0; +@@ -570,7 +570,7 @@ static bool test_ServerReqChallenge_zero_challenge( + const char *machine_name; + struct dcerpc_binding_handle *b = p->binding_handle; + struct netr_ServerAuthenticate2 a; +- uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + uint32_t out_negotiate_flags = 0; + const struct samr_Password *mach_password = NULL; + enum netr_SchannelType sec_chan_type = 0; +@@ -647,7 +647,7 @@ static bool test_ServerReqChallenge_5_repeats( + const char *machine_name; + struct dcerpc_binding_handle *b = p->binding_handle; + struct netr_ServerAuthenticate2 a; +- uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + uint32_t out_negotiate_flags = 0; + const struct samr_Password *mach_password = NULL; + enum netr_SchannelType sec_chan_type = 0; +@@ -731,7 +731,7 @@ static bool test_ServerReqChallenge_4_repeats( + const char *machine_name; + struct dcerpc_binding_handle *b = p->binding_handle; + struct netr_ServerAuthenticate2 a; +- uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + uint32_t out_negotiate_flags = 0; + const struct samr_Password *mach_password = NULL; + enum netr_SchannelType sec_chan_type = 0; +@@ -1527,7 +1527,7 @@ static bool test_SetPassword2_all_zeros( + struct netr_CryptPassword new_password; + struct dcerpc_pipe *p = NULL; + struct dcerpc_binding_handle *b = NULL; +- uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ + + if (!test_SetupCredentials2( + p1, +@@ -1603,7 +1603,7 @@ static bool test_SetPassword2_maximum_length_password( + struct netr_CryptPassword new_password; + struct dcerpc_pipe *p = NULL; + struct dcerpc_binding_handle *b = NULL; +- uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + DATA_BLOB new_random_pass = data_blob_null; + + if (!test_SetupCredentials2( +@@ -1686,7 +1686,7 @@ static bool test_SetPassword2_all_zero_password( + struct netr_CryptPassword new_password; + struct dcerpc_pipe *p = NULL; + struct dcerpc_binding_handle *b = NULL; +- uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ + + if (!test_SetupCredentials2( + p1, +@@ -4046,7 +4046,7 @@ static bool test_netr_GetForestTrustInformation(struct torture_context *tctx, + struct dcerpc_pipe *p = NULL; + struct dcerpc_binding_handle *b = NULL; + +- if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + machine_credentials, &creds)) { + return false; + } +@@ -4985,7 +4985,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx, + + torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n"); + +- if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + machine_credentials, &creds)) { + return false; + } +@@ -5560,7 +5560,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx, + + torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT); + +- if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, ++ if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, + machine_credentials, &creds)) { + return false; + } +diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c +index ff5dc1d68003..ee8dac67dfa8 100644 +--- a/source4/torture/rpc/samba3rpc.c ++++ b/source4/torture/rpc/samba3rpc.c +@@ -1071,7 +1071,7 @@ static bool auth2(struct torture_context *tctx, + goto done; + } + +- negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; ++ negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; + E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash); + + a.in.server_name = talloc_asprintf( +@@ -1260,10 +1260,19 @@ static bool schan(struct torture_context *tctx, + E_md4hash(cli_credentials_get_password(user_creds), + pinfo.ntpassword.hash); + +- netlogon_creds_arcfour_crypt(creds_state, pinfo.ntpassword.hash, 16); +- + logon.password = &pinfo; + ++ /* ++ * We don't use this here: ++ * ++ * netlogon_creds_encrypt_samlogon_logon(creds_state, ++ * NetlogonInteractiveInformation, ++ * &logon); ++ * ++ * in order to detect bugs ++ */ ++ netlogon_creds_aes_encrypt(creds_state, pinfo.ntpassword.hash, 16); ++ + r.in.logon_level = NetlogonInteractiveInformation; + r.in.logon = &logon; + r.out.return_authenticator = &return_authenticator; +-- +2.34.1 + + +From 5a6eba6e6bf3cd87a5875634d82335b216bf1069 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 09:54:17 +0100 +Subject: [PATCH 15/30] CVE-2022-38023 s4:rpc_server/netlogon: split out + dcesrv_netr_ServerAuthenticate3_check_downgrade() + +We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no', +which means we'll need the downgrade detection in more places. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit b6339fd1dcbe903e73efeea074ab0bd04ef83561) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 114 ++++++++++-------- + 1 file changed, 67 insertions(+), 47 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 3c77d1302993..87e4bbe00f2d 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -125,6 +125,67 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal + return NT_STATUS_OK; + } + ++static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ struct dcesrv_call_state *dce_call, ++ struct netr_ServerAuthenticate3 *r, ++ struct netlogon_server_pipe_state *pipe_state, ++ uint32_t negotiate_flags, ++ NTSTATUS orig_status) ++{ ++ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; ++ bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); ++ bool reject_des_client = !allow_nt4_crypto; ++ bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); ++ ++ if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { ++ reject_des_client = false; ++ } ++ ++ if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ reject_des_client = false; ++ reject_md5_client = false; ++ } ++ ++ if (reject_des_client || reject_md5_client) { ++ /* ++ * Here we match Windows 2012 and return no flags. ++ */ ++ *r->out.negotiate_flags = 0; ++ return NT_STATUS_DOWNGRADE_DETECTED; ++ } ++ ++ /* ++ * This talloc_free is important to prevent re-use of the ++ * challenge. We have to delay it this far due to NETApp ++ * servers per: ++ * https://bugzilla.samba.org/show_bug.cgi?id=11291 ++ */ ++ TALLOC_FREE(pipe_state); ++ ++ /* ++ * At this point we must also cleanup the TDB cache ++ * entry, if we fail the client needs to call ++ * netr_ServerReqChallenge again. ++ * ++ * Note: this handles a non existing record just fine, ++ * the r->in.computer_name might not be the one used ++ * in netr_ServerReqChallenge(), but we are trying to ++ * just tidy up the normal case to prevent re-use. ++ */ ++ schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx, ++ r->in.computer_name); ++ ++ /* ++ * According to Microsoft (see bugid #6099) ++ * Windows 7 looks at the negotiate_flags ++ * returned in this structure *even if the ++ * call fails with access denied! ++ */ ++ *r->out.negotiate_flags = negotiate_flags; ++ ++ return orig_status; ++} ++ + /* + * Do the actual processing of a netr_ServerAuthenticate3 message. + * called from dcesrv_netr_ServerAuthenticate3, which handles the logging. +@@ -152,11 +213,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + "objectSid", "samAccountName", NULL}; + uint32_t server_flags = 0; + uint32_t negotiate_flags = 0; +- bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx); +- bool reject_des_client = !allow_nt4_crypto; +- bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx); + + ZERO_STRUCTP(r->out.return_credentials); ++ *r->out.negotiate_flags = 0; + *r->out.rid = 0; + + pipe_state = dcesrv_iface_state_find_conn(dce_call, +@@ -243,52 +302,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + + negotiate_flags = *r->in.negotiate_flags & server_flags; + +- if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { +- reject_des_client = false; +- } +- +- if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- reject_des_client = false; +- reject_md5_client = false; +- } +- +- if (reject_des_client || reject_md5_client) { +- /* +- * Here we match Windows 2012 and return no flags. +- */ +- *r->out.negotiate_flags = 0; +- return NT_STATUS_DOWNGRADE_DETECTED; ++ nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_OK); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ return nt_status; + } + +- /* +- * This talloc_free is important to prevent re-use of the +- * challenge. We have to delay it this far due to NETApp +- * servers per: +- * https://bugzilla.samba.org/show_bug.cgi?id=11291 +- */ +- TALLOC_FREE(pipe_state); +- +- /* +- * At this point we must also cleanup the TDB cache +- * entry, if we fail the client needs to call +- * netr_ServerReqChallenge again. +- * +- * Note: this handles a non existing record just fine, +- * the r->in.computer_name might not be the one used +- * in netr_ServerReqChallenge(), but we are trying to +- * just tidy up the normal case to prevent re-use. +- */ +- schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx, +- r->in.computer_name); +- +- /* +- * According to Microsoft (see bugid #6099) +- * Windows 7 looks at the negotiate_flags +- * returned in this structure *even if the +- * call fails with access denied! +- */ +- *r->out.negotiate_flags = negotiate_flags; +- + switch (r->in.secure_channel_type) { + case SEC_CHAN_WKSTA: + case SEC_CHAN_DNS_DOMAIN: +-- +2.34.1 + + +From 267a886bcdf3b502d83a3470e9d5b51191210153 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 10:10:33 +0100 +Subject: [PATCH 16/30] CVE-2022-38023 s4:rpc_server/netlogon: require aes if + weak crypto is disabled + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 4c7f84798acd1e3218209d66d1a92e9f42954d51) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 +++++++++ + source4/torture/rpc/netlogon_crypto.c | 2 +- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 87e4bbe00f2d..4141cc40687f 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -137,6 +137,15 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + bool reject_des_client = !allow_nt4_crypto; + bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + ++ /* ++ * If weak cryto is disabled, do not announce that we support RC4. ++ */ ++ if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { ++ /* Without RC4 and DES we require AES */ ++ reject_des_client = true; ++ reject_md5_client = true; ++ } ++ + if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { + reject_des_client = false; + } +diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c +index 05beb2b77b3b..85844604ee27 100644 +--- a/source4/torture/rpc/netlogon_crypto.c ++++ b/source4/torture/rpc/netlogon_crypto.c +@@ -150,7 +150,7 @@ static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p, + force_client_rc4) { + torture_assert_ntstatus_equal(tctx, + a.out.result, +- NT_STATUS_ACCESS_DENIED, ++ NT_STATUS_DOWNGRADE_DETECTED, + "Unexpected status code"); + return false; + } +-- +2.34.1 + + +From 2b4abfc0bf48e89cd93f97f9afcff23e932f427b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 24 Nov 2022 18:26:18 +0100 +Subject: [PATCH 17/30] CVE-2022-38023 docs-xml/smbdotconf: change 'reject md5 + clients' default to yes + +AES is supported by Windows Server >= 2008R2, Windows (Client) >= 7 and Samba >= 4.0, +so there's no reason to allow md5 clients by default. +However some third party domain members may need it. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit c8e53394b98b128ed460a6111faf05dfbad980d1) +--- + docs-xml/smbdotconf/logon/rejectmd5clients.xml | 11 ++++++++--- + lib/param/loadparm.c | 1 + + selftest/target/Samba4.pm | 4 ++++ + source3/param/loadparm.c | 1 + + 4 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +index 0bb9f6f6c8ec..edcbe02e99a3 100644 +--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml ++++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +@@ -7,11 +7,16 @@ + only in 'active directory domain controller' mode), will + reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. + +- You can set this to yes if all domain members support aes. +- This will prevent downgrade attacks. ++ Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows ++ starting with Server 2008R2 and Windows 7, it's available in Samba ++ starting with 4.0, however third party domain members like NetApp ONTAP ++ still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details. ++ ++ The default changed from 'no' to 'yes', with the patches for CVE-2022-38023, ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240 + + This option overrides the 'allow nt4 crypto' option. + + +-no ++yes + +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index e953499efba3..2b644ee97c02 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -2725,6 +2725,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) + lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template"); + + lpcfg_do_global_parameter(lp_ctx, "server schannel", "True"); ++ lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True"); + + lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True"); + +diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm +index d26022466c66..fb63bbeff059 100755 +--- a/selftest/target/Samba4.pm ++++ b/selftest/target/Samba4.pm +@@ -1620,6 +1620,8 @@ sub provision_ad_dc_ntvfs($$$) + client min protocol = CORE + server min protocol = LANMAN1 + ++ reject md5 clients = no ++ + CVE_2020_1472:warn_about_unused_debug_level = 3 + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no +@@ -1985,6 +1987,8 @@ sub provision_ad_dc($$$$$$$) + lpq cache time = 0 + print notify backchannel = yes + ++ reject md5 clients = no ++ + CVE_2020_1472:warn_about_unused_debug_level = 3 + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 91747e09eccd..28ce4de6dd67 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -666,6 +666,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) + Globals.require_strong_key = true; + Globals.reject_md5_servers = true; + Globals.server_schannel = true; ++ Globals.reject_md5_clients = true; + Globals.read_raw = true; + Globals.write_raw = true; + Globals.null_passwords = false; +-- +2.34.1 + + +From d05bde2dfe40483b9f31a94a8d475f628f7aa1e3 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 10:31:08 +0100 +Subject: [PATCH 18/30] CVE-2022-38023 s4:rpc_server/netlogon: defer downgrade + check until we found the account in our SAM + +We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no', +which means we'll need use the account name from our SAM. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit b09f51eefc311bbb1525efd1dc7b9a837f7ec3c2) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 76 +++++++++++++------ + 1 file changed, 53 insertions(+), 23 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 4141cc40687f..e39a530fd7f5 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -311,13 +311,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + + negotiate_flags = *r->in.negotiate_flags & server_flags; + +- nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( +- dce_call, r, pipe_state, negotiate_flags, +- NT_STATUS_OK); +- if (!NT_STATUS_IS_OK(nt_status)) { +- return nt_status; +- } +- + switch (r->in.secure_channel_type) { + case SEC_CHAN_WKSTA: + case SEC_CHAN_DNS_DOMAIN: +@@ -326,16 +319,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + case SEC_CHAN_RODC: + break; + case SEC_CHAN_NULL: +- return NT_STATUS_INVALID_PARAMETER; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_INVALID_PARAMETER); + default: + DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", + r->in.secure_channel_type)); +- return NT_STATUS_INVALID_PARAMETER; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_INVALID_PARAMETER); + } + + sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); + if (sam_ctx == NULL) { +- return NT_STATUS_INVALID_SYSTEM_SERVICE; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_INVALID_SYSTEM_SERVICE); + } + + if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || +@@ -364,16 +363,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + encoded_name = ldb_binary_encode_string(mem_ctx, + r->in.account_name); + if (encoded_name == NULL) { +- return NT_STATUS_NO_MEMORY; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_MEMORY); + } + + len = strlen(encoded_name); + if (len < 2) { +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + + if (require_trailer && encoded_name[len - 1] != trailer) { +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + encoded_name[len - 1] = '\0'; + +@@ -391,30 +396,42 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + "but there's no tdo for [%s] => [%s] \n", + log_escape(mem_ctx, r->in.account_name), + encoded_name)); +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + if (!NT_STATUS_IS_OK(nt_status)) { +- return nt_status; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ nt_status); + } + + nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx, + &curNtHash, + &prevNtHash); + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + if (!NT_STATUS_IS_OK(nt_status)) { +- return nt_status; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ nt_status); + } + + flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL); + if (flatname == NULL) { +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + + *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname); + if (*trust_account_for_search == NULL) { +- return NT_STATUS_NO_MEMORY; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_MEMORY); + } + } else { + *trust_account_for_search = r->in.account_name; +@@ -429,14 +446,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (num_records == 0) { + DEBUG(3,("Couldn't find user [%s] in samdb.\n", + log_escape(mem_ctx, r->in.account_name))); +- return NT_STATUS_NO_TRUST_SAM_ACCOUNT; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + + if (num_records > 1) { + DEBUG(0,("Found %d records matching user [%s]\n", + num_records, + log_escape(mem_ctx, r->in.account_name))); +- return NT_STATUS_INTERNAL_DB_CORRUPTION; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_INTERNAL_DB_CORRUPTION); + } + + *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0], +@@ -445,9 +466,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (*trust_account_in_db == NULL) { + DEBUG(0,("No samAccountName returned in record matching user [%s]\n", + r->in.account_name)); +- return NT_STATUS_INTERNAL_DB_CORRUPTION; ++ return dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_INTERNAL_DB_CORRUPTION); + } +- ++ ++ nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( ++ dce_call, r, pipe_state, negotiate_flags, ++ NT_STATUS_OK); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ return nt_status; ++ } ++ + user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0); + + if (user_account_control & UF_ACCOUNTDISABLE) { +-- +2.34.1 + + +From 88c10a23f06376605a29fc9ddb7737868ffad916 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 13:13:36 +0100 +Subject: [PATCH 19/30] CVE-2022-38023 s4:rpc_server/netlogon: add 'server + reject md5 schannel:COMPUTERACCOUNT = no' and 'allow nt4 + crypto:COMPUTERACCOUNT = yes' + +This makes it more flexible when we change the global default to +'reject md5 servers = yes'. + +'allow nt4 crypto = no' is already the default. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 69b36541606d7064de9648cd54b35adfdf8f0e8f) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 58 ++++++++++++++++++- + 1 file changed, 55 insertions(+), 3 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index e39a530fd7f5..f303dc00ada2 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -130,12 +130,48 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + struct netr_ServerAuthenticate3 *r, + struct netlogon_server_pipe_state *pipe_state, + uint32_t negotiate_flags, ++ const char *trust_account_in_db, + NTSTATUS orig_status) + { + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; +- bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); +- bool reject_des_client = !allow_nt4_crypto; +- bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); ++ bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); ++ bool account_allow_nt4_crypto = global_allow_nt4_crypto; ++ const char *explicit_nt4_opt = NULL; ++ bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); ++ bool account_reject_md5_client = global_reject_md5_client; ++ const char *explicit_md5_opt = NULL; ++ bool reject_des_client; ++ bool allow_nt4_crypto; ++ bool reject_md5_client; ++ ++ /* ++ * We don't use lpcfg_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ ++ if (trust_account_in_db != NULL) { ++ explicit_nt4_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "allow nt4 crypto", ++ trust_account_in_db); ++ } ++ if (explicit_nt4_opt != NULL) { ++ account_allow_nt4_crypto = lp_bool(explicit_nt4_opt); ++ } ++ allow_nt4_crypto = account_allow_nt4_crypto; ++ if (trust_account_in_db != NULL) { ++ explicit_md5_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "server reject md5 schannel", ++ trust_account_in_db); ++ } ++ if (explicit_md5_opt != NULL) { ++ account_reject_md5_client = lp_bool(explicit_md5_opt); ++ } ++ reject_md5_client = account_reject_md5_client; ++ ++ reject_des_client = !allow_nt4_crypto; + + /* + * If weak cryto is disabled, do not announce that we support RC4. +@@ -321,12 +357,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + case SEC_CHAN_NULL: + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_INVALID_PARAMETER); + default: + DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", + r->in.secure_channel_type)); + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_INVALID_PARAMETER); + } + +@@ -334,6 +372,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (sam_ctx == NULL) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_INVALID_SYSTEM_SERVICE); + } + +@@ -365,6 +404,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (encoded_name == NULL) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_MEMORY); + } + +@@ -372,12 +412,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (len < 2) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + + if (require_trailer && encoded_name[len - 1] != trailer) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + encoded_name[len - 1] = '\0'; +@@ -398,11 +440,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + encoded_name)); + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + if (!NT_STATUS_IS_OK(nt_status)) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + nt_status); + } + +@@ -412,11 +456,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + if (!NT_STATUS_IS_OK(nt_status)) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + nt_status); + } + +@@ -424,6 +470,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (flatname == NULL) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + +@@ -431,6 +478,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + if (*trust_account_for_search == NULL) { + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_MEMORY); + } + } else { +@@ -448,6 +496,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + log_escape(mem_ctx, r->in.account_name))); + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_NO_TRUST_SAM_ACCOUNT); + } + +@@ -457,6 +506,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + log_escape(mem_ctx, r->in.account_name))); + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_INTERNAL_DB_CORRUPTION); + } + +@@ -468,11 +518,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( + r->in.account_name)); + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ NULL, /* trust_account_in_db */ + NT_STATUS_INTERNAL_DB_CORRUPTION); + } + + nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, ++ *trust_account_in_db, + NT_STATUS_OK); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; +-- +2.34.1 + + +From b8f6e9fa3e218add0b2ca4fb14bcb9b5167ab8f5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 13:31:14 +0100 +Subject: [PATCH 20/30] CVE-2022-38023 docs-xml/smbdotconf: document "allow nt4 + crypto:COMPUTERACCOUNT = no" + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit bd429d025981b445bf63935063e8e302bfab3f9b) +--- + docs-xml/smbdotconf/logon/allownt4crypto.xml | 76 +++++++++++++++++++- + 1 file changed, 74 insertions(+), 2 deletions(-) + +diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml +index 06afcef73b1b..bbd03a42db74 100644 +--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml ++++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml +@@ -1,11 +1,18 @@ + + ++ ++ This option is deprecated and will be removed in future, ++ as it is a security problem if not set to "no" (which will be ++ the hardcoded behavior in future). ++ ++ + This option controls whether the netlogon server (currently + only in 'active directory domain controller' mode), will +- reject clients which does not support NETLOGON_NEG_STRONG_KEYS ++ reject clients which do not support NETLOGON_NEG_STRONG_KEYS + nor NETLOGON_NEG_SUPPORTS_AES. + + This option was added with Samba 4.2.0. It may lock out clients +@@ -18,8 +25,73 @@ + + "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. + +- This option is over-ridden by the 'reject md5 clients' option. ++ Avoid using this option! Use explicit 'yes' instead! ++ Which is available with the patches for ++ CVE-2022-38023 ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240 ++ ++ ++ Samba will log an error in the log files at log level 0 ++ if legacy a client is rejected or allowed without an explicit, ++ 'yes' option ++ for the client. The message will indicate ++ the explicit 'yes' ++ line to be added, if the legacy client software requires it. (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ ++ This allows admins to use "yes" only for a short grace period, ++ in order to collect the explicit ++ 'yes' options. ++ ++ This option is over-ridden by the 'yes' option. + + + no + ++ ++ ++ ++ ++ If you still have legacy domain members which required 'allow nt4 crypto = yes', ++ it is possible to specify an explicit exception per computer account ++ by using 'allow nt4 crypto:COMPUTERACCOUNT = yes' as option. ++ Note that COMPUTERACCOUNT has to be the sAMAccountName value of ++ the computer account (including the trailing '$' sign). ++ ++ ++ ++ Samba will log a complaint in the log files at log level 0 ++ about the security problem if the option is set to "yes", ++ but the related computer does not require it. ++ (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ ++ ++ Samba will log a warning in the log files at log level 5, ++ if a setting is still needed for the specified computer account. ++ ++ ++ ++ See CVE-2022-38023, ++ https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ ++ ++ This option overrides the option. ++ ++ This option is over-ridden by the 'yes' option. ++ ++ ++ allow nt4 crypto:LEGACYCOMPUTER1$ = yes ++ allow nt4 crypto:NASBOX$ = yes ++ allow nt4 crypto:LEGACYCOMPUTER2$ = yes ++ ++ ++ ++ +-- +2.34.1 + + +From 16895f56b2f35dda0df54b1b416d7fac05965fcc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 14:02:11 +0100 +Subject: [PATCH 21/30] CVE-2022-38023 docs-xml/smbdotconf: document "server + reject md5 schannel:COMPUTERACCOUNT" + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 2ad302b42254e3c2800aaf11669fe2e6d55fa8a1) +--- + docs-xml/smbdotconf/logon/allownt4crypto.xml | 13 ++- + .../smbdotconf/logon/rejectmd5clients.xml | 96 ++++++++++++++++++- + 2 files changed, 103 insertions(+), 6 deletions(-) + +diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml +index bbd03a42db74..ee63e6cc2453 100644 +--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml ++++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml +@@ -45,7 +45,9 @@ + in order to collect the explicit + 'yes' options. + +- This option is over-ridden by the 'yes' option. ++ This option is over-ridden by the effective value of 'yes' from ++ the '' ++ and/or '' options. + + + no +@@ -85,12 +87,19 @@ + + This option overrides the option. + +- This option is over-ridden by the 'yes' option. ++ This option is over-ridden by the effective value of 'yes' from ++ the '' ++ and/or '' options. ++ Which means 'yes' ++ is only useful in combination with 'no' + + + allow nt4 crypto:LEGACYCOMPUTER1$ = yes ++ server reject md5 schannel:LEGACYCOMPUTER1$ = no + allow nt4 crypto:NASBOX$ = yes ++ server reject md5 schannel:NASBOX$ = no + allow nt4 crypto:LEGACYCOMPUTER2$ = yes ++ server reject md5 schannel:LEGACYCOMPUTER2$ = no + + + +diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +index edcbe02e99a3..fe7701d92772 100644 +--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml ++++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml +@@ -1,8 +1,15 @@ + + ++ ++ This option is deprecated and will be removed in a future release, ++ as it is a security problem if not set to "yes" (which will be ++ the hardcoded behavior in the future). ++ ++ + This option controls whether the netlogon server (currently + only in 'active directory domain controller' mode), will + reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. +@@ -10,13 +17,94 @@ + Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows + starting with Server 2008R2 and Windows 7, it's available in Samba + starting with 4.0, however third party domain members like NetApp ONTAP +- still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details. ++ still uses RC4 (HMAC-MD5), see ++ https://www.samba.org/samba/security/CVE-2022-38023.html ++ for more details. ++ ++ ++ The default changed from 'no' to 'yes', with the patches for ++ CVE-2022-38023 ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ ++ ++ Avoid using this option! Use an explicit per machine account ++ '' instead! ++ Which is available with the patches for ++ CVE-2022-38023 ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ + +- The default changed from 'no' to 'yes', with the patches for CVE-2022-38023, +- see https://bugzilla.samba.org/show_bug.cgi?id=15240 ++ ++ Samba will log an error in the log files at log level 0 ++ if legacy a client is rejected or allowed without an explicit, ++ 'no' option ++ for the client. The message will indicate ++ the explicit 'no' ++ line to be added, if the legacy client software requires it. (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ + +- This option overrides the 'allow nt4 crypto' option. ++ This allows admins to use "no" only for a short grace period, ++ in order to collect the explicit ++ 'no' options. ++ ++ When set to 'yes' this option overrides the ++ '' and ++ '' options and implies ++ 'no'. ++ + + + yes + ++ ++ ++ ++ ++ If you still have legacy domain members or trusted domains, ++ which required "reject md5 clients = no" before, ++ it is possible to specify an explicit exception per computer account ++ by setting 'server reject md5 schannel:COMPUTERACCOUNT = no'. ++ Note that COMPUTERACCOUNT has to be the sAMAccountName value of ++ the computer account (including the trailing '$' sign). ++ ++ ++ ++ Samba will log a complaint in the log files at log level 0 ++ about the security problem if the option is set to "no", ++ but the related computer does not require it. ++ (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ ++ ++ Samba will log a warning in the log files at log level 5 ++ if a setting is still needed for the specified computer account. ++ ++ ++ ++ See CVE-2022-38023, ++ https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ ++ ++ This option overrides the option. ++ ++ When set to 'yes' this option overrides the ++ '' and ++ '' options and implies ++ 'no'. ++ ++ ++ ++ server reject md5 schannel:LEGACYCOMPUTER1$ = no ++ server reject md5 schannel:NASBOX$ = no ++ server reject md5 schannel:LEGACYCOMPUTER2$ = no ++ ++ ++ ++ +-- +2.34.1 + + +From 71283bb55feb027a94c3795bd1b94217be93c1a6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 13:13:36 +0100 +Subject: [PATCH 22/30] CVE-2022-38023 s4:rpc_server/netlogon: debug 'reject + md5 servers' and 'allow nt4 crypto' misconfigurations + +This allows the admin to notice what's wrong in order to adjust the +configuration if required. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 43df4be35950f491864ae8ada05d51b42a556381) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 143 ++++++++++++++++++ + 1 file changed, 143 insertions(+) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index f303dc00ada2..5f2f765abe5b 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -64,10 +64,34 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context + const struct dcesrv_interface *iface) + { + struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; ++ bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); ++ bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); ++ static bool warned_global_nt4_once = false; ++ static bool warned_global_md5_once = false; + static bool warned_global_schannel_once = false; + ++ if (global_allow_nt4_crypto && !warned_global_nt4_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'allow nt4 crypto = no' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_nt4_once = true; ++ } ++ ++ if (!global_reject_md5_client && !warned_global_md5_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2022-38023: " ++ "Please configure 'reject md5 clients = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_md5_once = true; ++ } ++ + if (!schannel_global_required && !warned_global_schannel_once) { + /* + * We want admins to notice their misconfiguration! +@@ -143,6 +167,12 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + bool reject_des_client; + bool allow_nt4_crypto; + bool reject_md5_client; ++ bool need_des = true; ++ bool need_md5 = true; ++ int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); ++ int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); + + /* + * We don't use lpcfg_parm_bool(), as we +@@ -183,19 +213,84 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + } + + if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { ++ need_des = false; + reject_des_client = false; + } + + if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ need_des = false; ++ need_md5 = false; + reject_des_client = false; + reject_md5_client = false; + } + + if (reject_des_client || reject_md5_client) { ++ TALLOC_CTX *frame = talloc_stackframe(); ++ ++ if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { ++ if (CVE_2022_38023_error_level < DBGLVL_NOTICE) { ++ CVE_2022_38023_error_level = DBGLVL_NOTICE; ++ } ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: " ++ "client_account[%s] computer_name[%s] " ++ "schannel_type[%u] " ++ "client_negotiate_flags[0x%x] " ++ "%s%s%s " ++ "NT_STATUS_DOWNGRADE_DETECTED " ++ "WEAK_CRYPTO_DISALLOWED\n", ++ log_escape(frame, r->in.account_name), ++ log_escape(frame, r->in.computer_name), ++ r->in.secure_channel_type, ++ (unsigned)*r->in.negotiate_flags, ++ trust_account_in_db ? "real_account[" : "", ++ trust_account_in_db ? trust_account_in_db : "", ++ trust_account_in_db ? "]" : "")); ++ goto return_downgrade; ++ } ++ ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: " ++ "client_account[%s] computer_name[%s] " ++ "schannel_type[%u] " ++ "client_negotiate_flags[0x%x] " ++ "%s%s%s " ++ "NT_STATUS_DOWNGRADE_DETECTED " ++ "reject_des[%u] reject_md5[%u]\n", ++ log_escape(frame, r->in.account_name), ++ log_escape(frame, r->in.computer_name), ++ r->in.secure_channel_type, ++ (unsigned)*r->in.negotiate_flags, ++ trust_account_in_db ? "real_account[" : "", ++ trust_account_in_db ? trust_account_in_db : "", ++ trust_account_in_db ? "]" : "", ++ reject_des_client, ++ reject_md5_client)); ++ if (trust_account_in_db == NULL) { ++ goto return_downgrade; ++ } ++ ++ if (reject_md5_client && explicit_md5_opt == NULL) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server reject md5 schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ trust_account_in_db)); ++ } ++ if (reject_des_client && explicit_nt4_opt == NULL) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'allow nt4 crypto:%s = yes' " ++ "might be needed for a legacy client.\n", ++ trust_account_in_db)); ++ } ++ ++return_downgrade: + /* + * Here we match Windows 2012 and return no flags. + */ + *r->out.negotiate_flags = 0; ++ TALLOC_FREE(frame); + return NT_STATUS_DOWNGRADE_DETECTED; + } + +@@ -228,6 +323,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + */ + *r->out.negotiate_flags = negotiate_flags; + ++ if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) { ++ return orig_status; ++ } ++ ++ if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) { ++ D_INFO("CVE-2022-38023: Check if option " ++ "'server reject md5 schannel:%s = yes' not needed!?\n", ++ trust_account_in_db); ++ } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) { ++ D_INFO("CVE-2022-38023: Check if option " ++ "'server reject md5 schannel:%s = no' " ++ "still needed for a legacy client.\n", ++ trust_account_in_db); ++ } else if (need_md5 && explicit_md5_opt == NULL) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server reject md5 schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ trust_account_in_db)); ++ } else if (!account_reject_md5_client && explicit_md5_opt) { ++ DEBUG(CVE_2022_38023_warn_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server reject md5 schannel:%s = no' not needed!?\n", ++ trust_account_in_db)); ++ } ++ ++ if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) { ++ D_INFO("CVE-2022-38023: Check if option " ++ "'allow nt4 crypto:%s = no' not needed!?\n", ++ trust_account_in_db); ++ } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) { ++ D_INFO("CVE-2022-38023: Check if option " ++ "'allow nt4 crypto:%s = yes' " ++ "still needed for a legacy client.\n", ++ trust_account_in_db); ++ } else if (need_des && explicit_nt4_opt == NULL) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'allow nt4 crypto:%s = yes' " ++ "might be needed for a legacy client.\n", ++ trust_account_in_db)); ++ } else if (account_allow_nt4_crypto && explicit_nt4_opt) { ++ DEBUG(CVE_2022_38023_warn_level, ( ++ "CVE-2022-38023: Check if option " ++ "'allow nt4 crypto:%s = yes' not needed!?\n", ++ trust_account_in_db)); ++ } ++ + return orig_status; + } + +-- +2.34.1 + + +From ab3062a57e170f90bca2d88771559d7c5ea38837 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 14:57:20 +0100 +Subject: [PATCH 23/30] CVE-2022-38023 selftest:Samba4: avoid global 'allow nt4 + crypto = yes' and 'reject md5 clients = no' + +Instead of using the generic deprecated option use the specific +allow nt4 crypto:COMPUTERACCOUNT = yes and +server reject md5 schannel:COMPUTERACCOUNT = no +in order to allow legacy tests for pass. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 7ae3735810c2db32fa50f309f8af3c76ffa29768) +--- + selftest/target/Samba4.pm | 60 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 53 insertions(+), 7 deletions(-) + +diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm +index fb63bbeff059..b61acbf8e57b 100755 +--- a/selftest/target/Samba4.pm ++++ b/selftest/target/Samba4.pm +@@ -1608,7 +1608,6 @@ sub provision_ad_dc_ntvfs($$$) + my $extra_conf_options = "netbios aliases = localDC1-a + server services = +winbind -winbindd + ldap server require strong auth = allow_sasl_over_tls +- allow nt4 crypto = yes + raw NTLMv2 auth = yes + lsa over netlogon = yes + rpc server port = 1027 +@@ -1620,9 +1619,19 @@ sub provision_ad_dc_ntvfs($$$) + client min protocol = CORE + server min protocol = LANMAN1 + +- reject md5 clients = no +- + CVE_2020_1472:warn_about_unused_debug_level = 3 ++ CVE_2022_38023:warn_about_unused_debug_level = 3 ++ allow nt4 crypto:torturetest\$ = yes ++ server reject md5 schannel:schannel2\$ = no ++ server reject md5 schannel:schannel3\$ = no ++ server reject md5 schannel:schannel8\$ = no ++ server reject md5 schannel:schannel9\$ = no ++ server reject md5 schannel:torturetest\$ = no ++ server reject md5 schannel:tests4u2proxywk\$ = no ++ server reject md5 schannel:tests4u2selfbdc\$ = no ++ server reject md5 schannel:tests4u2selfwk\$ = no ++ server reject md5 schannel:torturepacbdc\$ = no ++ server reject md5 schannel:torturepacwksta\$ = no + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no + server require schannel:schannel2\$ = no +@@ -1677,6 +1686,13 @@ sub provision_fl2000dc($$) + kdc enable fast = no + spnego:simulate_w2k=yes + ntlmssp_server:force_old_spnego=yes ++ ++ CVE_2022_38023:warn_about_unused_debug_level = 3 ++ server reject md5 schannel:tests4u2proxywk\$ = no ++ server reject md5 schannel:tests4u2selfbdc\$ = no ++ server reject md5 schannel:tests4u2selfwk\$ = no ++ server reject md5 schannel:torturepacbdc\$ = no ++ server reject md5 schannel:torturepacwksta\$ = no + "; + my $extra_provision_options = ["--base-schema=2008_R2"]; + # This environment uses plain text secrets +@@ -1717,11 +1733,23 @@ sub provision_fl2003dc($$$) + my $ip_addr2 = Samba::get_ipv6_addr("fakednsforwarder2"); + + print "PROVISIONING DC WITH FOREST LEVEL 2003...\n"; +- my $extra_conf_options = "allow dns updates = nonsecure and secure ++ my $extra_conf_options = " ++ allow dns updates = nonsecure and secure ++ + kdc enable fast = no + dcesrv:header signing = no + dcesrv:max auth states = 0 +- dns forwarder = $ip_addr1 [$ip_addr2]:54"; ++ ++ dns forwarder = $ip_addr1 [$ip_addr2]:54 ++ ++ CVE_2022_38023:warn_about_unused_debug_level = 3 ++ server reject md5 schannel:tests4u2proxywk\$ = no ++ server reject md5 schannel:tests4u2selfbdc\$ = no ++ server reject md5 schannel:tests4u2selfwk\$ = no ++ server reject md5 schannel:torturepacbdc\$ = no ++ server reject md5 schannel:torturepacwksta\$ = no ++"; ++ + my $extra_provision_options = ["--base-schema=2008_R2"]; + my $ret = $self->provision($prefix, + "domain controller", +@@ -1776,6 +1804,13 @@ sub provision_fl2008r2dc($$$) + ldap server require strong auth = no + # delay by 10 seconds, 10^7 usecs + ldap_server:delay_expire_disconnect = 10000 ++ ++ CVE_2022_38023:warn_about_unused_debug_level = 3 ++ server reject md5 schannel:tests4u2proxywk\$ = no ++ server reject md5 schannel:tests4u2selfbdc\$ = no ++ server reject md5 schannel:tests4u2selfwk\$ = no ++ server reject md5 schannel:torturepacbdc\$ = no ++ server reject md5 schannel:torturepacwksta\$ = no + "; + my $extra_provision_options = ["--base-schema=2008_R2"]; + my $ret = $self->provision($prefix, +@@ -1987,9 +2022,20 @@ sub provision_ad_dc($$$$$$$) + lpq cache time = 0 + print notify backchannel = yes + +- reject md5 clients = no +- + CVE_2020_1472:warn_about_unused_debug_level = 3 ++ CVE_2022_38023:warn_about_unused_debug_level = 3 ++ CVE_2022_38023:error_debug_level = 2 ++ server reject md5 schannel:schannel2\$ = no ++ server reject md5 schannel:schannel3\$ = no ++ server reject md5 schannel:schannel8\$ = no ++ server reject md5 schannel:schannel9\$ = no ++ server reject md5 schannel:torturetest\$ = no ++ server reject md5 schannel:tests4u2proxywk\$ = no ++ server reject md5 schannel:tests4u2selfbdc\$ = no ++ server reject md5 schannel:tests4u2selfwk\$ = no ++ server reject md5 schannel:torturepacbdc\$ = no ++ server reject md5 schannel:torturepacwksta\$ = no ++ server reject md5 schannel:samlogontest\$ = no + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no + server require schannel:schannel2\$ = no +-- +2.34.1 + + +From 8ab5154b071bc02c540da963cf1c7e15cbf6c63b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 16:57:24 +0100 +Subject: [PATCH 24/30] CVE-2022-38023 s4:rpc_server/netlogon: split out + dcesrv_netr_check_schannel() function + +This will allow us to reuse the function in other places. +As it will also get some additional checks soon. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit f43dc4f0bd60d4e127b714565147f82435aa4f07) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 84 +++++++++++-------- + 1 file changed, 51 insertions(+), 33 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 5f2f765abe5b..8e952ec2e0c7 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -877,18 +877,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca + return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); + } + +-/* +- * NOTE: The following functions are nearly identical to the ones available in +- * source3/rpc_server/srv_nelog_nt.c +- * The reason we keep 2 copies is that they use different structures to +- * represent the auth_info and the decrpc pipes. +- */ +-static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, +- TALLOC_CTX *mem_ctx, +- const char *computer_name, +- struct netr_Authenticator *received_authenticator, +- struct netr_Authenticator *return_authenticator, +- struct netlogon_creds_CredentialState **creds_out) ++static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ uint16_t opnum) + { + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + TALLOC_CTX *frame = talloc_stackframe(); +@@ -897,15 +890,11 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + bool schannel_global_required = (schannel == true); + bool schannel_required = schannel_global_required; + const char *explicit_opt = NULL; +- struct netlogon_creds_CredentialState *creds = NULL; + int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); + unsigned int dbg_lvl = DBGLVL_DEBUG; +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; +- enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; +- uint16_t opnum = dce_call->pkt.u.request.opnum; + const char *opname = ""; + const char *reason = ""; + +@@ -913,8 +902,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + opname = ndr_table_netlogon.calls[opnum].name; + } + +- dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); +- + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + reason = "WITH SEALED"; +@@ -927,17 +914,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + reason = "WITHOUT"; + } + +- nt_status = schannel_check_creds_state(mem_ctx, +- lp_ctx, +- computer_name, +- received_authenticator, +- return_authenticator, +- &creds); +- if (!NT_STATUS_IS_OK(nt_status)) { +- ZERO_STRUCTP(return_authenticator); +- return nt_status; +- } +- + /* + * We don't use lpcfg_parm_bool(), as we + * need the explicit_opt pointer in order to +@@ -977,7 +953,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + log_escape(frame, creds->computer_name))); + } + +- *creds_out = creds; + TALLOC_FREE(frame); + return nt_status; + } +@@ -1011,8 +986,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } +- TALLOC_FREE(creds); +- ZERO_STRUCTP(return_authenticator); + TALLOC_FREE(frame); + return nt_status; + } +@@ -1056,11 +1029,56 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + log_escape(frame, creds->computer_name))); + } + +- *creds_out = creds; + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + ++/* ++ * NOTE: The following functions are nearly identical to the ones available in ++ * source3/rpc_server/srv_nelog_nt.c ++ * The reason we keep 2 copies is that they use different structures to ++ * represent the auth_info and the decrpc pipes. ++ */ ++static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, ++ TALLOC_CTX *mem_ctx, ++ const char *computer_name, ++ struct netr_Authenticator *received_authenticator, ++ struct netr_Authenticator *return_authenticator, ++ struct netlogon_creds_CredentialState **creds_out) ++{ ++ NTSTATUS nt_status; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; ++ ++ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); ++ ++ nt_status = schannel_check_creds_state(mem_ctx, ++ dce_call->conn->dce_ctx->lp_ctx, ++ computer_name, ++ received_authenticator, ++ return_authenticator, ++ &creds); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ ZERO_STRUCTP(return_authenticator); ++ return nt_status; ++ } ++ ++ nt_status = dcesrv_netr_check_schannel(dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ dce_call->pkt.u.request.opnum); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ TALLOC_FREE(creds); ++ ZERO_STRUCTP(return_authenticator); ++ return nt_status; ++ } ++ ++ *creds_out = creds; ++ return NT_STATUS_OK; ++} ++ + /* + Change the machine account password for the currently connected + client. Supplies only the NT#. +-- +2.34.1 + + +From 875734d5294ff48950a24d6a89be52c916307bc2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 17:15:36 +0100 +Subject: [PATCH 25/30] CVE-2022-38023 s4:rpc_server/netlogon: make sure all + dcesrv_netr_LogonSamLogon*() calls go through dcesrv_netr_check_schannel() + +We'll soon add some additional contraints in dcesrv_netr_check_schannel(), +which are also required for dcesrv_netr_LogonSamLogonEx(). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 689507457f5e6666488732f91a355a2183fb1662) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 36 +++++++++++++++---- + 1 file changed, 29 insertions(+), 7 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 8e952ec2e0c7..d5bca620b0d4 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -1441,6 +1441,35 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL + struct auth_usersupplied_info *user_info = NULL; + NTSTATUS nt_status; + struct tevent_req *subreq = NULL; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; ++ ++ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); ++ ++ switch (dce_call->pkt.u.request.opnum) { ++ case NDR_NETR_LOGONSAMLOGON: ++ case NDR_NETR_LOGONSAMLOGONWITHFLAGS: ++ /* ++ * These already called dcesrv_netr_check_schannel() ++ * via dcesrv_netr_creds_server_step_check() ++ */ ++ break; ++ case NDR_NETR_LOGONSAMLOGONEX: ++ default: ++ if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ nt_status = dcesrv_netr_check_schannel(dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ dce_call->pkt.u.request.opnum); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ return nt_status; ++ } ++ break; ++ } + + *r->out.authoritative = 1; + +@@ -1789,7 +1818,6 @@ static void dcesrv_netr_LogonSamLogon_base_reply( + static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct netr_LogonSamLogonEx *r) + { +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + struct dcesrv_netr_LogonSamLogon_base_state *state; + NTSTATUS nt_status; + +@@ -1827,12 +1855,6 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, + return nt_status; + } + +- dcesrv_call_auth_info(dce_call, &auth_type, NULL); +- +- if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { +- return NT_STATUS_ACCESS_DENIED; +- } +- + nt_status = dcesrv_netr_LogonSamLogon_base_call(state); + + if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { +-- +2.34.1 + + +From 9c294a19374d15f04649c62f4e5f8df6a59610a5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 16:53:35 +0100 +Subject: [PATCH 26/30] CVE-2022-38023 docs-xml/smbdotconf: add "server + schannel require seal[:COMPUTERACCOUNT]" options + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 7732a4b0bde1d9f98a0371f17d22648495329470) +--- + .../smbdotconf/security/serverschannel.xml | 43 ++++++- + .../security/serverschannelrequireseal.xml | 118 ++++++++++++++++++ + lib/param/loadparm.c | 1 + + source3/param/loadparm.c | 1 + + 4 files changed, 157 insertions(+), 6 deletions(-) + create mode 100644 docs-xml/smbdotconf/security/serverschannelrequireseal.xml + +diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml +index 3e66df1c2032..42a657912cac 100644 +--- a/docs-xml/smbdotconf/security/serverschannel.xml ++++ b/docs-xml/smbdotconf/security/serverschannel.xml +@@ -12,19 +12,37 @@ + the hardcoded behavior in future). + + +- +- Samba will complain in the log files at log level 0, +- about the security problem if the option is not set to "yes". ++ Avoid using this option! Use explicit 'no' instead! + ++ ++ ++ Samba will log an error in the log files at log level 0 ++ if legacy a client is rejected or allowed without an explicit, ++ 'no' option ++ for the client. The message will indicate ++ the explicit 'no' ++ line to be added, if the legacy client software requires it. (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ + +- See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ This allows admins to use "auto" only for a short grace period, ++ in order to collect the explicit ++ 'no' options. + + +- If you still have legacy domain members use the option. ++ ++ See CVE-2020-1472(ZeroLogon), ++ https://bugzilla.samba.org/show_bug.cgi?id=14497. + + + This option is over-ridden by the option. + ++ This option is over-ridden by the effective value of 'yes' from ++ the '' ++ and/or '' options. ++ + + + yes +@@ -48,6 +66,9 @@ + about the security problem if the option is not set to "no", + but the related computer is actually using the netlogon + secure channel (schannel) feature. ++ (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). + + + +@@ -56,15 +77,25 @@ + + + +- See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ See CVE-2020-1472(ZeroLogon), ++ https://bugzilla.samba.org/show_bug.cgi?id=14497. + + + This option overrides the option. + ++ This option is over-ridden by the effective value of 'yes' from ++ the '' ++ and/or '' options. ++ Which means 'no' ++ is only useful in combination with 'no' ++ + + server require schannel:LEGACYCOMPUTER1$ = no ++ server require schannel seal:LEGACYCOMPUTER1$ = no + server require schannel:NASBOX$ = no ++ server require schannel seal:NASBOX$ = no + server require schannel:LEGACYCOMPUTER2$ = no ++ server require schannel seal:LEGACYCOMPUTER2$ = no + + + +diff --git a/docs-xml/smbdotconf/security/serverschannelrequireseal.xml b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml +new file mode 100644 +index 000000000000..d4620d1252dd +--- /dev/null ++++ b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml +@@ -0,0 +1,118 @@ ++ ++ ++ ++ ++ This option is deprecated and will be removed in future, ++ as it is a security problem if not set to "yes" (which will be ++ the hardcoded behavior in future). ++ ++ ++ ++ This option controls whether the netlogon server (currently ++ only in 'active directory domain controller' mode), will ++ reject the usage of netlogon secure channel without privacy/enryption. ++ ++ ++ ++ The option is modelled after the registry key available on Windows. ++ ++ ++ ++ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\RequireSeal=2 ++ ++ ++ ++ Avoid using this option! Use the per computer account specific option ++ '' instead! ++ Which is available with the patches for ++ CVE-2022-38023 ++ see https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ ++ ++ ++ Samba will log an error in the log files at log level 0 ++ if legacy a client is rejected or allowed without an explicit, ++ 'no' option ++ for the client. The message will indicate ++ the explicit 'no' ++ line to be added, if the legacy client software requires it. (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ ++ This allows admins to use "no" only for a short grace period, ++ in order to collect the explicit ++ 'no' options. ++ ++ ++ When set to 'yes' this option overrides the ++ '' and ++ '' options and implies ++ 'yes'. ++ ++ ++ ++ This option is over-ridden by the option. ++ ++ ++ ++ ++yes ++ ++ ++ ++ ++ ++ ++ If you still have legacy domain members, which required "server schannel require seal = no" before, ++ it is possible to specify explicit exception per computer account ++ by using 'server schannel require seal:COMPUTERACCOUNT = no' as option. ++ Note that COMPUTERACCOUNT has to be the sAMAccountName value of ++ the computer account (including the trailing '$' sign). ++ ++ ++ ++ Samba will log a complaint in the log files at log level 0 ++ about the security problem if the option is set to "no", ++ but the related computer does not require it. ++ (The log level can be adjusted with ++ '1' ++ in order to complain only at a higher log level). ++ ++ ++ ++ Samba will warn in the log files at log level 5, ++ if a setting is still needed for the specified computer account. ++ ++ ++ ++ See CVE-2022-38023, ++ https://bugzilla.samba.org/show_bug.cgi?id=15240. ++ ++ ++ ++ This option overrides the '' option. ++ ++ ++ ++ When set to 'yes' this option overrides the ++ '' and ++ '' options and implies ++ 'yes'. ++ ++ ++ ++ server require schannel seal:LEGACYCOMPUTER1$ = no ++ server require schannel seal:NASBOX$ = no ++ server require schannel seal:LEGACYCOMPUTER2$ = no ++ ++ ++ ++ +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index 2b644ee97c02..2b1eec5c4a12 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -2725,6 +2725,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) + lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template"); + + lpcfg_do_global_parameter(lp_ctx, "server schannel", "True"); ++ lpcfg_do_global_parameter(lp_ctx, "server schannel require seal", "True"); + lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True"); + + lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True"); +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index 28ce4de6dd67..443b63a1cf46 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -666,6 +666,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) + Globals.require_strong_key = true; + Globals.reject_md5_servers = true; + Globals.server_schannel = true; ++ Globals.server_schannel_require_seal = true; + Globals.reject_md5_clients = true; + Globals.read_raw = true; + Globals.write_raw = true; +-- +2.34.1 + + +From 422a2c9adcc39edb4a9ea3da435a7b53822f6ccc Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 2 Dec 2022 14:31:26 +0100 +Subject: [PATCH 27/30] CVE-2022-38023 s4:rpc_server/netlogon: add a per + connection cache to dcesrv_netr_check_schannel() + +It's enough to warn the admin once per connection. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 3c57608e1109c1d6e8bb8fbad2ef0b5d79d00e1a) +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 193 ++++++++++++++---- + 1 file changed, 153 insertions(+), 40 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index d5bca620b0d4..624c8d407242 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -877,23 +877,105 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca + return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); + } + +-static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, +- const struct netlogon_creds_CredentialState *creds, +- enum dcerpc_AuthType auth_type, +- enum dcerpc_AuthLevel auth_level, +- uint16_t opnum) ++struct dcesrv_netr_check_schannel_state { ++ struct dom_sid account_sid; ++ enum dcerpc_AuthType auth_type; ++ enum dcerpc_AuthLevel auth_level; ++ ++ bool schannel_global_required; ++ bool schannel_required; ++ bool schannel_explicitly_set; ++ ++ NTSTATUS result; ++}; ++ ++static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ struct dcesrv_netr_check_schannel_state **_s) + { + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; +- TALLOC_CTX *frame = talloc_stackframe(); +- NTSTATUS nt_status; + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); + bool schannel_required = schannel_global_required; + const char *explicit_opt = NULL; ++#define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) ++ struct dcesrv_netr_check_schannel_state *s = NULL; ++ NTSTATUS status; ++ ++ *_s = NULL; ++ ++ s = dcesrv_iface_state_find_conn(dce_call, ++ DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, ++ struct dcesrv_netr_check_schannel_state); ++ if (s != NULL) { ++ if (!dom_sid_equal(&s->account_sid, creds->sid)) { ++ goto new_state; ++ } ++ if (s->auth_type != auth_type) { ++ goto new_state; ++ } ++ if (s->auth_level != auth_level) { ++ goto new_state; ++ } ++ ++ *_s = s; ++ return NT_STATUS_OK; ++ } ++ ++new_state: ++ TALLOC_FREE(s); ++ s = talloc_zero(dce_call, ++ struct dcesrv_netr_check_schannel_state); ++ if (s == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ s->account_sid = *creds->sid; ++ s->auth_type = auth_type; ++ s->auth_level = auth_level; ++ s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; ++ ++ /* ++ * We don't use lpcfg_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ explicit_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "server require schannel", ++ creds->account_name); ++ if (explicit_opt != NULL) { ++ schannel_required = lp_bool(explicit_opt); ++ } ++ ++ s->schannel_global_required = schannel_global_required; ++ s->schannel_required = schannel_required; ++ s->schannel_explicitly_set = explicit_opt != NULL; ++ ++ status = dcesrv_iface_state_store_conn(dce_call, ++ DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, ++ s); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ *_s = s; ++ return NT_STATUS_OK; ++} ++ ++static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call, ++ struct dcesrv_netr_check_schannel_state *s, ++ const struct netlogon_creds_CredentialState *creds, ++ uint16_t opnum) ++{ ++ struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); ++ TALLOC_CTX *frame = talloc_stackframe(); + unsigned int dbg_lvl = DBGLVL_DEBUG; + const char *opname = ""; + const char *reason = ""; +@@ -902,37 +984,43 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + opname = ndr_table_netlogon.calls[opnum].name; + } + +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + reason = "WITH SEALED"; +- } else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { ++ } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { + reason = "WITH SIGNED"; + } else { +- smb_panic("Schannel without SIGN/SEAL"); ++ reason = "WITH INVALID"; ++ dbg_lvl = DBGLVL_ERR; ++ s->result = NT_STATUS_INTERNAL_ERROR; + } + } else { + reason = "WITHOUT"; + } + +- /* +- * We don't use lpcfg_parm_bool(), as we +- * need the explicit_opt pointer in order to +- * adjust the debug messages. +- */ +- explicit_opt = lpcfg_get_parametric(lp_ctx, +- NULL, +- "server require schannel", +- creds->account_name); +- if (explicit_opt != NULL) { +- schannel_required = lp_bool(explicit_opt); ++ if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) { ++ if (!NT_STATUS_IS_OK(s->result)) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ TALLOC_FREE(frame); ++ return s->result; + } + +- if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +- nt_status = NT_STATUS_OK; ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ s->result = NT_STATUS_OK; + +- if (explicit_opt != NULL && !schannel_required) { ++ if (s->schannel_explicitly_set && !s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); +- } else if (!schannel_required) { ++ } else if (!s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } + +@@ -943,9 +1031,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), +- nt_errstr(nt_status))); +- +- if (explicit_opt != NULL && !schannel_required) { ++ nt_errstr(s->result))); ++ if (s->schannel_explicitly_set && !s->schannel_required) { + DEBUG(CVE_2020_1472_warn_level, ( + "CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' not needed for '%s'!\n", +@@ -954,13 +1041,13 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + } + + TALLOC_FREE(frame); +- return nt_status; ++ return s->result; + } + +- if (schannel_required) { +- nt_status = NT_STATUS_ACCESS_DENIED; ++ if (s->schannel_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; + +- if (explicit_opt != NULL) { ++ if (s->schannel_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); +@@ -973,8 +1060,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), +- nt_errstr(nt_status))); +- if (explicit_opt != NULL) { ++ nt_errstr(s->result))); ++ if (s->schannel_explicitly_set) { + D_NOTICE("CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = yes' " + "rejects access for client.\n", +@@ -987,12 +1074,12 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + log_escape(frame, creds->account_name))); + } + TALLOC_FREE(frame); +- return nt_status; ++ return s->result; + } + +- nt_status = NT_STATUS_OK; ++ s->result = NT_STATUS_OK; + +- if (explicit_opt != NULL) { ++ if (s->schannel_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); +@@ -1005,9 +1092,9 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), +- nt_errstr(nt_status))); ++ nt_errstr(s->result))); + +- if (explicit_opt != NULL) { ++ if (s->schannel_explicitly_set) { + D_INFO("CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = no' " + "still needed for '%s'!\n", +@@ -1030,6 +1117,32 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + } + + TALLOC_FREE(frame); ++ return s->result; ++} ++ ++static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, ++ const struct netlogon_creds_CredentialState *creds, ++ enum dcerpc_AuthType auth_type, ++ enum dcerpc_AuthLevel auth_level, ++ uint16_t opnum) ++{ ++ struct dcesrv_netr_check_schannel_state *s = NULL; ++ NTSTATUS status; ++ ++ status = dcesrv_netr_check_schannel_get_state(dce_call, ++ creds, ++ auth_type, ++ auth_level, ++ &s); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ ++ status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum); ++ if (!NT_STATUS_IS_OK(status)) { ++ return status; ++ } ++ + return NT_STATUS_OK; + } + +-- +2.34.1 + + +From 78d79aade1f07776266e22829a53a594bb2968b8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 25 Nov 2022 14:05:30 +0100 +Subject: [PATCH 28/30] CVE-2022-38023 s4:rpc_server/netlogon: implement + "server schannel require seal[:COMPUTERACCOUNT]" + +By default we'll now require schannel connections with +privacy/sealing/encryption. + +But we allow exceptions for specific computer/trust accounts. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit b3ed90a0541a271a7c6d4bee1201fa47adc3c0c1) +--- + selftest/target/Samba4.pm | 28 ++ + source4/rpc_server/netlogon/dcerpc_netlogon.c | 244 +++++++++++++++++- + 2 files changed, 271 insertions(+), 1 deletion(-) + +diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm +index b61acbf8e57b..087860b9ebdd 100755 +--- a/selftest/target/Samba4.pm ++++ b/selftest/target/Samba4.pm +@@ -1645,9 +1645,23 @@ sub provision_ad_dc_ntvfs($$$) + server require schannel:schannel10\$ = no + server require schannel:schannel11\$ = no + server require schannel:torturetest\$ = no ++ server schannel require seal:schannel0\$ = no ++ server schannel require seal:schannel1\$ = no ++ server schannel require seal:schannel2\$ = no ++ server schannel require seal:schannel3\$ = no ++ server schannel require seal:schannel4\$ = no ++ server schannel require seal:schannel5\$ = no ++ server schannel require seal:schannel6\$ = no ++ server schannel require seal:schannel7\$ = no ++ server schannel require seal:schannel8\$ = no ++ server schannel require seal:schannel9\$ = no ++ server schannel require seal:schannel10\$ = no ++ server schannel require seal:schannel11\$ = no ++ server schannel require seal:torturetest\$ = no + + # needed for 'samba.tests.auth_log' tests + server require schannel:LOCALDC\$ = no ++ server schannel require seal:LOCALDC\$ = no + "; + push (@{$extra_provision_options}, "--use-ntvfs"); + my $ret = $self->provision($prefix, +@@ -2049,6 +2063,19 @@ sub provision_ad_dc($$$$$$$) + server require schannel:schannel10\$ = no + server require schannel:schannel11\$ = no + server require schannel:torturetest\$ = no ++ server schannel require seal:schannel0\$ = no ++ server schannel require seal:schannel1\$ = no ++ server schannel require seal:schannel2\$ = no ++ server schannel require seal:schannel3\$ = no ++ server schannel require seal:schannel4\$ = no ++ server schannel require seal:schannel5\$ = no ++ server schannel require seal:schannel6\$ = no ++ server schannel require seal:schannel7\$ = no ++ server schannel require seal:schannel8\$ = no ++ server schannel require seal:schannel9\$ = no ++ server schannel require seal:schannel10\$ = no ++ server schannel require seal:schannel11\$ = no ++ server schannel require seal:torturetest\$ = no + + auth event notification = true + dsdb event notification = true +@@ -2742,6 +2769,7 @@ sub setup_ad_dc_smb1 + + # needed for 'samba.tests.auth_log' tests + server require schannel:ADDCSMB1\$ = no ++ server schannel require seal:ADDCSMB1\$ = no + "; + return _setup_ad_dc($self, $path, $conf_opts, "addcsmb1", "addom2.samba.example.com"); + } +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 624c8d407242..ddcb8487a56d 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -68,9 +68,11 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context + bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); ++ bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); + static bool warned_global_nt4_once = false; + static bool warned_global_md5_once = false; + static bool warned_global_schannel_once = false; ++ static bool warned_global_seal_once = false; + + if (global_allow_nt4_crypto && !warned_global_nt4_once) { + /* +@@ -102,6 +104,16 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context + warned_global_schannel_once = true; + } + ++ if (!global_require_seal && !warned_global_seal_once) { ++ /* ++ * We want admins to notice their misconfiguration! ++ */ ++ D_ERR("CVE-2022-38023 (and others): " ++ "Please configure 'server schannel require seal = yes' (the default), " ++ "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); ++ warned_global_seal_once = true; ++ } ++ + return dcesrv_interface_bind_reject_connect(context, iface); + } + +@@ -886,6 +898,10 @@ struct dcesrv_netr_check_schannel_state { + bool schannel_required; + bool schannel_explicitly_set; + ++ bool seal_global_required; ++ bool seal_required; ++ bool seal_explicitly_set; ++ + NTSTATUS result; + }; + +@@ -900,6 +916,9 @@ static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *d + bool schannel_global_required = (schannel == true); + bool schannel_required = schannel_global_required; + const char *explicit_opt = NULL; ++ bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); ++ bool require_seal = global_require_seal; ++ const char *explicit_seal_opt = NULL; + #define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) + struct dcesrv_netr_check_schannel_state *s = NULL; + NTSTATUS status; +@@ -937,6 +956,19 @@ new_state: + s->auth_level = auth_level; + s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; + ++ /* ++ * We don't use lpcfg_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ explicit_seal_opt = lpcfg_get_parametric(lp_ctx, ++ NULL, ++ "server schannel require seal", ++ creds->account_name); ++ if (explicit_seal_opt != NULL) { ++ require_seal = lp_bool(explicit_seal_opt); ++ } ++ + /* + * We don't use lpcfg_parm_bool(), as we + * need the explicit_opt pointer in order to +@@ -954,6 +986,10 @@ new_state: + s->schannel_required = schannel_required; + s->schannel_explicitly_set = explicit_opt != NULL; + ++ s->seal_global_required = global_require_seal; ++ s->seal_required = require_seal; ++ s->seal_explicitly_set = explicit_seal_opt != NULL; ++ + status = dcesrv_iface_state_store_conn(dce_call, + DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, + s); +@@ -975,6 +1011,10 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); ++ int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); ++ int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, ++ "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); + TALLOC_CTX *frame = talloc_stackframe(); + unsigned int dbg_lvl = DBGLVL_DEBUG; + const char *opname = ""; +@@ -1004,18 +1044,107 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + } + + DEBUG(dbg_lvl, ( +- "CVE-2020-1472(ZeroLogon): " ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && ++ s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) ++ { ++ s->result = NT_STATUS_OK; ++ ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); ++ } else if (!s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); ++ } else if (!s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); ++ ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): " ++ "Option 'server require schannel:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ if (s->seal_explicitly_set && !s->seal_required) { ++ DEBUG(CVE_2022_38023_warn_level, ( ++ "CVE-2022-38023: " ++ "Option 'server schannel require seal:%s = no' not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ + TALLOC_FREE(frame); + return s->result; + } + + if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ if (s->seal_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; ++ ++ if (s->seal_explicitly_set) { ++ dbg_lvl = DBGLVL_NOTICE; ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); ++ } ++ ++ DEBUG(dbg_lvl, ( ++ "CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "from client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->seal_explicitly_set) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ if (s->schannel_explicitly_set && !s->schannel_required) { ++ DEBUG(CVE_2020_1472_warn_level, ( ++ "CVE-2020-1472(ZeroLogon): Option " ++ "'server require schannel:%s = no' " ++ "not needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ + s->result = NT_STATUS_OK; + + if (s->schannel_explicitly_set && !s->schannel_required) { +@@ -1023,6 +1152,11 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + } else if (!s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } else if (!s->seal_required) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon): " +@@ -1039,7 +1173,77 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } ++ if (s->seal_explicitly_set && !s->seal_required) { ++ D_INFO("CVE-2022-38023: " ++ "Option 'server schannel require seal:%s = no' still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else if (!s->seal_required) { ++ /* ++ * admins should set ++ * server schannel require seal:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: " ++ "Please use 'server schannel require seal:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ ++ TALLOC_FREE(frame); ++ return s->result; ++ } ++ ++ if (s->seal_required) { ++ s->result = NT_STATUS_ACCESS_DENIED; ++ ++ if (s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ if (!s->schannel_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); ++ } else if (s->schannel_required) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); ++ } + ++ DEBUG(dbg_lvl, ( ++ "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " ++ "%s request (opnum[%u]) %s schannel from " ++ "from client_account[%s] client_computer_name[%s] %s\n", ++ opname, opnum, reason, ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name), ++ nt_errstr(s->result))); ++ if (s->seal_explicitly_set) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = yes' " ++ "rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } else { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } ++ if (!s->schannel_explicitly_set) { ++ DEBUG(CVE_2020_1472_error_level, ( ++ "CVE-2020-1472(ZeroLogon): Check if option " ++ "'server require schannel:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } else if (s->schannel_required) { ++ D_NOTICE("CVE-2022-38023: Option " ++ "'server require schannel:%s = yes' " ++ "also rejects access for client.\n", ++ log_escape(frame, creds->account_name)); ++ } + TALLOC_FREE(frame); + return s->result; + } +@@ -1052,6 +1256,9 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); + } ++ if (!s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " +@@ -1073,12 +1280,25 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } ++ if (!s->seal_explicitly_set) { ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Check if option " ++ "'server schannel require seal:%s = no' " ++ "might be needed for a legacy client.\n", ++ log_escape(frame, creds->account_name))); ++ } + TALLOC_FREE(frame); + return s->result; + } + + s->result = NT_STATUS_OK; + ++ if (s->seal_explicitly_set) { ++ dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); ++ } else { ++ dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); ++ } ++ + if (s->schannel_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } else { +@@ -1094,6 +1314,28 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); + ++ if (s->seal_explicitly_set) { ++ D_INFO("CVE-2022-38023: Option " ++ "'server schannel require seal:%s = no' " ++ "still needed for '%s'!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name)); ++ } else { ++ /* ++ * admins should set ++ * server schannel require seal:COMPUTER$ = no ++ * in order to avoid the level 0 messages. ++ * Over time they can switch the global value ++ * to be strict. ++ */ ++ DEBUG(CVE_2022_38023_error_level, ( ++ "CVE-2022-38023: Please use " ++ "'server schannel require seal:%s = no' " ++ "for '%s' to avoid this warning!\n", ++ log_escape(frame, creds->account_name), ++ log_escape(frame, creds->computer_name))); ++ } ++ + if (s->schannel_explicitly_set) { + D_INFO("CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = no' " +-- +2.34.1 + + +From 8a9aed5d0dab28a20004ed6cc73f2472b11fbd41 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 30 Nov 2022 15:13:47 +0100 +Subject: [PATCH 29/30] CVE-2022-38023 testparm: warn about server/client + schannel != yes + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit f964c0c357214637f80d0089723b9b11d1b38f7e) +--- + source3/utils/testparm.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c +index 27a8bc1fb8e8..b3ddd48b3f1d 100644 +--- a/source3/utils/testparm.c ++++ b/source3/utils/testparm.c +@@ -598,11 +598,25 @@ static int do_global_checks(void) + ret = 1; + } + +- if (!lp_server_schannel()) { ++ if (lp_server_schannel() != true) { /* can be 'auto' */ + fprintf(stderr, +- "WARNING: You have configured 'server schannel = no'. " ++ "WARNING: You have not configured " ++ "'server schannel = yes' (the default). " + "Your server is vulernable to \"ZeroLogon\" " +- "(CVE-2020-1472)\n\n"); ++ "(CVE-2020-1472)\n" ++ "If required use individual " ++ "'server require schannel:COMPUTERACCOUNT$ = no' " ++ "options\n\n"); ++ } ++ if (lp_client_schannel() != true) { /* can be 'auto' */ ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'client schannel = yes' (the default). " ++ "Your server is vulernable to \"ZeroLogon\" " ++ "(CVE-2020-1472)\n" ++ "If required use individual " ++ "'client schannel:NETBIOSDOMAIN = no' " ++ "options\n\n"); + } + + return ret; +-- +2.34.1 + + +From a3e10bf4b8fc328167e7219337742bf12eb41111 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 6 Dec 2022 13:36:17 +0100 +Subject: [PATCH 30/30] CVE-2022-38023 testparm: warn about unsecure schannel + related options + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +Reviewed-by: Ralph Boehme +(cherry picked from commit 4d540473c3d43d048a30dd63efaeae9ff87b2aeb) +--- + source3/utils/testparm.c | 61 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c +index b3ddd48b3f1d..02ef3de83ae5 100644 +--- a/source3/utils/testparm.c ++++ b/source3/utils/testparm.c +@@ -608,6 +608,37 @@ static int do_global_checks(void) + "'server require schannel:COMPUTERACCOUNT$ = no' " + "options\n\n"); + } ++ if (lp_allow_nt4_crypto()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'allow nt4 crypto = no' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023 and others!\n" ++ "If required use individual " ++ "'allow nt4 crypto:COMPUTERACCOUNT$ = yes' " ++ "options\n\n"); ++ } ++ if (!lp_reject_md5_clients()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'reject md5 clients = yes' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023!\n" ++ "If required use individual " ++ "'server reject md5 schannel:COMPUTERACCOUNT$ = yes' " ++ "options\n\n"); ++ } ++ if (!lp_server_schannel_require_seal()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'server schannel require seal = yes' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023!\n" ++ "If required use individual " ++ "'server schannel require seal:COMPUTERACCOUNT$ = no' " ++ "options\n\n"); ++ } ++ + if (lp_client_schannel() != true) { /* can be 'auto' */ + fprintf(stderr, + "WARNING: You have not configured " +@@ -618,6 +649,36 @@ static int do_global_checks(void) + "'client schannel:NETBIOSDOMAIN = no' " + "options\n\n"); + } ++ if (!lp_reject_md5_servers()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'reject md5 servers = yes' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023\n" ++ "If required use individual " ++ "'reject md5 servers:NETBIOSDOMAIN = no' " ++ "options\n\n"); ++ } ++ if (!lp_require_strong_key()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'require strong key = yes' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023\n" ++ "If required use individual " ++ "'require strong key:NETBIOSDOMAIN = no' " ++ "options\n\n"); ++ } ++ if (!lp_winbind_sealed_pipes()) { ++ fprintf(stderr, ++ "WARNING: You have not configured " ++ "'winbind sealed pipes = yes' (the default). " ++ "Your server is vulernable to " ++ "CVE-2022-38023\n" ++ "If required use individual " ++ "'winbind sealed pipes:NETBIOSDOMAIN = no' " ++ "options\n\n"); ++ } + + return ret; + } +-- +2.34.1 + diff --git a/SPECS/samba.spec b/SPECS/samba.spec index 2f24fb4..cbba1ca 100644 --- a/SPECS/samba.spec +++ b/SPECS/samba.spec @@ -134,7 +134,7 @@ %define samba_requires_eq() %(LC_ALL="C" echo '%*' | xargs -r rpm -q --qf 'Requires: %%{name} = %%{epoch}:%%{version}\\n' | sed -e 's/ (none):/ /' -e 's/ 0:/ /' | grep -v "is not") -%global baserelease 101 +%global baserelease 103 %global samba_version 4.16.4 %global talloc_version 2.3.3 @@ -207,6 +207,8 @@ Source201: README.downgrade Patch0: samba-s4u.patch # https://gitlab.com/samba-team/samba/-/merge_requests/2477 Patch1: samba-4.16-waf-crypto.patch +Patch2: CVE-2022-38023-v4-16.patch +Patch3: CVE-2022-38023-for-s3-v4-16.patch Requires(pre): /usr/sbin/groupadd Requires(post): systemd @@ -4166,6 +4168,13 @@ fi * Wed Mar 15 2023 MSVSphere Packaging Team - 4.16.4-101 - Rebuilt for MSVSphere 9.1. +* Mon Jan 16 2023 Andreas Schneider - 4.16.4-103 +- related: rhbz#2154372 - Add additional patches for CVE-2022-38023 + +* Tue Dec 20 2022 Andreas Schneider - 4.16.4-102 +- Fix CVE-2022-38023 +- resolves: rhbz#2154372 + * Thu Aug 25 2022 Andreas Schneider - 4.16.4-101 - resolves: rhbz#2121317 - Do not require samba package in python3-samba