[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Feb 29 05:08:01 UTC 2024


The branch, master has been updated
       via  0c1ac197768 samba-tool user getpassword: Clarify success wording
       via  00daa520ce8 python/nt_time: have a go at using 1_000_000 number separators.
       via  d3d87aee2a7 python:nt_time: add a nt_now() function
       via  33a8ae1748a python:nt_time: add string_from_nt_time
       via  60022ed55f7 py:nt_time: add nt_time_from_string()
       via  bfba074d2f4 pyldb: try to turn ldb_string_to_time() errors into exceptions
       via  8892b0cc926 ldb: ldb_string_to_time reports more errors
       via  9beb57892db s4:pydsdb: add not-implemented raising functions to when appropriate
       via  ed344bb22f4 pyldb: catch some talloc failures
       via  c68b390e66f pyldb: free some finished requests
       via  a4c4e3c95f9 pyldb: free things more often on error
       via  cccc994fa07 pyldb: add a macro to free when raising exceptions
       via  8cf9d4cae1e pytest:audit_log_base: use string_is_guid()
       via  6d087d1d29e pytest:auth_log_base: use string_is_guid()
      from  0fe263a56d0 pylibs: add string_is_guid() helper.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0c1ac19776835034df8f54a78c2022375cff921e
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Feb 29 14:57:40 2024 +1300

    samba-tool user getpassword: Clarify success wording
    
    It may be the case that there was no password, or read access to the
    password was not permitted.  The structure of the code and the pattern
    in LDIF that missing information is simply returned as missing
    attributes makes it hard to detect and communicate a clear
    error here, particularly as an error may not be wanted if
    (say) pwdLastSet is queried on a gMSA that we can not read.
    
    So we just make the string to indicate, as I think it was meant,
    that the tool ran to compleation.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Feb 29 05:07:45 UTC 2024 on atb-devel-224

commit 00daa520ce80deb76e08684b3f9b3f22202bcd2c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 23 16:23:03 2024 +1300

    python/nt_time: have a go at using 1_000_000 number separators.
    
    I noticed these are available in Python 3.6+, which is what we support,
    and they're arguably nicer than using exponentiation.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d3d87aee2a782691f7bf5b8247f07068fc2fb381
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:52:12 2024 +1300

    python:nt_time: add a nt_now() function
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 33a8ae1748ae02435b0097366085ddaabb503dc8
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:51:41 2024 +1300

    python:nt_time: add string_from_nt_time
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 60022ed55f7a213440b70c6d4b4796a4a7b0fa9f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 14 14:31:35 2024 +1300

    py:nt_time: add nt_time_from_string()
    
    This is for samba-tool, which could do with a common understanding of
    time strings across various sub-tools.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit bfba074d2f41e70ce743ce7e216c498ab5bd977a
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 14 14:22:53 2024 +1300

    pyldb: try to turn ldb_string_to_time() errors into exceptions
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8892b0cc92650c20f908f1076677ab4c2b6cc418
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 14 14:20:28 2024 +1300

    ldb: ldb_string_to_time reports more errors
    
    The underlying function should return -1 and set errno when given invalid
    strings, but we were not looking and have decided on 0 for error.
    
    It would be a pain to change this function to return -1. Apart from the
    API fuss, it is sometimes used unchecked to set an unsigned number and
    an unchecked 0 is better than UINT*_MAX in those contexts.
    
    It is probably not easy to get an -1 from a timegm() -- most
    implementations will happily convert overflows for you, so e.g. the
    15th month would be March of the next year. But EOVERFLOW is mentioned
    in the manpages.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9beb57892db1e4056a038519961cc657cf7a744f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 21 23:13:51 2024 +1300

    s4:pydsdb: add not-implemented raising functions to when appropriate
    
    It will be less confusing, I hope.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ed344bb22f449b977e2ffc30e486446615163110
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:30:29 2024 +1300

    pyldb: catch some talloc failures
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c68b390e66f6888796a6911b031a11eea86a890d
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:27:59 2024 +1300

    pyldb: free some finished requests
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a4c4e3c95f9589ace6659a556ae2847acb70a2e0
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Feb 22 12:57:19 2024 +1300

    pyldb: free things more often on error
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cccc994fa076f3f784bce7258a95d756d44cd190
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Feb 22 11:19:30 2024 +1300

    pyldb: add a macro to free when raising exceptions
    
    We often forget.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8cf9d4cae1e73077c463648a7fcc9cbf329c03ec
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:19:59 2024 +1300

    pytest:audit_log_base: use string_is_guid()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6d087d1d29e7d64f1efa8fcf8cfb542665aa122f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:19:38 2024 +1300

    pytest:auth_log_base: use string_is_guid()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/ldb/common/ldb_msg.c                           | 11 +++-
 lib/ldb/pyldb.c                                    | 48 +++++++++++++---
 lib/ldb/pyldb.h                                    | 10 +++-
 lib/ldb/tests/python/api.py                        |  1 +
 .../samba/netcmd/user/readpasswords/getpassword.py |  2 +-
 python/samba/nt_time.py                            | 64 +++++++++++++++++++++-
 python/samba/tests/audit_log_base.py               | 11 +---
 python/samba/tests/auth_log_base.py                | 11 +---
 python/samba/tests/samba_tool/user.py              |  2 +-
 .../samba/tests/samba_tool/user_virtualCryptSHA.py |  2 +-
 .../tests/samba_tool/user_virtualCryptSHA_base.py  |  2 +-
 python/samba/tests/samba_tool/user_wdigest.py      |  2 +-
 source4/dsdb/pydsdb.c                              | 34 +++++++++++-
 13 files changed, 165 insertions(+), 35 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c
index afddbe40ef6..53f675ed183 100644
--- a/lib/ldb/common/ldb_msg.c
+++ b/lib/ldb/common/ldb_msg.c
@@ -1597,6 +1597,7 @@ char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
 time_t ldb_string_to_time(const char *s)
 {
 	struct tm tm;
+	time_t t;
 
 	if (s == NULL) return 0;
 
@@ -1609,7 +1610,15 @@ time_t ldb_string_to_time(const char *s)
 	tm.tm_year -= 1900;
 	tm.tm_mon -= 1;
 
-	return timegm(&tm);
+	t = timegm(&tm);
+
+	if (t == (time_t)-1 && errno != 0) {
+		/*
+		 * timegm() returns -1 on error, but also for '19691231235959.0Z'.
+		 */
+		return 0;
+	}
+	return t;
 }
 
 /*
diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c
index 3177e20bb8b..23637a6b2a2 100644
--- a/lib/ldb/pyldb.c
+++ b/lib/ldb/pyldb.c
@@ -3137,13 +3137,13 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P
 
 	talloc_steal(req, attrs);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, mod->ldb, req);
 
 	req->op.search.res = NULL;
 
 	ret = mod->ops->search(mod, req);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, mod->ldb, req);
 
 	py_ret = PyLdbResult_FromResult(req->op.search.res);
 
@@ -3164,14 +3164,19 @@ static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
 		return NULL;
 
 	req = talloc_zero(NULL, struct ldb_request);
+	if (req == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
 	req->operation = LDB_ADD;
 	req->op.add.message = pyldb_Message_AsMessage(py_message);
 
 	mod = pyldb_Module_AsModule(self);
 	ret = mod->ops->add(mod, req);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, mod->ldb, req);
 
+	TALLOC_FREE(req);
 	Py_RETURN_NONE;
 }
 
@@ -3186,14 +3191,20 @@ static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
 		return NULL;
 
 	req = talloc_zero(NULL, struct ldb_request);
+	if (req == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
+
 	req->operation = LDB_MODIFY;
 	req->op.mod.message = pyldb_Message_AsMessage(py_message);
 
 	mod = pyldb_Module_AsModule(self);
 	ret = mod->ops->modify(mod, req);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, mod->ldb, req);
 
+	TALLOC_FREE(req);
 	Py_RETURN_NONE;
 }
 
@@ -3207,12 +3218,18 @@ static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
 		return NULL;
 
 	req = talloc_zero(NULL, struct ldb_request);
+	if (req == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
 	req->operation = LDB_DELETE;
 	req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
 
 	ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, NULL, req);
+
+	TALLOC_FREE(req);
 
 	Py_RETURN_NONE;
 }
@@ -3227,6 +3244,10 @@ static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
 		return NULL;
 
 	req = talloc_zero(NULL, struct ldb_request);
+	if (req == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
 
 	req->operation = LDB_RENAME;
 	req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
@@ -3234,7 +3255,9 @@ static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
 
 	ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, NULL, req);
+
+	TALLOC_FREE(req);
 
 	Py_RETURN_NONE;
 }
@@ -4726,7 +4749,7 @@ static PyObject *py_register_module(PyObject *module, PyObject *args)
 		TALLOC_FREE(ops);
 	}
 
-	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
+	PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(PyExc_LdbError, ret, NULL, ops);
 
 	Py_RETURN_NONE;
 }
@@ -4756,10 +4779,17 @@ static PyObject *py_timestring(PyObject *module, PyObject *args)
 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
 {
 	char *str;
-	if (!PyArg_ParseTuple(args, "s", &str))
+	time_t t;
+	if (!PyArg_ParseTuple(args, "s", &str)) {
 		return NULL;
+	}
+	t = ldb_string_to_time(str);
 
-	return PyLong_FromLong(ldb_string_to_time(str));
+	if (t == 0 && errno != 0) {
+		PyErr_SetFromErrno(PyExc_ValueError);
+		return NULL;
+	}
+	return PyLong_FromLong(t);
 }
 
 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
diff --git a/lib/ldb/pyldb.h b/lib/ldb/pyldb.h
index 2d354422cdb..45637b76691 100644
--- a/lib/ldb/pyldb.h
+++ b/lib/ldb/pyldb.h
@@ -110,7 +110,15 @@ typedef struct {
 	} \
 } while(0)
 
-/* Picked out of thin air. To do this properly, we should probably have some part of the 
+#define PyErr_LDB_ERROR_IS_ERR_RAISE_FREE(err,ret,ldb,mem_ctx) do {	\
+	if (ret != LDB_SUCCESS) { \
+		PyErr_SetLdbError(err, ret, ldb); \
+		TALLOC_FREE(mem_ctx);		  \
+		return NULL; \
+	} \
+} while(0)
+
+/* Picked out of thin air. To do this properly, we should probably have some part of the
  * errors in LDB be allocated to bindings ? */
 #define LDB_ERR_PYTHON_EXCEPTION	142
 
diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py
index 043b7213a49..77d848937ee 100755
--- a/lib/ldb/tests/python/api.py
+++ b/lib/ldb/tests/python/api.py
@@ -59,6 +59,7 @@ class NoContextTests(TestCase):
 
     def test_string_to_time(self):
         self.assertEqual(0, ldb.string_to_time("19700101000000.0Z"))
+        self.assertEqual(-1, ldb.string_to_time("19691231235959.0Z"))
         self.assertEqual(1195499412, ldb.string_to_time("20071119191012.0Z"))
 
         self.assertEqual(-62167219200, ldb.string_to_time("00000101000000.0Z"))
diff --git a/python/samba/netcmd/user/readpasswords/getpassword.py b/python/samba/netcmd/user/readpasswords/getpassword.py
index f9624129a7e..278c4b241e7 100644
--- a/python/samba/netcmd/user/readpasswords/getpassword.py
+++ b/python/samba/netcmd/user/readpasswords/getpassword.py
@@ -207,4 +207,4 @@ samba-tool user getpassword --filter=samaccountname=TestUser3 --attributes=msDS-
 
         ldif = samdb.write_ldif(obj, ldb.CHANGETYPE_NONE)
         self.outf.write("%s" % ldif)
-        self.errf.write("Got password OK\n")
+        self.errf.write("Any available password returned OK\n")
diff --git a/python/samba/nt_time.py b/python/samba/nt_time.py
index 7a6417ecaaa..496dde576b4 100644
--- a/python/samba/nt_time.py
+++ b/python/samba/nt_time.py
@@ -19,6 +19,7 @@
 
 import datetime
 from typing import NewType
+import re
 
 
 NtTime = NewType("NtTime", int)
@@ -27,7 +28,7 @@ NtTimeDelta = NewType("NtTimeDelta", int)
 
 NT_EPOCH = datetime.datetime(1601, 1, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
 NT_TICKS_PER_μSEC = 10
-NT_TICKS_PER_SEC = NT_TICKS_PER_μSEC * 10**6
+NT_TICKS_PER_SEC = NT_TICKS_PER_μSEC * 1_000_000
 
 
 def _validate_nt_time(nt_time: NtTime) -> None:
@@ -44,6 +45,11 @@ def nt_time_from_datetime(tm: datetime.datetime) -> NtTime:
     return nt_time
 
 
+def nt_now() -> NtTime:
+    dt = datetime.datetime.now(datetime.timezone.utc)
+    return nt_time_from_datetime(dt)
+
+
 def datetime_from_nt_time(nt_time: NtTime) -> datetime.datetime:
     _validate_nt_time(nt_time)
     time_since_epoch = datetime.timedelta(microseconds=nt_time / NT_TICKS_PER_μSEC)
@@ -56,3 +62,59 @@ def nt_time_delta_from_datetime(dt: datetime.timedelta) -> NtTimeDelta:
 
 def timedelta_from_nt_time_delta(nt_time_delta: NtTimeDelta) -> datetime.timedelta:
     return datetime.timedelta(microseconds=nt_time_delta / NT_TICKS_PER_μSEC)
+
+
+def nt_time_from_string(s: str) -> NtTime:
+    """Convert a subset of ISO 8601 date/time strings, ldap timestamps,
+    and the string 'now' into NT time.
+
+    The ldap format is
+
+       YYYYmmddHHMMSS.0Z
+
+    which is 14 digits followed by the fixed string '.0Z'. This is
+    used in LDIF and internally by ldb.
+
+    The ISO format is
+
+    YYYY-mm-dd[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]
+
+    where the '*' can be any character, and the optional last
+    '[+HH:MM[:SS[.ffffff]]]' is a timezone offset (use '+00:00' for
+    UTC).
+    """
+    try:
+        if s == 'now':
+            dt = datetime.datetime.now(datetime.timezone.utc)
+        elif re.match(r'^\d{14}\.0Z$', s):
+            # "20230127223641.0Z"
+            dt = datetime.strptime(s, '%Y%m%d%H%M%S.0Z')
+        else:
+            dt = datetime.datetime.fromisoformat(s)
+    except ValueError:
+        raise ValueError("Expected a date in either "
+                         "ISO8601 'YYYY-MM-DD HH:MM:SS' format, "
+                         "LDAP timestamp 'YYYYmmddHHMMSS.0Z', "
+                         "or the literal string 'now'. "
+                         f" Got '{s}'.")
+
+    if dt.tzinfo is None:
+        # This is a cursed timestamp with no timezone info. We have to
+        # guess or nt_time_from_datetime() will fail. The best guess
+        # is the system timezone, which we can get this way:
+        dt = dt.astimezone()
+
+    return nt_time_from_datetime(dt)
+
+
+def string_from_nt_time(nttime: NtTime, format:str=None) -> str:
+    """Format an NtTime date as a string.
+
+    If format is not provided, an ISO 8601 string is used.
+    """
+    dt = datetime_from_nt_time(nttime)
+
+    if format is not None:
+        return dt.strftime(format)
+
+    return dt.isoformat()
diff --git a/python/samba/tests/audit_log_base.py b/python/samba/tests/audit_log_base.py
index fa5ecc7cace..e82b9bedf5a 100644
--- a/python/samba/tests/audit_log_base.py
+++ b/python/samba/tests/audit_log_base.py
@@ -21,10 +21,10 @@ import samba.tests
 from samba.messaging import Messaging
 from samba.dcerpc.messaging import MSG_AUTH_LOG, AUTH_EVENT_NAME
 from samba.param import LoadParm
+from samba import string_is_guid
 import time
 import json
 import os
-import re
 
 
 def getAudit(message):
@@ -190,14 +190,9 @@ class AuditLogTestBase(samba.tests.TestCase):
                 # No new messages. We’ve probably got them all.
                 break
 
-    GUID_RE = re.compile(
-        "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
-
-    #
-    # Is the supplied GUID string correctly formatted
-    #
     def is_guid(self, guid):
-        return self.GUID_RE.fullmatch(guid)
+        """Is the supplied GUID string correctly formatted"""
+        return string_is_guid(guid)
 
     def get_session(self):
         return self.auth_context["sessionId"]
diff --git a/python/samba/tests/auth_log_base.py b/python/samba/tests/auth_log_base.py
index 131f019de43..5c5c878c823 100644
--- a/python/samba/tests/auth_log_base.py
+++ b/python/samba/tests/auth_log_base.py
@@ -22,10 +22,10 @@ import samba.tests
 from samba.messaging import Messaging
 from samba.dcerpc.messaging import MSG_AUTH_LOG, AUTH_EVENT_NAME
 from samba.param import LoadParm
+from samba import string_is_guid
 import time
 import json
 import os
-import re
 
 
 def default_msg_filter(msg):
@@ -211,11 +211,6 @@ class AuthLogTestBase(samba.tests.TestCase):
 
         return list(filter(is_not_netlogon, messages))
 
-    GUID_RE = re.compile(
-        "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
-
-    #
-    # Is the supplied GUID string correctly formatted
-    #
     def is_guid(self, guid):
-        return self.GUID_RE.fullmatch(guid)
+        """Is the supplied GUID string correctly formatted"""
+        return string_is_guid(guid)
diff --git a/python/samba/tests/samba_tool/user.py b/python/samba/tests/samba_tool/user.py
index a19592a1f8c..ef74858eaec 100644
--- a/python/samba/tests/samba_tool/user.py
+++ b/python/samba/tests/samba_tool/user.py
@@ -346,7 +346,7 @@ class UserCmdTestCase(SambaToolCmdTest):
                                                 "--attributes=%s" % attributes,
                                                 "--decrypt-samba-gpg")
             self.assertCmdSuccess(result, out, err, "Ensure getpassword runs")
-            self.assertEqual(err, "Got password OK\n", "getpassword without url")
+            self.assertEqual(err, "Any available password returned OK\n", "getpassword without url")
             self.assertMatch(out, "sAMAccountName: %s" % (user["name"]),
                              "getpassword: 'sAMAccountName': %s out[%s]" % (user["name"], out))
             if expect_nt_hash or "virtualSambaGPG:: " in out:
diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA.py b/python/samba/tests/samba_tool/user_virtualCryptSHA.py
index e95a4be2aa9..a25fc8367c4 100644
--- a/python/samba/tests/samba_tool/user_virtualCryptSHA.py
+++ b/python/samba/tests/samba_tool/user_virtualCryptSHA.py
@@ -73,7 +73,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
                               out,
                               err,
                               "Ensure getpassword runs")
-        self.assertEqual(err, "Got password OK\n", "getpassword")
+        self.assertEqual(err, "Any available password returned OK\n", "getpassword")
         return out
 
     # Change the just the NT password hash, as would happen if the password
diff --git a/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py b/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
index 14e3de97a2f..b07b8144d86 100644
--- a/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
+++ b/python/samba/tests/samba_tool/user_virtualCryptSHA_base.py
@@ -79,7 +79,7 @@ class UserCmdCryptShaTestCase(SambaToolCmdTest):
                               out,
                               err,
                               "Ensure getpassword runs")
-        self.assertEqual(err, "Got password OK\n", "getpassword")
+        self.assertEqual(err, "Any available password returned OK\n", "getpassword")
         return out
 
     # Change the just the NT password hash, as would happen if the password
diff --git a/python/samba/tests/samba_tool/user_wdigest.py b/python/samba/tests/samba_tool/user_wdigest.py
index 0d8776203de..349cb490d54 100644
--- a/python/samba/tests/samba_tool/user_wdigest.py
+++ b/python/samba/tests/samba_tool/user_wdigest.py
@@ -89,7 +89,7 @@ class UserCmdWdigestTestCase(SambaToolCmdTest):
                               out,
                               err,
                               "Ensure getpassword runs")
-        self.assertEqual(err, "Got password OK\n", "getpassword")
+        self.assertEqual(err, "Any available password returned OK\n", "getpassword")
 
         if missing:
             self.assertTrue(attribute not in out)
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index aac311a84ff..9dfccf2cbc1 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1168,6 +1168,18 @@ static PyObject *py_dsdb_allocate_rid(PyObject *self, PyObject *args)
 }
 
 #ifdef AD_DC_BUILD_IS_ENABLED
+/*
+ * These functions will not work correctly on non-AD_DC builds.
+ *
+ * The only real principal in deciding whether to put something within
+ * these guards is whether it will compile and work when
+ * bld.AD_DC_BUILD_IS_ENABLED() says no.
+ *
+ * Most of DSDB is built and samba-tool will work fine with remote
+ * servers (using -H ldap://), but some DNS and periodic service
+ * functions are not built.
+ */
+
 static PyObject *py_dns_delete_tombstones(PyObject *self, PyObject *args)
 {
 	PyObject *py_ldb;
@@ -1333,7 +1345,18 @@ static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *ar
 	return Py_BuildValue("(II)", num_objects_removed,
 			    num_links_removed);
 }
-#endif
+
+#else
+
+static PyObject *py_dsdb_not_implemented(PyObject *self, PyObject *args)
+{
+	PyErr_SetString(PyExc_NotImplementedError,
+			"Library built without AD DC support");
+	return NULL;
+}
+
+#endif /* AD_DC_BUILD_IS_ENABLED */
+
 
 static PyObject *py_dsdb_load_udv_v2(PyObject *self, PyObject *args)
 {
@@ -1481,7 +1504,7 @@ static PyMethodDef py_dsdb_methods[] = {
 	{ "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
 		METH_VARARGS, "Get the server site name as a string"},
 	{ "_dsdb_convert_schema_to_openldap",
-		(PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS, 
+		(PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS,
 		"dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
 		"Create an OpenLDAP schema from a schema." },
 	{ "_samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
@@ -1550,6 +1573,13 @@ static PyMethodDef py_dsdb_methods[] = {
 		METH_VARARGS, NULL},
 	{ "_dns_delete_tombstones", (PyCFunction)py_dns_delete_tombstones,
 		METH_VARARGS, NULL},
+#else
+	{ "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_not_implemented,
+		METH_VARARGS, NULL},
+	{ "_scavenge_dns_records", (PyCFunction)py_dsdb_not_implemented,
+		METH_VARARGS, NULL},
+	{ "_dns_delete_tombstones", (PyCFunction)py_dsdb_not_implemented,
+		METH_VARARGS, NULL},
 #endif
 	{ "_dsdb_create_own_rid_set", (PyCFunction)py_dsdb_create_own_rid_set, METH_VARARGS,
 		"_dsdb_create_own_rid_set(samdb)"


-- 
Samba Shared Repository



More information about the samba-cvs mailing list