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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2


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/101] 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.37.2