From a3944de6990686bf674e7a9badded501873a7cfa Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl@samba.org>
Date: Fri, 20 May 2022 10:55:23 +0200
Subject: [PATCH 01/28] CVE-2022-2127: winbindd: Fix WINBINDD_PAM_AUTH_CRAP
 length checks

With WBFLAG_BIG_NTLMV2_BLOB being set plus lm_resp_len too large you
can crash winbind. We don't independently check lm_resp_len
sufficiently.

Discovered via Coverity ID 1504444 Out-of-bounds access

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

Signed-off-by: Volker Lendecke <vl@samba.org>

Conflict: NA
Reference: https://download.samba.org/pub/samba/patches/security/samba-4.17.10-security-2023-07-19.patch
---
 source3/winbindd/winbindd_pam_auth_crap.c | 31 +++++++++++++++--------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c
index 6120522ce3c..e6a32c7ed79 100644
--- a/source3/winbindd/winbindd_pam_auth_crap.c
+++ b/source3/winbindd/winbindd_pam_auth_crap.c
@@ -52,6 +52,9 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 	DATA_BLOB chal = data_blob_null;
 	struct wbint_SidArray *require_membership_of_sid = NULL;
 	NTSTATUS status;
+	bool lmlength_ok = false;
+	bool ntlength_ok = false;
+	bool pwlength_ok = false;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct winbindd_pam_auth_crap_state);
@@ -115,16 +118,24 @@ struct tevent_req *winbindd_pam_auth_crap_send(
 		fstrcpy(request->data.auth_crap.workstation, lp_netbios_name());
 	}
 
-	if (request->data.auth_crap.lm_resp_len > sizeof(request->data.auth_crap.lm_resp)
-		|| request->data.auth_crap.nt_resp_len > sizeof(request->data.auth_crap.nt_resp)) {
-		if (!(request->flags & WBFLAG_BIG_NTLMV2_BLOB) ||
-		     request->extra_len != request->data.auth_crap.nt_resp_len) {
-			DBG_ERR("Invalid password length %u/%u\n",
-				request->data.auth_crap.lm_resp_len,
-				request->data.auth_crap.nt_resp_len);
-			tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-			return tevent_req_post(req, ev);
-		}
+	lmlength_ok = (request->data.auth_crap.lm_resp_len <=
+		       sizeof(request->data.auth_crap.lm_resp));
+
+	ntlength_ok = (request->data.auth_crap.nt_resp_len <=
+		       sizeof(request->data.auth_crap.nt_resp));
+
+	ntlength_ok |=
+		((request->flags & WBFLAG_BIG_NTLMV2_BLOB) &&
+		 (request->extra_len == request->data.auth_crap.nt_resp_len));
+
+	pwlength_ok = lmlength_ok && ntlength_ok;
+
+	if (!pwlength_ok) {
+		DBG_ERR("Invalid password length %u/%u\n",
+			request->data.auth_crap.lm_resp_len,
+			request->data.auth_crap.nt_resp_len);
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		return tevent_req_post(req, ev);
 	}
 
 	state->domain = talloc_strdup(state, request->data.auth_crap.domain);
-- 
2.34.1
