Blob Blame History Raw
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