Monday, May 29, 2017

[389-commits] [lib389] 01/01: Ticket 32 - Add TLS external bind support for testing

This is an automated email from the git hooks/post-receive script.

firstyear pushed a commit to branch master
in repository lib389.

commit 3a7802da1c9ef6810b18ecffa298d1e0c5ef083b
Author: William Brown <firstyear@redhat.com>
Date: Fri May 26 15:39:58 2017 +1000

Ticket 32 - Add TLS external bind support for testing

Bug Description: Previously it was difficult to test TLS external
binds. We should add this to lib389 before any refactor of the
certmap code.

Fix Description: This covers a number of locations. Importantly:

* The ability to configure certmaps programatically via config.
* The ability to generate and extract user certificates signed
by the internal CA from lib389
* The ability to perform an external TLS bind.

https://pagure.io/lib389/issue/32

Author: wibrown

Review by: spichugi (Thanks!)
---
lib389/__init__.py | 63 +++++++++++++++-----
lib389/config.py | 98 ++++++++++++++++++++++++++++++-
lib389/idm/user.py | 1 +
lib389/nss_ssl.py | 119 ++++++++++++++++++++++++++++++++++++--
lib389/rootdse.py | 3 +
lib389/tests/nss_ssl_test.py | 69 ++++++++++------------
lib389/tests/tls_external_test.py | 83 ++++++++++++++++++++++++++
python-lib389.spec | 4 ++
8 files changed, 383 insertions(+), 57 deletions(-)

diff --git a/lib389/__init__.py b/lib389/__init__.py
index 44ff322..1967f57 100644
--- a/lib389/__init__.py
+++ b/lib389/__init__.py
@@ -98,6 +98,7 @@ 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]+)$')

+# This controls pyldap debug levels
TRACE_LEVEL = 0

# My logger
@@ -530,6 +531,8 @@ class DirSrv(SimpleLDAPObject, object):
server = DirSrv(verbose=self.verbose)
args_instance[SER_HOST] = self.host
args_instance[SER_PORT] = self.port
+ if self.sslport is not None:
+ args_instance[SER_SECURE_PORT] = self.sslport
args_instance[SER_SERVERID_PROP] = self.serverid
args_standalone = args_instance.copy()
server.allocate(args_standalone)
@@ -994,7 +997,8 @@ class DirSrv(SimpleLDAPObject, object):

self.state = DIRSRV_STATE_ALLOCATED

- def open(self, saslmethod=None, sasltoken=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,
+ usercert=None, userkey=None):
'''
It opens a ldap bound connection to dirsrv so that online
administrative tasks are possible. It binds with the binddn
@@ -1012,35 +1016,64 @@ class DirSrv(SimpleLDAPObject, object):
@raise LDAPError
'''

+ ##################
+ # WARNING: While you have a python ldap connection open some settings like
+ # ldap.set_option MAY NOT WORK AS YOU EXPECT.
+ # There are cases (especially CACERT/USERCERTS) where when one connection
+ # is open set_option SILENTLY fails!!!!
+ #
+ # You MAY need to set post_open=False in your DirSrv start/restart instance!
+ ##################
+
uri = self.toLDAPURL()
- 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, trace_level=TRACE_LEVEL)
- else:
- super(DirSrv, self).__init__(uri, trace_level=TRACE_LEVEL)

- #if certdir is None and self.isLocal and self.nss_ssl._rsa_ca_exists():
- # certdir = self.get_cert_dir()
- # log.debug("Using dirsrv ca certificate %s" % certdir)
+ if certdir is None and self.isLocal:
+ certdir = self.get_cert_dir()
+ log.debug("Using dirsrv ca certificate %s" % certdir)
+
+ if userkey is not None:
+ # Note this sets LDAP.OPT not SELF. Because once self has opened
+ # it can NOT change opts AT ALL.
+ ldap.set_option(ldap.OPT_X_TLS_KEYFILE, userkey)
+ log.debug("Using user private key %s" % userkey)
+ if usercert is not None:
+ # Note this sets LDAP.OPT not SELF. Because once self has opened
+ # it can NOT change opts AT ALL.
+ ldap.set_option(ldap.OPT_X_TLS_CERTFILE, usercert)
+ log.debug("Using user certificate %s" % usercert)

if certdir is not None:
"""
We have a certificate directory, so lets start up TLS negotiations
"""
- self.set_option(ldap.OPT_X_TLS_CACERTDIR, certdir)
+ # Note this sets LDAP.OPT not SELF. Because once self has opened
+ # it can NOT change opts AT ALL.
+ ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, certdir)
log.debug("Using external ca certificate %s" % certdir)

if certdir or starttls:
try:
- self.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, reqcert)
+ # Note this sets LDAP.OPT not SELF. Because once self has opened
+ # it can NOT change opts on reused (ie restart)
+ ldap.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:
log.fatal('TLS negotiation failed: %s' % str(e))
raise e

+ ## NOW INIT THIS. This MUST be after all the ldap.OPT set above,
+ # so that we inherit the settings correctly!!!!
+ 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, trace_level=TRACE_LEVEL)
+ else:
+ super(DirSrv, self).__init__(uri, trace_level=TRACE_LEVEL)
+
+ if starttls and not uri.startswith('ldaps'):
+ self.start_tls_s()
+
if saslmethod and saslmethod.lower() == 'gssapi':
"""
Perform kerberos/gssapi authentication
@@ -1056,6 +1089,10 @@ class DirSrv(SimpleLDAPObject, object):
log.debug("SASL/GSSAPI Bind Failed: %s" % str(e))
raise e

+ elif saslmethod == 'EXTERNAL':
+ # Do nothing.
+ sasl_auth = ldap.sasl.external()
+ self.sasl_interactive_bind_s("", sasl_auth)
elif saslmethod and sasltoken is not None:
# Just pass the sasltoken in!
self.sasl_interactive_bind_s("", sasltoken)
diff --git a/lib389/config.py b/lib389/config.py
index 532ac73..01b731e 100644
--- a/lib389/config.py
+++ b/lib389/config.py
@@ -197,7 +197,7 @@ class Encryption(DSLdapObject):
self._must_attributes = ['cn']
self._protected = True

- def create(self, rdn=None, properties={'cn': 'encryption'}):
+ def create(self, rdn=None, properties={'cn': 'encryption', 'nsSSLClientAuth': 'allowed'}):
if rdn is not None:
self._log.debug("dn on cn=encryption is not None. This is a mistake.")
super(Encryption, self).create(properties=properties)
@@ -232,3 +232,99 @@ class RSA(DSLdapObject):
# Our self._dn is already set, no need for rdn.
super(RSA, self).create(properties=properties)

+class CertmapLegacy(object):
+ """
+ Manage certificate mappings in Directory Server
+
+ This is based on the old certmap fileformat. As a result, the interface is rather
+ crude, until we re-write to use dynamic mappings.
+ """
+ def __init__(self, conn):
+ self._instance = conn
+ pass
+
+ def reset(self):
+ """
+ Reset the certmap to empty.
+ """
+ certmap = os.path.join(self._instance.get_config_dir(), 'certmap.conf')
+ with open(certmap, 'w') as f:
+ f.write('# LDAP Certificate mappings \n')
+
+ def _parse_maps(self, maps):
+ certmaps = {}
+ cur_map = None
+ for l in maps:
+ if l.startswith('certmap'):
+ # Line matches format of: certmap name issuer
+ (_, name, issuer) = l.split(None, 2)
+ certmaps[name] = {
+ 'DNComps': None,
+ 'FilterComps': None,
+ 'VerifyCert': None,
+ 'CmapLdapAttr': None,
+ 'Library': None,
+ 'InitFn': None,
+ }
+ certmaps[name]['issuer'] = issuer
+ else:
+ # The line likely is:
+ # name:property [value]
+ (name, pav) = l.split(':')
+ pavs = pav.split(None, 1)
+ if len(pavs) == 1:
+ # We have an empty property
+ certmaps[name][pav] = ''
+ else:
+ # We clearly have a value.
+ if pavs[0] == 'DNComps' or pavs[0] == 'FilterComps':
+ # These two are comma sep lists
+ values = [w.split for w in pavs[1].split(',')]
+ certmaps[name][pavs[0]] = values
+ else:
+ certmaps[name][pavs[0]] = pavs[1]
+ return certmaps
+
+ def list(self):
+ """
+ Parse and list current certmaps.
+ """
+ certmap = os.path.join(self._instance.get_config_dir(), 'certmap.conf')
+ maps = []
+ with open(certmap, 'r') as f:
+ for line in f.readlines():
+ s_line = line.strip()
+ if not s_line.startswith('#'):
+ content = s_line.split('#')[0]
+ if content != '':
+ maps.append(content)
+ certmaps = self._parse_maps(maps)
+ return certmaps
+
+ def set(self, certmaps):
+ """
+ Take a dict of certmaps and write them out.
+ """
+ output = ""
+ for name in certmaps:
+ certmap = certmaps[name]
+ output += "certmap %s %s\n" % (name, certmap['issuer'])
+ for v in ['DNComps', 'FilterComps']:
+ if certmap[v] == None:
+ output += "# %s:%s\n" % (name, v)
+ elif certmap[v] == '':
+ output += "%s:%s\n" % (name, v)
+ else:
+ output += "%s:%s %s\n" % (name, v, ', '.join(certmap[v]))
+ for v in ['VerifyCert', 'CmapLdapAttr', 'Library', 'InitFn']:
+ if certmap[v] == None:
+ output += "# %s:%s\n" % (name, v)
+ else:
+ output += "%s:%s %s\n" % (name, v, certmap[v])
+ # Now write it out
+ certmap = os.path.join(self._instance.get_config_dir(), 'certmap.conf')
+ with open(certmap, 'w') as f:
+ f.write(output)
+
+
+
diff --git a/lib389/idm/user.py b/lib389/idm/user.py
index ad1f95f..66a72cf 100644
--- a/lib389/idm/user.py
+++ b/lib389/idm/user.py
@@ -32,6 +32,7 @@ class UserAccount(Account):
'top',
'account',
'posixaccount',
+ # inetOrgPerson allows userCertificate
'inetOrgPerson',
'organizationalPerson',
# This may not always work at sites?
diff --git a/lib389/nss_ssl.py b/lib389/nss_ssl.py
index 36bc26a..05ddbfc 100644
--- a/lib389/nss_ssl.py
+++ b/lib389/nss_ssl.py
@@ -14,6 +14,7 @@ import sys
import random
import string
import re
+import socket
# from nss import nss
from subprocess import check_call, check_output
from lib389.passwd import password_generate
@@ -21,6 +22,7 @@ from lib389.passwd import password_generate
KEYBITS = 4096
CA_NAME = 'Self-Signed-CA'
CERT_NAME = 'Server-Cert'
+USER_PREFIX = 'user-'
PIN_TXT = 'pin.txt'
PWD_TXT = 'pwdfile.txt'
ISSUER = 'CN=ca.lib389.example.com,O=testing,L=lib389,ST=Queensland,C=AU'
@@ -193,6 +195,16 @@ class NssSsl(object):
(ssl_flag, mime_flag, jar_flag) = trust_flags.split(',')
return 'C' in ssl_flag

+ def _rsa_cert_is_user(self, cert_tuple):
+ """
+ Check an RSA cert is user trust
+
+ Sadly we can't check for ext key usage, because NSS makes this really hard.
+ """
+ trust_flags = cert_tuple[1]
+ (ssl_flag, mime_flag, jar_flag) = trust_flags.split(',')
+ return 'u' in ssl_flag
+
def _rsa_ca_exists(self):
"""
Detect if a self-signed ca exists
@@ -206,7 +218,7 @@ class NssSsl(object):

def _rsa_key_and_cert_exists(self):
"""
- Check if a valid server key and cert pain exist.
+ Check if a valid server key and cert pair exist.
"""
have_cert = False
cert_list = self._rsa_cert_list()
@@ -216,6 +228,21 @@ class NssSsl(object):
have_cert = True
return have_cert

+ def _rsa_user_exists(self, name):
+ """
+ Check if a valid server key and cert pair exist for a user.
+
+ we use the format, user-<name>
+ """
+ have_user = False
+ cert_list = self._rsa_cert_list()
+ for cert in cert_list:
+ if (cert[0] == '%s%s' % (USER_PREFIX, name)):
+ if self._rsa_cert_key_exists(cert) and self._rsa_cert_is_user(cert):
+ have_user = True
+ return have_user
+
+
def create_rsa_key_and_cert(self, alt_names=[]):
"""
Create a key and a cert that is signed by the self signed ca
@@ -224,9 +251,13 @@ class NssSsl(object):
extra names to take.
"""

+ if len(alt_names) == 0:
+ alt_names.append(socket.gethostname())
+ if self.dirsrv.host not in alt_names:
+ alt_names.append(self.dirsrv.host)
+
# Create noise.
self._generate_noise('%s/noise.txt' % self.dirsrv.get_cert_dir())
- # Now run the command. Can we do this with NSS native?
cmd = [
'/usr/bin/certutil',
'-S',
@@ -235,8 +266,7 @@ class NssSsl(object):
'-s',
SELF_ISSUER.format(HOSTNAME=self.dirsrv.host),
# We MUST issue with SANs else ldap wont verify the name.
- '-8',
- self.dirsrv.host,
+ '-8', ','.join(alt_names),
'-c',
CA_NAME,
'-g',
@@ -256,3 +286,84 @@ class NssSsl(object):
result = check_output(cmd)
self.dirsrv.log.debug("nss output: %s" % result)
return True
+
+ def create_rsa_user(self, name):
+ """
+ Create a key and cert for a user to authenticate to the directory.
+
+ Name is the uid of the account, and will become the CN of the cert.
+ """
+ cmd = [
+ '/usr/bin/certutil',
+ '-S',
+ '-n',
+ '%s%s' % (USER_PREFIX, name),
+ '-s',
+ SELF_ISSUER.format(HOSTNAME=name),
+ '--keyUsage',
+ 'digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment',
+ '--nsCertType',
+ 'sslClient',
+ '--extKeyUsage',
+ 'clientAuth',
+ '-c',
+ CA_NAME,
+ '-g',
+ '%s' % KEYBITS,
+ '-t',
+ ',,',
+ '-v',
+ '%s' % VALID,
+ '-d',
+ self._certdb,
+ '-z',
+ '%s/noise.txt' % self.dirsrv.get_cert_dir(),
+ '-f',
+ '%s/%s' % (self.dirsrv.get_cert_dir(), PWD_TXT),
+ ]
+
+ result = check_output(cmd)
+ self.dirsrv.log.debug("nss output: %s" % result)
+ # Now extract this into PEM files that we can use.
+ # pk12util -o user-william.p12 -d . -k pwdfile.txt -n user-william -W ''
+ check_call([
+ 'pk12util',
+ '-d', self._certdb,
+ '-o', '%s/%s%s.p12' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name),
+ '-k', '%s/%s' % (self.dirsrv.get_cert_dir(), PWD_TXT),
+ '-n', '%s%s' % (USER_PREFIX, name),
+ '-W', '""'
+ ])
+ # openssl pkcs12 -in user-william.p12 -passin pass:'' -out file.pem -nocerts -nodes
+ # Extract the key
+ check_call([
+ 'openssl',
+ 'pkcs12',
+ '-in', '%s/%s%s.p12' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name),
+ '-passin', 'pass:""',
+ '-out', '%s/%s%s.key' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name),
+ '-nocerts',
+ '-nodes'
+ ])
+ # Extract the cert
+ check_call([
+ 'openssl',
+ 'pkcs12',
+ '-in', '%s/%s%s.p12' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name),
+ '-passin', 'pass:""',
+ '-out', '%s/%s%s.crt' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name),
+ '-nokeys',
+ '-clcerts',
+ '-nodes'
+ ])
+ return True
+
+ def get_rsa_user(self, name):
+ """
+ Return a dict of information for ca, key and cert paths for the user id
+ """
+ ca_path = '%s/ca.crt' % self.dirsrv.get_cert_dir()
+ key_path = '%s/%s%s.key' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name)
+ crt_path = '%s/%s%s.crt' % (self.dirsrv.get_cert_dir(), USER_PREFIX, name)
+ return {'ca': ca_path, 'key': key_path, 'crt': crt_path}
+
diff --git a/lib389/rootdse.py b/lib389/rootdse.py
index e6d34e9..efd299f 100644
--- a/lib389/rootdse.py
+++ b/lib389/rootdse.py
@@ -33,6 +33,9 @@ class RootDSE(DSLdapObject):
def supports_sasl_plain(self):
return self.present("supportedSASLMechanisms", "PLAIN")

+ def supports_sasl_external(self):
+ return self.present("supportedSASLMechanisms", "EXTERNAL")
+
def supports_exop_whoami(self):
return self.present("supportedExtension", "1.3.6.1.4.1.4203.1.11.3")

diff --git a/lib389/tests/nss_ssl_test.py b/lib389/tests/nss_ssl_test.py
index a3e47f4..e1867b6 100644
--- a/lib389/tests/nss_ssl_test.py
+++ b/lib389/tests/nss_ssl_test.py
@@ -10,72 +10,63 @@ from lib389._constants import *
from lib389 import DirSrv, Entry
import pytest
import os
+import logging

-INSTANCE_PORT = 54321
-INSTANCE_SERVERID = 'standalone'
-# INSTANCE_PREFIX = None
+from lib389.topologies import topology_st as topo

+DEBUGGING = os.getenv('DEBUGGING', False)

-class TopologyStandalone(object):
- def __init__(self, standalone):
- standalone.open()
- self.standalone = standalone
+if DEBUGGING:
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+ logging.getLogger(__name__).setLevel(logging.INFO)

+log = logging.getLogger(__name__)

-@pytest.fixture(scope="module")
-def topology(request):
- standalone = DirSrv(verbose=False)
- standalone.log.debug("Instance allocated")
- args = {SER_HOST: LOCALHOST,
- SER_PORT: INSTANCE_PORT,
- # SER_DEPLOYED_DIR: INSTANCE_PREFIX,
- SER_SERVERID_PROP: INSTANCE_SERVERID}
- standalone.allocate(args)
- if standalone.exists():
- standalone.delete()
- standalone.create()
- standalone.open()
-
- def fin():
- standalone.delete()
- request.addfinalizer(fin)
-
- return TopologyStandalone(standalone)
-
-
-def test_nss(topology):
+def test_nss(topo):
"""
Build a nss db, create a ca, and check that it is correct.
"""

+ standalone = topo.standalone
+
# This is a trick. The nss db that ships with DS is broken fundamentally.
# THIS ASSUMES old nss format. SQLite will bite us!
for f in ('key3.db', 'cert8.db', 'key4.db', 'cert9.db', 'secmod.db', 'pkcs11.txt'):
try:
- os.remove("%s/%s" % (topology.standalone.confdir, f))
+ os.remove("%s/%s" % (standalone.confdir, f))
except:
pass

+
# Check if the db exists. Should be false.
- assert(topology.standalone.nss_ssl._db_exists() is False)
+ assert(standalone.nss_ssl._db_exists() is False)
# Create it. Should work.
- assert(topology.standalone.nss_ssl.reinit() is True)
+ assert(standalone.nss_ssl.reinit() is True)
# Check if the db exists. Should be true
- assert(topology.standalone.nss_ssl._db_exists() is True)
+ assert(standalone.nss_ssl._db_exists() is True)

# Check if ca exists. Should be false.
- assert(topology.standalone.nss_ssl._rsa_ca_exists() is False)
+ assert(standalone.nss_ssl._rsa_ca_exists() is False)
# Create it. Should work.
- assert(topology.standalone.nss_ssl.create_rsa_ca() is True)
+ assert(standalone.nss_ssl.create_rsa_ca() is True)
# Check if ca exists. Should be true
- assert(topology.standalone.nss_ssl._rsa_ca_exists() is True)
+ assert(standalone.nss_ssl._rsa_ca_exists() is True)

# Check if we have a server cert / key. Should be false.
- assert(topology.standalone.nss_ssl._rsa_key_and_cert_exists() is False)
+ assert(standalone.nss_ssl._rsa_key_and_cert_exists() is False)
# Create it. Should work.
- assert(topology.standalone.nss_ssl.create_rsa_key_and_cert() is True)
+ assert(standalone.nss_ssl.create_rsa_key_and_cert() is True)
# Check if server cert and key exist. Should be true.
- assert(topology.standalone.nss_ssl._rsa_key_and_cert_exists() is True)
+ assert(standalone.nss_ssl._rsa_key_and_cert_exists() is True)
+
+ # Check making users certs. They should never conflict
+ for user in ('william', 'noriko', 'mark'):
+ assert(standalone.nss_ssl._rsa_user_exists(user) is False)
+ # Create the user cert
+ assert(standalone.nss_ssl.create_rsa_user(user) is True)
+ # Assert it exists now
+ assert(standalone.nss_ssl._rsa_user_exists(user) is True)


if __name__ == "__main__":
diff --git a/lib389/tests/tls_external_test.py b/lib389/tests/tls_external_test.py
new file mode 100644
index 0000000..3eef771
--- /dev/null
+++ b/lib389/tests/tls_external_test.py
@@ -0,0 +1,83 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+
+import pytest
+import ldap
+
+from lib389.topologies import topology_st
+from lib389.utils import *
+from lib389.sasl import PlainSASL
+from lib389.idm.user import UserAccounts
+
+from lib389.config import CertmapLegacy
+
+log = logging.getLogger(__name__)
+
+def test_tls_external(topology_st):
+
+ standalone = topology_st.standalone
+
+ # SETUP TLS
+ standalone.stop()
+ assert(standalone.nss_ssl.reinit() is True)
+ assert(standalone.nss_ssl.create_rsa_ca() is True)
+ assert(standalone.nss_ssl.create_rsa_key_and_cert() is True)
+ # Create a user
+ assert(standalone.nss_ssl.create_rsa_user('testuser') is True)
+ # Now get the details of where the key and crt are.
+ tls_locs = standalone.nss_ssl.get_rsa_user('testuser')
+ # {'ca': ca_path, 'key': key_path, 'crt': crt_path}
+
+ # Start again
+ standalone.start()
+
+ users = UserAccounts(standalone, DEFAULT_SUFFIX)
+ user = users.create(properties={
+ 'uid': 'testuser',
+ 'cn' : 'testuser',
+ 'sn' : 'user',
+ 'uidNumber' : '1000',
+ 'gidNumber' : '2000',
+ 'homeDirectory' : '/home/testuser'
+ })
+
+ standalone.rsa.create()
+ # Set the secure port and nsslapd-security
+ standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1 )
+ standalone.config.set('nsslapd-security', 'on')
+ standalone.sslport = SECUREPORT_STANDALONE1
+ # Now turn on the certmap.
+ cm = CertmapLegacy(standalone)
+ certmaps = cm.list()
+ certmaps['default']['DNComps'] = ''
+ certmaps['default']['FilterComps'] = ['cn']
+ certmaps['default']['VerifyCert'] = 'off'
+ cm.set(certmaps)
+
+ # Check that EXTERNAL is listed in supported mechns.
+ assert(standalone.rootdse.supports_sasl_external())
+ # Restart to allow certmaps to be re-read: Note, we CAN NOT use post_open
+ # here, it breaks on auth. see lib389/__init__.py
+ standalone.restart(post_open=False)
+
+ # Now attempt a bind with TLS external
+ conn = standalone.openConnection(saslmethod='EXTERNAL', connOnly=True, certdir=standalone.get_cert_dir(), userkey=tls_locs['key'], usercert=tls_locs['crt'])
+
+ assert(conn.whoami_s() == "dn: uid=testuser,ou=People,dc=example,dc=com")
+
+ # Backup version of the code:
+ # ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
+ # ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, tls_locs['ca'])
+ # ldap.set_option(ldap.OPT_X_TLS_KEYFILE, tls_locs['key'])
+ # ldap.set_option(ldap.OPT_X_TLS_CERTFILE, tls_locs['crt'])
+ # conn = ldap.initialize(standalone.toLDAPURL())
+
+ # sasl_auth = ldap.sasl.external()
+ # conn.sasl_interactive_bind_s("", sasl_auth)
+
diff --git a/python-lib389.spec b/python-lib389.spec
index 60dbb82..b4060b0 100644
--- a/python-lib389.spec
+++ b/python-lib389.spec
@@ -32,6 +32,7 @@ Summary: %{sum}
Requires: python-ldap
Requires: krb5-workstation
Requires: krb5-server
+Requires: openssl
# Conditional will need to change later.
%if 0%{?rhel} >= 8 || 0%{?fedora}
Requires: python2
@@ -58,6 +59,9 @@ and configuring the 389 Directory Server.
%if 0%{?rhel} >= 8 || 0%{?fedora}
%package -n python%{python3_pkgversion}-%{srcname}
Summary: %{sum}
+Requires: krb5-workstation
+Requires: krb5-server
+Requires: openssl
Requires: python%{python3_pkgversion}
Requires: python%{python3_pkgversion}-pytest
Requires: python%{python3_pkgversion}-pyldap

--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
_______________________________________________
389-commits mailing list -- 389-commits@lists.fedoraproject.org
To unsubscribe send an email to 389-commits-leave@lists.fedoraproject.org

No comments:

Post a Comment