From b0d99036cc44884e9d5ae1caf2076f00c94b7f79 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Tue, 29 Nov 2022 15:45:56 +0100
Subject: [PATCH 41/54] CVE-2022-37966 s4:libnet: allow python bindings to
 force setting an nthash via SAMR level 18

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

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit 4ebbe7e40754eeb1c8f221dd59018c3e681ab2ab)

Conflict: NA
Reference: https://attachments.samba.org/attachment.cgi?id=17695
---
 source4/libnet/py_net.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/source4/libnet/py_net.c b/source4/libnet/py_net.c
index df9280d8c18d..fe5979e7a57a 100644
--- a/source4/libnet/py_net.c
+++ b/source4/libnet/py_net.c
@@ -244,20 +244,32 @@ static PyObject *py_net_set_password(py_net_Object *self, PyObject *args, PyObje
 	NTSTATUS status;
 	TALLOC_CTX *mem_ctx;
 	struct tevent_context *ev;
-	const char *kwnames[] = { "account_name", "domain_name", "newpassword", NULL };
+	const char *kwnames[] = { "account_name", "domain_name", "newpassword", "force_samr_18", NULL };
+	PyObject *py_force_samr_18 = Py_False;
 
 	ZERO_STRUCT(r);
 
 	r.generic.level = LIBNET_SET_PASSWORD_GENERIC;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss:set_password",
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|O:set_password",
 					discard_const_p(char *, kwnames),
 					 &r.generic.in.account_name,
 					 &r.generic.in.domain_name,
-					 &r.generic.in.newpassword)) {
+					 &r.generic.in.newpassword,
+					 &py_force_samr_18)) {
 		return NULL;
 	}
 
+	if (py_force_samr_18) {
+		if (!PyBool_Check(py_force_samr_18)) {
+			PyErr_SetString(PyExc_TypeError, "Expected boolean force_samr_18");
+			return NULL;
+		}
+		if (py_force_samr_18 == Py_True) {
+			r.generic.samr_level = LIBNET_SET_PASSWORD_SAMR_HANDLE_18;
+		}
+	}
+
 	/* FIXME: we really need to get a context from the caller or we may end
 	 * up with 2 event contexts */
 	ev = s4_event_context_init(NULL);
-- 
2.34.1
