This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master
in repository lib389.
commit 92658d9a466b4ab2dea4106d39b4339d79696db5
Author: William Brown <firstyear(a)redhat.com>
Date: Tue Feb 21 10:29:00 2017 +1000
Ticket 49137 - Add sasl plain tests, lib389 support
Bug Description: We need to test that SASL plain works in DS.
Fix Description: To do this, we need to fix sasl in lib389, we
correct openConnection to use more than just gssapi, we fix
start tls to work over multiple connections.
https://pagure.io/389-ds-base/issue/49137
Author: wibrown
Review by: mreynolds (THanks!)
---
lib389/__init__.py | 77 ++++++++++++++----------------------------------
lib389/_mapped_object.py | 4 +--
lib389/nss_ssl.py | 8 +++--
lib389/rootdse.py | 3 ++
lib389/sasl.py | 4 +--
lib389/tools.py | 10 +++----
6 files changed, 40 insertions(+), 66 deletions(-)
diff --git a/lib389/__init__.py b/lib389/__init__.py
index e189c83..14ea6ee 100644
--- a/lib389/__init__.py
+++ b/lib389/__init__.py
@@ -98,6 +98,8 @@ if MAJOR >= 3 or (MAJOR == 2 and MINOR >= 7):
RE_DBMONATTR = re.compile(r'^([a-zA-Z]+)-([1-9][0-9]*)$')
RE_DBMONATTRSUN = re.compile(r'^([a-zA-Z]+)-([a-zA-Z]+)$')
+TRACE_LEVEL = 0
+
# My logger
log = logging.getLogger(__name__)
@@ -273,56 +275,15 @@ class DirSrv(SimpleLDAPObject, object):
self.instdir = self.ds_paths.inst_dir
self.dbdir = self.ds_paths.db_dir
- def __localinit__(self):
- '''
- Establish a connection to the started instance. It binds with the
- binddn property, then it initializes various fields from DirSrv
- (via __initPart2)
-
- @param - self
-
- @return - None
-
- @raise ldap.LDAPError - if failure during initialization
- '''
- uri = self.toLDAPURL()
-
- SimpleLDAPObject.__init__(self, uri)
-
- # see if binddn is a dn or a uid that we need to lookup
- if self.binddn and not is_a_dn(self.binddn):
- self.simple_bind_s("", "") # anon
- ent = self.getEntry(CFGSUFFIX, ldap.SCOPE_SUBTREE,
- "(uid=%s)" % self.binddn,
- ['uid'])
- if ent:
- self.binddn = ent.dn
- else:
- raise ValueError("Error: could not find %s under %s" % (
- self.binddn, CFGSUFFIX))
-
- needtls = False
- while True:
- try:
- if needtls:
- self.start_tls_s()
- try:
- self.simple_bind_s(ensure_str(self.binddn), self.bindpw)
- except ldap.SERVER_DOWN as e:
- # TODO add server info in exception
- log.debug("Cannot connect to %r" % uri)
- raise e
- break
- except ldap.CONFIDENTIALITY_REQUIRED:
- needtls = True
- self.__initPart2()
-
def rebind(self):
"""Reconnect to the DS
@raise ldap.CONFIDENTIALITY_REQUIRED - missing TLS:
"""
- SimpleLDAPObject.__init__(self, self.toLDAPURL())
+ if hasattr(ldap, 'PYLDAP_VERSION') and MAJOR >= 3:
+ super(DirSrv, self).__init__(uri, bytes_mode=False, trace_level=TRACE_LEVEL)
+ else:
+ super(DirSrv, self).__init__(uri, trace_level=TRACE_LEVEL)
# self.start_tls_s()
self.simple_bind_s(ensure_str(self.binddn), self.bindpw)
@@ -1037,7 +998,7 @@ class DirSrv(SimpleLDAPObject, object):
self.state = DIRSRV_STATE_ALLOCATED
- def open(self, saslmethod=None, certdir=None, starttls=False, connOnly=False,
reqcert=ldap.OPT_X_TLS_HARD):
+ def open(self, saslmethod=None, sasltoken=None, certdir=None, starttls=False,
connOnly=False, reqcert=ldap.OPT_X_TLS_HARD):
'''
It opens a ldap bound connection to dirsrv so that online
administrative tasks are possible. It binds with the binddn
@@ -1048,6 +1009,7 @@ class DirSrv(SimpleLDAPObject, object):
@param self
@param saslmethod - None, or GSSAPI
+ @param sasltoken - The ldap.sasl token type to bind with.
@param certdir - Certificate directory for TLS
@return None
@@ -1058,22 +1020,24 @@ class DirSrv(SimpleLDAPObject, object):
if self.verbose:
self.log.info('open(): Connecting to uri %s' % uri)
if hasattr(ldap, 'PYLDAP_VERSION') and MAJOR >= 3:
- super(DirSrv, self).__init__(uri, bytes_mode=False)
+ super(DirSrv, self).__init__(uri, bytes_mode=False, trace_level=TRACE_LEVEL)
else:
- super(DirSrv, self).__init__(uri)
+ super(DirSrv, self).__init__(uri, trace_level=TRACE_LEVEL)
- if certdir:
+ if certdir is not None:
"""
We have a certificate directory, so lets start up TLS negotiations
"""
- ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, certdir)
- log.debug("Using ca certificate %s" % certdir)
+ self.set_option(ldap.OPT_X_TLS_CACERTDIR, certdir)
+ log.debug("Using external ca certificate %s" % certdir)
+ else:
+ self.set_option(ldap.OPT_X_TLS_CACERTDIR, self.get_cert_dir())
+ log.debug("Using dirsrv ca certificate %s" % certdir)
if certdir or starttls:
try:
- # MUST be set on ldap. not the object, because pyldap is broken
- # and only works if you set this globally.
- ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, reqcert)
+ self.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, reqcert)
+ log.debug("Using certificate policy %s" % reqcert)
log.debug("ldap.OPT_X_TLS_REQUIRE_CERT = %s" % reqcert)
self.start_tls_s()
except ldap.LDAPError as e:
@@ -1095,6 +1059,9 @@ class DirSrv(SimpleLDAPObject, object):
log.debug("SASL/GSSAPI Bind Failed: %s" % str(e))
raise e
+ elif saslmethod and sasltoken is not None:
+ # Just pass the sasltoken in!
+ self.sasl_interactive_bind_s("", sasltoken)
elif saslmethod:
# Unknown or unsupported method
log.debug('Unsupported SASL method: %s' % saslmethod)
@@ -1146,7 +1113,7 @@ class DirSrv(SimpleLDAPObject, object):
# check that DirSrv was in DIRSRV_STATE_ONLINE state
if self.state == DIRSRV_STATE_ONLINE:
# Don't raise an error. Just move the state and return
- SimpleLDAPObject.unbind(self)
+ self.unbind_s()
self.state = DIRSRV_STATE_OFFLINE
diff --git a/lib389/_mapped_object.py b/lib389/_mapped_object.py
index 7d3afa1..93aad50 100644
--- a/lib389/_mapped_object.py
+++ b/lib389/_mapped_object.py
@@ -267,8 +267,8 @@ class DSLdapObject(DSLogging):
# If the account can be bound to, this will attempt to do so. We don't check
# for exceptions, just pass them back!
- def bind(self, password=None):
- conn = self._instance.openConnection()
+ def bind(self, password=None, *args, **kwargs):
+ conn = self._instance.openConnection(*args, **kwargs)
conn.simple_bind_s(self.dn, password)
return conn
diff --git a/lib389/nss_ssl.py b/lib389/nss_ssl.py
index bf9876b..36bc26a 100644
--- a/lib389/nss_ssl.py
+++ b/lib389/nss_ssl.py
@@ -23,8 +23,8 @@ CA_NAME = 'Self-Signed-CA'
CERT_NAME = 'Server-Cert'
PIN_TXT = 'pin.txt'
PWD_TXT = 'pwdfile.txt'
-ISSUER = 'CN=ca.unknown.example.com,O=testing,L=unknown,ST=Queensland,C=AU'
-SELF_ISSUER = 'CN={HOSTNAME},O=testing,L=unknown,ST=Queensland,C=AU'
+ISSUER = 'CN=ca.lib389.example.com,O=testing,L=lib389,ST=Queensland,C=AU'
+SELF_ISSUER = 'CN={HOSTNAME},O=testing,L=lib389,ST=Queensland,C=AU'
VALID = 2
@@ -125,6 +125,7 @@ class NssSsl(object):
result = check_output(cmd)
self.dirsrv.log.debug("nss output: %s" % result)
# Now extract the CAcert to a well know place.
+ # This allows us to point the cacert dir here and it "just works"
cmd = [
'/usr/bin/certutil',
'-L',
@@ -233,6 +234,9 @@ class NssSsl(object):
CERT_NAME,
'-s',
SELF_ISSUER.format(HOSTNAME=self.dirsrv.host),
+ # We MUST issue with SANs else ldap wont verify the name.
+ '-8',
+ self.dirsrv.host,
'-c',
CA_NAME,
'-g',
diff --git a/lib389/rootdse.py b/lib389/rootdse.py
index df98cbf..8d3a6d1 100644
--- a/lib389/rootdse.py
+++ b/lib389/rootdse.py
@@ -27,6 +27,9 @@ class RootDSE(DSLdapObject):
def supports_sasl_ldapssotoken(self):
return self.present("supportedSASLMechanisms",
"LDAPSSOTOKEN")
+ def supports_sasl_plain(self):
+ return self.present("supportedSASLMechanisms", "PLAIN")
+
def supports_exop_whoami(self):
return self.present("supportedExtension",
"1.3.6.1.4.1.4203.1.11.3")
diff --git a/lib389/sasl.py b/lib389/sasl.py
index ee19c40..e64e3c3 100644
--- a/lib389/sasl.py
+++ b/lib389/sasl.py
@@ -12,7 +12,7 @@ Lib389 python ldap sasl operations.
These should be upstreamed if possible.
"""
-from ldap.sasl import sasl, CB_PASS
+from ldap.sasl import sasl, CB_AUTHNAME, CB_PASS
class LdapSSOTokenSASL(sasl):
"""
@@ -29,6 +29,6 @@ class PlainSASL(sasl):
"""
def __init__(self, authz_id, passwd):
- auth_dict = { CB_USER:authz_id, CB_PASS:passwd }
+ auth_dict = { CB_AUTHNAME:authz_id, CB_PASS:passwd }
sasl.__init__(self, auth_dict, "PLAIN")
diff --git a/lib389/tools.py b/lib389/tools.py
index 10cc7aa..51de689 100644
--- a/lib389/tools.py
+++ b/lib389/tools.py
@@ -857,18 +857,18 @@ class DirSrvTools(object):
for line in hostfp.readlines():
if ipPattern is None:
words = line.split()
- assert(words[1] == expectedHost)
- return True
+ if words[1] == expectedHost:
+ return True
else:
if line.find(ipPattern) >= 0:
words = line.split()
# We just want to make sure it's in there somewhere
- assert(expectedHost in words)
- return True
+ if expectedHost in words:
+ return True
except AssertionError:
raise AssertionError(
"Error: %s should contain '%s' host for %s" %
- ('/etc/hosts/', expectedHost, ipPattern))
+ ('/etc/hosts', expectedHost, ipPattern))
raise AssertionError(
"Error: /etc/hosts does not contain '%s' as a host for
%s"
% (expectedHost, ipPattern))
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.