[PATCH] Convert samba-tool GPO cmds to use s3 SMB Python bindings

Tim Beale timbeale at catalyst.net.nz
Fri Jan 11 04:37:18 UTC 2019


Take 2 with glaring python import error fixed...

CI link: https://gitlab.com/catalyst-samba/samba/pipelines/42949972

On 11/01/19 5:10 PM, Tim Beale wrote:
> This converts the 'samba-tool gpo' commands to use the s3 SMB bindings,
> which will mean the commands will now work on a DC with SMBv1 disabled.
>
> This should be the last of SMB python binding changes needed for 4.10.
> Then we can finally close bug 13676.
>
> CI link: https://gitlab.com/catalyst-samba/samba/pipelines/42946382
>
> Review appreciated. Thanks
>
-------------- next part --------------
From fb655ad2c2fea51995d98a00f19976e80a264c30 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Fri, 14 Dec 2018 10:37:11 +1300
Subject: [PATCH 1/6] python/gpclass: Convert gpclass to use s3 SMB Python
 bindings

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 python/samba/gpclass.py | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index fb7c705..0040f23 100644
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -29,7 +29,8 @@ import xml.etree.ElementTree as etree
 import re
 from samba.net import Net
 from samba.dcerpc import nbt
-from samba import smb
+from samba.samba3 import libsmb_samba_internal as libsmb
+from samba.samba3 import param as s3param
 import samba.gpo as gpo
 from samba.param import LoadParm
 from uuid import UUID
@@ -386,7 +387,7 @@ def cache_gpo_dir(conn, cache, sub_dir):
         if e.errno != errno.EEXIST:
             raise
     for fdata in conn.list(sub_dir):
-        if fdata['attrib'] & smb.FILE_ATTRIBUTE_DIRECTORY:
+        if fdata['attrib'] & libsmb.FILE_ATTRIBUTE_DIRECTORY:
             cache_gpo_dir(conn, cache, os.path.join(sub_dir, fdata['name']))
         else:
             local_name = fdata['name'].upper()
@@ -407,7 +408,10 @@ def check_safe_path(path):
 
 
 def check_refresh_gpo_list(dc_hostname, lp, creds, gpos):
-    conn = smb.SMB(dc_hostname, 'sysvol', lp=lp, creds=creds, sign=True)
+    # the SMB bindings rely on having a s3 loadparm
+    s3_lp = s3param.get_context()
+    s3_lp.load(lp.configfile)
+    conn = libsmb.Conn(dc_hostname, 'sysvol', lp=s3_lp, creds=creds, sign=True)
     cache_path = lp.cache_path('gpo_cache')
     for gpo in gpos:
         if not gpo.file_sys_path:
-- 
2.7.4


From 1e91d1e44d18999be036d7e827056a9c01b2fb06 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Tue, 8 Jan 2019 14:42:05 +1300
Subject: [PATCH 2/6] s3:pylibsmb: Add .set_acl API to SMB py bindings

This is pretty similar code to py_smb_getacl(), except it's calling
cli_set_security_descriptor() instead of cli_query_security_descriptor()

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 source3/libsmb/pylibsmb.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index e0ce518..1c945d2 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -1525,6 +1525,54 @@ static PyObject *py_smb_getacl(struct py_cli_state *self, PyObject *args)
 				    sd, sd);
 }
 
+/*
+ * Set ACL on file/directory using given security descriptor object
+ */
+static PyObject *py_smb_setacl(struct py_cli_state *self, PyObject *args)
+{
+	NTSTATUS status;
+	const char *filename;
+	PyObject *py_sd;
+	struct security_descriptor *sd;
+	unsigned int sinfo = SECINFO_DEFAULT_FLAGS;
+	uint16_t fnum;
+
+	/* there's no async version of cli_set_security_descriptor() */
+	if (self->thread_state != NULL) {
+		PyErr_SetString(PyExc_RuntimeError,
+				"set_acl() is not supported on "
+				"a multi_threaded connection");
+		return NULL;
+	}
+
+	if (!PyArg_ParseTuple(args, "sO|I:set_acl", &filename, &py_sd,
+			      &sinfo)) {
+		return NULL;
+	}
+
+	sd = pytalloc_get_type(py_sd, struct security_descriptor);
+	if (!sd) {
+		PyErr_Format(PyExc_TypeError,
+			"Expected dcerpc.security.descriptor as argument, got %s",
+			talloc_get_name(pytalloc_get_ptr(py_sd)));
+		return NULL;
+	}
+
+	status = cli_ntcreate(self->cli, filename, 0,
+			      SEC_FLAG_MAXIMUM_ALLOWED, 0,
+			      FILE_SHARE_READ|FILE_SHARE_WRITE,
+			      FILE_OPEN, 0x0, 0x0, &fnum, NULL);
+	PyErr_NTSTATUS_IS_ERR_RAISE(status);
+
+	status = cli_set_security_descriptor(self->cli, fnum, sinfo, sd);
+	PyErr_NTSTATUS_IS_ERR_RAISE(status);
+
+	status = cli_close(self->cli, fnum);
+	PyErr_NTSTATUS_IS_ERR_RAISE(status);
+
+	Py_RETURN_NONE;
+}
+
 static PyMethodDef py_cli_state_methods[] = {
 	{ "settimeout", (PyCFunction)py_cli_settimeout, METH_VARARGS,
 	  "settimeout(new_timeout_msecs) => return old_timeout_msecs" },
@@ -1577,6 +1625,9 @@ static PyMethodDef py_cli_state_methods[] = {
 	{ "get_acl", (PyCFunction)py_smb_getacl, METH_VARARGS,
 	  "get_acl(path[, security_info=0]) -> security_descriptor object\n\n"
 	  "\t\tGet security descriptor for file." },
+	{ "set_acl", (PyCFunction)py_smb_setacl, METH_VARARGS,
+	  "set_acl(path, security_descriptor[, security_info=0]) -> None\n\n"
+	  "\t\tSet security descriptor for file." },
 	{ NULL, NULL, 0, NULL }
 };
 
-- 
2.7.4


From bc4914f6546a8ac450995aa6ecb5aa226a5e85b3 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Tue, 8 Jan 2019 15:10:46 +1300
Subject: [PATCH 3/6] netcmd: Change SMB flags from s4 Py bindings to s3

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 python/samba/netcmd/gpo.py | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py
index a064f44..d443129 100644
--- a/python/samba/netcmd/gpo.py
+++ b/python/samba/netcmd/gpo.py
@@ -44,6 +44,7 @@ from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHE
 from samba.netcmd.common import netcmd_finddc
 from samba import policy
 from samba import smb
+from samba.samba3 import libsmb_samba_internal as libsmb
 from samba import NTSTATUSError
 import uuid
 from samba.ntacls import dsacl2fsacl
@@ -280,7 +281,7 @@ def backup_directory_remote_to_local(conn, remotedir, localdir):
             r_name = r_dir + '\\' + e['name']
             l_name = os.path.join(l_dir, e['name'])
 
-            if e['attrib'] & smb.FILE_ATTRIBUTE_DIRECTORY:
+            if e['attrib'] & libsmb.FILE_ATTRIBUTE_DIRECTORY:
                 r_dirs.append(r_name)
                 l_dirs.append(l_name)
                 os.mkdir(l_name)
@@ -294,10 +295,10 @@ def backup_directory_remote_to_local(conn, remotedir, localdir):
                 parser.write_xml(l_name + '.xml')
 
 
-attr_flags = smb.FILE_ATTRIBUTE_SYSTEM | \
-             smb.FILE_ATTRIBUTE_DIRECTORY | \
-             smb.FILE_ATTRIBUTE_ARCHIVE | \
-             smb.FILE_ATTRIBUTE_HIDDEN
+attr_flags = libsmb.FILE_ATTRIBUTE_SYSTEM | \
+             libsmb.FILE_ATTRIBUTE_DIRECTORY | \
+             libsmb.FILE_ATTRIBUTE_ARCHIVE | \
+             libsmb.FILE_ATTRIBUTE_HIDDEN
 
 
 def copy_directory_remote_to_local(conn, remotedir, localdir):
@@ -315,7 +316,7 @@ def copy_directory_remote_to_local(conn, remotedir, localdir):
             r_name = r_dir + '\\' + e['name']
             l_name = os.path.join(l_dir, e['name'])
 
-            if e['attrib'] & smb.FILE_ATTRIBUTE_DIRECTORY:
+            if e['attrib'] & libsmb.FILE_ATTRIBUTE_DIRECTORY:
                 r_dirs.append(r_name)
                 l_dirs.append(l_name)
                 os.mkdir(l_name)
-- 
2.7.4


From bc712a5c9ed70c03c20d5f144042a6d9074faad6 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Fri, 11 Jan 2019 14:25:32 +1300
Subject: [PATCH 4/6] s3:pylibsmb: Add FILE_READ_ATTRIBUTES access to
 .loadfile() API

Add FILE_READ_ATTRIBUTES when opening the file handle, as we need to
read the file's size.

The .loadfile() API can end up calling cli_qfileinfo_basic() to get the
file size. This can end up doing a 'FILE_ALL_INFORMATION' SMBv2 request
underneath, which the MS-SMB2 spec (section 3.3.5.20.1 Handling
SMB2_0_INFO_FILE) says the file handle must have FILE_READ_ATTRIBUTES
access granted.

I noticed this problem when running .loadfile() against the NTVFS
server.

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 source3/libsmb/pylibsmb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c
index 1c945d2..037a79c 100644
--- a/source3/libsmb/pylibsmb.c
+++ b/source3/libsmb/pylibsmb.c
@@ -928,7 +928,8 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args,
 
 	/* get a read file handle */
 	req = cli_ntcreate_send(NULL, self->ev, self->cli, filename, 0,
-				FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
+				FILE_READ_DATA | FILE_READ_ATTRIBUTES,
+				FILE_ATTRIBUTE_NORMAL,
 				FILE_SHARE_READ, FILE_OPEN, 0,
 				SMB2_IMPERSONATION_IMPERSONATION, 0);
 	if (!py_tevent_req_wait_exc(self, req)) {
-- 
2.7.4


From f8613f956ba9002ccd55862d5355d7c7aa897f75 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Fri, 11 Jan 2019 14:53:16 +1300
Subject: [PATCH 5/6] netcmd: Change GPO commands to use s3 SMB Py bindings

This means we can now use GPO commands on a DC that has SMBv1 disabled.

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 python/samba/netcmd/gpo.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py
index d443129..1b5e927 100644
--- a/python/samba/netcmd/gpo.py
+++ b/python/samba/netcmd/gpo.py
@@ -43,7 +43,7 @@ import samba.auth
 from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHENTICATED, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
 from samba.netcmd.common import netcmd_finddc
 from samba import policy
-from samba import smb
+from samba.samba3 import param as s3param
 from samba.samba3 import libsmb_samba_internal as libsmb
 from samba import NTSTATUSError
 import uuid
@@ -365,7 +365,10 @@ def create_directory_hier(conn, remotedir):
 def smb_connection(dc_hostname, service, lp, creds, sign=False):
     # SMB connect to DC
     try:
-        conn = smb.SMB(dc_hostname, service, lp=lp, creds=creds, sign=sign)
+        # the SMB bindings rely on having a s3 loadparm
+        s3_lp = s3param.get_context()
+        s3_lp.load(lp.configfile)
+        conn = libsmb.Conn(dc_hostname, service, lp=s3_lp, creds=creds, sign=sign)
     except Exception:
         raise CommandError("Error connecting to '%s' using SMB" % dc_hostname)
     return conn
-- 
2.7.4


From a2fdc338673f9dbfdd0c44542f4696e5cd6168da Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Fri, 11 Jan 2019 15:57:21 +1300
Subject: [PATCH 6/6] s4:pysmb: Add error log that the s4 bindings are
 deprecated

We plan to delete the s4 SMB Python bindings in the next Samba release
after v4.10, but first give external consumers a heads-up, just in case
they are currently using the s4 bindings.

Note the auth_log tests still use the s4 bindings, but all user-facing
tools should now be updated to use the s3 bindings.

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

Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
 source4/libcli/pysmb.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/source4/libcli/pysmb.c b/source4/libcli/pysmb.c
index 45ff9a0..5a02816 100644
--- a/source4/libcli/pysmb.c
+++ b/source4/libcli/pysmb.c
@@ -614,6 +614,18 @@ static PyObject *py_smb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs
 	uint8_t use_spnego = 0xFF;
 	PyObject *sign = Py_False;
 
+	/*
+	 * These Python bindings are now deprecated because the s4 SMB client
+	 * code doesn't support SMBv2 (and is unlikely to ever support it).
+	 * The s3 libsmb_samba_internal bindings are a better choice for use
+	 * within the Samba codebase, and support much the same API.
+	 * This warning is mostly for external consumers that might be using
+	 * these Python bindings (in which case, note libsmb_samba_internal
+	 * is not a stable API and may change in future).
+	 */
+	DBG_ERR("The smb.SMB() Python bindings are now deprecated "
+		"and will be removed in the next samba release\n");
+
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zz|OObbO",
 					 discard_const_p(char *, kwnames),
 					 &hostname, &service, &py_creds, &py_lp,
-- 
2.7.4



More information about the samba-technical mailing list