From 5f8c419d373f84be91d27e98718658907a764ceb Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 28 Nov 2017 15:34:44 +0100 Subject: [PATCH] Add tests for start_tls https://github.com/python-ldap/python-ldap/pull/42 Signed-off-by: Christian Heimes --- Lib/slapdtest.py | 18 +++++++++ Tests/certs/README | 24 ++++++++++++ Tests/certs/ca.conf | 77 ++++++++++++++++++++++++++++++++++++ Tests/certs/ca.pem | 80 ++++++++++++++++++++++++++++++++++++++ Tests/certs/client.conf | 16 ++++++++ Tests/certs/client.key | 28 ++++++++++++++ Tests/certs/client.pem | 83 +++++++++++++++++++++++++++++++++++++++ Tests/certs/gencerts.sh | 67 ++++++++++++++++++++++++++++++++ Tests/certs/gennssdb.sh | 28 ++++++++++++++ Tests/certs/server.conf | 16 ++++++++ Tests/certs/server.key | 28 ++++++++++++++ Tests/certs/server.pem | 86 +++++++++++++++++++++++++++++++++++++++++ Tests/t_cext.py | 29 ++++++++++++++ 13 files changed, 580 insertions(+) create mode 100644 Tests/certs/README create mode 100644 Tests/certs/ca.conf create mode 100644 Tests/certs/ca.pem create mode 100644 Tests/certs/client.conf create mode 100644 Tests/certs/client.key create mode 100644 Tests/certs/client.pem create mode 100755 Tests/certs/gencerts.sh create mode 100755 Tests/certs/gennssdb.sh create mode 100644 Tests/certs/server.conf create mode 100644 Tests/certs/server.key create mode 100644 Tests/certs/server.pem diff --git a/Lib/slapdtest.py b/Lib/slapdtest.py index 182097a..1df142b 100644 --- a/Lib/slapdtest.py +++ b/Lib/slapdtest.py @@ -37,6 +37,12 @@ suffix "%(suffix)s" rootdn "%(rootdn)s" rootpw "%(rootpw)s" + +TLSCACertificateFile "%(cafile)s" +TLSCertificateFile "%(servercert)s" +TLSCertificateKeyFile "%(serverkey)s" +# ignore missing client cert but fail with invalid client cert +TLSVerifyClient try """ LOCALHOST = '127.0.0.1' @@ -140,6 +146,15 @@ def __init__(self): self.ldap_uri = "ldap://%s:%d/" % (LOCALHOST, self._port) ldapi_path = os.path.join(self.testrundir, 'ldapi') self.ldapi_uri = "ldapi://%s" % quote_plus(ldapi_path) + # TLS certs + capath = os.path.abspath(os.path.join( + os.getcwd(), 'Tests/certs' + )) + self.cafile = os.path.join(capath, 'ca.pem') + self.servercert = os.path.join(capath, 'server.pem') + self.serverkey = os.path.join(capath, 'server.key') + self.clientcert = os.path.join(capath, 'client.pem') + self.clientkey = os.path.join(capath, 'client.key') def _check_requirements(self): binaries = [ @@ -218,6 +233,9 @@ def gen_config(self): 'rootpw': self.root_pw, 'root_uid': os.getuid(), 'root_gid': os.getgid(), + 'cafile': self.cafile, + 'servercert': self.servercert, + 'serverkey': self.serverkey, } return self.slapd_conf_template % config_dict diff --git a/Tests/certs/README b/Tests/certs/README new file mode 100644 index 0000000..4be616a --- /dev/null +++ b/Tests/certs/README @@ -0,0 +1,24 @@ +python-ldap test certificates +============================= + +Certificates and keys +--------------------- + +* ``ca.pem``: internal root CA certificate +* ``server.pem``: TLS server certificate for slapd, signed by root CA. The + server cert is valid for DNS Name ``localhost`` and IPs ``127.0.0.1`` and + ``:1``. +* ``server.key``: private key for ``server.pem``, no password protection +* ``client.pem``: certificate for TLS client cert authentication, signed by + root CA. +* ``client.key``: private key for ``client.pem``, no password protection + +Configuration and scripts +------------------------- + +* ``ca.conf`` contains the CA definition as well as extensions for the + client and server certificates. +* ``client.conf`` and ``server.conf`` hold the subject and base configuration + for server and client certs. +* ``gencerts.sh`` creates new CA, client and server certificates. +* ``gennssdb.sh`` can be used to create a NSSDB for all certs and keys. diff --git a/Tests/certs/ca.conf b/Tests/certs/ca.conf new file mode 100644 index 0000000..4fb2e2b --- /dev/null +++ b/Tests/certs/ca.conf @@ -0,0 +1,77 @@ +# Written by Christian Heimes + +[default] +ca = "ca" +tmpdir = $ENV::CATMPDIR +outdir = $ENV::CAOUTDIR +name_opt = multiline,-esc_msb,utf8 + +[req] +default_bits = 2048 +encrypt_key = no +default_md = sha256 +utf8 = yes +string_mask = utf8only +prompt = no +distinguished_name = ca_dn + +[ca_dn] +countryName = "DE" +organizationName = "python-ldap" +organizationalUnitName = "slapd-test" +commonName = "Python LDAP Test CA" + +[ca] +default_ca = python_ldap_ca + +[python_ldap_ca] +certificate = $outdir/$ca.pem +private_key = $outdir/$ca.key +new_certs_dir = $tmpdir +serial = $tmpdir/$ca.crt.srl +crlnumber = $tmpdir/$ca.crl.srl +database = $tmpdir/$ca.db +unique_subject = no +default_days = 1461 +default_md = sha256 +policy = match_pol +email_in_dn = no +preserve = no +name_opt = $name_opt +cert_opt = ca_default +copy_extensions = none +default_crl_days = 365 + +[match_pol] +countryName = match +stateOrProvinceName = optional +localityName = optional +organizationName = match +organizationalUnitName = match +commonName = supplied + +[ca_ext] +basicConstraints = critical,CA:true +keyUsage = critical,keyCertSign,cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always + +[server_san] +DNS.1 = localhost +IP.1 = 127.0.0.1 +IP.2 = ::1 + +[server_ext] +basicConstraints = critical,CA:false +keyUsage = critical,digitalSignature,keyEncipherment +extendedKeyUsage = critical,serverAuth +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +subjectAltName = @server_san + +[client_ext] +basicConstraints = critical,CA:false +keyUsage = critical,digitalSignature +extendedKeyUsage = critical,clientAuth +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always diff --git a/Tests/certs/ca.pem b/Tests/certs/ca.pem new file mode 100644 index 0000000..ffd6a5e --- /dev/null +++ b/Tests/certs/ca.pem @@ -0,0 +1,80 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA + Validity + Not Before: Nov 28 13:49:28 2017 GMT + Not After : Nov 28 13:49:28 2021 GMT + Subject: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b4:bd:47:78:d9:62:4e:8e:ae:18:53:b8:8e:9f: + 0b:13:ea:f2:59:c0:1d:7f:0b:5c:5a:ed:c8:b8:cd: + ff:66:94:c4:40:d5:cd:4c:da:06:d2:35:1c:6a:c5: + 76:70:6d:f0:81:8a:25:e4:35:c8:d5:79:17:3e:35: + ec:2b:97:73:77:6c:04:7f:1f:0b:b5:f3:fd:1a:cd: + 76:2c:5c:17:45:6a:6d:c4:d1:6c:f8:09:ba:a0:f8: + 57:44:d7:b4:1c:a4:be:a4:4b:e4:76:34:1c:b1:0b: + 12:42:7e:79:e4:01:e0:5f:8f:6c:03:2d:2a:b6:4e: + 72:85:f1:b9:ac:d5:22:a7:0a:fc:5a:0c:e5:75:8f: + 9f:20:c2:14:ab:53:6a:b0:e6:8a:0d:f4:97:53:7f: + f7:79:29:dd:ea:df:ae:39:6f:59:d8:b3:8e:da:bf: + 08:cd:03:ea:2a:91:33:c9:6f:21:a6:56:06:10:c1: + 40:4b:31:95:b0:47:2a:1e:2f:7d:eb:9b:f1:d4:27: + af:1a:5d:bf:0f:b4:f5:d5:b8:1d:04:61:fa:06:af: + 49:6f:ff:99:88:f3:44:16:ed:3b:f1:c8:ea:31:0a: + f3:f5:97:7a:17:08:e5:e8:8f:dd:1d:c8:8f:55:bf: + 47:93:9a:be:84:99:6f:f3:99:61:5d:b7:13:56:34: + 04:91 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + X509v3 Authority Key Identifier: + keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + + Signature Algorithm: sha256WithRSAEncryption + 03:d2:e6:f5:e4:1d:99:2e:df:02:b9:5b:f7:e0:82:ca:39:76: + 5c:8f:3d:f1:5f:d4:bd:1b:4b:4f:35:4b:5d:f6:21:8b:c0:87: + 23:de:7e:9d:93:1b:67:60:6d:df:7b:95:f0:6a:87:94:5c:f9: + a3:62:50:7b:68:02:b0:5c:d2:4b:f9:b1:97:ba:24:84:47:6e: + e1:e9:d6:e0:fa:2f:f7:9b:c5:67:3a:eb:8e:bc:b7:8f:31:7d: + 5c:ba:91:ce:9d:2c:91:85:32:74:e7:e9:ba:07:61:7c:8b:55: + 69:db:f9:7b:1d:ef:55:fc:bf:58:fc:99:66:9c:9e:92:35:75: + 53:0a:31:e1:34:8a:cf:bc:79:b0:0e:ac:bf:aa:f0:e3:74:88: + f2:a6:5c:38:ad:21:31:ea:cd:e2:57:01:6b:9e:0b:24:62:78: + ac:6a:88:ba:ae:be:20:27:63:ab:3b:e9:2c:c0:5c:81:c5:e7: + e6:fe:a7:09:30:b4:28:65:51:6f:1b:1d:22:f8:30:7d:87:ae: + da:28:99:5c:8b:15:f0:b7:45:d0:1d:3b:ad:c5:29:4a:ed:11: + 68:c4:af:28:a3:0b:9f:1b:c8:86:56:80:3d:6b:d3:1f:c6:b0: + 3d:4a:39:1c:10:57:2d:22:df:d7:7b:ad:7d:f9:12:47:bb:33: + 29:61:14:c4 +-----BEGIN CERTIFICATE----- +MIIDijCCAnKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJERTEU +MBIGA1UECgwLcHl0aG9uLWxkYXAxEzARBgNVBAsMCnNsYXBkLXRlc3QxHDAaBgNV +BAMME1B5dGhvbiBMREFQIFRlc3QgQ0EwHhcNMTcxMTI4MTM0OTI4WhcNMjExMTI4 +MTM0OTI4WjBWMQswCQYDVQQGEwJERTEUMBIGA1UECgwLcHl0aG9uLWxkYXAxEzAR +BgNVBAsMCnNsYXBkLXRlc3QxHDAaBgNVBAMME1B5dGhvbiBMREFQIFRlc3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0vUd42WJOjq4YU7iOnwsT +6vJZwB1/C1xa7ci4zf9mlMRA1c1M2gbSNRxqxXZwbfCBiiXkNcjVeRc+Newrl3N3 +bAR/Hwu18/0azXYsXBdFam3E0Wz4Cbqg+FdE17QcpL6kS+R2NByxCxJCfnnkAeBf +j2wDLSq2TnKF8bms1SKnCvxaDOV1j58gwhSrU2qw5ooN9JdTf/d5Kd3q3645b1nY +s47avwjNA+oqkTPJbyGmVgYQwUBLMZWwRyoeL33rm/HUJ68aXb8PtPXVuB0EYfoG +r0lv/5mI80QW7TvxyOoxCvP1l3oXCOXoj90dyI9Vv0eTmr6EmW/zmWFdtxNWNASR +AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBQ9gOO7lJfb3d/IGiOKyyvBPRrmhTAfBgNVHSMEGDAWgBQ9gOO7lJfb3d/I +GiOKyyvBPRrmhTANBgkqhkiG9w0BAQsFAAOCAQEAA9Lm9eQdmS7fArlb9+CCyjl2 +XI898V/UvRtLTzVLXfYhi8CHI95+nZMbZ2Bt33uV8GqHlFz5o2JQe2gCsFzSS/mx +l7okhEdu4enW4Pov95vFZzrrjry3jzF9XLqRzp0skYUydOfpugdhfItVadv5ex3v +Vfy/WPyZZpyekjV1Uwox4TSKz7x5sA6sv6rw43SI8qZcOK0hMerN4lcBa54LJGJ4 +rGqIuq6+ICdjqzvpLMBcgcXn5v6nCTC0KGVRbxsdIvgwfYeu2iiZXIsV8LdF0B07 +rcUpSu0RaMSvKKMLnxvIhlaAPWvTH8awPUo5HBBXLSLf13utffkSR7szKWEUxA== +-----END CERTIFICATE----- diff --git a/Tests/certs/client.conf b/Tests/certs/client.conf new file mode 100644 index 0000000..774dc3a --- /dev/null +++ b/Tests/certs/client.conf @@ -0,0 +1,16 @@ +# Written by Christian Heimes + +[req] +default_bits = 2048 +encrypt_key = no +default_md = sha256 +utf8 = yes +string_mask = utf8only +prompt = no +distinguished_name = client_dn + +[client_dn] +countryName = "DE" +organizationName = "python-ldap" +organizationalUnitName = "slapd-test" +commonName = "client" diff --git a/Tests/certs/client.key b/Tests/certs/client.key new file mode 100644 index 0000000..81c3e76 --- /dev/null +++ b/Tests/certs/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4aZb1WfASk2JR +VAwFMMQCJNkbBDj7d8QdqSMa32jgTG8m/0N5RYGhdIi6zVeO2GmrSDuRd9Lv5hqu +6ZgFI/rRCYSZHrIe6MXSOs6ZZKHIeQYkZcKa7Eg1FWQPBS51FJjYcotoHj5uxyKZ +pOBMC63qODgq77G4zcqIKVswKS34KAIwvBAAUmTMtyMOOEh8oZm4V4ILpFFNBfs9 +CcyKMcAtCiFXOYZQ0G16ExzT560FMxMmCHd8HkevhfgFlKZb9/bsHNb+tvBwTQNm +eUl4gnPDJk6YLBGIscBImvSRJu8o07aZBvAZvRhPa5iX/mtnlg0pDQ9jiGFK24qB +VPQKtwHjAgMBAAECggEBAIYO7Fir6uP2FHD+4kYbr0HHu7PyG+JirETLoeN1KW50 +4hC9XDWam6PdbVAu2knTdO248uTK8KLI6fjhg0upXjn761LMh7wEh1pOucW07A8q +O5bWCuRIhC1iwXxRzfX65SnkCwfDhKtPRA3hV9SwYNt1xw8fdFjd8S+OsOWP6gUN +A33rBN6L44zfabZmcIO4DvSjDP4zoOL640uFg9dyf2yHzFI+q4mZgMK2iW5TZILl +pNfdQF/hZsqrme+kzUyEtQHzLxGk1twYlFubePS0K1wzXRw6OqFRA0+pYNYP+JmJ +bQs1k/e/y5qRiD9+UzR3MOTASl9BWDu9KCK1LF5pqYECgYEA7SD43REkVmQkFinf +Re1kfOTkqCub1t4veTZBqVBNCF10fnQwPk1UQ2PShum1iJun6S3P0NzJP/svGc0N +m44XJaD8QHnXdsDkHGx36/Cj15+VYpGvSpkPUgVQk4Q82n29Y3v8/xR6xqhXiB2N +kuWHig8WIrrc690mUlL1NLQvH+ECgYEAxxaggQXlBTdDSMj2x3Y/0TJlkese2Oet +JxWu6xGfjrsjMxZj1c5C3ESeKws3Z1eH9nk3AVzJ/q/+2SyCM3lM+eFz6dAtKVDB +Olly4YhxoEZDgW4JXMVLP8d7xNDxWk9y7UitpvfDJ8J0hf//y9KR2jnokkfSKScN +AsqrMe7+6kMCgYEAgndztV3rGkU6vZ8II1c7xKPDUuu7cHsKr6w0cE2oNIQGxlRy +/rRZOkK/4E7R/Hl35wm3n3j6mWNARPfXFtEU1zU91NO0wrfaSfE8AeqCmu5IqNTz +Fx4jmcMm1CMbwDMScpwTVN0VuBuDHXb1H+99pW4rhaw+RN+GaCEQnJDOpMECgYBv +UTOFcOpRNEkm1VdGx9N/ARLRuAmTdlbW18TqIvx4LiLMWeSQk7fGuYdGwgrEeajI +I5ah6GP5SCbS/5P9fAGSZoENZx0ZUNH58jHN8SC3YRI1uHT7rkUY8E1ACyQoPuwf +yNdv2HECNjQ5CJ7aNG7g+igUQpw77l3UBcYbMWrPSQKBgG+R+nFGbjJ7oHyvJyJI +C3rlD6vay9BoXmjA05dCO36zDcq5xZqwLnQmYkFgBw+RwvwV8gbBirG7GEpy0rdt +5YbHwiI6fMfLsXocU9f86o2dhhpA2o42ig3mfe8X3LteWtmRfJ3BtHbW2ZWS8Kvx +MnZGm64AmjWV5oJb7e5jpgu6 +-----END PRIVATE KEY----- diff --git a/Tests/certs/client.pem b/Tests/certs/client.pem new file mode 100644 index 0000000..8133c6d --- /dev/null +++ b/Tests/certs/client.pem @@ -0,0 +1,83 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA + Validity + Not Before: Nov 28 13:49:28 2017 GMT + Not After : Nov 28 13:49:28 2021 GMT + Subject: C=DE, O=python-ldap, OU=slapd-test, CN=client + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b8:69:96:f5:59:f0:12:93:62:51:54:0c:05:30: + c4:02:24:d9:1b:04:38:fb:77:c4:1d:a9:23:1a:df: + 68:e0:4c:6f:26:ff:43:79:45:81:a1:74:88:ba:cd: + 57:8e:d8:69:ab:48:3b:91:77:d2:ef:e6:1a:ae:e9: + 98:05:23:fa:d1:09:84:99:1e:b2:1e:e8:c5:d2:3a: + ce:99:64:a1:c8:79:06:24:65:c2:9a:ec:48:35:15: + 64:0f:05:2e:75:14:98:d8:72:8b:68:1e:3e:6e:c7: + 22:99:a4:e0:4c:0b:ad:ea:38:38:2a:ef:b1:b8:cd: + ca:88:29:5b:30:29:2d:f8:28:02:30:bc:10:00:52: + 64:cc:b7:23:0e:38:48:7c:a1:99:b8:57:82:0b:a4: + 51:4d:05:fb:3d:09:cc:8a:31:c0:2d:0a:21:57:39: + 86:50:d0:6d:7a:13:1c:d3:e7:ad:05:33:13:26:08: + 77:7c:1e:47:af:85:f8:05:94:a6:5b:f7:f6:ec:1c: + d6:fe:b6:f0:70:4d:03:66:79:49:78:82:73:c3:26: + 4e:98:2c:11:88:b1:c0:48:9a:f4:91:26:ef:28:d3: + b6:99:06:f0:19:bd:18:4f:6b:98:97:fe:6b:67:96: + 0d:29:0d:0f:63:88:61:4a:db:8a:81:54:f4:0a:b7: + 01:e3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature + X509v3 Extended Key Usage: critical + TLS Web Client Authentication + X509v3 Subject Key Identifier: + C5:E2:E2:72:A6:55:C1:FB:D3:4B:11:01:D0:A0:AE:99:B6:8F:F1:39 + X509v3 Authority Key Identifier: + keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + + Signature Algorithm: sha256WithRSAEncryption + 11:76:03:a3:a6:9d:4e:3e:74:93:50:3b:31:d5:c7:d0:a8:34: + 84:01:6b:a2:08:cd:89:11:57:97:a2:e9:83:f0:a6:ef:03:8c: + b2:8d:31:8f:ee:b3:c9:8c:49:1f:e4:fc:21:58:8d:22:c2:17: + 96:2e:b1:d1:64:03:d6:48:70:41:65:22:38:bf:9f:00:dd:a8: + 82:a0:df:22:e0:9a:1b:27:16:4b:db:7f:b0:fe:9f:a8:80:90: + 69:ad:35:be:e6:95:fe:f9:64:96:0a:d8:d7:8e:aa:63:fb:9a: + d5:d0:e9:cb:8c:f3:08:c0:0c:26:72:c9:c6:29:5c:cf:3c:9e: + e2:38:37:5a:16:2f:70:82:0b:e6:80:27:90:bd:81:b4:58:52: + 6c:4e:b7:77:fc:49:76:7a:4f:6c:ee:ff:02:1f:f4:49:6e:78: + c3:fa:cd:ee:d3:e7:e5:05:a4:16:97:48:16:44:9f:81:1c:ac: + a9:30:0e:1d:ea:15:32:d7:2b:1e:68:92:0a:9c:5b:b2:27:57: + d3:21:3e:76:71:94:2d:da:76:61:aa:64:99:b7:54:1c:ba:e2: + a5:b3:21:a4:a8:36:fe:5d:a3:73:6a:5e:77:af:ab:9a:d9:62: + 00:f0:fd:90:1e:b6:cc:57:5d:92:0d:16:16:97:78:48:27:fc: + d9:2d:55:4d +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJERTEU +MBIGA1UECgwLcHl0aG9uLWxkYXAxEzARBgNVBAsMCnNsYXBkLXRlc3QxHDAaBgNV +BAMME1B5dGhvbiBMREFQIFRlc3QgQ0EwHhcNMTcxMTI4MTM0OTI4WhcNMjExMTI4 +MTM0OTI4WjBJMQswCQYDVQQGEwJERTEUMBIGA1UECgwLcHl0aG9uLWxkYXAxEzAR +BgNVBAsMCnNsYXBkLXRlc3QxDzANBgNVBAMMBmNsaWVudDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALhplvVZ8BKTYlFUDAUwxAIk2RsEOPt3xB2pIxrf +aOBMbyb/Q3lFgaF0iLrNV47YaatIO5F30u/mGq7pmAUj+tEJhJkesh7oxdI6zplk +och5BiRlwprsSDUVZA8FLnUUmNhyi2gePm7HIpmk4EwLreo4OCrvsbjNyogpWzAp +LfgoAjC8EABSZMy3Iw44SHyhmbhXggukUU0F+z0JzIoxwC0KIVc5hlDQbXoTHNPn +rQUzEyYId3weR6+F+AWUplv39uwc1v628HBNA2Z5SXiCc8MmTpgsEYixwEia9JEm +7yjTtpkG8Bm9GE9rmJf+a2eWDSkND2OIYUrbioFU9Aq3AeMCAwEAAaN4MHYwDAYD +VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUH +AwIwHQYDVR0OBBYEFMXi4nKmVcH700sRAdCgrpm2j/E5MB8GA1UdIwQYMBaAFD2A +47uUl9vd38gaI4rLK8E9GuaFMA0GCSqGSIb3DQEBCwUAA4IBAQARdgOjpp1OPnST +UDsx1cfQqDSEAWuiCM2JEVeXoumD8KbvA4yyjTGP7rPJjEkf5PwhWI0iwheWLrHR +ZAPWSHBBZSI4v58A3aiCoN8i4JobJxZL23+w/p+ogJBprTW+5pX++WSWCtjXjqpj ++5rV0OnLjPMIwAwmcsnGKVzPPJ7iODdaFi9wggvmgCeQvYG0WFJsTrd3/El2ek9s +7v8CH/RJbnjD+s3u0+flBaQWl0gWRJ+BHKypMA4d6hUy1yseaJIKnFuyJ1fTIT52 +cZQt2nZhqmSZt1QcuuKlsyGkqDb+XaNzal53r6ua2WIA8P2QHrbMV12SDRYWl3hI +J/zZLVVN +-----END CERTIFICATE----- diff --git a/Tests/certs/gencerts.sh b/Tests/certs/gencerts.sh new file mode 100755 index 0000000..6edafa0 --- /dev/null +++ b/Tests/certs/gencerts.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Written by Christian Heimes +set -e + +export CAOUTDIR=. +export CATMPDIR=tmp + +rm -rf $CATMPDIR +rm -rf ca.pem ca.key server.pem server.key client.pem client.key +rm -rf cert9.db key4.db pkcs11.tx + +mkdir -p $CAOUTDIR +mkdir -p $CATMPDIR + +touch $CATMPDIR/ca.db +touch $CATMPDIR/ca.db.attr +echo '01' > $CATMPDIR/ca.crt.srl +echo '01' > $CATMPDIR/ca.crl.srl + +# root CA +openssl req -new \ + -config ca.conf \ + -out $CATMPDIR/ca.csr \ + -keyout $CAOUTDIR/ca.key \ + -batch + +openssl ca -selfsign \ + -config ca.conf \ + -in $CATMPDIR/ca.csr \ + -out $CAOUTDIR/ca.pem \ + -extensions ca_ext \ + -batch + +# server cert +openssl req -new \ + -config server.conf \ + -out $CATMPDIR/server.csr \ + -keyout $CAOUTDIR/server.key \ + -batch + +openssl ca \ + -config ca.conf \ + -in $CATMPDIR/server.csr \ + -out $CAOUTDIR/server.pem \ + -policy match_pol \ + -extensions server_ext \ + -batch + +# client cert +openssl req -new \ + -config client.conf \ + -out $CATMPDIR/client.csr \ + -keyout $CAOUTDIR/client.key \ + -batch + +openssl ca \ + -config ca.conf \ + -in $CATMPDIR/client.csr \ + -out $CAOUTDIR/client.pem \ + -policy match_pol \ + -extensions client_ext \ + -batch + +# cleanup +rm -rf $CATMPDIR ca.key + +echo DONE diff --git a/Tests/certs/gennssdb.sh b/Tests/certs/gennssdb.sh new file mode 100755 index 0000000..aeeb333 --- /dev/null +++ b/Tests/certs/gennssdb.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Written by Christian Heimes +set -e + +CATMPDIR=tmp +PASSFILE=${CATMPDIR}/passwd.txt +NSSDB=sql:${CAOUTDIR} + +mkdir -p $CATMPDIR + +# Create PKCS#12 files for NSSDB import +echo "dummy" > $PASSFILE +openssl pkcs12 -name "servercert" -in server.pem -inkey server.key \ + -caname "testca" -CAfile ca.pem \ + -password "file:${PASSFILE}" -export -out server.p12 +openssl pkcs12 -name "clientcert" -in client.pem -inkey client.key \ + -caname "testca" -CAfile ca.pem \ + -password "file:${PASSFILE}" -export -out client.p12 + +# Create NSS DB +certutil -d $NSSDB -N --empty-password +certutil -d $NSSDB -A -n "testca" -t CT,, -a -i ca.pem +pk12util -d $NSSDB -i server.p12 -w ${PASSFILE} +pk12util -d $NSSDB -i client.p12 -w ${PASSFILE} +certutil -d $NSSDB -L + +# cleanup +rm -rf $CATMPDIR server.p12 client.p12 \ No newline at end of file diff --git a/Tests/certs/server.conf b/Tests/certs/server.conf new file mode 100644 index 0000000..94f4427 --- /dev/null +++ b/Tests/certs/server.conf @@ -0,0 +1,16 @@ +# Written by Christian Heimes + +[req] +default_bits = 2048 +encrypt_key = no +default_md = sha256 +utf8 = yes +string_mask = utf8only +prompt = no +distinguished_name = server_dn + +[server_dn] +countryName = "DE" +organizationName = "python-ldap" +organizationalUnitName = "slapd-test" +commonName = "server cert for localhost" diff --git a/Tests/certs/server.key b/Tests/certs/server.key new file mode 100644 index 0000000..081dc2f --- /dev/null +++ b/Tests/certs/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDTJOAnZdPnCTmy +gkI5XUHsuk1xL4eePxMcV+8HYMfQh+b354CygQnRcjj38uQ6S70mOIyCrTWKNrec +VrnV0xu4o16AkSRrkN0AVpfWk0ae2GaccDV+o82x+NBStfYNXW2xZ1aZIyFplGTU +yxQCpsU4yCX7RM7Ywq3fM6b8eoR2jRNGC/uMdNN/7WJkHfhJFOYFpPJ6vKOlR3PP +qzkj8WRu/ill63+phHA3UEUweKG4DoaP85M0WqHW4Kvp0A4sI5uPYI2lPrDqUf6L +Wc22gUpcFFNDReWYcxLobCsAeT4SqvEC83Dv53NKQS6wt4zLewVG1+8cjyctwv4m +PAatL8uDAgMBAAECggEACB8+BCX1nciMEKLUG1LMC2grPHRgmiTA/nEff8AoT4w6 +xUSBfdxa3VSwflE4mEl7kDHSreAt1BBAxeHMKj6BrXuTUgzDQuQCrFWoZ5eousmG +QPRMCoAQlI0GrnfTbDYw1wcrnJ5uVZpgupLJRUTXB1UjqOO/tTTf7VsWTFYGLG00 +8OeIenTGX0E1mVW9ERYCSYEtMfhQhSS3dhPmMm5VV6muIxv4ym6r2uodCY7ocxGA +JmI9F22xovH8CUtzoRbh0o4Y9VUVkKcMDl35+hya8c0BH4Vh22hnYgiyUkS1pBgY +GiX/rmU4FxkzLDrLLMB8cf+rzh+aOKjNupZ2dbNgsQKBgQDu3DLRHhUJEUcoK6Gb +ltVK179WsT1Me1Y/qiZ2SgGsXmSZFK+8cYLvXUI7Epz2Du2DwAb1J+sItie5QQ9g +o6eymTS7DuQ6MFS1UmC8PfSNjT/dFd/sVIEFJRcNkVC4CpJCnE4MQOUb6OIT8YnR ++HNDNMWc5+ab1OeFxMWRSrP52wKBgQDiS4oFkhfPtaxVyUHuiR0+0icjCGehWSM0 +eNoiX561HtBrYCZYp6kg1JMSLBSJPRaHi78td3z+6iDvE6HQtwrLq/LNd2CRJ80U +rkGjsItpZYfnJVMmK6Y4KksGlvYqWshWb8Zp0o+LPRb6g0TxZrbOGv7yD8FjaZwq +wlGxleIJeQKBgDDR+uT5BA2lZWjVeiOF8bRpYmdCtKe0Mc2zZkcZGzxy0pbjPoQC +o2NvKUFPrZsxM+SQ1Bs5fHV8XaQkoxL6gCUl4Tw2b/lgtX+WBcWT2C8yZpI2jV0N +bI1zpkGUqO3k4z4QGnewr+NDdyniXWv4Hv7mg1ltoJnLK0MRE9x9a0mvAoGBAIi4 +8w8ikVhhf1nlWvxvw0etWRAFh/coD+koC0MxWoY7s9jsIr71rW20gZc9Irs4OWBz +wnIJ+29YrcVEq0ObE96yaORS9/k7fuC719S6WcC4I0A4gOBTBv5wLxwwIVK9vsTa +i5psKWYK5tM8dG8Vi+VC0j4V3tXdfQkolosg74yhAoGAOLj21q7nNk+ExGAOesmR +qykxwIXxbHxDIfmEJJVE6OJMRvubr8WgaiSG0ptWBeiHDnldUS436difn7JXlsdo +K51jVzzgUqZXK75xvnSD7e5AL3fFRCU5usoU699fxWJTMs8H2z4alRng06MloeXJ +xrLwQyuLH8BWYFuPj4QxwwQ= +-----END PRIVATE KEY----- diff --git a/Tests/certs/server.pem b/Tests/certs/server.pem new file mode 100644 index 0000000..45ae694 --- /dev/null +++ b/Tests/certs/server.pem @@ -0,0 +1,86 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=DE, O=python-ldap, OU=slapd-test, CN=Python LDAP Test CA + Validity + Not Before: Nov 28 13:49:28 2017 GMT + Not After : Nov 28 13:49:28 2021 GMT + Subject: C=DE, O=python-ldap, OU=slapd-test, CN=server cert for localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d3:24:e0:27:65:d3:e7:09:39:b2:82:42:39:5d: + 41:ec:ba:4d:71:2f:87:9e:3f:13:1c:57:ef:07:60: + c7:d0:87:e6:f7:e7:80:b2:81:09:d1:72:38:f7:f2: + e4:3a:4b:bd:26:38:8c:82:ad:35:8a:36:b7:9c:56: + b9:d5:d3:1b:b8:a3:5e:80:91:24:6b:90:dd:00:56: + 97:d6:93:46:9e:d8:66:9c:70:35:7e:a3:cd:b1:f8: + d0:52:b5:f6:0d:5d:6d:b1:67:56:99:23:21:69:94: + 64:d4:cb:14:02:a6:c5:38:c8:25:fb:44:ce:d8:c2: + ad:df:33:a6:fc:7a:84:76:8d:13:46:0b:fb:8c:74: + d3:7f:ed:62:64:1d:f8:49:14:e6:05:a4:f2:7a:bc: + a3:a5:47:73:cf:ab:39:23:f1:64:6e:fe:29:65:eb: + 7f:a9:84:70:37:50:45:30:78:a1:b8:0e:86:8f:f3: + 93:34:5a:a1:d6:e0:ab:e9:d0:0e:2c:23:9b:8f:60: + 8d:a5:3e:b0:ea:51:fe:8b:59:cd:b6:81:4a:5c:14: + 53:43:45:e5:98:73:12:e8:6c:2b:00:79:3e:12:aa: + f1:02:f3:70:ef:e7:73:4a:41:2e:b0:b7:8c:cb:7b: + 05:46:d7:ef:1c:8f:27:2d:c2:fe:26:3c:06:ad:2f: + cb:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: critical + TLS Web Server Authentication + X509v3 Subject Key Identifier: + 98:03:0F:65:1A:34:A9:E1:09:1B:EC:D0:ED:A8:11:E6:AE:85:1F:2C + X509v3 Authority Key Identifier: + keyid:3D:80:E3:BB:94:97:DB:DD:DF:C8:1A:23:8A:CB:2B:C1:3D:1A:E6:85 + + X509v3 Subject Alternative Name: + DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 + Signature Algorithm: sha256WithRSAEncryption + a6:01:8e:6f:0f:db:35:1f:a2:03:f5:39:ca:16:5f:e5:5a:0f: + 7e:f1:24:8a:b9:6f:78:c1:2c:f7:3a:07:f1:27:46:47:e0:98: + a1:ec:23:38:30:b9:bc:66:ac:17:06:36:48:ad:5d:1d:b4:a2: + c1:2c:08:55:ff:00:01:04:26:60:38:a6:13:52:7b:d3:88:8a: + b1:1f:a4:cd:14:9b:c8:04:77:01:72:6d:fe:b5:8c:3a:25:e2: + 2b:83:73:4b:2e:c6:6f:20:8b:00:c7:3b:2e:de:62:e9:74:81: + c6:a5:f5:b1:f9:db:b9:58:f9:7c:a2:3f:4e:46:93:ae:af:75: + 01:77:ea:34:4e:82:dc:d3:53:39:c0:b0:f9:8a:86:8d:f5:f2: + c3:a0:fa:e4:a9:b3:2c:33:ba:78:d5:ef:12:05:33:4f:29:9b: + 88:41:52:73:5a:17:7e:bc:66:d0:dc:c7:14:6d:a5:99:78:67: + 81:36:76:29:63:de:76:d4:eb:ca:5c:82:1b:ae:7d:80:ed:32: + 69:b0:b7:7a:1d:e1:00:a8:b1:95:d3:4d:d5:e2:8c:f4:30:a7: + da:79:bd:f5:bb:7a:8d:c5:ec:1c:16:32:58:92:ad:fc:1c:83: + 49:ca:8c:f9:6d:d4:f7:2c:98:1a:25:47:36:16:4f:15:46:ea: + 71:78:f1:51 +-----BEGIN CERTIFICATE----- +MIID1TCCAr2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJERTEU +MBIGA1UECgwLcHl0aG9uLWxkYXAxEzARBgNVBAsMCnNsYXBkLXRlc3QxHDAaBgNV +BAMME1B5dGhvbiBMREFQIFRlc3QgQ0EwHhcNMTcxMTI4MTM0OTI4WhcNMjExMTI4 +MTM0OTI4WjBcMQswCQYDVQQGEwJERTEUMBIGA1UECgwLcHl0aG9uLWxkYXAxEzAR +BgNVBAsMCnNsYXBkLXRlc3QxIjAgBgNVBAMMGXNlcnZlciBjZXJ0IGZvciBsb2Nh +bGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTJOAnZdPnCTmy +gkI5XUHsuk1xL4eePxMcV+8HYMfQh+b354CygQnRcjj38uQ6S70mOIyCrTWKNrec +VrnV0xu4o16AkSRrkN0AVpfWk0ae2GaccDV+o82x+NBStfYNXW2xZ1aZIyFplGTU +yxQCpsU4yCX7RM7Ywq3fM6b8eoR2jRNGC/uMdNN/7WJkHfhJFOYFpPJ6vKOlR3PP +qzkj8WRu/ill63+phHA3UEUweKG4DoaP85M0WqHW4Kvp0A4sI5uPYI2lPrDqUf6L +Wc22gUpcFFNDReWYcxLobCsAeT4SqvEC83Dv53NKQS6wt4zLewVG1+8cjyctwv4m +PAatL8uDAgMBAAGjgacwgaQwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBaAw +FgYDVR0lAQH/BAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFJgDD2UaNKnhCRvs0O2o +EeauhR8sMB8GA1UdIwQYMBaAFD2A47uUl9vd38gaI4rLK8E9GuaFMCwGA1UdEQQl +MCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0B +AQsFAAOCAQEApgGObw/bNR+iA/U5yhZf5VoPfvEkirlveMEs9zoH8SdGR+CYoewj +ODC5vGasFwY2SK1dHbSiwSwIVf8AAQQmYDimE1J704iKsR+kzRSbyAR3AXJt/rWM +OiXiK4NzSy7GbyCLAMc7Lt5i6XSBxqX1sfnbuVj5fKI/TkaTrq91AXfqNE6C3NNT +OcCw+YqGjfXyw6D65KmzLDO6eNXvEgUzTymbiEFSc1oXfrxm0NzHFG2lmXhngTZ2 +KWPedtTrylyCG659gO0yabC3eh3hAKixldNN1eKM9DCn2nm99bt6jcXsHBYyWJKt +/ByDScqM+W3U9yyYGiVHNhZPFUbqcXjxUQ== +-----END CERTIFICATE----- diff --git a/Tests/t_cext.py b/Tests/t_cext.py index 6998e73..3a0f7df 100644 --- a/Tests/t_cext.py +++ b/Tests/t_cext.py @@ -807,6 +807,35 @@ def test_invalid_controls(self): l.sasl_interactive_bind_s, 'who', 'SASLObject', post=(1,)) self.assertInvalidControls(l.unbind_ext) + @unittest.skipUnless(_ldap.TLS_AVAIL, "needs tls") + def test_tls_ext(self): + l = self._open_conn(bind=False) + # StartTLS needs LDAPv3 + l.set_option(_ldap.OPT_PROTOCOL_VERSION, _ldap.VERSION3) + l.set_option(_ldap.OPT_X_TLS_CACERTFILE, self.server.cafile) + # re-create TLS context + l.set_option(_ldap.OPT_X_TLS_NEWCTX, 0) + l.start_tls_s() + + @unittest.skipUnless(_ldap.TLS_AVAIL, "needs tls") + def test_tls_ext_noca(self): + l = self._open_conn(bind=False) + l.set_option(_ldap.OPT_PROTOCOL_VERSION, _ldap.VERSION3) + l.set_option(_ldap.OPT_X_TLS_NEWCTX, 0) + with self.assertRaises(_ldap.CONNECT_ERROR): + l.start_tls_s() + + @unittest.skipUnless(_ldap.TLS_AVAIL, "needs tls") + def test_tls_ext_clientcert(self): + l = self._open_conn(bind=False) + l.set_option(_ldap.OPT_PROTOCOL_VERSION, _ldap.VERSION3) + l.set_option(_ldap.OPT_X_TLS_CACERTFILE, self.server.cafile) + l.set_option(_ldap.OPT_X_TLS_CERTFILE, self.server.clientcert) + l.set_option(_ldap.OPT_X_TLS_KEYFILE, self.server.clientkey) + l.set_option(_ldap.OPT_X_TLS_REQUIRE_CERT, _ldap.OPT_X_TLS_HARD) + l.set_option(_ldap.OPT_X_TLS_NEWCTX, 0) + l.start_tls_s() + # TODO verify that client auth actually works if __name__ == '__main__': unittest.main()