Blob Blame History Raw
From 9aa816f5017bd38cbb9af2af5a7c385647e4f76d Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab@samba.org>
Date: Tue, 7 Jan 2020 19:25:53 +0200
Subject: [PATCH 001/146] s3-rpcserver: fix security level check for
 DsRGetForestTrustInformation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Harmonize _netr_DsRGetForestTrustInformation with source4/ logic which
didn't change since DCE RPC channel refactoring.

With the current code we return RPC faul as can be seen in the logs:

2019/12/11 17:12:55.463081,  1, pid=20939, effective(1284200000, 1284200000), real(1284200000, 0), class=rpc_parse] ../librpc/ndr/ndr.c:471(ndr_print_function_debug)
       netr_DsRGetForestTrustInformation: struct netr_DsRGetForestTrustInformation
          in: struct netr_DsRGetForestTrustInformation
              server_name              : *
                  server_name              : '\\some-dc.example.com'
              trusted_domain_name      : NULL
              flags                    : 0x00000000 (0)
[2019/12/11 17:12:55.463122,  4, pid=20939, effective(1284200000, 1284200000), real(1284200000, 0), class=rpc_srv] ../source3/rpc_server/srv_pipe.c:1561(api_rpcTNP)
  api_rpcTNP: fault(5) return.

This is due to this check in processing a request:
        if (!(p->pipe_bound && (p->auth.auth_type != DCERPC_AUTH_TYPE_NONE)
                       && (p->auth.auth_level != DCERPC_AUTH_LEVEL_NONE))) {
                p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
                return WERR_ACCESS_DENIED;
        }

and since we get AuthZ response,

  Successful AuthZ: [netlogon,ncacn_np] user [EXAMPLE]\[admin] [S-1-5-21-1234567-890123456-500] at [Wed, 11 Dec 2019 17:12:55.461164 UTC]
  Remote host [ipv4:Y.Y.Y.Y:59017] local host [ipv4:X.X.X.X:445]
[2019/12/11 17:12:55.461584,  4, pid=20939, effective(0, 0), real(0, 0)] ../lib/audit_logging/audit_logging.c:141(audit_log_json)
  JSON Authorization: {"timestamp": "2019-12-11T17:12:55.461491+0000",
   "type": "Authorization", "Authorization": {"version": {"major": 1, "minor": 1},
   "localAddress": "ipv4:X.X.X.X:445", "remoteAddress": "ipv4:Y.Y.Y.Y:59017",
   "serviceDescription": "netlogon", "authType": "ncacn_np",
   "domain": "EXAMPLE", "account": "admin", "sid": "S-1-5-21-1234567-890123456-500",
   "sessionId": "c5a2386f-f2cc-4241-9a9e-d104cf5859d5", "logonServer": "SOME-DC",
   "transportProtection": "SMB", "accountFlags": "0x00000010"}}

this means we are actually getting anonymous DCE/RPC access to netlogon
on top of authenticated SMB connection. In such case we have exactly
auth_type set to DCERPC_AUTH_TYPE_NONE and auth_level set to
DCERPC_AUTH_LEVEL_NONE in the pipe->auth. Thus, returning an error.

Update the code to follow the same security level check as in s4 variant
of the call.

Signed-off-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>

Autobuild-User(master): Günther Deschner <gd@samba.org>
Autobuild-Date(master): Mon Jan 13 15:05:28 UTC 2020 on sn-devel-184

(cherry picked from commit c6d880a115095c336b8b74f45854a99abb1bbb87)
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index d799ba4feef..87613b99fde 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -2425,10 +2425,10 @@ WERROR _netr_DsRGetForestTrustInformation(struct pipes_struct *p,
 {
 	NTSTATUS status;
 	struct lsa_ForestTrustInformation *info, **info_ptr;
+	enum security_user_level security_level;
 
-	if (!(p->pipe_bound && (p->auth.auth_type != DCERPC_AUTH_TYPE_NONE)
-		       && (p->auth.auth_level != DCERPC_AUTH_LEVEL_NONE))) {
-		p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
+	security_level = security_session_user_level(p->session_info, NULL);
+	if (security_level < SECURITY_USER) {
 		return WERR_ACCESS_DENIED;
 	}
 
-- 
2.41.0


From e71fddb9ad5275a222d96bdcee06571a9a8c73c8 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 16:50:45 +0200
Subject: [PATCH 002/146] Add a test to check dNSHostName with netbios aliases

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/nb_alias_dnshostname |  2 ++
 testprogs/blackbox/test_net_ads.sh        | 14 ++++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 selftest/knownfail.d/nb_alias_dnshostname

diff --git a/selftest/knownfail.d/nb_alias_dnshostname b/selftest/knownfail.d/nb_alias_dnshostname
new file mode 100644
index 00000000000..3c14e9931b9
--- /dev/null
+++ b/selftest/knownfail.d/nb_alias_dnshostname
@@ -0,0 +1,2 @@
+^samba4.blackbox.net_ads.nb_alias check dNSHostName
+^samba4.blackbox.net_ads.nb_alias check main SPN
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 95c0cf76f90..6073ea972f9 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -220,6 +220,20 @@ testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samac
 ##Goodbye...
 testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
+# netbios aliases tests
+testit "join nb_alias" $VALGRIND $net_tool --option=netbiosaliases=nb_alias1,nb_alias2 ads join -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
+testit "testjoin nb_alias" $VALGRIND $net_tool ads testjoin || failed=`expr $failed + 1`
+
+testit_grep "nb_alias check dNSHostName" $fqdn $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ dNSHostName || failed=`expr $failed + 1`
+testit_grep "nb_alias check main SPN" ${uc_netbios}.${lc_realm} $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+
+testit_grep "nb_alias1 SPN" nb_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+testit_grep "nb_alias2 SPN" nb_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+
+##Goodbye...
+testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
 #
 # Test createcomputer option of 'net ads join'
 #
-- 
2.41.0


From e80e373485818eb7faebf5c9aae10d82fbc4e2e2 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:52:46 +0200
Subject: [PATCH 003/146] Fix accidental overwrite of dnsHostName by the last
 netbios alias

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/nb_alias_dnshostname | 2 --
 source3/libnet/libnet_join.c              | 5 +++--
 2 files changed, 3 insertions(+), 4 deletions(-)
 delete mode 100644 selftest/knownfail.d/nb_alias_dnshostname

diff --git a/selftest/knownfail.d/nb_alias_dnshostname b/selftest/knownfail.d/nb_alias_dnshostname
deleted file mode 100644
index 3c14e9931b9..00000000000
--- a/selftest/knownfail.d/nb_alias_dnshostname
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba4.blackbox.net_ads.nb_alias check dNSHostName
-^samba4.blackbox.net_ads.nb_alias check main SPN
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 9d4f656ffec..a31011b0ff8 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -507,6 +507,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 	ADS_STATUS status;
 	ADS_MODLIST mods;
 	fstring my_fqdn;
+	fstring my_alias;
 	const char **spn_array = NULL;
 	size_t num_spns = 0;
 	char *spn = NULL;
@@ -587,11 +588,11 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		/*
 		 * Add HOST/netbiosname.domainname
 		 */
-		fstr_sprintf(my_fqdn, "%s.%s",
+		fstr_sprintf(my_alias, "%s.%s",
 			     *netbios_aliases,
 			     lp_dnsdomain());
 
-		spn = talloc_asprintf(frame, "HOST/%s", my_fqdn);
+		spn = talloc_asprintf(frame, "HOST/%s", my_alias);
 		if (spn == NULL) {
 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
 			goto done;
-- 
2.41.0


From 7ca5f9b2956ec41777837a7e14800a4345505ed6 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Thu, 24 Oct 2019 19:04:51 +0300
Subject: [PATCH 004/146] Refactor ads_keytab_add_entry() to make it iterable

so we can more easily add msDS-AdditionalDnsHostName entries.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 source3/libads/kerberos_keytab.c | 197 +++++++++++++++++--------------
 1 file changed, 107 insertions(+), 90 deletions(-)

diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 97d5535041c..0f450a09df5 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -228,18 +228,16 @@ out:
 	return ok;
 }
 
-/**********************************************************************
- Adds a single service principal, i.e. 'host' to the system keytab
-***********************************************************************/
-
-int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
+static int add_kt_entry_etypes(krb5_context context, TALLOC_CTX *tmpctx,
+			       ADS_STRUCT *ads, const char *salt_princ_s,
+			       krb5_keytab keytab, krb5_kvno kvno,
+			       const char *srvPrinc, const char *my_fqdn,
+			       krb5_data *password, bool update_ads)
 {
 	krb5_error_code ret = 0;
-	krb5_context context = NULL;
-	krb5_keytab keytab = NULL;
-	krb5_data password;
-	krb5_kvno kvno;
-        krb5_enctype enctypes[6] = {
+	char *princ_s = NULL;
+	char *short_princ_s = NULL;
+	krb5_enctype enctypes[6] = {
 		ENCTYPE_DES_CBC_CRC,
 		ENCTYPE_DES_CBC_MD5,
 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
@@ -251,65 +249,7 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		ENCTYPE_ARCFOUR_HMAC,
 		0
 	};
-	char *princ_s = NULL;
-	char *short_princ_s = NULL;
-	char *salt_princ_s = NULL;
-	char *password_s = NULL;
-	char *my_fqdn;
-	TALLOC_CTX *tmpctx = NULL;
-	int i;
-
-	ret = smb_krb5_init_context_common(&context);
-	if (ret) {
-		DBG_ERR("kerberos init context failed (%s)\n",
-			error_message(ret));
-		return -1;
-	}
-
-	ret = ads_keytab_open(context, &keytab);
-	if (ret != 0) {
-		goto out;
-	}
-
-	/* retrieve the password */
-	if (!secrets_init()) {
-		DEBUG(1, (__location__ ": secrets_init failed\n"));
-		ret = -1;
-		goto out;
-	}
-	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-	if (!password_s) {
-		DEBUG(1, (__location__ ": failed to fetch machine password\n"));
-		ret = -1;
-		goto out;
-	}
-	ZERO_STRUCT(password);
-	password.data = password_s;
-	password.length = strlen(password_s);
-
-	/* we need the dNSHostName value here */
-	tmpctx = talloc_init(__location__);
-	if (!tmpctx) {
-		DEBUG(0, (__location__ ": talloc_init() failed!\n"));
-		ret = -1;
-		goto out;
-	}
-
-	my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name());
-	if (!my_fqdn) {
-		DEBUG(0, (__location__ ": unable to determine machine "
-			  "account's dns name in AD!\n"));
-		ret = -1;
-		goto out;
-	}
-
-	/* make sure we have a single instance of a the computer account */
-	if (!ads_has_samaccountname(ads, tmpctx, lp_netbios_name())) {
-		DEBUG(0, (__location__ ": unable to determine machine "
-			  "account's short name in AD!\n"));
-		ret = -1;
-		goto out;
-	}
+	size_t i;
 
 	/* Construct our principal */
 	if (strchr_m(srvPrinc, '@')) {
@@ -358,22 +298,6 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		}
 	}
 
-	kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
-	if (kvno == -1) {
-		/* -1 indicates failure, everything else is OK */
-		DEBUG(1, (__location__ ": ads_get_machine_kvno failed to "
-			 "determine the system's kvno.\n"));
-		ret = -1;
-		goto out;
-	}
-
-	salt_princ_s = kerberos_secrets_fetch_salt_princ();
-	if (salt_princ_s == NULL) {
-		DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n");
-		ret = -1;
-		goto out;
-	}
-
 	for (i = 0; enctypes[i]; i++) {
 
 		/* add the fqdn principal to the keytab */
@@ -383,11 +307,11 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 					    princ_s,
 					    salt_princ_s,
 					    enctypes[i],
-					    &password,
+					    password,
 					    false,
 					    false);
 		if (ret) {
-			DEBUG(1, (__location__ ": Failed to add entry to keytab\n"));
+			DBG_WARNING("Failed to add entry to keytab\n");
 			goto out;
 		}
 
@@ -399,16 +323,109 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 						    short_princ_s,
 						    salt_princ_s,
 						    enctypes[i],
-						    &password,
+						    password,
 						    false,
 						    false);
 			if (ret) {
-				DEBUG(1, (__location__
-					  ": Failed to add short entry to keytab\n"));
+				DBG_WARNING("Failed to add short entry to keytab\n");
 				goto out;
 			}
 		}
 	}
+out:
+	return ret;
+}
+
+/**********************************************************************
+ Adds a single service principal, i.e. 'host' to the system keytab
+***********************************************************************/
+
+int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
+{
+	krb5_error_code ret = 0;
+	krb5_context context = NULL;
+	krb5_keytab keytab = NULL;
+	krb5_data password;
+	krb5_kvno kvno;
+	char *salt_princ_s = NULL;
+	char *password_s = NULL;
+	char *my_fqdn;
+	TALLOC_CTX *tmpctx = NULL;
+
+	ret = smb_krb5_init_context_common(&context);
+	if (ret) {
+		DBG_ERR("kerberos init context failed (%s)\n",
+			error_message(ret));
+		return -1;
+	}
+
+	ret = ads_keytab_open(context, &keytab);
+	if (ret != 0) {
+		goto out;
+	}
+
+	/* retrieve the password */
+	if (!secrets_init()) {
+		DBG_WARNING("secrets_init failed\n");
+		ret = -1;
+		goto out;
+	}
+	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+	if (!password_s) {
+		DBG_WARNING("failed to fetch machine password\n");
+		ret = -1;
+		goto out;
+	}
+	ZERO_STRUCT(password);
+	password.data = password_s;
+	password.length = strlen(password_s);
+
+	/* we need the dNSHostName value here */
+	tmpctx = talloc_init(__location__);
+	if (!tmpctx) {
+		DBG_ERR("talloc_init() failed!\n");
+		ret = -1;
+		goto out;
+	}
+
+	my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name());
+	if (!my_fqdn) {
+		DBG_ERR("unable to determine machine account's dns name in "
+			"AD!\n");
+		ret = -1;
+		goto out;
+	}
+
+	/* make sure we have a single instance of a the computer account */
+	if (!ads_has_samaccountname(ads, tmpctx, lp_netbios_name())) {
+		DBG_ERR("unable to determine machine account's short name in "
+			"AD!\n");
+		ret = -1;
+		goto out;
+	}
+
+	kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
+	if (kvno == -1) {
+		/* -1 indicates failure, everything else is OK */
+		DBG_WARNING("ads_get_machine_kvno failed to determine the "
+			    "system's kvno.\n");
+		ret = -1;
+		goto out;
+	}
+
+	salt_princ_s = kerberos_secrets_fetch_salt_princ();
+	if (salt_princ_s == NULL) {
+		DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n");
+		ret = -1;
+		goto out;
+	}
+
+	ret = add_kt_entry_etypes(context, tmpctx, ads, salt_princ_s, keytab,
+				  kvno, srvPrinc, my_fqdn, &password,
+				  update_ads);
+	if (ret != 0) {
+		goto out;
+	}
 
 out:
 	SAFE_FREE(salt_princ_s);
-- 
2.41.0


From 087d6dd4c4f25860643ab5920a1b2c0c70e5551b Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 17:55:12 +0200
Subject: [PATCH 005/146] Add a test for msDS-AdditionalDnsHostName entries in
 keytab

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/dns_alias_keytab | 2 ++
 testprogs/blackbox/test_net_ads.sh    | 9 +++++++++
 2 files changed, 11 insertions(+)
 create mode 100644 selftest/knownfail.d/dns_alias_keytab

diff --git a/selftest/knownfail.d/dns_alias_keytab b/selftest/knownfail.d/dns_alias_keytab
new file mode 100644
index 00000000000..216592e1210
--- /dev/null
+++ b/selftest/knownfail.d/dns_alias_keytab
@@ -0,0 +1,2 @@
+^samba4.blackbox.net_ads.dns alias1 check keytab
+^samba4.blackbox.net_ads.dns alias2 check keytab
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 6073ea972f9..a40b477a173 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -217,6 +217,15 @@ testit_grep "dns alias SPN" $dns_alias2 $VALGRIND $net_tool ads search -P samacc
 testit_grep "dns alias addl" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 
+dedicated_keytab_file="$PREFIX_ABS/test_dns_aliases_dedicated_krb5.keytab"
+
+testit "dns alias create_keytab" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+testit_grep "dns alias1 check keytab" "host/${dns_alias1}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+testit_grep "dns alias2 check keytab" "host/${dns_alias2}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+rm -f $dedicated_keytab_file
+
 ##Goodbye...
 testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
-- 
2.41.0


From 1ae32dddad89cdb75ae2c8fb3e7378ce6f5ad6af Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:36:28 +0200
Subject: [PATCH 006/146] Add msDS-AdditionalDnsHostName entries to the keytab

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/dns_alias_keytab |  2 --
 source3/libads/ads_proto.h            |  5 +++
 source3/libads/kerberos_keytab.c      | 21 +++++++++++++
 source3/libads/ldap.c                 | 45 +++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 2 deletions(-)
 delete mode 100644 selftest/knownfail.d/dns_alias_keytab

diff --git a/selftest/knownfail.d/dns_alias_keytab b/selftest/knownfail.d/dns_alias_keytab
deleted file mode 100644
index 216592e1210..00000000000
--- a/selftest/knownfail.d/dns_alias_keytab
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba4.blackbox.net_ads.dns alias1 check keytab
-^samba4.blackbox.net_ads.dns alias2 check keytab
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 495ef5d3325..cd9c1082681 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -137,6 +137,11 @@ ADS_STATUS ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
 					enum ads_extended_dn_flags flags,
 					struct dom_sid *sid);
 char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
+ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
+                                            ADS_STRUCT *ads,
+                                            const char *machine_name,
+                                            char ***hostnames_array,
+                                            size_t *num_hostnames);
 char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
 bool ads_has_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
 ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 0f450a09df5..818ec884a03 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -351,6 +351,8 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 	char *password_s = NULL;
 	char *my_fqdn;
 	TALLOC_CTX *tmpctx = NULL;
+	char **hostnames_array = NULL;
+	size_t num_hostnames = 0;
 
 	ret = smb_krb5_init_context_common(&context);
 	if (ret) {
@@ -427,6 +429,25 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		goto out;
 	}
 
+	if (ADS_ERR_OK(ads_get_additional_dns_hostnames(tmpctx, ads,
+							lp_netbios_name(),
+							&hostnames_array,
+							&num_hostnames))) {
+		size_t i;
+
+		for (i = 0; i < num_hostnames; i++) {
+
+			ret = add_kt_entry_etypes(context, tmpctx, ads,
+						  salt_princ_s, keytab,
+						  kvno, srvPrinc,
+						  hostnames_array[i],
+						  &password, update_ads);
+			if (ret != 0) {
+				goto out;
+			}
+		}
+	}
+
 out:
 	SAFE_FREE(salt_princ_s);
 	TALLOC_FREE(tmpctx);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index db2b72ab1b5..02a628ee0e6 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1377,6 +1377,7 @@ char *ads_parent_dn(const char *dn)
 		"unicodePwd",
 
 		/* Additional attributes Samba checks */
+		"msDS-AdditionalDnsHostName",
 		"msDS-SupportedEncryptionTypes",
 		"nTSecurityDescriptor",
 
@@ -3663,6 +3664,50 @@ out:
 /********************************************************************
 ********************************************************************/
 
+ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
+					    ADS_STRUCT *ads,
+					    const char *machine_name,
+					    char ***hostnames_array,
+					    size_t *num_hostnames)
+{
+	ADS_STATUS status;
+	LDAPMessage *res = NULL;
+	int count;
+
+	status = ads_find_machine_acct(ads,
+				       &res,
+				       machine_name);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("Host Account for %s not found... skipping operation.\n",
+			 machine_name));
+		return status;
+	}
+
+	count = ads_count_replies(ads, res);
+	if (count != 1) {
+		status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+		goto done;
+	}
+
+	*hostnames_array = ads_pull_strings(ads, mem_ctx, res,
+					    "msDS-AdditionalDnsHostName",
+					    num_hostnames);
+	if (*hostnames_array == NULL) {
+		DEBUG(1, ("Host account for %s does not have msDS-AdditionalDnsHostName.\n",
+			  machine_name));
+		status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+		goto done;
+	}
+
+done:
+	ads_msgfree(ads, res);
+
+	return status;
+}
+
+/********************************************************************
+********************************************************************/
+
 char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name )
 {
 	LDAPMessage *res = NULL;
-- 
2.41.0


From 939b9265a533393189ef3c513e77b2cb009a51d5 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:54:12 +0200
Subject: [PATCH 007/146] Add net-ads-join dnshostname=fqdn option

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Fri May 29 13:33:28 UTC 2020 on sn-devel-184
---
 docs-xml/manpages/net.8.xml        |  7 ++++++-
 source3/libnet/libnet_join.c       |  7 ++++++-
 source3/librpc/idl/libnet_join.idl |  1 +
 source3/utils/net_ads.c            |  9 ++++++++-
 testprogs/blackbox/test_net_ads.sh | 15 +++++++++++++++
 5 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 37dfa2af694..69e18df8b6c 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -454,7 +454,7 @@ The remote server must be specified with the -S option.
 
 <refsect2>
 <title>[RPC|ADS] JOIN [TYPE] [--no-dns-updates] [-U username[%password]]
-[createupn=UPN] [createcomputer=OU] [machinepass=PASS]
+[dnshostname=FQDN] [createupn=UPN] [createcomputer=OU] [machinepass=PASS]
 [osName=string osVer=string] [options]</title>
 
 <para>
@@ -469,6 +469,11 @@ be created.</para>
 joining the domain.
 </para>
 
+<para>
+[FQDN] (ADS only) set the dnsHosName attribute during the join.
+The default format is netbiosname.dnsdomain.
+</para>
+
 <para>
 [UPN] (ADS only) set the principalname attribute during the join.  The default
 format is host/netbiosname@REALM.
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index a31011b0ff8..de558be4f91 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -546,7 +546,12 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-	fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, lp_dnsdomain());
+	if (r->in.dnshostname != NULL) {
+		fstr_sprintf(my_fqdn, "%s", r->in.dnshostname);
+	} else {
+		fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name,
+			     lp_dnsdomain());
+	}
 
 	if (!strlower_m(my_fqdn)) {
 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl
index e45034d40da..03d919863b5 100644
--- a/source3/librpc/idl/libnet_join.idl
+++ b/source3/librpc/idl/libnet_join.idl
@@ -37,6 +37,7 @@ interface libnetjoin
 		[in] string os_servicepack,
 		[in] boolean8 create_upn,
 		[in] string upn,
+		[in] string dnshostname,
 		[in] boolean8 modify_config,
 		[in,unique] ads_struct *ads,
 		[in] boolean8 debug,
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 07a22098fb1..3cf8fbbf7c8 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1710,6 +1710,8 @@ static int net_ads_join_usage(struct net_context *c, int argc, const char **argv
 {
 	d_printf(_("net ads join [--no-dns-updates] [options]\n"
 	           "Valid options:\n"));
+	d_printf(_("   dnshostname=FQDN      Set the dnsHostName attribute during the join.\n"
+		   "                         The default is in the form netbiosname.dnsdomain\n"));
 	d_printf(_("   createupn[=UPN]       Set the userPrincipalName attribute during the join.\n"
 		   "                         The default UPN is in the form host/netbiosname@REALM.\n"));
 	d_printf(_("   createcomputer=OU     Precreate the computer account in a specific OU.\n"
@@ -1830,6 +1832,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	const char *domain = lp_realm();
 	WERROR werr = WERR_NERR_SETUPNOTJOINED;
 	bool createupn = false;
+	const char *dnshostname = NULL;
 	const char *machineupn = NULL;
 	const char *machine_password = NULL;
 	const char *create_in_ou = NULL;
@@ -1870,7 +1873,10 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	/* process additional command line args */
 
 	for ( i=0; i<argc; i++ ) {
-		if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
+		if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
+			dnshostname = get_string_param(argv[i]);
+		}
+		else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
 			createupn = true;
 			machineupn = get_string_param(argv[i]);
 		}
@@ -1938,6 +1944,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	r->in.domain_name_type	= domain_name_type;
 	r->in.create_upn	= createupn;
 	r->in.upn		= machineupn;
+	r->in.dnshostname	= dnshostname;
 	r->in.account_ou	= create_in_ou;
 	r->in.os_name		= os_name;
 	r->in.os_version	= os_version;
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index a40b477a173..85257f445d8 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -277,6 +277,21 @@ rm -f $dedicated_keytab_file
 
 testit "leave+createupn" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
+#
+# Test dnshostname option of 'net ads join'
+#
+testit "join+dnshostname" $VALGRIND $net_tool ads join -U$DC_USERNAME%$DC_PASSWORD dnshostname="alt.hostname.$HOSTNAME" || failed=`expr $failed + 1`
+
+testit_grep "check dnshostname opt" "dNSHostName: alt.hostname.$HOSTNAME" $ldbsearch -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "CN=$HOSTNAME,CN=Computers,$base_dn" || failed=`expr $failed + 1`
+
+testit "create_keytab+dnshostname" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+testit_grep "check dnshostname+keytab" "host/alt.hostname.$HOSTNAME@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+rm -f $dedicated_keytab_file
+
+testit "leave+dnshostname" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
 rm -rf $BASEDIR/$WORKDIR
 
 exit $failed
-- 
2.41.0


From 25a6679a5260dafde7a7d2aed9bfe43eaf083b1c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:04:57 +0200
Subject: [PATCH 008/146] CVE-2020-1472(ZeroLogon): libcli/auth: add
 netlogon_creds_random_challenge()

It's good to have just a single isolated function that will generate
random challenges, in future we can add some logic in order to
avoid weak values, which are likely to be rejected by a server.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 libcli/auth/credentials.c | 8 ++++++++
 libcli/auth/proto.h       | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c
index b6c8ba281ba..dbbef9e7a3c 100644
--- a/libcli/auth/credentials.c
+++ b/libcli/auth/credentials.c
@@ -26,9 +26,17 @@
 #include "libcli/auth/libcli_auth.h"
 #include "../libcli/security/dom_sid.h"
 
+
+void netlogon_creds_random_challenge(struct netr_Credential *challenge)
+{
+	ZERO_STRUCTP(challenge);
+	generate_random_buffer(challenge->data, sizeof(challenge->data));
+}
+
 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
 				      const struct netr_Credential *in,
 				      struct netr_Credential *out)
+
 {
 	if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
 		AES_KEY key;
diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h
index 82febe74440..82797d453ed 100644
--- a/libcli/auth/proto.h
+++ b/libcli/auth/proto.h
@@ -11,6 +11,8 @@
 
 /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/credentials.c  */
 
+void netlogon_creds_random_challenge(struct netr_Credential *challenge);
+
 void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key);
 void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key);
 void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass);
-- 
2.41.0


From 1e8ad7efe35d8b79fef387ff709d6a499565c39a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:07:30 +0200
Subject: [PATCH 009/146] CVE-2020-1472(ZeroLogon): s4:torture/rpc: make use of
 netlogon_creds_random_challenge()

This will avoid getting flakey tests once our server starts to
reject weak challenges.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/torture/rpc/lsa.c      |  2 +-
 source4/torture/rpc/netlogon.c | 34 ++++++++++++----------------------
 2 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 21cc16afbaf..7bdc0cf679a 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -2847,7 +2847,7 @@ static bool check_pw_with_ServerAuthenticate3(struct dcerpc_pipe *p,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge failed");
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 026d86d50e4..e11014922f8 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -160,7 +160,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge failed");
@@ -229,7 +229,7 @@ bool test_SetupCredentials2ex(struct dcerpc_pipe *p, struct torture_context *tct
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge failed");
@@ -318,7 +318,7 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge failed");
@@ -390,7 +390,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge failed");
@@ -1278,7 +1278,7 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1367,7 +1367,7 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1456,7 +1456,7 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1546,7 +1546,7 @@ static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1638,8 +1638,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
 	r.in.credentials = &credentials1_random;
 	r.out.return_credentials = &credentials_discard;
 
-	generate_random_buffer(credentials1_random.data,
-			       sizeof(credentials1_random.data));
+	netlogon_creds_random_challenge(&credentials1_random);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1651,7 +1650,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1662,16 +1661,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx,
 	r.in.credentials = &credentials1_random;
 	r.out.return_credentials = &credentials_discard;
 
-	generate_random_buffer(credentials1_random.data,
-			       sizeof(credentials1_random.data));
-
-	r.in.server_name = NULL;
-	r.in.computer_name = "CHALTEST3";
-	r.in.credentials = &credentials1_random;
-	r.out.return_credentials = &credentials_discard;
-
-	generate_random_buffer(credentials1_random.data,
-			       sizeof(credentials1_random.data));
+	netlogon_creds_random_challenge(&credentials1_random);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r),
 		"ServerReqChallenge failed on b1");
@@ -1747,7 +1737,7 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx,
 	r.in.credentials = &credentials1;
 	r.out.return_credentials = &credentials2;
 
-	generate_random_buffer(credentials1.data, sizeof(credentials1.data));
+	netlogon_creds_random_challenge(&credentials1);
 
 	torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
 		"ServerReqChallenge");
-- 
2.41.0


From 74ee204ad4647d0d7a2097124652cbcd43406c7d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:08:38 +0200
Subject: [PATCH 010/146] CVE-2020-1472(ZeroLogon): libcli/auth: make use of
 netlogon_creds_random_challenge() in netlogon_creds_cli.c

This will avoid getting rejected by the server if we generate
a weak challenge.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 libcli/auth/netlogon_creds_cli.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index 817d2cd041a..0f6ca11ff96 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -1177,8 +1177,7 @@ static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req)
 
 	TALLOC_FREE(state->creds);
 
-	generate_random_buffer(state->client_challenge.data,
-			       sizeof(state->client_challenge.data));
+	netlogon_creds_random_challenge(&state->client_challenge);
 
 	subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev,
 						state->binding_handle,
-- 
2.41.0


From 10196846d019d0e2ccef51f32ddd39fc17ca60aa Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:10:53 +0200
Subject: [PATCH 011/146] CVE-2020-1472(ZeroLogon): s3:rpc_server:netlogon:
 make use of netlogon_creds_random_challenge()

This is not strictly needed, but makes things more clear.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 87613b99fde..86b2f343e82 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -840,8 +840,7 @@ NTSTATUS _netr_ServerReqChallenge(struct pipes_struct *p,
 
 	pipe_state->client_challenge = *r->in.credentials;
 
-	generate_random_buffer(pipe_state->server_challenge.data,
-			       sizeof(pipe_state->server_challenge.data));
+	netlogon_creds_random_challenge(&pipe_state->server_challenge);
 
 	*r->out.return_credentials = pipe_state->server_challenge;
 
-- 
2.41.0


From 215aca6d11b900ee3cf11568d27bce77e0567653 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:10:53 +0200
Subject: [PATCH 012/146] CVE-2020-1472(ZeroLogon): s4:rpc_server:netlogon:
 make use of netlogon_creds_random_challenge()

This is not strictly needed, but makes things more clear.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 023adfd99e9..de260d8051d 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -90,8 +90,7 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal
 
 	pipe_state->client_challenge = *r->in.credentials;
 
-	generate_random_buffer(pipe_state->server_challenge.data,
-			       sizeof(pipe_state->server_challenge.data));
+	netlogon_creds_random_challenge(&pipe_state->server_challenge);
 
 	*r->out.return_credentials = pipe_state->server_challenge;
 
-- 
2.41.0


From 4551bf623426e8c543b287807d447feb69bb0f09 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:15:26 +0200
Subject: [PATCH 013/146] CVE-2020-1472(ZeroLogon): libcli/auth: add
 netlogon_creds_is_random_challenge() to avoid weak values

This is the check Windows is using, so we won't generate challenges,
which are rejected by Windows DCs (and future Samba DCs).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 libcli/auth/credentials.c | 23 ++++++++++++++++++++++-
 libcli/auth/proto.h       |  1 +
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c
index dbbef9e7a3c..64b424c099f 100644
--- a/libcli/auth/credentials.c
+++ b/libcli/auth/credentials.c
@@ -27,10 +27,31 @@
 #include "../libcli/security/dom_sid.h"
 
 
+bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge)
+{
+	/*
+	 * If none of the first 5 bytes of the client challenge is unique, the
+	 * server MUST fail session-key negotiation without further processing
+	 * of the following steps.
+	 */
+
+	if (challenge->data[1] == challenge->data[0] &&
+	    challenge->data[2] == challenge->data[0] &&
+	    challenge->data[3] == challenge->data[0] &&
+	    challenge->data[4] == challenge->data[0])
+	{
+		return false;
+	}
+
+	return true;
+}
+
 void netlogon_creds_random_challenge(struct netr_Credential *challenge)
 {
 	ZERO_STRUCTP(challenge);
-	generate_random_buffer(challenge->data, sizeof(challenge->data));
+	while (!netlogon_creds_is_random_challenge(challenge)) {
+		generate_random_buffer(challenge->data, sizeof(challenge->data));
+	}
 }
 
 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h
index 82797d453ed..ad768682b9f 100644
--- a/libcli/auth/proto.h
+++ b/libcli/auth/proto.h
@@ -11,6 +11,7 @@
 
 /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/credentials.c  */
 
+bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge);
 void netlogon_creds_random_challenge(struct netr_Credential *challenge);
 
 void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key);
-- 
2.41.0


From f7e09421ace8fe60c0110770d909800d21ae6c8e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 16:17:29 +0200
Subject: [PATCH 014/146] CVE-2020-1472(ZeroLogon): libcli/auth: reject weak
 client challenges in netlogon_creds_server_init()

This implements the note from MS-NRPC 3.1.4.1 Session-Key Negotiation:

 7. If none of the first 5 bytes of the client challenge is unique, the
    server MUST fail session-key negotiation without further processing of
    the following steps.

It lets ./zerologon_tester.py from
https://github.com/SecuraBV/CVE-2020-1472.git
report: "Attack failed. Target is probably patched."

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[dbagnall@samba.org, abartlet@samba.org: wscript_build backport
differs because 4.10 has no gnutls dependency]
---
 libcli/auth/credentials.c | 16 ++++++++++++++++
 libcli/auth/wscript_build |  2 +-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c
index 64b424c099f..e2bc82809b7 100644
--- a/libcli/auth/credentials.c
+++ b/libcli/auth/credentials.c
@@ -25,6 +25,7 @@
 #include "../lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
 #include "../libcli/security/dom_sid.h"
+#include "lib/util/util_str_escape.h"
 
 
 bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge)
@@ -451,6 +452,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me
 {
 
 	struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
+	bool ok;
 
 	if (!creds) {
 		return NULL;
@@ -463,6 +465,20 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me
 	dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
 	dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
 
+	ok = netlogon_creds_is_random_challenge(client_challenge);
+	if (!ok) {
+		DBG_WARNING("CVE-2020-1472(ZeroLogon): "
+			    "non-random client challenge rejected for "
+			    "client_account[%s] client_computer_name[%s]\n",
+			    log_escape(mem_ctx, client_account),
+			    log_escape(mem_ctx, client_computer_name));
+		dump_data(DBGLVL_WARNING,
+			  client_challenge->data,
+			  sizeof(client_challenge->data));
+		talloc_free(creds);
+		return NULL;
+	}
+
 	creds->computer_name = talloc_strdup(creds, client_computer_name);
 	if (!creds->computer_name) {
 		talloc_free(creds);
diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build
index d319d9b879e..394505d166d 100644
--- a/libcli/auth/wscript_build
+++ b/libcli/auth/wscript_build
@@ -18,7 +18,7 @@ bld.SAMBA_SUBSYSTEM('NTLM_CHECK',
 
 bld.SAMBA_SUBSYSTEM('LIBCLI_AUTH',
 	source='credentials.c session.c smbencrypt.c smbdes.c',
-	public_deps='MSRPC_PARSE',
+	public_deps='MSRPC_PARSE util_str_escape',
 	public_headers='credentials.h:domain_credentials.h'
 	)
 
-- 
2.41.0


From 6bc86fb69bf50c89a334fd2dcbce6999a2360fb7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 19:20:25 +0200
Subject: [PATCH 015/146] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon:
 protect netr_ServerPasswordSet2 against unencrypted passwords

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 60 ++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index de260d8051d..acbf077c6c7 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -722,7 +722,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
 	struct NL_PASSWORD_VERSION version = {};
 	const uint32_t *new_version = NULL;
 	NTSTATUS nt_status;
-	DATA_BLOB new_password;
+	DATA_BLOB new_password = data_blob_null;
+	size_t confounder_len;
+	DATA_BLOB dec_blob = data_blob_null;
+	DATA_BLOB enc_blob = data_blob_null;
 	int ret;
 	struct samr_CryptPassword password_buf;
 
@@ -780,6 +783,61 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal
 		return NT_STATUS_WRONG_PASSWORD;
 	}
 
+	/*
+	 * Make sure the length field was encrypted,
+	 * otherwise we are under attack.
+	 */
+	if (new_password.length == r->in.new_password->length) {
+		DBG_WARNING("Length[%zu] field not encrypted\n",
+			    new_password.length);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * We don't allow empty passwords for machine accounts.
+	 */
+	if (new_password.length < 2) {
+		DBG_WARNING("Empty password Length[%zu]\n",
+			    new_password.length);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * Make sure the confounder part of CryptPassword
+	 * buffer was encrypted, otherwise we are under attack.
+	 */
+	confounder_len = 512 - new_password.length;
+	enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
+	dec_blob = data_blob_const(password_buf.data, confounder_len);
+	if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+		DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
+			    confounder_len);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * Check that the password part was actually encrypted,
+	 * otherwise we are under attack.
+	 */
+	enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
+				   new_password.length);
+	dec_blob = data_blob_const(password_buf.data + confounder_len,
+				   new_password.length);
+	if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+		DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
+			    new_password.length);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * don't allow zero buffers
+	 */
+	if (all_zero(new_password.data, new_password.length)) {
+		DBG_WARNING("Password zero buffer Length[%zu]\n",
+			    new_password.length);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
 	/* fetch the old password hashes (at least one of both has to exist) */
 
 	ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
-- 
2.41.0


From 1f8dec1cbb37f3406d999425590f8a923586ccac Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Wed, 16 Sep 2020 12:53:50 -0700
Subject: [PATCH 016/146] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon:
 protect netr_ServerPasswordSet2 against unencrypted passwords

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Jeremy Allison <jra@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 98 +++++++++++++++++++--
 1 file changed, 92 insertions(+), 6 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 86b2f343e82..fd9127b386f 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1326,9 +1326,14 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
 {
 	NTSTATUS status;
 	struct netlogon_creds_CredentialState *creds = NULL;
-	DATA_BLOB plaintext;
+	DATA_BLOB plaintext = data_blob_null;
+	DATA_BLOB new_password = data_blob_null;
+	size_t confounder_len;
+	DATA_BLOB dec_blob = data_blob_null;
+	DATA_BLOB enc_blob = data_blob_null;
 	struct samr_CryptPassword password_buf;
 	struct _samr_Credentials_t cr = { CRED_TYPE_PLAIN_TEXT, {0}};
+	bool ok;
 
 	become_root();
 	status = netr_creds_server_step_check(p, p->mem_ctx,
@@ -1364,18 +1369,99 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p,
 		netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
 	}
 
-	if (!decode_pw_buffer(p->mem_ctx,
-			      password_buf.data,
-			      (char**) &plaintext.data,
-			      &plaintext.length,
-			      CH_UTF16)) {
+	if (!extract_pw_from_buffer(p->mem_ctx, password_buf.data, &new_password)) {
 		DEBUG(2,("_netr_ServerPasswordSet2: unable to extract password "
 			 "from a buffer. Rejecting auth request as a wrong password\n"));
 		TALLOC_FREE(creds);
 		return NT_STATUS_WRONG_PASSWORD;
 	}
 
+	/*
+	 * Make sure the length field was encrypted,
+	 * otherwise we are under attack.
+	 */
+	if (new_password.length == r->in.new_password->length) {
+		DBG_WARNING("Length[%zu] field not encrypted\n",
+			new_password.length);
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * We don't allow empty passwords for machine accounts.
+	 */
+	if (new_password.length < 2) {
+		DBG_WARNING("Empty password Length[%zu]\n",
+			new_password.length);
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * Make sure the confounder part of CryptPassword
+	 * buffer was encrypted, otherwise we are under attack.
+	 */
+	confounder_len = 512 - new_password.length;
+	enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
+	dec_blob = data_blob_const(password_buf.data, confounder_len);
+	if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+		DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
+			    confounder_len);
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * Check that the password part was actually encrypted,
+	 * otherwise we are under attack.
+	 */
+	enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
+				   new_password.length);
+	dec_blob = data_blob_const(password_buf.data + confounder_len,
+				   new_password.length);
+	if (data_blob_cmp(&dec_blob, &enc_blob) == 0) {
+		DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
+			    new_password.length);
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * don't allow zero buffers
+	 */
+	if (all_zero(new_password.data, new_password.length)) {
+		DBG_WARNING("Password zero buffer Length[%zu]\n",
+			    new_password.length);
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/* Convert from UTF16 -> plaintext. */
+	ok = convert_string_talloc(p->mem_ctx,
+				CH_UTF16,
+				CH_UNIX,
+				new_password.data,
+				new_password.length,
+				(void *)&plaintext.data,
+				&plaintext.length);
+	if (!ok) {
+		DBG_WARNING("unable to extract password from a buffer. "
+			    "Rejecting auth request as a wrong password\n");
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
+	/*
+	 * We don't allow empty passwords for machine accounts.
+	 */
+
 	cr.creds.password = (const char*) plaintext.data;
+	if (strlen(cr.creds.password) == 0) {
+		DBG_WARNING("Empty plaintext password\n");
+		TALLOC_FREE(creds);
+		return NT_STATUS_WRONG_PASSWORD;
+	}
+
 	status = netr_set_machine_account_password(p->mem_ctx,
 						   p->session_info,
 						   p->msg_ctx,
-- 
2.41.0


From 2ad269be74481789ded62a3dcb538709c6d6e291 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 10:18:45 +0200
Subject: [PATCH 017/146] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon:
 refactor dcesrv_netr_creds_server_step_check()

We should debug more details about the failing request.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 45 ++++++++++++++-----
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index acbf077c6c7..b4326a4ecaa 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -623,26 +623,47 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	NTSTATUS nt_status;
 	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
 	bool schannel_global_required = (schannel == true);
+	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 (schannel_global_required) {
-		enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
-
-		dcesrv_call_auth_info(dce_call, &auth_type, NULL);
-
-		if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
-			DBG_ERR("[%s] is not using schannel\n",
-				computer_name);
-			return NT_STATUS_ACCESS_DENIED;
-		}
+	if (opnum < ndr_table_netlogon.num_calls) {
+		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
+	dcesrv_call_auth_info(dce_call, &auth_type, NULL);
+
 	nt_status = schannel_check_creds_state(mem_ctx,
 					       dce_call->conn->dce_ctx->lp_ctx,
 					       computer_name,
 					       received_authenticator,
 					       return_authenticator,
-					       creds_out);
-	return nt_status;
+					       &creds);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		ZERO_STRUCTP(return_authenticator);
+		return nt_status;
+	}
+
+	if (schannel_global_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));
+		TALLOC_FREE(creds);
+		ZERO_STRUCTP(return_authenticator);
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	*creds_out = creds;
+	return NT_STATUS_OK;
 }
 
 /*
-- 
2.41.0


From 57941290adb9a2fd4be9aa4a70f879a684b38dfd Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 16 Sep 2020 10:56:53 +0200
Subject: [PATCH 018/146] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon:
 support "server require schannel:WORKSTATION$ = no"

This allows to add expections for individual workstations, when using "server schannel = yes".
"server schannel = auto" is very insecure and will be removed soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index b4326a4ecaa..e7bafb31e83 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -623,6 +623,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	NTSTATUS nt_status;
 	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
 	bool schannel_global_required = (schannel == true);
+	bool schannel_required = schannel_global_required;
 	struct netlogon_creds_CredentialState *creds = NULL;
 	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
 	uint16_t opnum = dce_call->pkt.u.request.opnum;
@@ -645,7 +646,13 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		return nt_status;
 	}
 
-	if (schannel_global_required) {
+	schannel_required = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
+					    NULL,
+					    "server require schannel",
+					    creds->account_name,
+					    schannel_global_required);
+
+	if (schannel_required) {
 		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 			*creds_out = creds;
 			return NT_STATUS_OK;
-- 
2.41.0


From 779b37e825fe406892ff77be18c098d314cd387d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 17 Sep 2020 13:37:26 +0200
Subject: [PATCH 019/146] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: log
 warnings about unsecure configurations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This should give admins wawrnings until they have a secure
configuration.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 66 ++++++++++++++++++-
 1 file changed, 63 insertions(+), 3 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index e7bafb31e83..7668a9eb923 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -624,10 +624,12 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
 	bool schannel_global_required = (schannel == true);
 	bool schannel_required = schannel_global_required;
+	const char *explicit_opt = NULL;
 	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>";
+	static bool warned_global_once = false;
 
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
@@ -646,11 +648,18 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		return nt_status;
 	}
 
-	schannel_required = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
+	/*
+	 * 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(dce_call->conn->dce_ctx->lp_ctx,
 					    NULL,
 					    "server require schannel",
-					    creds->account_name,
-					    schannel_global_required);
+					    creds->account_name);
+	if (explicit_opt != NULL) {
+		schannel_required = lp_bool(explicit_opt);
+	}
 
 	if (schannel_required) {
 		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
@@ -664,11 +673,62 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			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 (!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 "
+			"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;
 }
-- 
2.41.0


From 60b83fbda31c53c592a02f0ed43356a912021021 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Thu, 17 Sep 2020 14:57:22 +0200
Subject: [PATCH 020/146] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon:
 refactor dcesrv_netr_creds_server_step_check()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We should debug more details about the failing request.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Günther Deschner <gd@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 43 +++++++++++++++++----
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index fd9127b386f..8541571b459 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -48,6 +48,7 @@
 #include "../lib/tsocket/tsocket.h"
 #include "lib/param/param.h"
 #include "libsmb/dsgetdcname.h"
+#include "lib/util/util_str_escape.h"
 
 extern userdom_struct current_user_info;
 
@@ -1073,19 +1074,21 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	NTSTATUS status;
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
 	struct loadparm_context *lp_ctx;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
+	uint16_t opnum = p->opnum;
+	const char *opname = "<unknown>";
 
 	if (creds_out != NULL) {
 		*creds_out = NULL;
 	}
 
-	if (schannel_global_required) {
-		if (p->auth.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
-			DBG_ERR("[%s] is not using schannel\n",
-				computer_name);
-			return NT_STATUS_ACCESS_DENIED;
-		}
+	if (opnum < ndr_table_netlogon.num_calls) {
+		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
+	auth_type = p->auth.auth_type;
+
 	lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers());
 	if (lp_ctx == NULL) {
 		DEBUG(0, ("loadparm_init_s3 failed\n"));
@@ -1094,9 +1097,33 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 
 	status = schannel_check_creds_state(mem_ctx, lp_ctx,
 					    computer_name, received_authenticator,
-					    return_authenticator, creds_out);
+					    return_authenticator, &creds);
 	talloc_unlink(mem_ctx, lp_ctx);
-	return status;
+
+	if (!NT_STATUS_IS_OK(status)) {
+		ZERO_STRUCTP(return_authenticator);
+		return status;
+	}
+
+	if (schannel_global_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));
+		TALLOC_FREE(creds);
+		ZERO_STRUCTP(return_authenticator);
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	*creds_out = creds;
+	return NT_STATUS_OK;
 }
 
 
-- 
2.41.0


From c0a188b2696edb8f3ae9f7f56a820b11358bad98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Thu, 17 Sep 2020 14:23:16 +0200
Subject: [PATCH 021/146] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon:
 support "server require schannel:WORKSTATION$ = no"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This allows to add expections for individual workstations, when using "server schannel = yes".
"server schannel = auto" is very insecure and will be removed soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Günther Deschner <gd@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 8541571b459..f9b10103bd5 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1073,6 +1073,7 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 {
 	NTSTATUS status;
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
+	bool schannel_required = schannel_global_required;
 	struct loadparm_context *lp_ctx;
 	struct netlogon_creds_CredentialState *creds = NULL;
 	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
@@ -1105,7 +1106,11 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		return status;
 	}
 
-	if (schannel_global_required) {
+	schannel_required = lp_parm_bool(GLOBAL_SECTION_SNUM,
+					 "server require schannel",
+					 creds->account_name,
+					 schannel_global_required);
+	if (schannel_required) {
 		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 			*creds_out = creds;
 			return NT_STATUS_OK;
-- 
2.41.0


From c9550b81b55316cf5d667502885fc248a5999fb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
Date: Thu, 17 Sep 2020 14:42:52 +0200
Subject: [PATCH 022/146] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: log
 warnings about unsecure configurations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Günther Deschner <gd@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 70 +++++++++++++++++++--
 1 file changed, 66 insertions(+), 4 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index f9b10103bd5..7f6704adbda 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1074,11 +1074,13 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	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 = p->opnum;
 	const char *opname = "<unknown>";
+	static bool warned_global_once = false;
 
 	if (creds_out != NULL) {
 		*creds_out = NULL;
@@ -1106,10 +1108,20 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		return status;
 	}
 
-	schannel_required = lp_parm_bool(GLOBAL_SECTION_SNUM,
-					 "server require schannel",
-					 creds->account_name,
-					 schannel_global_required);
+	/*
+	 * 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;
@@ -1122,11 +1134,61 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			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 (!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 "
+			"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;
 }
-- 
2.41.0


From 63f03e2e29e81f890a5d88c726cced6d3e7bbf5d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 17 Sep 2020 17:27:54 +0200
Subject: [PATCH 023/146] CVE-2020-1472(ZeroLogon): docs-xml: document 'server
 require schannel:COMPUTERACCOUNT'

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 .../smbdotconf/security/serverschannel.xml    | 69 +++++++++++++++----
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml
index 489492d79b1..b682d086f76 100644
--- a/docs-xml/smbdotconf/security/serverschannel.xml
+++ b/docs-xml/smbdotconf/security/serverschannel.xml
@@ -7,26 +7,65 @@
 <description>
 
     <para>
-	This option is deprecated with Samba 4.8 and will be removed in future.
-	At the same time the default changed to yes, which will be the
-	hardcoded behavior in future. If you have the need for the behavior of "auto"
-	to be kept, please file a bug at https://bugzilla.samba.org.
+	This option is deprecated and will be removed in future,
+	as it is a security problem if not set to "yes" (which will be
+	the hardcoded behavior in future).
     </para>
 
     <para>
-	This controls whether the server offers or even demands the use of the netlogon schannel.
-	<smbconfoption name="server schannel">no</smbconfoption> does not offer the schannel, <smbconfoption
-	name="server schannel">auto</smbconfoption> offers the schannel but does not enforce it, and <smbconfoption
-	name="server schannel">yes</smbconfoption> denies access if the client is not able to speak netlogon schannel.
-	This is only the case for Windows NT4 before SP4.
-	</para>
-
+	Samba will complain in the log files at log level 0,
+	about the security problem if the option is not set to "yes".
+    </para>
     <para>
-	Please note that with this set to <literal>no</literal>, you will have to apply the WindowsXP
-	<filename>WinXP_SignOrSeal.reg</filename> registry patch found in the docs/registry subdirectory of the Samba distribution tarball.
-	</para>
+	See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497
+    </para>
+
+    <para>If you still have legacy domain members use the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.
+    </para>
+
+    <para>This option yields precedence to the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.</para>
+
 </description>
 
 <value type="default">yes</value>
-<value type="example">auto</value>
+</samba:parameter>
+
+<samba:parameter name="server require schannel:COMPUTERACCOUNT"
+                 context="G"
+                 type="string"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+    <para>If you still have legacy domain members, which required "server schannel = auto" before,
+	it is possible to specify explicit expection per computer account
+	by using 'server require schannel:COMPUTERACCOUNT = no' as option.
+	Note that COMPUTERACCOUNT has to be the sAMAccountName value of
+	the computer account (including the trailing '$' sign).
+    </para>
+
+    <para>
+	Samba will complain in the log files at log level 0,
+	about the security problem if the option is not set to "no",
+	but the related computer is actually using the netlogon
+	secure channel (schannel) feature.
+    </para>
+
+    <para>
+	Samba will warn in the log files at log level 5,
+	if a setting is still needed for the specified computer account.
+    </para>
+
+    <para>
+	See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497
+    </para>
+
+    <para>This option takes precedence to the <smbconfoption name="server schannel"/> option.</para>
+
+    <programlisting>
+	server require schannel:LEGACYCOMPUTER1$ = no
+	server require schannel:NASBOX$ = no
+	server require schannel:LEGACYCOMPUTER2$ = no
+    </programlisting>
+</description>
+
 </samba:parameter>
-- 
2.41.0


From 8a40da45b7f4e7a9110daf010383c4fce30bd9b6 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Fri, 18 Sep 2020 12:39:54 +1200
Subject: [PATCH 024/146] CVE-2020-1472(ZeroLogon): s4 torture rpc: Test empty
 machine acct pwd

Ensure that an empty machine account password can't be set by
netr_ServerPasswordSet2

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
---
 source4/torture/rpc/netlogon.c | 64 +++++++++++++++-------------------
 1 file changed, 29 insertions(+), 35 deletions(-)

diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index e11014922f8..0ba45f0c1da 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -719,45 +719,39 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx,
 
 	cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
 
-	if (!torture_setting_bool(tctx, "dangerous", false)) {
-		torture_comment(tctx,
-			"Not testing ability to set password to '', enable dangerous tests to perform this test\n");
+	/*
+	 * As a consequence of CVE-2020-1472(ZeroLogon)
+	 * Samba explicitly disallows the setting of an empty machine account
+	 * password.
+	 *
+	 * Note that this may fail against Windows, and leave a machine account
+	 * with an empty password.
+	 */
+	password = "";
+	encode_pw_buffer(password_buf.data, password, STR_UNICODE);
+	if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+		netlogon_creds_aes_encrypt(creds, password_buf.data, 516);
 	} else {
-		/* by changing the machine password to ""
-		 * we check if the server uses password restrictions
-		 * for ServerPasswordSet2
-		 * (win2k3 accepts "")
-		 */
-		password = "";
-		encode_pw_buffer(password_buf.data, password, STR_UNICODE);
-		if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
-			netlogon_creds_aes_encrypt(creds, password_buf.data, 516);
-		} else {
-			netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
-		}
-		memcpy(new_password.data, password_buf.data, 512);
-		new_password.length = IVAL(password_buf.data, 512);
-
-		torture_comment(tctx,
-			"Testing ServerPasswordSet2 on machine account\n");
-		torture_comment(tctx,
-			"Changing machine account password to '%s'\n", password);
-
-		netlogon_creds_client_authenticator(creds, &credential);
-
-		torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerPasswordSet2_r(b, tctx, &r),
-			"ServerPasswordSet2 failed");
-		torture_assert_ntstatus_ok(tctx, r.out.result, "ServerPasswordSet2 failed");
+		netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
+	}
+	memcpy(new_password.data, password_buf.data, 512);
+	new_password.length = IVAL(password_buf.data, 512);
 
-		if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
-			torture_comment(tctx, "Credential chaining failed\n");
-		}
+	torture_comment(tctx,
+		"Testing ServerPasswordSet2 on machine account\n");
+	torture_comment(tctx,
+		"Changing machine account password to '%s'\n", password);
 
-		cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED);
-	}
+	netlogon_creds_client_authenticator(creds, &credential);
 
-	torture_assert(tctx, test_SetupCredentials(p, tctx, machine_credentials, &creds),
-		"ServerPasswordSet failed to actually change the password");
+	torture_assert_ntstatus_ok(
+		tctx, dcerpc_netr_ServerPasswordSet2_r(b, tctx, &r),
+		"ServerPasswordSet2 failed");
+	torture_assert_ntstatus_equal(
+		tctx,
+		r.out.result,
+		NT_STATUS_WRONG_PASSWORD,
+		"ServerPasswordSet2 did not return NT_STATUS_WRONG_PASSWORD");
 
 	/* now try a random password */
 	password = generate_random_password(tctx, 8, 255);
-- 
2.41.0


From 341a448cb69557410fa79dbb8a3d4adbab79d5b6 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Fri, 18 Sep 2020 15:57:34 +1200
Subject: [PATCH 025/146] CVE-2020-1472(ZeroLogon): s4 torture rpc: repeated
 bytes in client challenge

Ensure that client challenges with the first 5 bytes identical are
rejected.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>

[abartlet@samba.org: backported from master as test order was flipped]
---
 source4/torture/rpc/netlogon.c | 335 +++++++++++++++++++++++++++++++++
 1 file changed, 335 insertions(+)

diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 0ba45f0c1da..97c16688bc9 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -480,6 +480,325 @@ bool test_SetupCredentialsPipe(const struct dcerpc_pipe *p1,
 	return true;
 }
 
+static bool test_ServerReqChallenge(
+	struct torture_context *tctx,
+	struct dcerpc_pipe *p,
+	struct cli_credentials *credentials)
+{
+	struct netr_ServerReqChallenge r;
+	struct netr_Credential credentials1, credentials2, credentials3;
+	const char *machine_name;
+	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct netr_ServerAuthenticate2 a;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t out_negotiate_flags = 0;
+	const struct samr_Password *mach_password = NULL;
+	enum netr_SchannelType sec_chan_type = 0;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	const char *account_name = NULL;
+
+	machine_name = cli_credentials_get_workstation(credentials);
+	mach_password = cli_credentials_get_nt_hash(credentials, tctx);
+	account_name = cli_credentials_get_username(credentials);
+	sec_chan_type = cli_credentials_get_secure_channel_type(credentials);
+
+	torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+	r.in.server_name = NULL;
+	r.in.computer_name = machine_name;
+	r.in.credentials = &credentials1;
+	r.out.return_credentials = &credentials2;
+
+	netlogon_creds_random_challenge(&credentials1);
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+		"ServerReqChallenge failed");
+	torture_assert_ntstatus_ok(
+		tctx,
+		r.out.result,
+		"ServerReqChallenge failed");
+	a.in.server_name = NULL;
+	a.in.account_name = account_name;
+	a.in.secure_channel_type = sec_chan_type;
+	a.in.computer_name = machine_name;
+	a.in.negotiate_flags = &in_negotiate_flags;
+	a.out.negotiate_flags = &out_negotiate_flags;
+	a.in.credentials = &credentials3;
+	a.out.return_credentials = &credentials3;
+
+	creds = netlogon_creds_client_init(tctx, a.in.account_name,
+					   a.in.computer_name,
+					   a.in.secure_channel_type,
+					   &credentials1, &credentials2,
+					   mach_password, &credentials3,
+					   in_negotiate_flags);
+
+	torture_assert(tctx, creds != NULL, "memory allocation");
+
+	torture_comment(tctx, "Testing ServerAuthenticate2\n");
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a),
+		"ServerAuthenticate2 failed");
+	torture_assert_ntstatus_equal(
+		tctx,
+		a.out.result,
+		NT_STATUS_OK,
+		"ServerAuthenticate2 unexpected");
+
+	return true;
+}
+
+static bool test_ServerReqChallenge_zero_challenge(
+	struct torture_context *tctx,
+	struct dcerpc_pipe *p,
+	struct cli_credentials *credentials)
+{
+	struct netr_ServerReqChallenge r;
+	struct netr_Credential credentials1, credentials2, credentials3;
+	const char *machine_name;
+	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct netr_ServerAuthenticate2 a;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t out_negotiate_flags = 0;
+	const struct samr_Password *mach_password = NULL;
+	enum netr_SchannelType sec_chan_type = 0;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	const char *account_name = NULL;
+
+	machine_name = cli_credentials_get_workstation(credentials);
+	mach_password = cli_credentials_get_nt_hash(credentials, tctx);
+	account_name = cli_credentials_get_username(credentials);
+	sec_chan_type = cli_credentials_get_secure_channel_type(credentials);
+
+	torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+	r.in.server_name = NULL;
+	r.in.computer_name = machine_name;
+	r.in.credentials = &credentials1;
+	r.out.return_credentials = &credentials2;
+
+	/*
+	 * Set the client challenge to zero, this should fail
+	 * CVE-2020-1472(ZeroLogon)
+	 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497
+	 */
+	ZERO_STRUCT(credentials1);
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+		"ServerReqChallenge failed");
+	torture_assert_ntstatus_ok(
+		tctx,
+		r.out.result,
+		"ServerReqChallenge failed");
+	a.in.server_name = NULL;
+	a.in.account_name = account_name;
+	a.in.secure_channel_type = sec_chan_type;
+	a.in.computer_name = machine_name;
+	a.in.negotiate_flags = &in_negotiate_flags;
+	a.out.negotiate_flags = &out_negotiate_flags;
+	a.in.credentials = &credentials3;
+	a.out.return_credentials = &credentials3;
+
+	creds = netlogon_creds_client_init(tctx, a.in.account_name,
+					   a.in.computer_name,
+					   a.in.secure_channel_type,
+					   &credentials1, &credentials2,
+					   mach_password, &credentials3,
+					   in_negotiate_flags);
+
+	torture_assert(tctx, creds != NULL, "memory allocation");
+
+	torture_comment(tctx, "Testing ServerAuthenticate2\n");
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a),
+		"ServerAuthenticate2 failed");
+	torture_assert_ntstatus_equal(
+		tctx,
+		a.out.result,
+		NT_STATUS_ACCESS_DENIED,
+		"ServerAuthenticate2 unexpected");
+
+	return true;
+}
+
+static bool test_ServerReqChallenge_5_repeats(
+	struct torture_context *tctx,
+	struct dcerpc_pipe *p,
+	struct cli_credentials *credentials)
+{
+	struct netr_ServerReqChallenge r;
+	struct netr_Credential credentials1, credentials2, credentials3;
+	const char *machine_name;
+	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct netr_ServerAuthenticate2 a;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t out_negotiate_flags = 0;
+	const struct samr_Password *mach_password = NULL;
+	enum netr_SchannelType sec_chan_type = 0;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	const char *account_name = NULL;
+
+	machine_name = cli_credentials_get_workstation(credentials);
+	mach_password = cli_credentials_get_nt_hash(credentials, tctx);
+	account_name = cli_credentials_get_username(credentials);
+	sec_chan_type = cli_credentials_get_secure_channel_type(credentials);
+
+	torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+	r.in.server_name = NULL;
+	r.in.computer_name = machine_name;
+	r.in.credentials = &credentials1;
+	r.out.return_credentials = &credentials2;
+
+	/*
+	 * Set the first 5 bytes of the client challenge to the same value,
+	 * this should fail CVE-2020-1472(ZeroLogon)
+	 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497
+	 */
+	credentials1.data[0] = 'A';
+	credentials1.data[1] = 'A';
+	credentials1.data[2] = 'A';
+	credentials1.data[3] = 'A';
+	credentials1.data[4] = 'A';
+	credentials1.data[5] = 'B';
+	credentials1.data[6] = 'C';
+	credentials1.data[7] = 'D';
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+		"ServerReqChallenge failed");
+	torture_assert_ntstatus_ok(
+		tctx,
+		r.out.result,
+		"ServerReqChallenge failed");
+	a.in.server_name = NULL;
+	a.in.account_name = account_name;
+	a.in.secure_channel_type = sec_chan_type;
+	a.in.computer_name = machine_name;
+	a.in.negotiate_flags = &in_negotiate_flags;
+	a.out.negotiate_flags = &out_negotiate_flags;
+	a.in.credentials = &credentials3;
+	a.out.return_credentials = &credentials3;
+
+	creds = netlogon_creds_client_init(tctx, a.in.account_name,
+					   a.in.computer_name,
+					   a.in.secure_channel_type,
+					   &credentials1, &credentials2,
+					   mach_password, &credentials3,
+					   in_negotiate_flags);
+
+	torture_assert(tctx, creds != NULL, "memory allocation");
+
+	torture_comment(tctx, "Testing ServerAuthenticate2\n");
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a),
+		"ServerAuthenticate2 failed");
+	torture_assert_ntstatus_equal(
+		tctx,
+		a.out.result,
+		NT_STATUS_ACCESS_DENIED,
+		"ServerAuthenticate2 unexpected");
+
+	return true;
+}
+
+static bool test_ServerReqChallenge_4_repeats(
+	struct torture_context *tctx,
+	struct dcerpc_pipe *p,
+	struct cli_credentials *credentials)
+{
+	struct netr_ServerReqChallenge r;
+	struct netr_Credential credentials1, credentials2, credentials3;
+	const char *machine_name;
+	struct dcerpc_binding_handle *b = p->binding_handle;
+	struct netr_ServerAuthenticate2 a;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t out_negotiate_flags = 0;
+	const struct samr_Password *mach_password = NULL;
+	enum netr_SchannelType sec_chan_type = 0;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	const char *account_name = NULL;
+
+	machine_name = cli_credentials_get_workstation(credentials);
+	mach_password = cli_credentials_get_nt_hash(credentials, tctx);
+	account_name = cli_credentials_get_username(credentials);
+	sec_chan_type = cli_credentials_get_secure_channel_type(credentials);
+
+	torture_comment(tctx, "Testing ServerReqChallenge\n");
+
+	r.in.server_name = NULL;
+	r.in.computer_name = machine_name;
+	r.in.credentials = &credentials1;
+	r.out.return_credentials = &credentials2;
+
+        /*
+         * Set the first 4 bytes of the client challenge to the same
+         * value, this should pass as 5 bytes identical are needed to
+         * fail for CVE-2020-1472(ZeroLogon)
+         *
+	 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497
+	 */
+	credentials1.data[0] = 'A';
+	credentials1.data[1] = 'A';
+	credentials1.data[2] = 'A';
+	credentials1.data[3] = 'A';
+	credentials1.data[4] = 'B';
+	credentials1.data[5] = 'C';
+	credentials1.data[6] = 'D';
+	credentials1.data[7] = 'E';
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerReqChallenge_r(b, tctx, &r),
+		"ServerReqChallenge failed");
+	torture_assert_ntstatus_ok(
+		tctx,
+		r.out.result,
+		"ServerReqChallenge failed");
+	a.in.server_name = NULL;
+	a.in.account_name = account_name;
+	a.in.secure_channel_type = sec_chan_type;
+	a.in.computer_name = machine_name;
+	a.in.negotiate_flags = &in_negotiate_flags;
+	a.out.negotiate_flags = &out_negotiate_flags;
+	a.in.credentials = &credentials3;
+	a.out.return_credentials = &credentials3;
+
+	creds = netlogon_creds_client_init(tctx, a.in.account_name,
+					   a.in.computer_name,
+					   a.in.secure_channel_type,
+					   &credentials1, &credentials2,
+					   mach_password, &credentials3,
+					   in_negotiate_flags);
+
+	torture_assert(tctx, creds != NULL, "memory allocation");
+
+	torture_comment(tctx, "Testing ServerAuthenticate2\n");
+
+	torture_assert_ntstatus_ok(
+		tctx,
+		dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a),
+		"ServerAuthenticate2 failed");
+	torture_assert_ntstatus_equal(
+		tctx,
+		a.out.result,
+		NT_STATUS_OK,
+		"ServerAuthenticate2 unexpected");
+
+	return true;
+}
+
 /*
   try a change password for our machine account
 */
@@ -4949,6 +5268,22 @@ struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx)
 	torture_rpc_tcase_add_test(tcase, "lsa_over_netlogon", test_lsa_over_netlogon);
 	torture_rpc_tcase_add_test_creds(tcase, "SetupCredentialsDowngrade", test_SetupCredentialsDowngrade);
 
+	torture_rpc_tcase_add_test_creds(
+		tcase,
+		"ServerReqChallenge",
+		test_ServerReqChallenge);
+	torture_rpc_tcase_add_test_creds(
+		tcase,
+		"ServerReqChallenge_zero_challenge",
+		test_ServerReqChallenge_zero_challenge);
+	torture_rpc_tcase_add_test_creds(
+		tcase,
+		"ServerReqChallenge_5_repeats",
+		test_ServerReqChallenge_5_repeats);
+	torture_rpc_tcase_add_test_creds(
+		tcase,
+		"ServerReqChallenge_4_repeats",
+		test_ServerReqChallenge_4_repeats);
 	return suite;
 }
 
-- 
2.41.0


From 268303632f79d7395b452172c06b25ad68fe35fb Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Fri, 10 Jul 2020 15:09:33 -0700
Subject: [PATCH 026/146] s4: torture: Add smb2.notify.handle-permissions test.

Add knownfail entry.

CVE-2020-14318

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14434

Signed-off-by: Jeremy Allison <jra@samba.org>
(cherry picked from commit f100bd2f2e4f047942002a992c99104227a17f81)
---
 .../smb2_notify_handle_permissions            |  2 +
 source4/torture/smb2/notify.c                 | 80 +++++++++++++++++++
 2 files changed, 82 insertions(+)
 create mode 100644 selftest/knownfail.d/smb2_notify_handle_permissions

diff --git a/selftest/knownfail.d/smb2_notify_handle_permissions b/selftest/knownfail.d/smb2_notify_handle_permissions
new file mode 100644
index 00000000000..c0ec8fc8153
--- /dev/null
+++ b/selftest/knownfail.d/smb2_notify_handle_permissions
@@ -0,0 +1,2 @@
+^samba3.smb2.notify.handle-permissions
+
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index ebb4f8a4f8e..b017491c8fb 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -2569,6 +2569,83 @@ done:
 	return ok;
 }
 
+/*
+  Test asking for a change notify on a handle without permissions.
+*/
+
+#define BASEDIR_HPERM BASEDIR "_HPERM"
+
+static bool torture_smb2_notify_handle_permissions(
+		struct torture_context *torture,
+		struct smb2_tree *tree)
+{
+	bool ret = true;
+	NTSTATUS status;
+	union smb_notify notify;
+	union smb_open io;
+	struct smb2_handle h1 = {{0}};
+	struct smb2_request *req;
+
+	smb2_deltree(tree, BASEDIR_HPERM);
+	smb2_util_rmdir(tree, BASEDIR_HPERM);
+
+	torture_comment(torture,
+		"TESTING CHANGE NOTIFY "
+		"ON A HANDLE WITHOUT PERMISSIONS\n");
+
+	/*
+	  get a handle on the directory
+	*/
+	ZERO_STRUCT(io.smb2);
+	io.generic.level = RAW_OPEN_SMB2;
+	io.smb2.in.create_flags = 0;
+	io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
+	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+				NTCREATEX_SHARE_ACCESS_WRITE;
+	io.smb2.in.alloc_size = 0;
+	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
+	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	io.smb2.in.security_flags = 0;
+	io.smb2.in.fname = BASEDIR_HPERM;
+
+	status = smb2_create(tree, torture, &io.smb2);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	h1 = io.smb2.out.file.handle;
+
+	/* ask for a change notify,
+	   on file or directory name changes */
+	ZERO_STRUCT(notify.smb2);
+	notify.smb2.level = RAW_NOTIFY_SMB2;
+	notify.smb2.in.buffer_size = 1000;
+	notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+	notify.smb2.in.file.handle = h1;
+	notify.smb2.in.recursive = true;
+
+	req = smb2_notify_send(tree, &notify.smb2);
+	torture_assert_goto(torture,
+			req != NULL,
+			ret,
+			done,
+			"smb2_notify_send failed\n");
+
+	/*
+	 * Cancel it, we don't really want to wait.
+	 */
+	smb2_cancel(req);
+	status = smb2_notify_recv(req, torture, &notify.smb2);
+	/* Handle h1 doesn't have permissions for ChangeNotify. */
+	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+
+done:
+	if (!smb2_util_handle_empty(h1)) {
+		smb2_util_close(tree, h1);
+	}
+	smb2_deltree(tree, BASEDIR_HPERM);
+	return ret;
+}
+
 /*
    basic testing of SMB2 change notify
 */
@@ -2602,6 +2679,9 @@ struct torture_suite *torture_smb2_notify_init(TALLOC_CTX *ctx)
 				     torture_smb2_notify_rmdir3);
 	torture_suite_add_2smb2_test(suite, "rmdir4",
 				     torture_smb2_notify_rmdir4);
+	torture_suite_add_1smb2_test(suite,
+				    "handle-permissions",
+				    torture_smb2_notify_handle_permissions);
 
 	suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests");
 
-- 
2.41.0


From 448d4e99f8883a07589264cfca474c3dff8b5942 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 7 Jul 2020 18:25:23 -0700
Subject: [PATCH 027/146] s3: smbd: Ensure change notifies can't get set unless
 the directory handle is open for SEC_DIR_LIST.

Remove knownfail entry.

CVE-2020-14318

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14434

Signed-off-by: Jeremy Allison <jra@samba.org>
(cherry picked from commit f43ecce46a89c6380317fbb5f2ae38f48d3d42c8)
---
 selftest/knownfail.d/smb2_notify_handle_permissions | 2 --
 source3/smbd/notify.c                               | 8 ++++++++
 2 files changed, 8 insertions(+), 2 deletions(-)
 delete mode 100644 selftest/knownfail.d/smb2_notify_handle_permissions

diff --git a/selftest/knownfail.d/smb2_notify_handle_permissions b/selftest/knownfail.d/smb2_notify_handle_permissions
deleted file mode 100644
index c0ec8fc8153..00000000000
--- a/selftest/knownfail.d/smb2_notify_handle_permissions
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba3.smb2.notify.handle-permissions
-
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 44c0b09432e..d23c03bce41 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -283,6 +283,14 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32_t filter,
 	char fullpath[len+1];
 	NTSTATUS status = NT_STATUS_NOT_IMPLEMENTED;
 
+	/*
+	 * Setting a changenotify needs READ/LIST access
+	 * on the directory handle.
+	 */
+	if (!(fsp->access_mask & SEC_DIR_LIST)) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (fsp->notify != NULL) {
 		DEBUG(1, ("change_notify_create: fsp->notify != NULL, "
 			  "fname = %s\n", fsp->fsp_name->base_name));
-- 
2.41.0


From 041c86926999594f13b884522b1d9fcc65f92a52 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Thu, 9 Jul 2020 21:49:25 +0200
Subject: [PATCH 028/146] CVE-2020-14323 winbind: Fix invalid lookupsids DoS

A lookupsids request without extra_data will lead to "state->domain==NULL",
which makes winbindd_lookupsids_recv trying to dereference it.

Reported by Bas Alberts of the GitHub Security Lab Team as GHSL-2020-134

Bug: https://bugzilla.samba.org/show_bug.cgi?id=14436
Signed-off-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit f17967ad73e9c1d2bd6e0b7c181f08079d2a8214)
---
 source3/winbindd/winbindd_lookupsids.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_lookupsids.c b/source3/winbindd/winbindd_lookupsids.c
index d28b5fa9f01..a289fd86f0f 100644
--- a/source3/winbindd/winbindd_lookupsids.c
+++ b/source3/winbindd/winbindd_lookupsids.c
@@ -47,7 +47,7 @@ struct tevent_req *winbindd_lookupsids_send(TALLOC_CTX *mem_ctx,
 	DEBUG(3, ("lookupsids\n"));
 
 	if (request->extra_len == 0) {
-		tevent_req_done(req);
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
 		return tevent_req_post(req, ev);
 	}
 	if (request->extra_data.data[request->extra_len-1] != '\0') {
-- 
2.41.0


From e6e77a3a503f9223ecbc2d32a1d24e20f834659f Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Thu, 9 Jul 2020 21:48:57 +0200
Subject: [PATCH 029/146] CVE-2020-14323 torture4: Add a simple test for
 invalid lookup_sids winbind call

We can't add this test before the fix, add it to knownfail and have the fix
remove the knownfail entry again. As this crashes winbind, many tests after
this one will fail.

Reported by Bas Alberts of the GitHub Security Lab Team as GHSL-2020-134

Bug: https://bugzilla.samba.org/show_bug.cgi?id=14436
Signed-off-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit d0ca2a63aaedf123205337aaa211426175ffcebf)
---
 source4/torture/winbind/struct_based.c | 27 ++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/source4/torture/winbind/struct_based.c b/source4/torture/winbind/struct_based.c
index 9745b621ca9..71f248c0d61 100644
--- a/source4/torture/winbind/struct_based.c
+++ b/source4/torture/winbind/struct_based.c
@@ -1110,6 +1110,29 @@ static bool torture_winbind_struct_lookup_name_sid(struct torture_context *tortu
 	return true;
 }
 
+static bool torture_winbind_struct_lookup_sids_invalid(
+	struct torture_context *torture)
+{
+	struct winbindd_request req = {0};
+	struct winbindd_response rep = {0};
+	bool strict = torture_setting_bool(torture, "strict mode", false);
+	bool ok;
+
+	torture_comment(torture,
+			"Running WINBINDD_LOOKUP_SIDS (struct based)\n");
+
+	ok = true;
+	DO_STRUCT_REQ_REP_EXT(WINBINDD_LOOKUPSIDS, &req, &rep,
+			      NSS_STATUS_NOTFOUND,
+			      strict,
+			      ok=false,
+			      talloc_asprintf(
+				      torture,
+				      "invalid lookupsids succeeded"));
+
+	return ok;
+}
+
 struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx)
 {
 	struct torture_suite *suite = torture_suite_create(ctx, "struct");
@@ -1132,6 +1155,10 @@ struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx)
 	torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent);
 	torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent);
 	torture_suite_add_simple_test(suite, "lookup_name_sid", torture_winbind_struct_lookup_name_sid);
+	torture_suite_add_simple_test(
+		suite,
+		"lookup_sids_invalid",
+		torture_winbind_struct_lookup_sids_invalid);
 
 	suite->description = talloc_strdup(suite, "WINBIND - struct based protocol tests");
 
-- 
2.41.0


From 2b4763940d1826a2b4e5eaa1e2df338004cd9af0 Mon Sep 17 00:00:00 2001
From: Laurent Menase <laurent.menase@hpe.com>
Date: Wed, 20 May 2020 12:31:53 +0200
Subject: [PATCH 030/146] winbind: Fix a memleak

Bug: https://bugzilla.samba.org/show_bug.cgi?id=14388
Signed-off-by: Laurent Menase <laurent.menase@hpe.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Noel Power <noel.power@suse.com>

Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Mon Sep 14 13:33:13 UTC 2020 on sn-devel-184

(cherry picked from commit 8f868b0ea0b4795668f7bc0b028cd85686b249fb)
---
 source3/winbindd/winbindd_ads.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 556b4523866..325ba1abd82 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -405,6 +405,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
 	DBG_NOTICE("ads query_user_list gave %d entries\n", count);
 
 done:
+	ads_msgfree(ads, res);
 	return status;
 }
 
-- 
2.41.0


From accc423a4eb9170ab0dbe4b2ba90ce83790e7a16 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Mon, 17 Aug 2020 13:39:58 +0200
Subject: [PATCH 031/146] s3:tests: Add test for 'valid users = DOMAIN\%U'

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14467

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 53b6dd951249052772e1ffcf651b7efd0963b931)
(cherry picked from commit 20d3cf455c631c6cea6d471333779cc15d0e8d8a)
---
 selftest/knownfail.d/samba3.substiutions   | 1 +
 selftest/target/Samba3.pm                  | 4 ++++
 source3/script/tests/test_substitutions.sh | 5 +++++
 3 files changed, 10 insertions(+)
 create mode 100644 selftest/knownfail.d/samba3.substiutions

diff --git a/selftest/knownfail.d/samba3.substiutions b/selftest/knownfail.d/samba3.substiutions
new file mode 100644
index 00000000000..f116d3b2fcf
--- /dev/null
+++ b/selftest/knownfail.d/samba3.substiutions
@@ -0,0 +1 @@
+^samba3.substitutions.Test.login.to.share.with.substitution.for.valid.users
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 75960dbc790..9e4da0e6a08 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -423,6 +423,10 @@ sub setup_ad_member
 	path = $share_dir/D_%D/u_%u/g_%g
 	writeable = yes
 
+[sub_valid_users]
+	path = $share_dir
+	valid users = ADDOMAIN/%U
+
 ";
 
 	my $ret = $self->provision($prefix, $dcvars->{DOMAIN},
diff --git a/source3/script/tests/test_substitutions.sh b/source3/script/tests/test_substitutions.sh
index 1a46f11c85d..c813a8f9def 100755
--- a/source3/script/tests/test_substitutions.sh
+++ b/source3/script/tests/test_substitutions.sh
@@ -34,4 +34,9 @@ SMB_UNC="//$SERVER/sub_dug2"
 test_smbclient "Test login to share with substitution (Dug)" \
 	"ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1)
 
+SMB_UNC="//$SERVER/sub_valid_users"
+
+test_smbclient "Test login to share with substitution for valid users" \
+	"ls" "$SMB_UNC" "-U$USERNAME%$PASSWORD" || failed=$(expr $failed + 1)
+
 exit $failed
-- 
2.41.0


From 1c594e3734e3ffd2dfc615897ac95792878f2df4 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Mon, 17 Aug 2020 14:12:48 +0200
Subject: [PATCH 032/146] s3:smbd: Fix %U substitutions if it contains a domain
 name

'valid users = DOMAIN\%U' worked with Samba 3.6 and broke in a newer
version.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14467

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 5de7c91e6d4e98f438157a7675c8582cabdd828d)
(cherry picked from commit 60ddb7b20071b00f0cd7f1cb818022220eb0c279)
---
 selftest/knownfail.d/samba3.substiutions |  1 -
 source3/smbd/share_access.c              | 18 +++++++++++++++++-
 2 files changed, 17 insertions(+), 2 deletions(-)
 delete mode 100644 selftest/knownfail.d/samba3.substiutions

diff --git a/selftest/knownfail.d/samba3.substiutions b/selftest/knownfail.d/samba3.substiutions
deleted file mode 100644
index f116d3b2fcf..00000000000
--- a/selftest/knownfail.d/samba3.substiutions
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.substitutions.Test.login.to.share.with.substitution.for.valid.users
diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c
index 3cbf7f318a2..0705e197975 100644
--- a/source3/smbd/share_access.c
+++ b/source3/smbd/share_access.c
@@ -79,7 +79,23 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
 	enum lsa_SidType type;
 
 	if (username != NULL) {
-		name = talloc_sub_basic(mem_ctx, username, domain, name);
+		size_t domain_len = strlen(domain);
+
+		/* Check if username starts with domain name */
+		if (domain_len > 0) {
+			const char *sep = lp_winbind_separator();
+			int cmp = strncasecmp_m(username, domain, domain_len);
+			if (cmp == 0 && sep[0] == username[domain_len]) {
+				/* Move after the winbind separator */
+				domain_len += 1;
+			} else {
+				domain_len = 0;
+			}
+		}
+		name = talloc_sub_basic(mem_ctx,
+					username + domain_len,
+					domain,
+					name);
 	}
 	if (sharename != NULL) {
 		name = talloc_string_sub(mem_ctx, name, "%S", sharename);
-- 
2.41.0


From d93ddae23e1b378f771134e93d1b15e61e2278af Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Thu, 9 Jul 2020 11:48:26 +0200
Subject: [PATCH 033/146] docs: Fix documentation for require_membership_of of
 pam_winbind

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14358

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
(cherry picked from commit 4c74db6978c682f8ba4e74a6ee8157cfcbb54971)
---
 docs-xml/manpages/pam_winbind.8.xml | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/pam_winbind.8.xml b/docs-xml/manpages/pam_winbind.8.xml
index a9a227f1647..a61fb2d58e5 100644
--- a/docs-xml/manpages/pam_winbind.8.xml
+++ b/docs-xml/manpages/pam_winbind.8.xml
@@ -84,9 +84,11 @@
 		If this option is set, pam_winbind will only succeed if the user is a member of the given SID or NAME. A SID
 		can be either a group-SID, an alias-SID or even an user-SID. It is also possible to give a NAME instead of the
 		SID. That name must have the form: <parameter>MYDOMAIN\mygroup</parameter> or
-		<parameter>MYDOMAIN\myuser</parameter>.  pam_winbind will, in that case, lookup the SID internally. Note that
-		NAME may not contain any spaces. It is thus recommended to only use SIDs. You can verify the list of SIDs a
-		user is a member of with <command>wbinfo --user-sids=SID</command>.
+		<parameter>MYDOMAIN\myuser</parameter> (where '\' character corresponds to the value of
+		<parameter>winbind separator</parameter> parameter). It is also possible to use a UPN in the form
+		<parameter>user@REALM</parameter> or <parameter>group@REALM</parameter>. pam_winbind will, in that case, lookup
+		the SID internally. Note that NAME may not contain any spaces. It is thus recommended to only use SIDs. You can
+		verify the list of SIDs a user is a member of with <command>wbinfo --user-sids=SID</command>.
 		</para>
 
 		<para>
-- 
2.41.0


From c9aea952eb3f8d83701abd6db4d48c8d93a8517a Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Fri, 17 Jul 2020 12:14:16 +0200
Subject: [PATCH 034/146] docs: Fix documentation for require_membership_of of
 pam_winbind.conf

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14358

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Isaac Boukris <iboukris@samba.org>
(cherry picked from commit 71b7140fd0a33e7e8c5bf37c2897cea8224b3f01)
---
 docs-xml/manpages/pam_winbind.conf.5.xml | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/pam_winbind.conf.5.xml b/docs-xml/manpages/pam_winbind.conf.5.xml
index fcac1ee7036..d81a0bd6eba 100644
--- a/docs-xml/manpages/pam_winbind.conf.5.xml
+++ b/docs-xml/manpages/pam_winbind.conf.5.xml
@@ -69,9 +69,12 @@
 		If this option is set, pam_winbind will only succeed if the user is a member of the given SID or NAME. A SID
 		can be either a group-SID, an alias-SID or even an user-SID. It is also possible to give a NAME instead of the
 		SID. That name must have the form: <parameter>MYDOMAIN\mygroup</parameter> or
-		<parameter>MYDOMAIN\myuser</parameter>.  pam_winbind will, in that case, lookup the SID internally. Note that
-		NAME may not contain any spaces. It is thus recommended to only use SIDs. You can verify the list of SIDs a
-		user is a member of with <command>wbinfo --user-sids=SID</command>. This setting is empty by default.
+		<parameter>MYDOMAIN\myuser</parameter> (where '\' character corresponds to the value of
+		<parameter>winbind separator</parameter> parameter). It is also possible to use a UPN in the form
+		<parameter>user@REALM</parameter> or <parameter>group@REALM</parameter>. pam_winbind will, in that case, lookup
+		the SID internally. Note that NAME may not contain any spaces. It is thus recommended to only use SIDs. You can
+		verify the list of SIDs a user is a member of with <command>wbinfo --user-sids=SID</command>.
+		This setting is empty by default.
 		</para>
 		<para>This option only operates during password authentication, and will not restrict access if a password is not required for any reason (such as SSH key-based login).</para>
 		</listitem>
-- 
2.41.0


From b04be6ffd3a1c9eda1f1dc78d60ad7b3a9b7471d Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Thu, 11 Jun 2020 21:05:07 +0300
Subject: [PATCH 035/146] Fix a typo in recent net man page changes

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 4e51e832176a99f2a841c7a0d78fb0424f02956e)
---
 docs-xml/manpages/net.8.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 69e18df8b6c..9b1d4458acc 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -470,7 +470,7 @@ joining the domain.
 </para>
 
 <para>
-[FQDN] (ADS only) set the dnsHosName attribute during the join.
+[FQDN] (ADS only) set the dnsHostName attribute during the join.
 The default format is netbiosname.dnsdomain.
 </para>
 
-- 
2.41.0


From a5a7dac759c2570861732c68efefb62371a29565 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Tue, 16 Jun 2020 22:01:49 +0300
Subject: [PATCH 036/146] selftest: add tests for binary
 msDS-AdditionalDnsHostName

Like the short names added implicitly by Windows DC.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 4605d7aec5caf494a23f2c9800d6689f710ffbce)
---
 selftest/knownfail.d/binary_addl_hostname |  3 +++
 testprogs/blackbox/test_net_ads.sh        | 22 ++++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 selftest/knownfail.d/binary_addl_hostname

diff --git a/selftest/knownfail.d/binary_addl_hostname b/selftest/knownfail.d/binary_addl_hostname
new file mode 100644
index 00000000000..559db1df507
--- /dev/null
+++ b/selftest/knownfail.d/binary_addl_hostname
@@ -0,0 +1,3 @@
+^samba4.blackbox.net_ads.dns alias1 check keytab
+^samba4.blackbox.net_ads.dns alias2 check keytab
+^samba4.blackbox.net_ads.addl short check keytab
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 85257f445d8..eef4a31a6a7 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -41,6 +41,11 @@ if [ -x "$BINDIR/ldbdel" ]; then
 	ldbdel="$BINDIR/ldbdel"
 fi
 
+ldbmodify="ldbmodify"
+if [ -x "$BINDIR/ldbmodify" ]; then
+	ldbmodify="$BINDIR/ldbmodify"
+fi
+
 # Load test functions
 . `dirname $0`/subunit.sh
 
@@ -217,12 +222,29 @@ testit_grep "dns alias SPN" $dns_alias2 $VALGRIND $net_tool ads search -P samacc
 testit_grep "dns alias addl" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 
+# Test binary msDS-AdditionalDnsHostName like ones added by Windows DC
+short_alias_file="$PREFIX_ABS/short_alias_file"
+printf 'short_alias\0$' > $short_alias_file
+cat > $PREFIX_ABS/tmpldbmodify <<EOF
+dn: CN=$HOSTNAME,$computers_dn
+changetype: modify
+add: msDS-AdditionalDnsHostName
+msDS-AdditionalDnsHostName:< file://$short_alias_file
+EOF
+
+testit "add binary msDS-AdditionalDnsHostName" $VALGRIND $ldbmodify -k yes -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM $PREFIX_ABS/tmpldbmodify || failed=`expr $failed + 1`
+
+testit_grep "addl short alias" short_alias $ldbsearch --show-binary -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "CN=$HOSTNAME,CN=Computers,$base_dn" msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
+
+rm -f $PREFIX_ABS/tmpldbmodify $short_alias_file
+
 dedicated_keytab_file="$PREFIX_ABS/test_dns_aliases_dedicated_krb5.keytab"
 
 testit "dns alias create_keytab" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 
 testit_grep "dns alias1 check keytab" "host/${dns_alias1}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 testit_grep "dns alias2 check keytab" "host/${dns_alias2}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+testit_grep "addl short check keytab" "host/short_alias@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 
 rm -f $dedicated_keytab_file
 
-- 
2.41.0


From 2769976aaa13474d2b5ee7b58ee17d5824dfa5a2 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Thu, 11 Jun 2020 16:51:27 +0300
Subject: [PATCH 037/146] Properly handle msDS-AdditionalDnsHostName returned
 from Windows DC

Windows DC adds short names for each specified msDS-AdditionalDnsHostName
attribute, but these have a suffix of "\0$" and thus fail with
ldap_get_values(), use ldap_get_values_len() instead.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Isaac Boukris <iboukris@samba.org>
Autobuild-Date(master): Thu Jun 18 16:43:47 UTC 2020 on sn-devel-184

(cherry picked from commit 9a447fb7e0701bf8b2fd922aed44d89f40420251)
---
 selftest/knownfail.d/binary_addl_hostname |  3 --
 source3/libads/ldap.c                     | 38 +++++++++++++++++++++--
 2 files changed, 35 insertions(+), 6 deletions(-)
 delete mode 100644 selftest/knownfail.d/binary_addl_hostname

diff --git a/selftest/knownfail.d/binary_addl_hostname b/selftest/knownfail.d/binary_addl_hostname
deleted file mode 100644
index 559db1df507..00000000000
--- a/selftest/knownfail.d/binary_addl_hostname
+++ /dev/null
@@ -1,3 +0,0 @@
-^samba4.blackbox.net_ads.dns alias1 check keytab
-^samba4.blackbox.net_ads.dns alias2 check keytab
-^samba4.blackbox.net_ads.addl short check keytab
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 02a628ee0e6..2684bba63ec 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -3664,6 +3664,40 @@ out:
 /********************************************************************
 ********************************************************************/
 
+static char **get_addl_hosts(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+			      LDAPMessage *msg, size_t *num_values)
+{
+	const char *field = "msDS-AdditionalDnsHostName";
+	struct berval **values = NULL;
+	char **ret = NULL;
+	size_t i, converted_size;
+
+	values = ldap_get_values_len(ads->ldap.ld, msg, field);
+	if (values == NULL) {
+		return NULL;
+	}
+
+	*num_values = ldap_count_values_len(values);
+
+	ret = talloc_array(mem_ctx, char *, *num_values + 1);
+	if (ret == NULL) {
+		ldap_value_free_len(values);
+		return NULL;
+	}
+
+	for (i = 0; i < *num_values; i++) {
+		if (!pull_utf8_talloc(mem_ctx, &ret[i], values[i]->bv_val,
+				      &converted_size)) {
+			ldap_value_free_len(values);
+			return NULL;
+		}
+	}
+	ret[i] = NULL;
+
+	ldap_value_free_len(values);
+	return ret;
+}
+
 ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
 					    ADS_STRUCT *ads,
 					    const char *machine_name,
@@ -3689,9 +3723,7 @@ ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-	*hostnames_array = ads_pull_strings(ads, mem_ctx, res,
-					    "msDS-AdditionalDnsHostName",
-					    num_hostnames);
+	*hostnames_array = get_addl_hosts(ads, mem_ctx, res, num_hostnames);
 	if (*hostnames_array == NULL) {
 		DEBUG(1, ("Host account for %s does not have msDS-AdditionalDnsHostName.\n",
 			  machine_name));
-- 
2.41.0


From 9727953d482a3849d4ac1f40486bc567f6b77067 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Sat, 20 Jun 2020 17:17:33 +0200
Subject: [PATCH 038/146] Fix usage of ldap_get_values_len for
 msDS-AdditionalDnsHostName

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Mon Jun 22 09:59:04 UTC 2020 on sn-devel-184

(cherry picked from commit f9dd67355ba35539d7ae1774d5135fd05d747b3f)
---
 source3/libads/ldap.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 2684bba63ec..d1ce9cee2f0 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -3686,8 +3686,12 @@ static char **get_addl_hosts(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
 	}
 
 	for (i = 0; i < *num_values; i++) {
-		if (!pull_utf8_talloc(mem_ctx, &ret[i], values[i]->bv_val,
-				      &converted_size)) {
+		ret[i] = NULL;
+		if (!convert_string_talloc(mem_ctx, CH_UTF8, CH_UNIX,
+					   values[i]->bv_val,
+					   strnlen(values[i]->bv_val,
+						   values[i]->bv_len),
+					   &ret[i], &converted_size)) {
 			ldap_value_free_len(values);
 			return NULL;
 		}
-- 
2.41.0


From ec4cfe786d8c3cb67bb0e9224ae1822902c672d3 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Tue, 15 Dec 2020 15:17:04 +0100
Subject: [PATCH 039/146] HACK:s3:winbind: Rely on the domain child for online
 check

---
 source3/winbindd/winbindd_cm.c   | 9 +++++++++
 source3/winbindd/winbindd_dual.c | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 4bd03ed8b7a..502331f7260 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -89,6 +89,8 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+extern bool wb_idmap_child;
+
 struct dc_name_ip {
 	fstring name;
 	struct sockaddr_storage ss;
@@ -176,6 +178,13 @@ static void msg_try_to_go_online(struct messaging_context *msg,
 				continue;
 			}
 
+			if (wb_child_domain() == NULL && !wb_idmap_child) {
+				DEBUG(5,("msg_try_to_go_online: domain %s "
+					"NOT CONNECTING IN MAIN PROCESS.\n", domainname));
+				domain->online = true;
+				continue;
+			}
+
 			/* This call takes care of setting the online
 			   flag to true if we connected, or re-adding
 			   the offline handler if false. Bypasses online
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 6e3277e5529..35b76a367aa 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -1612,6 +1612,8 @@ static void child_handler(struct tevent_context *ev, struct tevent_fd *fde,
 	}
 }
 
+bool wb_idmap_child;
+
 static bool fork_domain_child(struct winbindd_child *child)
 {
 	int fdpair[2];
@@ -1715,6 +1717,7 @@ static bool fork_domain_child(struct winbindd_child *child)
 		setproctitle("domain child [%s]", child_domain->name);
 	} else if (child == idmap_child()) {
 		setproctitle("idmap child");
+		wb_idmap_child = true;
 	}
 
 	/* Handle online/offline messages. */
-- 
2.41.0


From 958bed1a1e5c9f334a1859bef14f4fe1657c3e49 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 9 Sep 2020 16:00:52 +0200
Subject: [PATCH 040/146] s3:smbd: Use fsp al the talloc memory context

Somehow the lck pointer gets freed before we call TALLOC_FREE().

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
---
 source3/smbd/open.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index de557f53a20..9a24e331ab1 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -4239,7 +4239,7 @@ static NTSTATUS open_directory(connection_struct *conn,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	lck = get_share_mode_lock(talloc_tos(), fsp->file_id,
+	lck = get_share_mode_lock(fsp, fsp->file_id,
 				  conn->connectpath, smb_dname,
 				  &mtimespec);
 
-- 
2.41.0


From 2591ae5d6a1dbd71391801b7bdf20bd37c8e8375 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 3 Feb 2021 12:58:31 +0100
Subject: [PATCH 041/146] Revert "s3:smbd: Use fsp al the talloc memory
 context"

This reverts commit 958bed1a1e5c9f334a1859bef14f4fe1657c3e49.
---
 source3/smbd/open.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 9a24e331ab1..de557f53a20 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -4239,7 +4239,7 @@ static NTSTATUS open_directory(connection_struct *conn,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	lck = get_share_mode_lock(fsp, fsp->file_id,
+	lck = get_share_mode_lock(talloc_tos(), fsp->file_id,
 				  conn->connectpath, smb_dname,
 				  &mtimespec);
 
-- 
2.41.0


From 2438619ec7ef18816f6b92c87a094851223d2bb1 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Wed, 22 Jul 2020 22:42:09 -0700
Subject: [PATCH 042/146] nsswitch/nsstest.c: Avoid nss function conflicts with
 glibc nss.h

glibc 2.32 will define these varibles [1] which results in conflicts
with these static function names, therefore prefix these function names
with samba_ to avoid it

[1] https://sourceware.org/git/?p=glibc.git;a=commit;h=499a92df8b9fc64a054cf3b7f728f8967fc1da7d

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Noel Power <npower@samba.org>

Autobuild-User(master): Noel Power <npower@samba.org>
Autobuild-Date(master): Tue Jul 28 10:52:00 UTC 2020 on sn-devel-184

(cherry picked from commit 6e496aa3635557b59792e469f7c7f8eccd822322)
---
 nsswitch/nsstest.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c
index 6d92806cffc..46f96795f39 100644
--- a/nsswitch/nsstest.c
+++ b/nsswitch/nsstest.c
@@ -137,7 +137,7 @@ static struct passwd *nss_getpwuid(uid_t uid)
 	return &pwd;
 }
 
-static void nss_setpwent(void)
+static void samba_nss_setpwent(void)
 {
 	NSS_STATUS (*_nss_setpwent)(void) =
 		(NSS_STATUS(*)(void))find_fn("setpwent");
@@ -152,7 +152,7 @@ static void nss_setpwent(void)
 	}
 }
 
-static void nss_endpwent(void)
+static void samba_nss_endpwent(void)
 {
 	NSS_STATUS (*_nss_endpwent)(void) =
 		(NSS_STATUS (*)(void))find_fn("endpwent");
@@ -284,7 +284,7 @@ again:
 	return &grp;
 }
 
-static void nss_setgrent(void)
+static void samba_nss_setgrent(void)
 {
 	NSS_STATUS (*_nss_setgrent)(void) =
 		(NSS_STATUS (*)(void))find_fn("setgrent");
@@ -299,7 +299,7 @@ static void nss_setgrent(void)
 	}
 }
 
-static void nss_endgrent(void)
+static void samba_nss_endgrent(void)
 {
 	NSS_STATUS (*_nss_endgrent)(void) =
 		(NSS_STATUS (*)(void))find_fn("endgrent");
@@ -396,7 +396,7 @@ static void nss_test_users(void)
 {
 	struct passwd *pwd;
 
-	nss_setpwent();
+	samba_nss_setpwent();
 	/* loop over all users */
 	while ((pwd = nss_getpwent())) {
 		printf("Testing user %s\n", pwd->pw_name);
@@ -418,14 +418,14 @@ static void nss_test_users(void)
 		printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid);
 		printf("\n");
 	}
-	nss_endpwent();
+	samba_nss_endpwent();
 }
 
 static void nss_test_groups(void)
 {
 	struct group *grp;
 
-	nss_setgrent();
+	samba_nss_setgrent();
 	/* loop over all groups */
 	while ((grp = nss_getgrent())) {
 		printf("Testing group %s\n", grp->gr_name);
@@ -446,7 +446,7 @@ static void nss_test_groups(void)
 		printf("getgrgid: "); print_group(grp);
 		printf("\n");
 	}
-	nss_endgrent();
+	samba_nss_endgrent();
 }
 
 static void nss_test_errors(void)
-- 
2.41.0


From d5410b038bb3b1d31783c0d825dc933497f6eeaa Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 3 Feb 2021 10:30:08 +0100
Subject: [PATCH 043/146] lib:util: Add basic memcache unit test

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14625

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit bebbf621d6052f797c5cf19a2a9bbc13e699d3f0)
---
 lib/util/tests/test_memcache.c | 122 +++++++++++++++++++++++++++++++++
 lib/util/wscript_build         |   6 ++
 selftest/tests.py              |   2 +
 3 files changed, 130 insertions(+)
 create mode 100644 lib/util/tests/test_memcache.c

diff --git a/lib/util/tests/test_memcache.c b/lib/util/tests/test_memcache.c
new file mode 100644
index 00000000000..8ea5e5b042e
--- /dev/null
+++ b/lib/util/tests/test_memcache.c
@@ -0,0 +1,122 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) 2021      Andreas Schneider <asn@samba.org>
+ *
+ * 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 <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "lib/replace/replace.h"
+#include "lib/util/talloc_stack.h"
+#include "lib/util/memcache.h"
+
+static int setup_talloc_context(void **state)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	*state = frame;
+	return 0;
+}
+
+static int teardown_talloc_context(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	TALLOC_FREE(frame);
+	return 0;
+}
+
+static void torture_memcache_init(void **state)
+{
+	TALLOC_CTX *mem_ctx = *state;
+	struct memcache *cache = NULL;
+
+	cache = memcache_init(mem_ctx, 0);
+	assert_non_null(cache);
+
+	TALLOC_FREE(cache);
+
+	cache = memcache_init(mem_ctx, 10);
+	assert_non_null(cache);
+
+	TALLOC_FREE(cache);
+}
+
+static void torture_memcache_add_lookup_delete(void **state)
+{
+	TALLOC_CTX *mem_ctx = *state;
+	struct memcache *cache = NULL;
+	DATA_BLOB key1, key2;
+	char *path1 = NULL, *path2 = NULL;
+
+	cache = memcache_init(mem_ctx, 0);
+	assert_non_null(cache);
+
+	key1 = data_blob_const("key1", 4);
+	path1 = talloc_strdup(mem_ctx, "/tmp/one");
+	assert_non_null(path1);
+
+	key2 = data_blob_const("key2", 4);
+	path2 = talloc_strdup(mem_ctx, "/tmp/two");
+	assert_non_null(path1);
+
+	memcache_add_talloc(cache, GETWD_CACHE, key1, &path1);
+	assert_null(path1);
+
+	memcache_add_talloc(cache, GETWD_CACHE, key2, &path2);
+	assert_null(path2);
+
+	path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1);
+	assert_non_null(path1);
+	assert_string_equal(path1, "/tmp/one");
+
+	path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2);
+	assert_non_null(path2);
+	assert_string_equal(path2, "/tmp/two");
+
+	memcache_delete(cache, GETWD_CACHE, key1);
+	path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1);
+	assert_null(path1);
+
+	memcache_flush(cache, GETWD_CACHE);
+	path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2);
+	assert_null(path2);
+
+	TALLOC_FREE(cache);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(torture_memcache_init),
+		cmocka_unit_test(torture_memcache_add_lookup_delete),
+	};
+
+	if (argc == 2) {
+		cmocka_set_test_filter(argv[1]);
+	}
+	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+
+	rc = cmocka_run_group_tests(tests,
+				    setup_talloc_context,
+				    teardown_talloc_context);
+
+	return rc;
+}
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index fd3027eff77..229dbd5ef6a 100644
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -256,3 +256,9 @@ else:
                      deps='cmocka replace talloc samba-util',
                      local_include=False,
                      install=False)
+
+    bld.SAMBA_BINARY('test_memcache',
+                     source='tests/test_memcache.c',
+                     deps='cmocka replace talloc samba-util',
+                     local_include=False,
+                     install=False)
diff --git a/selftest/tests.py b/selftest/tests.py
index e7639c4da27..e3f7d9acb4a 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -254,6 +254,8 @@ plantestsuite("samba.unittests.ms_fnmatch", "none",
               [os.path.join(bindir(), "default/lib/util/test_ms_fnmatch")])
 plantestsuite("samba.unittests.util_paths", "none",
               [os.path.join(bindir(), "default/lib/util/test_util_paths")])
+plantestsuite("samba.unittests.memcache", "none",
+              [os.path.join(bindir(), "default/lib/util/test_memcache")])
 plantestsuite("samba.unittests.ntlm_check", "none",
               [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")])
 plantestsuite("samba.unittests.test_registry_regfio", "none",
-- 
2.41.0


From 7f6661b3c60319073d7fd58906b9a3728f421fed Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 3 Feb 2021 10:37:12 +0100
Subject: [PATCH 044/146] lib:util: Add cache oversize test for memcache

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14625

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 00543ab3b29e3fbfe8314e51919629803e14ede6)
---
 lib/util/tests/test_memcache.c | 39 ++++++++++++++++++++++++++++++++++
 selftest/knownfail.d/memcache  |  1 +
 2 files changed, 40 insertions(+)
 create mode 100644 selftest/knownfail.d/memcache

diff --git a/lib/util/tests/test_memcache.c b/lib/util/tests/test_memcache.c
index 8ea5e5b042e..8a3997817c1 100644
--- a/lib/util/tests/test_memcache.c
+++ b/lib/util/tests/test_memcache.c
@@ -98,6 +98,44 @@ static void torture_memcache_add_lookup_delete(void **state)
 	path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2);
 	assert_null(path2);
 
+	TALLOC_FREE(path1);
+	TALLOC_FREE(path2);
+	TALLOC_FREE(cache);
+}
+
+static void torture_memcache_add_oversize(void **state)
+{
+	TALLOC_CTX *mem_ctx = *state;
+	struct memcache *cache = NULL;
+	DATA_BLOB key1, key2;
+	char *path1 = NULL, *path2 = NULL;
+
+	cache = memcache_init(mem_ctx, 10);
+	assert_non_null(cache);
+
+	key1 = data_blob_const("key1", 4);
+	path1 = talloc_strdup(mem_ctx, "/tmp/one");
+	assert_non_null(path1);
+
+	key2 = data_blob_const("key2", 4);
+	path2 = talloc_strdup(mem_ctx, "/tmp/two");
+	assert_non_null(path1);
+
+	memcache_add_talloc(cache, GETWD_CACHE, key1, &path1);
+	assert_null(path1);
+
+	memcache_add_talloc(cache, GETWD_CACHE, key2, &path2);
+	assert_null(path2);
+
+	path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1);
+	assert_null(path1);
+
+	path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2);
+	assert_non_null(path2);
+	assert_string_equal(path2, "/tmp/two");
+
+	TALLOC_FREE(path1);
+	TALLOC_FREE(path2);
 	TALLOC_FREE(cache);
 }
 
@@ -107,6 +145,7 @@ int main(int argc, char *argv[])
 	const struct CMUnitTest tests[] = {
 		cmocka_unit_test(torture_memcache_init),
 		cmocka_unit_test(torture_memcache_add_lookup_delete),
+		cmocka_unit_test(torture_memcache_add_oversize),
 	};
 
 	if (argc == 2) {
diff --git a/selftest/knownfail.d/memcache b/selftest/knownfail.d/memcache
new file mode 100644
index 00000000000..0a74ace3003
--- /dev/null
+++ b/selftest/knownfail.d/memcache
@@ -0,0 +1 @@
+^samba.unittests.memcache.torture_memcache_add_oversize
-- 
2.41.0


From 53c7f00510556aea15b640254934e514c1d88c25 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Tue, 2 Feb 2021 18:10:38 +0100
Subject: [PATCH 045/146] lib:util: Avoid free'ing our own pointer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14625

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Wed Feb  3 10:57:01 UTC 2021 on sn-devel-184

(cherry picked from commit 0bdbe50fac680be3fe21043246b8c75005611351)
---
 lib/util/memcache.c           | 19 +++++++++++++++----
 selftest/knownfail.d/memcache |  1 -
 2 files changed, 15 insertions(+), 5 deletions(-)
 delete mode 100644 selftest/knownfail.d/memcache

diff --git a/lib/util/memcache.c b/lib/util/memcache.c
index 1e616bd0e9a..7b0b27eaddb 100644
--- a/lib/util/memcache.c
+++ b/lib/util/memcache.c
@@ -223,14 +223,25 @@ static void memcache_delete_element(struct memcache *cache,
 	TALLOC_FREE(e);
 }
 
-static void memcache_trim(struct memcache *cache)
+static void memcache_trim(struct memcache *cache, struct memcache_element *e)
 {
+	struct memcache_element *tail = NULL;
+
 	if (cache->max_size == 0) {
 		return;
 	}
 
-	while ((cache->size > cache->max_size) && DLIST_TAIL(cache->mru)) {
-		memcache_delete_element(cache, DLIST_TAIL(cache->mru));
+	for (tail = DLIST_TAIL(cache->mru);
+	     (cache->size > cache->max_size) && (tail != NULL);
+	     tail = DLIST_TAIL(cache->mru))
+	{
+		if (tail == e) {
+			tail = DLIST_PREV(tail);
+			if (tail == NULL) {
+				break;
+			}
+		}
+		memcache_delete_element(cache, tail);
 	}
 }
 
@@ -351,7 +362,7 @@ void memcache_add(struct memcache *cache, enum memcache_number n,
 		memcpy(&mtv, cache_value.data, sizeof(mtv));
 		cache->size += mtv.len;
 	}
-	memcache_trim(cache);
+	memcache_trim(cache, e);
 }
 
 void memcache_add_talloc(struct memcache *cache, enum memcache_number n,
diff --git a/selftest/knownfail.d/memcache b/selftest/knownfail.d/memcache
deleted file mode 100644
index 0a74ace3003..00000000000
--- a/selftest/knownfail.d/memcache
+++ /dev/null
@@ -1 +0,0 @@
-^samba.unittests.memcache.torture_memcache_add_oversize
-- 
2.41.0


From 138662453fb421609b4fa30487a53a50c085895f Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Thu, 5 Nov 2020 15:48:08 -0800
Subject: [PATCH 046/146] s3: spoolss: Make parameters in call to
 user_ok_token() match all other uses.

We already have p->session_info->unix_info->unix_name, we don't
need to go through a legacy call to uidtoname(p->session_info->unix_token->uid).

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14568

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Mon Nov  9 04:10:45 UTC 2020 on sn-devel-184

(cherry picked from commit e5e1759057a767f517bf480a2172a36623df2799)
---
 source3/rpc_server/spoolss/srv_spoolss_nt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index f32b465afb6..c0f1803c2fa 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -1869,7 +1869,8 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 			return WERR_ACCESS_DENIED;
 		}
 
-		if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
+		if (!user_ok_token(p->session_info->unix_info->unix_name,
+				   p->session_info->info->domain_name,
 				   p->session_info->security_token, snum) ||
 		    !W_ERROR_IS_OK(print_access_check(p->session_info,
 						      p->msg_ctx,
-- 
2.41.0


From 9550eb620ff23fb9f9414c9de596789aae64aef1 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Wed, 11 Nov 2020 13:42:06 +0100
Subject: [PATCH 047/146] s3:smbd: Fix possible null pointer dereference in
 token_contains_name()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14572

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>

Autobuild-User(master): Alexander Bokovoy <ab@samba.org>
Autobuild-Date(master): Thu Nov 12 15:13:47 UTC 2020 on sn-devel-184

(cherry picked from commit 8036bf9717f83e83c3e4a9cf00fded42e9a5de15)
---
 source3/smbd/share_access.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c
index 0705e197975..64276c79fbe 100644
--- a/source3/smbd/share_access.c
+++ b/source3/smbd/share_access.c
@@ -79,7 +79,7 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
 	enum lsa_SidType type;
 
 	if (username != NULL) {
-		size_t domain_len = strlen(domain);
+		size_t domain_len = domain != NULL ? strlen(domain) : 0;
 
 		/* Check if username starts with domain name */
 		if (domain_len > 0) {
-- 
2.41.0


From 49a19805c6837df04dce449841d011fc67e0a7df Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Sat, 20 Feb 2021 15:50:12 +0100
Subject: [PATCH 048/146] passdb: Simplify sids_to_unixids()

Best reviewed with "git show -b", there's a "continue" statement that
changes subsequent indentation.

Decouple lookup status of ids from ID_TYPE_NOT_SPECIFIED

Bug: https://bugzilla.samba.org/show_bug.cgi?id=14571

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
---
 source3/passdb/lookup_sid.c | 123 +++++++++++++++++++++++++++++-------
 1 file changed, 101 insertions(+), 22 deletions(-)

diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 1bb15ccb8b4..186ba17fda6 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -29,6 +29,7 @@
 #include "../libcli/security/security.h"
 #include "lib/winbind_util.h"
 #include "../librpc/gen_ndr/idmap.h"
+#include "lib/util/bitmap.h"
 
 static bool lookup_unix_user_name(const char *name, struct dom_sid *sid)
 {
@@ -1247,7 +1248,9 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
 {
 	struct wbcDomainSid *wbc_sids = NULL;
 	struct wbcUnixId *wbc_ids = NULL;
+	struct bitmap *found = NULL;
 	uint32_t i, num_not_cached;
+	uint32_t wbc_ids_size = 0;
 	wbcErr err;
 	bool ret = false;
 
@@ -1255,6 +1258,20 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
 	if (wbc_sids == NULL) {
 		return false;
 	}
+	found = bitmap_talloc(wbc_sids, num_sids);
+	if (found == NULL) {
+		goto fail;
+	}
+
+	/*
+	 * We go through the requested SID array three times.
+	 * First time to look for global_sid_Unix_Users
+	 * and global_sid_Unix_Groups SIDS, and to look
+	 * for mappings cached in the idmap_cache.
+	 *
+	 * Use bitmap_set() to mark an ids[] array entry as
+	 * being mapped.
+	 */
 
 	num_not_cached = 0;
 
@@ -1266,17 +1283,20 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
 				       &sids[i], &rid)) {
 			ids[i].type = ID_TYPE_UID;
 			ids[i].id = rid;
+			bitmap_set(found, i);
 			continue;
 		}
 		if (sid_peek_check_rid(&global_sid_Unix_Groups,
 				       &sids[i], &rid)) {
 			ids[i].type = ID_TYPE_GID;
 			ids[i].id = rid;
+			bitmap_set(found, i);
 			continue;
 		}
 		if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
 		    && !expired)
 		{
+			bitmap_set(found, i);
 			continue;
 		}
 		ids[i].type = ID_TYPE_NOT_SPECIFIED;
@@ -1287,62 +1307,121 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
 	if (num_not_cached == 0) {
 		goto done;
 	}
-	wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
+
+	/*
+	 * For the ones that we couldn't map in the loop above, query winbindd
+	 * via wbcSidsToUnixIds().
+	 */
+
+	wbc_ids_size = num_not_cached;
+	wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, wbc_ids_size);
 	if (wbc_ids == NULL) {
 		goto fail;
 	}
-	for (i=0; i<num_not_cached; i++) {
+	for (i=0; i<wbc_ids_size; i++) {
 		wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
+		wbc_ids[i].id.gid = (uint32_t)-1;
 	}
-	err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
+	err = wbcSidsToUnixIds(wbc_sids, wbc_ids_size, wbc_ids);
 	if (!WBC_ERROR_IS_OK(err)) {
 		DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
 			   wbcErrorString(err)));
 	}
 
+	/*
+	 * Second time through the SID array, replace
+	 * the ids[] entries that wbcSidsToUnixIds() was able to
+	 * map.
+	 *
+	 * Use bitmap_set() to mark an ids[] array entry as
+	 * being mapped.
+	 */
+
 	num_not_cached = 0;
 
 	for (i=0; i<num_sids; i++) {
-		if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
-			switch (wbc_ids[num_not_cached].type) {
-			case WBC_ID_TYPE_UID:
-				ids[i].type = ID_TYPE_UID;
-				ids[i].id = wbc_ids[num_not_cached].id.uid;
-				break;
-			case WBC_ID_TYPE_GID:
-				ids[i].type = ID_TYPE_GID;
-				ids[i].id = wbc_ids[num_not_cached].id.gid;
-				break;
-			default:
-				/* The types match, and wbcUnixId -> id is a union anyway */
-				ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
-				ids[i].id = wbc_ids[num_not_cached].id.gid;
-				break;
-			}
-			num_not_cached += 1;
+		if (bitmap_query(found, i)) {
+			continue;
 		}
+
+		SMB_ASSERT(num_not_cached < wbc_ids_size);
+
+		switch (wbc_ids[num_not_cached].type) {
+		case WBC_ID_TYPE_UID:
+			ids[i].type = ID_TYPE_UID;
+			ids[i].id = wbc_ids[num_not_cached].id.uid;
+			bitmap_set(found, i);
+			break;
+		case WBC_ID_TYPE_GID:
+			ids[i].type = ID_TYPE_GID;
+			ids[i].id = wbc_ids[num_not_cached].id.gid;
+			bitmap_set(found, i);
+			break;
+		case WBC_ID_TYPE_BOTH:
+			ids[i].type = ID_TYPE_BOTH;
+			ids[i].id = wbc_ids[num_not_cached].id.uid;
+			bitmap_set(found, i);
+			break;
+		case WBC_ID_TYPE_NOT_SPECIFIED:
+			/*
+			 * wbcSidsToUnixIds() wasn't able to map this
+			 * so we still need to check legacy_sid_to_XXX()
+			 * below. Don't mark the bitmap entry
+			 * as being found so the final loop knows
+			 * to try and map this entry.
+			 */
+			ids[i].type = ID_TYPE_NOT_SPECIFIED;
+			ids[i].id = (uint32_t)-1;
+			break;
+		default:
+			/*
+			 * A successful return from wbcSidsToUnixIds()
+			 * cannot return anything other than the values
+			 * checked for above. Ensure this is so.
+			 */
+			smb_panic(__location__);
+			break;
+		}
+		num_not_cached += 1;
 	}
 
+	/*
+	 * Third and final time through the SID array,
+	 * try legacy_sid_to_gid()/legacy_sid_to_uid()
+	 * for entries we haven't already been able to
+	 * map.
+	 *
+	 * Use bitmap_set() to mark an ids[] array entry as
+	 * being mapped.
+	 */
+
 	for (i=0; i<num_sids; i++) {
-		if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
+		if (bitmap_query(found, i)) {
 			continue;
 		}
 		if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
 			ids[i].type = ID_TYPE_GID;
+			bitmap_set(found, i);
 			continue;
 		}
 		if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
 			ids[i].type = ID_TYPE_UID;
+			bitmap_set(found, i);
 			continue;
 		}
 	}
 done:
+	/*
+	 * Pass through the return array for consistency.
+	 * Any ids[].id mapped to (uint32_t)-1 must be returned
+	 * as ID_TYPE_NOT_SPECIFIED.
+	 */
 	for (i=0; i<num_sids; i++) {
 		switch(ids[i].type) {
 		case WBC_ID_TYPE_GID:
 		case WBC_ID_TYPE_UID:
 		case WBC_ID_TYPE_BOTH:
-			if (ids[i].id == -1) {
+			if (ids[i].id == (uint32_t)-1) {
 				ids[i].type = ID_TYPE_NOT_SPECIFIED;
 			}
 			break;
-- 
2.41.0


From 8b39b14dcaf104a2f3172917ef926a3fec5db891 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 24 Nov 2016 09:12:59 +0100
Subject: [PATCH 049/146] CVE-2016-2124: s4:libcli/sesssetup: don't fallback to
 non spnego authentication if we require kerberos

We should not send NTLM[v2] data on the wire if the user asked for kerberos
only.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12444

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/libcli/smb_composite/sesssetup.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c
index 6ee4929e8d7..a0a1f4baa56 100644
--- a/source4/libcli/smb_composite/sesssetup.c
+++ b/source4/libcli/smb_composite/sesssetup.c
@@ -620,6 +620,8 @@ struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *se
 	struct composite_context *c;
 	struct sesssetup_state *state;
 	NTSTATUS status;
+	enum credentials_use_kerberos krb5_state =
+		cli_credentials_get_kerberos_state(io->in.credentials);
 
 	c = composite_create(session, session->transport->ev);
 	if (c == NULL) return NULL;
@@ -635,6 +637,10 @@ struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *se
 
 	/* no session setup at all in earliest protocol varients */
 	if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
+		if (krb5_state == CRED_MUST_USE_KERBEROS) {
+			composite_error(c, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
+			return c;
+		}
 		ZERO_STRUCT(io->out);
 		composite_done(c);
 		return c;
@@ -642,9 +648,17 @@ struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *se
 
 	/* see what session setup interface we will use */
 	if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
+		if (krb5_state == CRED_MUST_USE_KERBEROS) {
+			composite_error(c, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
+			return c;
+		}
 		status = session_setup_old(c, session, io, &state->req);
 	} else if (!session->transport->options.use_spnego ||
 		   !(io->in.capabilities & CAP_EXTENDED_SECURITY)) {
+		if (krb5_state == CRED_MUST_USE_KERBEROS) {
+			composite_error(c, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
+			return c;
+		}
 		status = session_setup_nt1(c, session, io, &state->req);
 	} else {
 		struct tevent_req *subreq = NULL;
-- 
2.41.0


From 41cc796909aeade44c4f1e88923936ba4444278e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 27 Oct 2016 10:40:28 +0200
Subject: [PATCH 050/146] CVE-2016-2124: s3:libsmb: don't fallback to non
 spnego authentication if we require kerberos

We should not send NTLM[v2] nor plaintext data on the wire if the user
asked for kerberos only.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12444

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/libsmb/cliconnect.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 9bba2665663..9a69d4b7217 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1455,6 +1455,13 @@ struct tevent_req *cli_session_setup_creds_send(TALLOC_CTX *mem_ctx,
 		return req;
 	}
 
+	if (krb5_state == CRED_MUST_USE_KERBEROS) {
+		DBG_WARNING("Kerberos authentication requested, but "
+			    "the server does not support SPNEGO authentication\n");
+		tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
+		return tevent_req_post(req, ev);
+	}
+
 	if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
 		/*
 		 * SessionSetupAndX was introduced by LANMAN 1.0. So we skip
-- 
2.41.0


From 3c1688714ea93cdb7c3088b8a5e5da3025e43b42 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Sat, 18 Jan 2020 08:06:45 +0100
Subject: [PATCH 051/146] s3/auth: use set_current_user_info() in
 auth3_generate_session_info_pac()

This delays reloading config slightly, but I don't see how could affect
observable behaviour other then log messages coming from the functions in
between the different locations for lp_load_with_shares() like
make_session_info_krb5() are sent to a different logfile if "log file" uses %U.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit dc4b1e39ce1f2201a2d6ae2d4cffef2448f69a62)

[scabrero@samba.org Prerequisite for CVE-2020-25717 backport]
---
 source3/auth/auth_generic.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 167d4e00367..0e9c423efef 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -159,12 +159,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		}
 	}
 
-	/* setup the string used by %U */
-	sub_set_smb_name(username);
-
-	/* reload services so that the new %U is taken into account */
-	lp_load_with_shares(get_dyn_CONFIGFILE());
-
 	status = make_session_info_krb5(mem_ctx,
 					ntuser, ntdomain, username, pw,
 					info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
@@ -176,6 +170,14 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		goto done;
 	}
 
+	/* setup the string used by %U */
+	set_current_user_info((*session_info)->unix_info->sanitized_username,
+			      (*session_info)->unix_info->unix_name,
+			      (*session_info)->info->domain_name);
+
+	/* reload services so that the new %U is taken into account */
+	lp_load_with_shares(get_dyn_CONFIGFILE());
+
 	DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n",
 		  ntuser, ntdomain, rhost));
 
-- 
2.41.0


From cf43f0a90b3025077479d37ad905fe730695e739 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 4 Nov 2021 11:51:08 +0100
Subject: [PATCH 052/146] selftest: Fix ktest usermap file

The user was not mapped:

user_in_list: checking user |KTEST/administrator| against |KTEST\Administrator|
The user 'KTEST/administrator' has no mapping. Skip it next time.

Signed-off-by: Samuel Cabrero <scabrero@samba.org>

[scabrero@samba.org Once smb_getpswnam() fallbacks are removed the user
 has to be mapped]
---
 selftest/target/Samba3.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 9e4da0e6a08..2eb5003112e 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1124,7 +1124,7 @@ sub setup_ktest
 
 	open(USERMAP, ">$prefix/lib/username.map") or die("Unable to open $prefix/lib/username.map");
 	print USERMAP "
-$ret->{USERNAME} = KTEST\\Administrator
+$ret->{USERNAME} = KTEST/Administrator
 ";
 	close(USERMAP);
 
-- 
2.41.0


From 703f43ea7817fa0ab423134a4c40bf9c37f90274 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 5 Oct 2021 16:42:00 +0200
Subject: [PATCH 053/146] selftest/Samba3: replace (winbindd => "yes",
 skip_wait => 1) with (winbindd => "offline")

This is much more flexible and concentrates the logic in a single place.

We'll use winbindd => "offline" in other places soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14870
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 4dc3c68c9a28f71888e3d6dd3b1f0bcdb8fa45de)
(cherry picked from commit 89b9cb8b786c3e4eb8691b5363390b68d8228a2d)

[scabrero@samba.org Backported to 4.10]
---
 selftest/target/Samba3.pm | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 2eb5003112e..bbbefea44b7 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1333,7 +1333,7 @@ sub check_or_start($$$$$) {
 
 		$ENV{ENVNAME} = "$ENV{ENVNAME}.winbindd";
 
-		if ($winbindd ne "yes") {
+		if ($winbindd ne "yes" and $winbindd ne "offline") {
 			$SIG{USR1} = $SIG{ALRM} = $SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub {
 				my $signame = shift;
 				print("Skip winbindd received signal $signame");
@@ -2564,13 +2564,17 @@ sub wait_for_start($$$$$)
 		}
 	}
 
-	if ($winbindd eq "yes") {
+	if ($winbindd eq "yes" or $winbindd eq "offline") {
 	    print "checking for winbindd\n";
 	    my $count = 0;
 	    $cmd = "SELFTEST_WINBINDD_SOCKET_DIR='$envvars->{SELFTEST_WINBINDD_SOCKET_DIR}' ";
 	    $cmd .= "NSS_WRAPPER_PASSWD='$envvars->{NSS_WRAPPER_PASSWD}' ";
 	    $cmd .= "NSS_WRAPPER_GROUP='$envvars->{NSS_WRAPPER_GROUP}' ";
-	    $cmd .= Samba::bindir_path($self, "wbinfo") . " --ping-dc";
+	    if ($winbindd eq "yes") {
+		$cmd .= Samba::bindir_path($self, "wbinfo") . " --ping-dc";
+	    } elsif ($winbindd eq "offline") {
+		$cmd .= Samba::bindir_path($self, "wbinfo") . " --ping";
+	    }
 
 	    do {
 		if ($ret != 0) {
-- 
2.41.0


From eadbcf608a98c8ff90b2d5d91b61fc8100d2cc71 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 22 Oct 2021 16:20:36 +0200
Subject: [PATCH 054/146] CVE-2020-25719 CVE-2020-25717: selftest: remove
 "gensec:require_pac" settings

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 selftest/selftest.pl      | 2 --
 selftest/target/Samba4.pm | 2 --
 2 files changed, 4 deletions(-)

diff --git a/selftest/selftest.pl b/selftest/selftest.pl
index f2968139cfd..8c273951ab3 100755
--- a/selftest/selftest.pl
+++ b/selftest/selftest.pl
@@ -637,8 +637,6 @@ sub write_clientconf($$$)
 	client lanman auth = Yes
 	log level = 1
 	torture:basedir = $clientdir
-#We don't want to pass our self-tests if the PAC code is wrong
-	gensec:require_pac = true
 #We don't want to run 'speed' tests for very long
         torture:timelimit = 1
         winbind separator = /
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index a7a6c4c9587..0f644661176 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -777,8 +777,6 @@ sub provision_raw_step1($$)
 	notify:inotify = false
 	ldb:nosync = true
 	ldap server require strong auth = yes
-#We don't want to pass our self-tests if the PAC code is wrong
-	gensec:require_pac = true
 	log file = $ctx->{logdir}/log.\%m
 	log level = $ctx->{server_loglevel}
 	lanman auth = Yes
-- 
2.41.0


From 628493ea5f0cda3851ab13a41b8018daa228132b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 4 Oct 2021 17:29:34 +0200
Subject: [PATCH 055/146] CVE-2020-25717: s3:winbindd: make sure we default to
 r->out.authoritative = true

We need to make sure that temporary failures don't trigger a fallback
to the local SAM that silently ignores the domain name part for users.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[scabrero@samba.org Backported for 4.10 due to no logon_id for
log_authentication() neither is_allowed_domain()]
---
 source3/winbindd/winbindd_dual_srv.c      |  7 +++++++
 source3/winbindd/winbindd_irpc.c          |  7 +++++++
 source3/winbindd/winbindd_pam.c           | 13 ++++++++++---
 source3/winbindd/winbindd_pam_auth_crap.c |  9 ++++++++-
 source3/winbindd/winbindd_util.c          |  7 +++++++
 5 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index ab14f5d51a0..0842241e02e 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -928,6 +928,13 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p,
 	union netr_Validation *validation = NULL;
 	bool interactive = false;
 
+	/*
+	 * Make sure we start with authoritative=true,
+	 * it will only set to false if we don't know the
+	 * domain.
+	 */
+	r->out.authoritative = true;
+
 	domain = wb_child_domain();
 	if (domain == NULL) {
 		return NT_STATUS_REQUEST_NOT_ACCEPTED;
diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c
index 8cbb0b93086..45615c2dc47 100644
--- a/source3/winbindd/winbindd_irpc.c
+++ b/source3/winbindd/winbindd_irpc.c
@@ -143,6 +143,13 @@ static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg,
 	const char *target_domain_name = NULL;
 	const char *account_name = NULL;
 
+	/*
+	 * Make sure we start with authoritative=true,
+	 * it will only set to false if we don't know the
+	 * domain.
+	 */
+	req->out.authoritative = true;
+
 	switch (req->in.logon_level) {
 	case NetlogonInteractiveInformation:
 	case NetlogonServiceInformation:
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 35018fbe284..deed81d0a79 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1703,7 +1703,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(
 	unsigned char local_nt_response[24];
 	fstring name_namespace, name_domain, name_user;
 	NTSTATUS result;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags = 0;
 	uint16_t validation_level;
 	union netr_Validation *validation = NULL;
@@ -2238,6 +2238,13 @@ done:
 		result = NT_STATUS_NO_LOGON_SERVERS;
 	}
 
+	/*
+	 * Here we don't alter
+	 * state->response->data.auth.authoritative based
+	 * on the servers response
+	 * as we don't want a fallback to the local sam
+	 * for interactive PAM logons
+	 */
 	set_auth_errors(state->response, result);
 
 	DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n",
@@ -2420,7 +2427,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
 	const char *name_user = NULL;
 	const char *name_domain = NULL;
 	const char *workstation;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags = 0;
 	uint16_t validation_level;
 	union netr_Validation *validation = NULL;
@@ -2482,7 +2489,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
 				       &validation_level,
 				       &validation);
 	if (!NT_STATUS_IS_OK(result)) {
-		state->response->data.auth.authoritative = authoritative;
 		goto done;
 	}
 
@@ -2526,6 +2532,7 @@ done:
 	}
 
 	set_auth_errors(state->response, result);
+	state->response->data.auth.authoritative = authoritative;
 
 	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index b7912db43df..40cab81b5ea 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -24,6 +24,7 @@
 
 struct winbindd_pam_auth_crap_state {
 	struct winbindd_response *response;
+	bool authoritative;
 	uint32_t flags;
 };
 
@@ -45,7 +46,7 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 	if (req == NULL) {
 		return NULL;
 	}
-
+	state->authoritative = true;
 	state->flags = request->flags;
 
 	if (state->flags & WBFLAG_PAM_AUTH_PAC) {
@@ -124,6 +125,11 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 
 	domain = find_auth_domain(request->flags, auth_domain);
 	if (domain == NULL) {
+		/*
+		 * We don't know the domain so
+		 * we're not authoritative
+		 */
+		state->authoritative = false;
 		tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
 		return tevent_req_post(req, ev);
 	}
@@ -184,6 +190,7 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req,
 
 	if (tevent_req_is_nterror(req, &status)) {
 		set_auth_errors(response, status);
+		response->data.auth.authoritative = state->authoritative;
 		return status;
 	}
 
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 3245c70bb8e..315eb366a52 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -2062,6 +2062,13 @@ void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
 
 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
 {
+	/*
+	 * Make sure we start with authoritative=true,
+	 * it will only set to false if we don't know the
+	 * domain.
+	 */
+	resp->data.auth.authoritative = true;
+
 	resp->data.auth.nt_status = NT_STATUS_V(result);
 	fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
 
-- 
2.41.0


From fc3b3940208c2f03ea3aeb4b6f7e609fa9f90648 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 4 Oct 2021 17:29:34 +0200
Subject: [PATCH 056/146] CVE-2020-25717: s4:auth/ntlm: make sure
 auth_check_password() defaults to r->out.authoritative = true

We need to make sure that temporary failures don't trigger a fallback
to the local SAM that silently ignores the domain name part for users.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/auth/ntlm/auth.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 3a3fa7eaa59..f754bd5cd44 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -169,6 +169,11 @@ _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
 	/*TODO: create a new event context here! */
 	ev = auth_ctx->event_ctx;
 
+	/*
+	 * We are authoritative by default
+	 */
+	*pauthoritative = 1;
+
 	subreq = auth_check_password_send(mem_ctx,
 					  ev,
 					  auth_ctx,
-- 
2.41.0


From ecd3a8af56dcd1aad43999a253175aa04b298eef Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 057/146] CVE-2020-25717: s4:torture: start with authoritative
 = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/torture/rpc/samlogon.c | 4 ++--
 source4/torture/rpc/schannel.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index e689dfd5e98..957cb410712 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -1385,7 +1385,7 @@ static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
 	union netr_LogonLevel logon;
 	union netr_Validation validation;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags = 0;
 
 	ZERO_STRUCT(logon);
@@ -1498,7 +1498,7 @@ bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
 	union netr_LogonLevel logon;
 	union netr_Validation validation;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	struct dcerpc_binding_handle *b = p->binding_handle;
 
 	ZERO_STRUCT(a);
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
index c237c82bbe7..72d0bf28fdd 100644
--- a/source4/torture/rpc/schannel.c
+++ b/source4/torture/rpc/schannel.c
@@ -50,7 +50,7 @@ bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
 	struct netr_NetworkInfo ninfo;
 	union netr_LogonLevel logon;
 	union netr_Validation validation;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t _flags = 0;
 	DATA_BLOB names_blob, chal, lm_resp, nt_resp;
 	int i;
-- 
2.41.0


From 3feb493c3dd5383712a41729ed6f770695acb8b7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 058/146] CVE-2020-25717: s4:smb_server: start with
 authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/smb_server/smb/sesssetup.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c
index 13f13934412..5e817eecd4b 100644
--- a/source4/smb_server/smb/sesssetup.c
+++ b/source4/smb_server/smb/sesssetup.c
@@ -102,7 +102,7 @@ static void sesssetup_old_send(struct tevent_req *subreq)
 	struct auth_session_info *session_info;
 	struct smbsrv_session *smb_sess;
 	NTSTATUS status;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags;
 
 	status = auth_check_password_recv(subreq, req, &user_info_dc,
@@ -243,7 +243,7 @@ static void sesssetup_nt1_send(struct tevent_req *subreq)
 	struct auth_user_info_dc *user_info_dc = NULL;
 	struct auth_session_info *session_info;
 	struct smbsrv_session *smb_sess;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags;
 	NTSTATUS status;
 
-- 
2.41.0


From e1a1787d1d3b64adc743eab4f626068b438d0e5c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 059/146] CVE-2020-25717: s4:auth_simple: start with
 authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source4/auth/ntlm/auth_simple.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/auth/ntlm/auth_simple.c b/source4/auth/ntlm/auth_simple.c
index fcd9050979d..da8f094a838 100644
--- a/source4/auth/ntlm/auth_simple.c
+++ b/source4/auth/ntlm/auth_simple.c
@@ -150,7 +150,7 @@ static void authenticate_ldap_simple_bind_done(struct tevent_req *subreq)
 	const struct tsocket_address *local_address = user_info->local_host;
 	const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
 	struct auth_user_info_dc *user_info_dc = NULL;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags = 0;
 	NTSTATUS nt_status;
 
-- 
2.41.0


From e09409714301455ba7bbed1d80a9c90c05257aaf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 060/146] CVE-2020-25717: s3:ntlm_auth: start with
 authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/utils/ntlm_auth.c             |  4 ++--
 source3/utils/ntlm_auth_diagnostics.c | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 36c32e4a3dc..3f70732a837 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -1766,7 +1766,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
 				TALLOC_FREE(mem_ctx);
 
 			} else {
-				uint8_t authoritative = 0;
+				uint8_t authoritative = 1;
 
 				if (!domain) {
 					domain = smb_xstrdup(get_winbind_domain());
@@ -2235,7 +2235,7 @@ static bool check_auth_crap(void)
 	char *hex_lm_key;
 	char *hex_user_session_key;
 	char *error_string;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 
 	setbuf(stdout, NULL);
 
diff --git a/source3/utils/ntlm_auth_diagnostics.c b/source3/utils/ntlm_auth_diagnostics.c
index 41591a8de33..fc0fc19bacb 100644
--- a/source3/utils/ntlm_auth_diagnostics.c
+++ b/source3/utils/ntlm_auth_diagnostics.c
@@ -54,7 +54,7 @@ static bool test_lm_ntlm_broken(enum ntlm_break break_which)
 	DATA_BLOB lm_response = data_blob(NULL, 24);
 	DATA_BLOB nt_response = data_blob(NULL, 24);
 	DATA_BLOB session_key = data_blob(NULL, 16);
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uchar lm_key[8];
 	uchar user_session_key[16];
 	uchar lm_hash[16];
@@ -177,7 +177,7 @@ static bool test_ntlm_in_lm(void)
 	NTSTATUS nt_status;
 	uint32_t flags = 0;
 	DATA_BLOB nt_response = data_blob(NULL, 24);
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uchar lm_key[8];
 	uchar lm_hash[16];
 	uchar user_session_key[16];
@@ -245,7 +245,7 @@ static bool test_ntlm_in_both(void)
 	uint32_t flags = 0;
 	DATA_BLOB nt_response = data_blob(NULL, 24);
 	DATA_BLOB session_key = data_blob(NULL, 16);
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint8_t lm_key[8];
 	uint8_t lm_hash[16];
 	uint8_t user_session_key[16];
@@ -322,7 +322,7 @@ static bool test_lmv2_ntlmv2_broken(enum ntlm_break break_which)
 	DATA_BLOB lmv2_response = data_blob_null;
 	DATA_BLOB ntlmv2_session_key = data_blob_null;
 	DATA_BLOB names_blob = NTLMv2_generate_names_blob(NULL, get_winbind_netbios_name(), get_winbind_domain());
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uchar user_session_key[16];
 	DATA_BLOB chall = get_challenge();
 	char *error_string;
@@ -452,7 +452,7 @@ static bool test_plaintext(enum ntlm_break break_which)
 	char *password;
 	smb_ucs2_t *nt_response_ucs2;
 	size_t converted_size;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uchar user_session_key[16];
 	uchar lm_key[16];
 	static const uchar zeros[8] = { 0, };
-- 
2.41.0


From 26570ee2e981cc5d44eeeed020a051a4771470fe Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 061/146] CVE-2020-25717: s3:torture: start with authoritative
 = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[scabrero@samba.org Backported to 4.10 due to missing commit
a5548af018643f2e78c482e33ef0e6073db149e4 to check return value
of SMBOWFencrypt()]
---
 source3/torture/pdbtest.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c
index 64bc45e6a7c..48190e78bf8 100644
--- a/source3/torture/pdbtest.c
+++ b/source3/torture/pdbtest.c
@@ -277,7 +277,7 @@ static bool test_auth(TALLOC_CTX *mem_ctx, struct samu *pdb_entry)
 	struct netr_SamInfo6 *info6_wbc = NULL;
 	NTSTATUS status;
 	bool ok;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 
 	SMBOWFencrypt(pdb_get_nt_passwd(pdb_entry), challenge_8,
 		      local_nt_response);
-- 
2.41.0


From 36af26aac042ce48ae912d0ab7ce398280d81c93 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 062/146] CVE-2020-25717: s3:rpcclient: start with
 authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/rpcclient/cmd_netlogon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c
index 631740562c6..30fa1ed7816 100644
--- a/source3/rpcclient/cmd_netlogon.c
+++ b/source3/rpcclient/cmd_netlogon.c
@@ -496,7 +496,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli,
 	uint32_t logon_param = 0;
 	const char *workstation = NULL;
 	struct netr_SamInfo3 *info3 = NULL;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	uint32_t flags = 0;
 	uint16_t validation_level;
 	union netr_Validation *validation = NULL;
-- 
2.41.0


From 8eec50d65a10baa4e282c4a833c3cb202cd33255 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 063/146] CVE-2020-25717: s3:auth: start with authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[scabrero@samba.org Backported to 4.10 due to missing commits
7f75dec865256049e99f7fcf46317cd2d53e95d1 and
434030ba711e677fdd167a255d05c1cd4db943b7]
---
 source3/auth/auth_generic.c | 2 +-
 source3/auth/auth_samba4.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 0e9c423efef..4ef2270cb34 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -415,7 +415,7 @@ NTSTATUS auth_check_password_session_info(struct auth4_context *auth_context,
 {
 	NTSTATUS nt_status;
 	void *server_info;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 
 	if (auth_context->check_ntlm_password_send != NULL) {
 		struct tevent_context *ev = NULL;
diff --git a/source3/auth/auth_samba4.c b/source3/auth/auth_samba4.c
index a71c75631d7..bf7ccb4348c 100644
--- a/source3/auth/auth_samba4.c
+++ b/source3/auth/auth_samba4.c
@@ -118,7 +118,7 @@ static NTSTATUS check_samba4_security(const struct auth_context *auth_context,
 	NTSTATUS nt_status;
 	struct auth_user_info_dc *user_info_dc;
 	struct auth4_context *auth4_context;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 
 	nt_status = make_auth4_context_s4(auth_context, mem_ctx, &auth4_context);
 	if (!NT_STATUS_IS_OK(nt_status)) {
-- 
2.41.0


From 46bc67c24c83940ef56cfa5dbbdb8544c290f200 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 26 Oct 2021 17:42:41 +0200
Subject: [PATCH 064/146] CVE-2020-25717: auth/ntlmssp: start with
 authoritative = 1

This is not strictly needed, but makes it easier to audit
that we don't miss important places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 auth/ntlmssp/ntlmssp_server.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c
index 140e89daeb1..eebada670be 100644
--- a/auth/ntlmssp/ntlmssp_server.c
+++ b/auth/ntlmssp/ntlmssp_server.c
@@ -830,7 +830,7 @@ static void ntlmssp_server_auth_done(struct tevent_req *subreq)
 	struct gensec_security *gensec_security = state->gensec_security;
 	struct gensec_ntlmssp_context *gensec_ntlmssp = state->gensec_ntlmssp;
 	struct auth4_context *auth_context = gensec_security->auth_context;
-	uint8_t authoritative = 0;
+	uint8_t authoritative = 1;
 	NTSTATUS status;
 
 	status = auth_context->check_ntlm_password_recv(subreq,
-- 
2.41.0


From 986642f066c3fdf187a8799898196a23cb9d532c Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@samba.org>
Date: Tue, 28 Sep 2021 10:43:40 +0200
Subject: [PATCH 065/146] CVE-2020-25717: loadparm: Add new parameter "min
 domain uid"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>

[abartlet@samba.org Backported from master/4.15 due to
 conflicts with other new parameters]
---
 docs-xml/smbdotconf/security/mindomainuid.xml | 17 +++++++++++++++++
 docs-xml/smbdotconf/winbind/idmapconfig.xml   |  4 ++++
 lib/param/loadparm.c                          |  4 ++++
 source3/param/loadparm.c                      |  2 ++
 4 files changed, 27 insertions(+)
 create mode 100644 docs-xml/smbdotconf/security/mindomainuid.xml

diff --git a/docs-xml/smbdotconf/security/mindomainuid.xml b/docs-xml/smbdotconf/security/mindomainuid.xml
new file mode 100644
index 00000000000..46ae795d730
--- /dev/null
+++ b/docs-xml/smbdotconf/security/mindomainuid.xml
@@ -0,0 +1,17 @@
+<samba:parameter name="min domain uid"
+                 type="integer"
+                 context="G"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+  <para>
+    The integer parameter specifies the minimum uid allowed when mapping a
+    local account to a domain account.
+  </para>
+
+  <para>
+    Note that this option interacts with the configured <emphasis>idmap ranges</emphasis>!
+  </para>
+</description>
+
+<value type="default">1000</value>
+</samba:parameter>
diff --git a/docs-xml/smbdotconf/winbind/idmapconfig.xml b/docs-xml/smbdotconf/winbind/idmapconfig.xml
index 1374040fb29..f70f11df757 100644
--- a/docs-xml/smbdotconf/winbind/idmapconfig.xml
+++ b/docs-xml/smbdotconf/winbind/idmapconfig.xml
@@ -80,6 +80,9 @@
 		authoritative for a unix ID to SID mapping, so it must be set
 		for each individually configured domain and for the default
 		configuration. The configured ranges must be mutually disjoint.
+		</para>
+		<para>
+		Note that the low value interacts with the <smbconfoption name="min domain uid"/> option!
 		</para></listitem>
 		</varlistentry>
 
@@ -115,4 +118,5 @@
 	</programlisting>
 	
 </description>
+<related>min domain uid</related>
 </samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 4c3dfff24f3..4aa91f4d404 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -3015,6 +3015,10 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(
 		lp_ctx, "ldap max search request size", "256000");
 
+	lpcfg_do_global_parameter(lp_ctx,
+				  "min domain uid",
+				  "1000");
+
 	for (i = 0; parm_table[i].label; i++) {
 		if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
 			lp_ctx->flags[i] |= FLAG_DEFAULT;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 0db44e92d19..57d1d909099 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -963,6 +963,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.ldap_max_authenticated_request_size = 16777216;
 	Globals.ldap_max_search_request_size = 256000;
 
+	Globals.min_domain_uid = 1000;
+
 	/* Now put back the settings that were set with lp_set_cmdline() */
 	apply_lp_set_cmdline();
 }
-- 
2.41.0


From 16fa6601a3517c723e90dfb8b1a086df2616e668 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 8 Oct 2021 19:57:18 +0200
Subject: [PATCH 066/146] CVE-2020-25717: s3:auth: let
 auth3_generate_session_info_pac() forward the low level errors

Mapping everything to ACCESS_DENIED makes it hard to debug problems,
which may happen because of our more restrictive behaviour in future.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 4ef2270cb34..26a38f92b30 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -166,7 +166,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
 			  nt_errstr(status)));
-		status = NT_STATUS_ACCESS_DENIED;
+		status = nt_status_squash(status);
 		goto done;
 	}
 
-- 
2.41.0


From 10a4bdbe4a16fec1bd9b212736a9d26500e0981e Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@samba.org>
Date: Tue, 28 Sep 2021 10:45:11 +0200
Subject: [PATCH 067/146] CVE-2020-25717: s3:auth: Check minimum domain uid

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_util.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 8ff20c33759..8801d3f0f0b 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -2078,6 +2078,22 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
 			}
 		}
 		goto out;
+	} else if ((lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
+		   !is_myname(domain) && pwd->pw_uid < lp_min_domain_uid()) {
+		/*
+		 * !is_myname(domain) because when smbd starts tries to setup
+		 * the guest user info, calling this function with nobody
+		 * username. Nobody is usually uid 65535 but it can be changed
+		 * to a regular user with 'guest account' parameter
+		 */
+		nt_status = NT_STATUS_INVALID_TOKEN;
+		DBG_NOTICE("Username '%s%s%s' is invalid on this system, "
+			   "it does not meet 'min domain uid' "
+			   "restriction (%u < %u): %s\n",
+			   nt_domain, lp_winbind_separator(), nt_username,
+			   pwd->pw_uid, lp_min_domain_uid(),
+			   nt_errstr(nt_status));
+		goto out;
 	}
 
 	result = make_server_info(tmp_ctx);
-- 
2.41.0


From 58bea3837cfbeba5cd5c56060a42117fffedbda4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 8 Oct 2021 17:40:30 +0200
Subject: [PATCH 068/146] CVE-2020-25717: s3:auth: we should not try to
 autocreate the guest account

We should avoid autocreation of users as much as possible.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/user_krb5.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c
index 8998f9c8f8a..074e8c7eb71 100644
--- a/source3/auth/user_krb5.c
+++ b/source3/auth/user_krb5.c
@@ -155,7 +155,7 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 			if (!fuser) {
 				return NT_STATUS_NO_MEMORY;
 			}
-			pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
+			pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false);
 		}
 
 		/* extra sanity check that the guest account is valid */
-- 
2.41.0


From e78afbcff415d78cb29b65204fefeb0355d6651e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 8 Oct 2021 18:08:20 +0200
Subject: [PATCH 069/146] CVE-2020-25717: s3:auth: no longer let
 check_account() autocreate local users

So far we autocreated local user accounts based on just the
account_name (just ignoring any domain part).

This only happens via a possible 'add user script',
which is not typically defined on domain members
and on NT4 DCs local users already exist in the
local passdb anyway.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 8801d3f0f0b..6ee500493e6 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1873,7 +1873,7 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
+	passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false);
 	if (!passwd) {
 		DEBUG(3, ("Failed to find authenticated user %s via "
 			  "getpwnam(), denying access.\n", dom_user));
-- 
2.41.0


From a3ffab81c235aae479262cca73cf4361f76f7f9d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 8 Oct 2021 12:33:16 +0200
Subject: [PATCH 070/146] CVE-2020-25717: s3:auth: remove fallbacks in
 smb_getpwnam()

So far we tried getpwnam("DOMAIN\account") first and
always did a fallback to getpwnam("account") completely
ignoring the domain part, this just causes problems
as we mix "DOMAIN1\account", "DOMAIN2\account",
and "account"!

As we require a running winbindd for domain member setups
we should no longer do a fallback to just "account" for
users served by winbindd!

For users of the local SAM don't use this code path,
as check_sam_security() doesn't call check_account().

The only case where smb_getpwnam("account") happens is
when map_username() via ("username map [script]")  mapped
"DOMAIN\account" to something without '\', but that is
explicitly desired by the admin.

Note: use 'git show -w'

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Ralph Boehme <slow@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_util.c | 77 ++++++++++++++++++++++------------------
 1 file changed, 42 insertions(+), 35 deletions(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 6ee500493e6..161e05c2106 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1908,7 +1908,7 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
 {
 	struct passwd *pw = NULL;
 	char *p = NULL;
-	char *username = NULL;
+	const char *username = NULL;
 
 	/* we only save a copy of the username it has been mangled 
 	   by winbindd use default domain */
@@ -1927,48 +1927,55 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
 	/* code for a DOMAIN\user string */
 
 	if ( p ) {
-		pw = Get_Pwnam_alloc( mem_ctx, domuser );
-		if ( pw ) {
-			/* make sure we get the case of the username correct */
-			/* work around 'winbind use default domain = yes' */
-
-			if ( lp_winbind_use_default_domain() &&
-			     !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
-				char *domain;
-
-				/* split the domain and username into 2 strings */
-				*p = '\0';
-				domain = username;
-
-				*p_save_username = talloc_asprintf(mem_ctx,
-								"%s%c%s",
-								domain,
-								*lp_winbind_separator(),
-								pw->pw_name);
-				if (!*p_save_username) {
-					TALLOC_FREE(pw);
-					return NULL;
-				}
-			} else {
-				*p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
-			}
+		const char *domain = NULL;
 
-			/* whew -- done! */
-			return pw;
+		/* split the domain and username into 2 strings */
+		*p = '\0';
+		domain = username;
+		p++;
+		username = p;
+
+		if (strequal(domain, get_global_sam_name())) {
+			/*
+			 * This typically don't happen
+			 * as check_sam_Security()
+			 * don't call make_server_info_info3()
+			 * and thus check_account().
+			 *
+			 * But we better keep this.
+			 */
+			goto username_only;
 		}
 
-		/* setup for lookup of just the username */
-		/* remember that p and username are overlapping memory */
-
-		p++;
-		username = talloc_strdup(mem_ctx, p);
-		if (!username) {
+		pw = Get_Pwnam_alloc( mem_ctx, domuser );
+		if (pw == NULL) {
 			return NULL;
 		}
+		/* make sure we get the case of the username correct */
+		/* work around 'winbind use default domain = yes' */
+
+		if ( lp_winbind_use_default_domain() &&
+		     !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
+			*p_save_username = talloc_asprintf(mem_ctx,
+							"%s%c%s",
+							domain,
+							*lp_winbind_separator(),
+							pw->pw_name);
+			if (!*p_save_username) {
+				TALLOC_FREE(pw);
+				return NULL;
+			}
+		} else {
+			*p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
+		}
+
+		/* whew -- done! */
+		return pw;
+
 	}
 
 	/* just lookup a plain username */
-
+username_only:
 	pw = Get_Pwnam_alloc(mem_ctx, username);
 
 	/* Create local user if requested but only if winbindd
-- 
2.41.0


From 9a1bb168388205f5a2bfa459a5da63c5046eaa7a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 4 Oct 2021 18:03:55 +0200
Subject: [PATCH 071/146] CVE-2020-25717: s3:auth: don't let create_local_token
 depend on !winbind_ping()

We always require a running winbindd on a domain member, so
we should better fail a request instead of silently alter
the behaviour, which results in a different unix token, just
because winbindd might be restarted.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_util.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 161e05c2106..c0e5cfd7fa8 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -551,13 +551,11 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
 	}
 
 	/*
-	 * If winbind is not around, we can not make much use of the SIDs the
-	 * domain controller provided us with. Likewise if the user name was
-	 * mapped to some local unix user.
+	 * If the user name was mapped to some local unix user,
+	 * we can not make much use of the SIDs the
+	 * domain controller provided us with.
 	 */
-
-	if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
-	    (server_info->nss_token)) {
+	if (server_info->nss_token) {
 		char *found_username = NULL;
 		status = create_token_from_username(session_info,
 						    server_info->unix_name,
-- 
2.41.0


From bbe5c6693ba6954dab5bfef9f8c3778164cd879e Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab@samba.org>
Date: Wed, 11 Nov 2020 18:50:45 +0200
Subject: [PATCH 072/146] CVE-2020-25717: Add FreeIPA domain controller role

As we want to reduce use of 'classic domain controller' role but FreeIPA
relies on it internally, add a separate role to mark FreeIPA domain
controller role.

It means that role won't result in ROLE_STANDALONE.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Alexander Bokovoy <ab@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>

[abartlet@samba.org Backported due to conflict with DEBUG
 statements and IPA branding changes in comments]
---
 docs-xml/smbdotconf/security/serverrole.xml |  7 ++++
 lib/param/loadparm_server_role.c            |  2 ++
 lib/param/param_table.c                     |  1 +
 lib/param/util.c                            |  1 +
 libcli/netlogon/netlogon.c                  |  2 +-
 libds/common/roles.h                        |  1 +
 source3/auth/auth.c                         |  3 ++
 source3/auth/auth_sam.c                     |  2 ++
 source3/include/smb_macros.h                |  2 +-
 source3/lib/netapi/joindomain.c             |  1 +
 source3/param/loadparm.c                    |  4 ++-
 source3/passdb/lookup_sid.c                 |  1 -
 source3/passdb/machine_account_secrets.c    |  7 ++--
 source3/registry/reg_backend_prod_options.c |  1 +
 source3/rpc_server/dssetup/srv_dssetup_nt.c |  1 +
 source3/smbd/server.c                       |  2 +-
 source3/winbindd/winbindd_misc.c            |  2 +-
 source3/winbindd/winbindd_util.c            | 40 ++++++++++++++++-----
 source4/auth/ntlm/auth.c                    |  1 +
 source4/kdc/kdc-heimdal.c                   |  1 +
 source4/rpc_server/samr/dcesrv_samr.c       |  2 ++
 21 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/docs-xml/smbdotconf/security/serverrole.xml b/docs-xml/smbdotconf/security/serverrole.xml
index 9511c61c96d..b8b83a127b5 100644
--- a/docs-xml/smbdotconf/security/serverrole.xml
+++ b/docs-xml/smbdotconf/security/serverrole.xml
@@ -78,6 +78,13 @@
     url="http://wiki.samba.org/index.php/Samba4/HOWTO">Samba4
     HOWTO</ulink></para>
 
+    <para><anchor id="IPA-DC"/><emphasis>SERVER ROLE = IPA DOMAIN CONTROLLER</emphasis></para>
+
+    <para>This mode of operation runs Samba in a hybrid mode for IPA
+    domain controller, providing forest trust to Active Directory.
+    This role requires special configuration performed by IPA installers
+    and should not be used manually by any administrator.
+    </para>
 </description>
 
 <related>security</related>
diff --git a/lib/param/loadparm_server_role.c b/lib/param/loadparm_server_role.c
index 7a6bc770723..a78d1ab9cf3 100644
--- a/lib/param/loadparm_server_role.c
+++ b/lib/param/loadparm_server_role.c
@@ -42,6 +42,7 @@ static const struct srv_role_tab {
 	{ ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
 	{ ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
 	{ ROLE_ACTIVE_DIRECTORY_DC, "ROLE_ACTIVE_DIRECTORY_DC" },
+	{ ROLE_IPA_DC, "ROLE_IPA_DC"},
 	{ 0, NULL }
 };
 
@@ -140,6 +141,7 @@ bool lp_is_security_and_server_role_valid(int server_role, int security)
 	case ROLE_DOMAIN_PDC:
 	case ROLE_DOMAIN_BDC:
 	case ROLE_ACTIVE_DIRECTORY_DC:
+	case ROLE_IPA_DC:
 		if (security == SEC_USER) {
 			valid = true;
 		}
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index f9d3b55adf2..aed205d1944 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -100,6 +100,7 @@ static const struct enum_list enum_server_role[] = {
 	{ROLE_ACTIVE_DIRECTORY_DC, "active directory domain controller"},
 	{ROLE_ACTIVE_DIRECTORY_DC, "domain controller"},
 	{ROLE_ACTIVE_DIRECTORY_DC, "dc"},
+	{ROLE_IPA_DC, "IPA primary domain controller"},
 	{-1, NULL}
 };
 
diff --git a/lib/param/util.c b/lib/param/util.c
index cd8e74b9d8f..9a0fc102de8 100644
--- a/lib/param/util.c
+++ b/lib/param/util.c
@@ -255,6 +255,7 @@ const char *lpcfg_sam_name(struct loadparm_context *lp_ctx)
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
 	case ROLE_ACTIVE_DIRECTORY_DC:
+	case ROLE_IPA_DC:
 		return lpcfg_workgroup(lp_ctx);
 	default:
 		return lpcfg_netbios_name(lp_ctx);
diff --git a/libcli/netlogon/netlogon.c b/libcli/netlogon/netlogon.c
index 58a331d70ad..838bdf84c87 100644
--- a/libcli/netlogon/netlogon.c
+++ b/libcli/netlogon/netlogon.c
@@ -93,7 +93,7 @@ NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
 		if (ndr->offset < ndr->data_size) {
 			TALLOC_FREE(ndr);
 			/*
-			 * We need to handle a bug in FreeIPA (at least <= 4.1.2).
+			 * We need to handle a bug in IPA (at least <= 4.1.2).
 			 *
 			 * They include the ip address information without setting
 			 * NETLOGON_NT_VERSION_5EX_WITH_IP, while using
diff --git a/libds/common/roles.h b/libds/common/roles.h
index 4772c8d7d3f..03ba1915b21 100644
--- a/libds/common/roles.h
+++ b/libds/common/roles.h
@@ -33,6 +33,7 @@ enum server_role {
 	
 	/* not in samr.idl */
 	ROLE_ACTIVE_DIRECTORY_DC = 4,
+	ROLE_IPA_DC = 5,
 
 	/* To determine the role automatically, this is not a valid role */
 	ROLE_AUTO          = 100
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 0a96d591808..c5bfe9ac626 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -529,6 +529,7 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
 		break;
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
+	case ROLE_IPA_DC:
 		DEBUG(5,("Making default auth method list for DC\n"));
 		methods = "anonymous sam winbind sam_ignoredomain";
 		break;
@@ -557,6 +558,7 @@ NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx,
 	switch (lp_server_role()) {
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
+	case ROLE_IPA_DC:
 		methods = "sam_netlogon3 winbind";
 		break;
 
@@ -578,6 +580,7 @@ NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx,
 	case ROLE_DOMAIN_MEMBER:
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
+	case ROLE_IPA_DC:
 		methods = "sam";
 		break;
 	case ROLE_ACTIVE_DIRECTORY_DC:
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index f9764d87e3c..d0b29083d46 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -139,6 +139,7 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
 			break;
 		case ROLE_DOMAIN_PDC:
 		case ROLE_DOMAIN_BDC:
+		case ROLE_IPA_DC:
 			if ( !is_local_name && !is_my_domain ) {
 				DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
 					effective_domain));
@@ -209,6 +210,7 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
 	switch (lp_server_role()) {
 	case ROLE_DOMAIN_PDC:
 	case ROLE_DOMAIN_BDC:
+	case ROLE_IPA_DC:
 		break;
 	default:
 		DBG_ERR("Invalid server role\n");
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 06d24744960..346401510c2 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -213,7 +213,7 @@ copy an IP address from one buffer to another
  Check to see if we are a DC for this domain
 *****************************************************************************/
 
-#define IS_DC  (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) 
+#define IS_DC  (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_server_role() == ROLE_IPA_DC)
 #define IS_AD_DC  (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
 
 /*
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index 8d0752f4531..0344c0e0416 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -369,6 +369,7 @@ WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
 		case ROLE_DOMAIN_MEMBER:
 		case ROLE_DOMAIN_PDC:
 		case ROLE_DOMAIN_BDC:
+		case ROLE_IPA_DC:
 			*r->out.name_type = NetSetupDomainName;
 			break;
 		case ROLE_STANDALONE:
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 57d1d909099..98e05d13d59 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -4321,6 +4321,7 @@ int lp_default_server_announce(void)
 			default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
 			break;
 		case ROLE_DOMAIN_PDC:
+		case ROLE_IPA_DC:
 			default_server_announce |= SV_TYPE_DOMAIN_CTRL;
 			break;
 		case ROLE_DOMAIN_BDC:
@@ -4346,7 +4347,8 @@ int lp_default_server_announce(void)
 bool lp_domain_master(void)
 {
 	if (Globals._domain_master == Auto)
-		return (lp_server_role() == ROLE_DOMAIN_PDC);
+		return (lp_server_role() == ROLE_DOMAIN_PDC ||
+			lp_server_role() == ROLE_IPA_DC);
 
 	return (bool)Globals._domain_master;
 }
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 186ba17fda6..839da5cfbf4 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -117,7 +117,6 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
 	if (((flags & LOOKUP_NAME_DOMAIN) || (flags == 0)) &&
 	    strequal(domain, get_global_sam_name()))
 	{
-
 		/* It's our own domain, lookup the name in passdb */
 		if (lookup_global_sam_name(name, flags, &rid, &type)) {
 			sid_compose(&sid, get_global_sam_sid(), rid);
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index dfc21f295a1..b60cf56c490 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -198,7 +198,8 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
 	dyn_guid = (struct GUID *)secrets_fetch(key, &size);
 
 	if (!dyn_guid) {
-		if (lp_server_role() == ROLE_DOMAIN_PDC) {
+		if (lp_server_role() == ROLE_DOMAIN_PDC ||
+		    lp_server_role() == ROLE_IPA_DC) {
 			new_guid = GUID_random();
 			if (!secrets_store_domain_guid(domain, &new_guid))
 				return False;
@@ -314,9 +315,7 @@ static const char *trust_keystr(const char *domain)
 
 enum netr_SchannelType get_default_sec_channel(void)
 {
-	if (lp_server_role() == ROLE_DOMAIN_BDC ||
-	    lp_server_role() == ROLE_DOMAIN_PDC ||
-	    lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
+	if (IS_DC) {
 		return SEC_CHAN_BDC;
 	} else {
 		return SEC_CHAN_WKSTA;
diff --git a/source3/registry/reg_backend_prod_options.c b/source3/registry/reg_backend_prod_options.c
index 655c587ac40..7bd3f324c37 100644
--- a/source3/registry/reg_backend_prod_options.c
+++ b/source3/registry/reg_backend_prod_options.c
@@ -40,6 +40,7 @@ static int prod_options_fetch_values(const char *key, struct regval_ctr *regvals
 	switch (lp_server_role()) {
 		case ROLE_DOMAIN_PDC:
 		case ROLE_DOMAIN_BDC:
+		case ROLE_IPA_DC:
 			value_ascii = "LanmanNT";
 			break;
 		case ROLE_STANDALONE:
diff --git a/source3/rpc_server/dssetup/srv_dssetup_nt.c b/source3/rpc_server/dssetup/srv_dssetup_nt.c
index 7e3efa8504e..aa896e15ac4 100644
--- a/source3/rpc_server/dssetup/srv_dssetup_nt.c
+++ b/source3/rpc_server/dssetup/srv_dssetup_nt.c
@@ -62,6 +62,7 @@ static WERROR fill_dsrole_dominfo_basic(TALLOC_CTX *ctx,
 			basic->domain = get_global_sam_name();
 			break;
 		case ROLE_DOMAIN_PDC:
+		case ROLE_IPA_DC:
 			basic->role = DS_ROLE_PRIMARY_DC;
 			basic->domain = get_global_sam_name();
 			break;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 7d96a5762ec..d263507b22f 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -1969,7 +1969,7 @@ extern void build_options(bool screen);
 		exit_daemon("smbd can not open secrets.tdb", EACCES);
 	}
 
-	if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
+	if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC || lp_server_role() == ROLE_IPA_DC) {
 		struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
 		if (!open_schannel_session_store(NULL, lp_ctx)) {
 			exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index cc0701e597a..f09b029fd13 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -75,7 +75,7 @@ static char *get_trust_type_string(TALLOC_CTX *mem_ctx,
 	case SEC_CHAN_BDC: {
 		int role = lp_server_role();
 
-		if (role == ROLE_DOMAIN_PDC) {
+		if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) {
 			s = talloc_strdup(mem_ctx, "PDC");
 			if (s == NULL) {
 				return NULL;
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 315eb366a52..04e79e70f6b 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1225,15 +1225,37 @@ bool init_domain_list(void)
 			secure_channel_type = SEC_CHAN_LOCAL;
 		}
 
-		status = add_trusted_domain(get_global_sam_name(),
-					    NULL,
-					    get_global_sam_sid(),
-					    LSA_TRUST_TYPE_DOWNLEVEL,
-					    trust_flags,
-					    0, /* trust_attribs */
-					    secure_channel_type,
-					    NULL,
-					    &domain);
+		if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
+			/* This is IPA DC that presents itself as
+			 * an Active Directory domain controller to trusted AD
+			 * forests but in fact is a classic domain controller.
+			 */
+			trust_flags = NETR_TRUST_FLAG_PRIMARY;
+			trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
+			trust_flags |= NETR_TRUST_FLAG_NATIVE;
+			trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
+			trust_flags |= NETR_TRUST_FLAG_TREEROOT;
+			status = add_trusted_domain(pdb_domain_info->name,
+						    pdb_domain_info->dns_domain,
+						    &pdb_domain_info->sid,
+						    LSA_TRUST_TYPE_UPLEVEL,
+						    trust_flags,
+						    LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
+						    secure_channel_type,
+						    NULL,
+						    &domain);
+			TALLOC_FREE(pdb_domain_info);
+		} else {
+			status = add_trusted_domain(get_global_sam_name(),
+						    NULL,
+						    get_global_sam_sid(),
+						    LSA_TRUST_TYPE_DOWNLEVEL,
+						    trust_flags,
+						    0, /* trust_attribs */
+						    secure_channel_type,
+						    NULL,
+						    &domain);
+		}
 		if (!NT_STATUS_IS_OK(status)) {
 			DBG_ERR("Failed to add local SAM to "
 				"domain to winbindd's internal list\n");
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index f754bd5cd44..7dab02b5c4d 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -773,6 +773,7 @@ const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
 	case ROLE_ACTIVE_DIRECTORY_DC:
+	case ROLE_IPA_DC:
 		auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
 		break;
 	}
diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c
index b5de5a790d4..49aa560470c 100644
--- a/source4/kdc/kdc-heimdal.c
+++ b/source4/kdc/kdc-heimdal.c
@@ -276,6 +276,7 @@ static NTSTATUS kdc_task_init(struct task_server *task)
 		return NT_STATUS_INVALID_DOMAIN_ROLE;
 	case ROLE_DOMAIN_PDC:
 	case ROLE_DOMAIN_BDC:
+	case ROLE_IPA_DC:
 		task_server_terminate(
 		    task, "Cannot start KDC as a 'classic Samba' DC", false);
 		return NT_STATUS_INVALID_DOMAIN_ROLE;
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 51fed4da62b..1f09b721408 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -568,6 +568,7 @@ static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state
 		break;
 	case ROLE_DOMAIN_PDC:
 	case ROLE_DOMAIN_BDC:
+	case ROLE_IPA_DC:
 	case ROLE_AUTO:
 		return NT_STATUS_INTERNAL_ERROR;
 	case ROLE_DOMAIN_MEMBER:
@@ -675,6 +676,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
 		break;
 	case ROLE_DOMAIN_PDC:
 	case ROLE_DOMAIN_BDC:
+	case ROLE_IPA_DC:
 	case ROLE_AUTO:
 		return NT_STATUS_INTERNAL_ERROR;
 	case ROLE_DOMAIN_MEMBER:
-- 
2.41.0


From 3a8b4d3b410508dfb0538376046a5b38c53f9568 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 5 Oct 2021 18:11:57 +0200
Subject: [PATCH 073/146] CVE-2020-25717: auth/gensec: always require a PAC in
 domain mode (DC or member)

AD domains always provide a PAC unless UF_NO_AUTH_DATA_REQUIRED is set
on the service account, which can only be explicitly configured,
but that's an invalid configuration!

We still try to support standalone servers in an MIT realm,
as legacy setup.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 auth/gensec/gensec_util.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index e185acc0c20..694661b53b5 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -25,6 +25,8 @@
 #include "auth/gensec/gensec_internal.h"
 #include "auth/common_auth.h"
 #include "../lib/util/asn1.h"
+#include "param/param.h"
+#include "libds/common/roles.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -46,10 +48,27 @@ NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
 	session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
 
 	if (!pac_blob) {
-		if (gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
-			DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access\n",
-				  principal_string));
-			return NT_STATUS_ACCESS_DENIED;
+		enum server_role server_role =
+			lpcfg_server_role(gensec_security->settings->lp_ctx);
+
+		/*
+		 * For any domain setup (DC or member) we require having
+		 * a PAC, as the service ticket comes from an AD DC,
+		 * which will always provide a PAC, unless
+		 * UF_NO_AUTH_DATA_REQUIRED is configured for our
+		 * account, but that's just an invalid configuration,
+		 * the admin configured for us!
+		 *
+		 * As a legacy case, we still allow kerberos tickets from an MIT
+		 * realm, but only in standalone mode. In that mode we'll only
+		 * ever accept a kerberos authentication with a keytab file
+		 * being explicitly configured via the 'keytab method' option.
+		 */
+		if (server_role != ROLE_STANDALONE) {
+			DBG_WARNING("Unable to find PAC in ticket from %s, "
+				    "failing to allow access\n",
+				    principal_string);
+			return NT_STATUS_NO_IMPERSONATION_TOKEN;
 		}
 		DBG_NOTICE("Unable to find PAC for %s, resorting to local "
 			   "user lookup\n", principal_string);
-- 
2.41.0


From 15cca0f7ee6f4b8d96b6b650b2d009b030a2bc5f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 11 Oct 2021 23:17:19 +0200
Subject: [PATCH 074/146] CVE-2020-25717: s4:auth: remove unused
 auth_generate_session_info_principal()

We'll require a PAC at the main gensec layer already.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[abartlet@samba.org Backported from master/4.15 as
 check_password is sync in 4.14]
---
 source4/auth/auth.h          |  8 ------
 source4/auth/ntlm/auth.c     | 49 ++++--------------------------------
 source4/auth/ntlm/auth_sam.c | 12 ---------
 3 files changed, 5 insertions(+), 64 deletions(-)

diff --git a/source4/auth/auth.h b/source4/auth/auth.h
index 51895c9259f..f16d0649de2 100644
--- a/source4/auth/auth.h
+++ b/source4/auth/auth.h
@@ -73,14 +73,6 @@ struct auth_operations {
 				TALLOC_CTX *mem_ctx,
 				struct auth_user_info_dc **interim_info,
 				bool *authoritative);
-
-	/* Lookup a 'session info interim' return based only on the principal or DN */
-	NTSTATUS (*get_user_info_dc_principal)(TALLOC_CTX *mem_ctx,
-						       struct auth4_context *auth_context,
-						       const char *principal,
-						       struct ldb_dn *user_dn,
-						       struct auth_user_info_dc **interim_info);
-	uint32_t flags;
 };
 
 struct auth_method_context {
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 7dab02b5c4d..2765fd1b13c 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -86,48 +86,6 @@ _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t cha
 	return NT_STATUS_OK;
 }
 
-/****************************************************************************
-Used in the gensec_gssapi and gensec_krb5 server-side code, where the
-PAC isn't available, and for tokenGroups in the DSDB stack.
-
- Supply either a principal or a DN
-****************************************************************************/
-static NTSTATUS auth_generate_session_info_principal(struct auth4_context *auth_ctx,
-						  TALLOC_CTX *mem_ctx,
-						  const char *principal,
-						  struct ldb_dn *user_dn,
-                                                  uint32_t session_info_flags,
-                                                  struct auth_session_info **session_info)
-{
-	NTSTATUS nt_status;
-	struct auth_method_context *method;
-	struct auth_user_info_dc *user_info_dc;
-
-	for (method = auth_ctx->methods; method; method = method->next) {
-		if (!method->ops->get_user_info_dc_principal) {
-			continue;
-		}
-
-		nt_status = method->ops->get_user_info_dc_principal(mem_ctx, auth_ctx, principal, user_dn, &user_info_dc);
-		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
-			continue;
-		}
-		if (!NT_STATUS_IS_OK(nt_status)) {
-			return nt_status;
-		}
-
-		nt_status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx, 
-							       user_info_dc,
-							       user_info_dc->info->account_name,
-							       session_info_flags, session_info);
-		talloc_free(user_info_dc);
-
-		return nt_status;
-	}
-
-	return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 /**
  * Check a user's Plaintext, LM or NTLM password.
  * (sync version)
@@ -663,8 +621,11 @@ static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
 	TALLOC_CTX *tmp_ctx;
 
 	if (!pac_blob) {
-		return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name,
-						       NULL, session_info_flags, session_info);
+		/*
+		 * This should already be catched at the main
+		 * gensec layer, but better check twice
+		 */
+		return NT_STATUS_INTERNAL_ERROR;
 	}
 
 	tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c
index fb88cb87f66..a8c7d8b4b85 100644
--- a/source4/auth/ntlm/auth_sam.c
+++ b/source4/auth/ntlm/auth_sam.c
@@ -854,28 +854,16 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
 	return NT_STATUS_OK;
 }
 
-/* Wrapper for the auth subsystem pointer */
-static NTSTATUS authsam_get_user_info_dc_principal_wrapper(TALLOC_CTX *mem_ctx,
-							  struct auth4_context *auth_context,
-							  const char *principal,
-							  struct ldb_dn *user_dn,
-							  struct auth_user_info_dc **user_info_dc)
-{
-	return authsam_get_user_info_dc_principal(mem_ctx, auth_context->lp_ctx, auth_context->sam_ctx,
-						 principal, user_dn, user_info_dc);
-}
 static const struct auth_operations sam_ignoredomain_ops = {
 	.name		           = "sam_ignoredomain",
 	.want_check	           = authsam_ignoredomain_want_check,
 	.check_password	           = authsam_check_password_internals,
-	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
 };
 
 static const struct auth_operations sam_ops = {
 	.name		           = "sam",
 	.want_check	           = authsam_want_check,
 	.check_password	           = authsam_check_password_internals,
-	.get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
 };
 
 _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *);
-- 
2.41.0


From ec14a33f17e638870c997b56d4b5ce9096cbb27a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 21 Sep 2021 12:27:28 +0200
Subject: [PATCH 075/146] CVE-2020-25717: s3:ntlm_auth: fix memory leaks in
 ntlm_auth_generate_session_info_pac()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/utils/ntlm_auth.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 3f70732a837..fefdd32bf11 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -827,23 +827,27 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c
 	if (!p) {
 		DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
 			  princ_name));
-		return NT_STATUS_LOGON_FAILURE;
+		status = NT_STATUS_LOGON_FAILURE;
+		goto done;
 	}
 
 	user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
 	if (!user) {
-		return NT_STATUS_NO_MEMORY;
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
 	}
 
 	realm = talloc_strdup(talloc_tos(), p + 1);
 	if (!realm) {
-		return NT_STATUS_NO_MEMORY;
+		status = NT_STATUS_NO_MEMORY;
+		goto done;
 	}
 
 	if (!strequal(realm, lp_realm())) {
 		DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
 		if (!lp_allow_trusted_domains()) {
-			return NT_STATUS_LOGON_FAILURE;
+			status = NT_STATUS_LOGON_FAILURE;
+			goto done;
 		}
 	}
 
@@ -851,7 +855,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c
 		domain = talloc_strdup(mem_ctx,
 					logon_info->info3.base.logon_domain.string);
 		if (!domain) {
-			return NT_STATUS_NO_MEMORY;
+			status = NT_STATUS_NO_MEMORY;
+			goto done;
 		}
 		DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
 	} else {
@@ -881,7 +886,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c
 			domain = talloc_strdup(mem_ctx, realm);
 		}
 		if (!domain) {
-			return NT_STATUS_NO_MEMORY;
+			status = NT_STATUS_NO_MEMORY;
+			goto done;
 		}
 		DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
 	}
-- 
2.41.0


From 9e036a77eca721c4ea23c3f629d9e504d5780f79 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 21 Sep 2021 12:44:01 +0200
Subject: [PATCH 076/146] CVE-2020-25717: s3:ntlm_auth: let
 ntlm_auth_generate_session_info_pac() base the name on the PAC LOGON_INFO
 only

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/utils/ntlm_auth.c | 91 ++++++++++++---------------------------
 1 file changed, 28 insertions(+), 63 deletions(-)

diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index fefdd32bf11..ff2fd30a9ae 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -799,10 +799,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c
 	struct PAC_LOGON_INFO *logon_info = NULL;
 	char *unixuser;
 	NTSTATUS status;
-	char *domain = NULL;
-	char *realm = NULL;
-	char *user = NULL;
-	char *p;
+	const char *domain = "";
+	const char *user = "";
 
 	tmp_ctx = talloc_new(mem_ctx);
 	if (!tmp_ctx) {
@@ -819,79 +817,46 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c
 		if (!NT_STATUS_IS_OK(status)) {
 			goto done;
 		}
-	}
-
-	DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
-
-	p = strchr_m(princ_name, '@');
-	if (!p) {
-		DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
-			  princ_name));
-		status = NT_STATUS_LOGON_FAILURE;
+	} else {
+		status = NT_STATUS_ACCESS_DENIED;
+		DBG_WARNING("Kerberos ticket for[%s] has no PAC: %s\n",
+			    princ_name, nt_errstr(status));
 		goto done;
 	}
 
-	user = talloc_strndup(mem_ctx, princ_name, p - princ_name);
-	if (!user) {
-		status = NT_STATUS_NO_MEMORY;
-		goto done;
+	if (logon_info->info3.base.account_name.string != NULL) {
+		user = logon_info->info3.base.account_name.string;
+	} else {
+		user = "";
+	}
+	if (logon_info->info3.base.logon_domain.string != NULL) {
+		domain = logon_info->info3.base.logon_domain.string;
+	} else {
+		domain = "";
 	}
 
-	realm = talloc_strdup(talloc_tos(), p + 1);
-	if (!realm) {
-		status = NT_STATUS_NO_MEMORY;
+	if (strlen(user) == 0 || strlen(domain) == 0) {
+		status = NT_STATUS_ACCESS_DENIED;
+		DBG_WARNING("Kerberos ticket for[%s] has invalid "
+			    "account_name[%s]/logon_domain[%s]: %s\n",
+			    princ_name,
+			    logon_info->info3.base.account_name.string,
+			    logon_info->info3.base.logon_domain.string,
+			    nt_errstr(status));
 		goto done;
 	}
 
-	if (!strequal(realm, lp_realm())) {
-		DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
+	DBG_NOTICE("Kerberos ticket principal name is [%s] "
+		   "account_name[%s]/logon_domain[%s]\n",
+		   princ_name, user, domain);
+
+	if (!strequal(domain, lp_workgroup())) {
 		if (!lp_allow_trusted_domains()) {
 			status = NT_STATUS_LOGON_FAILURE;
 			goto done;
 		}
 	}
 
-	if (logon_info && logon_info->info3.base.logon_domain.string) {
-		domain = talloc_strdup(mem_ctx,
-					logon_info->info3.base.logon_domain.string);
-		if (!domain) {
-			status = NT_STATUS_NO_MEMORY;
-			goto done;
-		}
-		DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
-	} else {
-
-		/* If we have winbind running, we can (and must) shorten the
-		   username by using the short netbios name. Otherwise we will
-		   have inconsistent user names. With Kerberos, we get the
-		   fully qualified realm, with ntlmssp we get the short
-		   name. And even w2k3 does use ntlmssp if you for example
-		   connect to an ip address. */
-
-		wbcErr wbc_status;
-		struct wbcDomainInfo *info = NULL;
-
-		DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
-			   realm));
-
-		wbc_status = wbcDomainInfo(realm, &info);
-
-		if (WBC_ERROR_IS_OK(wbc_status)) {
-			domain = talloc_strdup(mem_ctx,
-						info->short_name);
-			wbcFreeMemory(info);
-		} else {
-			DEBUG(3, ("Could not find short name: %s\n",
-				  wbcErrorString(wbc_status)));
-			domain = talloc_strdup(mem_ctx, realm);
-		}
-		if (!domain) {
-			status = NT_STATUS_NO_MEMORY;
-			goto done;
-		}
-		DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
-	}
-
 	unixuser = talloc_asprintf(tmp_ctx, "%s%c%s", domain, winbind_separator(), user);
 	if (!unixuser) {
 		status = NT_STATUS_NO_MEMORY;
-- 
2.41.0


From 4c01fd62e30b8e1137e7de01ecb41c94550dac24 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 4 Oct 2021 19:42:20 +0200
Subject: [PATCH 077/146] CVE-2020-25717: s3:auth: let
 auth3_generate_session_info_pac() delegate everything to
 make_server_info_wbcAuthUserInfo()

This consolidates the code paths used for NTLMSSP and Kerberos!

I checked what we were already doing for NTLMSSP, which is this:

a) source3/auth/auth_winbind.c calls wbcAuthenticateUserEx()
b) as a domain member we require a valid response from winbindd,
   otherwise we'll return NT_STATUS_NO_LOGON_SERVERS
c) we call make_server_info_wbcAuthUserInfo(), which internally
   calls make_server_info_info3()
d) auth_check_ntlm_password() calls
   smb_pam_accountcheck(unix_username, rhost), where rhost
   is only an ipv4 or ipv6 address (without reverse dns lookup)
e) from auth3_check_password_send/auth3_check_password_recv()
   server_returned_info will be passed to auth3_generate_session_info(),
   triggered by gensec_session_info(), which means we'll call into
   create_local_token() in order to transform auth_serversupplied_info
   into auth_session_info.

For Kerberos gensec_session_info() will call
auth3_generate_session_info_pac() via the gensec_generate_session_info_pac()
helper function. The current logic is this:

a) gensec_generate_session_info_pac() is the function that
   evaluates the 'gensec:require_pac', which defaulted to 'no'
   before.
b) auth3_generate_session_info_pac() called
   wbcAuthenticateUserEx() in order to pass the PAC blob
   to winbindd, but only to prime its cache, e.g. netsamlogon cache
   and others. Most failures were just ignored.
c) If the PAC blob is available, it extracted the PAC_LOGON_INFO
   from it.
d) Then we called the horrible get_user_from_kerberos_info() function:
   - It uses a first part of the tickets principal name (before the @)
     as username and combines that with the 'logon_info->base.logon_domain'
     if the logon_info (PAC) is present.
   - As a fallback without a PAC it's tries to ask winbindd for a mapping
     from realm to netbios domain name.
   - Finally is falls back to using the realm as netbios domain name
   With this information is builds 'userdomain+winbind_separator+useraccount'
   and calls map_username() followed by smb_getpwnam() with create=true,
   Note this is similar to the make_server_info_info3() => check_account()
   => smb_getpwnam() logic under 3.
   - It also calls smb_pam_accountcheck(), but may pass the reverse DNS lookup name
     instead of the ip address as rhost.
   - It does some MAP_TO_GUEST_ON_BAD_UID logic and auto creates the
     guest account.
e) We called create_info3_from_pac_logon_info()
f) make_session_info_krb5() calls gets called and triggers this:
   - If get_user_from_kerberos_info() mapped to guest, it calls
     make_server_info_guest()
   - If create_info3_from_pac_logon_info() created a info3 from logon_info,
     it calls make_server_info_info3()
   - Without a PAC it tries pdb_getsampwnam()/make_server_info_sam() with
     a fallback to make_server_info_pw()
   From there it calls create_local_token()

I tried to change auth3_generate_session_info_pac() to behave similar
to auth_winbind.c together with auth3_generate_session_info() as
a domain member, as we now rely on a PAC:

a) As domain member we require a PAC and always call wbcAuthenticateUserEx()
   and require a valid response!
b) we call make_server_info_wbcAuthUserInfo(), which internally
   calls make_server_info_info3(). Note make_server_info_info3()
   handles MAP_TO_GUEST_ON_BAD_UID and make_server_info_guest()
   internally.
c) Similar to auth_check_ntlm_password() we now call
   smb_pam_accountcheck(unix_username, rhost), where rhost
   is only an ipv4 or ipv6 address (without reverse dns lookup)
d) From there it calls create_local_token()

As standalone server (in an MIT realm) we continue
with the already existing code logic, which works without a PAC:
a) we keep smb_getpwnam() with create=true logic as it
   also requires an explicit 'add user script' option.
b) In the following commits we assert that there's
   actually no PAC in this mode, which means we can
   remove unused and confusing code.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14646
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[abartlet@samba.org Backported due to change in structure
 initialization with { 0 } to zero ]
[abartlet@samba.org backported to 4.12 due to conflict
 with code not present to reload shared on krb5 login]
---
 source3/auth/auth_generic.c | 139 ++++++++++++++++++++++++++++--------
 1 file changed, 110 insertions(+), 29 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 26a38f92b30..3099e8f9057 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -46,6 +46,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 						uint32_t session_info_flags,
 						struct auth_session_info **session_info)
 {
+	enum server_role server_role = lp_server_role();
 	TALLOC_CTX *tmp_ctx;
 	struct PAC_LOGON_INFO *logon_info = NULL;
 	struct netr_SamInfo3 *info3_copy = NULL;
@@ -54,39 +55,59 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 	char *ntuser;
 	char *ntdomain;
 	char *username;
-	char *rhost;
+	const char *rhost;
 	struct passwd *pw;
 	NTSTATUS status;
-	int rc;
 
 	tmp_ctx = talloc_new(mem_ctx);
 	if (!tmp_ctx) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	if (pac_blob) {
-#ifdef HAVE_KRB5
-		struct wbcAuthUserParams params = {};
+	if (tsocket_address_is_inet(remote_address, "ip")) {
+		rhost = tsocket_address_inet_addr_string(
+			remote_address, tmp_ctx);
+		if (rhost == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto done;
+		}
+	} else {
+		rhost = "127.0.0.1";
+	}
+
+	if (server_role != ROLE_STANDALONE) {
+		struct wbcAuthUserParams params = { 0 };
 		struct wbcAuthUserInfo *info = NULL;
 		struct wbcAuthErrorInfo *err = NULL;
+		struct auth_serversupplied_info *server_info = NULL;
+		char *original_user_name = NULL;
+		char *p = NULL;
 		wbcErr wbc_err;
 
+		if (pac_blob == NULL) {
+			/*
+			 * This should already be catched at the main
+			 * gensec layer, but better check twice
+			 */
+			status = NT_STATUS_INTERNAL_ERROR;
+			goto done;
+		}
+
 		/*
 		 * Let winbind decode the PAC.
 		 * This will also store the user
 		 * data in the netsamlogon cache.
 		 *
-		 * We need to do this *before* we
-		 * call get_user_from_kerberos_info()
-		 * as that does a user lookup that
-		 * expects info in the netsamlogon cache.
-		 *
-		 * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=11259
+		 * This used to be a cache prime
+		 * optimization, but now we delegate
+		 * all logic to winbindd, as we require
+		 * winbindd as domain member anyway.
 		 */
 		params.level = WBC_AUTH_USER_LEVEL_PAC;
 		params.password.pac.data = pac_blob->data;
 		params.password.pac.length = pac_blob->length;
 
+		/* we are contacting the privileged pipe */
 		become_root();
 		wbc_err = wbcAuthenticateUserEx(&params, &info, &err);
 		unbecome_root();
@@ -99,18 +120,90 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		 */
 
 		switch (wbc_err) {
-			case WBC_ERR_WINBIND_NOT_AVAILABLE:
 			case WBC_ERR_SUCCESS:
 				break;
+			case WBC_ERR_WINBIND_NOT_AVAILABLE:
+				status = NT_STATUS_NO_LOGON_SERVERS;
+				DBG_ERR("winbindd not running - "
+					"but required as domain member: %s\n",
+					nt_errstr(status));
+				goto done;
 			case WBC_ERR_AUTH_ERROR:
 				status = NT_STATUS(err->nt_status);
 				wbcFreeMemory(err);
 				goto done;
+			case WBC_ERR_NO_MEMORY:
+				status = NT_STATUS_NO_MEMORY;
+				goto done;
 			default:
 				status = NT_STATUS_LOGON_FAILURE;
 				goto done;
 		}
 
+		status = make_server_info_wbcAuthUserInfo(tmp_ctx,
+							  info->account_name,
+							  info->domain_name,
+							  info, &server_info);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(10, ("make_server_info_wbcAuthUserInfo failed: %s\n",
+				   nt_errstr(status)));
+			goto done;
+		}
+
+		/* We skip doing this step if the caller asked us not to */
+		if (!(server_info->guest)) {
+			const char *unix_username = server_info->unix_name;
+
+			/* We might not be root if we are an RPC call */
+			become_root();
+			status = smb_pam_accountcheck(unix_username, rhost);
+			unbecome_root();
+
+			if (!NT_STATUS_IS_OK(status)) {
+				DEBUG(3, ("check_ntlm_password:  PAM Account for user [%s] "
+					  "FAILED with error %s\n",
+					  unix_username, nt_errstr(status)));
+				goto done;
+			}
+
+			DEBUG(5, ("check_ntlm_password:  PAM Account for user [%s] "
+				  "succeeded\n", unix_username));
+		}
+
+		DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
+
+		p = strchr_m(princ_name, '@');
+		if (!p) {
+			DEBUG(3, ("[%s] Doesn't look like a valid principal\n",
+				  princ_name));
+			status = NT_STATUS_LOGON_FAILURE;
+			goto done;
+		}
+
+		original_user_name = talloc_strndup(tmp_ctx, princ_name, p - princ_name);
+		if (original_user_name == NULL) {
+			status = NT_STATUS_NO_MEMORY;
+			goto done;
+		}
+
+		status = create_local_token(mem_ctx,
+					    server_info,
+					    NULL,
+					    original_user_name,
+					    session_info);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(10, ("create_local_token failed: %s\n",
+				   nt_errstr(status)));
+			goto done;
+		}
+
+		goto session_info_ready;
+	}
+
+	/* This is the standalone legacy code path */
+
+	if (pac_blob != NULL) {
+#ifdef HAVE_KRB5
 		status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL,
 						 NULL, NULL, 0, &logon_info);
 #else
@@ -121,22 +214,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		}
 	}
 
-	rc = get_remote_hostname(remote_address,
-				 &rhost,
-				 tmp_ctx);
-	if (rc < 0) {
-		status = NT_STATUS_NO_MEMORY;
-		goto done;
-	}
-	if (strequal(rhost, "UNKNOWN")) {
-		rhost = tsocket_address_inet_addr_string(remote_address,
-							 tmp_ctx);
-		if (rhost == NULL) {
-			status = NT_STATUS_NO_MEMORY;
-			goto done;
-		}
-	}
-
 	status = get_user_from_kerberos_info(tmp_ctx, rhost,
 					     princ_name, logon_info,
 					     &is_mapped, &is_guest,
@@ -170,6 +247,8 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		goto done;
 	}
 
+session_info_ready:
+
 	/* setup the string used by %U */
 	set_current_user_info((*session_info)->unix_info->sanitized_username,
 			      (*session_info)->unix_info->unix_name,
@@ -179,7 +258,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 	lp_load_with_shares(get_dyn_CONFIGFILE());
 
 	DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n",
-		  ntuser, ntdomain, rhost));
+		  (*session_info)->info->account_name,
+		  (*session_info)->info->domain_name,
+		  rhost));
 
 	status = NT_STATUS_OK;
 
-- 
2.41.0


From 2d7cd152d95e091447731b3699be9654ca13cffc Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 5 Oct 2021 17:14:01 +0200
Subject: [PATCH 078/146] CVE-2020-25717: selftest: configure 'ktest' env with
 winbindd and idmap_autorid

The 'ktest' environment was/is designed to test kerberos in an active
directory member setup. It was created at a time we wanted to test
smbd/winbindd with kerberos without having the source4 ad dc available.

This still applies to testing the build with system krb5 libraries
but without relying on a running ad dc.

As a domain member setup requires a running winbindd, we should test it
that way, in order to reflect a valid setup.

As a side effect it provides a way to demonstrate that we can accept
smb connections authenticated via kerberos, but no connection to
a domain controller! In order get this working offline, we need an
idmap backend with ID_TYPE_BOTH support, so we use 'autorid', which
should be the default choice.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14646
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[scabrero@samba.org Backported to 4.11 Run winbindd in offline mode
 but keep the user name mapping to avoid having to backport fixes
 for bso#14539]
---
 selftest/target/Samba3.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index bbbefea44b7..7034127ef0b 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1176,7 +1176,7 @@ $ret->{USERNAME} = KTEST/Administrator
 	# access the share for tests.
 	chmod 0777, "$prefix/share";
 
-	if (not $self->check_or_start($ret, "yes", "no", "yes")) {
+	if (not $self->check_or_start($ret, "yes", "offline", "yes")) {
 	       return undef;
 	}
 	return $ret;
-- 
2.41.0


From 6b4c3693d4ae3c54fd4c890b71829ac582436dee Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 5 Oct 2021 18:12:49 +0200
Subject: [PATCH 079/146] CVE-2020-25717: s3:auth: let
 auth3_generate_session_info_pac() reject a PAC in standalone mode

We should be strict in standalone mode, that we only support MIT realms
without a PAC in order to keep the code sane.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>

[abartlet@samba.org Backported to Samba 4.12 has conflcits
 as the share reload code is in a different spot]
---
 source3/auth/auth_generic.c | 29 +++++++++--------------------
 1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 3099e8f9057..23f746c078e 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -48,8 +48,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 {
 	enum server_role server_role = lp_server_role();
 	TALLOC_CTX *tmp_ctx;
-	struct PAC_LOGON_INFO *logon_info = NULL;
-	struct netr_SamInfo3 *info3_copy = NULL;
 	bool is_mapped;
 	bool is_guest;
 	char *ntuser;
@@ -203,19 +201,20 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 	/* This is the standalone legacy code path */
 
 	if (pac_blob != NULL) {
-#ifdef HAVE_KRB5
-		status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL,
-						 NULL, NULL, 0, &logon_info);
-#else
-		status = NT_STATUS_ACCESS_DENIED;
-#endif
+		/*
+		 * In standalone mode we don't expect a PAC!
+		 * we only support MIT realms
+		 */
+		status = NT_STATUS_BAD_TOKEN_TYPE;
+		DBG_WARNING("Unexpected PAC for [%s] in standalone mode - %s\n",
+			    princ_name, nt_errstr(status));
 		if (!NT_STATUS_IS_OK(status)) {
 			goto done;
 		}
 	}
 
 	status = get_user_from_kerberos_info(tmp_ctx, rhost,
-					     princ_name, logon_info,
+					     princ_name, NULL,
 					     &is_mapped, &is_guest,
 					     &ntuser, &ntdomain,
 					     &username, &pw);
@@ -226,19 +225,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 		goto done;
 	}
 
-	/* Get the info3 from the PAC data if we have it */
-	if (logon_info) {
-		status = create_info3_from_pac_logon_info(tmp_ctx,
-					logon_info,
-					&info3_copy);
-		if (!NT_STATUS_IS_OK(status)) {
-			goto done;
-		}
-	}
-
 	status = make_session_info_krb5(mem_ctx,
 					ntuser, ntdomain, username, pw,
-					info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
+					NULL, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
 					session_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
-- 
2.41.0


From 6f6a1fedb97d119a7f15831f7295b1774e806ba8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 8 Oct 2021 17:59:59 +0200
Subject: [PATCH 080/146] CVE-2020-25717: s3:auth: simplify
 get_user_from_kerberos_info() by removing the unused logon_info argument

This code is only every called in standalone mode on a MIT realm,
it means we never have a PAC and we also don't have winbindd arround.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_generic.c |  2 +-
 source3/auth/proto.h        |  1 -
 source3/auth/user_krb5.c    | 57 +++++++------------------------------
 3 files changed, 11 insertions(+), 49 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index 23f746c078e..a11aae713f5 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -214,7 +214,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 	}
 
 	status = get_user_from_kerberos_info(tmp_ctx, rhost,
-					     princ_name, NULL,
+					     princ_name,
 					     &is_mapped, &is_guest,
 					     &ntuser, &ntdomain,
 					     &username, &pw);
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index fcfd1f36ca2..1ed3f4a2f77 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -416,7 +416,6 @@ struct PAC_LOGON_INFO;
 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 				     const char *cli_name,
 				     const char *princ_name,
-				     struct PAC_LOGON_INFO *logon_info,
 				     bool *is_mapped,
 				     bool *mapped_to_guest,
 				     char **ntuser,
diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c
index 074e8c7eb71..7b69ca6c222 100644
--- a/source3/auth/user_krb5.c
+++ b/source3/auth/user_krb5.c
@@ -31,7 +31,6 @@
 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 				     const char *cli_name,
 				     const char *princ_name,
-				     struct PAC_LOGON_INFO *logon_info,
 				     bool *is_mapped,
 				     bool *mapped_to_guest,
 				     char **ntuser,
@@ -40,8 +39,8 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 				     struct passwd **_pw)
 {
 	NTSTATUS status;
-	char *domain = NULL;
-	char *realm = NULL;
+	const char *domain = NULL;
+	const char *realm = NULL;
 	char *user = NULL;
 	char *p;
 	char *fuser = NULL;
@@ -62,55 +61,16 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	realm = talloc_strdup(talloc_tos(), p + 1);
-	if (!realm) {
-		return NT_STATUS_NO_MEMORY;
-	}
+	realm = p + 1;
 
 	if (!strequal(realm, lp_realm())) {
 		DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm));
 		if (!lp_allow_trusted_domains()) {
 			return NT_STATUS_LOGON_FAILURE;
 		}
-	}
-
-	if (logon_info && logon_info->info3.base.logon_domain.string) {
-		domain = talloc_strdup(mem_ctx,
-					logon_info->info3.base.logon_domain.string);
-		if (!domain) {
-			return NT_STATUS_NO_MEMORY;
-		}
-		DEBUG(10, ("Domain is [%s] (using PAC)\n", domain));
+		domain = realm;
 	} else {
-
-		/* If we have winbind running, we can (and must) shorten the
-		   username by using the short netbios name. Otherwise we will
-		   have inconsistent user names. With Kerberos, we get the
-		   fully qualified realm, with ntlmssp we get the short
-		   name. And even w2k3 does use ntlmssp if you for example
-		   connect to an ip address. */
-
-		wbcErr wbc_status;
-		struct wbcDomainInfo *info = NULL;
-
-		DEBUG(10, ("Mapping [%s] to short name using winbindd\n",
-			   realm));
-
-		wbc_status = wbcDomainInfo(realm, &info);
-
-		if (WBC_ERROR_IS_OK(wbc_status)) {
-			domain = talloc_strdup(mem_ctx,
-						info->short_name);
-			wbcFreeMemory(info);
-		} else {
-			DEBUG(3, ("Could not find short name: %s\n",
-				  wbcErrorString(wbc_status)));
-			domain = talloc_strdup(mem_ctx, realm);
-		}
-		if (!domain) {
-			return NT_STATUS_NO_MEMORY;
-		}
-		DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain));
+		domain = lp_workgroup();
 	}
 
 	fuser = talloc_asprintf(mem_ctx,
@@ -175,7 +135,11 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 	*ntuser = user;
-	*ntdomain = domain;
+	*ntdomain = talloc_strdup(mem_ctx, domain);
+	if (*ntdomain == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	*_pw = pw;
 
 	return NT_STATUS_OK;
@@ -282,7 +246,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 				     const char *cli_name,
 				     const char *princ_name,
-				     struct PAC_LOGON_INFO *logon_info,
 				     bool *is_mapped,
 				     bool *mapped_to_guest,
 				     char **ntuser,
-- 
2.41.0


From 8fd8d952c4396484f822c51f71667baaf49402b4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 8 Oct 2021 18:03:04 +0200
Subject: [PATCH 081/146] CVE-2020-25717: s3:auth: simplify
 make_session_info_krb5() by removing unused arguments

This is only ever be called in standalone mode with an MIT realm,
so we don't have a PAC/info3 structure.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 source3/auth/auth_generic.c |  2 +-
 source3/auth/proto.h        |  2 --
 source3/auth/user_krb5.c    | 20 +-------------------
 3 files changed, 2 insertions(+), 22 deletions(-)

diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index a11aae713f5..4dd1af784bf 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -227,7 +227,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
 
 	status = make_session_info_krb5(mem_ctx,
 					ntuser, ntdomain, username, pw,
-					NULL, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
+					is_guest, is_mapped,
 					session_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
diff --git a/source3/auth/proto.h b/source3/auth/proto.h
index 1ed3f4a2f77..c00ac70fd3f 100644
--- a/source3/auth/proto.h
+++ b/source3/auth/proto.h
@@ -427,9 +427,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 				char *ntdomain,
 				char *username,
 				struct passwd *pw,
-				const struct netr_SamInfo3 *info3,
 				bool mapped_to_guest, bool username_was_mapped,
-				DATA_BLOB *session_key,
 				struct auth_session_info **session_info);
 
 /* The following definitions come from auth/auth_samba4.c  */
diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c
index 7b69ca6c222..b8f37cbeee0 100644
--- a/source3/auth/user_krb5.c
+++ b/source3/auth/user_krb5.c
@@ -150,9 +150,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 				char *ntdomain,
 				char *username,
 				struct passwd *pw,
-				const struct netr_SamInfo3 *info3,
 				bool mapped_to_guest, bool username_was_mapped,
-				DATA_BLOB *session_key,
 				struct auth_session_info **session_info)
 {
 	NTSTATUS status;
@@ -166,20 +164,6 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 			return status;
 		}
 
-	} else if (info3) {
-		/* pass the unmapped username here since map_username()
-		   will be called again in make_server_info_info3() */
-
-		status = make_server_info_info3(mem_ctx,
-						ntuser, ntdomain,
-						&server_info,
-						info3);
-		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(1, ("make_server_info_info3 failed: %s!\n",
-				  nt_errstr(status)));
-			return status;
-		}
-
 	} else {
 		/*
 		 * We didn't get a PAC, we have to make up the user
@@ -231,7 +215,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 
 	server_info->nss_token |= username_was_mapped;
 
-	status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info);
+	status = create_local_token(mem_ctx, server_info, NULL, ntuser, session_info);
 	talloc_free(server_info);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(10,("failed to create local token: %s\n",
@@ -261,9 +245,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
 				char *ntdomain,
 				char *username,
 				struct passwd *pw,
-				const struct netr_SamInfo3 *info3,
 				bool mapped_to_guest, bool username_was_mapped,
-				DATA_BLOB *session_key,
 				struct auth_session_info **session_info)
 {
 	return NT_STATUS_NOT_IMPLEMENTED;
-- 
2.41.0


From bf0696ec4f3080ebd0b61cac5a05a9284ccabda8 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Wed, 1 Sep 2021 15:39:19 +1200
Subject: [PATCH 082/146] krb5pac.idl: Add ticket checksum PAC buffer type

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Isaac Boukris <iboukris@samba.org>
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881
(cherry picked from commit ff2f38fae79220e16765e17671972f9a55eb7cce)
---
 librpc/idl/krb5pac.idl | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl
index f27e7243ee4..711b7f94b6c 100644
--- a/librpc/idl/krb5pac.idl
+++ b/librpc/idl/krb5pac.idl
@@ -112,7 +112,8 @@ interface krb5pac
 		PAC_TYPE_KDC_CHECKSUM = 7,
 		PAC_TYPE_LOGON_NAME = 10,
 		PAC_TYPE_CONSTRAINED_DELEGATION = 11,
-		PAC_TYPE_UPN_DNS_INFO = 12
+		PAC_TYPE_UPN_DNS_INFO = 12,
+		PAC_TYPE_TICKET_CHECKSUM = 16
 	} PAC_TYPE;
 
 	typedef struct {
@@ -128,6 +129,7 @@ interface krb5pac
 		[case(PAC_TYPE_CONSTRAINED_DELEGATION)][subcontext(0xFFFFFC01)]
 			PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation;
 		[case(PAC_TYPE_UPN_DNS_INFO)]	PAC_UPN_DNS_INFO upn_dns_info;
+		[case(PAC_TYPE_TICKET_CHECKSUM)]	PAC_SIGNATURE_DATA ticket_checksum;
 		/* when new PAC info types are added they are supposed to be done
 		   in such a way that they are backwards compatible with existing
 		   servers. This makes it safe to just use a [default] for
-- 
2.41.0


From 7a9f618fdbf32872594f47dd4bc83ce087af4bbc Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Wed, 1 Sep 2021 15:40:59 +1200
Subject: [PATCH 083/146] security.idl: Add well-known SIDs for FAST

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Isaac Boukris <iboukris@samba.org>
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881
(cherry picked from commit 0092b4a3ed58b2c256d4dd9117cce927a3edde12)
---
 librpc/idl/security.idl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl
index 5930f448955..e6065a35691 100644
--- a/librpc/idl/security.idl
+++ b/librpc/idl/security.idl
@@ -292,6 +292,9 @@ interface security
 	const string SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = "S-1-18-1";
 	const string SID_SERVICE_ASSERTED_IDENTITY = "S-1-18-2";
 
+	const string SID_COMPOUNDED_AUTHENTICATION = "S-1-5-21-0-0-0-496";
+	const string SID_CLAIMS_VALID = "S-1-5-21-0-0-0-497";
+
 	/*
 	 * http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
 	 */
-- 
2.41.0


From 7713b56a8a8b26e05aa9a517348e3f95da1144a7 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Wed, 29 Sep 2021 16:15:26 +1300
Subject: [PATCH 084/146] krb5pac.idl: Add missing buffer type values

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Backported-by: Andreas Schneider <asn@samba.org>
---
 librpc/idl/krb5pac.idl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl
index 711b7f94b6c..141894ec5f1 100644
--- a/librpc/idl/krb5pac.idl
+++ b/librpc/idl/krb5pac.idl
@@ -113,6 +113,9 @@ interface krb5pac
 		PAC_TYPE_LOGON_NAME = 10,
 		PAC_TYPE_CONSTRAINED_DELEGATION = 11,
 		PAC_TYPE_UPN_DNS_INFO = 12,
+		PAC_TYPE_CLIENT_CLAIMS_INFO = 13,
+		PAC_TYPE_DEVICE_INFO = 14,
+		PAC_TYPE_DEVICE_CLAIMS_INFO = 15,
 		PAC_TYPE_TICKET_CHECKSUM = 16
 	} PAC_TYPE;
 
-- 
2.41.0


From a85bf1d86d6e081c781cc93a8e7aaa049c3818d0 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Tue, 26 Oct 2021 20:33:38 +1300
Subject: [PATCH 085/146] CVE-2020-25719 krb5pac.idl: Add PAC_ATTRIBUTES_INFO
 PAC buffer type

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
 librpc/idl/krb5pac.idl | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl
index 141894ec5f1..4bfec2de5e6 100644
--- a/librpc/idl/krb5pac.idl
+++ b/librpc/idl/krb5pac.idl
@@ -97,6 +97,16 @@ interface krb5pac
 		PAC_UPN_DNS_FLAGS flags;
 	} PAC_UPN_DNS_INFO;
 
+	typedef [bitmap32bit] bitmap {
+		PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED = 0x00000001,
+		PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY = 0x00000002
+	} PAC_ATTRIBUTE_INFO_FLAGS;
+
+	typedef struct {
+		uint32 flags_length; /* length in bits */
+		PAC_ATTRIBUTE_INFO_FLAGS flags;
+	} PAC_ATTRIBUTES_INFO;
+
 	typedef [public] struct {
 		PAC_LOGON_INFO *info;
 	} PAC_LOGON_INFO_CTR;
@@ -116,7 +126,8 @@ interface krb5pac
 		PAC_TYPE_CLIENT_CLAIMS_INFO = 13,
 		PAC_TYPE_DEVICE_INFO = 14,
 		PAC_TYPE_DEVICE_CLAIMS_INFO = 15,
-		PAC_TYPE_TICKET_CHECKSUM = 16
+		PAC_TYPE_TICKET_CHECKSUM = 16,
+		PAC_TYPE_ATTRIBUTES_INFO = 17
 	} PAC_TYPE;
 
 	typedef struct {
@@ -133,6 +144,7 @@ interface krb5pac
 			PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation;
 		[case(PAC_TYPE_UPN_DNS_INFO)]	PAC_UPN_DNS_INFO upn_dns_info;
 		[case(PAC_TYPE_TICKET_CHECKSUM)]	PAC_SIGNATURE_DATA ticket_checksum;
+		[case(PAC_TYPE_ATTRIBUTES_INFO)]	PAC_ATTRIBUTES_INFO attributes_info;
 		/* when new PAC info types are added they are supposed to be done
 		   in such a way that they are backwards compatible with existing
 		   servers. This makes it safe to just use a [default] for
-- 
2.41.0


From 57e4c415ecae66ee984a30eb66d5d248e0e8587d Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Tue, 26 Oct 2021 20:33:49 +1300
Subject: [PATCH 086/146] CVE-2020-25719 krb5pac.idl: Add PAC_REQUESTER_SID PAC
 buffer type

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
 librpc/idl/krb5pac.idl | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl
index 4bfec2de5e6..f750359a069 100644
--- a/librpc/idl/krb5pac.idl
+++ b/librpc/idl/krb5pac.idl
@@ -107,6 +107,10 @@ interface krb5pac
 		PAC_ATTRIBUTE_INFO_FLAGS flags;
 	} PAC_ATTRIBUTES_INFO;
 
+	typedef struct {
+		dom_sid sid;
+	} PAC_REQUESTER_SID;
+
 	typedef [public] struct {
 		PAC_LOGON_INFO *info;
 	} PAC_LOGON_INFO_CTR;
@@ -127,7 +131,8 @@ interface krb5pac
 		PAC_TYPE_DEVICE_INFO = 14,
 		PAC_TYPE_DEVICE_CLAIMS_INFO = 15,
 		PAC_TYPE_TICKET_CHECKSUM = 16,
-		PAC_TYPE_ATTRIBUTES_INFO = 17
+		PAC_TYPE_ATTRIBUTES_INFO = 17,
+		PAC_TYPE_REQUESTER_SID = 18
 	} PAC_TYPE;
 
 	typedef struct {
@@ -145,6 +150,7 @@ interface krb5pac
 		[case(PAC_TYPE_UPN_DNS_INFO)]	PAC_UPN_DNS_INFO upn_dns_info;
 		[case(PAC_TYPE_TICKET_CHECKSUM)]	PAC_SIGNATURE_DATA ticket_checksum;
 		[case(PAC_TYPE_ATTRIBUTES_INFO)]	PAC_ATTRIBUTES_INFO attributes_info;
+		[case(PAC_TYPE_REQUESTER_SID)]	PAC_REQUESTER_SID requester_sid;
 		/* when new PAC info types are added they are supposed to be done
 		   in such a way that they are backwards compatible with existing
 		   servers. This makes it safe to just use a [default] for
-- 
2.41.0


From 7782a97868ead29b6e87fa98dcef8dbc2706b67d Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
Date: Mon, 27 Sep 2021 11:20:19 +1300
Subject: [PATCH 087/146] CVE-2020-25721 krb5pac: Add new buffers for
 samAccountName and objectSID

These appear when PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID is set.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14835

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
 librpc/idl/krb5pac.idl   | 18 ++++++++++++++++--
 librpc/ndr/ndr_krb5pac.c |  4 ++--
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl
index f750359a069..94b9160d6eb 100644
--- a/librpc/idl/krb5pac.idl
+++ b/librpc/idl/krb5pac.idl
@@ -86,15 +86,29 @@ interface krb5pac
 	} PAC_CONSTRAINED_DELEGATION;
 
 	typedef [bitmap32bit] bitmap {
-		PAC_UPN_DNS_FLAG_CONSTRUCTED = 0x00000001
+		PAC_UPN_DNS_FLAG_CONSTRUCTED = 0x00000001,
+		PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID = 0x00000002
 	} PAC_UPN_DNS_FLAGS;
 
+	typedef struct {
+		[value(2*strlen_m(samaccountname))] uint16 samaccountname_size;
+		[relative_short,subcontext(0),subcontext_size(samaccountname_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *samaccountname;
+		[value(ndr_size_dom_sid(objectsid, ndr->flags))] uint16 objectsid_size;
+		[relative_short,subcontext(0),subcontext_size(objectsid_size)] dom_sid *objectsid;
+	} PAC_UPN_DNS_INFO_SAM_NAME_AND_SID;
+
+	typedef [nodiscriminant] union {
+		[case(PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_SAM_NAME_AND_SID sam_name_and_sid;
+		[default];
+	} PAC_UPN_DNS_INFO_EX;
+
 	typedef struct {
 		[value(2*strlen_m(upn_name))] uint16 upn_name_size;
 		[relative_short,subcontext(0),subcontext_size(upn_name_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *upn_name;
 		[value(2*strlen_m(dns_domain_name))] uint16 dns_domain_name_size;
 		[relative_short,subcontext(0),subcontext_size(dns_domain_name_size),flag(NDR_ALIGN8|STR_NOTERM|NDR_REMAINING)] string *dns_domain_name;
 		PAC_UPN_DNS_FLAGS flags;
+		[switch_is(flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_EX ex;
 	} PAC_UPN_DNS_INFO;
 
 	typedef [bitmap32bit] bitmap {
@@ -160,7 +174,7 @@ interface krb5pac
 
 	typedef [public,nopush,nopull] struct {
 		PAC_TYPE type;
-		[value(_ndr_size_PAC_INFO(info, type, 0))] uint32 _ndr_size;
+		[value(_ndr_size_PAC_INFO(info, type, LIBNDR_FLAG_ALIGN8))] uint32 _ndr_size;
 		/*
 		 * We need to have two subcontexts to get the padding right,
 		 * the outer subcontext uses NDR_ROUND(_ndr_size, 8), while
diff --git a/librpc/ndr/ndr_krb5pac.c b/librpc/ndr/ndr_krb5pac.c
index a9ae2c4a789..57b28df9e52 100644
--- a/librpc/ndr/ndr_krb5pac.c
+++ b/librpc/ndr/ndr_krb5pac.c
@@ -41,7 +41,7 @@ enum ndr_err_code ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const
 	if (ndr_flags & NDR_SCALARS) {
 		NDR_CHECK(ndr_push_align(ndr, 4));
 		NDR_CHECK(ndr_push_PAC_TYPE(ndr, NDR_SCALARS, r->type));
-		NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,0)));
+		NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,LIBNDR_FLAG_ALIGN8)));
 		{
 			uint32_t _flags_save_PAC_INFO = ndr->flags;
 			ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
@@ -59,7 +59,7 @@ enum ndr_err_code ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const
 				{
 					struct ndr_push *_ndr_info_pad;
 					struct ndr_push *_ndr_info;
-					size_t _ndr_size = _ndr_size_PAC_INFO(r->info, r->type, 0);
+					size_t _ndr_size = _ndr_size_PAC_INFO(r->info, r->type, LIBNDR_FLAG_ALIGN8);
 					NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info_pad, 0, NDR_ROUND(_ndr_size, 8)));
 					NDR_CHECK(ndr_push_subcontext_start(_ndr_info_pad, &_ndr_info, 0, _ndr_size));
 					NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->info, r->type));
-- 
2.41.0


From 44e8dd1a9a3c02dee31497fe20411758fce1acf9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab@samba.org>
Date: Fri, 12 Nov 2021 19:06:01 +0200
Subject: [PATCH 088/146] IPA DC: add missing checks

When introducing FreeIPA support, two places were forgotten:

 - schannel gensec module needs to be aware of IPA DC
 - _lsa_QueryInfoPolicy should treat IPA DC as PDC

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14903

Signed-off-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>

Autobuild-User(master): Alexander Bokovoy <ab@samba.org>
Autobuild-Date(master): Sat Nov 13 07:01:26 UTC 2021 on sn-devel-184

(cherry picked from commit c69b66f649c1d47a7367f7efe25b8df32369a3a5)
---
 auth/gensec/schannel.c              | 1 +
 source3/rpc_server/lsa/srv_lsa_nt.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c
index 71e9afdf48e..f23c1effb23 100644
--- a/auth/gensec/schannel.c
+++ b/auth/gensec/schannel.c
@@ -740,6 +740,7 @@ static NTSTATUS schannel_server_start(struct gensec_security *gensec_security)
 	case ROLE_DOMAIN_BDC:
 	case ROLE_DOMAIN_PDC:
 	case ROLE_ACTIVE_DIRECTORY_DC:
+	case ROLE_IPA_DC:
 		return NT_STATUS_OK;
 	default:
 		return NT_STATUS_NOT_IMPLEMENTED;
diff --git a/source3/rpc_server/lsa/srv_lsa_nt.c b/source3/rpc_server/lsa/srv_lsa_nt.c
index 57bfc596005..3f77856457e 100644
--- a/source3/rpc_server/lsa/srv_lsa_nt.c
+++ b/source3/rpc_server/lsa/srv_lsa_nt.c
@@ -672,6 +672,7 @@ NTSTATUS _lsa_QueryInfoPolicy(struct pipes_struct *p,
 		switch (lp_server_role()) {
 			case ROLE_DOMAIN_PDC:
 			case ROLE_DOMAIN_BDC:
+			case ROLE_IPA_DC:
 				name = get_global_sam_name();
 				sid = dom_sid_dup(p->mem_ctx, get_global_sam_sid());
 				if (!sid) {
-- 
2.41.0


From c64bcd68614871cdddc9fe37c860729f490b4da1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 12 Nov 2021 15:27:58 +0100
Subject: [PATCH 089/146] CVE-2020-25717: idmap_nss: verify that the name of
 the sid belongs to the configured domain

We already check the sid belongs to the domain, but checking the name
too feels better and make it easier to understand.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

[abartlet@samba.org backorted from commit bfd093648b4af51d104096c0cb3535e8706671e5
 as header libcli/security/dom_sid.h was not present for struct dom_sid_buf]

[abartlet@samba.org fix CVE marker]
---
 source3/winbindd/idmap_nss.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c
index 3fe98cbc729..243b67ccafd 100644
--- a/source3/winbindd/idmap_nss.c
+++ b/source3/winbindd/idmap_nss.c
@@ -25,6 +25,7 @@
 #include "nsswitch/winbind_client.h"
 #include "idmap.h"
 #include "lib/winbind_util.h"
+#include "libcli/security/dom_sid.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
@@ -135,18 +136,21 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 	for (i = 0; ids[i]; i++) {
 		struct group *gr;
 		enum lsa_SidType type;
-		const char *p = NULL;
+		const char *_domain = NULL;
+		const char *_name = NULL;
+		char *domain = NULL;
 		char *name = NULL;
 		bool ret;
 
 		/* by default calls to winbindd are disabled
 		   the following call will not recurse so this is safe */
 		(void)winbind_on();
-		ret = winbind_lookup_sid(talloc_tos(), ids[i]->sid, NULL,
-					 &p, &type);
+		ret = winbind_lookup_sid(talloc_tos(),
+					 ids[i]->sid,
+					 &_domain,
+					 &_name,
+					 &type);
 		(void)winbind_off();
-		name = discard_const_p(char, p);
-
 		if (!ret) {
 			/* TODO: how do we know if the name is really not mapped,
 			 * or something just failed ? */
@@ -154,6 +158,18 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 			continue;
 		}
 
+		domain = discard_const_p(char, _domain);
+		name = discard_const_p(char, _name);
+
+		if (!strequal(domain, dom->name)) {
+			struct dom_sid_buf buf;
+			DBG_ERR("DOMAIN[%s] ignoring SID[%s] belongs to %s [%s\\%s]\n",
+			        dom->name, dom_sid_str_buf(ids[i]->sid, &buf),
+				sid_type_lookup(type), domain, name);
+			ids[i]->status = ID_UNMAPPED;
+			continue;
+		}
+
 		switch (type) {
 		case SID_NAME_USER: {
 			struct passwd *pw;
@@ -186,6 +202,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 			ids[i]->status = ID_UNKNOWN;
 			break;
 		}
+		TALLOC_FREE(domain);
 		TALLOC_FREE(name);
 	}
 	return NT_STATUS_OK;
-- 
2.41.0


From c7d277ef2c902482eca00fc981bf340a088fbfe1 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Fri, 12 Nov 2021 20:53:30 +1300
Subject: [PATCH 090/146] CVE-2020-25717: nsswitch/nsstest.c: Lower 'non
 existent uid' to make room for new accounts

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit fdbee5e074ebd76d659613b8b7114d70f938c38a)
---
 nsswitch/nsstest.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c
index 46f96795f39..8ce7493d1b6 100644
--- a/nsswitch/nsstest.c
+++ b/nsswitch/nsstest.c
@@ -460,7 +460,7 @@ static void nss_test_errors(void)
 		printf("ERROR Non existent user gave error %d\n", last_error);
 	}
 
-	pwd = getpwuid(0xFFF0);
+	pwd = getpwuid(0xFF00);
 	if (pwd || last_error != NSS_STATUS_NOTFOUND) {
 		total_errors++;
 		printf("ERROR Non existent uid gave error %d\n", last_error);
-- 
2.41.0


From 0ff9bba35a043267a2781c294f5832378cd6da54 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
Date: Fri, 12 Nov 2021 16:10:31 +1300
Subject: [PATCH 091/146] CVE-2020-25717: s3:auth: Fallback to a SID/UID based
 mapping if the named based lookup fails
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Before the CVE-2020-25717 fixes we had a fallback from
getpwnam('DOMAIN\user') to getpwnam('user') which was very dangerous and
unpredictable.

Now we do the fallback based on sid_to_uid() followed by
getpwuid() on the returned uid.

This obsoletes 'username map [script]' based workaround adviced
for CVE-2020-25717, when nss_winbindd is not used or
idmap_nss is actually used.

In future we may decide to prefer or only do the SID/UID based
lookup, but for now we want to keep this unchanged as much as possible.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>

[metze@samba.org moved the new logic into the fallback codepath only
 in order to avoid behavior changes as much as possible]
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Mon Nov 15 19:01:56 UTC 2021 on sn-devel-184

[abartlet@samba.org backported from commit 0a546be05295a7e4a552f9f4f0c74aeb2e9a0d6e
 as usage.py is not present in Samba 4.10]
---
 source3/auth/auth_util.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index c0e5cfd7fa8..b463059f259 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1837,7 +1837,9 @@ const struct auth_session_info *get_session_info_system(void)
 ***************************************************************************/
 
 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
-			      const char *username, char **found_username,
+			      const char *username,
+			      const struct dom_sid *sid,
+			      char **found_username,
 			      struct passwd **pwd,
 			      bool *username_was_mapped)
 {
@@ -1872,6 +1874,31 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
 	}
 
 	passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false);
+	if (!passwd && !*username_was_mapped) {
+		struct dom_sid_buf buf;
+		uid_t uid;
+		bool ok;
+
+		DBG_DEBUG("Failed to find authenticated user %s via "
+			  "getpwnam(), fallback to sid_to_uid(%s).\n",
+			  dom_user, dom_sid_str_buf(sid, &buf));
+
+		ok = sid_to_uid(sid, &uid);
+		if (!ok) {
+			DBG_ERR("Failed to convert SID %s to a UID (dom_user[%s])\n",
+				dom_sid_str_buf(sid, &buf), dom_user);
+			return NT_STATUS_NO_SUCH_USER;
+		}
+		passwd = getpwuid_alloc(mem_ctx, uid);
+		if (!passwd) {
+			DBG_ERR("Failed to find local account with UID %lld for SID %s (dom_user[%s])\n",
+				(long long)uid,
+				dom_sid_str_buf(sid, &buf),
+				dom_user);
+			return NT_STATUS_NO_SUCH_USER;
+		}
+		real_username = talloc_strdup(mem_ctx, passwd->pw_name);
+	}
 	if (!passwd) {
 		DEBUG(3, ("Failed to find authenticated user %s via "
 			  "getpwnam(), denying access.\n", dom_user));
@@ -2017,6 +2044,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
 	bool username_was_mapped;
 	struct passwd *pwd;
 	struct auth_serversupplied_info *result;
+	struct dom_sid sid;
 	TALLOC_CTX *tmp_ctx = talloc_stackframe();
 
 	/* 
@@ -2063,9 +2091,13 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
 
 	/* this call will try to create the user if necessary */
 
+	sid_copy(&sid, info3->base.domain_sid);
+	sid_append_rid(&sid, info3->base.rid);
+
 	nt_status = check_account(tmp_ctx,
 				  nt_domain,
 				  nt_username,
+				  &sid,
 				  &found_username,
 				  &pwd,
 				  &username_was_mapped);
-- 
2.41.0


From f035c041e42594bacfe7c3f4e5ea5d05399e1c5a Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 26 Nov 2021 10:57:17 +0100
Subject: [PATCH 092/146] CVE-2020-25717: s3-auth: fix MIT Realm regression

This looks like a regression introduced by the recent security fixes. This
commit should hopefully fixes it.

As a quick solution it might be possible to use the username map script based on
the example in https://bugzilla.samba.org/show_bug.cgi?id=14901#c0. We're not
sure this behaves identical, but it might work in the standalone server case.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14922

Reported-at: https://lists.samba.org/archive/samba/2021-November/238720.html

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Ralph Boehme <slow@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit 1e61de8306604a0d3858342df8a1d2412d8d418b)
---
 source3/auth/user_krb5.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c
index b8f37cbeee0..169bf563368 100644
--- a/source3/auth/user_krb5.c
+++ b/source3/auth/user_krb5.c
@@ -46,6 +46,7 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 	char *fuser = NULL;
 	char *unixuser = NULL;
 	struct passwd *pw = NULL;
+	bool may_retry = false;
 
 	DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name));
 
@@ -71,6 +72,7 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 		domain = realm;
 	} else {
 		domain = lp_workgroup();
+		may_retry = true;
 	}
 
 	fuser = talloc_asprintf(mem_ctx,
@@ -89,6 +91,13 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx,
 	*mapped_to_guest = false;
 
 	pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
+	if (may_retry && pw == NULL && !*is_mapped) {
+		fuser = talloc_strdup(mem_ctx, user);
+		if (!fuser) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true);
+	}
 	if (pw) {
 		if (!unixuser) {
 			return NT_STATUS_NO_MEMORY;
-- 
2.41.0


From 8b8d1b20b16381c305c23ce03a559b8c7de67f5d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Thu, 13 Jan 2022 16:48:01 +0100
Subject: [PATCH 093/146] CVE-2021-44142: libadouble: add defines for icon
 lengths

From https://www.ietf.org/rfc/rfc1740.txt

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914

Signed-off-by: Ralph Boehme <slow@samba.org>
---
 source3/modules/vfs_fruit.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index afad70ce180..3a35620bfe4 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -283,6 +283,8 @@ typedef enum {ADOUBLE_META, ADOUBLE_RSRC} adouble_type_t;
 #define ADEDLEN_MACFILEI        4
 #define ADEDLEN_PRODOSFILEI     8
 #define ADEDLEN_MSDOSFILEI      2
+#define ADEDLEN_ICONBW          128
+#define ADEDLEN_ICONCOL         1024
 #define ADEDLEN_DID             4
 #define ADEDLEN_PRIVDEV         8
 #define ADEDLEN_PRIVINO         8
-- 
2.41.0


From 3f2e9a6de36c086cff0bb3296f00c85a37a2653c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Sat, 20 Nov 2021 16:36:42 +0100
Subject: [PATCH 094/146] CVE-2021-44142: smbd: add Netatalk xattr used by
 vfs_fruit to the list of private Samba xattrs

This is an internal xattr that should not be user visible.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914

Signed-off-by: Ralph Boehme <slow@samba.org>
[slow@samba.org: conflict due to changed includes in source3/smbd/trans2.c]
---
 source3/smbd/trans2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index f8d987bbe63..406087c0419 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -176,6 +176,16 @@ void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
  Refuse to allow clients to overwrite our private xattrs.
 ****************************************************************************/
 
+/*
+ * Taken from vfs_fruit.c
+ */
+#define NETATALK_META_XATTR "org.netatalk.Metadata"
+#if defined(HAVE_ATTROPEN)
+#define AFPINFO_EA_NETATALK NETATALK_META_XATTR
+#else
+#define AFPINFO_EA_NETATALK "user." NETATALK_META_XATTR
+#endif
+
 bool samba_private_attr_name(const char *unix_ea_name)
 {
 	static const char * const prohibited_ea_names[] = {
@@ -183,6 +193,7 @@ bool samba_private_attr_name(const char *unix_ea_name)
 		SAMBA_XATTR_DOS_ATTRIB,
 		SAMBA_XATTR_MARKER,
 		XATTR_NTACL_NAME,
+		AFPINFO_EA_NETATALK,
 		NULL
 	};
 
-- 
2.41.0


From 00287584703e9e91e804e0f182bd844b7c436716 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Fri, 26 Nov 2021 07:19:32 +0100
Subject: [PATCH 095/146] CVE-2021-44142: libadouble: harden ad_unpack_xattrs()

This ensures ad_unpack_xattrs() is only called for an ad_type of ADOUBLE_RSRC,
which is used for parsing ._ AppleDouble sidecar files, and the buffer
ad->ad_data is AD_XATTR_MAX_HDR_SIZE bytes large which is a prerequisite for all
buffer out-of-bounds access checks in ad_unpack_xattrs().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914

Signed-off-by: Ralph Boehme <slow@samba.org>
---
 source3/modules/vfs_fruit.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 3a35620bfe4..76139e51047 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -728,14 +728,27 @@ static bool ad_pack(struct adouble *ad)
 static bool ad_unpack_xattrs(struct adouble *ad)
 {
 	struct ad_xattr_header *h = &ad->adx_header;
+	size_t bufsize = talloc_get_size(ad->ad_data);
 	const char *p = ad->ad_data;
 	uint32_t hoff;
 	uint32_t i;
 
+	if (ad->ad_type != ADOUBLE_RSRC) {
+		return false;
+	}
+
 	if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) {
 		return true;
 	}
 
+	/*
+	 * Ensure the buffer ad->ad_data was allocated by ad_alloc() for an
+	 * ADOUBLE_RSRC type (._ AppleDouble file on-disk).
+	 */
+	if (bufsize != AD_XATTR_MAX_HDR_SIZE) {
+		return false;
+	}
+
 	/* 2 bytes padding */
 	hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2;
 
@@ -985,11 +998,12 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
 		ad->ad_eid[eid].ade_len = len;
 	}
 
-	ok = ad_unpack_xattrs(ad);
-	if (!ok) {
-		return false;
+	if (ad->ad_type == ADOUBLE_RSRC) {
+		ok = ad_unpack_xattrs(ad);
+		if (!ok) {
+			return false;
+		}
 	}
-
 	return true;
 }
 
-- 
2.41.0


From 94141fa38e082e4ab50be6c2f79c8506e72bc274 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Thu, 25 Nov 2021 15:04:03 +0100
Subject: [PATCH 096/146] CVE-2021-44142: libadouble: add basic cmocka tests

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914

Signed-off-by: Ralph Boehme <slow@samba.org>
[slow@samba.org: conflict due to missing test in selftest/tests.py]
---
 selftest/knownfail.d/samba.unittests.adouble |   3 +
 selftest/tests.py                            |   2 +
 source3/lib/test_adouble.c                   | 393 +++++++++++++++++++
 source3/wscript_build                        |   5 +
 4 files changed, 403 insertions(+)
 create mode 100644 selftest/knownfail.d/samba.unittests.adouble
 create mode 100644 source3/lib/test_adouble.c

diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble
new file mode 100644
index 00000000000..8b0314f2fae
--- /dev/null
+++ b/selftest/knownfail.d/samba.unittests.adouble
@@ -0,0 +1,3 @@
+^samba.unittests.adouble.parse_abouble_finderinfo2\(none\)
+^samba.unittests.adouble.parse_abouble_finderinfo3\(none\)
+^samba.unittests.adouble.parse_abouble_date2\(none\)
diff --git a/selftest/tests.py b/selftest/tests.py
index e3f7d9acb4a..4bc4d301c4c 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -260,3 +260,5 @@ plantestsuite("samba.unittests.ntlm_check", "none",
               [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")])
 plantestsuite("samba.unittests.test_registry_regfio", "none",
               [os.path.join(bindir(), "default/source3/test_registry_regfio")])
+plantestsuite("samba.unittests.adouble", "none",
+              [os.path.join(bindir(), "test_adouble")])
diff --git a/source3/lib/test_adouble.c b/source3/lib/test_adouble.c
new file mode 100644
index 00000000000..667d2a7542e
--- /dev/null
+++ b/source3/lib/test_adouble.c
@@ -0,0 +1,393 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) 2021 Ralph Boehme <slow@samba.org>
+ *
+ * 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"
+extern NTSTATUS vfs_fruit_init(TALLOC_CTX *mem_ctx);
+
+#include "vfs_fruit.c"
+#include <cmocka.h>
+
+
+static int setup_talloc_context(void **state)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+
+	*state = frame;
+	return 0;
+}
+
+static int teardown_talloc_context(void **state)
+{
+	TALLOC_CTX *frame = *state;
+
+	TALLOC_FREE(frame);
+	return 0;
+}
+
+/*
+ * Basic and sane buffer.
+ */
+static uint8_t ad_basic[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x32,	/* offset */
+	0x00, 0x00, 0x00, 0x20,	/* length */
+	/* adentry 2: Resourcefork */
+	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
+	0x00, 0x00, 0x00, 0x52,	/* offset */
+	0xff, 0xff, 0xff, 0x00,	/* length */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ * An empty FinderInfo entry.
+ */
+static uint8_t ad_finderinfo1[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x52,	/* off: points at end of buffer */
+	0x00, 0x00, 0x00, 0x00,	/* len: 0, so off+len don't exceed bufferlen */
+	/* adentry 2: Resourcefork */
+	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
+	0x00, 0x00, 0x00, 0x52,	/* offset */
+	0xff, 0xff, 0xff, 0x00,	/* length */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ * A dangerous FinderInfo with correct length exceeding buffer by one byte.
+ */
+static uint8_t ad_finderinfo2[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x33,	/* off: points at beginng of data + 1 */
+	0x00, 0x00, 0x00, 0x20,	/* len: 32, so off+len exceeds bufferlen by 1 */
+	/* adentry 2: Resourcefork */
+	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
+	0x00, 0x00, 0x00, 0x52,	/* offset */
+	0xff, 0xff, 0xff, 0x00,	/* length */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+static uint8_t ad_finderinfo3[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x33,	/* off: points at beginng of data + 1 */
+	0x00, 0x00, 0x00, 0x1f,	/* len: 31, so off+len don't exceed buf */
+	/* adentry 2: Resourcefork */
+	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
+	0x00, 0x00, 0x00, 0x52,	/* offset */
+	0xff, 0xff, 0xff, 0x00,	/* length */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ * A dangerous name entry.
+ */
+static uint8_t ad_name[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x32,	/* offset */
+	0x00, 0x00, 0x00, 0x20,	/* length */
+	/* adentry 2: Name */
+	0x00, 0x00, 0x00, 0x03,	/* eid: Name */
+	0x00, 0x00, 0x00, 0x52,	/* off: points at end of buffer */
+	0x00, 0x00, 0x00, 0x01,	/* len: 1, so off+len exceeds bufferlen */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ * A empty ADEID_FILEDATESI entry.
+ */
+static uint8_t ad_date1[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x32,	/* offset */
+	0x00, 0x00, 0x00, 0x20,	/* length */
+	/* adentry 2: Dates */
+	0x00, 0x00, 0x00, 0x08,	/* eid: dates */
+	0x00, 0x00, 0x00, 0x52,	/* off: end of buffer */
+	0x00, 0x00, 0x00, 0x00,	/* len: 0, empty entry, valid */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/*
+ * A dangerous ADEID_FILEDATESI entry, invalid length.
+ */
+static uint8_t ad_date2[] = {
+	0x00, 0x05, 0x16, 0x07, /* Magic */
+	0x00, 0x02, 0x00, 0x00, /* Version */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x00, 0x00, 0x00, /* Filler */
+	0x00, 0x02,             /* Count */
+	/* adentry 1: FinderInfo */
+	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
+	0x00, 0x00, 0x00, 0x32,	/* offset */
+	0x00, 0x00, 0x00, 0x20,	/* length */
+	/* adentry 2: Dates */
+	0x00, 0x00, 0x00, 0x08,	/* eid: dates */
+	0x00, 0x00, 0x00, 0x43,	/* off: FinderInfo buf but one byte short */
+	0x00, 0x00, 0x00, 0x0f,	/* len: 15, so off+len don't exceed bufferlen */
+	/* FinderInfo data: 32 bytes */
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+static struct adouble *parse_adouble(TALLOC_CTX *mem_ctx,
+				     uint8_t *adbuf,
+				     size_t adsize,
+				     off_t filesize)
+{
+	struct adouble *ad = NULL;
+	bool ok;
+
+	ad = talloc_zero(mem_ctx, struct adouble);
+	ad->ad_data = talloc_zero_size(ad, adsize);
+	assert_non_null(ad);
+
+	memcpy(ad->ad_data, adbuf, adsize);
+
+	ok = ad_unpack(ad, 2, filesize);
+	if (!ok) {
+		return NULL;
+	}
+
+	return ad;
+}
+
+static void parse_abouble_basic(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+	char *p = NULL;
+
+	ad = parse_adouble(frame, ad_basic, sizeof(ad_basic), 0xffffff52);
+	assert_non_null(ad);
+
+	p = ad_get_entry(ad, ADEID_FINDERI);
+	assert_non_null(p);
+
+	return;
+}
+
+static void parse_abouble_finderinfo1(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+	char *p = NULL;
+
+	ad = parse_adouble(frame,
+			   ad_finderinfo1,
+			   sizeof(ad_finderinfo1),
+			   0xffffff52);
+	assert_non_null(ad);
+
+	p = ad_get_entry(ad, ADEID_FINDERI);
+	assert_null(p);
+
+	return;
+}
+
+static void parse_abouble_finderinfo2(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+
+	ad = parse_adouble(frame,
+			   ad_finderinfo2,
+			   sizeof(ad_finderinfo2),
+			   0xffffff52);
+	assert_null(ad);
+
+	return;
+}
+
+static void parse_abouble_finderinfo3(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+
+	ad = parse_adouble(frame,
+			   ad_finderinfo3,
+			   sizeof(ad_finderinfo3),
+			   0xffffff52);
+	assert_null(ad);
+
+	return;
+}
+
+static void parse_abouble_name(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+
+	ad = parse_adouble(frame, ad_name, sizeof(ad_name), 0x52);
+	assert_null(ad);
+
+	return;
+}
+
+static void parse_abouble_date1(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+	char *p = NULL;
+
+	ad = parse_adouble(frame, ad_date1, sizeof(ad_date1), 0x52);
+	assert_non_null(ad);
+
+	p = ad_get_entry(ad, ADEID_FILEDATESI);
+	assert_null(p);
+
+	return;
+}
+
+static void parse_abouble_date2(void **state)
+{
+	TALLOC_CTX *frame = *state;
+	struct adouble *ad = NULL;
+
+	ad = parse_adouble(frame, ad_date2, sizeof(ad_date2), 0x52);
+	assert_null(ad);
+
+	return;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+	const struct CMUnitTest tests[] = {
+		cmocka_unit_test(parse_abouble_basic),
+		cmocka_unit_test(parse_abouble_finderinfo1),
+		cmocka_unit_test(parse_abouble_finderinfo2),
+		cmocka_unit_test(parse_abouble_finderinfo3),
+		cmocka_unit_test(parse_abouble_name),
+		cmocka_unit_test(parse_abouble_date1),
+		cmocka_unit_test(parse_abouble_date2),
+	};
+
+	if (argc == 2) {
+		cmocka_set_test_filter(argv[1]);
+	}
+	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+
+	rc = cmocka_run_group_tests(tests,
+				    setup_talloc_context,
+				    teardown_talloc_context);
+
+	return rc;
+}
diff --git a/source3/wscript_build b/source3/wscript_build
index 26e251f442a..5230ae32934 100644
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -1080,6 +1080,11 @@ bld.SAMBA3_SUBSYSTEM('SPOOLSSD',
 
 ########################## BINARIES #################################
 
+bld.SAMBA3_BINARY('test_adouble',
+                 source='lib/test_adouble.c',
+                 deps='smbd_base STRING_REPLACE cmocka OFFLOAD_TOKEN',
+                 install=False)
+
 bld.SAMBA3_BINARY('smbd/smbd',
                  source='smbd/server.c smbd/smbd_cleanupd.c',
                  deps='''
-- 
2.41.0


From 5c1c2ea3dbe554f621014bb2b3133c0859dce2da Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Thu, 13 Jan 2022 17:03:02 +0100
Subject: [PATCH 097/146] CVE-2021-44142: libadouble: harden parsing code

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914

Signed-off-by: Ralph Boehme <slow@samba.org>
---
 selftest/knownfail.d/samba.unittests.adouble |   3 -
 source3/modules/vfs_fruit.c                  | 114 ++++++++++++++++---
 2 files changed, 100 insertions(+), 17 deletions(-)
 delete mode 100644 selftest/knownfail.d/samba.unittests.adouble

diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble
deleted file mode 100644
index 8b0314f2fae..00000000000
--- a/selftest/knownfail.d/samba.unittests.adouble
+++ /dev/null
@@ -1,3 +0,0 @@
-^samba.unittests.adouble.parse_abouble_finderinfo2\(none\)
-^samba.unittests.adouble.parse_abouble_finderinfo3\(none\)
-^samba.unittests.adouble.parse_abouble_date2\(none\)
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 76139e51047..17e97d15bdb 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -540,6 +540,94 @@ static AfpInfo *afpinfo_new(TALLOC_CTX *ctx);
 static ssize_t afpinfo_pack(const AfpInfo *ai, char *buf);
 static AfpInfo *afpinfo_unpack(TALLOC_CTX *ctx, const void *data);
 
+/*
+ * All entries besides FinderInfo and resource fork must fit into the
+ * buffer. FinderInfo is special as it may be larger then the default 32 bytes
+ * if it contains marshalled xattrs, which we will fixup that in
+ * ad_convert(). The first 32 bytes however must also be part of the buffer.
+ *
+ * The resource fork is never accessed directly by the ad_data buf.
+ */
+static bool ad_entry_check_size(uint32_t eid,
+				size_t bufsize,
+				uint32_t off,
+				uint32_t got_len)
+{
+	struct {
+		off_t expected_len;
+		bool fixed_size;
+		bool minimum_size;
+	} ad_checks[] = {
+		[ADEID_DFORK] = {-1, false, false}, /* not applicable */
+		[ADEID_RFORK] = {-1, false, false}, /* no limit */
+		[ADEID_NAME] = {ADEDLEN_NAME, false, false},
+		[ADEID_COMMENT] = {ADEDLEN_COMMENT, false, false},
+		[ADEID_ICONBW] = {ADEDLEN_ICONBW, true, false},
+		[ADEID_ICONCOL] = {ADEDLEN_ICONCOL, false, false},
+		[ADEID_FILEI] = {ADEDLEN_FILEI, true, false},
+		[ADEID_FILEDATESI] = {ADEDLEN_FILEDATESI, true, false},
+		[ADEID_FINDERI] = {ADEDLEN_FINDERI, false, true},
+		[ADEID_MACFILEI] = {ADEDLEN_MACFILEI, true, false},
+		[ADEID_PRODOSFILEI] = {ADEDLEN_PRODOSFILEI, true, false},
+		[ADEID_MSDOSFILEI] = {ADEDLEN_MSDOSFILEI, true, false},
+		[ADEID_SHORTNAME] = {ADEDLEN_SHORTNAME, false, false},
+		[ADEID_AFPFILEI] = {ADEDLEN_AFPFILEI, true, false},
+		[ADEID_DID] = {ADEDLEN_DID, true, false},
+		[ADEID_PRIVDEV] = {ADEDLEN_PRIVDEV, true, false},
+		[ADEID_PRIVINO] = {ADEDLEN_PRIVINO, true, false},
+		[ADEID_PRIVSYN] = {ADEDLEN_PRIVSYN, true, false},
+		[ADEID_PRIVID] = {ADEDLEN_PRIVID, true, false},
+	};
+
+	if (eid >= ADEID_MAX) {
+		return false;
+	}
+	if (got_len == 0) {
+		/* Entry present, but empty, allow */
+		return true;
+	}
+	if (ad_checks[eid].expected_len == 0) {
+		/*
+		 * Shouldn't happen: implicitly initialized to zero because
+		 * explicit initializer missing.
+		 */
+		return false;
+	}
+	if (ad_checks[eid].expected_len == -1) {
+		/* Unused or no limit */
+		return true;
+	}
+	if (ad_checks[eid].fixed_size) {
+		if (ad_checks[eid].expected_len != got_len) {
+			/* Wrong size fo fixed size entry. */
+			return false;
+		}
+	} else {
+		if (ad_checks[eid].minimum_size) {
+			if (got_len < ad_checks[eid].expected_len) {
+				/*
+				 * Too small for variable sized entry with
+				 * minimum size.
+				 */
+				return false;
+			}
+		} else {
+			if (got_len > ad_checks[eid].expected_len) {
+				/* Too big for variable sized entry. */
+				return false;
+			}
+		}
+	}
+	if (off + got_len < off) {
+		/* wrap around */
+		return false;
+	}
+	if (off + got_len > bufsize) {
+		/* overflow */
+		return false;
+	}
+	return true;
+}
 
 /**
  * Return a pointer to an AppleDouble entry
@@ -548,8 +636,15 @@ static AfpInfo *afpinfo_unpack(TALLOC_CTX *ctx, const void *data);
  **/
 static char *ad_get_entry(const struct adouble *ad, int eid)
 {
+	size_t bufsize = talloc_get_size(ad->ad_data);
 	off_t off = ad_getentryoff(ad, eid);
 	size_t len = ad_getentrylen(ad, eid);
+	bool valid;
+
+	valid = ad_entry_check_size(eid, bufsize, off, len);
+	if (!valid) {
+		return NULL;
+	}
 
 	if (off == 0 || len == 0) {
 		return NULL;
@@ -935,20 +1030,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
 			return false;
 		}
 
-		/*
-		 * All entries besides FinderInfo and resource fork
-		 * must fit into the buffer. FinderInfo is special as
-		 * it may be larger then the default 32 bytes (if it
-		 * contains marshalled xattrs), but we will fixup that
-		 * in ad_convert(). And the resource fork is never
-		 * accessed directly by the ad_data buf (also see
-		 * comment above) anyway.
-		 */
-		if ((eid != ADEID_RFORK) &&
-		    (eid != ADEID_FINDERI) &&
-		    ((off + len) > bufsize)) {
-			DEBUG(1, ("bogus eid %d: off: %" PRIu32 ", len: %" PRIu32 "\n",
-				  eid, off, len));
+		ok = ad_entry_check_size(eid, bufsize, off, len);
+		if (!ok) {
+			DBG_ERR("bogus eid [%"PRIu32"] bufsize [%zu] "
+				"off [%"PRIu32"] len [%"PRIu32"]\n",
+				eid, bufsize, off, len);
 			return false;
 		}
 
-- 
2.41.0


From 2c1f15a39367493733e4d275c3709a6497225917 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs@samba.org>
Date: Fri, 5 Mar 2021 15:48:29 -0700
Subject: [PATCH 098/146] winbind: Only use unixid2sid mapping when module
 reports ID_MAPPED

Only consider a mapping to be valid when the idmap module reports
ID_MAPPED. Otherwise return the null SID.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14663

Signed-off-by: Christof Schmitt <cs@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit db2afa57e4aa926b478db1be4d693edbdf4d2a23)
(cherry picked from commit 3aa06edf38bc4002f031476baa50712fd1a67f4d)
---
 source3/winbindd/winbindd_dual_srv.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 0842241e02e..94331163006 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -275,8 +275,10 @@ NTSTATUS _wbint_UnixIDs2Sids(struct pipes_struct *p,
 	}
 
 	for (i=0; i<r->in.num_ids; i++) {
-		r->out.xids[i] = maps[i]->xid;
-		sid_copy(&r->out.sids[i], maps[i]->sid);
+		if (maps[i]->status == ID_MAPPED) {
+			r->out.xids[i] = maps[i]->xid;
+			sid_copy(&r->out.sids[i], maps[i]->sid);
+		}
 	}
 
 	TALLOC_FREE(maps);
-- 
2.41.0


From 754ece447c2dea8cccbe8740df5aff75dca7b646 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs@samba.org>
Date: Fri, 5 Mar 2021 16:01:13 -0700
Subject: [PATCH 099/146] idmap_rfc2307: Do not return SID from unixids_to_sids
 on type mismatch

The call to winbind_lookup_name already wrote the result in the id_map
array. The later check for the type detected a mismatch, but that did
not remove the SID from the result struct.

Change this by first assigning the SID to a temporary variable and only
write it to the id_map array after the type checks.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14663

Signed-off-by: Christof Schmitt <cs@samba.org>
(cherry picked from commit 79dd4b133c37451c98fe7f7c45da881e89e91ffc)
(cherry picked from commit af37d5abae924d095e7b35620d850cf1f19021c4)
---
 source3/winbindd/idmap_rfc2307.c     | 4 +++-
 source3/winbindd/winbindd_dual_srv.c | 2 ++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/idmap_rfc2307.c b/source3/winbindd/idmap_rfc2307.c
index e3bf58d8165..2fffaec6cca 100644
--- a/source3/winbindd/idmap_rfc2307.c
+++ b/source3/winbindd/idmap_rfc2307.c
@@ -228,6 +228,7 @@ static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
 
 	for (i = 0; i < count; i++) {
 		char *name;
+		struct dom_sid sid;
 		enum lsa_SidType lsa_type;
 		struct id_map *map;
 		uint32_t id;
@@ -276,7 +277,7 @@ static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
 		   the following call will not recurse so this is safe */
 		(void)winbind_on();
 		/* Lookup name from PDC using lsa_lookup_names() */
-		b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
+		b = winbind_lookup_name(dom_name, name, &sid, &lsa_type);
 		(void)winbind_off();
 
 		if (!b) {
@@ -300,6 +301,7 @@ static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
 		}
 
 		map->status = ID_MAPPED;
+		sid_copy(map->sid, &sid);
 	}
 }
 
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 94331163006..34375b3858f 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -278,6 +278,8 @@ NTSTATUS _wbint_UnixIDs2Sids(struct pipes_struct *p,
 		if (maps[i]->status == ID_MAPPED) {
 			r->out.xids[i] = maps[i]->xid;
 			sid_copy(&r->out.sids[i], maps[i]->sid);
+		} else {
+			r->out.sids[i] = (struct dom_sid) { 0 };
 		}
 	}
 
-- 
2.41.0


From f831d80dde35ba0e29014a9e4f34cb3ce6eb6161 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs@samba.org>
Date: Fri, 5 Mar 2021 16:07:54 -0700
Subject: [PATCH 100/146] idmap_nss: Do not return SID from unixids_to_sids on
 type mismatch

The call to winbind_lookup_name already wrote the result in the id_map
array. The later check for the type detected a mismatch, but that did
not remove the SID from the result struct.

Change this by first assigning the SID to a temporary variable and only
write it to the id_map array after the type checks.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14663

Signed-off-by: Christof Schmitt <cs@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>

Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Thu Mar 11 08:38:41 UTC 2021 on sn-devel-184

(cherry picked from commit 0e789ba1802ca22e5a01abd6e93ef66cd45566a7)
(cherry picked from commit 3f366878d33cf977230137021f6376936b2a1862)
---
 source3/winbindd/idmap_nss.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c
index 243b67ccafd..e4bf1923786 100644
--- a/source3/winbindd/idmap_nss.c
+++ b/source3/winbindd/idmap_nss.c
@@ -56,6 +56,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 		struct passwd *pw;
 		struct group *gr;
 		const char *name;
+		struct dom_sid sid;
 		enum lsa_SidType type;
 		bool ret;
 
@@ -87,7 +88,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 		   the following call will not recurse so this is safe */
 		(void)winbind_on();
 		/* Lookup name from PDC using lsa_lookup_names() */
-		ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
+		ret = winbind_lookup_name(dom->name, name, &sid, &type);
 		(void)winbind_off();
 
 		if (!ret) {
@@ -100,6 +101,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 		switch (type) {
 		case SID_NAME_USER:
 			if (ids[i]->xid.type == ID_TYPE_UID) {
+				sid_copy(ids[i]->sid, &sid);
 				ids[i]->status = ID_MAPPED;
 			}
 			break;
@@ -108,6 +110,7 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 		case SID_NAME_ALIAS:
 		case SID_NAME_WKN_GRP:
 			if (ids[i]->xid.type == ID_TYPE_GID) {
+				sid_copy(ids[i]->sid, &sid);
 				ids[i]->status = ID_MAPPED;
 			}
 			break;
-- 
2.41.0


From 4ef3d95fb680cf278e68b6794459ff7bce1489aa Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Tue, 23 Nov 2021 15:48:57 +0100
Subject: [PATCH 101/146] s3:winbind: Fix possible NULL pointer dereference

BUG: https://bugzilla.redhat.com/show_bug.cgi?id=2019888

Signed-off-by: Andreas Schneider <asn@samba.org>
Rewiewed-by: Jeremy Allison <jra@samba.org>

Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Mon Nov 29 19:40:50 UTC 2021 on sn-devel-184

(cherry picked from commit cbf312f02bc86f9325fb89f6f5441bc61fd3974f)
---
 source3/winbindd/winbindd_util.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 04e79e70f6b..d1bd81b2372 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1691,6 +1691,9 @@ char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
 	}
 
 	tmp_user = talloc_strdup(mem_ctx, user);
+	if (tmp_user == NULL) {
+		return NULL;
+	}
 	if (!strlower_m(tmp_user)) {
 		TALLOC_FREE(tmp_user);
 		return NULL;
-- 
2.41.0


From 95c9485bb600e965f24712534850d1a7fd325c44 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Tue, 6 Dec 2022 16:00:36 +0100
Subject: [PATCH 102/146] CVE-2022-38023 docs-xml: improve wording for several
 options: "takes precedence" -> "overrides"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 8ec62694a94c346e6ba8f3144a417c9984a1c8b9)
---
 docs-xml/smbdotconf/logon/rejectmd5clients.xml   | 2 +-
 docs-xml/smbdotconf/security/serverschannel.xml  | 2 +-
 docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 2 +-
 docs-xml/smbdotconf/winbind/requirestrongkey.xml | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
index 41684ef1080..0bb9f6f6c8e 100644
--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml
+++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
@@ -10,7 +10,7 @@
 	<para>You can set this to yes if all domain members support aes.
 	This will prevent downgrade attacks.</para>
 
-	<para>This option takes precedence to the 'allow nt4 crypto' option.</para>
+	<para>This option overrides the 'allow nt4 crypto' option.</para>
 </description>
 
 <value type="default">no</value>
diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml
index b682d086f76..79e4e73a95c 100644
--- a/docs-xml/smbdotconf/security/serverschannel.xml
+++ b/docs-xml/smbdotconf/security/serverschannel.xml
@@ -59,7 +59,7 @@
 	See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497
     </para>
 
-    <para>This option takes precedence to the <smbconfoption name="server schannel"/> option.</para>
+    <para>This option overrides the <smbconfoption name="server schannel"/> option.</para>
 
     <programlisting>
 	server require schannel:LEGACYCOMPUTER1$ = no
diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
index 37656293aa4..151b4676c57 100644
--- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
+++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
@@ -15,7 +15,7 @@
 	<para>The behavior can be controlled per netbios domain
 	by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option.</para>
 
-	<para>This option takes precedence to the <smbconfoption name="require strong key"/> option.</para>
+	<para>This option overrides the <smbconfoption name="require strong key"/> option.</para>
 </description>
 
 <value type="default">no</value>
diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml
index 4db62bfb02d..b17620ec8f1 100644
--- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml
+++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml
@@ -19,7 +19,7 @@
 
 	<para>This option yields precedence to the <smbconfoption name="reject md5 servers"/> option.</para>
 
-	<para>This option takes precedence to the <smbconfoption name="client schannel"/> option.</para>
+	<para>This option overrides the <smbconfoption name="client schannel"/> option.</para>
 </description>
 
 <value type="default">yes</value>
-- 
2.41.0


From d6ab8377e55e4bda76c86de9bba1ddee30361481 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow@samba.org>
Date: Tue, 6 Dec 2022 16:05:26 +0100
Subject: [PATCH 103/146] CVE-2022-38023 docs-xml: improve wording for several
 options: "yields precedence" -> "is over-riden"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 830e865ba5648f6520bc552ffd71b61f754b8251)
---
 docs-xml/smbdotconf/logon/allownt4crypto.xml                 | 2 +-
 docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml | 2 +-
 docs-xml/smbdotconf/security/clientschannel.xml              | 2 +-
 docs-xml/smbdotconf/security/serverschannel.xml              | 2 +-
 docs-xml/smbdotconf/winbind/requirestrongkey.xml             | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml
index 03dc8fa93f7..06afcef73b1 100644
--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml
+++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml
@@ -18,7 +18,7 @@
 
 	<para>"allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks.</para>
 
-	<para>This option yields precedence to the 'reject md5 clients' option.</para>
+	<para>This option is over-ridden by the 'reject md5 clients' option.</para>
 </description>
 
 <value type="default">no</value>
diff --git a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
index 03531adbfb3..8bccab391cc 100644
--- a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
+++ b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
@@ -15,7 +15,7 @@
 	<para>The behavior can be overwritten per interface name (e.g. lsarpc, netlogon, samr, srvsvc,
 	winreg, wkssvc ...) by using 'allow dcerpc auth level connect:interface = yes' as option.</para>
 
-	<para>This option yields precedence to the implementation specific restrictions.
+	<para>This option is over-ridden by the implementation specific restrictions.
 	E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY.
 	The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY.
 	</para>
diff --git a/docs-xml/smbdotconf/security/clientschannel.xml b/docs-xml/smbdotconf/security/clientschannel.xml
index 5b07da95050..d124ad48181 100644
--- a/docs-xml/smbdotconf/security/clientschannel.xml
+++ b/docs-xml/smbdotconf/security/clientschannel.xml
@@ -23,7 +23,7 @@
     <para>Note that for active directory domains this is hardcoded to
     <smbconfoption name="client schannel">yes</smbconfoption>.</para>
 
-    <para>This option yields precedence to the <smbconfoption name="require strong key"/> option.</para>
+    <para>This option is over-ridden by the <smbconfoption name="require strong key"/> option.</para>
 </description>
 <value type="default">yes</value>
 <value type="example">auto</value>
diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml
index 79e4e73a95c..3e66df1c203 100644
--- a/docs-xml/smbdotconf/security/serverschannel.xml
+++ b/docs-xml/smbdotconf/security/serverschannel.xml
@@ -23,7 +23,7 @@
     <para>If you still have legacy domain members use the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.
     </para>
 
-    <para>This option yields precedence to the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.</para>
+    <para>This option is over-ridden by the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.</para>
 
 </description>
 
diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml
index b17620ec8f1..9c1c1d7af14 100644
--- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml
+++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml
@@ -17,7 +17,7 @@
 
 	<para>Note for active directory domain this option is hardcoded to 'yes'</para>
 
-	<para>This option yields precedence to the <smbconfoption name="reject md5 servers"/> option.</para>
+	<para>This option is over-ridden by the <smbconfoption name="reject md5 servers"/> option.</para>
 
 	<para>This option overrides the <smbconfoption name="client schannel"/> option.</para>
 </description>
-- 
2.41.0


From 976080e72039b68ab66b757f1c3cb258eaca23df Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 14:46:59 +0100
Subject: [PATCH 104/146] CVE-2022-38023 libcli/auth: pass lp_ctx to
 netlogon_creds_cli_set_global_db()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 992f39a2c8a58301ceeb965f401e29cd64c5a209)
---
 libcli/auth/netlogon_creds_cli.c           | 3 ++-
 libcli/auth/netlogon_creds_cli.h           | 2 +-
 source3/rpc_client/cli_netlogon.c          | 2 +-
 source3/utils/destroy_netlogon_creds_cli.c | 2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index 0f6ca11ff96..c9873a5748e 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -201,7 +201,8 @@ static NTSTATUS netlogon_creds_cli_context_common(
 
 static struct db_context *netlogon_creds_cli_global_db;
 
-NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db)
+NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx,
+					  struct db_context **db)
 {
 	if (netlogon_creds_cli_global_db != NULL) {
 		return NT_STATUS_INVALID_PARAMETER_MIX;
diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h
index 56a2dd9bc77..2ce5de9d305 100644
--- a/libcli/auth/netlogon_creds_cli.h
+++ b/libcli/auth/netlogon_creds_cli.h
@@ -31,7 +31,7 @@ struct messaging_context;
 struct dcerpc_binding_handle;
 struct db_context;
 
-NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db);
+NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struct db_context **db);
 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx);
 void netlogon_creds_cli_close_global_db(void);
 
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index f073f0d925e..b784064f17e 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -76,7 +76,7 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void)
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = netlogon_creds_cli_set_global_db(&global_db);
+	status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db);
 	TALLOC_FREE(frame);
 	if (!NT_STATUS_IS_OK(status)) {
 		return status;
diff --git a/source3/utils/destroy_netlogon_creds_cli.c b/source3/utils/destroy_netlogon_creds_cli.c
index 137ac8393e7..95a650f4654 100644
--- a/source3/utils/destroy_netlogon_creds_cli.c
+++ b/source3/utils/destroy_netlogon_creds_cli.c
@@ -83,7 +83,7 @@ int main(int argc, const char *argv[])
 		goto done;
 	}
 
-	status = netlogon_creds_cli_set_global_db(&global_db);
+	status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db);
 	if (!NT_STATUS_IS_OK(status)) {
 		fprintf(stderr,
 			"netlogon_creds_cli_set_global_db failed: %s\n",
-- 
2.41.0


From dfe17c3453980d53445a2cc6221cb8728fc9e3cf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 14:47:33 +0100
Subject: [PATCH 105/146] CVE-2022-38023 libcli/auth: add/use
 netlogon_creds_cli_warn_options()

This warns the admin about insecure options

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

(similar to commit 7e7adf86e59e8a673fbe87de46cef0d62221e800)
[jsutton@samba.org Replaced call to tevent_cached_getpid() with one to
 getpid()]
---
 libcli/auth/netlogon_creds_cli.c | 66 ++++++++++++++++++++++++++++++++
 libcli/auth/netlogon_creds_cli.h |  2 +
 2 files changed, 68 insertions(+)

diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index c9873a5748e..20a3da5060f 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -204,6 +204,8 @@ static struct db_context *netlogon_creds_cli_global_db;
 NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx,
 					  struct db_context **db)
 {
+	netlogon_creds_cli_warn_options(lp_ctx);
+
 	if (netlogon_creds_cli_global_db != NULL) {
 		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
@@ -218,6 +220,8 @@ NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx)
 	struct db_context *global_db;
 	int hash_size, tdb_flags;
 
+	netlogon_creds_cli_warn_options(lp_ctx);
+
 	if (netlogon_creds_cli_global_db != NULL) {
 		return NT_STATUS_OK;
 	}
@@ -258,6 +262,68 @@ void netlogon_creds_cli_close_global_db(void)
 	TALLOC_FREE(netlogon_creds_cli_global_db);
 }
 
+void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx)
+{
+	bool global_reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx);
+	bool global_require_strong_key = lpcfg_require_strong_key(lp_ctx);
+	int global_client_schannel = lpcfg_client_schannel(lp_ctx);
+	bool global_seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx);
+	static bool warned_global_reject_md5_servers = false;
+	static bool warned_global_require_strong_key = false;
+	static bool warned_global_client_schannel = false;
+	static bool warned_global_seal_secure_channel = false;
+	static int warned_global_pid = 0;
+	int current_pid = getpid();
+
+	if (warned_global_pid != current_pid) {
+		warned_global_reject_md5_servers = false;
+		warned_global_require_strong_key = false;
+		warned_global_client_schannel = false;
+		warned_global_seal_secure_channel = false;
+		warned_global_pid = current_pid;
+	}
+
+	if (!global_reject_md5_servers && !warned_global_reject_md5_servers) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		DBG_ERR("CVE-2022-38023 (and others): "
+			"Please configure 'reject md5 servers = yes' (the default), "
+			"See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_reject_md5_servers = true;
+	}
+
+	if (!global_require_strong_key && !warned_global_require_strong_key) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		DBG_ERR("CVE-2022-38023 (and others): "
+			"Please configure 'require strong key = yes' (the default), "
+			"See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_require_strong_key = true;
+	}
+
+	if (global_client_schannel != true && !warned_global_client_schannel) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		DBG_ERR("CVE-2022-38023 (and others): "
+			"Please configure 'client schannel = yes' (the default), "
+			"See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_client_schannel = true;
+	}
+
+	if (!global_seal_secure_channel && !warned_global_seal_secure_channel) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		DBG_ERR("CVE-2022-38023 (and others): "
+			"Please configure 'winbind sealed pipes = yes' (the default), "
+			"See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_seal_secure_channel = true;
+	}
+}
+
 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
 				struct messaging_context *msg_ctx,
 				const char *client_account,
diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h
index 2ce5de9d305..e4e0232e92f 100644
--- a/libcli/auth/netlogon_creds_cli.h
+++ b/libcli/auth/netlogon_creds_cli.h
@@ -35,6 +35,8 @@ NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struc
 NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx);
 void netlogon_creds_cli_close_global_db(void);
 
+void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx);
+
 NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
 				struct messaging_context *msg_ctx,
 				const char *client_account,
-- 
2.41.0


From 75c44fdccf18bfa34530f05937e8e3305b2c927e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 16:16:05 +0100
Subject: [PATCH 106/146] CVE-2022-38023 s3:net: add and use
 net_warn_member_options() helper

This makes sure domain member related 'net' commands print warnings
about unsecure smb.conf options.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 1fdf1d55a5dd550bdb16d037b5dc995c33c1a67a)
---
 source3/utils/net.c       |  6 ++++++
 source3/utils/net_ads.c   | 14 ++++++++++++++
 source3/utils/net_dom.c   |  2 ++
 source3/utils/net_join.c  |  2 ++
 source3/utils/net_proto.h |  2 ++
 source3/utils/net_rpc.c   | 10 ++++++++++
 source3/utils/net_util.c  | 15 +++++++++++++++
 7 files changed, 51 insertions(+)

diff --git a/source3/utils/net.c b/source3/utils/net.c
index 8350e8c0967..c17dd972c3f 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -83,6 +83,8 @@ enum netr_SchannelType get_sec_channel_type(const char *param)
 
 static int net_changetrustpw(struct net_context *c, int argc, const char **argv)
 {
+	net_warn_member_options();
+
 	if (net_ads_check_our_domain(c) == 0)
 		return net_ads_changetrustpw(c, argc, argv);
 
@@ -110,6 +112,8 @@ static int net_primarytrust_dumpinfo(struct net_context *c, int argc,
 		return 1;
 	}
 
+	net_warn_member_options();
+
 	if (c->opt_stdin) {
 		set_line_buffering(stdin);
 		set_line_buffering(stdout);
@@ -185,6 +189,8 @@ static int net_changesecretpw(struct net_context *c, int argc,
 		return 1;
 	}
 
+	net_warn_member_options();
+
 	if(c->opt_force) {
 		struct secrets_domain_info1 *info = NULL;
 		struct secrets_domain_info1_change *prev = NULL;
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 3cf8fbbf7c8..32a7b2d7f7f 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1290,6 +1290,8 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
 		return -1;
 	}
@@ -1431,6 +1433,8 @@ static NTSTATUS net_ads_join_ok(struct net_context *c)
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
+	net_warn_member_options();
+
 	net_use_krb_machine_account(c);
 
 	get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
@@ -1461,6 +1465,8 @@ int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	/* Display success or failure */
 	status = net_ads_join_ok(c);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -1846,6 +1852,8 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	if (c->display_usage)
 		return net_ads_join_usage(c, argc, argv);
 
+	net_warn_member_options();
+
 	if (!modify_config) {
 
 		werr = check_ads_config();
@@ -2732,6 +2740,8 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
 		return -1;
 	}
 
+	net_warn_member_options();
+
 	net_use_krb_machine_account(c);
 
 	use_in_memory_ccache();
@@ -3001,6 +3011,8 @@ static int net_ads_keytab_add(struct net_context *c,
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	d_printf(_("Processing principals to add...\n"));
 	if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
 		return -1;
@@ -3040,6 +3052,8 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
 		return -1;
 	}
diff --git a/source3/utils/net_dom.c b/source3/utils/net_dom.c
index 1e45c59220c..db6e34e52de 100644
--- a/source3/utils/net_dom.c
+++ b/source3/utils/net_dom.c
@@ -154,6 +154,8 @@ static int net_dom_join(struct net_context *c, int argc, const char **argv)
 		return net_dom_usage(c, argc, argv);
 	}
 
+	net_warn_member_options();
+
 	if (c->opt_host) {
 		server_name = c->opt_host;
 	}
diff --git a/source3/utils/net_join.c b/source3/utils/net_join.c
index 1493dff74d7..f67f08f79a8 100644
--- a/source3/utils/net_join.c
+++ b/source3/utils/net_join.c
@@ -39,6 +39,8 @@ int net_join(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	if (net_ads_check_our_domain(c) == 0) {
 		if (net_ads_join(c, argc, argv) == 0)
 			return 0;
diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h
index 22fe39e0f1c..38581a796cb 100644
--- a/source3/utils/net_proto.h
+++ b/source3/utils/net_proto.h
@@ -423,6 +423,8 @@ int net_run_function(struct net_context *c, int argc, const char **argv,
 		      const char *whoami, struct functable *table);
 void net_display_usage_from_functable(struct functable *table);
 
+void net_warn_member_options(void);
+
 const char *net_share_type_str(int num_type);
 
 NTSTATUS net_scan_dc(struct net_context *c,
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index f2d63d2af65..52c2ec37a89 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -370,6 +370,8 @@ static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	mem_ctx = talloc_init("net_rpc_oldjoin");
 	if (!mem_ctx) {
 		return -1;
@@ -489,6 +491,8 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	mem_ctx = talloc_init("net_rpc_testjoin");
 	if (!mem_ctx) {
 		return -1;
@@ -563,6 +567,8 @@ static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **a
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	mem_ctx = talloc_init("net_rpc_join_newstyle");
 	if (!mem_ctx) {
 		return -1;
@@ -684,6 +690,8 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv)
 		return -1;
 	}
 
+	net_warn_member_options();
+
 	if (strlen(lp_netbios_name()) > 15) {
 		d_printf(_("Our netbios name can be at most 15 chars long, "
 			   "\"%s\" is %u chars long\n"),
@@ -814,6 +822,8 @@ int net_rpc_info(struct net_context *c, int argc, const char **argv)
 		return 0;
 	}
 
+	net_warn_member_options();
+
 	return run_rpc_command(c, NULL, &ndr_table_samr,
 			       NET_FLAGS_PDC, rpc_info_internals,
 			       argc, argv);
diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c
index a84b4f5500e..94a8dc9defe 100644
--- a/source3/utils/net_util.c
+++ b/source3/utils/net_util.c
@@ -29,6 +29,8 @@
 #include "secrets.h"
 #include "../libcli/security/security.h"
 #include "libsmb/libsmb.h"
+#include "libcli/auth/netlogon_creds_cli.h"
+#include "lib/param/param.h"
 
 NTSTATUS net_rpc_lookup_name(struct net_context *c,
 			     TALLOC_CTX *mem_ctx, struct cli_state *cli,
@@ -534,6 +536,19 @@ void net_display_usage_from_functable(struct functable *table)
 	}
 }
 
+void net_warn_member_options(void)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct loadparm_context *lp_ctx = NULL;
+
+	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+	if (lp_ctx != NULL) {
+		netlogon_creds_cli_warn_options(lp_ctx);
+	}
+
+	TALLOC_FREE(frame);
+}
+
 const char *net_share_type_str(int num_type)
 {
 	switch(num_type) {
-- 
2.41.0


From 9d7eba489e7f798dd3115439da1bc92a87059ce1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 14:59:36 +0100
Subject: [PATCH 107/146] CVE-2022-38023 s3:winbindd: also allow per domain
 "winbind sealed pipes:DOMAIN" and "require strong key:DOMAIN"

This avoids advising insecure defaults for the global options.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit d60828f6391307a59abaa02b72b6a8acf66b2fef)
---
 source3/winbindd/winbindd_cm.c | 41 +++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 502331f7260..1a8017cf4cc 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -2734,6 +2734,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	struct netlogon_creds_cli_context *p_creds;
 	struct cli_credentials *creds = NULL;
 	bool retry = false; /* allow one retry attempt for expired session */
+	bool sealed_pipes = true;
+	bool strong_key = true;
 
 	if (sid_check_is_our_sam(&domain->sid)) {
 		if (domain->rodc == false || need_rw_dc == false) {
@@ -2907,14 +2909,24 @@ retry:
 
  anonymous:
 
+	sealed_pipes = lp_winbind_sealed_pipes();
+	sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
+				    domain->name,
+				    sealed_pipes);
+	strong_key = lp_require_strong_key();
+	strong_key = lp_parm_bool(-1, "require strong key",
+				  domain->name,
+				  strong_key);
+
 	/* Finally fall back to anonymous. */
-	if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
+	if (sealed_pipes || strong_key) {
 		status = NT_STATUS_DOWNGRADE_DETECTED;
 		DEBUG(1, ("Unwilling to make SAMR connection to domain %s "
 			  "without connection level security, "
-			  "must set 'winbind sealed pipes = false' and "
-			  "'require strong key = false' to proceed: %s\n",
-			  domain->name, nt_errstr(status)));
+			  "must set 'winbind sealed pipes:%s = false' and "
+			  "'require strong key:%s = false' to proceed: %s\n",
+			  domain->name, domain->name, domain->name,
+			  nt_errstr(status)));
 		goto done;
 	}
 	status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr,
@@ -3061,6 +3073,8 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 	struct netlogon_creds_cli_context *p_creds;
 	struct cli_credentials *creds = NULL;
 	bool retry = false; /* allow one retry attempt for expired session */
+	bool sealed_pipes = true;
+	bool strong_key = true;
 
 retry:
 	result = init_dc_connection_rpc(domain, false);
@@ -3216,13 +3230,24 @@ retry:
 		goto done;
 	}
 
-	if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
+	sealed_pipes = lp_winbind_sealed_pipes();
+	sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes",
+				    domain->name,
+				    sealed_pipes);
+	strong_key = lp_require_strong_key();
+	strong_key = lp_parm_bool(-1, "require strong key",
+				  domain->name,
+				  strong_key);
+
+	/* Finally fall back to anonymous. */
+	if (sealed_pipes || strong_key) {
 		result = NT_STATUS_DOWNGRADE_DETECTED;
 		DEBUG(1, ("Unwilling to make LSA connection to domain %s "
 			  "without connection level security, "
-			  "must set 'winbind sealed pipes = false' and "
-			  "'require strong key = false' to proceed: %s\n",
-			  domain->name, nt_errstr(result)));
+			  "must set 'winbind sealed pipes:%s = false' and "
+			  "'require strong key:%s = false' to proceed: %s\n",
+			  domain->name, domain->name, domain->name,
+			  nt_errstr(result)));
 		goto done;
 	}
 
-- 
2.41.0


From b310b2672f80a717188675b6c762d184436a190c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 24 Nov 2022 18:22:23 +0100
Subject: [PATCH 108/146] CVE-2022-38023 docs-xml/smbdotconf: change 'reject
 md5 servers' default to yes

AES is supported by Windows >= 2008R2 and Samba >= 4.0 so there's no
reason to allow md5 servers by default.

Note the change in netlogon_creds_cli_context_global() is only cosmetic,
but avoids confusion while reading the code. Check with:

 git show -U35 libcli/auth/netlogon_creds_cli.c

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 1c6c1129905d0c7a60018e7bf0f17a0fd198a584)
---
 docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 7 +++++--
 lib/param/loadparm.c                             | 1 +
 libcli/auth/netlogon_creds_cli.c                 | 4 ++--
 source3/param/loadparm.c                         | 1 +
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
index 151b4676c57..3bc4eaf7b02 100644
--- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
+++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml
@@ -13,10 +13,13 @@
 	This will prevent downgrade attacks.</para>
 
 	<para>The behavior can be controlled per netbios domain
-	by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option.</para>
+	by using 'reject md5 servers:NETBIOSDOMAIN = no' as option.</para>
+
+	<para>The default changed from 'no' to 'yes, with the patches for CVE-2022-38023,
+	see https://bugzilla.samba.org/show_bug.cgi?id=15240</para>
 
 	<para>This option overrides the <smbconfoption name="require strong key"/> option.</para>
 </description>
 
-<value type="default">no</value>
+<value type="default">yes</value>
 </samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 4aa91f4d404..dc659a449ea 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2733,6 +2733,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
 	lpcfg_do_global_parameter(lp_ctx, "winbind scan trusted domains", "True");
 	lpcfg_do_global_parameter(lp_ctx, "require strong key", "True");
+	lpcfg_do_global_parameter(lp_ctx, "reject md5 servers", "True");
 	lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
 	lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
 	lpcfg_do_global_parameter_var(lp_ctx, "gpo update command", "%s/samba-gpupdate", dyn_SCRIPTSBINDIR);
diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index 20a3da5060f..0558cb237a4 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -340,8 +340,8 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx,
 	const char *client_computer;
 	uint32_t proposed_flags;
 	uint32_t required_flags = 0;
-	bool reject_md5_servers = false;
-	bool require_strong_key = false;
+	bool reject_md5_servers = true;
+	bool require_strong_key = true;
 	int require_sign_or_seal = true;
 	bool seal_secure_channel = true;
 	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 98e05d13d59..fbc987e119a 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -657,6 +657,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.client_schannel = true;
 	Globals.winbind_sealed_pipes = true;
 	Globals.require_strong_key = true;
+	Globals.reject_md5_servers = true;
 	Globals.server_schannel = true;
 	Globals.read_raw = true;
 	Globals.write_raw = true;
-- 
2.41.0


From b62fb90dd434c99131086f27cb74cf2c109fb9d2 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 6 Dec 2022 10:56:29 +0100
Subject: [PATCH 109/146] CVE-2022-38023 s4:rpc_server/netlogon: 'server
 schannel != yes' warning to dcesrv_interface_netlogon_bind

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit e060ea5b3edbe3cba492062c9605f88fae212ee0)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 +++++++++++--------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 7668a9eb923..e7f8cd5c075 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -60,6 +60,21 @@
 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
 					       const struct dcesrv_interface *iface)
 {
+	struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+	int schannel = lpcfg_server_schannel(lp_ctx);
+	bool schannel_global_required = (schannel == true);
+	static bool warned_global_schannel_once = false;
+
+	if (!schannel_global_required && !warned_global_schannel_once) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		D_ERR("CVE-2020-1472(ZeroLogon): "
+		      "Please configure 'server schannel = yes' (the default), "
+		      "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
+		warned_global_schannel_once = true;
+	}
+
 	return dcesrv_interface_bind_reject_connect(context, iface);
 }
 
@@ -629,7 +644,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
 	uint16_t opnum = dce_call->pkt.u.request.opnum;
 	const char *opname = "<unknown>";
-	static bool warned_global_once = false;
 
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
@@ -681,16 +695,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	if (!schannel_global_required && !warned_global_once) {
-		/*
-		 * We want admins to notice their misconfiguration!
-		 */
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"Please configure 'server schannel = yes', "
-			"See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
-		warned_global_once = true;
-	}
-
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"%s request (opnum[%u]) WITH schannel from "
-- 
2.41.0


From dbddee016499bddab42870226eda0b19facca936 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 12 Dec 2022 14:03:50 +0100
Subject: [PATCH 110/146] CVE-2022-38023 s4:rpc_server/netlogon: add a lp_ctx
 variable to dcesrv_netr_creds_server_step_check()

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 7baabbe9819cd5a2714e7ea4e57a0c23062c0150)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index e7f8cd5c075..bd3a36e60cc 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -635,8 +635,9 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 						    struct netr_Authenticator *return_authenticator,
 						    struct netlogon_creds_CredentialState **creds_out)
 {
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 	NTSTATUS nt_status;
-	int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
+	int schannel = lpcfg_server_schannel(lp_ctx);
 	bool schannel_global_required = (schannel == true);
 	bool schannel_required = schannel_global_required;
 	const char *explicit_opt = NULL;
@@ -652,7 +653,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	dcesrv_call_auth_info(dce_call, &auth_type, NULL);
 
 	nt_status = schannel_check_creds_state(mem_ctx,
-					       dce_call->conn->dce_ctx->lp_ctx,
+					       lp_ctx,
 					       computer_name,
 					       received_authenticator,
 					       return_authenticator,
@@ -667,7 +668,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	 * need the explicit_opt pointer in order to
 	 * adjust the debug messages.
 	 */
-	explicit_opt = lpcfg_get_parametric(dce_call->conn->dce_ctx->lp_ctx,
+	explicit_opt = lpcfg_get_parametric(lp_ctx,
 					    NULL,
 					    "server require schannel",
 					    creds->account_name);
-- 
2.41.0


From da1c4d9055c0b7fcb5e6952e3e63c7089b2b0432 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 12 Dec 2022 14:03:50 +0100
Subject: [PATCH 111/146] CVE-2022-38023 s4:rpc_server/netlogon: add
 talloc_stackframe() to dcesrv_netr_creds_server_step_check()

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 0e6a2ba83ef1be3c6a0f5514c21395121621a145)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 32 +++++++++++--------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index bd3a36e60cc..b842fa6a556 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -636,6 +636,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 						    struct netlogon_creds_CredentialState **creds_out)
 {
 	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	TALLOC_CTX *frame = talloc_stackframe();
 	NTSTATUS nt_status;
 	int schannel = lpcfg_server_schannel(lp_ctx);
 	bool schannel_global_required = (schannel == true);
@@ -679,6 +680,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	if (schannel_required) {
 		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 			*creds_out = creds;
+			TALLOC_FREE(frame);
 			return NT_STATUS_OK;
 		}
 
@@ -686,13 +688,15 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' is needed! \n",
-			log_escape(mem_ctx, creds->account_name));
+			"'server require schannel:%s = no' "
+			"might be needed for a legacy client.\n",
+			log_escape(frame, creds->account_name));
 		TALLOC_FREE(creds);
 		ZERO_STRUCTP(return_authenticator);
+		TALLOC_FREE(frame);
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
@@ -701,13 +705,14 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			"%s request (opnum[%u]) WITH schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"Option 'server require schannel:%s = no' not needed!?\n",
-			log_escape(mem_ctx, creds->account_name));
+			log_escape(frame, creds->account_name));
 
 		*creds_out = creds;
+		TALLOC_FREE(frame);
 		return NT_STATUS_OK;
 	}
 
@@ -717,24 +722,25 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			 "%s request (opnum[%u]) without schannel from "
 			 "client_account[%s] client_computer_name[%s]\n",
 			 opname, opnum,
-			 log_escape(mem_ctx, creds->account_name),
-			 log_escape(mem_ctx, creds->computer_name));
+			 log_escape(frame, creds->account_name),
+			 log_escape(frame, creds->computer_name));
 		DBG_INFO("CVE-2020-1472(ZeroLogon): "
 			 "Option 'server require schannel:%s = no' still needed!\n",
-			 log_escape(mem_ctx, creds->account_name));
+			 log_escape(frame, creds->account_name));
 	} else {
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
 			"'server require schannel:%s = no' might be needed!\n",
-			log_escape(mem_ctx, creds->account_name));
+			log_escape(frame, creds->account_name));
 	}
 
 	*creds_out = creds;
+	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
 }
 
-- 
2.41.0


From 01d4d64eaca505da9c542f2149c0bd362ad180d1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 12:37:03 +0100
Subject: [PATCH 112/146] CVE-2022-38023 s4:rpc_server/netlogon: re-order
 checking in dcesrv_netr_creds_server_step_check()

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit ec62151a2fb49ecbeaa3bf924f49a956832b735e)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 41 +++++++++----------
 1 file changed, 19 insertions(+), 22 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index b842fa6a556..9b3a933abca 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -677,13 +677,27 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		schannel_required = lp_bool(explicit_opt);
 	}
 
-	if (schannel_required) {
-		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-			*creds_out = creds;
-			TALLOC_FREE(frame);
-			return NT_STATUS_OK;
+	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (!schannel_required) {
+			DBG_ERR("CVE-2020-1472(ZeroLogon): "
+				"%s request (opnum[%u]) WITH schannel from "
+				"client_account[%s] client_computer_name[%s]\n",
+				opname, opnum,
+				log_escape(frame, creds->account_name),
+				log_escape(frame, creds->computer_name));
+		}
+		if (explicit_opt != NULL && !schannel_required) {
+			DBG_ERR("CVE-2020-1472(ZeroLogon): "
+				"Option 'server require schannel:%s = no' not needed!?\n",
+				log_escape(frame, creds->account_name));
 		}
 
+		*creds_out = creds;
+		TALLOC_FREE(frame);
+		return NT_STATUS_OK;
+	}
+
+	if (schannel_required) {
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
@@ -700,23 +714,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
-	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) WITH schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"Option 'server require schannel:%s = no' not needed!?\n",
-			log_escape(frame, creds->account_name));
-
-		*creds_out = creds;
-		TALLOC_FREE(frame);
-		return NT_STATUS_OK;
-	}
-
-
 	if (explicit_opt != NULL) {
 		DBG_INFO("CVE-2020-1472(ZeroLogon): "
 			 "%s request (opnum[%u]) without schannel from "
-- 
2.41.0


From 90531a4cb89b0d390261de1920f17a8ea7a9cbcb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 12:37:03 +0100
Subject: [PATCH 113/146] CVE-2022-38023 s4:rpc_server/netlogon: improve
 CVE-2020-1472(ZeroLogon) debug messages

In order to avoid generating useless debug messages during make test,
we will use 'CVE_2020_1472:warn_about_unused_debug_level = 3'
and 'CVE_2020_1472:error_debug_level = 2' in order to avoid schannel warnings.

Review with: git show -w

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 16ee03efc194d9c1c2c746f63236b977a419918d)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 147 +++++++++++++-----
 1 file changed, 106 insertions(+), 41 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 9b3a933abca..8084061aabc 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -643,15 +643,34 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	bool schannel_required = schannel_global_required;
 	const char *explicit_opt = NULL;
 	struct netlogon_creds_CredentialState *creds = NULL;
+	int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
+	int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
+	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
+	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
 	uint16_t opnum = dce_call->pkt.u.request.opnum;
 	const char *opname = "<unknown>";
+	const char *reason = "<unknown>";
 
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
-	dcesrv_call_auth_info(dce_call, &auth_type, NULL);
+	dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
+
+	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+			reason = "WITH SEALED";
+		} else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+			reason = "WITH SIGNED";
+		} else {
+			smb_panic("Schannel without SIGN/SEAL");
+		}
+	} else {
+		reason = "WITHOUT";
+	}
 
 	nt_status = schannel_check_creds_state(mem_ctx,
 					       lp_ctx,
@@ -678,62 +697,108 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	}
 
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		if (!schannel_required) {
-			DBG_ERR("CVE-2020-1472(ZeroLogon): "
-				"%s request (opnum[%u]) WITH schannel from "
-				"client_account[%s] client_computer_name[%s]\n",
-				opname, opnum,
-				log_escape(frame, creds->account_name),
-				log_escape(frame, creds->computer_name));
+		nt_status = NT_STATUS_OK;
+
+		if (explicit_opt != NULL && !schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
+		} else if (!schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon): "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(nt_status)));
+
 		if (explicit_opt != NULL && !schannel_required) {
-			DBG_ERR("CVE-2020-1472(ZeroLogon): "
-				"Option 'server require schannel:%s = no' not needed!?\n",
-				log_escape(frame, creds->account_name));
+			DEBUG(CVE_2020_1472_warn_level, (
+			      "CVE-2020-1472(ZeroLogon): "
+			      "Option 'server require schannel:%s = no' not needed for '%s'!\n",
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name)));
 		}
 
 		*creds_out = creds;
 		TALLOC_FREE(frame);
-		return NT_STATUS_OK;
+		return nt_status;
 	}
 
 	if (schannel_required) {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) without schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' "
-			"might be needed for a legacy client.\n",
-			log_escape(frame, creds->account_name));
+		nt_status = NT_STATUS_ACCESS_DENIED;
+
+		if (explicit_opt != NULL) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
+		} else {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(nt_status)));
+		if (explicit_opt != NULL) {
+			D_NOTICE("CVE-2020-1472(ZeroLogon): Option "
+				"'server require schannel:%s = yes' "
+				"rejects access for client.\n",
+				log_escape(frame, creds->account_name));
+		} else {
+			DEBUG(CVE_2020_1472_error_level, (
+			      "CVE-2020-1472(ZeroLogon): Check if option "
+			      "'server require schannel:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      log_escape(frame, creds->account_name)));
+		}
 		TALLOC_FREE(creds);
 		ZERO_STRUCTP(return_authenticator);
 		TALLOC_FREE(frame);
-		return NT_STATUS_ACCESS_DENIED;
+		return nt_status;
 	}
 
+	nt_status = NT_STATUS_OK;
+
 	if (explicit_opt != NULL) {
-		DBG_INFO("CVE-2020-1472(ZeroLogon): "
-			 "%s request (opnum[%u]) without schannel from "
-			 "client_account[%s] client_computer_name[%s]\n",
-			 opname, opnum,
-			 log_escape(frame, creds->account_name),
-			 log_escape(frame, creds->computer_name));
-		DBG_INFO("CVE-2020-1472(ZeroLogon): "
-			 "Option 'server require schannel:%s = no' still needed!\n",
-			 log_escape(frame, creds->account_name));
+		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) without schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' might be needed!\n",
-			log_escape(frame, creds->account_name));
+		dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+	}
+
+	DEBUG(dbg_lvl, (
+	      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+	      "%s request (opnum[%u]) %s schannel from "
+	      "client_account[%s] client_computer_name[%s] %s\n",
+	      opname, opnum, reason,
+	      log_escape(frame, creds->account_name),
+	      log_escape(frame, creds->computer_name),
+	      nt_errstr(nt_status)));
+
+	if (explicit_opt != NULL) {
+		D_INFO("CVE-2020-1472(ZeroLogon): Option "
+		       "'server require schannel:%s = no' "
+		       "still needed for '%s'!\n",
+		       log_escape(frame, creds->account_name),
+		       log_escape(frame, creds->computer_name));
+	} else {
+		/*
+		 * admins should set
+		 * server require schannel:COMPUTER$ = no
+		 * in order to avoid the level 0 messages.
+		 * Over time they can switch the global value
+		 * to be strict.
+		 */
+		DEBUG(CVE_2020_1472_error_level, (
+		      "CVE-2020-1472(ZeroLogon): "
+		      "Please use 'server require schannel:%s = no' "
+		      "for '%s' to avoid this warning!\n",
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name)));
 	}
 
 	*creds_out = creds;
-- 
2.41.0


From 2ea49737a5cac8ead895da30d40f18019103b285 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 12:26:01 +0100
Subject: [PATCH 114/146] CVE-2022-38023 selftest:Samba4: avoid global 'server
 schannel = auto'

Instead of using the generic deprecated option use the specific
server require schannel:COMPUTERACCOUNT = no in order to allow
legacy tests for pass.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 63c96ea6c02981795e67336401143f2a8836992c)
---
 selftest/target/Samba4.pm | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 0f644661176..8dad74cae43 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1708,7 +1708,24 @@ sub provision_ad_dc_ntvfs($$)
 	dsdb event notification = true
 	dsdb password event notification = true
 	dsdb group change notification = true
-	server schannel = auto
+
+	CVE_2020_1472:warn_about_unused_debug_level = 3
+	server require schannel:schannel0\$ = no
+	server require schannel:schannel1\$ = no
+	server require schannel:schannel2\$ = no
+	server require schannel:schannel3\$ = no
+	server require schannel:schannel4\$ = no
+	server require schannel:schannel5\$ = no
+	server require schannel:schannel6\$ = no
+	server require schannel:schannel7\$ = no
+	server require schannel:schannel8\$ = no
+	server require schannel:schannel9\$ = no
+	server require schannel:schannel10\$ = no
+	server require schannel:schannel11\$ = no
+	server require schannel:torturetest\$ = no
+
+	# needed for 'samba.tests.auth_log' tests
+	server require schannel:LOCALDC\$ = no
 	";
 	my $extra_provision_options = ["--use-ntvfs"];
 	my $ret = $self->provision($prefix,
@@ -2085,8 +2102,22 @@ sub provision_ad_dc($$$$$$)
 	lpq cache time = 0
 	print notify backchannel = yes
 
-	server schannel = auto
-        auth event notification = true
+	CVE_2020_1472:warn_about_unused_debug_level = 3
+	server require schannel:schannel0\$ = no
+	server require schannel:schannel1\$ = no
+	server require schannel:schannel2\$ = no
+	server require schannel:schannel3\$ = no
+	server require schannel:schannel4\$ = no
+	server require schannel:schannel5\$ = no
+	server require schannel:schannel6\$ = no
+	server require schannel:schannel7\$ = no
+	server require schannel:schannel8\$ = no
+	server require schannel:schannel9\$ = no
+	server require schannel:schannel10\$ = no
+	server require schannel:schannel11\$ = no
+	server require schannel:torturetest\$ = no
+
+	auth event notification = true
 	dsdb event notification = true
 	dsdb password event notification = true
 	dsdb group change notification = true
-- 
2.41.0


From a9ad04a6a886c4f17120fcf585bba7b979752d3c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Mon, 28 Nov 2022 15:02:13 +0100
Subject: [PATCH 115/146] CVE-2022-38023 s4:torture: use
 NETLOGON_NEG_SUPPORTS_AES by default

For generic tests we should use the best available features.

And AES will be required by default soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit cfd55a22cda113fbb2bfa373b54091dde1ea6e66)
---
 source4/torture/ntp/ntp_signd.c |  2 +-
 source4/torture/rpc/lsa.c       |  4 ++--
 source4/torture/rpc/netlogon.c  | 18 +++++++++---------
 source4/torture/rpc/samba3rpc.c | 15 ++++++++++++---
 4 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/source4/torture/ntp/ntp_signd.c b/source4/torture/ntp/ntp_signd.c
index d2a41819fcf..66f2b8956a2 100644
--- a/source4/torture/ntp/ntp_signd.c
+++ b/source4/torture/ntp/ntp_signd.c
@@ -68,7 +68,7 @@ static bool test_ntp_signd(struct torture_context *tctx,
 	uint32_t rid;
 	const char *machine_name;
 	const struct samr_Password *pwhash = cli_credentials_get_nt_hash(credentials, mem_ctx);
-	uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 
 	struct sign_request sign_req;
 	struct signed_reply signed_reply;
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 7bdc0cf679a..52e220ce225 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -4260,7 +4260,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p,
 	torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b");
 
 	ok = check_pw_with_ServerAuthenticate3(p1, tctx,
-					       NETLOGON_NEG_AUTH2_ADS_FLAGS,
+					       NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 					       server_name,
 					       incoming_creds, &creds);
 	torture_assert_int_equal(tctx, ok, expected_result,
@@ -4357,7 +4357,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p,
 	torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b");
 
 	ok = check_pw_with_ServerAuthenticate3(p2, tctx,
-					       NETLOGON_NEG_AUTH2_ADS_FLAGS,
+					       NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 					       server_name,
 					       incoming_creds, &creds);
 	torture_assert(tctx, ok, "check_pw_with_ServerAuthenticate3 with changed password");
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 97c16688bc9..1fceeae88cc 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -189,7 +189,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx,
 
 	/* This allows the tests to continue against the more fussy windows 2008 */
 	if (NT_STATUS_EQUAL(a.out.result, NT_STATUS_DOWNGRADE_DETECTED)) {
-		return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+		return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 					      credentials,
 					      cli_credentials_get_secure_channel_type(credentials),
 					      creds_out);
@@ -423,7 +423,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx,
 		"ServerAuthenticate3 failed");
 	torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_DOWNGRADE_DETECTED, "ServerAuthenticate3 should have failed");
 
-	negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	creds = netlogon_creds_client_init(tctx, a.in.account_name,
 					   a.in.computer_name,
 					   a.in.secure_channel_type,
@@ -490,7 +490,7 @@ static bool test_ServerReqChallenge(
 	const char *machine_name;
 	struct dcerpc_binding_handle *b = p->binding_handle;
 	struct netr_ServerAuthenticate2 a;
-	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	uint32_t out_negotiate_flags = 0;
 	const struct samr_Password *mach_password = NULL;
 	enum netr_SchannelType sec_chan_type = 0;
@@ -562,7 +562,7 @@ static bool test_ServerReqChallenge_zero_challenge(
 	const char *machine_name;
 	struct dcerpc_binding_handle *b = p->binding_handle;
 	struct netr_ServerAuthenticate2 a;
-	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	uint32_t out_negotiate_flags = 0;
 	const struct samr_Password *mach_password = NULL;
 	enum netr_SchannelType sec_chan_type = 0;
@@ -639,7 +639,7 @@ static bool test_ServerReqChallenge_5_repeats(
 	const char *machine_name;
 	struct dcerpc_binding_handle *b = p->binding_handle;
 	struct netr_ServerAuthenticate2 a;
-	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	uint32_t out_negotiate_flags = 0;
 	const struct samr_Password *mach_password = NULL;
 	enum netr_SchannelType sec_chan_type = 0;
@@ -723,7 +723,7 @@ static bool test_ServerReqChallenge_4_repeats(
 	const char *machine_name;
 	struct dcerpc_binding_handle *b = p->binding_handle;
 	struct netr_ServerAuthenticate2 a;
-	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	uint32_t out_negotiate_flags = 0;
 	const struct samr_Password *mach_password = NULL;
 	enum netr_SchannelType sec_chan_type = 0;
@@ -3459,7 +3459,7 @@ static bool test_netr_GetForestTrustInformation(struct torture_context *tctx,
 	struct dcerpc_pipe *p = NULL;
 	struct dcerpc_binding_handle *b = NULL;
 
-	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 				    machine_credentials, &creds)) {
 		return false;
 	}
@@ -4398,7 +4398,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
 
 	torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n");
 
-	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+	if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 				    machine_credentials, &creds)) {
 		return false;
 	}
@@ -4973,7 +4973,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx,
 
 	torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT);
 
-	if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
+	if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
 				    machine_credentials, &creds)) {
 		return false;
 	}
diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c
index 9cd479c9baf..6fc4ed326d2 100644
--- a/source4/torture/rpc/samba3rpc.c
+++ b/source4/torture/rpc/samba3rpc.c
@@ -1074,7 +1074,7 @@ static bool auth2(struct torture_context *tctx,
 		goto done;
 	}
 
-	negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
+	negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
 	E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash);
 
 	a.in.server_name = talloc_asprintf(
@@ -1264,10 +1264,19 @@ static bool schan(struct torture_context *tctx,
 		E_md4hash(cli_credentials_get_password(user_creds),
 			  pinfo.ntpassword.hash);
 
-		netlogon_creds_arcfour_crypt(creds_state, pinfo.ntpassword.hash, 16);
-
 		logon.password = &pinfo;
 
+		/*
+		 * We don't use this here:
+		 *
+		 * netlogon_creds_encrypt_samlogon_logon(creds_state,
+		 *                                       NetlogonInteractiveInformation,
+		 *                                       &logon);
+		 *
+		 * in order to detect bugs
+		 */
+		netlogon_creds_aes_encrypt(creds_state, pinfo.ntpassword.hash, 16);
+
 		r.in.logon_level = NetlogonInteractiveInformation;
 		r.in.logon = &logon;
 		r.out.return_authenticator = &return_authenticator;
-- 
2.41.0


From 6088b76def86b8f56511707c69b6cdd016722715 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 09:54:17 +0100
Subject: [PATCH 116/146] CVE-2022-38023 s4:rpc_server/netlogon: split out
 dcesrv_netr_ServerAuthenticate3_check_downgrade()

We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no',
which means we'll need the downgrade detection in more places.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit b6339fd1dcbe903e73efeea074ab0bd04ef83561)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 114 ++++++++++--------
 1 file changed, 67 insertions(+), 47 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 8084061aabc..6a00fe4efcf 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -128,6 +128,67 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
+	struct dcesrv_call_state *dce_call,
+	struct netr_ServerAuthenticate3 *r,
+	struct netlogon_server_pipe_state *pipe_state,
+	uint32_t negotiate_flags,
+	NTSTATUS orig_status)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
+	bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
+	bool reject_des_client = !allow_nt4_crypto;
+	bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
+
+	if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
+		reject_des_client = false;
+	}
+
+	if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+		reject_des_client = false;
+		reject_md5_client = false;
+	}
+
+	if (reject_des_client || reject_md5_client) {
+		/*
+		 * Here we match Windows 2012 and return no flags.
+		 */
+		*r->out.negotiate_flags = 0;
+		return NT_STATUS_DOWNGRADE_DETECTED;
+	}
+
+	/*
+	 * This talloc_free is important to prevent re-use of the
+	 * challenge.  We have to delay it this far due to NETApp
+	 * servers per:
+	 * https://bugzilla.samba.org/show_bug.cgi?id=11291
+	 */
+	TALLOC_FREE(pipe_state);
+
+	/*
+	 * At this point we must also cleanup the TDB cache
+	 * entry, if we fail the client needs to call
+	 * netr_ServerReqChallenge again.
+	 *
+	 * Note: this handles a non existing record just fine,
+	 * the r->in.computer_name might not be the one used
+	 * in netr_ServerReqChallenge(), but we are trying to
+	 * just tidy up the normal case to prevent re-use.
+	 */
+	schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
+				  r->in.computer_name);
+
+	/*
+	 * According to Microsoft (see bugid #6099)
+	 * Windows 7 looks at the negotiate_flags
+	 * returned in this structure *even if the
+	 * call fails with access denied!
+	 */
+	*r->out.negotiate_flags = negotiate_flags;
+
+	return orig_status;
+}
+
 /*
  * Do the actual processing of a netr_ServerAuthenticate3 message.
  * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
@@ -155,11 +216,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 			       "objectSid", "samAccountName", NULL};
 	uint32_t server_flags = 0;
 	uint32_t negotiate_flags = 0;
-	bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
-	bool reject_des_client = !allow_nt4_crypto;
-	bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
 
 	ZERO_STRUCTP(r->out.return_credentials);
+	*r->out.negotiate_flags = 0;
 	*r->out.rid = 0;
 
 	pipe_state = dcesrv_iface_state_find_conn(dce_call,
@@ -238,52 +297,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 
 	negotiate_flags = *r->in.negotiate_flags & server_flags;
 
-	if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
-		reject_des_client = false;
-	}
-
-	if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
-		reject_des_client = false;
-		reject_md5_client = false;
-	}
-
-	if (reject_des_client || reject_md5_client) {
-		/*
-		 * Here we match Windows 2012 and return no flags.
-		 */
-		*r->out.negotiate_flags = 0;
-		return NT_STATUS_DOWNGRADE_DETECTED;
+	nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
+			dce_call, r, pipe_state, negotiate_flags,
+			NT_STATUS_OK);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		return nt_status;
 	}
 
-	/*
-	 * This talloc_free is important to prevent re-use of the
-	 * challenge.  We have to delay it this far due to NETApp
-	 * servers per:
-	 * https://bugzilla.samba.org/show_bug.cgi?id=11291
-	 */
-	TALLOC_FREE(pipe_state);
-
-	/*
-	 * At this point we must also cleanup the TDB cache
-	 * entry, if we fail the client needs to call
-	 * netr_ServerReqChallenge again.
-	 *
-	 * Note: this handles a non existing record just fine,
-	 * the r->in.computer_name might not be the one used
-	 * in netr_ServerReqChallenge(), but we are trying to
-	 * just tidy up the normal case to prevent re-use.
-	 */
-	schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
-				  r->in.computer_name);
-
-	/*
-	 * According to Microsoft (see bugid #6099)
-	 * Windows 7 looks at the negotiate_flags
-	 * returned in this structure *even if the
-	 * call fails with access denied!
-	 */
-	*r->out.negotiate_flags = negotiate_flags;
-
 	switch (r->in.secure_channel_type) {
 	case SEC_CHAN_WKSTA:
 	case SEC_CHAN_DNS_DOMAIN:
-- 
2.41.0


From 3e43111a1417414b545fcc46a72e701cf6e71c59 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 24 Nov 2022 18:26:18 +0100
Subject: [PATCH 117/146] CVE-2022-38023 docs-xml/smbdotconf: change 'reject
 md5 clients' default to yes

AES is supported by Windows Server >= 2008R2, Windows (Client) >= 7 and Samba >= 4.0,
so there's no reason to allow md5 clients by default.
However some third party domain members may need it.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit c8e53394b98b128ed460a6111faf05dfbad980d1)
---
 docs-xml/smbdotconf/logon/rejectmd5clients.xml | 11 ++++++++---
 lib/param/loadparm.c                           |  1 +
 selftest/target/Samba4.pm                      |  4 ++++
 source3/param/loadparm.c                       |  1 +
 4 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
index 0bb9f6f6c8e..edcbe02e99a 100644
--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml
+++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
@@ -7,11 +7,16 @@
 	only in 'active directory domain controller' mode), will
 	reject clients which does not support NETLOGON_NEG_SUPPORTS_AES.</para>
 
-	<para>You can set this to yes if all domain members support aes.
-	This will prevent downgrade attacks.</para>
+	<para>Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows
+	starting with Server 2008R2 and Windows 7, it's available in Samba
+	starting with 4.0, however third party domain members like NetApp ONTAP
+	still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details.</para>
+
+	<para>The default changed from 'no' to 'yes', with the patches for CVE-2022-38023,
+	see https://bugzilla.samba.org/show_bug.cgi?id=15240</para>
 
 	<para>This option overrides the 'allow nt4 crypto' option.</para>
 </description>
 
-<value type="default">no</value>
+<value type="default">yes</value>
 </samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index dc659a449ea..77a80176f7d 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2790,6 +2790,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template");
 
 	lpcfg_do_global_parameter(lp_ctx, "server schannel", "True");
+	lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True");
 
 	lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True");
 
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 8dad74cae43..7e3d7c9de8e 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1709,6 +1709,8 @@ sub provision_ad_dc_ntvfs($$)
 	dsdb password event notification = true
 	dsdb group change notification = true
 
+	reject md5 clients = no
+
 	CVE_2020_1472:warn_about_unused_debug_level = 3
 	server require schannel:schannel0\$ = no
 	server require schannel:schannel1\$ = no
@@ -2102,6 +2104,8 @@ sub provision_ad_dc($$$$$$)
 	lpq cache time = 0
 	print notify backchannel = yes
 
+	reject md5 clients = no
+
 	CVE_2020_1472:warn_about_unused_debug_level = 3
 	server require schannel:schannel0\$ = no
 	server require schannel:schannel1\$ = no
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index fbc987e119a..1cf468b1009 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -659,6 +659,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.require_strong_key = true;
 	Globals.reject_md5_servers = true;
 	Globals.server_schannel = true;
+	Globals.reject_md5_clients = true;
 	Globals.read_raw = true;
 	Globals.write_raw = true;
 	Globals.null_passwords = false;
-- 
2.41.0


From 886878d18d22eb4a2f3b63663e0ffe284ed9788b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 10:31:08 +0100
Subject: [PATCH 118/146] CVE-2022-38023 s4:rpc_server/netlogon: defer
 downgrade check until we found the account in our SAM

We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no',
which means we'll need use the account name from our SAM.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit b09f51eefc311bbb1525efd1dc7b9a837f7ec3c2)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 76 +++++++++++++------
 1 file changed, 53 insertions(+), 23 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 6a00fe4efcf..1c180343252 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -297,13 +297,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 
 	negotiate_flags = *r->in.negotiate_flags & server_flags;
 
-	nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
-			dce_call, r, pipe_state, negotiate_flags,
-			NT_STATUS_OK);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		return nt_status;
-	}
-
 	switch (r->in.secure_channel_type) {
 	case SEC_CHAN_WKSTA:
 	case SEC_CHAN_DNS_DOMAIN:
@@ -312,11 +305,15 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 	case SEC_CHAN_RODC:
 		break;
 	case SEC_CHAN_NULL:
-		return NT_STATUS_INVALID_PARAMETER;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_INVALID_PARAMETER);
 	default:
 		DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
 			  r->in.secure_channel_type));
-		return NT_STATUS_INVALID_PARAMETER;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_INVALID_PARAMETER);
 	}
 
 	sam_ctx = samdb_connect(mem_ctx,
@@ -326,7 +323,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 				dce_call->conn->remote_address,
 				0);
 	if (sam_ctx == NULL) {
-		return NT_STATUS_INVALID_SYSTEM_SERVICE;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_INVALID_SYSTEM_SERVICE);
 	}
 
 	if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
@@ -355,16 +354,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		encoded_name = ldb_binary_encode_string(mem_ctx,
 							r->in.account_name);
 		if (encoded_name == NULL) {
-			return NT_STATUS_NO_MEMORY;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_MEMORY);
 		}
 
 		len = strlen(encoded_name);
 		if (len < 2) {
-			return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 
 		if (require_trailer && encoded_name[len - 1] != trailer) {
-			return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		encoded_name[len - 1] = '\0';
 
@@ -382,30 +387,42 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 				  "but there's no tdo for [%s] => [%s] \n",
 				  log_escape(mem_ctx, r->in.account_name),
 				  encoded_name));
-			return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		if (!NT_STATUS_IS_OK(nt_status)) {
-			return nt_status;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				nt_status);
 		}
 
 		nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
 							      &curNtHash,
 							      &prevNtHash);
 		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
-			return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		if (!NT_STATUS_IS_OK(nt_status)) {
-			return nt_status;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				nt_status);
 		}
 
 		flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
 		if (flatname == NULL) {
-			return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 
 		*trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
 		if (*trust_account_for_search == NULL) {
-			return NT_STATUS_NO_MEMORY;
+			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_MEMORY);
 		}
 	} else {
 		*trust_account_for_search = r->in.account_name;
@@ -420,14 +437,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 	if (num_records == 0) {
 		DEBUG(3,("Couldn't find user [%s] in samdb.\n",
 			 log_escape(mem_ctx, r->in.account_name)));
-		return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 	}
 
 	if (num_records > 1) {
 		DEBUG(0,("Found %d records matching user [%s]\n",
 			 num_records,
 			 log_escape(mem_ctx, r->in.account_name)));
-		return NT_STATUS_INTERNAL_DB_CORRUPTION;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_INTERNAL_DB_CORRUPTION);
 	}
 
 	*trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
@@ -436,9 +457,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 	if (*trust_account_in_db == NULL) {
 		DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
 			 r->in.account_name));
-		return NT_STATUS_INTERNAL_DB_CORRUPTION;
+		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
+				dce_call, r, pipe_state, negotiate_flags,
+				NT_STATUS_INTERNAL_DB_CORRUPTION);
 	}
-	
+
+	nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
+			dce_call, r, pipe_state, negotiate_flags,
+			NT_STATUS_OK);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		return nt_status;
+	}
+
 	user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
 
 	if (user_account_control & UF_ACCOUNTDISABLE) {
-- 
2.41.0


From ed628f5bf355801023c1bb2ac4aabd06c5c878a6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 13:13:36 +0100
Subject: [PATCH 119/146] CVE-2022-38023 s4:rpc_server/netlogon: add 'server
 reject md5 schannel:COMPUTERACCOUNT = no' and 'allow nt4
 crypto:COMPUTERACCOUNT = yes'

This makes it more flexible when we change the global default to
'reject md5 servers = yes'.

'allow nt4 crypto = no' is already the default.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 69b36541606d7064de9648cd54b35adfdf8f0e8f)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 58 ++++++++++++++++++-
 1 file changed, 55 insertions(+), 3 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 1c180343252..b605daea794 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -133,12 +133,48 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
 	struct netr_ServerAuthenticate3 *r,
 	struct netlogon_server_pipe_state *pipe_state,
 	uint32_t negotiate_flags,
+	const char *trust_account_in_db,
 	NTSTATUS orig_status)
 {
 	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
-	bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
-	bool reject_des_client = !allow_nt4_crypto;
-	bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
+	bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
+	bool account_allow_nt4_crypto = global_allow_nt4_crypto;
+	const char *explicit_nt4_opt = NULL;
+	bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
+	bool account_reject_md5_client = global_reject_md5_client;
+	const char *explicit_md5_opt = NULL;
+	bool reject_des_client;
+	bool allow_nt4_crypto;
+	bool reject_md5_client;
+
+	/*
+	 * We don't use lpcfg_parm_bool(), as we
+	 * need the explicit_opt pointer in order to
+	 * adjust the debug messages.
+	 */
+
+	if (trust_account_in_db != NULL) {
+		explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
+							NULL,
+							"allow nt4 crypto",
+							trust_account_in_db);
+	}
+	if (explicit_nt4_opt != NULL) {
+		account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
+	}
+	allow_nt4_crypto = account_allow_nt4_crypto;
+	if (trust_account_in_db != NULL) {
+		explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
+							NULL,
+							"server reject md5 schannel",
+							trust_account_in_db);
+	}
+	if (explicit_md5_opt != NULL) {
+		account_reject_md5_client = lp_bool(explicit_md5_opt);
+	}
+	reject_md5_client = account_reject_md5_client;
+
+	reject_des_client = !allow_nt4_crypto;
 
 	if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
 		reject_des_client = false;
@@ -307,12 +343,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 	case SEC_CHAN_NULL:
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_INVALID_PARAMETER);
 	default:
 		DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
 			  r->in.secure_channel_type));
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_INVALID_PARAMETER);
 	}
 
@@ -325,6 +363,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 	if (sam_ctx == NULL) {
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_INVALID_SYSTEM_SERVICE);
 	}
 
@@ -356,6 +395,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		if (encoded_name == NULL) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_MEMORY);
 		}
 
@@ -363,12 +403,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		if (len < 2) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 
 		if (require_trailer && encoded_name[len - 1] != trailer) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		encoded_name[len - 1] = '\0';
@@ -389,11 +431,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 				  encoded_name));
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		if (!NT_STATUS_IS_OK(nt_status)) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				nt_status);
 		}
 
@@ -403,11 +447,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 		if (!NT_STATUS_IS_OK(nt_status)) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				nt_status);
 		}
 
@@ -415,6 +461,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		if (flatname == NULL) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 		}
 
@@ -422,6 +469,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 		if (*trust_account_for_search == NULL) {
 			return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_MEMORY);
 		}
 	} else {
@@ -439,6 +487,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 			 log_escape(mem_ctx, r->in.account_name)));
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_NO_TRUST_SAM_ACCOUNT);
 	}
 
@@ -448,6 +497,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 			 log_escape(mem_ctx, r->in.account_name)));
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_INTERNAL_DB_CORRUPTION);
 	}
 
@@ -459,11 +509,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
 			 r->in.account_name));
 		return dcesrv_netr_ServerAuthenticate3_check_downgrade(
 				dce_call, r, pipe_state, negotiate_flags,
+				NULL, /* trust_account_in_db */
 				NT_STATUS_INTERNAL_DB_CORRUPTION);
 	}
 
 	nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
 			dce_call, r, pipe_state, negotiate_flags,
+			*trust_account_in_db,
 			NT_STATUS_OK);
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		return nt_status;
-- 
2.41.0


From b15c69701d065504588671187a5cec9eea9dcf57 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 13:31:14 +0100
Subject: [PATCH 120/146] CVE-2022-38023 docs-xml/smbdotconf: document "allow
 nt4 crypto:COMPUTERACCOUNT = no"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit bd429d025981b445bf63935063e8e302bfab3f9b)
---
 docs-xml/smbdotconf/logon/allownt4crypto.xml | 76 +++++++++++++++++++-
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml
index 06afcef73b1..bbd03a42db7 100644
--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml
+++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml
@@ -1,11 +1,18 @@
 <samba:parameter name="allow nt4 crypto"
                  context="G"
                  type="boolean"
+                 deprecated="1"
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
+	<para>
+	This option is deprecated and will be removed in future,
+	as it is a security problem if not set to "no" (which will be
+	the hardcoded behavior in future).
+	</para>
+
 	<para>This option controls whether the netlogon server (currently
 	only in 'active directory domain controller' mode), will
-	reject clients which does not support NETLOGON_NEG_STRONG_KEYS
+	reject clients which do not support NETLOGON_NEG_STRONG_KEYS
 	nor NETLOGON_NEG_SUPPORTS_AES.</para>
 
 	<para>This option was added with Samba 4.2.0. It may lock out clients
@@ -18,8 +25,73 @@
 
 	<para>"allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks.</para>
 
-	<para>This option is over-ridden by the 'reject md5 clients' option.</para>
+	<para><emphasis>Avoid using this option!</emphasis> Use explicit '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>' instead!
+	Which is available with the patches for
+	<ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>
+	see <ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink></para>
+
+	<para>
+	Samba will log an error in the log files at log level 0
+	if legacy a client is rejected or allowed without an explicit,
+	'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>' option
+	for the client. The message will indicate
+	the explicit '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>'
+	line to be added, if the legacy client software requires it. (The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:error_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+	</para>
+
+	<para>This allows admins to use "yes" only for a short grace period,
+	in order to collect the explicit
+	'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>' options.</para>
+
+	<para>This option is over-ridden by the '<smbconfoption name="reject md5 clients">yes</smbconfoption>' option.</para>
 </description>
 
 <value type="default">no</value>
 </samba:parameter>
+
+<samba:parameter name="allow nt4 crypto:COMPUTERACCOUNT"
+                 context="G"
+                 type="string"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+    <para>If you still have legacy domain members which required 'allow nt4 crypto = yes',
+	it is possible to specify an explicit exception per computer account
+	by using 'allow nt4 crypto:COMPUTERACCOUNT = yes' as option.
+	Note that COMPUTERACCOUNT has to be the sAMAccountName value of
+	the computer account (including the trailing '$' sign).
+    </para>
+
+    <para>
+	Samba will log a complaint in the log files at log level 0
+	about the security problem if the option is set to "yes",
+	but the related computer does not require it.
+	(The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:warn_about_unused_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+    </para>
+
+    <para>
+	Samba will log a warning in the log files at log level 5,
+	if a setting is still needed for the specified computer account.
+    </para>
+
+    <para>
+	See <ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>,
+	<ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+    </para>
+
+    <para>This option overrides the <smbconfoption name="allow nt4 crypto"/> option.</para>
+
+    <para>This option is over-ridden by the '<smbconfoption name="reject md5 clients">yes</smbconfoption>' option.</para>
+
+    <programlisting>
+	allow nt4 crypto:LEGACYCOMPUTER1$ = yes
+	allow nt4 crypto:NASBOX$ = yes
+	allow nt4 crypto:LEGACYCOMPUTER2$ = yes
+    </programlisting>
+</description>
+
+</samba:parameter>
-- 
2.41.0


From bbc9f54fdc1ebbfc0c27b61aff43a63a16aed9d9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 14:02:11 +0100
Subject: [PATCH 121/146] CVE-2022-38023 docs-xml/smbdotconf: document "server
 reject md5 schannel:COMPUTERACCOUNT"

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 2ad302b42254e3c2800aaf11669fe2e6d55fa8a1)
---
 docs-xml/smbdotconf/logon/allownt4crypto.xml  | 13 ++-
 .../smbdotconf/logon/rejectmd5clients.xml     | 96 ++++++++++++++++++-
 2 files changed, 103 insertions(+), 6 deletions(-)

diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml
index bbd03a42db7..ee63e6cc245 100644
--- a/docs-xml/smbdotconf/logon/allownt4crypto.xml
+++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml
@@ -45,7 +45,9 @@
 	in order to collect the explicit
 	'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>' options.</para>
 
-	<para>This option is over-ridden by the '<smbconfoption name="reject md5 clients">yes</smbconfoption>' option.</para>
+	<para>This option is over-ridden by the effective value of 'yes' from
+	the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>'
+	and/or '<smbconfoption name="reject md5 clients"/>' options.</para>
 </description>
 
 <value type="default">no</value>
@@ -85,12 +87,19 @@
 
     <para>This option overrides the <smbconfoption name="allow nt4 crypto"/> option.</para>
 
-    <para>This option is over-ridden by the '<smbconfoption name="reject md5 clients">yes</smbconfoption>' option.</para>
+    <para>This option is over-ridden by the effective value of 'yes' from
+    the '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>'
+    and/or '<smbconfoption name="reject md5 clients"/>' options.</para>
+    <para>Which means '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">yes</smbconfoption>'
+    is only useful in combination with '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'</para>
 
     <programlisting>
 	allow nt4 crypto:LEGACYCOMPUTER1$ = yes
+	server reject md5 schannel:LEGACYCOMPUTER1$ = no
 	allow nt4 crypto:NASBOX$ = yes
+	server reject md5 schannel:NASBOX$ = no
 	allow nt4 crypto:LEGACYCOMPUTER2$ = yes
+	server reject md5 schannel:LEGACYCOMPUTER2$ = no
     </programlisting>
 </description>
 
diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
index edcbe02e99a..fe7701d9277 100644
--- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml
+++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml
@@ -1,8 +1,15 @@
 <samba:parameter name="reject md5 clients"
                  context="G"
                  type="boolean"
+                 deprecated="1"
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
+	<para>
+	This option is deprecated and will be removed in a future release,
+	as it is a security problem if not set to "yes" (which will be
+	the hardcoded behavior in the future).
+	</para>
+
 	<para>This option controls whether the netlogon server (currently
 	only in 'active directory domain controller' mode), will
 	reject clients which does not support NETLOGON_NEG_SUPPORTS_AES.</para>
@@ -10,13 +17,94 @@
 	<para>Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows
 	starting with Server 2008R2 and Windows 7, it's available in Samba
 	starting with 4.0, however third party domain members like NetApp ONTAP
-	still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details.</para>
+	still uses RC4 (HMAC-MD5), see
+	<ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">https://www.samba.org/samba/security/CVE-2022-38023.html</ulink>
+	for more details.
+	</para>
+
+	<para>The default changed from 'no' to 'yes', with the patches for
+	<ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>
+	see <ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+	</para>
+
+	<para><emphasis>Avoid using this option!</emphasis> Use an explicit per machine account
+	'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT"/>' instead!
+	Which is available with the patches for
+	<ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>
+	see <ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+	</para>
 
-	<para>The default changed from 'no' to 'yes', with the patches for CVE-2022-38023,
-	see https://bugzilla.samba.org/show_bug.cgi?id=15240</para>
+	<para>
+	Samba will log an error in the log files at log level 0
+	if legacy a client is rejected or allowed without an explicit,
+	'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>' option
+	for the client. The message will indicate
+	the explicit '<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>'
+	line to be added, if the legacy client software requires it. (The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:error_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+	</para>
 
-	<para>This option overrides the 'allow nt4 crypto' option.</para>
+	<para>This allows admins to use "no" only for a short grace period,
+	in order to collect the explicit
+	'<smbconfoption name="server reject md5 schannel:COMPUTERACCOUNT">no</smbconfoption>' options.</para>
+
+	<para>When set to 'yes' this option overrides the
+	'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT"/>' and
+	'<smbconfoption name="allow nt4 crypto"/>' options and implies
+	'<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">no</smbconfoption>'.
+	</para>
 </description>
 
 <value type="default">yes</value>
 </samba:parameter>
+
+<samba:parameter name="server reject md5 schannel:COMPUTERACCOUNT"
+                 context="G"
+                 type="string"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+    <para>If you still have legacy domain members or trusted domains,
+	which required "reject md5 clients = no" before,
+	it is possible to specify an explicit exception per computer account
+	by setting 'server reject md5 schannel:COMPUTERACCOUNT = no'.
+	Note that COMPUTERACCOUNT has to be the sAMAccountName value of
+	the computer account (including the trailing '$' sign).
+    </para>
+
+    <para>
+	Samba will log a complaint in the log files at log level 0
+	about the security problem if the option is set to "no",
+	but the related computer does not require it.
+	(The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:warn_about_unused_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+    </para>
+
+    <para>
+	Samba will log a warning in the log files at log level 5
+	if a setting is still needed for the specified computer account.
+    </para>
+
+    <para>
+	See <ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>,
+	<ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+    </para>
+
+    <para>This option overrides the <smbconfoption name="reject md5 clients"/> option.</para>
+
+    <para>When set to 'yes' this option overrides the
+    '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT"/>' and
+    '<smbconfoption name="allow nt4 crypto"/>' options and implies
+    '<smbconfoption name="allow nt4 crypto:COMPUTERACCOUNT">no</smbconfoption>'.
+    </para>
+
+    <programlisting>
+	server reject md5 schannel:LEGACYCOMPUTER1$ = no
+	server reject md5 schannel:NASBOX$ = no
+	server reject md5 schannel:LEGACYCOMPUTER2$ = no
+    </programlisting>
+</description>
+
+</samba:parameter>
-- 
2.41.0


From 88311bae73bfdd2863ee94f421ef89266bff97f0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 13:13:36 +0100
Subject: [PATCH 122/146] CVE-2022-38023 s4:rpc_server/netlogon: debug 'reject
 md5 servers' and 'allow nt4 crypto' misconfigurations

This allows the admin to notice what's wrong in order to adjust the
configuration if required.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 43df4be35950f491864ae8ada05d51b42a556381)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 121 ++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index b605daea794..b93ff08abcd 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -61,10 +61,34 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context
 					       const struct dcesrv_interface *iface)
 {
 	struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+	bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
+	bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
 	int schannel = lpcfg_server_schannel(lp_ctx);
 	bool schannel_global_required = (schannel == true);
+	static bool warned_global_nt4_once = false;
+	static bool warned_global_md5_once = false;
 	static bool warned_global_schannel_once = false;
 
+	if (global_allow_nt4_crypto && !warned_global_nt4_once) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		D_ERR("CVE-2022-38023 (and others): "
+		      "Please configure 'allow nt4 crypto = no' (the default), "
+		      "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_nt4_once = true;
+	}
+
+	if (!global_reject_md5_client && !warned_global_md5_once) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		D_ERR("CVE-2022-38023: "
+		      "Please configure 'reject md5 clients = yes' (the default), "
+		      "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_md5_once = true;
+	}
+
 	if (!schannel_global_required && !warned_global_schannel_once) {
 		/*
 		 * We want admins to notice their misconfiguration!
@@ -146,6 +170,12 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
 	bool reject_des_client;
 	bool allow_nt4_crypto;
 	bool reject_md5_client;
+	bool need_des = true;
+	bool need_md5 = true;
+	int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
+			"CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
+	int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
+			"CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
 
 	/*
 	 * We don't use lpcfg_parm_bool(), as we
@@ -177,19 +207,62 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
 	reject_des_client = !allow_nt4_crypto;
 
 	if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
+		need_des = false;
 		reject_des_client = false;
 	}
 
 	if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+		need_des = false;
+		need_md5 = false;
 		reject_des_client = false;
 		reject_md5_client = false;
 	}
 
 	if (reject_des_client || reject_md5_client) {
+		TALLOC_CTX *frame = talloc_stackframe();
+
+		DEBUG(CVE_2022_38023_error_level, (
+		      "CVE-2022-38023: "
+		      "client_account[%s] computer_name[%s] "
+		      "schannel_type[%u] "
+		      "client_negotiate_flags[0x%x] "
+		      "%s%s%s "
+		      "NT_STATUS_DOWNGRADE_DETECTED "
+		      "reject_des[%u] reject_md5[%u]\n",
+		      log_escape(frame, r->in.account_name),
+		      log_escape(frame, r->in.computer_name),
+		      r->in.secure_channel_type,
+		      (unsigned)*r->in.negotiate_flags,
+		      trust_account_in_db ? "real_account[" : "",
+		      trust_account_in_db ? trust_account_in_db : "",
+		      trust_account_in_db ? "]" : "",
+		      reject_des_client,
+		      reject_md5_client));
+		if (trust_account_in_db == NULL) {
+			goto return_downgrade;
+		}
+
+		if (reject_md5_client && explicit_md5_opt == NULL) {
+			DEBUG(CVE_2022_38023_error_level, (
+			      "CVE-2022-38023: Check if option "
+			      "'server reject md5 schannel:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      trust_account_in_db));
+		}
+		if (reject_des_client && explicit_nt4_opt == NULL) {
+			DEBUG(CVE_2022_38023_error_level, (
+			      "CVE-2022-38023: Check if option "
+			      "'allow nt4 crypto:%s = yes' "
+			      "might be needed for a legacy client.\n",
+			      trust_account_in_db));
+		}
+
+return_downgrade:
 		/*
 		 * Here we match Windows 2012 and return no flags.
 		 */
 		*r->out.negotiate_flags = 0;
+		TALLOC_FREE(frame);
 		return NT_STATUS_DOWNGRADE_DETECTED;
 	}
 
@@ -222,6 +295,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
 	 */
 	*r->out.negotiate_flags = negotiate_flags;
 
+	if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
+		return orig_status;
+	}
+
+	if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
+		D_INFO("CVE-2022-38023: Check if option "
+		       "'server reject md5 schannel:%s = yes' not needed!?\n",
+		       trust_account_in_db);
+	} else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
+		D_INFO("CVE-2022-38023: Check if option "
+			 "'server reject md5 schannel:%s = no' "
+			 "still needed for a legacy client.\n",
+			 trust_account_in_db);
+	} else if (need_md5 && explicit_md5_opt == NULL) {
+		DEBUG(CVE_2022_38023_error_level, (
+		      "CVE-2022-38023: Check if option "
+		      "'server reject md5 schannel:%s = no' "
+		      "might be needed for a legacy client.\n",
+		      trust_account_in_db));
+	} else if (!account_reject_md5_client && explicit_md5_opt) {
+		DEBUG(CVE_2022_38023_warn_level, (
+		      "CVE-2022-38023: Check if option "
+		      "'server reject md5 schannel:%s = no' not needed!?\n",
+		      trust_account_in_db));
+	}
+
+	if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
+		D_INFO("CVE-2022-38023: Check if option "
+		       "'allow nt4 crypto:%s = no' not needed!?\n",
+		       trust_account_in_db);
+	} else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
+		D_INFO("CVE-2022-38023: Check if option "
+			 "'allow nt4 crypto:%s = yes' "
+			 "still needed for a legacy client.\n",
+			 trust_account_in_db);
+	} else if (need_des && explicit_nt4_opt == NULL) {
+		DEBUG(CVE_2022_38023_error_level, (
+		      "CVE-2022-38023: Check if option "
+		      "'allow nt4 crypto:%s = yes' "
+		      "might be needed for a legacy client.\n",
+		      trust_account_in_db));
+	} else if (account_allow_nt4_crypto && explicit_nt4_opt) {
+		DEBUG(CVE_2022_38023_warn_level, (
+		      "CVE-2022-38023: Check if option "
+		      "'allow nt4 crypto:%s = yes' not needed!?\n",
+		      trust_account_in_db));
+	}
+
 	return orig_status;
 }
 
-- 
2.41.0


From 73230d08dd1ec2390e52b24f0398d328a55e5866 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 14:57:20 +0100
Subject: [PATCH 123/146] CVE-2022-38023 selftest:Samba4: avoid global 'allow
 nt4 crypto = yes' and 'reject md5 clients = no'

Instead of using the generic deprecated option use the specific
allow nt4 crypto:COMPUTERACCOUNT = yes and
server reject md5 schannel:COMPUTERACCOUNT = no
in order to allow legacy tests for pass.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(backported from commit 7ae3735810c2db32fa50f309f8af3c76ffa29768)
---
 selftest/target/Samba4.pm | 60 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 53 insertions(+), 7 deletions(-)

diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 7e3d7c9de8e..aafb9ee14ca 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1700,7 +1700,6 @@ sub provision_ad_dc_ntvfs($$)
         my $extra_conf_options = "netbios aliases = localDC1-a
         server services = +winbind -winbindd
 	ldap server require strong auth = allow_sasl_over_tls
-	allow nt4 crypto = yes
 	raw NTLMv2 auth = yes
 	lsa over netlogon = yes
         rpc server port = 1027
@@ -1709,9 +1708,19 @@ sub provision_ad_dc_ntvfs($$)
 	dsdb password event notification = true
 	dsdb group change notification = true
 
-	reject md5 clients = no
-
 	CVE_2020_1472:warn_about_unused_debug_level = 3
+	CVE_2022_38023:warn_about_unused_debug_level = 3
+	allow nt4 crypto:torturetest\$ = yes
+	server reject md5 schannel:schannel2\$ = no
+	server reject md5 schannel:schannel3\$ = no
+	server reject md5 schannel:schannel8\$ = no
+	server reject md5 schannel:schannel9\$ = no
+	server reject md5 schannel:torturetest\$ = no
+	server reject md5 schannel:tests4u2proxywk\$ = no
+	server reject md5 schannel:tests4u2selfbdc\$ = no
+	server reject md5 schannel:tests4u2selfwk\$ = no
+	server reject md5 schannel:torturepacbdc\$ = no
+	server reject md5 schannel:torturepacwksta\$ = no
 	server require schannel:schannel0\$ = no
 	server require schannel:schannel1\$ = no
 	server require schannel:schannel2\$ = no
@@ -1770,6 +1779,13 @@ sub provision_fl2000dc($$)
 	my $extra_conf_options = "
 	spnego:simulate_w2k=yes
 	ntlmssp_server:force_old_spnego=yes
+
+	CVE_2022_38023:warn_about_unused_debug_level = 3
+	server reject md5 schannel:tests4u2proxywk\$ = no
+	server reject md5 schannel:tests4u2selfbdc\$ = no
+	server reject md5 schannel:tests4u2selfwk\$ = no
+	server reject md5 schannel:torturepacbdc\$ = no
+	server reject md5 schannel:torturepacwksta\$ = no
 ";
 	my $extra_provision_options = ["--use-ntvfs"];
 	# This environment uses plain text secrets
@@ -1818,7 +1834,16 @@ sub provision_fl2003dc($$$)
 	my $extra_conf_options = "allow dns updates = nonsecure and secure
 	dcesrv:header signing = no
 	dcesrv:max auth states = 0
-	dns forwarder = 127.0.0.$swiface1 127.0.0.$swiface2";
+	dns forwarder = 127.0.0.$swiface1 127.0.0.$swiface2
+
+	CVE_2022_38023:warn_about_unused_debug_level = 3
+	server reject md5 schannel:tests4u2proxywk\$ = no
+	server reject md5 schannel:tests4u2selfbdc\$ = no
+	server reject md5 schannel:tests4u2selfwk\$ = no
+	server reject md5 schannel:torturepacbdc\$ = no
+	server reject md5 schannel:torturepacwksta\$ = no
+";
+
 	my $extra_provision_options = ["--use-ntvfs"];
 	my $ret = $self->provision($prefix,
 				   "domain controller",
@@ -1874,8 +1899,18 @@ sub provision_fl2008r2dc($$$)
 	my ($self, $prefix, $dcvars) = @_;
 
 	print "PROVISIONING DC WITH FOREST LEVEL 2008r2...\n";
-        my $extra_conf_options = "ldap server require strong auth = no";
+	my $extra_conf_options = "
+	ldap server require strong auth = no
+
+	CVE_2022_38023:warn_about_unused_debug_level = 3
+	server reject md5 schannel:tests4u2proxywk\$ = no
+	server reject md5 schannel:tests4u2selfbdc\$ = no
+	server reject md5 schannel:tests4u2selfwk\$ = no
+	server reject md5 schannel:torturepacbdc\$ = no
+	server reject md5 schannel:torturepacwksta\$ = no
+";
 	my $extra_provision_options = ["--use-ntvfs"];
+
 	my $ret = $self->provision($prefix,
 				   "domain controller",
 				   "dc7",
@@ -2104,9 +2139,20 @@ sub provision_ad_dc($$$$$$)
 	lpq cache time = 0
 	print notify backchannel = yes
 
-	reject md5 clients = no
-
 	CVE_2020_1472:warn_about_unused_debug_level = 3
+	CVE_2022_38023:warn_about_unused_debug_level = 3
+	CVE_2022_38023:error_debug_level = 2
+	server reject md5 schannel:schannel2\$ = no
+	server reject md5 schannel:schannel3\$ = no
+	server reject md5 schannel:schannel8\$ = no
+	server reject md5 schannel:schannel9\$ = no
+	server reject md5 schannel:torturetest\$ = no
+	server reject md5 schannel:tests4u2proxywk\$ = no
+	server reject md5 schannel:tests4u2selfbdc\$ = no
+	server reject md5 schannel:tests4u2selfwk\$ = no
+	server reject md5 schannel:torturepacbdc\$ = no
+	server reject md5 schannel:torturepacwksta\$ = no
+	server reject md5 schannel:samlogontest\$ = no
 	server require schannel:schannel0\$ = no
 	server require schannel:schannel1\$ = no
 	server require schannel:schannel2\$ = no
-- 
2.41.0


From 2efdacb36c42985595284db6db90953feecc6e1a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 16:57:24 +0100
Subject: [PATCH 124/146] CVE-2022-38023 s4:rpc_server/netlogon: split out
 dcesrv_netr_check_schannel() function

This will allow us to reuse the function in other places.
As it will also get some additional checks soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit f43dc4f0bd60d4e127b714565147f82435aa4f07)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 84 +++++++++++--------
 1 file changed, 51 insertions(+), 33 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index b93ff08abcd..94adb74165f 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -845,18 +845,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca
 	return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
 }
 
-/*
- * NOTE: The following functions are nearly identical to the ones available in
- * source3/rpc_server/srv_nelog_nt.c
- * The reason we keep 2 copies is that they use different structures to
- * represent the auth_info and the decrpc pipes.
- */
-static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
-						    TALLOC_CTX *mem_ctx,
-						    const char *computer_name,
-						    struct netr_Authenticator *received_authenticator,
-						    struct netr_Authenticator *return_authenticator,
-						    struct netlogon_creds_CredentialState **creds_out)
+static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
+					   const struct netlogon_creds_CredentialState *creds,
+					   enum dcerpc_AuthType auth_type,
+					   enum dcerpc_AuthLevel auth_level,
+					   uint16_t opnum)
 {
 	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 	TALLOC_CTX *frame = talloc_stackframe();
@@ -865,15 +858,11 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 	bool schannel_global_required = (schannel == true);
 	bool schannel_required = schannel_global_required;
 	const char *explicit_opt = NULL;
-	struct netlogon_creds_CredentialState *creds = NULL;
 	int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
 		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
 	int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
 		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
-	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
-	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
-	uint16_t opnum = dce_call->pkt.u.request.opnum;
 	const char *opname = "<unknown>";
 	const char *reason = "<unknown>";
 
@@ -881,8 +870,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
-	dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
-
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 		if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
 			reason = "WITH SEALED";
@@ -895,17 +882,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		reason = "WITHOUT";
 	}
 
-	nt_status = schannel_check_creds_state(mem_ctx,
-					       lp_ctx,
-					       computer_name,
-					       received_authenticator,
-					       return_authenticator,
-					       &creds);
-	if (!NT_STATUS_IS_OK(nt_status)) {
-		ZERO_STRUCTP(return_authenticator);
-		return nt_status;
-	}
-
 	/*
 	 * We don't use lpcfg_parm_bool(), as we
 	 * need the explicit_opt pointer in order to
@@ -945,7 +921,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			      log_escape(frame, creds->computer_name)));
 		}
 
-		*creds_out = creds;
 		TALLOC_FREE(frame);
 		return nt_status;
 	}
@@ -979,8 +954,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 			      "might be needed for a legacy client.\n",
 			      log_escape(frame, creds->account_name)));
 		}
-		TALLOC_FREE(creds);
-		ZERO_STRUCTP(return_authenticator);
 		TALLOC_FREE(frame);
 		return nt_status;
 	}
@@ -1024,11 +997,56 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 		      log_escape(frame, creds->computer_name)));
 	}
 
-	*creds_out = creds;
 	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
 }
 
+/*
+ * NOTE: The following functions are nearly identical to the ones available in
+ * source3/rpc_server/srv_nelog_nt.c
+ * The reason we keep 2 copies is that they use different structures to
+ * represent the auth_info and the decrpc pipes.
+ */
+static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
+						    TALLOC_CTX *mem_ctx,
+						    const char *computer_name,
+						    struct netr_Authenticator *received_authenticator,
+						    struct netr_Authenticator *return_authenticator,
+						    struct netlogon_creds_CredentialState **creds_out)
+{
+	NTSTATUS nt_status;
+	struct netlogon_creds_CredentialState *creds = NULL;
+	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
+	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
+
+	dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
+
+	nt_status = schannel_check_creds_state(mem_ctx,
+					       dce_call->conn->dce_ctx->lp_ctx,
+					       computer_name,
+					       received_authenticator,
+					       return_authenticator,
+					       &creds);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		ZERO_STRUCTP(return_authenticator);
+		return nt_status;
+	}
+
+	nt_status = dcesrv_netr_check_schannel(dce_call,
+					       creds,
+					       auth_type,
+					       auth_level,
+					       dce_call->pkt.u.request.opnum);
+	if (!NT_STATUS_IS_OK(nt_status)) {
+		TALLOC_FREE(creds);
+		ZERO_STRUCTP(return_authenticator);
+		return nt_status;
+	}
+
+	*creds_out = creds;
+	return NT_STATUS_OK;
+}
+
 /*
   Change the machine account password for the currently connected
   client.  Supplies only the NT#.
-- 
2.41.0


From b95d07ebad63544c585a43590bdeaf5247cbaf46 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 17:15:36 +0100
Subject: [PATCH 125/146] CVE-2022-38023 s4:rpc_server/netlogon: make sure all
 dcesrv_netr_LogonSamLogon*() calls go through dcesrv_netr_check_schannel()

We'll soon add some additional contraints in dcesrv_netr_check_schannel(),
which are also required for dcesrv_netr_LogonSamLogonEx().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 689507457f5e6666488732f91a355a2183fb1662)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 36 +++++++++++++++----
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 94adb74165f..f4413d7a03b 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -1408,6 +1408,35 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL
 	struct auth_usersupplied_info *user_info = NULL;
 	NTSTATUS nt_status;
 	struct tevent_req *subreq = NULL;
+	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
+	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
+
+	dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
+
+	switch (dce_call->pkt.u.request.opnum) {
+	case NDR_NETR_LOGONSAMLOGON:
+	case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
+		/*
+		 * These already called dcesrv_netr_check_schannel()
+		 * via dcesrv_netr_creds_server_step_check()
+		 */
+		break;
+	case NDR_NETR_LOGONSAMLOGONEX:
+	default:
+		if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+			return NT_STATUS_ACCESS_DENIED;
+		}
+
+		nt_status = dcesrv_netr_check_schannel(dce_call,
+						       creds,
+						       auth_type,
+						       auth_level,
+						       dce_call->pkt.u.request.opnum);
+		if (!NT_STATUS_IS_OK(nt_status)) {
+			return nt_status;
+		}
+		break;
+	}
 
 	*r->out.authoritative = 1;
 
@@ -1739,7 +1768,6 @@ static void dcesrv_netr_LogonSamLogon_base_reply(
 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 				     struct netr_LogonSamLogonEx *r)
 {
-	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
 	struct dcesrv_netr_LogonSamLogon_base_state *state;
 	NTSTATUS nt_status;
 
@@ -1777,12 +1805,6 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call,
 		return nt_status;
 	}
 
-	dcesrv_call_auth_info(dce_call, &auth_type, NULL);
-
-	if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
-		return NT_STATUS_ACCESS_DENIED;
-	}
-
 	nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
 
 	if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
-- 
2.41.0


From 5e5019dbdf9b49e07bd5f88bafa7275d5d076166 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 16:53:35 +0100
Subject: [PATCH 126/146] CVE-2022-38023 docs-xml/smbdotconf: add "server
 schannel require seal[:COMPUTERACCOUNT]" options

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 7732a4b0bde1d9f98a0371f17d22648495329470)
---
 .../smbdotconf/security/serverschannel.xml    |  43 ++++++-
 .../security/serverschannelrequireseal.xml    | 118 ++++++++++++++++++
 lib/param/loadparm.c                          |   1 +
 source3/param/loadparm.c                      |   1 +
 4 files changed, 157 insertions(+), 6 deletions(-)
 create mode 100644 docs-xml/smbdotconf/security/serverschannelrequireseal.xml

diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml
index 3e66df1c203..42a657912ca 100644
--- a/docs-xml/smbdotconf/security/serverschannel.xml
+++ b/docs-xml/smbdotconf/security/serverschannel.xml
@@ -12,19 +12,37 @@
 	the hardcoded behavior in future).
     </para>
 
-    <para>
-	Samba will complain in the log files at log level 0,
-	about the security problem if the option is not set to "yes".
+    <para><emphasis>Avoid using this option!</emphasis> Use explicit '<smbconfoption name="server require schannel:COMPUTERACCOUNT">no</smbconfoption>' instead!
     </para>
+
+    <para>
+	Samba will log an error in the log files at log level 0
+	if legacy a client is rejected or allowed without an explicit,
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT">no</smbconfoption>' option
+	for the client. The message will indicate
+	the explicit '<smbconfoption name="server require schannel:COMPUTERACCOUNT">no</smbconfoption>'
+	line to be added, if the legacy client software requires it. (The log level can be adjusted with
+	'<smbconfoption name="CVE_2020_1472:error_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+	</para>
+
     <para>
-	See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497
+	This allows admins to use "auto" only for a short grace period,
+	in order to collect the explicit
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT">no</smbconfoption>' options.
     </para>
 
-    <para>If you still have legacy domain members use the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.
+    <para>
+	See <ulink url="https://www.samba.org/samba/security/CVE-2020-1472.html">CVE-2020-1472(ZeroLogon)</ulink>,
+	<ulink url="https://bugzilla.samba.org/show_bug.cgi?id=14497">https://bugzilla.samba.org/show_bug.cgi?id=14497</ulink>.
     </para>
 
     <para>This option is over-ridden by the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.</para>
 
+    <para>This option is over-ridden by the effective value of 'yes' from
+    the '<smbconfoption name="server schannel require seal:COMPUTERACCOUNT"/>'
+    and/or '<smbconfoption name="server schannel require seal"/>' options.</para>
+
 </description>
 
 <value type="default">yes</value>
@@ -48,6 +66,9 @@
 	about the security problem if the option is not set to "no",
 	but the related computer is actually using the netlogon
 	secure channel (schannel) feature.
+	(The log level can be adjusted with
+	'<smbconfoption name="CVE_2020_1472:warn_about_unused_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
     </para>
 
     <para>
@@ -56,15 +77,25 @@
     </para>
 
     <para>
-	See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497
+	See <ulink url="https://www.samba.org/samba/security/CVE-2020-1472.html">CVE-2020-1472(ZeroLogon)</ulink>,
+	<ulink url="https://bugzilla.samba.org/show_bug.cgi?id=14497">https://bugzilla.samba.org/show_bug.cgi?id=14497</ulink>.
     </para>
 
     <para>This option overrides the <smbconfoption name="server schannel"/> option.</para>
 
+    <para>This option is over-ridden by the effective value of 'yes' from
+    the '<smbconfoption name="server schannel require seal:COMPUTERACCOUNT"/>'
+    and/or '<smbconfoption name="server schannel require seal"/>' options.</para>
+    <para>Which means '<smbconfoption name="server require schannel:COMPUTERACCOUNT">no</smbconfoption>'
+    is only useful in combination with '<smbconfoption name="server schannel require seal:COMPUTERACCOUNT">no</smbconfoption>'</para>
+
     <programlisting>
 	server require schannel:LEGACYCOMPUTER1$ = no
+	server require schannel seal:LEGACYCOMPUTER1$ = no
 	server require schannel:NASBOX$ = no
+	server require schannel seal:NASBOX$ = no
 	server require schannel:LEGACYCOMPUTER2$ = no
+	server require schannel seal:LEGACYCOMPUTER2$ = no
     </programlisting>
 </description>
 
diff --git a/docs-xml/smbdotconf/security/serverschannelrequireseal.xml b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml
new file mode 100644
index 00000000000..d4620d1252d
--- /dev/null
+++ b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml
@@ -0,0 +1,118 @@
+<samba:parameter name="server schannel require seal"
+                 context="G"
+                 type="boolean"
+                 deprecated="1"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+	<para>
+	This option is deprecated and will be removed in future,
+	as it is a security problem if not set to "yes" (which will be
+	the hardcoded behavior in future).
+	</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.
+	</para>
+
+	<para>
+	The option is modelled after the registry key available on Windows.
+	</para>
+
+	<programlisting>
+	HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\RequireSeal=2
+	</programlisting>
+
+	<para>
+	<emphasis>Avoid using this option!</emphasis> Use the per computer account specific option
+	'<smbconfoption name="server schannel require seal:COMPUTERACCOUNT"/>' instead!
+	Which is available with the patches for
+	<ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>
+	see <ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+	</para>
+
+	<para>
+	Samba will log an error in the log files at log level 0
+	if legacy a client is rejected or allowed without an explicit,
+	'<smbconfoption name="server schannel require seal:COMPUTERACCOUNT">no</smbconfoption>' option
+	for the client. The message will indicate
+	the explicit '<smbconfoption name="server schannel require seal:COMPUTERACCOUNT">no</smbconfoption>'
+	line to be added, if the legacy client software requires it. (The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:error_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+	</para>
+
+	<para>This allows admins to use "no" only for a short grace period,
+	in order to collect the explicit
+	'<smbconfoption name="server schannel require seal:COMPUTERACCOUNT">no</smbconfoption>' options.</para>
+
+	<para>
+	When set to 'yes' this option overrides the
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT"/>' and
+	'<smbconfoption name="server schannel"/>' options and implies
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT">yes</smbconfoption>'.
+	</para>
+
+	<para>
+	This option is over-ridden by the <smbconfoption name="server schannel require seal:COMPUTERACCOUNT"/> option.
+	</para>
+
+</description>
+
+<value type="default">yes</value>
+</samba:parameter>
+
+<samba:parameter name="server schannel require seal:COMPUTERACCOUNT"
+                 context="G"
+                 type="string"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+
+	<para>
+	If you still have legacy domain members, which required "server schannel require seal = no" before,
+	it is possible to specify explicit exception per computer account
+	by using 'server schannel require seal:COMPUTERACCOUNT = no' as option.
+	Note that COMPUTERACCOUNT has to be the sAMAccountName value of
+	the computer account (including the trailing '$' sign).
+	</para>
+
+	<para>
+	Samba will log a complaint in the log files at log level 0
+	about the security problem if the option is set to "no",
+	but the related computer does not require it.
+	(The log level can be adjusted with
+	'<smbconfoption name="CVE_2022_38023:warn_about_unused_debug_level">1</smbconfoption>'
+	in order to complain only at a higher log level).
+	</para>
+
+	<para>
+	Samba will warn in the log files at log level 5,
+	if a setting is still needed for the specified computer account.
+	</para>
+
+	<para>
+	See <ulink url="https://www.samba.org/samba/security/CVE-2022-38023.html">CVE-2022-38023</ulink>,
+	<ulink url="https://bugzilla.samba.org/show_bug.cgi?id=15240">https://bugzilla.samba.org/show_bug.cgi?id=15240</ulink>.
+	</para>
+
+	<para>
+	This option overrides the '<smbconfoption name="server schannel require seal"/>' option.
+	</para>
+
+	<para>
+	When set to 'yes' this option overrides the
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT"/>' and
+	'<smbconfoption name="server schannel"/>' options and implies
+	'<smbconfoption name="server require schannel:COMPUTERACCOUNT">yes</smbconfoption>'.
+	</para>
+
+	<programlisting>
+	server require schannel seal:LEGACYCOMPUTER1$ = no
+	server require schannel seal:NASBOX$ = no
+	server require schannel seal:LEGACYCOMPUTER2$ = no
+	</programlisting>
+</description>
+
+</samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 77a80176f7d..4b3976ebdb6 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2790,6 +2790,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template");
 
 	lpcfg_do_global_parameter(lp_ctx, "server schannel", "True");
+	lpcfg_do_global_parameter(lp_ctx, "server schannel require seal", "True");
 	lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True");
 
 	lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True");
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 1cf468b1009..8dab202fc17 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -659,6 +659,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 	Globals.require_strong_key = true;
 	Globals.reject_md5_servers = true;
 	Globals.server_schannel = true;
+	Globals.server_schannel_require_seal = true;
 	Globals.reject_md5_clients = true;
 	Globals.read_raw = true;
 	Globals.write_raw = true;
-- 
2.41.0


From 83be39efadc4c4fad4a873e23016e1c5a8d65380 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 2 Dec 2022 14:31:26 +0100
Subject: [PATCH 127/146] CVE-2022-38023 s4:rpc_server/netlogon: add a per
 connection cache to dcesrv_netr_check_schannel()

It's enough to warn the admin once per connection.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 3c57608e1109c1d6e8bb8fbad2ef0b5d79d00e1a)
---
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 193 ++++++++++++++----
 1 file changed, 153 insertions(+), 40 deletions(-)

diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index f4413d7a03b..474d0806e6b 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -845,23 +845,105 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca
 	return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
 }
 
-static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
-					   const struct netlogon_creds_CredentialState *creds,
-					   enum dcerpc_AuthType auth_type,
-					   enum dcerpc_AuthLevel auth_level,
-					   uint16_t opnum)
+struct dcesrv_netr_check_schannel_state {
+	struct dom_sid account_sid;
+	enum dcerpc_AuthType auth_type;
+	enum dcerpc_AuthLevel auth_level;
+
+	bool schannel_global_required;
+	bool schannel_required;
+	bool schannel_explicitly_set;
+
+	NTSTATUS result;
+};
+
+static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call,
+						     const struct netlogon_creds_CredentialState *creds,
+						     enum dcerpc_AuthType auth_type,
+						     enum dcerpc_AuthLevel auth_level,
+						     struct dcesrv_netr_check_schannel_state **_s)
 {
 	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
-	TALLOC_CTX *frame = talloc_stackframe();
-	NTSTATUS nt_status;
 	int schannel = lpcfg_server_schannel(lp_ctx);
 	bool schannel_global_required = (schannel == true);
 	bool schannel_required = schannel_global_required;
 	const char *explicit_opt = NULL;
+#define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1)
+	struct dcesrv_netr_check_schannel_state *s = NULL;
+	NTSTATUS status;
+
+	*_s = NULL;
+
+	s = dcesrv_iface_state_find_conn(dce_call,
+			DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
+			struct dcesrv_netr_check_schannel_state);
+	if (s != NULL) {
+		if (!dom_sid_equal(&s->account_sid, creds->sid)) {
+			goto new_state;
+		}
+		if (s->auth_type != auth_type) {
+			goto new_state;
+		}
+		if (s->auth_level != auth_level) {
+			goto new_state;
+		}
+
+		*_s = s;
+		return NT_STATUS_OK;
+	}
+
+new_state:
+	TALLOC_FREE(s);
+	s = talloc_zero(dce_call,
+			struct dcesrv_netr_check_schannel_state);
+	if (s == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	s->account_sid = *creds->sid;
+	s->auth_type = auth_type;
+	s->auth_level = auth_level;
+	s->result = NT_STATUS_MORE_PROCESSING_REQUIRED;
+
+	/*
+	 * We don't use lpcfg_parm_bool(), as we
+	 * need the explicit_opt pointer in order to
+	 * adjust the debug messages.
+	 */
+	explicit_opt = lpcfg_get_parametric(lp_ctx,
+					    NULL,
+					    "server require schannel",
+					    creds->account_name);
+	if (explicit_opt != NULL) {
+		schannel_required = lp_bool(explicit_opt);
+	}
+
+	s->schannel_global_required = schannel_global_required;
+	s->schannel_required = schannel_required;
+	s->schannel_explicitly_set = explicit_opt != NULL;
+
+	status = dcesrv_iface_state_store_conn(dce_call,
+			DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
+			s);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	*_s = s;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call,
+						struct dcesrv_netr_check_schannel_state *s,
+						const struct netlogon_creds_CredentialState *creds,
+						uint16_t opnum)
+{
+	struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 	int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
 		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
 	int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
 		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
+	TALLOC_CTX *frame = talloc_stackframe();
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	const char *opname = "<unknown>";
 	const char *reason = "<unknown>";
@@ -870,37 +952,43 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
-	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+	if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
 			reason = "WITH SEALED";
-		} else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+		} else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
 			reason = "WITH SIGNED";
 		} else {
-			smb_panic("Schannel without SIGN/SEAL");
+			reason = "WITH INVALID";
+			dbg_lvl = DBGLVL_ERR;
+			s->result = NT_STATUS_INTERNAL_ERROR;
 		}
 	} else {
 		reason = "WITHOUT";
 	}
 
-	/*
-	 * We don't use lpcfg_parm_bool(), as we
-	 * need the explicit_opt pointer in order to
-	 * adjust the debug messages.
-	 */
-	explicit_opt = lpcfg_get_parametric(lp_ctx,
-					    NULL,
-					    "server require schannel",
-					    creds->account_name);
-	if (explicit_opt != NULL) {
-		schannel_required = lp_bool(explicit_opt);
+	if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		if (!NT_STATUS_IS_OK(s->result)) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon): "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(s->result)));
+		TALLOC_FREE(frame);
+		return s->result;
 	}
 
-	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		nt_status = NT_STATUS_OK;
+	if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		s->result = NT_STATUS_OK;
 
-		if (explicit_opt != NULL && !schannel_required) {
+		if (s->schannel_explicitly_set && !s->schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
-		} else if (!schannel_required) {
+		} else if (!s->schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 		}
 
@@ -911,9 +999,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 		      opname, opnum, reason,
 		      log_escape(frame, creds->account_name),
 		      log_escape(frame, creds->computer_name),
-		      nt_errstr(nt_status)));
-
-		if (explicit_opt != NULL && !schannel_required) {
+		      nt_errstr(s->result)));
+		if (s->schannel_explicitly_set && !s->schannel_required) {
 			DEBUG(CVE_2020_1472_warn_level, (
 			      "CVE-2020-1472(ZeroLogon): "
 			      "Option 'server require schannel:%s = no' not needed for '%s'!\n",
@@ -922,13 +1009,13 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 		}
 
 		TALLOC_FREE(frame);
-		return nt_status;
+		return s->result;
 	}
 
-	if (schannel_required) {
-		nt_status = NT_STATUS_ACCESS_DENIED;
+	if (s->schannel_required) {
+		s->result = NT_STATUS_ACCESS_DENIED;
 
-		if (explicit_opt != NULL) {
+		if (s->schannel_explicitly_set) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
 		} else {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
@@ -941,8 +1028,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 		      opname, opnum, reason,
 		      log_escape(frame, creds->account_name),
 		      log_escape(frame, creds->computer_name),
-		      nt_errstr(nt_status)));
-		if (explicit_opt != NULL) {
+		      nt_errstr(s->result)));
+		if (s->schannel_explicitly_set) {
 			D_NOTICE("CVE-2020-1472(ZeroLogon): Option "
 				"'server require schannel:%s = yes' "
 				"rejects access for client.\n",
@@ -955,12 +1042,12 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 			      log_escape(frame, creds->account_name)));
 		}
 		TALLOC_FREE(frame);
-		return nt_status;
+		return s->result;
 	}
 
-	nt_status = NT_STATUS_OK;
+	s->result = NT_STATUS_OK;
 
-	if (explicit_opt != NULL) {
+	if (s->schannel_explicitly_set) {
 		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
 		dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
@@ -973,9 +1060,9 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 	      opname, opnum, reason,
 	      log_escape(frame, creds->account_name),
 	      log_escape(frame, creds->computer_name),
-	      nt_errstr(nt_status)));
+	      nt_errstr(s->result)));
 
-	if (explicit_opt != NULL) {
+	if (s->schannel_explicitly_set) {
 		D_INFO("CVE-2020-1472(ZeroLogon): Option "
 		       "'server require schannel:%s = no' "
 		       "still needed for '%s'!\n",
@@ -998,6 +1085,32 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
 	}
 
 	TALLOC_FREE(frame);
+	return s->result;
+}
+
+static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call,
+					   const struct netlogon_creds_CredentialState *creds,
+					   enum dcerpc_AuthType auth_type,
+					   enum dcerpc_AuthLevel auth_level,
+					   uint16_t opnum)
+{
+	struct dcesrv_netr_check_schannel_state *s = NULL;
+	NTSTATUS status;
+
+	status = dcesrv_netr_check_schannel_get_state(dce_call,
+						      creds,
+						      auth_type,
+						      auth_level,
+						      &s);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	return NT_STATUS_OK;
 }
 
-- 
2.41.0


From ef51add9def64d75f17b394924c238fffc81168f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 25 Nov 2022 14:05:30 +0100
Subject: [PATCH 128/146] CVE-2022-38023 s4:rpc_server/netlogon: implement
 "server schannel require seal[:COMPUTERACCOUNT]"

By default we'll now require schannel connections with
privacy/sealing/encryption.

But we allow exceptions for specific computer/trust accounts.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit b3ed90a0541a271a7c6d4bee1201fa47adc3c0c1)
---
 selftest/target/Samba4.pm                     |  27 ++
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 244 +++++++++++++++++-
 2 files changed, 270 insertions(+), 1 deletion(-)

diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index aafb9ee14ca..c267b81d865 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -1734,9 +1734,23 @@ sub provision_ad_dc_ntvfs($$)
 	server require schannel:schannel10\$ = no
 	server require schannel:schannel11\$ = no
 	server require schannel:torturetest\$ = no
+	server schannel require seal:schannel0\$ = no
+	server schannel require seal:schannel1\$ = no
+	server schannel require seal:schannel2\$ = no
+	server schannel require seal:schannel3\$ = no
+	server schannel require seal:schannel4\$ = no
+	server schannel require seal:schannel5\$ = no
+	server schannel require seal:schannel6\$ = no
+	server schannel require seal:schannel7\$ = no
+	server schannel require seal:schannel8\$ = no
+	server schannel require seal:schannel9\$ = no
+	server schannel require seal:schannel10\$ = no
+	server schannel require seal:schannel11\$ = no
+	server schannel require seal:torturetest\$ = no
 
 	# needed for 'samba.tests.auth_log' tests
 	server require schannel:LOCALDC\$ = no
+	server schannel require seal:LOCALDC\$ = no
 	";
 	my $extra_provision_options = ["--use-ntvfs"];
 	my $ret = $self->provision($prefix,
@@ -2166,6 +2180,19 @@ sub provision_ad_dc($$$$$$)
 	server require schannel:schannel10\$ = no
 	server require schannel:schannel11\$ = no
 	server require schannel:torturetest\$ = no
+	server schannel require seal:schannel0\$ = no
+	server schannel require seal:schannel1\$ = no
+	server schannel require seal:schannel2\$ = no
+	server schannel require seal:schannel3\$ = no
+	server schannel require seal:schannel4\$ = no
+	server schannel require seal:schannel5\$ = no
+	server schannel require seal:schannel6\$ = no
+	server schannel require seal:schannel7\$ = no
+	server schannel require seal:schannel8\$ = no
+	server schannel require seal:schannel9\$ = no
+	server schannel require seal:schannel10\$ = no
+	server schannel require seal:schannel11\$ = no
+	server schannel require seal:torturetest\$ = no
 
 	auth event notification = true
 	dsdb event notification = true
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 474d0806e6b..343cd53473c 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -65,9 +65,11 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context
 	bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
 	int schannel = lpcfg_server_schannel(lp_ctx);
 	bool schannel_global_required = (schannel == true);
+	bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
 	static bool warned_global_nt4_once = false;
 	static bool warned_global_md5_once = false;
 	static bool warned_global_schannel_once = false;
+	static bool warned_global_seal_once = false;
 
 	if (global_allow_nt4_crypto && !warned_global_nt4_once) {
 		/*
@@ -99,6 +101,16 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context
 		warned_global_schannel_once = true;
 	}
 
+	if (!global_require_seal && !warned_global_seal_once) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		D_ERR("CVE-2022-38023 (and others): "
+		      "Please configure 'server schannel require seal = yes' (the default), "
+		      "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
+		warned_global_seal_once = true;
+	}
+
 	return dcesrv_interface_bind_reject_connect(context, iface);
 }
 
@@ -854,6 +866,10 @@ struct dcesrv_netr_check_schannel_state {
 	bool schannel_required;
 	bool schannel_explicitly_set;
 
+	bool seal_global_required;
+	bool seal_required;
+	bool seal_explicitly_set;
+
 	NTSTATUS result;
 };
 
@@ -868,6 +884,9 @@ static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *d
 	bool schannel_global_required = (schannel == true);
 	bool schannel_required = schannel_global_required;
 	const char *explicit_opt = NULL;
+	bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
+	bool require_seal = global_require_seal;
+	const char *explicit_seal_opt = NULL;
 #define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1)
 	struct dcesrv_netr_check_schannel_state *s = NULL;
 	NTSTATUS status;
@@ -905,6 +924,19 @@ new_state:
 	s->auth_level = auth_level;
 	s->result = NT_STATUS_MORE_PROCESSING_REQUIRED;
 
+	/*
+	 * We don't use lpcfg_parm_bool(), as we
+	 * need the explicit_opt pointer in order to
+	 * adjust the debug messages.
+	 */
+	explicit_seal_opt = lpcfg_get_parametric(lp_ctx,
+						 NULL,
+						 "server schannel require seal",
+						 creds->account_name);
+	if (explicit_seal_opt != NULL) {
+		require_seal = lp_bool(explicit_seal_opt);
+	}
+
 	/*
 	 * We don't use lpcfg_parm_bool(), as we
 	 * need the explicit_opt pointer in order to
@@ -922,6 +954,10 @@ new_state:
 	s->schannel_required = schannel_required;
 	s->schannel_explicitly_set = explicit_opt != NULL;
 
+	s->seal_global_required = global_require_seal;
+	s->seal_required = require_seal;
+	s->seal_explicitly_set = explicit_seal_opt != NULL;
+
 	status = dcesrv_iface_state_store_conn(dce_call,
 			DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC,
 			s);
@@ -943,6 +979,10 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
 	int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
 		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
+	int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
+	int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
 	TALLOC_CTX *frame = talloc_stackframe();
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	const char *opname = "<unknown>";
@@ -972,18 +1012,107 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 		}
 
 		DEBUG(dbg_lvl, (
-		      "CVE-2020-1472(ZeroLogon): "
+		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(s->result)));
+		TALLOC_FREE(frame);
+		return s->result;
+	}
+
+	if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL &&
+	    s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
+	{
+		s->result = NT_STATUS_OK;
+
+		if (s->schannel_explicitly_set && !s->schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
+		} else if (!s->schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		}
+		if (s->seal_explicitly_set && !s->seal_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level);
+		} else if (!s->seal_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
 		      "%s request (opnum[%u]) %s schannel from "
 		      "client_account[%s] client_computer_name[%s] %s\n",
 		      opname, opnum, reason,
 		      log_escape(frame, creds->account_name),
 		      log_escape(frame, creds->computer_name),
 		      nt_errstr(s->result)));
+
+		if (s->schannel_explicitly_set && !s->schannel_required) {
+			DEBUG(CVE_2020_1472_warn_level, (
+			      "CVE-2020-1472(ZeroLogon): "
+			      "Option 'server require schannel:%s = no' not needed for '%s'!\n",
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name)));
+		}
+
+		if (s->seal_explicitly_set && !s->seal_required) {
+			DEBUG(CVE_2022_38023_warn_level, (
+			      "CVE-2022-38023: "
+			      "Option 'server schannel require seal:%s = no' not needed for '%s'!\n",
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name)));
+		}
+
 		TALLOC_FREE(frame);
 		return s->result;
 	}
 
 	if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (s->seal_required) {
+			s->result = NT_STATUS_ACCESS_DENIED;
+
+			if (s->seal_explicitly_set) {
+				dbg_lvl = DBGLVL_NOTICE;
+			} else {
+				dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+			}
+			if (s->schannel_explicitly_set && !s->schannel_required) {
+				dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level);
+			}
+
+			DEBUG(dbg_lvl, (
+			      "CVE-2022-38023: "
+			      "%s request (opnum[%u]) %s schannel from "
+			      "from client_account[%s] client_computer_name[%s] %s\n",
+			      opname, opnum, reason,
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name),
+			      nt_errstr(s->result)));
+			if (s->seal_explicitly_set) {
+				D_NOTICE("CVE-2022-38023: Option "
+					 "'server schannel require seal:%s = yes' "
+					 "rejects access for client.\n",
+					 log_escape(frame, creds->account_name));
+			} else {
+				DEBUG(CVE_2020_1472_error_level, (
+				      "CVE-2022-38023: Check if option "
+				      "'server schannel require seal:%s = no' "
+				      "might be needed for a legacy client.\n",
+				      log_escape(frame, creds->account_name)));
+			}
+			if (s->schannel_explicitly_set && !s->schannel_required) {
+				DEBUG(CVE_2020_1472_warn_level, (
+				      "CVE-2020-1472(ZeroLogon): Option "
+				      "'server require schannel:%s = no' "
+				      "not needed for '%s'!\n",
+				      log_escape(frame, creds->account_name),
+				      log_escape(frame, creds->computer_name)));
+			}
+			TALLOC_FREE(frame);
+			return s->result;
+		}
+
 		s->result = NT_STATUS_OK;
 
 		if (s->schannel_explicitly_set && !s->schannel_required) {
@@ -991,6 +1120,11 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 		} else if (!s->schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 		}
+		if (s->seal_explicitly_set && !s->seal_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		} else if (!s->seal_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
 
 		DEBUG(dbg_lvl, (
 		      "CVE-2020-1472(ZeroLogon): "
@@ -1007,11 +1141,81 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 			      log_escape(frame, creds->account_name),
 			      log_escape(frame, creds->computer_name)));
 		}
+		if (s->seal_explicitly_set && !s->seal_required) {
+			D_INFO("CVE-2022-38023: "
+			       "Option 'server schannel require seal:%s = no' still needed for '%s'!\n",
+			       log_escape(frame, creds->account_name),
+			       log_escape(frame, creds->computer_name));
+		} else if (!s->seal_required) {
+			/*
+			 * admins should set
+			 * server schannel require seal:COMPUTER$ = no
+			 * in order to avoid the level 0 messages.
+			 * Over time they can switch the global value
+			 * to be strict.
+			 */
+			DEBUG(CVE_2022_38023_error_level, (
+			      "CVE-2022-38023: "
+			      "Please use 'server schannel require seal:%s = no' "
+			      "for '%s' to avoid this warning!\n",
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name)));
+		}
 
 		TALLOC_FREE(frame);
 		return s->result;
 	}
 
+	if (s->seal_required) {
+		s->result = NT_STATUS_ACCESS_DENIED;
+
+		if (s->seal_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
+		} else {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
+		if (!s->schannel_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+		} else if (s->schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
+		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "from client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(s->result)));
+		if (s->seal_explicitly_set) {
+			D_NOTICE("CVE-2022-38023: Option "
+			         "'server schannel require seal:%s = yes' "
+			         "rejects access for client.\n",
+			         log_escape(frame, creds->account_name));
+		} else {
+			DEBUG(CVE_2022_38023_error_level, (
+			      "CVE-2022-38023: Check if option "
+			      "'server schannel require seal:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      log_escape(frame, creds->account_name)));
+		}
+		if (!s->schannel_explicitly_set) {
+			DEBUG(CVE_2020_1472_error_level, (
+			      "CVE-2020-1472(ZeroLogon): Check if option "
+			      "'server require schannel:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      log_escape(frame, creds->account_name)));
+		} else if (s->schannel_required) {
+			D_NOTICE("CVE-2022-38023: Option "
+			         "'server require schannel:%s = yes' "
+			         "also rejects access for client.\n",
+			         log_escape(frame, creds->account_name));
+		}
+		TALLOC_FREE(frame);
+		return s->result;
+	}
+
 	if (s->schannel_required) {
 		s->result = NT_STATUS_ACCESS_DENIED;
 
@@ -1020,6 +1224,9 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 		} else {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
 		}
+		if (!s->seal_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
 
 		DEBUG(dbg_lvl, (
 		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
@@ -1041,12 +1248,25 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 			      "might be needed for a legacy client.\n",
 			      log_escape(frame, creds->account_name)));
 		}
+		if (!s->seal_explicitly_set) {
+			DEBUG(CVE_2022_38023_error_level, (
+			      "CVE-2022-38023: Check if option "
+			      "'server schannel require seal:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      log_escape(frame, creds->account_name)));
+		}
 		TALLOC_FREE(frame);
 		return s->result;
 	}
 
 	s->result = NT_STATUS_OK;
 
+	if (s->seal_explicitly_set) {
+		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+	} else {
+		dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+	}
+
 	if (s->schannel_explicitly_set) {
 		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
@@ -1062,6 +1282,28 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca
 	      log_escape(frame, creds->computer_name),
 	      nt_errstr(s->result)));
 
+	if (s->seal_explicitly_set) {
+		D_INFO("CVE-2022-38023: Option "
+		       "'server schannel require seal:%s = no' "
+		       "still needed for '%s'!\n",
+		       log_escape(frame, creds->account_name),
+		       log_escape(frame, creds->computer_name));
+	} else {
+		/*
+		 * admins should set
+		 * server schannel require seal:COMPUTER$ = no
+		 * in order to avoid the level 0 messages.
+		 * Over time they can switch the global value
+		 * to be strict.
+		 */
+		DEBUG(CVE_2022_38023_error_level, (
+		      "CVE-2022-38023: Please use "
+		       "'server schannel require seal:%s = no' "
+		      "for '%s' to avoid this warning!\n",
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name)));
+	}
+
 	if (s->schannel_explicitly_set) {
 		D_INFO("CVE-2020-1472(ZeroLogon): Option "
 		       "'server require schannel:%s = no' "
-- 
2.41.0


From fe38dc0186d3505db4c105f78dc46c2270c43240 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Wed, 30 Nov 2022 15:13:47 +0100
Subject: [PATCH 129/146] CVE-2022-38023 testparm: warn about server/client
 schannel != yes

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit f964c0c357214637f80d0089723b9b11d1b38f7e)
---
 source3/utils/testparm.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index c673ef71a92..aa990b729d7 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -522,6 +522,27 @@ static int do_global_checks(void)
 		ret = 1;
 	}
 
+	if (lp_server_schannel() != true) { /* can be 'auto' */
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'server schannel = yes' (the default). "
+			"Your server is vulernable to \"ZeroLogon\" "
+			"(CVE-2020-1472)\n"
+			"If required use individual "
+			"'server require schannel:COMPUTERACCOUNT$ = no' "
+			"options\n\n");
+	}
+	if (lp_client_schannel() != true) { /* can be 'auto' */
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'client schannel = yes' (the default). "
+			"Your server is vulernable to \"ZeroLogon\" "
+			"(CVE-2020-1472)\n"
+			"If required use individual "
+			"'client schannel:NETBIOSDOMAIN = no' "
+			"options\n\n");
+	}
+
 	return ret;
 }
 
-- 
2.41.0


From c870a61377d0245a3fd25f5d5c8663d965fe469a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 6 Dec 2022 13:36:17 +0100
Subject: [PATCH 130/146] CVE-2022-38023 testparm: warn about unsecure schannel
 related options

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit 4d540473c3d43d048a30dd63efaeae9ff87b2aeb)
---
 source3/utils/testparm.c | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index aa990b729d7..f9253d323aa 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -532,6 +532,37 @@ static int do_global_checks(void)
 			"'server require schannel:COMPUTERACCOUNT$ = no' "
 			"options\n\n");
 	}
+	if (lp_allow_nt4_crypto()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'allow nt4 crypto = no' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023 and others!\n"
+			"If required use individual "
+			"'allow nt4 crypto:COMPUTERACCOUNT$ = yes' "
+			"options\n\n");
+	}
+	if (!lp_reject_md5_clients()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'reject md5 clients = yes' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023!\n"
+			"If required use individual "
+			"'server reject md5 schannel:COMPUTERACCOUNT$ = yes' "
+			"options\n\n");
+	}
+	if (!lp_server_schannel_require_seal()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'server schannel require seal = yes' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023!\n"
+			"If required use individual "
+			"'server schannel require seal:COMPUTERACCOUNT$ = no' "
+			"options\n\n");
+	}
+
 	if (lp_client_schannel() != true) { /* can be 'auto' */
 		fprintf(stderr,
 			"WARNING: You have not configured "
@@ -542,6 +573,36 @@ static int do_global_checks(void)
 			"'client schannel:NETBIOSDOMAIN = no' "
 			"options\n\n");
 	}
+	if (!lp_reject_md5_servers()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'reject md5 servers = yes' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023\n"
+			"If required use individual "
+			"'reject md5 servers:NETBIOSDOMAIN = no' "
+			"options\n\n");
+	}
+	if (!lp_require_strong_key()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'require strong key = yes' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023\n"
+			"If required use individual "
+			"'require strong key:NETBIOSDOMAIN = no' "
+			"options\n\n");
+	}
+	if (!lp_winbind_sealed_pipes()) {
+		fprintf(stderr,
+			"WARNING: You have not configured "
+			"'winbind sealed pipes = yes' (the default). "
+			"Your server is vulernable to "
+			"CVE-2022-38023\n"
+			"If required use individual "
+			"'winbind sealed pipes:NETBIOSDOMAIN = no' "
+			"options\n\n");
+	}
 
 	return ret;
 }
-- 
2.41.0


From 938168a5f7c3225562ed772bf8a9bbecc0badb62 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
Date: Mon, 12 Sep 2022 16:31:05 +0200
Subject: [PATCH 131/146] s3:auth: Flush the GETPWSID in memory cache for NTLM
 auth

Example valgrind output:

==22502== 22,747,002 bytes in 21,049 blocks are possibly lost in loss record 1,075 of 1,075
==22502==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==22502==    by 0x11D7089C: _talloc_pooled_object (in /usr/lib64/libtalloc.so.2.1.16)
==22502==    by 0x9027834: tcopy_passwd (in /usr/lib64/libsmbconf.so.0)
==22502==    by 0x6A1E1A3: pdb_copy_sam_account (in /usr/lib64/libsamba-passdb.so.0.27.2)
==22502==    by 0x6A28AB7: pdb_getsampwnam (in /usr/lib64/libsamba-passdb.so.0.27.2)
==22502==    by 0x65D0BC4: check_sam_security (in /usr/lib64/samba/libauth-samba4.so)
==22502==    by 0x65C70F0: ??? (in /usr/lib64/samba/libauth-samba4.so)
==22502==    by 0x65C781A: auth_check_ntlm_password (in /usr/lib64/samba/libauth-samba4.so)
==22502==    by 0x14E464: ??? (in /usr/sbin/winbindd)
==22502==    by 0x151CED: winbind_dual_SamLogon (in /usr/sbin/winbindd)
==22502==    by 0x152072: winbindd_dual_pam_auth_crap (in /usr/sbin/winbindd)
==22502==    by 0x167DE0: ??? (in /usr/sbin/winbindd)
==22502==    by 0x12F29B12: tevent_common_invoke_fd_handler (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F30086: ??? (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F2E056: ??? (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F2925C: _tevent_loop_once (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x16A243: ??? (in /usr/sbin/winbindd)
==22502==    by 0x16AA04: ??? (in /usr/sbin/winbindd)
==22502==    by 0x12F29F68: tevent_common_invoke_immediate_handler (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F29F8F: tevent_common_loop_immediate (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F2FE3C: ??? (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F2E056: ??? (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F2925C: _tevent_loop_once (in /usr/lib64/libtevent.so.0.9.39)
==22502==    by 0x12F4C7: main (in /usr/sbin/winbindd)

You can find one for each string in pdb_copy_sam_account(), in total
this already has 67 MB in total for this valgrind run.

pdb_getsampwnam() -> memcache_add_talloc(NULL, PDB_GETPWSID_CACHE, ...)

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15169

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>

Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Fri Sep 16 20:30:31 UTC 2022 on sn-devel-184

(cherry picked from commit 9ef2f7345f0d387567fca598cc7008af95598903)
---
 source3/auth/check_samsec.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c
index 53b6da53dc1..4276c3060ed 100644
--- a/source3/auth/check_samsec.c
+++ b/source3/auth/check_samsec.c
@@ -24,6 +24,7 @@
 #include "auth.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "passdb.h"
+#include "lib/util/memcache.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -487,8 +488,6 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge,
 	nt_status = make_server_info_sam(mem_ctx, sampass, server_info);
 	unbecome_root();
 
-	TALLOC_FREE(sampass);
-
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
 		goto done;
@@ -507,6 +506,11 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge,
 	(*server_info)->nss_token |= user_info->was_mapped;
 
 done:
+	/*
+	 * Always flush the getpwsid cache or this will grow indefinetly for
+	 * each NTLM auththentication.
+	 */
+	memcache_flush(NULL, PDB_GETPWSID_CACHE);
 	TALLOC_FREE(sampass);
 	data_blob_free(&user_sess_key);
 	data_blob_free(&lm_sess_key);
-- 
2.41.0


From 296612a8c1dda253e1f2c0618f1f8330e2e23b34 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 22 Dec 2022 16:46:15 +0100
Subject: [PATCH 132/146] 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 | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 7034127ef0b..0c14f02be11 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -199,7 +199,6 @@ sub setup_nt4_dc
 	lanman auth = yes
 	ntlm auth = yes
 	raw NTLMv2 auth = yes
-	server schannel = auto
 
 	rpc_server:epmapper = external
 	rpc_server:spoolss = external
@@ -213,6 +212,22 @@ sub setup_nt4_dc
 	rpc_daemon:spoolssd = fork
 	rpc_daemon:lsasd = fork
 	rpc_daemon:fssd = fork
+
+	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.41.0


From 1a90fc7cbc4054f9815ffaca710b5bdba0dffd6f Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 22 Dec 2022 11:33:12 +0100
Subject: [PATCH 133/146] CVE-2022-38023 s3:rpc_server/netlogon: add
 talloc_stackframe() to dcesrv_netr_creds_server_step_check()

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 38 ++++++++++++---------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 7f6704adbda..f9b674d0052 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1071,6 +1071,7 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 					     struct netr_Authenticator *return_authenticator,
 					     struct netlogon_creds_CredentialState **creds_out)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
 	NTSTATUS status;
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
 	bool schannel_required = schannel_global_required;
@@ -1092,19 +1093,19 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 
 	auth_type = p->auth.auth_type;
 
-	lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers());
+	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
 	if (lp_ctx == NULL) {
 		DEBUG(0, ("loadparm_init_s3 failed\n"));
+		TALLOC_FREE(frame);
 		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);
+		TALLOC_FREE(frame);
 		return status;
 	}
 
@@ -1125,6 +1126,7 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	if (schannel_required) {
 		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 			*creds_out = creds;
+			TALLOC_FREE(frame);
 			return NT_STATUS_OK;
 		}
 
@@ -1132,13 +1134,15 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' is needed! \n",
-			log_escape(mem_ctx, creds->account_name));
+			"'server require schannel:%s = no' "
+			"might be needed for a legacy client.\n",
+			log_escape(frame, creds->account_name));
 		TALLOC_FREE(creds);
 		ZERO_STRUCTP(return_authenticator);
+		TALLOC_FREE(frame);
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
@@ -1157,13 +1161,14 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			"%s request (opnum[%u]) WITH schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"Option 'server require schannel:%s = no' not needed!?\n",
-			log_escape(mem_ctx, creds->account_name));
+			log_escape(frame, creds->account_name));
 
 		*creds_out = creds;
+		TALLOC_FREE(frame);
 		return NT_STATUS_OK;
 	}
 
@@ -1172,24 +1177,25 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			 "%s request (opnum[%u]) without schannel from "
 			 "client_account[%s] client_computer_name[%s]\n",
 			 opname, opnum,
-			 log_escape(mem_ctx, creds->account_name),
-			 log_escape(mem_ctx, creds->computer_name));
+			 log_escape(frame, creds->account_name),
+			 log_escape(frame, creds->computer_name));
 		DBG_INFO("CVE-2020-1472(ZeroLogon): "
 			 "Option 'server require schannel:%s = no' still needed!\n",
-			 log_escape(mem_ctx, creds->account_name));
+			 log_escape(frame, creds->account_name));
 	} else {
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
 			opname, opnum,
-			log_escape(mem_ctx, creds->account_name),
-			log_escape(mem_ctx, creds->computer_name));
+			log_escape(frame, creds->account_name),
+			log_escape(frame, creds->computer_name));
 		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
 			"'server require schannel:%s = no' might be needed!\n",
-			log_escape(mem_ctx, creds->account_name));
+			log_escape(frame, creds->account_name));
 	}
 
 	*creds_out = creds;
+	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
 }
 
-- 
2.41.0


From d3e503e670501186fcce9702b72cda3b03afc0cf Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 21 Dec 2022 18:17:57 +0100
Subject: [PATCH 134/146] CVE-2022-38023 s3:rpc_server/netlogon: re-order
 checking in netr_creds_server_step_check()

This will simplify the following changes.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 40 ++++++++++-----------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index f9b674d0052..b42794eea8d 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1123,13 +1123,27 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		schannel_required = lp_bool(explicit_opt);
 	}
 
-	if (schannel_required) {
-		if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-			*creds_out = creds;
-			TALLOC_FREE(frame);
-			return NT_STATUS_OK;
+	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (!schannel_required) {
+			DBG_ERR("CVE-2020-1472(ZeroLogon): "
+				"%s request (opnum[%u]) WITH schannel from "
+				"client_account[%s] client_computer_name[%s]\n",
+				opname, opnum,
+				log_escape(frame, creds->account_name),
+				log_escape(frame, creds->computer_name));
+		}
+		if (explicit_opt != NULL && !schannel_required) {
+			DBG_ERR("CVE-2020-1472(ZeroLogon): "
+				"Option 'server require schannel:%s = no' not needed!?\n",
+				log_escape(frame, creds->account_name));
 		}
 
+		*creds_out = creds;
+		TALLOC_FREE(frame);
+		return NT_STATUS_OK;
+	}
+
+	if (schannel_required) {
 		DBG_ERR("CVE-2020-1472(ZeroLogon): "
 			"%s request (opnum[%u]) without schannel from "
 			"client_account[%s] client_computer_name[%s]\n",
@@ -1156,22 +1170,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		warned_global_once = true;
 	}
 
-	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) WITH schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"Option 'server require schannel:%s = no' not needed!?\n",
-			log_escape(frame, creds->account_name));
-
-		*creds_out = creds;
-		TALLOC_FREE(frame);
-		return NT_STATUS_OK;
-	}
-
 	if (explicit_opt != NULL) {
 		DBG_INFO("CVE-2020-1472(ZeroLogon): "
 			 "%s request (opnum[%u]) without schannel from "
-- 
2.41.0


From 44de3ae0d4b6f1a728124429dfc748c538714a05 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 22 Dec 2022 11:35:57 +0100
Subject: [PATCH 135/146] CVE-2022-38023 s3:rpc_server/netlogon: improve
 CVE-2020-1472(ZeroLogon) debug messages

In order to avoid generating useless debug messages during make test,
we will use 'CVE_2020_1472:warn_about_unused_debug_level = 3'
and 'CVE_2020_1472:error_debug_level = 2' in order to avoid schannel warnings.

Review with: git show -w

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 149 ++++++++++++++------
 1 file changed, 109 insertions(+), 40 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index b42794eea8d..1d261c9a639 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1078,9 +1078,14 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	const char *explicit_opt = NULL;
 	struct loadparm_context *lp_ctx;
 	struct netlogon_creds_CredentialState *creds = NULL;
+	int CVE_2020_1472_warn_level = DBGLVL_ERR;
+	int CVE_2020_1472_error_level = DBGLVL_ERR;
+	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
+	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
 	uint16_t opnum = p->opnum;
 	const char *opname = "<unknown>";
+	const char *reason = "<unknown>";
 	static bool warned_global_once = false;
 
 	if (creds_out != NULL) {
@@ -1092,6 +1097,7 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	}
 
 	auth_type = p->auth.auth_type;
+	auth_level = p->auth.auth_level;
 
 	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
 	if (lp_ctx == NULL) {
@@ -1100,6 +1106,23 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		return NT_STATUS_INTERNAL_ERROR;
 	}
 
+	CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
+	CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
+		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
+
+	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+			reason = "WITH SEALED";
+		} else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+			reason = "WITH SIGNED";
+		} else {
+			smb_panic("Schannel without SIGN/SEAL");
+		}
+	} else {
+		reason = "WITHOUT";
+	}
+
 	status = schannel_check_creds_state(mem_ctx, lp_ctx,
 					    computer_name, received_authenticator,
 					    return_authenticator, &creds);
@@ -1124,40 +1147,69 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 	}
 
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
-		if (!schannel_required) {
-			DBG_ERR("CVE-2020-1472(ZeroLogon): "
-				"%s request (opnum[%u]) WITH schannel from "
-				"client_account[%s] client_computer_name[%s]\n",
-				opname, opnum,
-				log_escape(frame, creds->account_name),
-				log_escape(frame, creds->computer_name));
+		status = NT_STATUS_OK;
+
+		if (explicit_opt != NULL && !schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
+		} else if (!schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon): "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(status)));
+
 		if (explicit_opt != NULL && !schannel_required) {
-			DBG_ERR("CVE-2020-1472(ZeroLogon): "
-				"Option 'server require schannel:%s = no' not needed!?\n",
-				log_escape(frame, creds->account_name));
+			DEBUG(CVE_2020_1472_warn_level, (
+			      "CVE-2020-1472(ZeroLogon): "
+			      "Option 'server require schannel:%s = no' not needed for '%s'!\n",
+			      log_escape(frame, creds->account_name),
+			      log_escape(frame, creds->computer_name)));
 		}
 
 		*creds_out = creds;
 		TALLOC_FREE(frame);
-		return NT_STATUS_OK;
+		return status;
 	}
 
 	if (schannel_required) {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) without schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' "
-			"might be needed for a legacy client.\n",
-			log_escape(frame, creds->account_name));
+		status = NT_STATUS_ACCESS_DENIED;
+
+		if (explicit_opt != NULL) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
+		} else {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+		}
+
+		DEBUG(dbg_lvl, (
+		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+		      "%s request (opnum[%u]) %s schannel from "
+		      "client_account[%s] client_computer_name[%s] %s\n",
+		      opname, opnum, reason,
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name),
+		      nt_errstr(status)));
+		if (explicit_opt != NULL) {
+			D_NOTICE("CVE-2020-1472(ZeroLogon): Option "
+				"'server require schannel:%s = yes' "
+				"rejects access for client.\n",
+				log_escape(frame, creds->account_name));
+		} else {
+			DEBUG(CVE_2020_1472_error_level, (
+			      "CVE-2020-1472(ZeroLogon): Check if option "
+			      "'server require schannel:%s = no' "
+			      "might be needed for a legacy client.\n",
+			      log_escape(frame, creds->account_name)));
+		}
 		TALLOC_FREE(creds);
 		ZERO_STRUCTP(return_authenticator);
 		TALLOC_FREE(frame);
-		return NT_STATUS_ACCESS_DENIED;
+		return status;
 	}
 
 	if (!schannel_global_required && !warned_global_once) {
@@ -1170,26 +1222,43 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		warned_global_once = true;
 	}
 
+	status = NT_STATUS_OK;
+
 	if (explicit_opt != NULL) {
-		DBG_INFO("CVE-2020-1472(ZeroLogon): "
-			 "%s request (opnum[%u]) without schannel from "
-			 "client_account[%s] client_computer_name[%s]\n",
-			 opname, opnum,
-			 log_escape(frame, creds->account_name),
-			 log_escape(frame, creds->computer_name));
-		DBG_INFO("CVE-2020-1472(ZeroLogon): "
-			 "Option 'server require schannel:%s = no' still needed!\n",
-			 log_escape(frame, creds->account_name));
+		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
-		DBG_ERR("CVE-2020-1472(ZeroLogon): "
-			"%s request (opnum[%u]) without schannel from "
-			"client_account[%s] client_computer_name[%s]\n",
-			opname, opnum,
-			log_escape(frame, creds->account_name),
-			log_escape(frame, creds->computer_name));
-		DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option "
-			"'server require schannel:%s = no' might be needed!\n",
-			log_escape(frame, creds->account_name));
+		dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+	}
+
+	DEBUG(dbg_lvl, (
+	      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
+	      "%s request (opnum[%u]) %s schannel from "
+	      "client_account[%s] client_computer_name[%s] %s\n",
+	      opname, opnum, reason,
+	      log_escape(frame, creds->account_name),
+	      log_escape(frame, creds->computer_name),
+	      nt_errstr(status)));
+
+	if (explicit_opt != NULL) {
+		D_INFO("CVE-2020-1472(ZeroLogon): Option "
+		       "'server require schannel:%s = no' "
+		       "still needed for '%s'!\n",
+		       log_escape(frame, creds->account_name),
+		       log_escape(frame, creds->computer_name));
+	} else {
+		/*
+		 * admins should set
+		 * server require schannel:COMPUTER$ = no
+		 * in order to avoid the level 0 messages.
+		 * Over time they can switch the global value
+		 * to be strict.
+		 */
+		DEBUG(CVE_2020_1472_error_level, (
+		      "CVE-2020-1472(ZeroLogon): "
+		      "Please use 'server require schannel:%s = no' "
+		      "for '%s' to avoid this warning!\n",
+		      log_escape(frame, creds->account_name),
+		      log_escape(frame, creds->computer_name)));
 	}
 
 	*creds_out = creds;
-- 
2.41.0


From 7e0bfe3db2b4d274b3bf2e5f011ae8207ce6f4ab Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 21 Dec 2022 18:37:05 +0100
Subject: [PATCH 136/146] 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>
---
 selftest/target/Samba3.pm | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 0c14f02be11..e8a4c3bbbb6 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -140,7 +140,7 @@ sub getlog_env_app($$$)
 	close(LOG);
 
 	return "" if $out eq $title;
- 
+
 	return $out;
 }
 
@@ -200,6 +200,21 @@ sub setup_nt4_dc
 	ntlm auth = yes
 	raw NTLMv2 auth = yes
 
+	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
+
 	rpc_server:epmapper = external
 	rpc_server:spoolss = external
 	rpc_server:lsarpc = external
@@ -1588,7 +1603,7 @@ sub provision($$$$$$$$$)
 	my $nmbdsockdir="$prefix_abs/nmbd";
 	unlink($nmbdsockdir);
 
-	## 
+	##
 	## create the test directory layout
 	##
 	die ("prefix_abs = ''") if $prefix_abs eq "";
@@ -2393,7 +2408,7 @@ sub provision($$$$$$$$$)
 	unless (open(PASSWD, ">$nss_wrapper_passwd")) {
            warn("Unable to open $nss_wrapper_passwd");
            return undef;
-        } 
+        }
 	print PASSWD "nobody:x:$uid_nobody:$gid_nobody:nobody gecos:$prefix_abs:/bin/false
 $unix_name:x:$unix_uid:$unix_gids[0]:$unix_name gecos:$prefix_abs:/bin/false
 pdbtest:x:$uid_pdbtest:$gid_nogroup:pdbtest gecos:$prefix_abs:/bin/false
-- 
2.41.0


From 340bdcc92d979eb67d67e2a2d8056f939a011f37 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 22 Dec 2022 11:42:51 +0100
Subject: [PATCH 137/146] CVE-2022-38023 s3:rpc_server/netlogon: split out
 netr_check_schannel() function

This will allow us to reuse the function in other places.
As it will also get some additional checks soon.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 107 ++++++++++++--------
 1 file changed, 62 insertions(+), 45 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 1d261c9a639..eb364eaf29a 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1064,53 +1064,30 @@ NTSTATUS _netr_ServerAuthenticate2(struct pipes_struct *p,
 /*************************************************************************
  *************************************************************************/
 
-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)
+static NTSTATUS netr_check_schannel(struct pipes_struct *p,
+				    const struct netlogon_creds_CredentialState *creds,
+				    enum dcerpc_AuthType auth_type,
+				    enum dcerpc_AuthLevel auth_level,
+				    uint16_t opnum)
 {
 	TALLOC_CTX *frame = talloc_stackframe();
 	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;
-	int CVE_2020_1472_warn_level = DBGLVL_ERR;
-	int CVE_2020_1472_error_level = DBGLVL_ERR;
+	int CVE_2020_1472_warn_level = lp_parm_int(GLOBAL_SECTION_SNUM,
+		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
+	int CVE_2020_1472_error_level = lp_parm_int(GLOBAL_SECTION_SNUM,
+		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
-	enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
-	enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
-	uint16_t opnum = p->opnum;
 	const char *opname = "<unknown>";
 	const char *reason = "<unknown>";
 	static bool warned_global_once = false;
 
-	if (creds_out != NULL) {
-		*creds_out = NULL;
-	}
-
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
 	}
 
-	auth_type = p->auth.auth_type;
-	auth_level = p->auth.auth_level;
-
-	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
-	if (lp_ctx == NULL) {
-		DEBUG(0, ("loadparm_init_s3 failed\n"));
-		TALLOC_FREE(frame);
-		return NT_STATUS_INTERNAL_ERROR;
-	}
-
-	CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL,
-		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
-	CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL,
-		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
-
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 		if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
 			reason = "WITH SEALED";
@@ -1123,15 +1100,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		reason = "WITHOUT";
 	}
 
-	status = schannel_check_creds_state(mem_ctx, lp_ctx,
-					    computer_name, received_authenticator,
-					    return_authenticator, &creds);
-	if (!NT_STATUS_IS_OK(status)) {
-		ZERO_STRUCTP(return_authenticator);
-		TALLOC_FREE(frame);
-		return status;
-	}
-
 	/*
 	 * We don't use lp_parm_bool(), as we
 	 * need the explicit_opt pointer in order to
@@ -1172,7 +1140,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			      log_escape(frame, creds->computer_name)));
 		}
 
-		*creds_out = creds;
 		TALLOC_FREE(frame);
 		return status;
 	}
@@ -1206,8 +1173,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 			      "might be needed for a legacy client.\n",
 			      log_escape(frame, creds->account_name)));
 		}
-		TALLOC_FREE(creds);
-		ZERO_STRUCTP(return_authenticator);
 		TALLOC_FREE(frame);
 		return status;
 	}
@@ -1261,11 +1226,63 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
 		      log_escape(frame, creds->computer_name)));
 	}
 
-	*creds_out = creds;
 	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
 }
 
+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 loadparm_context *lp_ctx = NULL;
+	NTSTATUS 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;
+	uint16_t opnum = p->opnum;
+
+	if (creds_out != NULL) {
+		*creds_out = NULL;
+	}
+
+	auth_type = p->auth.auth_type;
+	auth_level = p->auth.auth_level;
+
+	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_FREE(lp_ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		ZERO_STRUCTP(return_authenticator);
+		return status;
+	}
+
+	status = netr_check_schannel(p,
+				     creds,
+				     auth_type,
+				     auth_level,
+				     opnum);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(creds);
+		ZERO_STRUCTP(return_authenticator);
+		return status;
+	}
+
+	*creds_out = creds;
+	return NT_STATUS_OK;
+}
 
 /*************************************************************************
  *************************************************************************/
-- 
2.41.0


From 8b52bfc3bb274d7d1607b505c18b4ccafe25cad7 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Thu, 22 Dec 2022 09:29:04 +0100
Subject: [PATCH 138/146] CVE-2022-38023 s3:rpc_server/netlogon: make sure all
 dcesrv_netr_LogonSamLogon*() calls go through netr_check_schannel()

We'll soon add some additional contraints in dcesrv_netr_check_schannel(),
which are also required for dcesrv_netr_LogonSamLogonEx().

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 30 ++++++++++++++++-----
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index eb364eaf29a..ca343d3e28a 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1766,6 +1766,8 @@ 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 = p->auth.auth_type;
+	enum dcerpc_AuthLevel auth_level = p->auth.auth_level;
 
 #ifdef DEBUG_PASSWORD
 	logon = netlogon_creds_shallow_copy_logon(p->mem_ctx,
@@ -1779,11 +1781,32 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p,
 	switch (p->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:
+			if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+				return NT_STATUS_ACCESS_DENIED;
+			}
+
+			status = netr_check_schannel(p,
+						     creds,
+						     auth_type,
+						     auth_level,
+						     p->opnum);
+			if (NT_STATUS_IS_ERR(status)) {
+				return status;
+			}
+
 			fn = "_netr_LogonSamLogonEx";
 			break;
 		default:
@@ -2123,13 +2146,6 @@ NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p,
 		return status;
 	}
 
-	/* Only allow this if the pipe is protected. */
-	if (p->auth.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.41.0


From 43dca97088ce82a5e346887b8078f346e8249929 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 4 Jan 2023 17:23:41 +0100
Subject: [PATCH 139/146] CVE-2022-38023 s3:rpc_server/netlogon: Rename
 variable

This will simplify the following changes.

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index ca343d3e28a..5500a421334 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1072,9 +1072,10 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 {
 	TALLOC_CTX *frame = talloc_stackframe();
 	NTSTATUS status;
+	const char *explicit_opt = NULL;
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
 	bool schannel_required = schannel_global_required;
-	const char *explicit_opt = NULL;
+	bool schannel_explicitly_set = false;
 	int CVE_2020_1472_warn_level = lp_parm_int(GLOBAL_SECTION_SNUM,
 		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
 	int CVE_2020_1472_error_level = lp_parm_int(GLOBAL_SECTION_SNUM,
@@ -1113,11 +1114,12 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	if (explicit_opt != NULL) {
 		schannel_required = lp_bool(explicit_opt);
 	}
+	schannel_explicitly_set = explicit_opt != NULL;
 
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
 		status = NT_STATUS_OK;
 
-		if (explicit_opt != NULL && !schannel_required) {
+		if (schannel_explicitly_set && !schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
 		} else if (!schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
@@ -1132,7 +1134,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		      log_escape(frame, creds->computer_name),
 		      nt_errstr(status)));
 
-		if (explicit_opt != NULL && !schannel_required) {
+		if (schannel_explicitly_set && !schannel_required) {
 			DEBUG(CVE_2020_1472_warn_level, (
 			      "CVE-2020-1472(ZeroLogon): "
 			      "Option 'server require schannel:%s = no' not needed for '%s'!\n",
@@ -1147,7 +1149,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	if (schannel_required) {
 		status = NT_STATUS_ACCESS_DENIED;
 
-		if (explicit_opt != NULL) {
+		if (schannel_explicitly_set) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
 		} else {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
@@ -1161,7 +1163,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		      log_escape(frame, creds->account_name),
 		      log_escape(frame, creds->computer_name),
 		      nt_errstr(status)));
-		if (explicit_opt != NULL) {
+		if (schannel_explicitly_set) {
 			D_NOTICE("CVE-2020-1472(ZeroLogon): Option "
 				"'server require schannel:%s = yes' "
 				"rejects access for client.\n",
@@ -1189,7 +1191,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 
 	status = NT_STATUS_OK;
 
-	if (explicit_opt != NULL) {
+	if (schannel_explicitly_set) {
 		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
 		dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
@@ -1204,7 +1206,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	      log_escape(frame, creds->computer_name),
 	      nt_errstr(status)));
 
-	if (explicit_opt != NULL) {
+	if (schannel_explicitly_set) {
 		D_INFO("CVE-2020-1472(ZeroLogon): Option "
 		       "'server require schannel:%s = no' "
 		       "still needed for '%s'!\n",
-- 
2.41.0


From 4ae0a15ed4ebde7b1725f9ada406c179de238267 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 4 Jan 2023 17:39:20 +0100
Subject: [PATCH 140/146] CVE-2022-38023 s3:rpc_server/netlogon: Return error
 on invalid auth level

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 23 +++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 5500a421334..fb5a05b75c8 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1071,7 +1071,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 				    uint16_t opnum)
 {
 	TALLOC_CTX *frame = talloc_stackframe();
-	NTSTATUS status;
+	NTSTATUS status = NT_STATUS_MORE_PROCESSING_REQUIRED;
 	const char *explicit_opt = NULL;
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
 	bool schannel_required = schannel_global_required;
@@ -1095,12 +1095,31 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		} else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
 			reason = "WITH SIGNED";
 		} else {
-			smb_panic("Schannel without SIGN/SEAL");
+			reason = "WITH INVALID";
+			dbg_lvl = DBGLVL_ERR;
+			status = NT_STATUS_INTERNAL_ERROR;
 		}
 	} else {
 		reason = "WITHOUT";
 	}
 
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		if (!NT_STATUS_IS_OK(status)) {
+			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(status)));
+		TALLOC_FREE(frame);
+		return status;
+	}
+
 	/*
 	 * We don't use lp_parm_bool(), as we
 	 * need the explicit_opt pointer in order to
-- 
2.41.0


From f59b49f3c23a9a7879a6975aa77e9cf2560a68be Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 4 Jan 2023 17:42:37 +0100
Subject: [PATCH 141/146] CVE-2022-38023 s3:rpc_server/netlogon: Rename
 variable

This will simplify the following changes.

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
---
 source3/rpc_server/netlogon/srv_netlog_nt.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index fb5a05b75c8..fd128a70c8b 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1083,7 +1083,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	const char *opname = "<unknown>";
 	const char *reason = "<unknown>";
-	static bool warned_global_once = false;
+	static bool warned_global_schannel_once = false;
 
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
@@ -1198,14 +1198,14 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		return status;
 	}
 
-	if (!schannel_global_required && !warned_global_once) {
+	if (!schannel_global_required && !warned_global_schannel_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;
+		warned_global_schannel_once = true;
 	}
 
 	status = NT_STATUS_OK;
-- 
2.41.0


From 6b038af7f70f0331d85dac00647cfe8dedefec28 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
Date: Wed, 4 Jan 2023 17:50:04 +0100
Subject: [PATCH 142/146] CVE-2022-38023 s3:rpc_server/netlogon: implement
 "server schannel require seal[:COMPUTERACCOUNT]"

By default we'll now require schannel connections with
privacy/sealing/encryption.

But we allow exceptions for specific computer/trust accounts.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240

Signed-off-by: Samuel Cabrero <scabrero@suse.de>
---
 selftest/target/Samba3.pm                   |  14 ++
 source3/rpc_server/netlogon/srv_netlog_nt.c | 237 +++++++++++++++++++-
 2 files changed, 249 insertions(+), 2 deletions(-)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index e8a4c3bbbb6..cf6c38562de 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -215,6 +215,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
+
 	rpc_server:epmapper = external
 	rpc_server:spoolss = external
 	rpc_server:lsarpc = external
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index fd128a70c8b..38772586d81 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -1076,14 +1076,22 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	bool schannel_global_required = (lp_server_schannel() == true) ? true:false;
 	bool schannel_required = schannel_global_required;
 	bool schannel_explicitly_set = false;
+	bool seal_global_required = (lp_server_schannel_require_seal() == true) ? true:false;
+	bool seal_required = seal_global_required;
+	bool seal_explicitly_set = false;
 	int CVE_2020_1472_warn_level = lp_parm_int(GLOBAL_SECTION_SNUM,
 		"CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR);
 	int CVE_2020_1472_error_level = lp_parm_int(GLOBAL_SECTION_SNUM,
 		"CVE_2020_1472", "error_debug_level", DBGLVL_ERR);
+	int CVE_2022_38023_warn_level = lp_parm_int(GLOBAL_SECTION_SNUM,
+		"CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
+	int CVE_2022_38023_error_level = lp_parm_int(GLOBAL_SECTION_SNUM,
+		"CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
 	unsigned int dbg_lvl = DBGLVL_DEBUG;
 	const char *opname = "<unknown>";
 	const char *reason = "<unknown>";
 	static bool warned_global_schannel_once = false;
+	static bool warned_global_seal_once = false;
 
 	if (opnum < ndr_table_netlogon.num_calls) {
 		opname = ndr_table_netlogon.calls[opnum].name;
@@ -1120,6 +1128,20 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		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 schannel require seal",
+					    creds->account_name,
+					    NULL);
+	if (explicit_opt != NULL) {
+		seal_required = lp_bool(explicit_opt);
+	}
+	seal_explicitly_set = explicit_opt != NULL;
+
 	/*
 	 * We don't use lp_parm_bool(), as we
 	 * need the explicit_opt pointer in order to
@@ -1135,7 +1157,96 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	}
 	schannel_explicitly_set = explicit_opt != NULL;
 
+	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL &&
+	    auth_level == DCERPC_AUTH_LEVEL_PRIVACY)
+	{
+		status = NT_STATUS_OK;
+
+		if (schannel_explicitly_set && !schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level);
+		} else if (!schannel_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		}
+		if (seal_explicitly_set && !seal_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level);
+		} else if (!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(status)));
+
+		if (schannel_explicitly_set && !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 (seal_explicitly_set && !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 status;
+	}
+
 	if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+		if (seal_required) {
+			status = NT_STATUS_ACCESS_DENIED;
+
+			if (seal_explicitly_set) {
+				dbg_lvl = DBGLVL_NOTICE;
+			} else {
+				dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+			}
+			if (schannel_explicitly_set && !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(status)));
+			if (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 (schannel_explicitly_set && !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 status;
+		}
+
 		status = NT_STATUS_OK;
 
 		if (schannel_explicitly_set && !schannel_required) {
@@ -1143,6 +1254,11 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		} else if (!schannel_required) {
 			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 		}
+		if (seal_explicitly_set && !seal_required) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+		} else if (!seal_required) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
 
 		DEBUG(dbg_lvl, (
 		      "CVE-2020-1472(ZeroLogon): "
@@ -1152,7 +1268,6 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		      log_escape(frame, creds->account_name),
 		      log_escape(frame, creds->computer_name),
 		      nt_errstr(status)));
-
 		if (schannel_explicitly_set && !schannel_required) {
 			DEBUG(CVE_2020_1472_warn_level, (
 			      "CVE-2020-1472(ZeroLogon): "
@@ -1160,7 +1275,77 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 			      log_escape(frame, creds->account_name),
 			      log_escape(frame, creds->computer_name)));
 		}
+		if (seal_explicitly_set && !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 (!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 status;
+	}
+
+	if (seal_required) {
+		status = NT_STATUS_ACCESS_DENIED;
 
+		if (seal_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE);
+		} else {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
+		if (!schannel_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
+		} else if (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(status)));
+		if (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 (!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 (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 status;
 	}
@@ -1173,6 +1358,9 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		} else {
 			dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level);
 		}
+		if (!seal_explicitly_set) {
+			dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+		}
 
 		DEBUG(dbg_lvl, (
 		      "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: "
@@ -1194,6 +1382,13 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 			      "might be needed for a legacy client.\n",
 			      log_escape(frame, creds->account_name)));
 		}
+		if (!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 status;
 	}
@@ -1208,8 +1403,24 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 		warned_global_schannel_once = true;
 	}
 
+	if (!seal_global_required && !warned_global_seal_once) {
+		/*
+		 * We want admins to notice their misconfiguration!
+		 */
+		DBG_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;
+	}
+
 	status = NT_STATUS_OK;
 
+	if (seal_explicitly_set) {
+		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
+	} else {
+		dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level);
+	}
+
 	if (schannel_explicitly_set) {
 		dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO);
 	} else {
@@ -1225,6 +1436,28 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	      log_escape(frame, creds->computer_name),
 	      nt_errstr(status)));
 
+	if (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 (schannel_explicitly_set) {
 		D_INFO("CVE-2020-1472(ZeroLogon): Option "
 		       "'server require schannel:%s = no' "
@@ -1248,7 +1481,7 @@ static NTSTATUS netr_check_schannel(struct pipes_struct *p,
 	}
 
 	TALLOC_FREE(frame);
-	return NT_STATUS_OK;
+	return status;
 }
 
 static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p,
-- 
2.41.0


From 91f9dac1f8431b3670efd403643cdbbc93b3738a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Sat, 15 Jul 2023 17:20:32 +0200
Subject: [PATCH 143/146] netlogon.idl: add support for
 netr_LogonGetCapabilities response level 2

We don't have any documentation about this yet, but tests against
a Windows Server 2022 patched with KB5028166 revealed that
the response for query_level=2 is exactly the same as
for querey_level=1.

Until we know the reason for query_level=2 we won't
use it as client nor support it in the server, but
we want ndrdump to work.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15418

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 5f87888ed53320538cf773d64868390d8641a40e)
---
 librpc/idl/netlogon.idl | 1 +
 1 file changed, 1 insertion(+)

diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl
index 22f86b92076..c7945d023c4 100644
--- a/librpc/idl/netlogon.idl
+++ b/librpc/idl/netlogon.idl
@@ -1195,6 +1195,7 @@ interface netlogon
 	/* Function 0x15 */
 	typedef [switch_type(uint32)] union {
 		[case(1)] netr_NegotiateFlags server_capabilities;
+		[case(2)] netr_NegotiateFlags server_capabilities;
 	} netr_Capabilities;
 
 	NTSTATUS netr_LogonGetCapabilities(
-- 
2.41.0


From 016cb0817938e8dbb7be126d263f83d590b7045c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Sat, 15 Jul 2023 17:25:05 +0200
Subject: [PATCH 144/146] s4:torture/rpc: let rpc.schannel also check
 netr_LogonGetCapabilities with different levels

The important change it that we expect DCERPC_NCA_S_FAULT_INVALID_TAG
for unsupported query_levels, we allow it to work with servers
with or without support for query_level=2.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15418

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 404ce08e9088968311c714e756f5d58ce2cef715)
---
 .../knownfail.d/netr_LogonGetCapabilities     |  3 +
 source4/torture/rpc/netlogon.c                | 77 ++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 selftest/knownfail.d/netr_LogonGetCapabilities

diff --git a/selftest/knownfail.d/netr_LogonGetCapabilities b/selftest/knownfail.d/netr_LogonGetCapabilities
new file mode 100644
index 00000000000..30aadf3bb9d
--- /dev/null
+++ b/selftest/knownfail.d/netr_LogonGetCapabilities
@@ -0,0 +1,3 @@
+^samba3.rpc.schannel.*\.schannel\(nt4_dc
+^samba3.rpc.schannel.*\.schannel\(ad_dc
+^samba4.rpc.schannel.*\.schannel\(ad_dc
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 1fceeae88cc..49ad1e6760f 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -1469,8 +1469,47 @@ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *t
 	r.out.capabilities = &capabilities;
 	r.out.return_authenticator = &return_auth;
 
-	torture_comment(tctx, "Testing LogonGetCapabilities\n");
+	torture_comment(tctx, "Testing LogonGetCapabilities with query_level=0\n");
 
+	r.in.query_level = 0;
+	ZERO_STRUCT(return_auth);
+
+	/*
+	 * we need to operate on a temporary copy of creds
+	 * because dcerpc_netr_LogonGetCapabilities with
+	 * an unknown query level returns DCERPC_NCA_S_FAULT_INVALID_TAG
+	 * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
+	 * without looking a the authenticator.
+	 */
+	tmp_creds = *creds;
+	netlogon_creds_client_authenticator(&tmp_creds, &auth);
+
+	status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r);
+	torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE,
+				      "LogonGetCapabilities query_level=0 failed");
+
+	torture_comment(tctx, "Testing LogonGetCapabilities with query_level=3\n");
+
+	r.in.query_level = 3;
+	ZERO_STRUCT(return_auth);
+
+	/*
+	 * we need to operate on a temporary copy of creds
+	 * because dcerpc_netr_LogonGetCapabilities with
+	 * an unknown query level returns DCERPC_NCA_S_FAULT_INVALID_TAG
+	 * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
+	 * without looking a the authenticator.
+	 */
+	tmp_creds = *creds;
+	netlogon_creds_client_authenticator(&tmp_creds, &auth);
+
+	status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r);
+	torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE,
+				      "LogonGetCapabilities query_level=0 failed");
+
+	torture_comment(tctx, "Testing LogonGetCapabilities with query_level=1\n");
+
+	r.in.query_level = 1;
 	ZERO_STRUCT(return_auth);
 
 	/*
@@ -1490,6 +1529,42 @@ bool test_netlogon_capabilities(struct dcerpc_pipe *p, struct torture_context *t
 
 	*creds = tmp_creds;
 
+	torture_assert(tctx, netlogon_creds_client_check(creds,
+							 &r.out.return_authenticator->cred),
+		       "Credential chaining failed");
+
+	torture_assert_int_equal(tctx, creds->negotiate_flags,
+				 capabilities.server_capabilities,
+				 "negotiate flags");
+
+	torture_comment(tctx, "Testing LogonGetCapabilities with query_level=2\n");
+
+	r.in.query_level = 2;
+	ZERO_STRUCT(return_auth);
+
+	/*
+	 * we need to operate on a temporary copy of creds
+	 * because dcerpc_netr_LogonGetCapabilities with
+	 * an query level 2 may returns DCERPC_NCA_S_FAULT_INVALID_TAG
+	 * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
+	 * without looking a the authenticator.
+	 */
+	tmp_creds = *creds;
+	netlogon_creds_client_authenticator(&tmp_creds, &auth);
+
+	status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
+		/*
+		 * an server without KB5028166 returns
+		 * DCERPC_NCA_S_FAULT_INVALID_TAG =>
+		 * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
+		 */
+		return true;
+	}
+	torture_assert_ntstatus_ok(tctx, status, "LogonGetCapabilities query_level=2 failed");
+
+	*creds = tmp_creds;
+
 	torture_assert(tctx, netlogon_creds_client_check(creds,
 							 &r.out.return_authenticator->cred),
 		       "Credential chaining failed");
-- 
2.41.0


From 68811d0faa78c8610c5249d3422fa41d461f5bcf Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Sat, 15 Jul 2023 16:11:48 +0200
Subject: [PATCH 145/146] s4:rpc_server:netlogon: generate FAULT_INVALID_TAG
 for invalid netr_LogonGetCapabilities levels

This is important as Windows clients with KB5028166 seem to
call netr_LogonGetCapabilities with query_level=2 after
a call with query_level=1.

An unpatched Windows Server returns DCERPC_NCA_S_FAULT_INVALID_TAG
for query_level values other than 1.
While Samba tries to return NT_STATUS_NOT_SUPPORTED, but
later fails to marshall the response, which results
in DCERPC_FAULT_BAD_STUB_DATA instead.

Because we don't have any documentation for level 2 yet,
we just try to behave like an unpatched server and
generate DCERPC_NCA_S_FAULT_INVALID_TAG instead of
DCERPC_FAULT_BAD_STUB_DATA.
Which allows patched Windows clients to keep working
against a Samba DC.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15418

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit d5f1097b6220676d56ed5fc6707acf667b704518)
---
 .../knownfail.d/netr_LogonGetCapabilities     |  2 --
 source4/rpc_server/netlogon/dcerpc_netlogon.c | 28 ++++++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/selftest/knownfail.d/netr_LogonGetCapabilities b/selftest/knownfail.d/netr_LogonGetCapabilities
index 30aadf3bb9d..99c7ac711ed 100644
--- a/selftest/knownfail.d/netr_LogonGetCapabilities
+++ b/selftest/knownfail.d/netr_LogonGetCapabilities
@@ -1,3 +1 @@
 ^samba3.rpc.schannel.*\.schannel\(nt4_dc
-^samba3.rpc.schannel.*\.schannel\(ad_dc
-^samba4.rpc.schannel.*\.schannel\(ad_dc
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 343cd53473c..72c6dc3d74e 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -2910,6 +2910,30 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c
 	struct netlogon_creds_CredentialState *creds;
 	NTSTATUS status;
 
+	switch (r->in.query_level) {
+	case 1:
+		break;
+	case 2:
+		/*
+		 * Until we know the details behind KB5028166
+		 * just return DCERPC_NCA_S_FAULT_INVALID_TAG
+		 * like an unpatched Windows Server.
+		 */
+		FALL_THROUGH;
+	default:
+		/*
+		 * There would not be a way to marshall the
+		 * the response. Which would mean our final
+		 * ndr_push would fail an we would return
+		 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
+		 *
+		 * But it's important to match a Windows server
+		 * especially before KB5028166, see also our bug #15418
+		 * Otherwise Windows client would stop talking to us.
+		 */
+		DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
+	}
+
 	status = dcesrv_netr_creds_server_step_check(dce_call,
 						     mem_ctx,
 						     r->in.computer_name,
@@ -2921,10 +2945,6 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c
 	}
 	NT_STATUS_NOT_OK_RETURN(status);
 
-	if (r->in.query_level != 1) {
-		return NT_STATUS_NOT_SUPPORTED;
-	}
-
 	r->out.capabilities->server_capabilities = creds->negotiate_flags;
 
 	return NT_STATUS_OK;
-- 
2.41.0


From 517a2ee8570a31283491fca09a8f11a7826a7ed2 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Sat, 15 Jul 2023 16:11:48 +0200
Subject: [PATCH 146/146] s3:rpc_server:netlogon: generate FAULT_INVALID_TAG
 for invalid netr_LogonGetCapabilities levels

This is important as Windows clients with KB5028166 seem to
call netr_LogonGetCapabilities with query_level=2 after
a call with query_level=1.

An unpatched Windows Server returns DCERPC_NCA_S_FAULT_INVALID_TAG
for query_level values other than 1.
While Samba tries to return NT_STATUS_NOT_SUPPORTED, but
later fails to marshall the response, which results
in DCERPC_FAULT_BAD_STUB_DATA instead.

Because we don't have any documentation for level 2 yet,
we just try to behave like an unpatched server and
generate DCERPC_NCA_S_FAULT_INVALID_TAG instead of
DCERPC_FAULT_BAD_STUB_DATA.
Which allows patched Windows clients to keep working
against a Samba DC.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15418

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Mon Jul 17 07:35:09 UTC 2023 on atb-devel-224

(cherry picked from commit dfeabce44fbb78083fbbb2aa634fc4172cf83db9)
---
 .../knownfail.d/netr_LogonGetCapabilities     |  1 -
 source3/rpc_server/netlogon/srv_netlog_nt.c   | 29 ++++++++++++++++---
 2 files changed, 25 insertions(+), 5 deletions(-)
 delete mode 100644 selftest/knownfail.d/netr_LogonGetCapabilities

diff --git a/selftest/knownfail.d/netr_LogonGetCapabilities b/selftest/knownfail.d/netr_LogonGetCapabilities
deleted file mode 100644
index 99c7ac711ed..00000000000
--- a/selftest/knownfail.d/netr_LogonGetCapabilities
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.rpc.schannel.*\.schannel\(nt4_dc
diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c
index 38772586d81..bf75a9f1adc 100644
--- a/source3/rpc_server/netlogon/srv_netlog_nt.c
+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c
@@ -2672,6 +2672,31 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p,
 	struct netlogon_creds_CredentialState *creds;
 	NTSTATUS status;
 
+	switch (r->in.query_level) {
+	case 1:
+		break;
+	case 2:
+		/*
+		 * Until we know the details behind KB5028166
+		 * just return DCERPC_NCA_S_FAULT_INVALID_TAG
+		 * like an unpatched Windows Server.
+		 */
+		FALL_THROUGH;
+	default:
+		/*
+		 * There would not be a way to marshall the
+		 * the response. Which would mean our final
+		 * ndr_push would fail an we would return
+		 * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
+		 *
+		 * But it's important to match a Windows server
+		 * especially before KB5028166, see also our bug #15418
+		 * Otherwise Windows client would stop talking to us.
+		 */
+		p->fault_state = DCERPC_NCA_S_FAULT_INVALID_TAG;
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
 	become_root();
 	status = netr_creds_server_step_check(p, p->mem_ctx,
 					      r->in.computer_name,
@@ -2683,10 +2708,6 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p,
 		return status;
 	}
 
-	if (r->in.query_level != 1) {
-		return NT_STATUS_NOT_SUPPORTED;
-	}
-
 	r->out.capabilities->server_capabilities = creds->negotiate_flags;
 
 	return NT_STATUS_OK;
-- 
2.41.0