2414 lines
81 KiB
Diff
2414 lines
81 KiB
Diff
From f7c26ead133ab9b67c6802a2303a22fd98e3c41a Mon Sep 17 00:00:00 2001
|
|
From: Samuel Cabrero <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 = "<unknown>";
|
|
- 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 <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 <scabrero@samba.org>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 <abartlet@samba.org> 2004-2008
|
|
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 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 <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+#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 = "<unknown>";
|
|
+ const char *reason = "<unknown>";
|
|
+
|
|
+ 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 <abartlet@samba.org> 2004-2008
|
|
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 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 <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+#ifndef __LIBRPC_RPC_SERVER_NETLOGON_SCHANNEL_UTIL_H__
|
|
+#define __LIBRPC_RPC_SERVER_NETLOGON_SCHANNEL_UTIL_H__
|
|
+
|
|
+#include "replace.h"
|
|
+#include <talloc.h>
|
|
+#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 = "<unknown>";
|
|
- const char *reason = "<unknown>";
|
|
-
|
|
- 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 <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 = "<unknown>";
|
|
-
|
|
- 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 <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 <scabrero@samba.org>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
(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 @@
|
|
</para>
|
|
|
|
<para>
|
|
- 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.
|
|
</para>
|
|
|
|
<para>
|
|
--
|
|
2.39.0
|
|
|
|
|
|
From 2cb3ecb5c258fd23ca2f1fd2635be90336a0d7e0 Mon Sep 17 00:00:00 2001
|
|
From: Samuel Cabrero <scabrero@suse.de>
|
|
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 <scabrero@samba.org>
|
|
Reviewed-by: Andreas Schneider <asn@samba.org>
|
|
|
|
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
|
|
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
|
|
|