From 9c813b21755dc5faf2f6eb7dc3fb081d20223174 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 11:19:10 +0100 Subject: [PATCH 01/10] python/samba: Add some compatability PY2/PY3 functions I hope these changes are a short term interim solution for the absence of the 'six' module/library. I also hope that soon this module can be removed and be replaced by usage of six. Signed-off-by: Noel Power --- python/samba/compat.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/samba/compat.py b/python/samba/compat.py index 667a1a443b1..d17dc3c2ce9 100644 --- a/python/samba/compat.py +++ b/python/samba/compat.py @@ -22,8 +22,20 @@ PY3 = sys.version_info[0] == 3 if PY3: + # compat functions + from urllib.parse import quote as urllib_quote + from urllib.request import urlopen as urllib_urlopen + + # compat types integer_types = int, + string_types = str text_type = str else: + # compat functions + from urllib import quote as urllib_quote + from urllib import urlopen as urllib_urlopen + + # compat types integer_types = (int, long) + string_types = basestring text_type = unicode From ec0aaabd987570b110197323abcfbefd88fa3c13 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Thu, 12 Apr 2018 14:46:59 +0100 Subject: [PATCH 02/10] lib/ldb: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- lib/ldb/pyldb.c | 10 +++++----- lib/ldb/pyldb_util.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 67ecafbc420..110ec8e60ad 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -1078,7 +1078,7 @@ static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list, const char *str = NULL; Py_ssize_t size; PyObject *item = PyList_GetItem(list, i); - if (!PyStr_Check(item)) { + if (!(PyStr_Check(item) || PyUnicode_Check(item))) { PyErr_Format(PyExc_TypeError, "%s should be strings", paramname); talloc_free(ret); return NULL; @@ -2861,7 +2861,7 @@ static struct ldb_message_element *PyObject_AsMessageElement( me->name = talloc_strdup(me, attr_name); me->flags = flags; - if (PyBytes_Check(set_obj) || PyStr_Check(set_obj)) { + if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) { me->num_values = 1; me->values = talloc_array(me, struct ldb_val, me->num_values); if (PyBytes_Check(set_obj)) { @@ -2897,7 +2897,7 @@ static struct ldb_message_element *PyObject_AsMessageElement( return NULL; } msg = _msg; - } else if (PyStr_Check(obj)) { + } else if (PyUnicode_Check(obj)) { msg = PyStr_AsUTF8AndSize(obj, &size); if (msg == NULL) { talloc_free(me); @@ -3069,7 +3069,7 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb if (py_elements != NULL) { Py_ssize_t i; - if (PyBytes_Check(py_elements) || PyStr_Check(py_elements)) { + if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) { char *_msg = NULL; el->num_values = 1; el->values = talloc_array(el, struct ldb_val, 1); @@ -3110,7 +3110,7 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb char *_msg = NULL; result = PyBytes_AsStringAndSize(item, &_msg, &size); msg = _msg; - } else if (PyStr_Check(item)) { + } else if (PyUnicode_Check(item)) { msg = PyStr_AsUTF8AndSize(item, &size); result = (msg == NULL) ? -1 : 0; } else { diff --git a/lib/ldb/pyldb_util.c b/lib/ldb/pyldb_util.c index 3bda1dbc2a8..46ee4034122 100644 --- a/lib/ldb/pyldb_util.c +++ b/lib/ldb/pyldb_util.c @@ -70,7 +70,7 @@ bool pyldb_Object_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, struct ldb_dn *odn; PyTypeObject *PyLdb_Dn_Type; - if (ldb_ctx != NULL && PyStr_Check(object)) { + if (ldb_ctx != NULL && (PyStr_Check(object) || PyUnicode_Check(object))) { odn = ldb_dn_new(mem_ctx, ldb_ctx, PyStr_AsUTF8(object)); *dn = odn; return true; From 485186ec51dfd468a83be3736e90144cd65016d4 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:17:20 +0100 Subject: [PATCH 03/10] lib/tevent: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- lib/tevent/pytevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 10d8a22a8cf..369ec6e02c8 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -188,7 +188,7 @@ static PyObject *py_register_backend(PyObject *self, PyObject *args) return NULL; } - if (!PyStr_Check(name)) { + if (!(PyStr_Check(name) || PyUnicode_Check(name))) { PyErr_SetNone(PyExc_TypeError); Py_DECREF(name); return NULL; From 67659adbe1caf7ee675941de566995415b7506d6 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:32:15 +0100 Subject: [PATCH 04/10] libcli/nbt: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- libcli/nbt/pynbt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcli/nbt/pynbt.c b/libcli/nbt/pynbt.c index 254c98a4b89..032561a4bd8 100644 --- a/libcli/nbt/pynbt.c +++ b/libcli/nbt/pynbt.c @@ -57,7 +57,7 @@ static PyObject *py_nbt_node_init(PyTypeObject *self, PyObject *args, PyObject * static bool PyObject_AsDestinationTuple(PyObject *obj, const char **dest_addr, uint16_t *dest_port) { - if (PyStr_Check(obj)) { + if (PyStr_Check(obj) || PyUnicode_Check(obj)) { *dest_addr = PyStr_AsString(obj); *dest_port = NBT_NAME_SERVICE_PORT; return true; @@ -69,7 +69,7 @@ static bool PyObject_AsDestinationTuple(PyObject *obj, const char **dest_addr, u return false; } - if (!PyStr_Check(PyTuple_GetItem(obj, 0))) { + if (!(PyStr_Check(PyTuple_GetItem(obj, 0)) || PyUnicode_Check(PyTuple_GetItem(obj, 0)))) { PyErr_SetString(PyExc_TypeError, "Destination tuple first element not string"); return false; } @@ -111,7 +111,7 @@ static bool PyObject_AsNBTName(PyObject *obj, struct nbt_name_socket *name_socke } } - if (PyStr_Check(obj)) { + if (PyStr_Check(obj) || PyUnicode_Check(obj)) { /* FIXME: Parse string to be able to interpret things like RHONWYN<02> ? */ name->name = PyStr_AsString(obj); name->scope = NULL; From c9da4b9820cd62e403a42135e41e047efd14ceaf Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:33:10 +0100 Subject: [PATCH 05/10] s4/auth: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- source4/auth/pyauth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/auth/pyauth.c b/source4/auth/pyauth.c index 4cb12f882bc..fc22637564d 100644 --- a/source4/auth/pyauth.c +++ b/source4/auth/pyauth.c @@ -184,7 +184,7 @@ static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, const char *value; Py_ssize_t size; PyObject *item = PyList_GetItem(list, i); - if (!PyStr_Check(item)) { + if (!(PyStr_Check(item) || PyUnicode_Check(item))) { PyErr_Format(PyExc_TypeError, "%s should be strings", paramname); return NULL; } From c755f5f3a31e804715d5d53038fbc5c4a8150641 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:33:47 +0100 Subject: [PATCH 06/10] s4/dsdb: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- source4/dsdb/pydsdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index 8d84a16dd18..d9177bbd1d7 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -580,7 +580,7 @@ static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args) for (i = 0; i < el->num_values; i++) { PyObject *item = PyList_GetItem(el_list, i); - if (!PyStr_Check(item)) { + if (!(PyStr_Check(item) || PyUnicode_Check(item))) { PyErr_Format(PyExc_TypeError, "ldif_elements should be strings"); talloc_free(tmp_ctx); return NULL; From c79b65af37e9a76ea2dc5780c231ed7bb3bb3ef8 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:34:19 +0100 Subject: [PATCH 07/10] s4/librpc: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- source4/librpc/rpc/pyrpc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source4/librpc/rpc/pyrpc.c b/source4/librpc/rpc/pyrpc.c index 8b817b8b46d..e86ea0e94aa 100644 --- a/source4/librpc/rpc/pyrpc.c +++ b/source4/librpc/rpc/pyrpc.c @@ -50,28 +50,32 @@ static bool ndr_syntax_from_py_object(PyObject *object, struct ndr_syntax_id *sy { ZERO_STRUCTP(syntax_id); - if (PyStr_Check(object)) { + if (PyStr_Check(object) || PyUnicode_Check(object)) { return PyString_AsGUID(object, &syntax_id->uuid); } else if (PyTuple_Check(object)) { + PyObject *item = NULL; if (PyTuple_Size(object) < 1 || PyTuple_Size(object) > 2) { PyErr_SetString(PyExc_ValueError, "Syntax ID tuple has invalid size"); return false; } - if (!PyStr_Check(PyTuple_GetItem(object, 0))) { + item = PyTuple_GetItem(object, 0); + if (!(PyStr_Check(item) || PyUnicode_Check(item))) { PyErr_SetString(PyExc_ValueError, "Expected GUID as first element in tuple"); return false; } - if (!PyString_AsGUID(PyTuple_GetItem(object, 0), &syntax_id->uuid)) + if (!PyString_AsGUID(item, &syntax_id->uuid)) { return false; + } - if (!PyInt_Check(PyTuple_GetItem(object, 1))) { + item = PyTuple_GetItem(object, 1); + if (!PyInt_Check(item)) { PyErr_SetString(PyExc_ValueError, "Expected version as second element in tuple"); return false; } - syntax_id->if_version = PyInt_AsLong(PyTuple_GetItem(object, 1)); + syntax_id->if_version = PyInt_AsLong(item); return true; } From 197a38567d2fd234dfd517b2e66bc12a2f6b9e4c Mon Sep 17 00:00:00 2001 From: Noel Power Date: Fri, 13 Apr 2018 17:34:40 +0100 Subject: [PATCH 08/10] s4/param: Additionally accept unicode as string param in Py2 With the changes to make samba python code Py2/Py3 compatible there now are many instances where string content is decoded. Decoded string variables in Py2 are returned as the unicode type. Many Py2 c-module functions that take string arguments only check for the string type. However now it's quite possibe the content formally passed as a string argument is now passed as unicode after being decoded, such arguments are rejected and code can fail subtly. This only affects places where the type is directly checked e.g. via PyStr_Check etc. arguments that are parsed by ParseTuple* functions generally already accept both string and unicode (if 's', 'z', 's*' format specifiers are used) Signed-off-by: Noel Power --- source4/param/pyparam.c | 2 +- source4/param/pyparam_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/param/pyparam.c b/source4/param/pyparam.c index 18d7017b9c6..e7e908fcac3 100644 --- a/source4/param/pyparam.c +++ b/source4/param/pyparam.c @@ -456,7 +456,7 @@ static Py_ssize_t py_lp_ctx_len(PyObject *self) static PyObject *py_lp_ctx_getitem(PyObject *self, PyObject *name) { struct loadparm_service *service; - if (!PyStr_Check(name)) { + if (!(PyStr_Check(name) || PyUnicode_Check(name))) { PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported"); return NULL; } diff --git a/source4/param/pyparam_util.c b/source4/param/pyparam_util.c index 512a8b1cdb7..917caf809e5 100644 --- a/source4/param/pyparam_util.c +++ b/source4/param/pyparam_util.c @@ -34,7 +34,7 @@ _PUBLIC_ struct loadparm_context *lpcfg_from_py_object(TALLOC_CTX *mem_ctx, PyOb PyTypeObject *lp_type; bool is_lpobj; - if (PyStr_Check(py_obj)) { + if (PyStr_Check(py_obj) || PyUnicode_Check(py_obj)) { lp_ctx = loadparm_init_global(false); if (lp_ctx == NULL) { return NULL; From c9024f173ab20a940d773523a9c97cd8717a56d4 Mon Sep 17 00:00:00 2001 From: Noel Power Date: Tue, 10 Apr 2018 15:28:59 +0100 Subject: [PATCH 09/10] python/samba: Port to py3 code exercised by samba.tests.dsdb_lock Signed-off-by: Noel Power --- python/samba/__init__.py | 7 ++-- python/samba/dbchecker.py | 7 ++-- python/samba/descriptor.py | 2 +- python/samba/idmap.py | 2 +- python/samba/ms_display_specifiers.py | 3 +- python/samba/ms_schema.py | 11 ++++--- python/samba/netcmd/fsmo.py | 2 +- python/samba/provision/__init__.py | 62 ++++++++++++++++++----------------- python/samba/provision/sambadns.py | 12 +++---- python/samba/samdb.py | 4 +-- python/samba/schema.py | 7 ++-- 11 files changed, 63 insertions(+), 56 deletions(-) diff --git a/python/samba/__init__.py b/python/samba/__init__.py index f62f5e39202..54fd638eab1 100644 --- a/python/samba/__init__.py +++ b/python/samba/__init__.py @@ -29,6 +29,8 @@ import samba.param from samba import _glue from samba._ldb import Ldb as _Ldb +from samba.compat import string_types + def source_tree_topdir(): @@ -247,10 +249,9 @@ def substitute_var(text, values): :param text: Text in which to subsitute. :param values: Dictionary with keys and values. """ - for (name, value) in values.items(): - assert isinstance(name, str), "%r is not a string" % name - assert isinstance(value, str), "Value %r for %s is not a string" % (value, name) + assert isinstance(name, string_types), "%r is not a string" % name + assert isinstance(value, string_types), "Value %r for %s is not a string" % (value, name) text = text.replace("${%s}" % name, value) return text diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index fb968a56481..e5906523e93 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -144,6 +144,7 @@ def __init__(self, samdb, samdb_schema=None, verbose=False, fix=False, for nc in self.ncs: try: + nc = nc.decode('utf8') dn = self.samdb.get_wellknown_dn(ldb.Dn(self.samdb, nc), dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER) self.deleted_objects_containers.append(dn) @@ -178,13 +179,13 @@ def __init__(self, samdb, samdb_schema=None, verbose=False, fix=False, res = self.samdb.search(base=ldb.Dn(self.samdb, self.samdb.get_serverName()), scope=ldb.SCOPE_BASE, attrs=["serverReference"]) # 2. Get server reference - self.server_ref_dn = ldb.Dn(self.samdb, res[0]['serverReference'][0]) + self.server_ref_dn = ldb.Dn(self.samdb, res[0]['serverReference'][0].decode('utf8')) # 3. Get RID Set res = self.samdb.search(base=self.server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) if "rIDSetReferences" in res[0]: - self.rid_set_dn = ldb.Dn(self.samdb, res[0]['rIDSetReferences'][0]) + self.rid_set_dn = ldb.Dn(self.samdb, res[0]['rIDSetReferences'][0].decode('utf8')) else: self.rid_set_dn = None @@ -1178,7 +1179,7 @@ def check_dn(self, obj, attrname, syntax_oid): obj[attrname] = ldb.MessageElement(vals, 0, attrname) for val in obj[attrname]: - dsdb_dn = dsdb_Dn(self.samdb, val, syntax_oid) + dsdb_dn = dsdb_Dn(self.samdb, val.decode('utf8'), syntax_oid) # all DNs should have a GUID component guid = dsdb_dn.dn.get_extended_component("GUID") diff --git a/python/samba/descriptor.py b/python/samba/descriptor.py index a9c5e1580f0..e4650b294c4 100644 --- a/python/samba/descriptor.py +++ b/python/samba/descriptor.py @@ -413,7 +413,7 @@ def get_wellknown_sds(samdb): attrs=["namingContexts"]) for nc in current[0]["namingContexts"]: - + nc = nc.decode('utf8') dnsforestdn = ldb.Dn(samdb, "DC=ForestDnsZones,%s" % (str(samdb.get_root_basedn()))) if ldb.Dn(samdb, nc) == dnsforestdn: c = (ldb.Dn(samdb, "%s" % str(dnsforestdn)), get_dns_partition_descriptor) diff --git a/python/samba/idmap.py b/python/samba/idmap.py index 0cb729fbc29..a618347fa21 100644 --- a/python/samba/idmap.py +++ b/python/samba/idmap.py @@ -95,4 +95,4 @@ def setup_name_mapping(self, sid, type, unixid=None): cn: %s """ % (sid, unixid, sid, type_string, sid) - self.add(self.parse_ldif(mod).next()[1]) + self.add(next(self.parse_ldif(mod))[1]) diff --git a/python/samba/ms_display_specifiers.py b/python/samba/ms_display_specifiers.py index 0d7b39aaae9..3cba837c652 100644 --- a/python/samba/ms_display_specifiers.py +++ b/python/samba/ms_display_specifiers.py @@ -169,7 +169,8 @@ def read_ms_ldif(filename): out = [] - f = open(filename, "rU") + from io import open + f = open(filename, "r", encoding='latin-1') for entry in __read_raw_entries(f): out.append(__write_ldif_one(__transform_entry(entry))) diff --git a/python/samba/ms_schema.py b/python/samba/ms_schema.py index 889b7f5ef22..3e92393a4bf 100644 --- a/python/samba/ms_schema.py +++ b/python/samba/ms_schema.py @@ -21,6 +21,7 @@ import re import base64 import uuid +from samba.compat import string_types bitFields = {} @@ -172,7 +173,7 @@ def fix_dn(dn): def __convert_bitfield(key, value): """Evaluate the OR expression in 'value'""" - assert(isinstance(value, str)) + assert(isinstance(value, string_types)) value = value.replace("\n ", "") value = value.replace(" ", "") @@ -194,7 +195,7 @@ def __write_ldif_one(entry): out = [] for l in entry: - if isinstance(l[1], str): + if isinstance(l[1], string_types): vl = [l[1]] else: vl = l[1] @@ -246,8 +247,7 @@ def __transform_entry(entry, objectClass): if not l[2]: l[1] = oMObjectClassBER[l[1].strip()] l[2] = True - - if isinstance(l[1], str): + if isinstance(l[1], string_types): l[1] = fix_dn(l[1]) if key == 'dn': @@ -286,8 +286,9 @@ def __parse_schema_file(filename, objectClass): """Load and transform a schema file.""" out = [] + from io import open + f = open(filename, "r", encoding='latin-1') - f = open(filename, "rU") for entry in __read_raw_entries(f): out.append(__write_ldif_one(__transform_entry(entry, objectClass))) diff --git a/python/samba/netcmd/fsmo.py b/python/samba/netcmd/fsmo.py index 41e45592b46..14b8fa6c791 100644 --- a/python/samba/netcmd/fsmo.py +++ b/python/samba/netcmd/fsmo.py @@ -47,7 +47,7 @@ def get_fsmo_roleowner(samdb, roledn, role): raise if 'fSMORoleOwner' in res[0]: - master_owner = (ldb.Dn(samdb, res[0]["fSMORoleOwner"][0])) + master_owner = (ldb.Dn(samdb, res[0]["fSMORoleOwner"][0].decode('utf8'))) else: master_owner = None diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index 1709e75184e..83239db0299 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -25,7 +25,8 @@ """Functions for setting up a Samba configuration.""" __docformat__ = "restructuredText" - +from samba.compat import string_types +from samba.compat import urllib_quote from base64 import b64encode import errno import os @@ -37,7 +38,6 @@ import time import uuid import socket -import urllib import string import tempfile import samba.dsdb @@ -780,7 +780,7 @@ def make_smbconf(smbconf, hostname, domain, realm, targetdir, for name, path in shares.items(): f.write("[%s]\n" % name) - f.write("\tpath = %s\n" % path) + f.write("\tpath = %s\n" % shares[name]) f.write("\tread only = no\n") f.write("\n") finally: @@ -1070,7 +1070,7 @@ def setup_encrypted_secrets_key(path): finally: os.umask(umask_original) - with os.fdopen(fd, 'w') as f: + with os.fdopen(fd, 'wb') as f: key = samba.generate_random_bytes(16) f.write(key) @@ -1144,7 +1144,7 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass, "INVOCATIONID": invocationid, "NETBIOSNAME": names.netbiosname, "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain), - "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')), + "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')).decode('utf8'), "DOMAINSID": str(domainsid), "DCRID": str(dc_rid), "SAMBA_VERSION_STRING": version, @@ -1171,7 +1171,7 @@ def setup_self_join(samdb, admin_session_info, names, fill, machinepass, "INVOCATIONID": invocationid, "NETBIOSNAME": names.netbiosname, "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain), - "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')), + "MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')).decode('utf8'), "DOMAINSID": str(domainsid), "DCRID": str(dc_rid), "SAMBA_VERSION_STRING": version, @@ -1367,7 +1367,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid, else: domainguid_line = "" - descr = b64encode(get_domain_descriptor(names.domainsid)) + descr = b64encode(get_domain_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), { "DOMAINDN": names.domaindn, "DOMAINSID": str(names.domainsid), @@ -1390,7 +1390,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid, # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it if fill == FILL_FULL: logger.info("Adding configuration container") - descr = b64encode(get_config_descriptor(names.domainsid)) + descr = b64encode(get_config_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), { "CONFIGDN": names.configdn, "DESCRIPTOR": descr, @@ -1420,12 +1420,12 @@ def fill_samdb(samdb, lp, names, logger, policyguid, if fill == FILL_FULL: logger.info("Setting up sam.ldb configuration data") - partitions_descr = b64encode(get_config_partitions_descriptor(names.domainsid)) - sites_descr = b64encode(get_config_sites_descriptor(names.domainsid)) - ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(names.domainsid)) - protected1_descr = b64encode(get_config_delete_protected1_descriptor(names.domainsid)) - protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)) - protected2_descr = b64encode(get_config_delete_protected2_descriptor(names.domainsid)) + partitions_descr = b64encode(get_config_partitions_descriptor(names.domainsid)).decode('utf8') + sites_descr = b64encode(get_config_sites_descriptor(names.domainsid)).decode('utf8') + ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(names.domainsid)).decode('utf8') + protected1_descr = b64encode(get_config_delete_protected1_descriptor(names.domainsid)).decode('utf8') + protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)).decode('utf8') + protected2_descr = b64encode(get_config_delete_protected2_descriptor(names.domainsid)).decode('utf8') if "2008" in schema.base_schema: # exclude 2012-specific changes if we're using a 2008 schema @@ -1475,7 +1475,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid, }) logger.info("Adding users container") - users_desc = b64encode(get_domain_users_descriptor(names.domainsid)) + users_desc = b64encode(get_domain_users_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), { "DOMAINDN": names.domaindn, "USERS_DESCRIPTOR": users_desc @@ -1484,7 +1484,7 @@ def fill_samdb(samdb, lp, names, logger, policyguid, setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), { "DOMAINDN": names.domaindn}) logger.info("Adding computers container") - computers_desc = b64encode(get_domain_computers_descriptor(names.domainsid)) + computers_desc = b64encode(get_domain_computers_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), { "DOMAINDN": names.domaindn, "COMPUTERS_DESCRIPTOR": computers_desc @@ -1494,11 +1494,11 @@ def fill_samdb(samdb, lp, names, logger, policyguid, setup_path("provision_computers_modify.ldif"), { "DOMAINDN": names.domaindn}) logger.info("Setting up sam.ldb data") - infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid)) - lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid)) - system_desc = b64encode(get_domain_delete_protected1_descriptor(names.domainsid)) - builtin_desc = b64encode(get_domain_builtin_descriptor(names.domainsid)) - controllers_desc = b64encode(get_domain_controllers_descriptor(names.domainsid)) + infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(names.domainsid)).decode('utf8') + lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(names.domainsid)).decode('utf8') + system_desc = b64encode(get_domain_delete_protected1_descriptor(names.domainsid)).decode('utf8') + builtin_desc = b64encode(get_domain_builtin_descriptor(names.domainsid)).decode('utf8') + controllers_desc = b64encode(get_domain_controllers_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision.ldif"), { "CREATTIME": str(samba.unix2nttime(int(time.time()))), "DOMAINDN": names.domaindn, @@ -1517,14 +1517,14 @@ def fill_samdb(samdb, lp, names, logger, policyguid, # If we are setting up a subdomain, then this has been replicated in, so we don't need to add it if fill == FILL_FULL: - managedservice_descr = b64encode(get_managed_service_accounts_descriptor(names.domainsid)) + managedservice_descr = b64encode(get_managed_service_accounts_descriptor(names.domainsid)).decode('utf8') setup_modify_ldif(samdb, setup_path("provision_configuration_references.ldif"), { "CONFIGDN": names.configdn, "SCHEMADN": names.schemadn}) logger.info("Setting up well known security principals") - protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)) + protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(names.domainsid)).decode('utf8') setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), { "CONFIGDN": names.configdn, "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr, @@ -1541,8 +1541,8 @@ def fill_samdb(samdb, lp, names, logger, policyguid, setup_add_ldif(samdb, setup_path("provision_users.ldif"), { "DOMAINDN": names.domaindn, "DOMAINSID": str(names.domainsid), - "ADMINPASS_B64": b64encode(adminpass.encode('utf-16-le')), - "KRBTGTPASS_B64": b64encode(krbtgtpass.encode('utf-16-le')) + "ADMINPASS_B64": b64encode(adminpass.encode('utf-16-le')).decode('utf8'), + "KRBTGTPASS_B64": b64encode(krbtgtpass.encode('utf-16-le')).decode('utf8') }, controls=["relax:0", "provision:0"]) logger.info("Setting up self join") @@ -1562,7 +1562,9 @@ def fill_samdb(samdb, lp, names, logger, policyguid, ntds_dn = "CN=NTDS Settings,%s" % names.serverdn names.ntdsguid = samdb.searchone(basedn=ntds_dn, attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE) - assert isinstance(names.ntdsguid, str) + + names.ntdsguid = names.ntdsguid.decode('utf8') + assert isinstance(names.ntdsguid, string_types) return samdb @@ -1920,7 +1922,7 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, msg = ldb.Message(ldb.Dn(samdb, samdb.searchone("distinguishedName", expression="samAccountName=%s$" % names.netbiosname, - scope=ldb.SCOPE_SUBTREE))) + scope=ldb.SCOPE_SUBTREE).decode('utf8'))) msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement( elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE, name="msDS-SupportedEncryptionTypes") @@ -1938,8 +1940,8 @@ def provision_fill(samdb, secrets_ldb, logger, names, paths, backend_store=backend_store) domainguid = samdb.searchone(basedn=samdb.get_default_basedn(), - attribute="objectGUID") - assert isinstance(domainguid, str) + attribute="objectGUID").decode('utf8') + assert isinstance(domainguid, string_types) lastProvisionUSNs = get_last_provision_usn(samdb) maxUSN = get_max_usn(samdb, str(names.rootdn)) @@ -2189,7 +2191,7 @@ def provision(logger, session_info, smbconf=None, if paths.sysvol and not os.path.exists(paths.sysvol): os.makedirs(paths.sysvol, 0o775) - ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="") + ldapi_url = "ldapi://%s" % urllib_quote(paths.s4_ldapi_path, safe="") schema = Schema(domainsid, invocationid=invocationid, schemadn=names.schemadn, base_schema=base_schema) diff --git a/python/samba/provision/sambadns.py b/python/samba/provision/sambadns.py index 3d59c701066..218f57fe679 100644 --- a/python/samba/provision/sambadns.py +++ b/python/samba/provision/sambadns.py @@ -247,12 +247,12 @@ def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": domainzone_dn, - "SECDESC" : b64encode(descriptor) + "SECDESC" : b64encode(descriptor).decode('utf8') }) if fill_level != FILL_SUBDOMAIN: setup_add_ldif(samdb, setup_path("provision_dnszones_partitions.ldif"), { "ZONE_DN": forestzone_dn, - "SECDESC" : b64encode(descriptor) + "SECDESC" : b64encode(descriptor).decode('utf8') }) domainzone_guid = get_domainguid(samdb, domainzone_dn) @@ -267,8 +267,8 @@ def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, "ZONE_DNS": domainzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, - "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), - "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), + "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc).decode('utf8'), + "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc).decode('utf8'), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, @@ -287,8 +287,8 @@ def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn, "ZONE_DNS": forestzone_dns, "CONFIGDN": configdn, "SERVERDN": serverdn, - "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc), - "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc), + "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc).decode('utf8'), + "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc).decode('utf8'), }) setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), { "CONFIGDN": configdn, diff --git a/python/samba/samdb.py b/python/samba/samdb.py index b66afb7431c..a1a1f45b003 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -1024,12 +1024,12 @@ def sequence_number(self, seq_type): def get_dsServiceName(self): '''get the NTDS DN from the rootDSE''' res = self.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"]) - return res[0]["dsServiceName"][0] + return res[0]["dsServiceName"][0].decode('utf8') def get_serverName(self): '''get the server DN from the rootDSE''' res = self.search(base="", scope=ldb.SCOPE_BASE, attrs=["serverName"]) - return res[0]["serverName"][0] + return res[0]["serverName"][0].decode('utf8') def dns_lookup(self, dns_name, dns_partition=None): '''Do a DNS lookup in the database, returns the NDR database structures''' diff --git a/python/samba/schema.py b/python/samba/schema.py index 67ec357a285..e161aa8ca0b 100644 --- a/python/samba/schema.py +++ b/python/samba/schema.py @@ -122,7 +122,7 @@ def __init__(self, domain_sid, invocationid=None, schemadn=None, setup_path("provision_schema_basedn_modify.ldif"), {"SCHEMADN": schemadn, "OBJVERSION" : schema_version}) - descr = b64encode(get_schema_descriptor(domain_sid)) + descr = b64encode(get_schema_descriptor(domain_sid)).decode('utf8') self.schema_dn_add = read_and_sub_file( setup_path("provision_schema_basedn.ldif"), {"SCHEMADN": schemadn, "DESCRIPTOR": descr}) @@ -130,13 +130,14 @@ def __init__(self, domain_sid, invocationid=None, schemadn=None, if override_prefixmap is not None: self.prefixmap_data = override_prefixmap else: - self.prefixmap_data = open(setup_path("prefixMap.txt"), 'r').read() + self.prefixmap_data = open(setup_path("prefixMap.txt"), 'rb').read() if additional_prefixmap is not None: for map in additional_prefixmap: self.prefixmap_data += "%s\n" % map - self.prefixmap_data = b64encode(self.prefixmap_data) + #self.prefixmap_data = b64encode(self.prefixmap_data.encode('utf8')).decode('utf8') + self.prefixmap_data = b64encode(self.prefixmap_data).decode('utf8') # We don't actually add this ldif, just parse it prefixmap_ldif = "dn: %s\nprefixMap:: %s\n\n" % (self.schemadn, self.prefixmap_data) From 77329973850e47cfd11702780db2be704ea0b87d Mon Sep 17 00:00:00 2001 From: Noel Power Date: Tue, 10 Apr 2018 16:03:37 +0100 Subject: [PATCH 10/10] s4/selftest: enable samba.tests.dsdb_lock for python3 Signed-off-by: Noel Power --- source4/selftest/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index d1e5bc6a509..9d41e9eb77c 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -578,7 +578,7 @@ def planoldpythontestsuite(env, module, name=None, extra_path=[], environ={}, ex planoldpythontestsuite("none", "simple", extra_path=["%s/lib/tdb/python/tests" % srcdir()], name="tdb.python") planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.sam", py3_compatible=True) planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dsdb", py3_compatible=True) -planpythontestsuite("none", "samba.tests.dsdb_lock") +planpythontestsuite("none", "samba.tests.dsdb_lock", py3_compatible=True) planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.bare", py3_compatible=True) planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.unix") planpythontestsuite("ad_dc_ntvfs:local", "samba.tests.dcerpc.srvsvc")