[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Feb 29 02:39:01 UTC 2024


The branch, master has been updated
       via  0fe263a56d0 pylibs: add string_is_guid() helper.
       via  7b089e1206a samba-tool: with --json, error messages are in JSON
       via  1f128fee27c samba-tool: instances remember whether --json was requested
       via  542ba5cbd5e samba-tool: add self.print_json_status() helper
       via  742fc4d841c samba-tool: avoid mutable Command class values
       via  29abab6a460 samba-tool domain level: avoid using assert
       via  8650ba0a187 samba-tool domain claim: use secrets module for token
       via  2908a6d67bc samba-tool user getpassword: Also return the time a GMSA password is valid until
       via  71f7c4a3c59 samba-tool: Allow ;format=UnixTime etc to operate on virtual attributes
       via  dfe71c4235a python/samba/tests: Include more detail on invoication in test of "samba-tool user show"
       via  380c80b4d60 samba-tool user getpassword: Do not show preview of gMSA password
       via  801e3fd6dd1 s3:libads: Trace ldap search base/filter/scope
      from  2b515b7dcc6 s4-kdc: Add "Fresh Public Key Identity" SID if PKINIT freshness used

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


- Log -----------------------------------------------------------------
commit 0fe263a56d049b62be71ced9d8a78bc0a749c195
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Feb 15 21:20:24 2024 +0000

    pylibs: add string_is_guid() helper.
    
    In various places we use regular expressions to check for GUID-ness,
    though typically we don't match GUIDs with uppercase hex digits when
    we really should.
    
    If we centralise the check, we have more chance of getting it right.
    
    Pair-programmed-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Feb 29 02:38:07 UTC 2024 on atb-devel-224

commit 7b089e1206a8a8256ad108f5f0e03d3b33f8bf9f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:14:24 2024 +1300

    samba-tool: with --json, error messages are in JSON
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1f128fee27c50aa305de3434443c4a52c408f9c6
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 28 16:13:15 2024 +1300

    samba-tool: instances remember whether --json was requested
    
    All our subcommands are going to learn --json eventually, and they
    shouldn't all have to do this individually.
    
    The next commit uses this to automatically format CommandErrors as JSON.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 542ba5cbd5e9a562cd81b5b2385b56d03555a87f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 16 00:59:25 2024 +0000

    samba-tool: add self.print_json_status() helper
    
    This is a helper to return JSON for simple messages.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 742fc4d841c1b02cc733760e7841ca13a95f3ebc
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 23 16:19:02 2024 +1300

    samba-tool: avoid mutable Command class values
    
    These values are shared across all instances of the class,
    which makes no difference in samba-tool itself, because there
    is one instance per process. But in tests we can have many
    Command classes at once (due to runcmd()), and if any of them
    happened to append to takes_args or takes_options rather than
    replacing it, well, the effect would be subtle.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 29abab6a460aa61699c4a1811c148552874c1236
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Feb 14 05:09:30 2024 +0000

    samba-tool domain level: avoid using assert
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8650ba0a187d4c0a05fd4596570b940431338a27
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 2 14:23:38 2024 +1300

    samba-tool domain claim: use secrets module for token
    
    `binascii.hexlify(os.urandom(8)).decode()` was fine, but `os.urandom`
    is OS specific and can theoretically block (says the documentation).
    
    We will let Python's secrets module worry about such details.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2908a6d67bca58c9de6991cbe312276408a34b7a
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Feb 9 11:44:33 2024 +1300

    samba-tool user getpassword: Also return the time a GMSA password is valid until
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 71f7c4a3c59d170f3cf48c5230d3edf4d51d500c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Feb 28 17:27:31 2024 +1300

    samba-tool: Allow ;format=UnixTime etc to operate on virtual attributes
    
    To convert a virtual attribute we must understand that it has
    been put into "obj" under the name including the ;format= part
    and so we must look it back up with that name when looking to
    covert it from (say) NTTIME to a unix time.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit dfe71c4235ad9943ba55d5d192b168554be749b3
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Feb 29 10:38:38 2024 +1300

    python/samba/tests: Include more detail on invoication in test of "samba-tool user show"
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 380c80b4d609e87af63045ab7695c81159d89311
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Feb 2 16:10:06 2024 +1300

    samba-tool user getpassword: Do not show preview of gMSA password
    
    The AD server will send a preview of the next gMSA password, 5mins before
    it is expected to be active.
    
    This is useful in a keytab, which needs to be in place before a ticket
    could possibly be issued, but is not helpful for authentication, as
    the server also accepts passwords for 5mins after the change.
    
    This avoids needing teach all users of this tool how to fall back to
    the previous password for a 5min period every 30 days, by default.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 801e3fd6dd102e33f789cbe1e604b728aafc96bb
Author: Pavel Filipenský <pfilipensky at samba.org>
Date:   Mon Feb 26 08:31:24 2024 +0100

    s3:libads: Trace ldap search base/filter/scope
    
    Signed-off-by: Pavel Filipenský <pfilipensky at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 python/samba/__init__.py                           | 32 ++++++++++
 python/samba/netcmd/__init__.py                    | 69 +++++++++++++++++++++-
 python/samba/netcmd/domain/claim/claim_type.py     |  6 +-
 python/samba/netcmd/domain/level.py                | 12 ++--
 python/samba/netcmd/user/readpasswords/common.py   | 38 ++++++++++--
 python/samba/tests/samba_tool/user.py              |  4 +-
 .../tests/samba_tool/user_getpassword_gmsa.py      | 24 +++++++-
 source3/libads/ldap.c                              |  5 ++
 8 files changed, 173 insertions(+), 17 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 3e6ea7d18e1..3b253f7d79c 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -26,6 +26,7 @@ import os
 import time
 import ldb
 import samba.param
+import re
 from samba import _glue
 from samba._ldb import Ldb as _Ldb
 
@@ -356,6 +357,37 @@ def arcfour_encrypt(key, data):
     return arcfour_crypt_blob(data, key)
 
 
+GUID_RE = re.compile(
+    "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
+
+GUID_MIXCASE_RE = re.compile(
+    "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
+    flags = re.IGNORECASE)
+
+
+def string_is_guid(string, lower_case_only=False):
+    """Is the string an ordinary undecorated string GUID?
+
+    That is, like 12345678-abcd-1234-FEED-1234567890ab, and not like
+    variants which have surrounding curly brackets or lack hyphens.
+
+    If lower case_only is true, only lowercase hex characters are
+    accepted. This is tighter than we ever require, but matches what
+    we usually emit.
+    """
+    # Note: it is rightly tempting to use misc.GUID() here and catch
+    # the error, but misc.GUID is more forgiving than we want,
+    # allowing all kinds of weird variants.
+    if lower_case_only:
+        m = GUID_RE.fullmatch(string)
+    else:
+        m = GUID_MIXCASE_RE.fullmatch(string)
+
+    if m is None:
+        return False
+    return True
+
+
 def enable_net_export_keytab():
     """This function modifies the samba.net.Net class to contain
     an export_keytab() method."""
diff --git a/python/samba/netcmd/__init__.py b/python/samba/netcmd/__init__.py
index 7ddc1dc0828..01497055d68 100644
--- a/python/samba/netcmd/__init__.py
+++ b/python/samba/netcmd/__init__.py
@@ -82,8 +82,8 @@ class Command(object):
     # synopsis must be defined in all subclasses in order to provide the
     # command usage
     synopsis = None
-    takes_args = []
-    takes_options = []
+    takes_args = ()
+    takes_options = ()
     takes_optiongroups = {}
 
     hidden = False
@@ -93,6 +93,7 @@ class Command(object):
     raw_argv = None
     raw_args = None
     raw_kwargs = None
+    preferred_output_format = None
 
     def _set_files(self, outf=None, errf=None):
         if outf is not None:
@@ -108,6 +109,19 @@ class Command(object):
         parser.print_usage()
 
     def _print_error(self, msg, evalue=None, klass=None):
+        if self.preferred_output_format == 'json':
+            if evalue is None:
+                evalue = 1
+            else:
+                msg = f"{msg} - {evalue}"
+            if klass is not None:
+                kwargs = {'error class': klass}
+            else:
+                kwargs = {}
+
+            self.print_json_status(evalue, msg, **kwargs)
+            return
+
         err = colour.c_DARK_RED("ERROR")
         klass = '' if klass is None else f'({klass})'
 
@@ -155,6 +169,50 @@ class Command(object):
         json.dump(data, self.outf, cls=JSONEncoder, indent=2, sort_keys=True)
         self.outf.write("\n")
 
+    def print_json_status(self, error=None, message=None, **kwargs):
+        """For commands that really have nothing to say when they succeed
+        (`samba-tool foo delete --json`), we can still emit
+        '{"status": "OK"}\n'. And if they fail they can say:
+        '{"status": "error"}\n'.
+        This function hopes to keep things consistent.
+
+        If error is true-ish but not True, it is stringified and added
+        as a message. For example, if error is an LdbError with an
+        OBJECT_NOT_FOUND code, self.print_json_status(error) results
+        in this:
+
+            '{"status": "error", "message": "object not found"}\n'
+
+        unless an explicit message is added, in which case that is
+        used. A message can be provided on success, like this:
+
+            '{"status": "OK", "message": "thanks for asking!"}\n'
+
+        Extra keywords can be added too.
+
+        In summary, you might go:
+
+            try:
+                samdb.delete(dn)
+            except Exception as e:
+                print_json_status(e)
+                return
+            print_json_status()
+        """
+        data = {}
+        if error:
+            data['status'] = 'error'
+            if error is not True:
+                data['message'] = str(error)
+        else:
+            data['status'] = 'OK'
+
+        if message is not None:
+            data['message'] = message
+
+        data.update(kwargs)
+        self.print_json(data)
+
     def show_command_error(self, e):
         """display a command error"""
         if isinstance(e, CommandError):
@@ -256,6 +314,13 @@ class Command(object):
                     del kwargs[option.dest]
         kwargs.update(optiongroups)
 
+        if kwargs.get('output_format') == 'json':
+            self.preferred_output_format = 'json'
+        else:
+            # we need to reset this for the tests that reuse the
+            # samba-tool object.
+            self.preferred_output_format = None
+
         if self.use_colour:
             self.apply_colour_choice(kwargs.pop('color', 'auto'))
 
diff --git a/python/samba/netcmd/domain/claim/claim_type.py b/python/samba/netcmd/domain/claim/claim_type.py
index 754f8b11117..72e98d33125 100644
--- a/python/samba/netcmd/domain/claim/claim_type.py
+++ b/python/samba/netcmd/domain/claim/claim_type.py
@@ -20,8 +20,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import binascii
-import os
+import secrets
 
 import samba.getopt as options
 from samba.netcmd import Command, CommandError, Option, SuperCommand
@@ -97,8 +96,7 @@ class cmd_domain_claim_claim_type_create(Command):
 
         # Generate the new Claim Type cn.
         # Windows creates a random number here containing 16 hex digits.
-        # We can achieve something similar using urandom(8)
-        instance = binascii.hexlify(os.urandom(8)).decode()
+        instance = secrets.token_hex(8)
         cn = f"ad://ext/{display_name}:{instance}"
 
         # adminDescription should be present but still have a fallback.
diff --git a/python/samba/netcmd/domain/level.py b/python/samba/netcmd/domain/level.py
index eefe360563d..f4d257ac324 100644
--- a/python/samba/netcmd/domain/level.py
+++ b/python/samba/netcmd/domain/level.py
@@ -81,22 +81,26 @@ class cmd_domain_level(Command):
         try:
             res_forest = samdb.search("CN=Partitions,%s" % samdb.get_config_basedn(),
                                       scope=ldb.SCOPE_BASE, attrs=["msDS-Behavior-Version"])
-            assert len(res_forest) == 1
+            if len(res_forest) != 1:
+                raise CommandError("Forest not found")
 
             res_domain = samdb.search(domain_dn, scope=ldb.SCOPE_BASE,
                                       attrs=["msDS-Behavior-Version", "nTMixedDomain"])
-            assert len(res_domain) == 1
+            if len(res_domain) != 1:
+                raise CommandError("domain not found")
 
             res_domain_cross = samdb.search("CN=Partitions,%s" % samdb.get_config_basedn(),
                                             scope=ldb.SCOPE_SUBTREE,
                                             expression="(&(objectClass=crossRef)(nCName=%s))" % domain_dn,
                                             attrs=["msDS-Behavior-Version"])
-            assert len(res_domain_cross) == 1
+            if len(res_domain_cross) != 1:
+                raise CommandError("no crossRef objects found")
 
             res_dc_s = samdb.search("CN=Sites,%s" % samdb.get_config_basedn(),
                                     scope=ldb.SCOPE_SUBTREE, expression="(objectClass=nTDSDSA)",
                                     attrs=["msDS-Behavior-Version"])
-            assert len(res_dc_s) >= 1
+            if len(res_dc_s) == 0:
+                raise CommandError("no nTDSDSA objects found")
 
             # default values, since "msDS-Behavior-Version" does not exist on Windows 2000 AD
             level_forest = DS_DOMAIN_FUNCTION_2000
diff --git a/python/samba/netcmd/user/readpasswords/common.py b/python/samba/netcmd/user/readpasswords/common.py
index 6d44881823d..8af8be7341e 100644
--- a/python/samba/netcmd/user/readpasswords/common.py
+++ b/python/samba/netcmd/user/readpasswords/common.py
@@ -22,6 +22,7 @@
 import base64
 import builtins
 import binascii
+import datetime
 import errno
 import io
 import os
@@ -34,7 +35,8 @@ from samba.dcerpc import drsblobs, security, gmsa
 from samba.ndr import ndr_unpack
 from samba.netcmd import Command, CommandError
 from samba.samdb import SamDB
-
+from samba.nt_time import timedelta_from_nt_time_delta, nt_time_from_datetime
+from samba.gkdi import MAX_CLOCK_SKEW
 
 # python[3]-gpgme is abandoned since ubuntu 1804 and debian 9
 # have to use python[3]-gpg instead
@@ -102,6 +104,8 @@ virtual_attributes = {
     "unicodePwd": {
         "flags": ldb.ATTR_FLAG_FORCE_BASE64_LDIF,
     },
+    "virtualManagedPasswordQueryTime": {
+    },
 }
 
 
@@ -369,10 +373,28 @@ class GetPasswordCommand(Command):
             managed_password = obj["msDS-ManagedPassword"][0]
             unpacked_managed_password = ndr_unpack(gmsa.MANAGEDPASSWORD_BLOB,
                                                    managed_password)
-            calculated["Primary:CLEARTEXT"] = \
-                unpacked_managed_password.passwords.current
             calculated["OLDCLEARTEXT"] = \
                 unpacked_managed_password.passwords.previous
+            query_interval = unpacked_managed_password.passwords.query_interval
+            calculated["GMSA:query_interval"] = \
+                query_interval
+
+            query_time_datetime = \
+                timedelta_from_nt_time_delta(query_interval) + datetime.datetime.now(tz=datetime.timezone.utc)
+
+            query_time_nttime = nt_time_from_datetime(query_time_datetime)
+
+            calculated["GMSA:query_time"] = query_time_nttime
+
+            # This password is useful for a keytab, but not for
+            # authentication, so don't show or provide it as the new password
+            # just yet
+            if calculated["GMSA:query_interval"] <= MAX_CLOCK_SKEW:
+                calculated["Primary:CLEARTEXT"] = \
+                    unpacked_managed_password.passwords.previous
+            else:
+                calculated["Primary:CLEARTEXT"] = \
+                    unpacked_managed_password.passwords.current
 
         account_name = str(obj["sAMAccountName"][0])
         if "userPrincipalName" in obj:
@@ -770,6 +792,10 @@ class GetPasswordCommand(Command):
                 v = get_wDigest(i, primary_wdigest, account_name, account_upn, domain, dns_domain)
                 if v is None:
                     continue
+            elif a == "virtualManagedPasswordQueryTime":
+                if "GMSA:query_time" not in calculated:
+                    continue
+                v = str(calculated["GMSA:query_time"])
             else:
                 continue
             obj[a] = ldb.MessageElement(v, ldb.FLAG_MOD_REPLACE, vattr["raw_attr"])
@@ -840,10 +866,14 @@ class GetPasswordCommand(Command):
                     continue
                 if ra["vformat"] != fm:
                     continue
+
                 srcattr = get_src_attrname(ra["attr"])
+                if srcattr is not None:
+                    an = "%s;format=%s" % (srcattr, fm)
+                else:
+                    srcattr = an = get_src_attrname(ra["raw_attr"])
                 if srcattr is None:
                     continue
-                an = "%s;format=%s" % (srcattr, fm)
                 if an in generated_formats:
                     continue
                 generated_formats[an] = fm
diff --git a/python/samba/tests/samba_tool/user.py b/python/samba/tests/samba_tool/user.py
index 26c9748ffc3..a19592a1f8c 100644
--- a/python/samba/tests/samba_tool/user.py
+++ b/python/samba/tests/samba_tool/user.py
@@ -600,7 +600,9 @@ sAMAccountName: %s
                 "-H", "ldap://%s" % os.environ["DC_SERVER"],
                 "-U%s%%%s" % (os.environ["DC_USERNAME"],
                               os.environ["DC_PASSWORD"]))
-            self.assertCmdSuccess(result, out, err, "Error running show")
+            self.assertCmdSuccess(result, out, err,
+                                  "Error running show --attributes=%s"
+                                  % ",".join(attrs))
 
             self.assertIn(";format=GeneralizedTime", out)
             self.assertIn(";format=UnixTime", out)
diff --git a/python/samba/tests/samba_tool/user_getpassword_gmsa.py b/python/samba/tests/samba_tool/user_getpassword_gmsa.py
index acd8907e992..bbb68c41b7e 100644
--- a/python/samba/tests/samba_tool/user_getpassword_gmsa.py
+++ b/python/samba/tests/samba_tool/user_getpassword_gmsa.py
@@ -26,6 +26,8 @@ import os
 sys.path.insert(0, "bin/python")
 os.environ["PYTHONUNBUFFERED"] = "1"
 
+import datetime, shlex
+
 from ldb import SCOPE_BASE
 
 from samba.credentials import MUST_USE_KERBEROS
@@ -33,7 +35,8 @@ from samba.dcerpc import security, samr
 from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT
 from samba.netcmd.domain.models import User
 from samba.ndr import ndr_pack, ndr_unpack
-from samba.tests import connect_samdb, delete_force
+from samba.nt_time import nt_time_from_datetime
+from samba.tests import connect_samdb, connect_samdb_env, delete_force
 
 from samba.tests import BlackboxTestCase
 
@@ -88,7 +91,8 @@ class GMSAPasswordTest(BlackboxTestCase):
         cls.user = User.get(cls.samdb, username=cls.username)
 
     def getpassword(self, attrs):
-        cmd = f"user getpassword --attributes={attrs} {self.username}"
+        shattrs = shlex.quote(attrs)
+        cmd = f"user getpassword --attributes={shattrs} {self.username}"
 
         ldif = self.check_output(cmd).decode()
         res = self.samdb.parse_ldif(ldif)
@@ -152,6 +156,22 @@ class GMSAPasswordTest(BlackboxTestCase):
 
         self.assertEqual(self.user.object_sid, connecting_user_sid)
 
+    def test_querytime(self):
+        user_msg = self.getpassword("virtualManagedPasswordQueryTime")
+        querytime = int(user_msg["virtualManagedPasswordQueryTime"][0])
+
+        # Just assert the number makes sense
+        self.assertGreater(querytime, nt_time_from_datetime(datetime.datetime.now(tz=datetime.timezone.utc)))
+        self.assertLess(querytime, nt_time_from_datetime(datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(hours = 21)))
+
+    def test_querytime_unixtime(self):
+        user_msg = self.getpassword("virtualManagedPasswordQueryTime;format=UnixTime")
+        querytime = int(user_msg["virtualManagedPasswordQueryTime;format=UnixTime"][0])
+
+        # Just assert the number makes sense
+        self.assertGreater(querytime, datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
+        self.assertLess(querytime, (datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(hours = 21)).timestamp())
+
     @classmethod
     def _make_cmdline(cls, line):
         """Override to pass line as samba-tool subcommand instead.
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 7f3c20746c8..ff67ad28a2a 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -154,6 +154,11 @@ static int ldap_search_with_timeout(LDAP *ld,
 	struct timeval *timeout_ptr = NULL;
 	int result;
 
+	DBG_DEBUG("ldap_search: base => [%s], filter => [%s], scope => [%d]\n",
+		 base,
+		 filter,
+		 scope);
+
 	/* Setup timeout for the ldap_search_ext_s call - local and remote. */
 	gotalarm = 0;
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list