[RFC] Advice on SMB client python bindings?

Tim Beale timbeale at catalyst.net.nz
Wed Dec 12 04:16:12 UTC 2018


The attached patch is all ready to git am and push. It's got the review
tags added, and the test changes (currently going through autobuild)
split out.

On 12/12/18 4:54 PM, Andrew Bartlett wrote:
> I've pushed the test changes, the rest looks great as well. 
>
> Reviewed-by: Andrew Bartlett <abartlet at samba.org>
>
> Metze,
>
> Can you push if you are happy?
>
> Thanks,
>
> Andrew Bartlett
-------------- next part --------------
From 8a7659491872338860536f7fd58c8c09a9b8391b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 3 Dec 2018 14:37:05 +0100
Subject: [PATCH 01/17] s3:pylibsmb: pass self to py_tevent_req_wait_exc()

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 99e5587..75236e7 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -364,7 +364,7 @@ static int py_tevent_req_wait(struct tevent_context *ev,
 
 #endif
 
-static bool py_tevent_req_wait_exc(struct tevent_context *ev,
+static bool py_tevent_req_wait_exc(struct py_cli_state *self,
 				   struct tevent_req *req)
 {
 	int ret;
@@ -373,7 +373,7 @@ static bool py_tevent_req_wait_exc(struct tevent_context *ev,
 		PyErr_NoMemory();
 		return false;
 	}
-	ret = py_tevent_req_wait(ev, req);
+	ret = py_tevent_req_wait(self->ev, req);
 	if (ret != 0) {
 		TALLOC_FREE(req);
 		errno = ret;
@@ -453,7 +453,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	req = cli_full_connection_creds_send(
 		NULL, self->ev, "myname", host, NULL, 0, share, "?????",
 		cli_creds, flags, SMB_SIGNING_DEFAULT);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return -1;
 	}
 	status = cli_full_connection_creds_recv(req, &self->cli);
@@ -612,7 +612,7 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
 				DesiredAccess, FileAttributes, ShareAccess,
 				CreateDisposition, CreateOptions,
 				SecurityFlags);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_ntcreate_recv(req, &fnum, NULL);
@@ -636,7 +636,7 @@ static PyObject *py_cli_close(struct py_cli_state *self, PyObject *args)
 	}
 
 	req = cli_close_send(NULL, self->ev, self->cli, fnum);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_close_recv(req);
@@ -672,7 +672,7 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args,
 
 	req = cli_write_andx_send(NULL, self->ev, self->cli, fnum, mode,
 				  (uint8_t *)buf, offset, buflen);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_write_andx_recv(req, &written);
@@ -708,7 +708,7 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args,
 
 	req = cli_read_andx_send(NULL, self->ev, self->cli, fnum,
 				 offset, size);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_read_andx_recv(req, &buflen, &buf);
@@ -740,7 +740,7 @@ static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args,
 	}
 
 	req = cli_ftruncate_send(NULL, self->ev, self->cli, fnum, size);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_ftruncate_recv(req);
@@ -771,7 +771,7 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self,
 
 	req = cli_nt_delete_on_close_send(NULL, self->ev, self->cli, fnum,
 					  flag);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_nt_delete_on_close_recv(req);
@@ -812,7 +812,7 @@ static PyObject *py_cli_list(struct py_cli_state *self,
 
 	req = cli_list_send(NULL, self->ev, self->cli, mask, attribute,
 			    info_level);
-	if (!py_tevent_req_wait_exc(self->ev, req)) {
+	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
 	status = cli_list_recv(req, NULL, &finfos, &num_finfos);
-- 
2.7.4


From 553a49b7b739a9f23929fe0e057bc76a088f2220 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 3 Dec 2018 15:02:06 +0100
Subject: [PATCH 02/17] s3:pylibsmb: only use poll_mt backend if
 multi_threaded=True is specified

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 python/samba/tests/libsmb_samba_internal.py |  3 +-
 source3/libsmb/pylibsmb.c                   | 52 +++++++++++++++++++++++------
 2 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/python/samba/tests/libsmb_samba_internal.py b/python/samba/tests/libsmb_samba_internal.py
index c88095c..db99c0b 100644
--- a/python/samba/tests/libsmb_samba_internal.py
+++ b/python/samba/tests/libsmb_samba_internal.py
@@ -59,7 +59,8 @@ class LibsmbTestCase(samba.tests.TestCase):
         creds.set_username(os.getenv("USERNAME"))
         creds.set_password(os.getenv("PASSWORD"))
 
-        c = libsmb_samba_internal.Conn(os.getenv("SERVER_IP"), "tmp", creds)
+        c = libsmb_samba_internal.Conn(os.getenv("SERVER_IP"), "tmp",
+                                       creds, multi_threaded=True)
 
         mythreads = []
 
diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 75236e7..a18fbaf 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -81,6 +81,8 @@ struct py_cli_state {
 	PyObject_HEAD
 	struct cli_state *cli;
 	struct tevent_context *ev;
+	int (*req_wait_fn)(struct tevent_context *ev,
+			   struct tevent_req *req);
 	struct py_cli_thread *thread_state;
 
 	struct tevent_req *oplock_waiter;
@@ -194,7 +196,10 @@ static int py_cli_thread_destructor(struct py_cli_thread *t)
 	return 0;
 }
 
-static bool py_cli_state_setup_ev(struct py_cli_state *self)
+static int py_tevent_cond_req_wait(struct tevent_context *ev,
+				   struct tevent_req *req);
+
+static bool py_cli_state_setup_mt_ev(struct py_cli_state *self)
 {
 	struct py_cli_thread *t = NULL;
 	int ret;
@@ -206,6 +211,8 @@ static bool py_cli_state_setup_ev(struct py_cli_state *self)
 	samba_tevent_set_debug(self->ev, "pylibsmb_tevent_mt");
 	tevent_set_trace_callback(self->ev, py_cli_state_trace_callback, self);
 
+	self->req_wait_fn = py_tevent_cond_req_wait;
+
 	self->thread_state = talloc_zero(NULL, struct py_cli_thread);
 	if (self->thread_state == NULL) {
 		goto fail;
@@ -303,8 +310,8 @@ fail:
 	return result;
 }
 
-static int py_tevent_req_wait(struct tevent_context *ev,
-			      struct tevent_req *req)
+static int py_tevent_cond_req_wait(struct tevent_context *ev,
+				   struct tevent_req *req)
 {
 	struct py_tevent_cond cond;
 	tevent_req_set_callback(req, py_tevent_signalme, &cond);
@@ -334,7 +341,10 @@ static void py_tevent_signalme(struct tevent_req *req)
 	py_tevent_cond_signal(cond);
 }
 
-#else
+#endif
+
+static int py_tevent_req_wait(struct tevent_context *ev,
+			      struct tevent_req *req);
 
 static bool py_cli_state_setup_ev(struct py_cli_state *self)
 {
@@ -345,6 +355,8 @@ static bool py_cli_state_setup_ev(struct py_cli_state *self)
 
 	samba_tevent_set_debug(self->ev, "pylibsmb_tevent");
 
+	self->req_wait_fn = py_tevent_req_wait;
+
 	return true;
 }
 
@@ -362,8 +374,6 @@ static int py_tevent_req_wait(struct tevent_context *ev,
 	return 0;
 }
 
-#endif
-
 static bool py_tevent_req_wait_exc(struct py_cli_state *self,
 				   struct tevent_req *req)
 {
@@ -373,7 +383,7 @@ static bool py_tevent_req_wait_exc(struct py_cli_state *self,
 		PyErr_NoMemory();
 		return false;
 	}
-	ret = py_tevent_req_wait(self->ev, req);
+	ret = self->req_wait_fn(self->ev, req);
 	if (ret != 0) {
 		TALLOC_FREE(req);
 		errno = ret;
@@ -410,6 +420,8 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	char *host, *share;
 	PyObject *creds = NULL;
 	struct cli_credentials *cli_creds;
+	PyObject *py_multi_threaded = Py_False;
+	bool multi_threaded = false;
 	struct tevent_req *req;
 	bool ret;
 	/*
@@ -421,7 +433,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
 
 	static const char *kwlist[] = {
-		"host", "share", "credentials", NULL
+		"host", "share", "credentials", "multi_threaded", NULL
 	};
 
 	PyTypeObject *py_type_Credentials = get_pytype(
@@ -431,8 +443,10 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	}
 
 	ret = ParseTupleAndKeywords(
-		args, kwds, "ss|O!", kwlist,
-		&host, &share, py_type_Credentials, &creds);
+		args, kwds, "ss|O!O", kwlist,
+		&host, &share,
+		py_type_Credentials, &creds,
+		&py_multi_threaded);
 
 	Py_DECREF(py_type_Credentials);
 
@@ -440,8 +454,24 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 		return -1;
 	}
 
-	if (!py_cli_state_setup_ev(self)) {
+	multi_threaded = PyObject_IsTrue(py_multi_threaded);
+
+	if (multi_threaded) {
+#ifdef HAVE_PTHREAD
+		ret = py_cli_state_setup_mt_ev(self);
+		if (!ret) {
+			return -1;
+		}
+#else
+		PyErr_SetString(PyExc_RuntimeError,
+				"No PTHREAD support available");
 		return -1;
+#endif
+	} else {
+		ret = py_cli_state_setup_ev(self);
+		if (!ret) {
+			return -1;
+		}
 	}
 
 	if (creds == NULL) {
-- 
2.7.4


From 1646ef7901d76ca17e353d36b3da80ce7625aab3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 3 Dec 2018 15:42:50 +0100
Subject: [PATCH 03/17] s3:pylibsmb: add sign=True to require signing

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index a18fbaf..8e63cbf 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -422,6 +422,9 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	struct cli_credentials *cli_creds;
 	PyObject *py_multi_threaded = Py_False;
 	bool multi_threaded = false;
+	PyObject *py_sign = Py_False;
+	bool sign = false;
+	int signing_state = SMB_SIGNING_DEFAULT;
 	struct tevent_req *req;
 	bool ret;
 	/*
@@ -433,7 +436,8 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
 
 	static const char *kwlist[] = {
-		"host", "share", "credentials", "multi_threaded", NULL
+		"host", "share", "credentials",
+		"multi_threaded", "sign", NULL
 	};
 
 	PyTypeObject *py_type_Credentials = get_pytype(
@@ -443,10 +447,11 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	}
 
 	ret = ParseTupleAndKeywords(
-		args, kwds, "ss|O!O", kwlist,
+		args, kwds, "ss|O!OO", kwlist,
 		&host, &share,
 		py_type_Credentials, &creds,
-		&py_multi_threaded);
+		&py_multi_threaded,
+		&py_sign);
 
 	Py_DECREF(py_type_Credentials);
 
@@ -455,6 +460,11 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	}
 
 	multi_threaded = PyObject_IsTrue(py_multi_threaded);
+	sign = PyObject_IsTrue(py_sign);
+
+	if (sign) {
+		signing_state = SMB_SIGNING_REQUIRED;
+	}
 
 	if (multi_threaded) {
 #ifdef HAVE_PTHREAD
@@ -482,7 +492,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 
 	req = cli_full_connection_creds_send(
 		NULL, self->ev, "myname", host, NULL, 0, share, "?????",
-		cli_creds, flags, SMB_SIGNING_DEFAULT);
+		cli_creds, flags, signing_state);
 	if (!py_tevent_req_wait_exc(self, req)) {
 		return -1;
 	}
-- 
2.7.4


From 93fc576aadb86474921a89acb3950b6d2e390ec7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 4 Dec 2018 10:40:18 +0100
Subject: [PATCH 04/17] s3:pylibsmb: add force_smb1=True in order to control
 forcing of SMB1

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 python/samba/tests/libsmb_samba_internal.py |  3 ++-
 source3/libsmb/pylibsmb.c                   | 35 ++++++++++++++++++++---------
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/python/samba/tests/libsmb_samba_internal.py b/python/samba/tests/libsmb_samba_internal.py
index db99c0b..8918d84 100644
--- a/python/samba/tests/libsmb_samba_internal.py
+++ b/python/samba/tests/libsmb_samba_internal.py
@@ -60,7 +60,8 @@ class LibsmbTestCase(samba.tests.TestCase):
         creds.set_password(os.getenv("PASSWORD"))
 
         c = libsmb_samba_internal.Conn(os.getenv("SERVER_IP"), "tmp",
-                                       creds, multi_threaded=True)
+                                       creds, multi_threaded=True,
+                                       force_smb1=True)
 
         mythreads = []
 
diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 8e63cbf..ed3c041 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -425,19 +425,16 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	PyObject *py_sign = Py_False;
 	bool sign = false;
 	int signing_state = SMB_SIGNING_DEFAULT;
+	PyObject *py_force_smb1 = Py_False;
+	bool force_smb1 = false;
 	struct tevent_req *req;
 	bool ret;
-	/*
-	 * For now we only support SMB1,
-	 * as most of the cli_*_send() function
-	 * don't support SMB2, it's only plugged
-	 * into the sync wrapper functions currently.
-	 */
-	int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
+	int flags = 0;
 
 	static const char *kwlist[] = {
 		"host", "share", "credentials",
-		"multi_threaded", "sign", NULL
+		"multi_threaded", "sign", "force_smb1",
+		NULL
 	};
 
 	PyTypeObject *py_type_Credentials = get_pytype(
@@ -447,11 +444,12 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 	}
 
 	ret = ParseTupleAndKeywords(
-		args, kwds, "ss|O!OO", kwlist,
+		args, kwds, "ss|O!OOO", kwlist,
 		&host, &share,
 		py_type_Credentials, &creds,
 		&py_multi_threaded,
-		&py_sign);
+		&py_sign,
+		&py_force_smb1);
 
 	Py_DECREF(py_type_Credentials);
 
@@ -461,11 +459,22 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 
 	multi_threaded = PyObject_IsTrue(py_multi_threaded);
 	sign = PyObject_IsTrue(py_sign);
+	force_smb1 = PyObject_IsTrue(py_force_smb1);
 
 	if (sign) {
 		signing_state = SMB_SIGNING_REQUIRED;
 	}
 
+	if (force_smb1) {
+		/*
+		 * As most of the cli_*_send() function
+		 * don't support SMB2 (it's only plugged
+		 * into the sync wrapper functions currently)
+		 * we have a way to force SMB1.
+		 */
+		flags = CLI_FULL_CONNECTION_FORCE_SMB1;
+	}
+
 	if (multi_threaded) {
 #ifdef HAVE_PTHREAD
 		ret = py_cli_state_setup_mt_ev(self);
@@ -477,6 +486,12 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 				"No PTHREAD support available");
 		return -1;
 #endif
+		if (!force_smb1) {
+			PyErr_SetString(PyExc_RuntimeError,
+					"multi_threaded is only possible on "
+					"SMB1 connections");
+			return -1;
+		}
 	} else {
 		ret = py_cli_state_setup_ev(self);
 		if (!ret) {
-- 
2.7.4


From a2c777e2e0987d04c1c2d95219c49bc11a8ff2f0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 4 Dec 2018 10:42:55 +0100
Subject: [PATCH 05/17] s3:pylibsmb: remember that a connection uses SMB1

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

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index ed3c041..e4552a2 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -21,6 +21,7 @@
 #include <Python.h>
 #include "includes.h"
 #include "python/py3compat.h"
+#include "libcli/smb/smbXcli_base.h"
 #include "libsmb/libsmb.h"
 #include "libcli/security/security.h"
 #include "system/select.h"
@@ -80,6 +81,7 @@ struct py_cli_oplock_break {
 struct py_cli_state {
 	PyObject_HEAD
 	struct cli_state *cli;
+	bool is_smb1;
 	struct tevent_context *ev;
 	int (*req_wait_fn)(struct tevent_context *ev,
 			   struct tevent_req *req);
@@ -403,6 +405,7 @@ static PyObject *py_cli_state_new(PyTypeObject *type, PyObject *args,
 		return NULL;
 	}
 	self->cli = NULL;
+	self->is_smb1 = false;
 	self->ev = NULL;
 	self->thread_state = NULL;
 	self->oplock_waiter = NULL;
@@ -519,6 +522,10 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 		return -1;
 	}
 
+	if (smbXcli_conn_protocol(self->cli->conn) < PROTOCOL_SMB2_02) {
+		self->is_smb1 = true;
+	}
+
 	self->oplock_waiter = cli_smb_oplock_break_waiter_send(
 		self->ev, self->ev, self->cli);
 	if (self->oplock_waiter == NULL) {
-- 
2.7.4


From 21f6ab07ba08363c954c9a68254219633f971b89 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Tue, 4 Dec 2018 12:32:58 +1300
Subject: [PATCH 06/17] s3:pylibsmb: .get_oplock_break API is dependent on
 multi_threaded=True

The .get_oplock_break is dependent on the pthread code, which is only
used when creating a SMB connection with multi_threaded=True.

Add an explicit error to the .get_oplock_break() if someone tries to use
it in non-multithreaded mode.

Initializing self->oplock_waiter in non-multithreaded mode is similarly
redundant if the API can never be used.

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

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index e4552a2..19587a8 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -526,6 +526,13 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 		self->is_smb1 = true;
 	}
 
+	/*
+	 * Oplocks require a multi threaded connection
+	 */
+	if (self->thread_state == NULL) {
+		return 0;
+	}
+
 	self->oplock_waiter = cli_smb_oplock_break_waiter_send(
 		self->ev, self->ev, self->cli);
 	if (self->oplock_waiter == NULL) {
@@ -585,6 +592,13 @@ static PyObject *py_cli_get_oplock_break(struct py_cli_state *self,
 		return NULL;
 	}
 
+	if (self->thread_state == NULL) {
+		PyErr_SetString(PyExc_RuntimeError,
+				"get_oplock_break() only possible on "
+				"a multi_threaded connection");
+		return NULL;
+	}
+
 	if (self->oplock_cond != NULL) {
 		errno = EBUSY;
 		PyErr_SetFromErrno(PyExc_RuntimeError);
-- 
2.7.4


From dc0a6b47fb18ee5a0c95185551277dc4a035e0b3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 13:47:40 +0100
Subject: [PATCH 07/17] s3:pylibsmb: make use of PyBytes_FromStringAndSize() in
 py_cli_read()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 19587a8..bb1d2b7 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -794,7 +794,7 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args,
 		PyErr_SetNTSTATUS(status);
 		return NULL;
 	}
-	result = Py_BuildValue("s#", (char *)buf, (int)buflen);
+	result = PyBytes_FromStringAndSize((const char *)buf, buflen);
 	TALLOC_FREE(req);
 	return result;
 }
-- 
2.7.4


From 97ce385930aea810efd673e71f6e55088107a539 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 14:04:30 +0100
Subject: [PATCH 08/17] s3:pylibsmb: make use of PYARG_BYTES_LEN in
 py_cli_write()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index bb1d2b7..3b1aa73 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -741,7 +741,7 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args,
 		"fnum", "buffer", "offset", "mode", NULL };
 
 	if (!ParseTupleAndKeywords(
-		    args, kwds, "Is#K|I", kwlist,
+		    args, kwds, "I" PYARG_BYTES_LEN "K|I", kwlist,
 		    &fnum, &buf, &buflen, &offset, &mode)) {
 		return NULL;
 	}
-- 
2.7.4


From d0b921a99325c1980ca3295e823533670c33de8f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 14:26:43 +0100
Subject: [PATCH 09/17] s3:libsmb: add cli_write_send/recv which work with
 SMB1/2/3

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/clireadwrite.c | 116 ++++++++++++++++++++++++++++++++++++++++++
 source3/libsmb/proto.h        |   7 +++
 2 files changed, 123 insertions(+)

diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 6bf3df6..6d47ccd 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -1065,6 +1065,122 @@ NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten)
 	return NT_STATUS_OK;
 }
 
+struct cli_write_state {
+	struct cli_state *cli;
+	size_t written;
+};
+
+static void cli_write_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_write_send(TALLOC_CTX *mem_ctx,
+				  struct tevent_context *ev,
+				  struct cli_state *cli, uint16_t fnum,
+				  uint16_t mode, const uint8_t *buf,
+				  off_t offset, size_t size)
+{
+	struct tevent_req *req = NULL;
+	struct cli_write_state *state = NULL;
+	struct tevent_req *subreq = NULL;
+
+	req = tevent_req_create(mem_ctx, &state, struct cli_write_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->cli = cli;
+
+	if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+		uint32_t max_size;
+		bool ok;
+
+		ok = smb2cli_conn_req_possible(state->cli->conn, &max_size);
+		if (!ok) {
+			tevent_req_nterror(
+				req,
+				NT_STATUS_INSUFFICIENT_RESOURCES);
+			return tevent_req_post(req, ev);
+		}
+
+		/*
+		 * downgrade depending on the available credits
+		 */
+		size = MIN(max_size, size);
+
+		subreq = cli_smb2_write_send(state,
+					     ev,
+					     cli,
+					     fnum,
+					     mode,
+					     buf,
+					     offset,
+					     size);
+	} else {
+		bool ok;
+
+		ok = smb1cli_conn_req_possible(state->cli->conn);
+		if (!ok) {
+			tevent_req_nterror(
+				req,
+				NT_STATUS_INSUFFICIENT_RESOURCES);
+			return tevent_req_post(req, ev);
+		}
+
+		subreq = cli_write_andx_send(state,
+					     ev,
+					     cli,
+					     fnum,
+					     mode,
+					     buf,
+					     offset,
+					     size);
+	}
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_write_done, req);
+
+	return req;
+}
+
+static void cli_write_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct cli_write_state *state =
+		tevent_req_data(req,
+		struct cli_write_state);
+	NTSTATUS status;
+
+	if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+		status = cli_smb2_write_recv(subreq, &state->written);
+	} else {
+		status = cli_write_andx_recv(subreq, &state->written);
+	}
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	tevent_req_done(req);
+}
+
+NTSTATUS cli_write_recv(struct tevent_req *req, size_t *pwritten)
+{
+	struct cli_write_state *state =
+		tevent_req_data(req,
+		struct cli_write_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+	if (pwritten != NULL) {
+		*pwritten = state->written;
+	}
+	tevent_req_received(req);
+	return NT_STATUS_OK;
+}
+
 struct cli_smb1_writeall_state {
 	struct tevent_context *ev;
 	struct cli_state *cli;
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index d0bc3e7..941d154 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -868,6 +868,13 @@ struct tevent_req *cli_write_andx_send(TALLOC_CTX *mem_ctx,
 				       off_t offset, size_t size);
 NTSTATUS cli_write_andx_recv(struct tevent_req *req, size_t *pwritten);
 
+struct tevent_req *cli_write_send(TALLOC_CTX *mem_ctx,
+				  struct tevent_context *ev,
+				  struct cli_state *cli, uint16_t fnum,
+				  uint16_t mode, const uint8_t *buf,
+				  off_t offset, size_t size);
+NTSTATUS cli_write_recv(struct tevent_req *req, size_t *pwritten);
+
 struct tevent_req *cli_writeall_send(
 	TALLOC_CTX *mem_ctx,
 	struct tevent_context *ev,
-- 
2.7.4


From 98577db4e0c63e095f6ca276f8faabdcb2a85109 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Tue, 11 Dec 2018 16:05:43 +1300
Subject: [PATCH 10/17] s3:libsmb: add comments for
 cli_write_send/cli_push_send

Added a code comment highlighting this 2 APIs do similar jobs, and tried
to explain why you might want to use one over the other.

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/clireadwrite.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 6d47ccd..e953fa5 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -1072,6 +1072,14 @@ struct cli_write_state {
 
 static void cli_write_done(struct tevent_req *subreq);
 
+/*
+ * Used to write to a file remotely.
+ * This is similar in functionality to cli_push_send(), except this is a more
+ * finer-grain API. For example, if the data we want to write exceeds the max
+ * write size of the underlying connection, then it's the caller's
+ * responsibility to handle this.
+ * For writing a small amount of data to file, this is a simpler API to use.
+ */
 struct tevent_req *cli_write_send(TALLOC_CTX *mem_ctx,
 				  struct tevent_context *ev,
 				  struct cli_state *cli, uint16_t fnum,
@@ -1455,6 +1463,16 @@ static void cli_push_setup_chunks(struct tevent_req *req);
 static void cli_push_chunk_ship(struct cli_push_chunk *chunk);
 static void cli_push_chunk_done(struct tevent_req *subreq);
 
+/*
+ * Used to write to a file remotely.
+ * This is similar in functionality to cli_write_send(), except this API
+ * handles writing a large file by breaking the data into chunks (so we don't
+ * exceed the max write size of the underlying connection). To do this, the
+ * (*source) callback handles copying the underlying file data into a message
+ * buffer, one chunk at a time.
+ * This API is recommended when writing a potentially large amount of data,
+ * e.g. when copying a file (or doing a 'put').
+ */
 struct tevent_req *cli_push_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 				 struct cli_state *cli,
 				 uint16_t fnum, uint16_t mode,
-- 
2.7.4


From 0bc5933e5f4d9c44aec2ade0aa270a3c60afa2ba Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 14:28:04 +0100
Subject: [PATCH 11/17] s3:pylibsmb: make use of protocol independent
 cli_write_send/recv in py_cli_write()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 3b1aa73..2dabacb 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -746,12 +746,12 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args,
 		return NULL;
 	}
 
-	req = cli_write_andx_send(NULL, self->ev, self->cli, fnum, mode,
-				  (uint8_t *)buf, offset, buflen);
+	req = cli_write_send(NULL, self->ev, self->cli, fnum, mode,
+			     (uint8_t *)buf, offset, buflen);
 	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
-	status = cli_write_andx_recv(req, &written);
+	status = cli_write_recv(req, &written);
 	TALLOC_FREE(req);
 
 	if (!NT_STATUS_IS_OK(status)) {
-- 
2.7.4


From 8ee5a4cdea547e8ef7438cf44247658b160cea2d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 14:28:04 +0100
Subject: [PATCH 12/17] s3:pylibsmb: make use of protocol independent
 cli_read_send/recv in py_cli_read()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 2dabacb..b6cff0b 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -769,8 +769,8 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args,
 	unsigned size;
 	struct tevent_req *req;
 	NTSTATUS status;
-	uint8_t *buf;
-	ssize_t buflen;
+	char *buf;
+	size_t received;
 	PyObject *result;
 
 	static const char *kwlist[] = {
@@ -782,20 +782,41 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args,
 		return NULL;
 	}
 
-	req = cli_read_andx_send(NULL, self->ev, self->cli, fnum,
-				 offset, size);
+	result = PyBytes_FromStringAndSize(NULL, size);
+	if (result == NULL) {
+		return NULL;
+	}
+	buf = PyBytes_AS_STRING(result);
+
+	req = cli_read_send(NULL, self->ev, self->cli, fnum,
+			    buf, offset, size);
 	if (!py_tevent_req_wait_exc(self, req)) {
+		Py_XDECREF(result);
 		return NULL;
 	}
-	status = cli_read_andx_recv(req, &buflen, &buf);
+	status = cli_read_recv(req, &received);
+	TALLOC_FREE(req);
 
 	if (!NT_STATUS_IS_OK(status)) {
-		TALLOC_FREE(req);
+		Py_XDECREF(result);
 		PyErr_SetNTSTATUS(status);
 		return NULL;
 	}
-	result = PyBytes_FromStringAndSize((const char *)buf, buflen);
-	TALLOC_FREE(req);
+
+	if (received > size) {
+		Py_XDECREF(result);
+		PyErr_Format(PyExc_IOError,
+			     "read invalid - got %zu requested %u",
+			     received, size);
+		return NULL;
+	}
+
+	if (received < size) {
+		if (_PyBytes_Resize(&result, received) < 0) {
+			return NULL;
+		}
+	}
+
 	return result;
 }
 
-- 
2.7.4


From 295f6b0b6cd5195fa362ca23a216998b9c030671 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 16:32:05 +0100
Subject: [PATCH 13/17] s3:libsmb: pass impersonation_level to
 cli_smb2_create_fnum_send()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 examples/fuse/clifuse.c        | 6 ++++--
 source3/libsmb/cli_smb2_fnum.c | 5 ++++-
 source3/libsmb/cli_smb2_fnum.h | 1 +
 source3/libsmb/clifile.c       | 4 +++-
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/examples/fuse/clifuse.c b/examples/fuse/clifuse.c
index 3c7e498..b724e64 100644
--- a/examples/fuse/clifuse.c
+++ b/examples/fuse/clifuse.c
@@ -151,7 +151,8 @@ static void cli_ll_create(fuse_req_t freq, fuse_ino_t parent, const char *name,
 
 	req = cli_smb2_create_fnum_send(
 		state, mstate->ev, mstate->cli, state->path,
-		0, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL,
+		0, SMB2_IMPERSONATION_IMPERSONATION,
+		FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_CREATE, FILE_NON_DIRECTORY_FILE);
 	if (req == NULL) {
@@ -836,7 +837,8 @@ static void cli_ll_open(fuse_req_t freq, fuse_ino_t ino,
 
 	req = cli_smb2_create_fnum_send(
 		state, mstate->ev, mstate->cli, istate->path,
-		0, acc, FILE_ATTRIBUTE_NORMAL,
+		0, SMB2_IMPERSONATION_IMPERSONATION,
+		acc, FILE_ATTRIBUTE_NORMAL,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_OPEN, FILE_NON_DIRECTORY_FILE);
 	if (req == NULL) {
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 35edec8..aef70f1 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -171,6 +171,7 @@ struct tevent_req *cli_smb2_create_fnum_send(TALLOC_CTX *mem_ctx,
 					     struct cli_state *cli,
 					     const char *fname,
 					     uint32_t create_flags,
+					     uint32_t impersonation_level,
 					     uint32_t desired_access,
 					     uint32_t file_attributes,
 					     uint32_t share_access,
@@ -262,7 +263,7 @@ struct tevent_req *cli_smb2_create_fnum_send(TALLOC_CTX *mem_ctx,
 				     cli->smb2.tcon,
 				     fname,
 				     flags_to_smb2_oplock(create_flags),
-				     SMB2_IMPERSONATION_IMPERSONATION,
+				     impersonation_level,
 				     desired_access,
 				     file_attributes,
 				     share_access,
@@ -345,6 +346,7 @@ NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
 	TALLOC_CTX *frame = talloc_stackframe();
 	struct tevent_context *ev;
 	struct tevent_req *req;
+	uint32_t impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
 	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
@@ -359,6 +361,7 @@ NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
 		goto fail;
 	}
 	req = cli_smb2_create_fnum_send(frame, ev, cli, fname, create_flags,
+					impersonation_level,
 					desired_access, file_attributes,
 					share_access, create_disposition,
 					create_options);
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index 4fce5fc..2edaae0 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -30,6 +30,7 @@ struct tevent_req *cli_smb2_create_fnum_send(TALLOC_CTX *mem_ctx,
 					     struct cli_state *cli,
 					     const char *fname,
 					     uint32_t create_flags,
+					     uint32_t impersonation_level,
 					     uint32_t desired_access,
 					     uint32_t file_attributes,
 					     uint32_t share_access,
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index b509263..dc3751a 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -2102,6 +2102,7 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct cli_ntcreate_state *state;
+	uint32_t impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
 
 	req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
 	if (req == NULL) {
@@ -2116,7 +2117,8 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
 		}
 
 		subreq = cli_smb2_create_fnum_send(
-			state, ev, cli, fname, create_flags, desired_access,
+			state, ev, cli, fname, create_flags,
+			impersonation_level, desired_access,
 			file_attributes, share_access, create_disposition,
 			create_options);
 	} else {
-- 
2.7.4


From d025f383d6d6aa5b37295aa072168f08e5988dcb Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 16:42:06 +0100
Subject: [PATCH 14/17] s3:libsmb: pass impersonation_level to
 cli_smb2_create_fnum()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/cli_smb2_fnum.c | 18 +++++++++++++++++-
 source3/libsmb/cli_smb2_fnum.h |  1 +
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index aef70f1..6cba442 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -335,6 +335,7 @@ NTSTATUS cli_smb2_create_fnum_recv(struct tevent_req *req, uint16_t *pfnum,
 NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
 			const char *fname,
 			uint32_t create_flags,
+			uint32_t impersonation_level,
 			uint32_t desired_access,
 			uint32_t file_attributes,
 			uint32_t share_access,
@@ -346,7 +347,6 @@ NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
 	TALLOC_CTX *frame = talloc_stackframe();
 	struct tevent_context *ev;
 	struct tevent_req *req;
-	uint32_t impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
 	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
@@ -644,6 +644,7 @@ NTSTATUS cli_smb2_mkdir(struct cli_state *cli, const char *dname)
 	status = cli_smb2_create_fnum(cli,
 			dname,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			FILE_READ_ATTRIBUTES,	/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
@@ -682,6 +683,7 @@ NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dname)
 	status = cli_smb2_create_fnum(cli,
 			dname,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			DELETE_ACCESS,		/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -700,6 +702,7 @@ NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dname)
 		status = cli_smb2_create_fnum(cli,
 			dname,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			DELETE_ACCESS,		/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -748,6 +751,7 @@ NTSTATUS cli_smb2_unlink(struct cli_state *cli, const char *fname)
 	status = cli_smb2_create_fnum(cli,
 			fname,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			DELETE_ACCESS,		/* desired_access */
 			FILE_ATTRIBUTE_NORMAL, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -766,6 +770,7 @@ NTSTATUS cli_smb2_unlink(struct cli_state *cli, const char *fname)
 		status = cli_smb2_create_fnum(cli,
 			fname,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			DELETE_ACCESS,		/* desired_access */
 			FILE_ATTRIBUTE_NORMAL, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -943,6 +948,7 @@ NTSTATUS cli_smb2_list(struct cli_state *cli,
 	status = cli_smb2_create_fnum(cli,
 			parent_dir,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			SEC_DIR_LIST|SEC_DIR_READ_ATTRIBUTE,/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
@@ -1119,6 +1125,7 @@ NTSTATUS cli_smb2_qpathinfo_basic(struct cli_state *cli,
 	status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			FILE_READ_ATTRIBUTES,	/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1132,6 +1139,7 @@ NTSTATUS cli_smb2_qpathinfo_basic(struct cli_state *cli,
 		status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			FILE_READ_ATTRIBUTES,		/* desired_access */
 			0, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1184,6 +1192,7 @@ NTSTATUS cli_smb2_chkpath(struct cli_state *cli,
 	status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			FILE_READ_ATTRIBUTES,	/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1229,6 +1238,7 @@ static NTSTATUS get_fnum_from_path(struct cli_state *cli,
 	status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			desired_access,
 			0, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1248,6 +1258,7 @@ static NTSTATUS get_fnum_from_path(struct cli_state *cli,
 		status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			desired_access,
 			0, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1262,6 +1273,7 @@ static NTSTATUS get_fnum_from_path(struct cli_state *cli,
 		status = cli_smb2_create_fnum(cli,
 			name,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			desired_access,
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -1997,6 +2009,7 @@ NTSTATUS cli_smb2_dskattr(struct cli_state *cli, const char *path,
 	status = cli_smb2_create_fnum(cli,
 			path,
 			0,			/* create_flags */
+			SMB2_IMPERSONATION_IMPERSONATION,
 			FILE_READ_ATTRIBUTES,	/* desired_access */
 			FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
@@ -2106,6 +2119,7 @@ NTSTATUS cli_smb2_get_fs_full_size_info(struct cli_state *cli,
 	/* First open the top level directory. */
 	status =
 	    cli_smb2_create_fnum(cli, "", 0,		   /* create_flags */
+				 SMB2_IMPERSONATION_IMPERSONATION,
 				 FILE_READ_ATTRIBUTES,     /* desired_access */
 				 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 				 FILE_SHARE_READ | FILE_SHARE_WRITE |
@@ -2198,6 +2212,7 @@ NTSTATUS cli_smb2_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr)
 	/* First open the top level directory. */
 	status =
 	    cli_smb2_create_fnum(cli, "", 0,		   /* create_flags */
+				 SMB2_IMPERSONATION_IMPERSONATION,
 				 FILE_READ_ATTRIBUTES,     /* desired_access */
 				 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 				 FILE_SHARE_READ | FILE_SHARE_WRITE |
@@ -2283,6 +2298,7 @@ NTSTATUS cli_smb2_get_fs_volume_info(struct cli_state *cli,
 	/* First open the top level directory. */
 	status =
 	    cli_smb2_create_fnum(cli, "", 0,		   /* create_flags */
+				 SMB2_IMPERSONATION_IMPERSONATION,
 				 FILE_READ_ATTRIBUTES,     /* desired_access */
 				 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
 				 FILE_SHARE_READ | FILE_SHARE_WRITE |
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index 2edaae0..921dc71 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -41,6 +41,7 @@ NTSTATUS cli_smb2_create_fnum_recv(struct tevent_req *req, uint16_t *pfnum,
 NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
 			const char *fname,
 			uint32_t create_flags,
+			uint32_t impersonation_level,
 			uint32_t desired_access,
 			uint32_t file_attributes,
 			uint32_t share_access,
-- 
2.7.4


From 963b06d0bb457300bf4b2416a12c76de14a5a934 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 16:35:16 +0100
Subject: [PATCH 15/17] s3:libsmb: pass ImpersonationLevel to
 cli_ntcreate1_send()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/clifile.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index dc3751a..1694af5 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -1951,6 +1951,7 @@ static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
 					     uint32_t ShareAccess,
 					     uint32_t CreateDisposition,
 					     uint32_t CreateOptions,
+					     uint32_t ImpersonationLevel,
 					     uint8_t SecurityFlags)
 {
 	struct tevent_req *req, *subreq;
@@ -1985,7 +1986,7 @@ static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
 	SIVAL(vwv+17, 1, CreateDisposition);
 	SIVAL(vwv+19, 1, CreateOptions |
 		(cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
-	SIVAL(vwv+21, 1, 0x02);	/* ImpersonationLevel */
+	SIVAL(vwv+21, 1, ImpersonationLevel);
 	SCVAL(vwv+23, 1, SecurityFlags);
 
 	bytes = talloc_array(state, uint8_t, 0);
@@ -2126,7 +2127,7 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
 		subreq = cli_ntcreate1_send(
 			state, ev, cli, fname, create_flags, desired_access,
 			file_attributes, share_access, create_disposition,
-			create_options, security_flags);
+			create_options, impersonation_level, security_flags);
 	}
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
-- 
2.7.4


From 98eb032350b063fafcf31a562e27f2771a67c109 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 16:38:57 +0100
Subject: [PATCH 16/17] s3:libsmb: pass impersonation_level to
 cli_ntcreate_send()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 examples/winexe/winexe.c             | 3 +++
 source3/libsmb/clifile.c             | 5 +++--
 source3/libsmb/clisymlink.c          | 6 ++++--
 source3/libsmb/proto.h               | 1 +
 source3/libsmb/pylibsmb.c            | 3 ++-
 source3/torture/nbench.c             | 3 ++-
 source3/torture/test_chain3.c        | 3 ++-
 source3/torture/test_notify.c        | 9 ++++++---
 source3/torture/test_notify_online.c | 5 +++--
 source3/torture/test_oplock_cancel.c | 2 +-
 source3/torture/torture.c            | 3 ++-
 11 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/examples/winexe/winexe.c b/examples/winexe/winexe.c
index cf667a6..429ba2f 100644
--- a/examples/winexe/winexe.c
+++ b/examples/winexe/winexe.c
@@ -872,6 +872,7 @@ static struct tevent_req *winexe_out_pipe_send(
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_OPEN,	/* CreateDisposition */
 		0,		/* CreateOptions */
+		SMB2_IMPERSONATION_IMPERSONATION,
 		0);		/* SecurityFlags */
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
@@ -1044,6 +1045,7 @@ static struct tevent_req *winexe_in_pipe_send(
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_OPEN,	/* CreateDisposition */
 		0,		/* CreateOptions */
+		SMB2_IMPERSONATION_IMPERSONATION,
 		0);		/* SecurityFlags */
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
@@ -1462,6 +1464,7 @@ static struct tevent_req *winexe_ctrl_send(
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_OPEN,	/* CreateDisposition */
 		0,		/* CreateOptions */
+		SMB2_IMPERSONATION_IMPERSONATION,
 		0);		/* SecurityFlags */
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 1694af5..6defa38 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -2099,11 +2099,11 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
 				     uint32_t share_access,
 				     uint32_t create_disposition,
 				     uint32_t create_options,
+				     uint32_t impersonation_level,
 				     uint8_t security_flags)
 {
 	struct tevent_req *req, *subreq;
 	struct cli_ntcreate_state *state;
-	uint32_t impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
 
 	req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
 	if (req == NULL) {
@@ -2197,6 +2197,7 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
 	TALLOC_CTX *frame = talloc_stackframe();
 	struct tevent_context *ev;
 	struct tevent_req *req;
+	uint32_t ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
 	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
 	if (smbXcli_conn_has_async_calls(cli->conn)) {
@@ -2215,7 +2216,7 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
 	req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
 				DesiredAccess, FileAttributes, ShareAccess,
 				CreateDisposition, CreateOptions,
-				SecurityFlags);
+				ImpersonationLevel, SecurityFlags);
 	if (req == NULL) {
 		goto fail;
 	}
diff --git a/source3/libsmb/clisymlink.c b/source3/libsmb/clisymlink.c
index 54435e4..1330752 100644
--- a/source3/libsmb/clisymlink.c
+++ b/source3/libsmb/clisymlink.c
@@ -72,7 +72,8 @@ struct tevent_req *cli_symlink_send(TALLOC_CTX *mem_ctx,
 		FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
 		FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_CREATE,
 		FILE_OPEN_REPARSE_POINT|FILE_SYNCHRONOUS_IO_NONALERT|
-		FILE_NON_DIRECTORY_FILE, 0);
+		FILE_NON_DIRECTORY_FILE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -274,7 +275,8 @@ struct tevent_req *cli_readlink_send(TALLOC_CTX *mem_ctx,
 	subreq = cli_ntcreate_send(
 		state, ev, cli, fname, 0, FILE_READ_ATTRIBUTES | FILE_READ_EA,
 		0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-		FILE_OPEN, FILE_OPEN_REPARSE_POINT, 0);
+		FILE_OPEN, FILE_OPEN_REPARSE_POINT,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 941d154..bfad4dc 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -397,6 +397,7 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
 				     uint32_t ShareAccess,
 				     uint32_t CreateDisposition,
 				     uint32_t CreateOptions,
+				     uint32_t ImpersonationLevel,
 				     uint8_t SecurityFlags);
 NTSTATUS cli_ntcreate_recv(struct tevent_req *req,
 			uint16_t *pfnum,
diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index b6cff0b..3f84d34 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -666,6 +666,7 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
 	unsigned ShareAccess = 0;
 	unsigned CreateDisposition = FILE_OPEN;
 	unsigned CreateOptions = 0;
+	unsigned ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
 	unsigned SecurityFlags = 0;
 	uint16_t fnum;
 	struct tevent_req *req;
@@ -687,7 +688,7 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
 	req = cli_ntcreate_send(NULL, self->ev, self->cli, fname, CreateFlags,
 				DesiredAccess, FileAttributes, ShareAccess,
 				CreateDisposition, CreateOptions,
-				SecurityFlags);
+				ImpersonationLevel, SecurityFlags);
 	if (!py_tevent_req_wait_exc(self, req)) {
 		return NULL;
 	}
diff --git a/source3/torture/nbench.c b/source3/torture/nbench.c
index 80b5a72..e9a0b4f 100644
--- a/source3/torture/nbench.c
+++ b/source3/torture/nbench.c
@@ -263,7 +263,8 @@ static struct tevent_req *nbench_cmd_send(TALLOC_CTX *mem_ctx,
 			state, ev, nb_state->cli, state->ft->cp.fname, flags,
 			desired_access, 0, share_mode,
 			state->ft->cp.cr_disposition,
-			state->ft->cp.cr_options, 0);
+			state->ft->cp.cr_options,
+			SMB2_IMPERSONATION_IMPERSONATION, 0);
 		break;
 	}
 	case NBENCH_CMD_CLOSE: {
diff --git a/source3/torture/test_chain3.c b/source3/torture/test_chain3.c
index eff39de..d957e51 100644
--- a/source3/torture/test_chain3.c
+++ b/source3/torture/test_chain3.c
@@ -180,7 +180,8 @@ static struct tevent_req *chain3_send(TALLOC_CTX *mem_ctx,
 		GENERIC_READ_ACCESS|GENERIC_WRITE_ACCESS,
 		FILE_ATTRIBUTE_NORMAL,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-		FILE_OVERWRITE_IF, 0, 0);
+		FILE_OVERWRITE_IF, 0,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
diff --git a/source3/torture/test_notify.c b/source3/torture/test_notify.c
index e377875..20b39d1 100644
--- a/source3/torture/test_notify.c
+++ b/source3/torture/test_notify.c
@@ -66,7 +66,8 @@ static struct tevent_req *wait_for_one_notify_send(TALLOC_CTX *mem_ctx,
 		state, state->ev, state->cli, path, 0,
 		MAXIMUM_ALLOWED_ACCESS,
 		0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-		FILE_OPEN, FILE_DIRECTORY_FILE, 0);
+		FILE_OPEN, FILE_DIRECTORY_FILE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -318,7 +319,8 @@ static struct tevent_req *notify_bench3_send(
 		state, state->ev, state->cli, state->dir, 0,
 		MAXIMUM_ALLOWED_ACCESS, 0,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-		FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0);
+		FILE_OPEN_IF, FILE_DIRECTORY_FILE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -456,7 +458,8 @@ static void notify_bench3_before_mkdir2(struct tevent_req *subreq)
 		MAXIMUM_ALLOWED_ACCESS,	0,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
 		FILE_CREATE,
-		FILE_DIRECTORY_FILE, 0);
+		FILE_DIRECTORY_FILE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
diff --git a/source3/torture/test_notify_online.c b/source3/torture/test_notify_online.c
index 7f4f521..c8ddf7c 100644
--- a/source3/torture/test_notify_online.c
+++ b/source3/torture/test_notify_online.c
@@ -61,7 +61,7 @@ static struct tevent_req *notify_online_send(
 		state, ev, cli, dname, EXTENDED_RESPONSE_REQUIRED,
 		SEC_FILE_READ_DATA, 0,
 		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-		FILE_OPEN, 0, 0);
+		FILE_OPEN, 0, SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -93,7 +93,8 @@ static void notify_online_opened_dir(struct tevent_req *subreq)
 		state, state->ev, state->cli, state->fname, 0,
 		GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-		FILE_OPEN, FILE_NON_DIRECTORY_FILE, 0);
+		FILE_OPEN, FILE_NON_DIRECTORY_FILE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
diff --git a/source3/torture/test_oplock_cancel.c b/source3/torture/test_oplock_cancel.c
index d856650..b003876 100644
--- a/source3/torture/test_oplock_cancel.c
+++ b/source3/torture/test_oplock_cancel.c
@@ -48,7 +48,7 @@ static struct tevent_req *create_cancel_send(
 	subreq = cli_ntcreate_send(
 		mem_ctx, ev, cli, fname, 0, FILE_GENERIC_READ,
 		FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE,
-		FILE_OPEN_IF, 0, 0);
+		FILE_OPEN_IF, 0, SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 4f810e5..1849a8d 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -8249,7 +8249,8 @@ static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
 		FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
 		FILE_ATTRIBUTE_NORMAL,
 		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-		FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
+		FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
+		SMB2_IMPERSONATION_IMPERSONATION, 0);
 
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
-- 
2.7.4


From 8ab1dc45498af3ccf4a17124fd297967fe539b61 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 7 Dec 2018 16:40:10 +0100
Subject: [PATCH 17/17] s3:pylibsmb: allow ImpersonationLevel argument to
 create()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Tim Beale <timbeale at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
---
 source3/libsmb/pylibsmb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 3f84d34..981e744 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -675,13 +675,13 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
 	static const char *kwlist[] = {
 		"Name", "CreateFlags", "DesiredAccess", "FileAttributes",
 		"ShareAccess", "CreateDisposition", "CreateOptions",
-		"SecurityFlags", NULL };
+		"ImpersonationLevel", "SecurityFlags", NULL };
 
 	if (!ParseTupleAndKeywords(
-		    args, kwds, "s|IIIIIII", kwlist,
+		    args, kwds, "s|IIIIIIII", kwlist,
 		    &fname, &CreateFlags, &DesiredAccess, &FileAttributes,
 		    &ShareAccess, &CreateDisposition, &CreateOptions,
-		    &SecurityFlags)) {
+		    &ImpersonationLevel, &SecurityFlags)) {
 		return NULL;
 	}
 
-- 
2.7.4



More information about the samba-technical mailing list