Skip to content

Commit cc95a2a

Browse files
committed
SlapdObject bind ldaps:// as well
Use a set() in _start_slapd() in case caller has somehow picked a duplicated the port.
1 parent 57493b1 commit cc95a2a

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

Lib/slapdtest/_slapdtest.py

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ class SlapdObject:
179179
.. versionchanged:: 3.1
180180
181181
Added context manager functionality
182+
183+
.. versionchanged:: UNRELEASED
184+
185+
Added ldaps_uri attribute
182186
"""
183187
slapd_conf_template = SLAPD_CONF_TEMPLATE
184188
database = 'mdb'
@@ -212,12 +216,13 @@ class SlapdObject:
212216

213217
def __init__(self):
214218
self._proc = None
215-
self._port = self._avail_tcp_port()
219+
self._port, self._tls_port = self._avail_tcp_ports(2)
216220
self.server_id = self._port % 4096
217221
self.testrundir = os.path.join(self.TMPDIR, 'python-ldap-test-%d' % self._port)
218222
self._slapd_conf = os.path.join(self.testrundir, 'slapd.d')
219223
self._db_directory = os.path.join(self.testrundir, "openldap-data")
220224
self.ldap_uri = "ldap://%s:%d/" % (self.local_host, self._port)
225+
self.ldaps_uri = "ldaps://%s:%d/" % (self.local_host, self._tls_port)
221226
if HAVE_LDAPI:
222227
ldapi_path = os.path.join(self.testrundir, 'ldapi')
223228
self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path)
@@ -314,18 +319,26 @@ def _cleanup_rundir(self):
314319
os.rmdir(self.testrundir)
315320
self._log.info('cleaned-up %s', self.testrundir)
316321

322+
def _avail_tcp_ports(self, n):
323+
"""Return a list of currently unused TCP port numbers.
324+
"""
325+
ports = []
326+
socks = [socket.socket(socket.AF_INET, socket.SOCK_STREAM) for _i in range(n)]
327+
try:
328+
for sock in socks:
329+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
330+
sock.bind((self.local_host, 0))
331+
ports.append(sock.getsockname()[1])
332+
finally:
333+
[sock.close() for sock in socks]
334+
self._log.info('Found available port(s) %s', socks)
335+
return ports
336+
317337
def _avail_tcp_port(self):
318338
"""
319339
find an available port for TCP connection
320340
"""
321-
sock = socket.socket()
322-
try:
323-
sock.bind((self.local_host, 0))
324-
port = sock.getsockname()[1]
325-
finally:
326-
sock.close()
327-
self._log.info('Found available port %d', port)
328-
return port
341+
return self._avail_tcp_ports(1)
329342

330343
def gen_config(self):
331344
"""
@@ -399,7 +412,7 @@ def _start_slapd(self):
399412
"""
400413
Spawns/forks the slapd process
401414
"""
402-
urls = [self.ldap_uri]
415+
urls = [self.ldap_uri, self.ldaps_uri]
403416
if self.ldapi_uri:
404417
urls.append(self.ldapi_uri)
405418
slapd_args = [
@@ -425,13 +438,18 @@ def _start_slapd(self):
425438
self._log.debug(
426439
"slapd connection check to %s", self.default_ldap_uri
427440
)
428-
self.ldapwhoami()
441+
# try all bound sockets to make sure the daemon is ready to go.
442+
self.ldapwhoami(ldap_uri=self.ldap_uri)
443+
self.ldapwhoami(ldap_uri=self.ldaps_uri)
444+
if self.ldapi_uri:
445+
self.ldapwhoami(ldap_uri=self.ldapi_uri)
429446
except RuntimeError:
430447
if time.monotonic() >= deadline:
431448
break
432449
time.sleep(0.2)
433450
else:
434451
return
452+
self._proc.kill()
435453
raise RuntimeError("slapd did not start properly")
436454

437455
def start(self):
@@ -448,8 +466,8 @@ def start(self):
448466
self._test_config()
449467
self._start_slapd()
450468
self._log.debug(
451-
'slapd with pid=%d listening on %s and %s',
452-
self._proc.pid, self.ldap_uri, self.ldapi_uri
469+
'slapd with pid=%d listening on %s, %s and %s',
470+
self._proc.pid, self.ldap_uri, self.ldaps_uri, self.ldapi_uri
453471
)
454472

455473
def stop(self):
@@ -483,8 +501,8 @@ def _stopped(self):
483501
self._log.info('slapd[%d] terminated', self._proc.pid)
484502
self._proc = None
485503

486-
def _cli_auth_args(self):
487-
if self.cli_sasl_external:
504+
def _cli_remote_args(self, ldap_uri):
505+
if ldap_uri.startswith('ldapi://'):
488506
authc_args = [
489507
'-Y', 'EXTERNAL',
490508
]
@@ -496,16 +514,36 @@ def _cli_auth_args(self):
496514
'-D', self.root_dn,
497515
'-w', self.root_pw,
498516
]
499-
return authc_args
517+
return ['-H', ldap_uri] + authc_args
500518

501519
# no cover to avoid spurious coverage changes
502520
def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
503521
stdin_data=None): # pragma: no cover
504522
if ldap_uri is None:
505523
ldap_uri = self.default_ldap_uri
506524

525+
environ = os.environ.copy()
526+
507527
if ldapcommand.split("/")[-1].startswith("ldap"):
508-
args = [ldapcommand, '-H', ldap_uri] + self._cli_auth_args()
528+
args = [ldapcommand] + self._cli_remote_args(ldap_uri)
529+
530+
# setting $LDAPNOINIT ignores all other environment and config files
531+
environ.pop('LDAPNOINIT', None)
532+
# we really only want to set the CA cert...
533+
environ['LDAPTLS_CACERT'] = self.cafile
534+
environ['LDAPTLS_REQCERT'] = 'demand'
535+
environ['LDAPTLS_REQSAN'] = 'demand'
536+
environ['LDAPTLS_CRLCHECK'] = 'none'
537+
environ['LDAPTLS_CRLFILE'] = ''
538+
# ... but need to provide more to override any system/user defaults.
539+
environ['LDAPVERSION'] = '3'
540+
environ['LDAPTIMEOUT'] = '5'
541+
environ['LDAPTIMELIMIT'] = '15'
542+
environ['LDAPSIZELIMIT'] = '12'
543+
environ['LDAPNETWORK_TIMEOUT'] = '5'
544+
environ['LDAPTLS_CERT'] = ''
545+
environ['LDAPTLS_KEY'] = ''
546+
509547
else:
510548
args = [ldapcommand, '-F', self._slapd_conf]
511549

@@ -514,7 +552,8 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
514552
self._log.debug('Run command: %r', ' '.join(args))
515553
proc = subprocess.Popen(
516554
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
517-
stderr=subprocess.PIPE
555+
stderr=subprocess.PIPE,
556+
env=environ,
518557
)
519558
self._log.debug('stdin_data=%r', stdin_data)
520559
stdout_data, stderr_data = proc.communicate(stdin_data)
@@ -530,11 +569,11 @@ def _cli_popen(self, ldapcommand, extra_args=None, ldap_uri=None,
530569
)
531570
return stdout_data, stderr_data
532571

533-
def ldapwhoami(self, extra_args=None):
572+
def ldapwhoami(self, extra_args=None, **kws):
534573
"""
535574
Runs ldapwhoami on this slapd instance
536575
"""
537-
self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args)
576+
self._cli_popen(self.PATH_LDAPWHOAMI, extra_args=extra_args, **kws)
538577

539578
def ldapadd(self, ldif, extra_args=None):
540579
"""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy