summaryrefslogtreecommitdiffstats
path: root/src/test/ssl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
commit46651ce6fe013220ed397add242004d764fc0153 (patch)
tree6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/test/ssl
parentInitial commit. (diff)
downloadpostgresql-14-46651ce6fe013220ed397add242004d764fc0153.tar.xz
postgresql-14-46651ce6fe013220ed397add242004d764fc0153.zip
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ssl')
-rw-r--r--src/test/ssl/.gitignore3
-rw-r--r--src/test/ssl/Makefile192
-rw-r--r--src/test/ssl/README102
-rw-r--r--src/test/ssl/cas.config64
-rw-r--r--src/test/ssl/client-dn.config16
-rw-r--r--src/test/ssl/client.config13
-rw-r--r--src/test/ssl/client_ca.config11
-rw-r--r--src/test/ssl/root_ca.config13
-rw-r--r--src/test/ssl/server-cn-and-alt-names.config25
-rw-r--r--src/test/ssl/server-cn-only.config13
-rw-r--r--src/test/ssl/server-multiple-alt-names.config20
-rw-r--r--src/test/ssl/server-no-names.config16
-rw-r--r--src/test/ssl/server-revoked.config15
-rw-r--r--src/test/ssl/server-single-alt-name.config18
-rw-r--r--src/test/ssl/server_ca.config11
-rw-r--r--src/test/ssl/ssl/.gitignore3
-rw-r--r--src/test/ssl/ssl/both-cas-1.crt57
-rw-r--r--src/test/ssl/ssl/both-cas-2.crt57
-rw-r--r--src/test/ssl/ssl/client+client_ca.crt36
-rw-r--r--src/test/ssl/ssl/client-crldir/9bb9e3c3.r011
-rw-r--r--src/test/ssl/ssl/client-der.keybin0 -> 1191 bytes
-rw-r--r--src/test/ssl/ssl/client-dn.crt19
-rw-r--r--src/test/ssl/ssl/client-dn.key27
-rw-r--r--src/test/ssl/ssl/client-encrypted-der.keybin0 -> 1191 bytes
-rw-r--r--src/test/ssl/ssl/client-encrypted-pem.key30
-rw-r--r--src/test/ssl/ssl/client-revoked.crt17
-rw-r--r--src/test/ssl/ssl/client-revoked.key27
-rw-r--r--src/test/ssl/ssl/client.crl11
-rw-r--r--src/test/ssl/ssl/client.crt17
-rw-r--r--src/test/ssl/ssl/client.key27
-rw-r--r--src/test/ssl/ssl/client_ca.crt19
-rw-r--r--src/test/ssl/ssl/client_ca.key27
-rw-r--r--src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r011
-rw-r--r--src/test/ssl/ssl/root+client-crldir/a3d11bff.r011
-rw-r--r--src/test/ssl/ssl/root+client.crl22
-rw-r--r--src/test/ssl/ssl/root+client_ca.crt38
-rw-r--r--src/test/ssl/ssl/root+server-crldir/a3d11bff.r011
-rw-r--r--src/test/ssl/ssl/root+server-crldir/a836cc2d.r011
-rw-r--r--src/test/ssl/ssl/root+server.crl22
-rw-r--r--src/test/ssl/ssl/root+server_ca.crt38
-rw-r--r--src/test/ssl/ssl/root.crl11
-rw-r--r--src/test/ssl/ssl/root_ca.crt19
-rw-r--r--src/test/ssl/ssl/root_ca.key27
-rw-r--r--src/test/ssl/ssl/server-cn-and-alt-names.crt20
-rw-r--r--src/test/ssl/ssl/server-cn-and-alt-names.key27
-rw-r--r--src/test/ssl/ssl/server-cn-only.crt18
-rw-r--r--src/test/ssl/ssl/server-cn-only.key27
-rw-r--r--src/test/ssl/ssl/server-crldir/a836cc2d.r011
-rw-r--r--src/test/ssl/ssl/server-multiple-alt-names.crt20
-rw-r--r--src/test/ssl/ssl/server-multiple-alt-names.key27
-rw-r--r--src/test/ssl/ssl/server-no-names.crt18
-rw-r--r--src/test/ssl/ssl/server-no-names.key27
-rw-r--r--src/test/ssl/ssl/server-password.key30
-rw-r--r--src/test/ssl/ssl/server-revoked.crt18
-rw-r--r--src/test/ssl/ssl/server-revoked.key27
-rw-r--r--src/test/ssl/ssl/server-single-alt-name.crt19
-rw-r--r--src/test/ssl/ssl/server-single-alt-name.key27
-rw-r--r--src/test/ssl/ssl/server-ss.crt19
-rw-r--r--src/test/ssl/ssl/server-ss.key27
-rw-r--r--src/test/ssl/ssl/server.crl11
-rw-r--r--src/test/ssl/ssl/server_ca.crt19
-rw-r--r--src/test/ssl/ssl/server_ca.key27
-rw-r--r--src/test/ssl/t/001_ssltests.pl600
-rw-r--r--src/test/ssl/t/002_scram.pl119
-rw-r--r--src/test/ssl/t/SSLServer.pm205
65 files changed, 2481 insertions, 0 deletions
diff --git a/src/test/ssl/.gitignore b/src/test/ssl/.gitignore
new file mode 100644
index 0000000..a325c2f
--- /dev/null
+++ b/src/test/ssl/.gitignore
@@ -0,0 +1,3 @@
+# Generated by regression tests
+/client-log
+/tmp_check/
diff --git a/src/test/ssl/Makefile b/src/test/ssl/Makefile
new file mode 100644
index 0000000..a517756
--- /dev/null
+++ b/src/test/ssl/Makefile
@@ -0,0 +1,192 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/test/ssl
+#
+# Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/test/ssl/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/test/ssl
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+export with_ssl
+
+CERTIFICATES := server_ca server-cn-and-alt-names \
+ server-cn-only server-single-alt-name server-multiple-alt-names \
+ server-no-names server-revoked server-ss \
+ client_ca client client-dn client-revoked \
+ root_ca
+
+SSLFILES := $(CERTIFICATES:%=ssl/%.key) $(CERTIFICATES:%=ssl/%.crt) \
+ ssl/server-password.key \
+ ssl/client.crl ssl/server.crl ssl/root.crl \
+ ssl/both-cas-1.crt ssl/both-cas-2.crt \
+ ssl/root+server_ca.crt ssl/root+server.crl \
+ ssl/root+client_ca.crt ssl/root+client.crl \
+ ssl/client+client_ca.crt ssl/client-der.key \
+ ssl/client-encrypted-pem.key ssl/client-encrypted-der.key
+
+SSLDIRS := ssl/client-crldir ssl/server-crldir \
+ ssl/root+client-crldir ssl/root+server-crldir
+
+# This target re-generates all the key and certificate files. Usually we just
+# use the ones that are committed to the tree without rebuilding them.
+#
+# This target will fail unless preceded by sslfiles-clean.
+#
+sslfiles: $(SSLFILES) $(SSLDIRS)
+
+# OpenSSL requires a directory to put all generated certificates in. We don't
+# use this for anything, but we need a location.
+ssl/new_certs_dir:
+ mkdir ssl/new_certs_dir
+
+# Rule for creating private/public key pairs.
+ssl/%.key:
+ openssl genrsa -out $@ 2048
+ chmod 0600 $@
+
+# Root CA certificate
+ssl/root_ca.crt: ssl/root_ca.key cas.config
+ touch ssl/root_ca-certindex
+ openssl req -new -out ssl/root_ca.crt -x509 -config cas.config -config root_ca.config -key ssl/root_ca.key -days 10000 -extensions v3_ca
+ echo "01" > ssl/root_ca.srl
+
+# Client and server CAs
+ssl/%_ca.crt: ssl/%_ca.key %_ca.config ssl/root_ca.crt ssl/new_certs_dir
+ touch ssl/$*_ca-certindex
+ echo "unique_subject=no" > ssl/$*_ca-certindex.attr
+ openssl req -new -out ssl/temp_ca.crt -config cas.config -config $*_ca.config -key ssl/$*_ca.key
+# Sign the certificate with the root CA
+ openssl ca -name root_ca -batch -config cas.config -in ssl/temp_ca.crt -out ssl/temp_ca_signed.crt -extensions v3_ca
+ openssl x509 -in ssl/temp_ca_signed.crt -out ssl/$*_ca.crt # to keep just the PEM cert
+ rm ssl/temp_ca.crt ssl/temp_ca_signed.crt
+ echo "01" > ssl/$*_ca.srl
+
+# Server certificates, signed by server CA:
+ssl/server-%.crt: ssl/server-%.key ssl/server_ca.crt server-%.config
+ openssl req -new -key ssl/server-$*.key -out ssl/server-$*.csr -config server-$*.config
+ openssl ca -name server_ca -batch -config cas.config -in ssl/server-$*.csr -out ssl/temp.crt -extensions v3_req -extfile server-$*.config
+ openssl x509 -in ssl/temp.crt -out ssl/server-$*.crt # to keep just the PEM cert
+ rm ssl/server-$*.csr
+
+# Self-signed version of server-cn-only.crt
+ssl/server-ss.crt: ssl/server-cn-only.key ssl/server-cn-only.crt server-cn-only.config
+ openssl req -new -key ssl/server-cn-only.key -out ssl/server-ss.csr -config server-cn-only.config
+ openssl x509 -req -days 10000 -in ssl/server-ss.csr -signkey ssl/server-cn-only.key -out ssl/server-ss.crt -extensions v3_req -extfile server-cn-only.config
+ rm ssl/server-ss.csr
+
+# Password-protected version of server-cn-only.key
+ssl/server-password.key: ssl/server-cn-only.key
+ openssl rsa -aes256 -in $< -out $@ -passout 'pass:secret1'
+
+# Client certificate, signed by the client CA:
+ssl/client.crt: ssl/client.key ssl/client_ca.crt
+ openssl req -new -key ssl/client.key -out ssl/client.csr -config client.config
+ openssl ca -name client_ca -batch -out ssl/temp.crt -config cas.config -infiles ssl/client.csr
+ openssl x509 -in ssl/temp.crt -out ssl/client.crt # to keep just the PEM cert
+ rm ssl/client.csr ssl/temp.crt
+
+# Client certificate with multi-part DN, signed by the client CA:
+ssl/client-dn.crt: ssl/client-dn.key ssl/client_ca.crt
+ openssl req -new -key ssl/client-dn.key -out ssl/client-dn.csr -config client-dn.config
+ openssl ca -name client_ca -batch -out ssl/temp.crt -config cas.config -infiles ssl/client-dn.csr
+ openssl x509 -in ssl/temp.crt -out ssl/client-dn.crt # to keep just the PEM cert
+ rm ssl/client-dn.csr ssl/temp.crt
+
+# Another client certificate, signed by the client CA. This one is revoked.
+ssl/client-revoked.crt: ssl/client-revoked.key ssl/client_ca.crt client.config
+ openssl req -new -key ssl/client-revoked.key -out ssl/client-revoked.csr -config client.config
+ openssl ca -name client_ca -batch -out ssl/temp.crt -config cas.config -infiles ssl/client-revoked.csr
+ openssl x509 -in ssl/temp.crt -out ssl/client-revoked.crt # to keep just the PEM cert
+ rm ssl/client-revoked.csr ssl/temp.crt
+
+# Convert the key to DER, to test our behaviour there too
+ssl/client-der.key: ssl/client.key
+ openssl rsa -in ssl/client.key -outform DER -out ssl/client-der.key
+
+# Convert the existing key to encrypted PEM (X.509 text) and DER (X.509 ASN.1) formats
+# to test libpq's support for the sslpassword= option.
+ssl/client-encrypted-pem.key: ssl/client.key
+ openssl rsa -in ssl/client.key -outform PEM -aes128 -passout 'pass:dUmmyP^#+' -out ssl/client-encrypted-pem.key
+
+ssl/client-encrypted-der.key: ssl/client.key
+ openssl rsa -in ssl/client.key -outform DER -aes128 -passout 'pass:dUmmyP^#+' -out ssl/client-encrypted-der.key
+
+# Root certificate files that contains both CA certificates, for testing
+# that multiple certificates can be used.
+ssl/both-cas-1.crt: ssl/root_ca.crt ssl/client_ca.crt ssl/server_ca.crt
+ cat $^ > $@
+
+# The same, but the certs are in different order
+ssl/both-cas-2.crt: ssl/root_ca.crt ssl/server_ca.crt ssl/client_ca.crt
+ cat $^ > $@
+
+# A root certificate file for the client, to validate server certs.
+ssl/root+server_ca.crt: ssl/root_ca.crt ssl/server_ca.crt
+ cat $^ > $@
+
+# and for the server, to validate client certs
+ssl/root+client_ca.crt: ssl/root_ca.crt ssl/client_ca.crt
+ cat $^ > $@
+
+ssl/client+client_ca.crt: ssl/client.crt ssl/client_ca.crt
+ cat $^ > $@
+
+#### CRLs
+
+ssl/client.crl: ssl/client-revoked.crt
+ openssl ca -config cas.config -name client_ca -revoke ssl/client-revoked.crt
+ openssl ca -config cas.config -name client_ca -gencrl -out ssl/client.crl
+
+ssl/server.crl: ssl/server-revoked.crt
+ openssl ca -config cas.config -name server_ca -revoke ssl/server-revoked.crt
+ openssl ca -config cas.config -name server_ca -gencrl -out ssl/server.crl
+
+ssl/root.crl: ssl/root_ca.crt
+ openssl ca -config cas.config -name root_ca -gencrl -out ssl/root.crl
+
+# If a CRL is used, OpenSSL requires a CRL file for *all* the CAs in the
+# chain, even if some of them are empty.
+ssl/root+server.crl: ssl/root.crl ssl/server.crl
+ cat $^ > $@
+ssl/root+client.crl: ssl/root.crl ssl/client.crl
+ cat $^ > $@
+
+ssl/root+server-crldir: ssl/server.crl ssl/root.crl
+ mkdir ssl/root+server-crldir
+ cp ssl/server.crl ssl/root+server-crldir/`openssl crl -hash -noout -in ssl/server.crl`.r0
+ cp ssl/root.crl ssl/root+server-crldir/`openssl crl -hash -noout -in ssl/root.crl`.r0
+
+ssl/root+client-crldir: ssl/client.crl ssl/root.crl
+ mkdir ssl/root+client-crldir
+ cp ssl/client.crl ssl/root+client-crldir/`openssl crl -hash -noout -in ssl/client.crl`.r0
+ cp ssl/root.crl ssl/root+client-crldir/`openssl crl -hash -noout -in ssl/root.crl`.r0
+
+ssl/server-crldir: ssl/server.crl
+ mkdir ssl/server-crldir
+ cp ssl/server.crl ssl/server-crldir/`openssl crl -hash -noout -in ssl/server.crl`.r0
+
+ssl/client-crldir: ssl/client.crl
+ mkdir ssl/client-crldir
+ cp ssl/client.crl ssl/client-crldir/`openssl crl -hash -noout -in ssl/client.crl`.r0
+
+.PHONY: sslfiles-clean
+sslfiles-clean:
+ rm -f $(SSLFILES) ssl/client_ca.srl ssl/server_ca.srl ssl/client_ca-certindex* ssl/server_ca-certindex* ssl/root_ca-certindex* ssl/root_ca.srl ssl/temp_ca.crt ssl/temp_ca_signed.crt
+ rm -rf $(SSLDIRS)
+
+clean distclean maintainer-clean:
+ rm -rf tmp_check
+ rm -rf ssl/*.old ssl/new_certs_dir ssl/client*_tmp.key
+
+# Doesn't depend on $(SSLFILES) because we don't rebuild them by default
+check:
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
diff --git a/src/test/ssl/README b/src/test/ssl/README
new file mode 100644
index 0000000..84baa47
--- /dev/null
+++ b/src/test/ssl/README
@@ -0,0 +1,102 @@
+src/test/ssl/README
+
+SSL regression tests
+====================
+
+This directory contains a test suite for SSL support. It tests both
+client-side functionality, i.e. verifying server certificates, and
+server-side functionality, i.e. certificate authorization.
+
+CAUTION: The test server run by this test is configured to listen for
+TCP connections on localhost. Any user on the same host is able to
+log in to the test server while the tests are running. Do not run this
+suite on a multi-user system where you don't trust all local users!
+
+Running the tests
+=================
+
+NOTE: You must have given the --enable-tap-tests argument to configure.
+
+Run
+ make check
+or
+ make installcheck
+You can use "make installcheck" if you previously did "make install".
+In that case, the code in the installation tree is tested. With
+"make check", a temporary installation tree is built from the current
+sources and then tested.
+
+Either way, this test initializes, starts, and stops a test Postgres
+cluster that is accessible to other local users!
+
+Certificates
+============
+
+The test suite needs a set of public/private key pairs and certificates to
+run:
+
+root_ca
+ root CA, use to sign the server and client CA certificates.
+
+server_ca
+ CA used to sign server certificates.
+
+client_ca
+ CA used to sign client certificates.
+
+server-cn-only
+server-cn-and-alt-names
+server-single-alt-name
+server-multiple-alt-names
+server-no-names
+ server certificates, with small variations in the hostnames present
+ in the certificate. Signed by server_ca.
+
+server-ss
+ same as server-cn-only, but self-signed.
+
+server-password
+ same as server-cn-only, but password-protected.
+
+client
+ a client certificate, for user "ssltestuser". Signed by client_ca.
+
+client-revoked
+ like "client", but marked as revoked in the client CA's CRL.
+
+In addition, there are a few files that combine various certificates together
+in the same file:
+
+both-cas-1
+ Contains root_ca.crt, client_ca.crt and server_ca.crt, in that order.
+
+both-cas-2
+ Contains root_ca.crt, server_ca.crt and client_ca.crt, in that order.
+
+root+server_ca
+ Contains root_crt and server_ca.crt. For use as client's "sslrootcert"
+ option.
+
+root+client_ca
+ Contains root_crt and client_ca.crt. For use as server's "ssl_ca_file".
+
+client+client_ca
+ Contains client.crt and client_ca.crt in that order. For use as client's
+ certificate chain.
+
+There are also CRLs for each of the CAs: root.crl, server.crl and client.crl.
+
+For convenience, all of these keypairs and certificates are included in the
+ssl/ subdirectory. The Makefile also contains a rule, "make sslfiles", to
+recreate them if you need to make changes.
+
+TODO
+====
+
+* Allow the client-side of the tests to be run on different host easily.
+ Currently, you have to manually set up the certificates for the right
+ hostname, and modify the test file to skip setting up the server. And you
+ have to modify the server to accept connections from the client host.
+
+* Test having multiple server certificates, so that the private key chooses
+ the certificate to present to clients. (And the same in the client-side.)
diff --git a/src/test/ssl/cas.config b/src/test/ssl/cas.config
new file mode 100644
index 0000000..8c0ef6d
--- /dev/null
+++ b/src/test/ssl/cas.config
@@ -0,0 +1,64 @@
+# This file contains the configuration for all the CAs.
+
+[ req ]
+prompt = no
+
+# Extensions for CA certs
+[ v3_ca ]
+basicConstraints = CA:true
+
+# Root CA, used to sign the certificates of the intermediary server and
+# client CAs.
+[ root_ca ]
+dir = ./ssl/
+database = ./ssl/root_ca-certindex
+serial = ./ssl/root_ca.srl
+default_md = sha256
+default_days= 10000
+default_crl_days= 10000
+certificate = ./ssl/root_ca.crt
+private_key = ./ssl/root_ca.key
+new_certs_dir = ./ssl/new_certs_dir
+policy = policy_match
+email_in_dn = no
+
+# CA used to sign all the server certificates.
+[ server_ca ]
+dir = ./ssl/
+database = ./ssl/server_ca-certindex
+default_md = sha256
+default_days= 10000
+default_crl_days= 10000
+certificate = ./ssl/server_ca.crt
+private_key = ./ssl/server_ca.key
+new_certs_dir = ./ssl/new_certs_dir
+serial = ./ssl/server_ca.srl
+policy = policy_match
+email_in_dn = no
+unique_subject = no
+crl = ./ssl/server.crl
+
+# CA used to sign all the client certificates.
+[ client_ca ]
+dir = ./ssl/
+database = ./ssl/client_ca-certindex
+default_md = sha256
+default_days= 10000
+default_crl_days= 10000
+certificate = ./ssl/client_ca.crt
+private_key = ./ssl/client_ca.key
+new_certs_dir = ./ssl/new_certs_dir
+serial = ./ssl/client_ca.srl
+policy = policy_match
+email_in_dn = no
+unique_subject = no
+crl = ./ssl/client.crl
+
+# This is common for all CAs.
+[ policy_match ]
+countryName = optional
+stateOrProvinceName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = optional
+emailAddress = optional
diff --git a/src/test/ssl/client-dn.config b/src/test/ssl/client-dn.config
new file mode 100644
index 0000000..ee2df54
--- /dev/null
+++ b/src/test/ssl/client-dn.config
@@ -0,0 +1,16 @@
+# An OpenSSL format CSR config file for creating a client certificate.
+#
+# The certificate is for user "ssltestuser-dn" with a multi-part DN
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+O = PGDG
+0.OU = Engineering
+1.OU = Testing
+CN = ssltestuser-dn
+
+# no extensions in client certs
+[ v3_req ]
diff --git a/src/test/ssl/client.config b/src/test/ssl/client.config
new file mode 100644
index 0000000..2e9d40d
--- /dev/null
+++ b/src/test/ssl/client.config
@@ -0,0 +1,13 @@
+# An OpenSSL format CSR config file for creating a client certificate.
+#
+# The certificate is for user "ssltestuser".
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = ssltestuser
+
+# no extensions in client certs
+[ v3_req ]
diff --git a/src/test/ssl/client_ca.config b/src/test/ssl/client_ca.config
new file mode 100644
index 0000000..ef93d59
--- /dev/null
+++ b/src/test/ssl/client_ca.config
@@ -0,0 +1,11 @@
+# An OpenSSL format CSR config file for creating the client root certificate.
+# This configuration file is also used when operating the CA.
+#
+# This certificate is used to sign client certificates. It is self-signed.
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = Test CA for PostgreSQL SSL regression test client certs
diff --git a/src/test/ssl/root_ca.config b/src/test/ssl/root_ca.config
new file mode 100644
index 0000000..187a9b8
--- /dev/null
+++ b/src/test/ssl/root_ca.config
@@ -0,0 +1,13 @@
+# A root certificate authority. The server and client CA's certificates
+# are signed by this root CA.
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = Test root CA for PostgreSQL SSL regression test suite
+
+# Extensions for CA certs
+[ v3_ca ]
+basicConstraints = CA:true
diff --git a/src/test/ssl/server-cn-and-alt-names.config b/src/test/ssl/server-cn-and-alt-names.config
new file mode 100644
index 0000000..6734251
--- /dev/null
+++ b/src/test/ssl/server-cn-and-alt-names.config
@@ -0,0 +1,25 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+# This certificate contains both a CN, and SANs.
+
+
+[ req ]
+distinguished_name = req_distinguished_name
+req_extensions = v3_req
+prompt = no
+
+[ req_distinguished_name ]
+# Note: According to RFC 2818 and 6125, the CN is ignored, when SANs are
+# present. In practice, the hostname that's put in the CN field is always
+# also listed as a SAN, but we intentionally don't do that here so that we
+# can test adherence to those RFCs.
+CN = common-name.pg-ssltest.test
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
+subjectAltName = @alt_names
+
+[ alt_names ]
+DNS.1 = dns1.alt-name.pg-ssltest.test
+DNS.2 = dns2.alt-name.pg-ssltest.test
diff --git a/src/test/ssl/server-cn-only.config b/src/test/ssl/server-cn-only.config
new file mode 100644
index 0000000..1e5d582
--- /dev/null
+++ b/src/test/ssl/server-cn-only.config
@@ -0,0 +1,13 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = common-name.pg-ssltest.test
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
diff --git a/src/test/ssl/server-multiple-alt-names.config b/src/test/ssl/server-multiple-alt-names.config
new file mode 100644
index 0000000..fe230df
--- /dev/null
+++ b/src/test/ssl/server-multiple-alt-names.config
@@ -0,0 +1,20 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+# This certificate contains multiple SANs, and no CN.
+
+[ req ]
+distinguished_name = req_distinguished_name
+req_extensions = v3_req
+prompt = no
+
+[ req_distinguished_name ]
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
+subjectAltName = @alt_names
+
+[ alt_names ]
+DNS.1 = dns1.alt-name.pg-ssltest.test
+DNS.2 = dns2.alt-name.pg-ssltest.test
+DNS.3 = *.wildcard.pg-ssltest.test
diff --git a/src/test/ssl/server-no-names.config b/src/test/ssl/server-no-names.config
new file mode 100644
index 0000000..2a71125
--- /dev/null
+++ b/src/test/ssl/server-no-names.config
@@ -0,0 +1,16 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+# This certificate contains no CN, nor SANs. Not very useful, but make
+# sure the client can handle it gracefully.
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
+
+[ alt_names ]
diff --git a/src/test/ssl/server-revoked.config b/src/test/ssl/server-revoked.config
new file mode 100644
index 0000000..47ef646
--- /dev/null
+++ b/src/test/ssl/server-revoked.config
@@ -0,0 +1,15 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+# This is identical to server-cn-only certificate, but this one is revoked
+# later.
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = common-name.pg-ssltest.test
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
diff --git a/src/test/ssl/server-single-alt-name.config b/src/test/ssl/server-single-alt-name.config
new file mode 100644
index 0000000..2b3ddf4
--- /dev/null
+++ b/src/test/ssl/server-single-alt-name.config
@@ -0,0 +1,18 @@
+# An OpenSSL format CSR config file for creating a server certificate.
+#
+# This certificate has a single SAN, and no CN.
+
+[ req ]
+distinguished_name = req_distinguished_name
+req_extensions = v3_req
+prompt = no
+
+[ req_distinguished_name ]
+OU = PostgreSQL test suite
+
+# For Subject Alternative Names
+[ v3_req ]
+subjectAltName = @alt_names
+
+[ alt_names ]
+DNS.1 = single.alt-name.pg-ssltest.test
diff --git a/src/test/ssl/server_ca.config b/src/test/ssl/server_ca.config
new file mode 100644
index 0000000..d6126d5
--- /dev/null
+++ b/src/test/ssl/server_ca.config
@@ -0,0 +1,11 @@
+# An OpenSSL format CSR config file for creating the server root certificate.
+# This configuration file is also used when operating the CA.
+#
+# This certificate is used to sign server certificates. It is self-signed.
+
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+CN = Test CA for PostgreSQL SSL regression test server certs
diff --git a/src/test/ssl/ssl/.gitignore b/src/test/ssl/ssl/.gitignore
new file mode 100644
index 0000000..af753d4
--- /dev/null
+++ b/src/test/ssl/ssl/.gitignore
@@ -0,0 +1,3 @@
+/*.old
+/new_certs_dir/
+/client*_tmp.key
diff --git a/src/test/ssl/ssl/both-cas-1.crt b/src/test/ssl/ssl/both-cas-1.crt
new file mode 100644
index 0000000..37ffa10
--- /dev/null
+++ b/src/test/ssl/ssl/both-cas-1.crt
@@ -0,0 +1,57 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIUEAgXJ/ibw6TVTUoomlBsPMfVTlMwDQYJKoZIhvcNAQEL
+BQAwQDE+MDwGA1UEAww1VGVzdCByb290IENBIGZvciBQb3N0Z3JlU1FMIFNTTCBy
+ZWdyZXNzaW9uIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYwNDE0MTM0
+MDU0WjBAMT4wPAYDVQQDDDVUZXN0IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NM
+IHJlZ3Jlc3Npb24gdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALZ81vKKBJlxgjwuNoK67I4IE9zfSLb0eHbgZwZxDVzdmFejARrHlWk3
++MK7Nav7RLSJ990am33zb58CTHc7YYVlBp07+PwLXzypqWkhYfok1OYYjyjCrFDs
+sjcJI3hRCZNEz+wYsG+tdYWJ+gRPQOWfh0YfO2rFgXAIMLiF6lyWzf1eOM+OjYrF
+/eyzwbMaJkkGa/AyZKz3wZiPq0jTuYLVmH4MK7MBOsUfSmsBsn/ohyRCQzM+ol0v
+Qlsrulj8usponRPDh9ng4PB5OSgR79YimQZnASQzJxiUvMADrKL5L6KwLxJlzbqY
+R0b5mLh8KBzBQmSh3Aj2e2I7Z17hdaMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEASzA7ApbuKn8lkC706gRL37a33yTZZ8rjZ4dnvCtq
+6OltlYDJ8IndotKbLH0SUEAxrvcaFnMt7AX9pRf2sGBKbY8zcxqPfsvzVehgx4Ea
+1RYksFW4h97jj1a1RKukTKuEOEEipbxwo0rLxfjvdaf2izqchJsLGtbocIZf0bD8
+djbE9jOLkx7saL08qC8ECrf9utsee+LJCsUYbNgYyIItEy6yVnmF/ICz93Utn1cI
+RfqZr1lM2Ia2LP9eDTmiuR9m+/MzkeRvvJHonNrRJHlcggtYHICvYioh9/jALBcm
+wZ+hTUePVqy4hOCBJ975CXjfKFN4MKQAdeB3EO5eBYAD3Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75x7yuQ1+gK8j
+1aO6D2nGym2x2OFniztlnx4PlWWWivIrYlxy6xAhfrVdjwjc5mMtOCrVKllsdC+S
+1EfqCZTu1+gF0SdG5cHuJ2Rtg4oisLSF221v/msPONAa1dObChWsJwme87VaFrL+
+B2yipfW1PUxM9a7/p19CRBcDQ+LNW+YFqwARByHGq1wfatJzpM8TXe+XEnRfW9KX
+P3a5PqR6evFQOzjcAf+QBJ0hAEddUDhdYECbs1GrApfsEHBuwXabdCH41j0F/0yc
+kctydWfBl2Vbmd3sfsFMHjde+SJhqxyq6xiSL59jnx4ZKmtn9VSOYbGmBCdBdYK7
+RTcnJQv9AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AB6zh/Jw+t232100Tztr7wJoKH8DL1hnSm3e7omdj0WlKfuZwTqDuMzB3H4LOSnS
+A00XpyMAGAJC6yRjS8pt+pjY5Jt6ouSqf6wNq0mF0jiIDeg1k/GNEjigx+0ITqbE
+lUJ56AcpoBNhOwBjOCRFh4JuspHZqHXgUNYTEicClbV+lZwoMIIK1e6FYRZDqMtL
++34GtZACImqvRkP5alqQg7hJUM1zbDVf2qebY4cfSu4OfTu6Og6KrL8Cu6bqR2et
+0a/TbthHYz1QGDYRoVTSP4uWoG9M1ZbsA/bNE2eqcrQj+dJ4AmIIr8Yl8mrwo/FZ
+SvgeLMlQY7UNwLUDtwy9QkI=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzZXJ2ZXIg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiSnYZbmc9vpCt
+Ku1sKV9l663JCceubhMw8Gg16kV0hXEFf/TgGC4zkiYNHN7+G45YD7Nq0kBCq3dH
+t2wPCc6c8pQoI64dfprVqPkvzoe1WBpZNetkUTk20v08jNeRa7XdRbRR6we1s9VG
+/prp8Hs2mmHqEfLuI9lvTT0Dz+VMmfFI8Lf278r+w+qOtVloAkX7AOyoLEJlNS0B
+QW9YWdH9N5ctaUXMG6lLV2OAjs+W1smpKfpIpMCA1lPGlElu70hynon/nQQvBP77
+SfQpZVc0esM18jkZpr5LEKUCw+x6LaMsqmBHpAULfCffxn2r0uMBW4L4VaGg3W6F
+h6iuJwRfAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AFlcKTaU/Ug3Q0hr3P1UQ6dWyK4aVn9rs4jvVfFl0a0RnbBowqK2C+zQVUWYTcjo
+KHREVje65goj6VzRB6ko/9mAQ6PZP8jRuRhfCmvmvSQ/mWdgPzSRsUh9MwgEm9c2
+vNbqwaznEU8cYZnLpHiR9O5S7/qWWxehjYtxk5Eb4J006YglYfHnhrRFJvPbiqlf
+IOEivZ7gIVfvaOTbLjmN2kLOnzdlwpXGjxxg4Nu9ZhXOhfrplzUvRfmqvVsDiHXb
+USIdX+OFZZqr64IKG4drT4K4Bt2wupOEyX4ZFsUXXd+Hgq83SWmV4wzflcpmGkLC
+JZ3CEMu8/WA5uQBXdQUozlE=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/both-cas-2.crt b/src/test/ssl/ssl/both-cas-2.crt
new file mode 100644
index 0000000..2f2723f
--- /dev/null
+++ b/src/test/ssl/ssl/both-cas-2.crt
@@ -0,0 +1,57 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIUEAgXJ/ibw6TVTUoomlBsPMfVTlMwDQYJKoZIhvcNAQEL
+BQAwQDE+MDwGA1UEAww1VGVzdCByb290IENBIGZvciBQb3N0Z3JlU1FMIFNTTCBy
+ZWdyZXNzaW9uIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYwNDE0MTM0
+MDU0WjBAMT4wPAYDVQQDDDVUZXN0IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NM
+IHJlZ3Jlc3Npb24gdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALZ81vKKBJlxgjwuNoK67I4IE9zfSLb0eHbgZwZxDVzdmFejARrHlWk3
++MK7Nav7RLSJ990am33zb58CTHc7YYVlBp07+PwLXzypqWkhYfok1OYYjyjCrFDs
+sjcJI3hRCZNEz+wYsG+tdYWJ+gRPQOWfh0YfO2rFgXAIMLiF6lyWzf1eOM+OjYrF
+/eyzwbMaJkkGa/AyZKz3wZiPq0jTuYLVmH4MK7MBOsUfSmsBsn/ohyRCQzM+ol0v
+Qlsrulj8usponRPDh9ng4PB5OSgR79YimQZnASQzJxiUvMADrKL5L6KwLxJlzbqY
+R0b5mLh8KBzBQmSh3Aj2e2I7Z17hdaMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEASzA7ApbuKn8lkC706gRL37a33yTZZ8rjZ4dnvCtq
+6OltlYDJ8IndotKbLH0SUEAxrvcaFnMt7AX9pRf2sGBKbY8zcxqPfsvzVehgx4Ea
+1RYksFW4h97jj1a1RKukTKuEOEEipbxwo0rLxfjvdaf2izqchJsLGtbocIZf0bD8
+djbE9jOLkx7saL08qC8ECrf9utsee+LJCsUYbNgYyIItEy6yVnmF/ICz93Utn1cI
+RfqZr1lM2Ia2LP9eDTmiuR9m+/MzkeRvvJHonNrRJHlcggtYHICvYioh9/jALBcm
+wZ+hTUePVqy4hOCBJ975CXjfKFN4MKQAdeB3EO5eBYAD3Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzZXJ2ZXIg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiSnYZbmc9vpCt
+Ku1sKV9l663JCceubhMw8Gg16kV0hXEFf/TgGC4zkiYNHN7+G45YD7Nq0kBCq3dH
+t2wPCc6c8pQoI64dfprVqPkvzoe1WBpZNetkUTk20v08jNeRa7XdRbRR6we1s9VG
+/prp8Hs2mmHqEfLuI9lvTT0Dz+VMmfFI8Lf278r+w+qOtVloAkX7AOyoLEJlNS0B
+QW9YWdH9N5ctaUXMG6lLV2OAjs+W1smpKfpIpMCA1lPGlElu70hynon/nQQvBP77
+SfQpZVc0esM18jkZpr5LEKUCw+x6LaMsqmBHpAULfCffxn2r0uMBW4L4VaGg3W6F
+h6iuJwRfAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AFlcKTaU/Ug3Q0hr3P1UQ6dWyK4aVn9rs4jvVfFl0a0RnbBowqK2C+zQVUWYTcjo
+KHREVje65goj6VzRB6ko/9mAQ6PZP8jRuRhfCmvmvSQ/mWdgPzSRsUh9MwgEm9c2
+vNbqwaznEU8cYZnLpHiR9O5S7/qWWxehjYtxk5Eb4J006YglYfHnhrRFJvPbiqlf
+IOEivZ7gIVfvaOTbLjmN2kLOnzdlwpXGjxxg4Nu9ZhXOhfrplzUvRfmqvVsDiHXb
+USIdX+OFZZqr64IKG4drT4K4Bt2wupOEyX4ZFsUXXd+Hgq83SWmV4wzflcpmGkLC
+JZ3CEMu8/WA5uQBXdQUozlE=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75x7yuQ1+gK8j
+1aO6D2nGym2x2OFniztlnx4PlWWWivIrYlxy6xAhfrVdjwjc5mMtOCrVKllsdC+S
+1EfqCZTu1+gF0SdG5cHuJ2Rtg4oisLSF221v/msPONAa1dObChWsJwme87VaFrL+
+B2yipfW1PUxM9a7/p19CRBcDQ+LNW+YFqwARByHGq1wfatJzpM8TXe+XEnRfW9KX
+P3a5PqR6evFQOzjcAf+QBJ0hAEddUDhdYECbs1GrApfsEHBuwXabdCH41j0F/0yc
+kctydWfBl2Vbmd3sfsFMHjde+SJhqxyq6xiSL59jnx4ZKmtn9VSOYbGmBCdBdYK7
+RTcnJQv9AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AB6zh/Jw+t232100Tztr7wJoKH8DL1hnSm3e7omdj0WlKfuZwTqDuMzB3H4LOSnS
+A00XpyMAGAJC6yRjS8pt+pjY5Jt6ouSqf6wNq0mF0jiIDeg1k/GNEjigx+0ITqbE
+lUJ56AcpoBNhOwBjOCRFh4JuspHZqHXgUNYTEicClbV+lZwoMIIK1e6FYRZDqMtL
++34GtZACImqvRkP5alqQg7hJUM1zbDVf2qebY4cfSu4OfTu6Og6KrL8Cu6bqR2et
+0a/TbthHYz1QGDYRoVTSP4uWoG9M1ZbsA/bNE2eqcrQj+dJ4AmIIr8Yl8mrwo/FZ
+SvgeLMlQY7UNwLUDtwy9QkI=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client+client_ca.crt b/src/test/ssl/ssl/client+client_ca.crt
new file mode 100644
index 0000000..2804527
--- /dev/null
+++ b/src/test/ssl/ssl/client+client_ca.crt
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIICzDCCAbQCAQEwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IGNsaWVudCBjZXJ0czAe
+Fw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBYxFDASBgNVBAMMC3NzbHRl
+c3R1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtIugLqHywEAE
+vyRZGMVAkdk1zCa5FFaPOEFhHiAMpwFOEIEi4Svk9kSSRecmeJcody1sLNoFqtTA
+b5tYaDoGIVZfc8/kxm8sbsTE/3JOsON3CMqjOQkI1ZKjDSF1gtrGSmatgjqsMnlP
+UJkFEsPhFg6NTf1ZUjFiQeWEli0fQJ2/k+7MI4S0t0pDJJJWrqF4l6eSgu8rsBoX
+XHy4OLAz6j23r2k5FZs6H/poII95ia+E8hG8SrJmMa88naRdq7hHW802Z6lEhnRW
+ND+tDGjt0ZaTfxx+CxN4UjgbboOJifTykVHjuzBR1+IzLHcxoZCLP1cjadSqMz5b
+ziJTGtHzYwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAcIGps6BnsRxkN5sphg6GK
+tzDvp2IUyOu5oeAHdJLT5JFZhKKzhDD4KiOv+XWzdHcSAl3xMqAqnFdSTCt2vtc+
+rk04eyVWJALyf6oPT60Vn5sFaaxlTg1+tnZMCCycDxM6lc/6onzgp6DUWGozlgSh
+eNgCyaNU73VTuMgd+s/QrZ5HCr0OPAb3aWRQy7hVZeOniNBXWrO/CC2Swfwz7jU3
+dvLAWYENUvZlE2S7HnQGclGIJb38qFCnquuSgmO9yT30Lmmwp33k5/evN9cNQMxU
+c4ChYCaabOGXUaBJNzJAYMEUHh+o+LPgFF2iB0mL7FAUip9XsjOiOwcrbusM/g+2
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75x7yuQ1+gK8j
+1aO6D2nGym2x2OFniztlnx4PlWWWivIrYlxy6xAhfrVdjwjc5mMtOCrVKllsdC+S
+1EfqCZTu1+gF0SdG5cHuJ2Rtg4oisLSF221v/msPONAa1dObChWsJwme87VaFrL+
+B2yipfW1PUxM9a7/p19CRBcDQ+LNW+YFqwARByHGq1wfatJzpM8TXe+XEnRfW9KX
+P3a5PqR6evFQOzjcAf+QBJ0hAEddUDhdYECbs1GrApfsEHBuwXabdCH41j0F/0yc
+kctydWfBl2Vbmd3sfsFMHjde+SJhqxyq6xiSL59jnx4ZKmtn9VSOYbGmBCdBdYK7
+RTcnJQv9AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AB6zh/Jw+t232100Tztr7wJoKH8DL1hnSm3e7omdj0WlKfuZwTqDuMzB3H4LOSnS
+A00XpyMAGAJC6yRjS8pt+pjY5Jt6ouSqf6wNq0mF0jiIDeg1k/GNEjigx+0ITqbE
+lUJ56AcpoBNhOwBjOCRFh4JuspHZqHXgUNYTEicClbV+lZwoMIIK1e6FYRZDqMtL
++34GtZACImqvRkP5alqQg7hJUM1zbDVf2qebY4cfSu4OfTu6Og6KrL8Cu6bqR2et
+0a/TbthHYz1QGDYRoVTSP4uWoG9M1ZbsA/bNE2eqcrQj+dJ4AmIIr8Yl8mrwo/FZ
+SvgeLMlQY7UNwLUDtwy9QkI=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client-crldir/9bb9e3c3.r0 b/src/test/ssl/ssl/client-crldir/9bb9e3c3.r0
new file mode 100644
index 0000000..a667680
--- /dev/null
+++ b/src/test/ssl/ssl/client-crldir/9bb9e3c3.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/client-der.key b/src/test/ssl/ssl/client-der.key
new file mode 100644
index 0000000..c9be5f9
--- /dev/null
+++ b/src/test/ssl/ssl/client-der.key
Binary files differ
diff --git a/src/test/ssl/ssl/client-dn.crt b/src/test/ssl/ssl/client-dn.crt
new file mode 100644
index 0000000..f2f6a62
--- /dev/null
+++ b/src/test/ssl/ssl/client-dn.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAe4CAQEwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IGNsaWVudCBjZXJ0czAe
+Fw0yMTAzMDUyMDUyNDVaFw00ODA3MjEyMDUyNDVaMFAxDTALBgNVBAoMBFBHREcx
+FDASBgNVBAsMC0VuZ2luZWVyaW5nMRAwDgYDVQQLDAdUZXN0aW5nMRcwFQYDVQQD
+DA5zc2x0ZXN0dXNlci1kbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AMRLriq2Sh8+N4bhVtRUp/MAEsLQK6u/GotMSmiSr9K31YBYOvNzw8liKt4Rmnh5
+zmsdXJBW8erPNpkUAy9tFRCAx0YobhWCSfyX3orEdrhDrLFihA62zXQC69T0u4Yp
+PSXGd0yCAcOZERQ4CQVgqnsh7Kmx5QaQnqxaz4OVPArWFJP4RQBT/l+r+kCeAn6h
+qvbSbxY3FoCElQq0EF5x1F2pjL+HcBvjeI+GP430gVeJJX0RaG14Fp4v9MQT6zv/
+gvvjHC8l7YSJUROjeUzLZpUnj/ik4yrtT4av/TDGTSOpGs5qEATqk4hxAUEWw6TJ
+RoLh3Oq2N5KuzDmKBBskLX0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAL2H54oyx
+pNkcgFF79lwc4c/Jda7j0wrZQIw5CWwO0MdCozJGRIEAA5WXA8b5THo1ZkaWv+sh
+lWnCOflBtGnEpD7dUpMW9lxGL5clMeMf3CoNYBb7zBofm+oTJytCzXHNftB4hCZj
+pvN79bNT4msWbmxDyi75nfbEfzK1BKnfCg+DWBBjEnHC8VzgDq6ACN6FEoyFb+fr
+dlDoof+S7k8jYAzhxwySI5DnMzr9OIwnepWfx9HENsasAighc8vFSEouShvsOlYS
+L0OIb9Tn6M5q1tWoLHulQsQYDPzaO/1M7ubsr5xCx1ReDK4gaNwS3YXn/2KE9Kco
+aKCrL89AjQrJPA==
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client-dn.key b/src/test/ssl/ssl/client-dn.key
new file mode 100644
index 0000000..1d67ef0
--- /dev/null
+++ b/src/test/ssl/ssl/client-dn.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAxEuuKrZKHz43huFW1FSn8wASwtArq78ai0xKaJKv0rfVgFg6
+83PDyWIq3hGaeHnOax1ckFbx6s82mRQDL20VEIDHRihuFYJJ/JfeisR2uEOssWKE
+DrbNdALr1PS7hik9JcZ3TIIBw5kRFDgJBWCqeyHsqbHlBpCerFrPg5U8CtYUk/hF
+AFP+X6v6QJ4CfqGq9tJvFjcWgISVCrQQXnHUXamMv4dwG+N4j4Y/jfSBV4klfRFo
+bXgWni/0xBPrO/+C++McLyXthIlRE6N5TMtmlSeP+KTjKu1Phq/9MMZNI6kazmoQ
+BOqTiHEBQRbDpMlGguHc6rY3kq7MOYoEGyQtfQIDAQABAoIBABqL3Zb7JhUJlfrQ
+uKxocnojdWYRPwawBof2Hk38IHkP0XjU9cv8yOqQMxnrKYfHeUn1I5KFn5vQwCJ9
+mVytlN6xe8GaMCEKiLT3WOpNXXzX8h/fIdrXj/tzda9MFZw0MYfNSk73egOYzL1+
+QoIOq5+RW+8rFr0Hi93lPhEeeotAYWDQgx9Ye/NSW6vK2m47hdBKf9SBsWs+Vafa
+mC9Bf4LQqRYSJZee1zDwIh+Om7/JTsjMZYU0/lpycRz7V5uHbamXKlOXF54ow3Wn
+CJ9eVVWo7sb3CaeJ0p2sHIFp89ybMQ2vvmNr6aJNtZWd5WYxsjKs40rVq6DiUlFn
+T6CK7uECgYEA/Ks4/OnZnorhaHwYTs0LqiPSM7oZw4qchCNDMoE3WngsaZoWUKmr
+2JTY6uYP/B+oWgwPBdDiPRDeGqtVNZSAVsZEDMbiqZxwHaLi9OKJ7sKgK8Q6ANV1
+q5qgH1yXXygWhlol/Nf9bbnGWWoN+33zvnADeKRcT/1gZLEQpJ46DHUCgYEAxuIx
+k/EOOT9kyC5WrBDY3l7veb/WGRQgXTXiCJaO4d7IYh8UpUXlg0ZYF4RfeKRsSd07
+n9QdW6ImrtDloNyG6HnDknYsPRUs8JcuuyrxaOsZ/p9LS76ItNV7gzREf4N/7jrD
+c6TJappgXm+dgXg6ENuyk05hzjT6qdvm9V80m+kCgYEA7kfXRYSP61lT/AJTtjTf
+FEQV3xxZYbRdqKvMmluLxTDhyXE8LDPm0SiGbPgsCPwd+1W18SktwqMeoo4DnLUA
+V1VBJb+GUKgsf3Z2jLT7mYRIIx46CUFFaGE5MnpScrXOkEOB4bIb2RfCu94tc4gz
+jtv6GhL+z5zHBA6MAIMLgWUCgYAlynNLPkHKpP4cf5mehnD/CCEPDGG9UDK6I3P4
+18r8pl2DL463vOlYoXQ5u8B8ZxngizY6L48Ii244R59qipzj7cc4vFW5oZ1xdfi+
+PfGzUwEUfeZL1T+axPn8O2FMrYsQlH/xKH3RUNZA+4p9QIAgFe7/yKQTD8QVpKBl
+PZr8iQKBgBjdrgMt1Az98ECXJCjM4uui2S9UenNQVmhmxgZUpHqfNk+WEvIIthDi
+FEJPSTHyhTI9XIrhhwNkW3UZMjMndAiNylXGfJdr/xGwLM57t5HhGgljSboV7Mnw
+RFnh2FZxa3i/8g+4lAPZNwU0W/JU46wgg4C2Eu/Ne7jA8XUXYu9t
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/client-encrypted-der.key b/src/test/ssl/ssl/client-encrypted-der.key
new file mode 100644
index 0000000..c9be5f9
--- /dev/null
+++ b/src/test/ssl/ssl/client-encrypted-der.key
Binary files differ
diff --git a/src/test/ssl/ssl/client-encrypted-pem.key b/src/test/ssl/ssl/client-encrypted-pem.key
new file mode 100644
index 0000000..1e7052a
--- /dev/null
+++ b/src/test/ssl/ssl/client-encrypted-pem.key
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,E619306A930B60F360BF805500BA5659
+
+B9aYmIdIoF7hT9tJARMQWE7Ii7g+KDNaF4U0ljBsxgbtMyi9DQrlrFsbUO0Wy6iO
+UY/h57UA1pk7yF+rwkTK0L2t0j/d+HZc3ddsN3cZ040PmX8+8QZJWRUs2ywTLa4O
+JxPm2rUxLSeVa+FY9Nr1Cl6meQ2JS7MA7KBNuriBWNleGGgkbBMaH7zq98aOJmaz
+l02J2wrJ5STP2UI8uEaT/UtAgLInlAljCSg5oe5cj4u9UyUkRN7fj4mexq1r5YNU
+zTu7GrgcAdXrhsAhg9mAJol4frwsQuEiJbVIurAAvCrJk7Gm8xVjKCN1stDOASAY
+aawO1huIdTzjbGXFHBtJ4YuRClXZr5ij6kN+KeQaS+JLjehsAb6762l9wUPP5Bxv
+8c6CCxc+U4ndN0ZQPsx0UrJ/AYO1s12mebuKZvIdNoYdLIqJLfX/HSrzaXw6XA8b
+gAvVOruKGq12v71OrIdahxSzRs7s6GODGynSayFprn3CK+GZJumwQ0EK+fBzrzB1
+8JTp98qwMYfSuDmGl8VbT9k8OZFZbDD4k5wj8fHx5R4zkdgfNqBNAKXPrwm5uRT8
++0mnYdP3ZnihnZnAoZvGXOE77TcZ/N9fLvwkBpwPmtftbn10HwlwXQgmn1ijMj60
+ZOYo1fvKJMmvCr+NUtyJALIvUdLQmjWx0PoZetIb24KBkTkr2ciU1d1RDEwOfffZ
+jwTfcJU/AXnxPBR6MBT9a+YkaMiOU0JF7vs/x0hG/o8GsXQJB/G7Vzakg0hxQ1WF
+KU0jInXPf2uCiBMEwuWRPHh25wspLjsHgt5pD55vE/M9Q7LFOez/9/RQqmmjDjZH
+sLJtdAjN57aaIhtzbYIYa7K7Eu5v0NrZ5++wP3h82aTy9PIlSmRGY8WiZSDDir0P
+w+PBP7JN/3ifqXURUmSDGbfdArbyuuF79Say6N9ijFeBAZrCgauw3jBs1dhusGJ/
+T6wh8mjdGf8SRm9SQdGuIyK7M657z3P0WRlpHN4beeGpzgGVexqjiyvtwQNH8kps
+3EDNwTe3HJMWf7G2FNjqtM0h3fnaB7d+prfzZIL5Y1Somgfiljp7zG/FfkYEybK6
+8OvW6O8byCSqJzugUa5HCv//iPYFrcALAXtva4KXtfauGhKmWpn3Wa5AW9/034H6
+QW/A8mcKSMKhGixZj5MZKGTMA9cRus3IRTAYnhCd5njJ1N/o67wwTGVuXVu6ExrM
+wY/WjkRrDlRopqo0U3wodHjfZ8/837rINwmcqzXTxasu+ApWUVZFuuQh/q3i8aTv
+BzFVOfLylxpIsoQHBQvNdM/u0HGXbw7wyjs6n+LCjeGwRuxKkoYlKf5cItNLDNvF
+6LYwA44BJ3/XfUSVZRD8PAVp5haUgpesPym1G5QdvYN4rWE6lsAtGSZDatWvaCsI
+S0qTwLFbw9BvclwkvJicvLwAmKiGMDyAwGNCPLnG7nZ48to4dXD93LmgC/mnENbp
+7EgW7fUtMvz0Lt2Xcd26ZTlJdOkT3sdKPSDxhgqsQoI4dQSmB4Fz40HsFvFtTCuF
+FXMFXjSkjiKrdfI+CQ1tJGXKpYAod8PcZ89vN3TjxehwhK6GxS0CiOJ+phh6q22i
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/client-revoked.crt b/src/test/ssl/ssl/client-revoked.crt
new file mode 100644
index 0000000..14857a3
--- /dev/null
+++ b/src/test/ssl/ssl/client-revoked.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICzDCCAbQCAQIwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IGNsaWVudCBjZXJ0czAe
+Fw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBYxFDASBgNVBAMMC3NzbHRl
+c3R1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoBcmY2Z+qa+l
+UB5YSYnGLt96S7axkoDvIzLJkwJugGqw1U72A6lAUTyAPVntsmbhoMpDEHK6ylg8
+U4HC3L1hbhSpFriTITJ3TzH4+wdDH1KZYlM2k0gfrKrksJyZ7ftAyuBvzBRlFbBe
+xopR9VQjqgAuNKByJswldOe0KwP0nmb/TtT9lkAt7XjrSut5MUezFVnvTxabm7tQ
+ciDG+8QqE0b8lH3N3VOXWZWCeXPRrwboO3baAmcue4V20N0ALARP+QZNElBa7Jq+
+l77VNjneRk07jjaE7PCGVlWfPggppZos1Ay1sb2JhK0S9pZrynQT/ck3qhG4QuKp
+cmn/Bbe/8wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBySTwOO9zSFCtfRjbbblDx
+AK2ttILR0ZJXnvzjNjuErsT9qeXaq2t/iG/vmhH5XDjaefXFLCLqFunvcg6cIz1A
+HhAw+JInfyk3TUpDaX6M0X8qj184e4kXzVc83Afa3LiP5JkirzCSv6ErqAHw2VVd
+bZbZUwMfQLpWHVqXK89Pb7q791H4VeEx9CLxtZ2PSr2GCdpFbVMJvdBPChD2Re1A
+ELcbMZ9iOq2AUN/gxrt7HnE3dRoGQk6AJOfvhi2eZcVWiLtITScdPk1nYcNxGid3
+BWW+tdLbjmSe2FXNfDwBTvuHh5A9S399X5l/nLAng2iTGSvIm1OgUnC2oWsok3EI
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client-revoked.key b/src/test/ssl/ssl/client-revoked.key
new file mode 100644
index 0000000..a915c6f
--- /dev/null
+++ b/src/test/ssl/ssl/client-revoked.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAoBcmY2Z+qa+lUB5YSYnGLt96S7axkoDvIzLJkwJugGqw1U72
+A6lAUTyAPVntsmbhoMpDEHK6ylg8U4HC3L1hbhSpFriTITJ3TzH4+wdDH1KZYlM2
+k0gfrKrksJyZ7ftAyuBvzBRlFbBexopR9VQjqgAuNKByJswldOe0KwP0nmb/TtT9
+lkAt7XjrSut5MUezFVnvTxabm7tQciDG+8QqE0b8lH3N3VOXWZWCeXPRrwboO3ba
+Amcue4V20N0ALARP+QZNElBa7Jq+l77VNjneRk07jjaE7PCGVlWfPggppZos1Ay1
+sb2JhK0S9pZrynQT/ck3qhG4QuKpcmn/Bbe/8wIDAQABAoIBAQCVmUx8MrlGZCa9
+Gb4y6hZSku87dXu2hdnyMHGBeRI92nVov6LRhQXfZAQKUND4l39cu+WzpyK6F344
+ItgvYqF7Nr9TxiNnMDuhu/cIzZ6B1LQU1+H1+73toryV9aE6bEH904FlWeGkRO4r
+5fH0qS2ynPyQnSZO7xJJjoQkdkvPAMId7ovA5kKRLqRbXORGkbHhDdzoBB5ogRmV
+CInIfO7mI85OJXXtggPNb7L9Tmb39/i+D/pagIWehzb9WOSnMnJ6//ORkEntqEOl
+yaalJVF7uhiQbMcqA+ZJN9WwQPeLOeYowGD48cCsdjCgOhxM0EVWhtkDoC5MeZSz
+0XQ7vrwxAoGBANFVznbReMP914AtDDY3ISrtsU3AZVuTpfi19+jogTOHZakt0ntt
+Ztaymh0CBcE1DSbSdPLLtVpyhkvfmZRRIzv48xV2LHRibVkx5hncXQRrm+85B2vh
+PMJ1/CO5Rky6DOq6RXWEbHKv56ZPUKeaokJsusUgafKkM8DpWDz5Re6VAoGBAMPH
+FBRrTIL6N8vv4IRmCBk8axmAtbAKOcSghSLtGi8oX4wgL0nltoW28aE4uNiLb7Dh
+vDOqluhc6ejaI6tCSo1+f1JSsiCvieFfRR76I0AQCGtdKZTu7hfxT+GQURm09iYX
+T06VqIfpTOgQ6O6ArYSF+nF1DxrzUJdVpywxqzpnAoGBANAiWaMHyORN2lul7pNl
+IwQ0yuo8lkqENixgePpJWlTqlWitl66C6xIjCFo5LZGZdtcXv5G8ezdP0TlVO7Ud
+K0Qw1TiMg8zAJGrf0yH5WT7Q43zqHffkPe43Mxgt2bjl73ve8rrSjKVHQrK3/8B1
+XklfJCBlhxHqs05mdAZD7oU1AoGAeD6BurjcWWXNd1hxkWAJgVZ2gUdoUCM3r+jX
+XMg72NL3PF1YLg8Et8PRTLBF99pMU1uR+DnCTh0jHX09gyZIG/ehw7I+7YxjJyUY
+kxoXJHW0dhzWOT82xUXVRjkZVqyqsmKGt0F8LV3BepdIOZSW/lo7pAu9p1PiH9Df
+yGkJPekCgYEAneTtCsznABsSw/5E2kq3fWQWZ+N9IIHQCNor4YnEWLiTe7Btexqv
++joMPnKWCZ9DqzgltmcNN4r/2nkNdJ9KJwlwkp6bKl9AnDSdSWuXUsxB8pecGylo
+cD4WMBUQqd2IEI8678Pr9fOHA97YzTF87HfBGcsW/g25dzfOfb8A0YE=
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/client.crl b/src/test/ssl/ssl/client.crl
new file mode 100644
index 0000000..a667680
--- /dev/null
+++ b/src/test/ssl/ssl/client.crl
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/client.crt b/src/test/ssl/ssl/client.crt
new file mode 100644
index 0000000..4d0a6ef
--- /dev/null
+++ b/src/test/ssl/ssl/client.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICzDCCAbQCAQEwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IGNsaWVudCBjZXJ0czAe
+Fw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBYxFDASBgNVBAMMC3NzbHRl
+c3R1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtIugLqHywEAE
+vyRZGMVAkdk1zCa5FFaPOEFhHiAMpwFOEIEi4Svk9kSSRecmeJcody1sLNoFqtTA
+b5tYaDoGIVZfc8/kxm8sbsTE/3JOsON3CMqjOQkI1ZKjDSF1gtrGSmatgjqsMnlP
+UJkFEsPhFg6NTf1ZUjFiQeWEli0fQJ2/k+7MI4S0t0pDJJJWrqF4l6eSgu8rsBoX
+XHy4OLAz6j23r2k5FZs6H/poII95ia+E8hG8SrJmMa88naRdq7hHW802Z6lEhnRW
+ND+tDGjt0ZaTfxx+CxN4UjgbboOJifTykVHjuzBR1+IzLHcxoZCLP1cjadSqMz5b
+ziJTGtHzYwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAcIGps6BnsRxkN5sphg6GK
+tzDvp2IUyOu5oeAHdJLT5JFZhKKzhDD4KiOv+XWzdHcSAl3xMqAqnFdSTCt2vtc+
+rk04eyVWJALyf6oPT60Vn5sFaaxlTg1+tnZMCCycDxM6lc/6onzgp6DUWGozlgSh
+eNgCyaNU73VTuMgd+s/QrZ5HCr0OPAb3aWRQy7hVZeOniNBXWrO/CC2Swfwz7jU3
+dvLAWYENUvZlE2S7HnQGclGIJb38qFCnquuSgmO9yT30Lmmwp33k5/evN9cNQMxU
+c4ChYCaabOGXUaBJNzJAYMEUHh+o+LPgFF2iB0mL7FAUip9XsjOiOwcrbusM/g+2
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client.key b/src/test/ssl/ssl/client.key
new file mode 100644
index 0000000..21e1e9f
--- /dev/null
+++ b/src/test/ssl/ssl/client.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAtIugLqHywEAEvyRZGMVAkdk1zCa5FFaPOEFhHiAMpwFOEIEi
+4Svk9kSSRecmeJcody1sLNoFqtTAb5tYaDoGIVZfc8/kxm8sbsTE/3JOsON3CMqj
+OQkI1ZKjDSF1gtrGSmatgjqsMnlPUJkFEsPhFg6NTf1ZUjFiQeWEli0fQJ2/k+7M
+I4S0t0pDJJJWrqF4l6eSgu8rsBoXXHy4OLAz6j23r2k5FZs6H/poII95ia+E8hG8
+SrJmMa88naRdq7hHW802Z6lEhnRWND+tDGjt0ZaTfxx+CxN4UjgbboOJifTykVHj
+uzBR1+IzLHcxoZCLP1cjadSqMz5bziJTGtHzYwIDAQABAoIBAA7mqzzODvwBDKM9
++8CInzCqbb9AvuvHzSBGfR6AZKrv96JzFg7hkY8lz7DHSCyRxTw42oHFKMyVrKBJ
+gP1xNIpR16T2VppuGIu33855f7cnvu5R0zDk5v7BkIWH6mv3ZIBFgzKJZybvTjWH
+u5x14EDyyITUUSfwfXyU1eGTLc4mU01g4kArSDy7dqWi9xrixfaiTH+bbfmoE96v
+6kiwICZuoYaBLwOi9e7iHenhpF9X+BHNgt+x4dO5FSTtb15G96CnTM1U8xN2rf6y
+pfwkWH0NoeeTvuGvzfFgQMVxk/72VtM21rntGA4z6ig7xHKZLJ2mFSb29/uISZKv
+P1igV5ECgYEA6J2J5vPYLpXGmwthICaPiVSShUfZpZ05w+/p5KmFwtuyENSTtD+0
+nr/TY3mQNqecDTZsN5lillqnlZcAXVFce9A6iyQuIYz1FwO6K+mQLDshl7sXRNrK
+AeThubltaieOtSXbeji8kmmEK95tO//Y7DNjLVn8gZ4Q2hOT97e8hCsCgYEAxrIK
+/RWqU94JuGwJFzUDpgaJYQG5rcc+J0cZejjFl5ppY0+DPMNBKrGaObUrXAPmWBS9
+Gm4qBN3Zd1F8qEnHF+dw5vZY5hcvANcKRqXiPUkdzmpBNtlb/E+bGIEmhlh96gxN
+AKQEPh2UM+Gc4eDfFUgfLnmqTLfPOSzpCXejmakCgYEAyZVMnoKOw8A0PsSbxNrl
+5OMPnsTnTmh0WOKeVPS74GO3anJuFfRnOHOQY1JDsbmKuMCDA6O/FgE13aLgQ/5w
+ITQQp+gQui6Hbwxh2BAuSsZrlCwkPB1GlmGdY+/Xa/kf6MgH7WEhudgLHGFDVI2h
+lP/rYK/s7P7oJ7RztGbbzcUCgYBzZ9wMDXZlyfRZYp6RFSCuYOOQLYFcVvpZs+kv
+XSQfHveRUBCIzVvfYVKTrA+oHTe/9yOy40OSmgyCShkeYeO6lZm0/Ga8FcEeOshk
+KltSf1JJntuL8QmFbfNGc1Ud+O4Bb+2Vrq4sKd/3llYZuBO6d65svwvUDXrV2ajs
+78ldKQKBgAZROsYDYkdwBJmKCipRAwp7qS67zUpGSzjnDdswa0S6ECMcbx46qhcc
+IvFx/2rjLDIZUVjXkt/U9phWIAq/xMd0Euk+zvIdMmiaJeAmT8DzxVyM4iHGWbuY
+qWpoSLJe8d+xDrHkQZHh+Pb4CpJwRNs3c0MGY3+i/PPTjxq4em8p
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/client_ca.crt b/src/test/ssl/ssl/client_ca.crt
new file mode 100644
index 0000000..1ef3771
--- /dev/null
+++ b/src/test/ssl/ssl/client_ca.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75x7yuQ1+gK8j
+1aO6D2nGym2x2OFniztlnx4PlWWWivIrYlxy6xAhfrVdjwjc5mMtOCrVKllsdC+S
+1EfqCZTu1+gF0SdG5cHuJ2Rtg4oisLSF221v/msPONAa1dObChWsJwme87VaFrL+
+B2yipfW1PUxM9a7/p19CRBcDQ+LNW+YFqwARByHGq1wfatJzpM8TXe+XEnRfW9KX
+P3a5PqR6evFQOzjcAf+QBJ0hAEddUDhdYECbs1GrApfsEHBuwXabdCH41j0F/0yc
+kctydWfBl2Vbmd3sfsFMHjde+SJhqxyq6xiSL59jnx4ZKmtn9VSOYbGmBCdBdYK7
+RTcnJQv9AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AB6zh/Jw+t232100Tztr7wJoKH8DL1hnSm3e7omdj0WlKfuZwTqDuMzB3H4LOSnS
+A00XpyMAGAJC6yRjS8pt+pjY5Jt6ouSqf6wNq0mF0jiIDeg1k/GNEjigx+0ITqbE
+lUJ56AcpoBNhOwBjOCRFh4JuspHZqHXgUNYTEicClbV+lZwoMIIK1e6FYRZDqMtL
++34GtZACImqvRkP5alqQg7hJUM1zbDVf2qebY4cfSu4OfTu6Og6KrL8Cu6bqR2et
+0a/TbthHYz1QGDYRoVTSP4uWoG9M1ZbsA/bNE2eqcrQj+dJ4AmIIr8Yl8mrwo/FZ
+SvgeLMlQY7UNwLUDtwy9QkI=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/client_ca.key b/src/test/ssl/ssl/client_ca.key
new file mode 100644
index 0000000..f79ea97
--- /dev/null
+++ b/src/test/ssl/ssl/client_ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAu+ce8rkNfoCvI9Wjug9pxsptsdjhZ4s7ZZ8eD5VlloryK2Jc
+cusQIX61XY8I3OZjLTgq1SpZbHQvktRH6gmU7tfoBdEnRuXB7idkbYOKIrC0hdtt
+b/5rDzjQGtXTmwoVrCcJnvO1Whay/gdsoqX1tT1MTPWu/6dfQkQXA0PizVvmBasA
+EQchxqtcH2rSc6TPE13vlxJ0X1vSlz92uT6kenrxUDs43AH/kASdIQBHXVA4XWBA
+m7NRqwKX7BBwbsF2m3Qh+NY9Bf9MnJHLcnVnwZdlW5nd7H7BTB43XvkiYascqusY
+ki+fY58eGSprZ/VUjmGxpgQnQXWCu0U3JyUL/QIDAQABAoIBAD4TfcrsTcP0GWg6
+RSvLucM9zv2JS/YcLlRFO/YkAfq5DoY8qZQhiiO2q44sGd54kl03CBeCNSa6P5k/
+Xj64SaaaV4HMdjBa6TWXd/siELmjLRBnzIDKSW4u87lZ2N2IeF52SxxjIQ+RHjME
+GuSk9UaZ6KIoLFczYSoQOpYOkFgNKdu0RcxGG+fM+AQMtCP/KjL61suBxeoLG+Cs
+kAB7EUsSbX+PsOy3V9l9n62F/NDPQBuNgwAMOF2qOXnMTsDHTkxlkka8CIHZeRLX
+VBifO6bf2TCpAQ9+cH+lmfXtOWYExvZvgGeMB9WE8gXSxOnSD0uqxSLgCAwr8sM1
+6TDitIECgYEA7K/p0efjOaw9/+hAJniXS+RQ90WXTkq3asIR+NDvpig2jIJAQ9Lx
+ngGQ86PlEIL53O7Ol4Av4589pmSAD1Q5dEXsXOcDod0mx0nidAp/C//fhyfX7xR2
+irIWDxKKuCc4xbiVWNGeXXC0cJufY2b6gbgpSfwC/i5CUlGzkLdoGKECgYEAyzwq
+g4jtU0O90wKl6REQuepCMTL6+/E6sFDl7OXxZdmeeTyLLgWevAwHOQeOhGuX9RMO
+ZYPngLSbrSC40o2i9369AUkJa0Meabji4fir7GvYzwarq/xHQjMvpGV13DVKEUoQ
+JLdZ9uJRih2tVeqlCiD1abCu3eVh2+Sc17iWKd0CgYEA13g19p+R3lkNgEDg1aUG
+p1JM2y8BVYbzfz75uXgME0mcj0GsW5JX364xVXwo9mUmLplAfe92qVO4fhgT9OCK
+BW36hYDRb7Oyr851V4qOqk/gIFyHWeFZIV6KcmJA4vDh4C3v2BHMh+gofDNQYN/I
+wfrzq6S+3MMkIWi7fc1Z+MECgYEApv4nCLGIIDS3Ux0H6nwFPF5KSVbUeBP830d5
+xbAjLEcmOgQPcJ9ZkLZpcOjOp+wojk08NRmvLUg56oXKl+edkrNm5hl3TdV2tfQf
+KQJFchwjp+iZQtYmTzTz3qcnsutukspCfYjSuVO5ID3GYaROPAZc4J028kk6oY41
+eePIL1kCgYEA1ghHZmNhhsjxrkfWFME/nSWFazyEx1XmMagmvXw9rlrnBPFdtLsU
+ZfFHM5gVaW/JMql0OGDjMSwc3fEEH8wd1eLXVxfCVLzvk8XVe81ahthMpndii813
+Cspl0AS9jpOkQK8JTZ38YAIqIr7H057veqAY+TbvIAdxoh+7DyW/aBs=
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0 b/src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0
new file mode 100644
index 0000000..a667680
--- /dev/null
+++ b/src/test/ssl/ssl/root+client-crldir/9bb9e3c3.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+client-crldir/a3d11bff.r0 b/src/test/ssl/ssl/root+client-crldir/a3d11bff.r0
new file mode 100644
index 0000000..e879cf2
--- /dev/null
+++ b/src/test/ssl/ssl/root+client-crldir/a3d11bff.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+client.crl b/src/test/ssl/ssl/root+client.crl
new file mode 100644
index 0000000..854d77b
--- /dev/null
+++ b/src/test/ssl/ssl/root+client.crl
@@ -0,0 +1,22 @@
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3QgY2xpZW50IGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBAhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAXjLxA9Qc6gAudwUHBxMIq5EHBcuNEX5e3GNlkyNf
+8I0DtHTPfJPvmAG+i6lYz//hHmmjxK0dR2ucg79XgXI/6OpDqlxS/TG1Xv52wA1p
+xz6GaJ2hC8Lk4/vbJo/Rrzme2QsI7xqBWya0JWVrehttqhFxPzWA5wID8X7G4Kb4
+pjVnzqYzn8A9FBiV9t10oZg60aVLqt3kbyy+U3pefvjhj8NmQc7uyuVjWvYZA0vG
+nnDUo4EKJzHNIYLk+EfpzKWO2XAWBLOT9SyyNCeMuQ5p/2pdAt9jtWHenms2ajo9
+2iUsHS91e3TooP9yNYuNcN8/wXY6H2Xm+dCLcEnkcr7EEw==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+client_ca.crt b/src/test/ssl/ssl/root+client_ca.crt
new file mode 100644
index 0000000..1867cd9
--- /dev/null
+++ b/src/test/ssl/ssl/root+client_ca.crt
@@ -0,0 +1,38 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIUEAgXJ/ibw6TVTUoomlBsPMfVTlMwDQYJKoZIhvcNAQEL
+BQAwQDE+MDwGA1UEAww1VGVzdCByb290IENBIGZvciBQb3N0Z3JlU1FMIFNTTCBy
+ZWdyZXNzaW9uIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYwNDE0MTM0
+MDU0WjBAMT4wPAYDVQQDDDVUZXN0IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NM
+IHJlZ3Jlc3Npb24gdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALZ81vKKBJlxgjwuNoK67I4IE9zfSLb0eHbgZwZxDVzdmFejARrHlWk3
++MK7Nav7RLSJ990am33zb58CTHc7YYVlBp07+PwLXzypqWkhYfok1OYYjyjCrFDs
+sjcJI3hRCZNEz+wYsG+tdYWJ+gRPQOWfh0YfO2rFgXAIMLiF6lyWzf1eOM+OjYrF
+/eyzwbMaJkkGa/AyZKz3wZiPq0jTuYLVmH4MK7MBOsUfSmsBsn/ohyRCQzM+ol0v
+Qlsrulj8usponRPDh9ng4PB5OSgR79YimQZnASQzJxiUvMADrKL5L6KwLxJlzbqY
+R0b5mLh8KBzBQmSh3Aj2e2I7Z17hdaMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEASzA7ApbuKn8lkC706gRL37a33yTZZ8rjZ4dnvCtq
+6OltlYDJ8IndotKbLH0SUEAxrvcaFnMt7AX9pRf2sGBKbY8zcxqPfsvzVehgx4Ea
+1RYksFW4h97jj1a1RKukTKuEOEEipbxwo0rLxfjvdaf2izqchJsLGtbocIZf0bD8
+djbE9jOLkx7saL08qC8ECrf9utsee+LJCsUYbNgYyIItEy6yVnmF/ICz93Utn1cI
+RfqZr1lM2Ia2LP9eDTmiuR9m+/MzkeRvvJHonNrRJHlcggtYHICvYioh9/jALBcm
+wZ+hTUePVqy4hOCBJ975CXjfKFN4MKQAdeB3EO5eBYAD3Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBjbGllbnQg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC75x7yuQ1+gK8j
+1aO6D2nGym2x2OFniztlnx4PlWWWivIrYlxy6xAhfrVdjwjc5mMtOCrVKllsdC+S
+1EfqCZTu1+gF0SdG5cHuJ2Rtg4oisLSF221v/msPONAa1dObChWsJwme87VaFrL+
+B2yipfW1PUxM9a7/p19CRBcDQ+LNW+YFqwARByHGq1wfatJzpM8TXe+XEnRfW9KX
+P3a5PqR6evFQOzjcAf+QBJ0hAEddUDhdYECbs1GrApfsEHBuwXabdCH41j0F/0yc
+kctydWfBl2Vbmd3sfsFMHjde+SJhqxyq6xiSL59jnx4ZKmtn9VSOYbGmBCdBdYK7
+RTcnJQv9AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AB6zh/Jw+t232100Tztr7wJoKH8DL1hnSm3e7omdj0WlKfuZwTqDuMzB3H4LOSnS
+A00XpyMAGAJC6yRjS8pt+pjY5Jt6ouSqf6wNq0mF0jiIDeg1k/GNEjigx+0ITqbE
+lUJ56AcpoBNhOwBjOCRFh4JuspHZqHXgUNYTEicClbV+lZwoMIIK1e6FYRZDqMtL
++34GtZACImqvRkP5alqQg7hJUM1zbDVf2qebY4cfSu4OfTu6Og6KrL8Cu6bqR2et
+0a/TbthHYz1QGDYRoVTSP4uWoG9M1ZbsA/bNE2eqcrQj+dJ4AmIIr8Yl8mrwo/FZ
+SvgeLMlQY7UNwLUDtwy9QkI=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/root+server-crldir/a3d11bff.r0 b/src/test/ssl/ssl/root+server-crldir/a3d11bff.r0
new file mode 100644
index 0000000..e879cf2
--- /dev/null
+++ b/src/test/ssl/ssl/root+server-crldir/a3d11bff.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+server-crldir/a836cc2d.r0 b/src/test/ssl/ssl/root+server-crldir/a836cc2d.r0
new file mode 100644
index 0000000..717951c
--- /dev/null
+++ b/src/test/ssl/ssl/root+server-crldir/a836cc2d.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+server.crl b/src/test/ssl/ssl/root+server.crl
new file mode 100644
index 0000000..9720b30
--- /dev/null
+++ b/src/test/ssl/ssl/root+server.crl
@@ -0,0 +1,22 @@
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root+server_ca.crt b/src/test/ssl/ssl/root+server_ca.crt
new file mode 100644
index 0000000..861eba8
--- /dev/null
+++ b/src/test/ssl/ssl/root+server_ca.crt
@@ -0,0 +1,38 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIUEAgXJ/ibw6TVTUoomlBsPMfVTlMwDQYJKoZIhvcNAQEL
+BQAwQDE+MDwGA1UEAww1VGVzdCByb290IENBIGZvciBQb3N0Z3JlU1FMIFNTTCBy
+ZWdyZXNzaW9uIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYwNDE0MTM0
+MDU0WjBAMT4wPAYDVQQDDDVUZXN0IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NM
+IHJlZ3Jlc3Npb24gdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALZ81vKKBJlxgjwuNoK67I4IE9zfSLb0eHbgZwZxDVzdmFejARrHlWk3
++MK7Nav7RLSJ990am33zb58CTHc7YYVlBp07+PwLXzypqWkhYfok1OYYjyjCrFDs
+sjcJI3hRCZNEz+wYsG+tdYWJ+gRPQOWfh0YfO2rFgXAIMLiF6lyWzf1eOM+OjYrF
+/eyzwbMaJkkGa/AyZKz3wZiPq0jTuYLVmH4MK7MBOsUfSmsBsn/ohyRCQzM+ol0v
+Qlsrulj8usponRPDh9ng4PB5OSgR79YimQZnASQzJxiUvMADrKL5L6KwLxJlzbqY
+R0b5mLh8KBzBQmSh3Aj2e2I7Z17hdaMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEASzA7ApbuKn8lkC706gRL37a33yTZZ8rjZ4dnvCtq
+6OltlYDJ8IndotKbLH0SUEAxrvcaFnMt7AX9pRf2sGBKbY8zcxqPfsvzVehgx4Ea
+1RYksFW4h97jj1a1RKukTKuEOEEipbxwo0rLxfjvdaf2izqchJsLGtbocIZf0bD8
+djbE9jOLkx7saL08qC8ECrf9utsee+LJCsUYbNgYyIItEy6yVnmF/ICz93Utn1cI
+RfqZr1lM2Ia2LP9eDTmiuR9m+/MzkeRvvJHonNrRJHlcggtYHICvYioh9/jALBcm
+wZ+hTUePVqy4hOCBJ975CXjfKFN4MKQAdeB3EO5eBYAD3Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzZXJ2ZXIg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiSnYZbmc9vpCt
+Ku1sKV9l663JCceubhMw8Gg16kV0hXEFf/TgGC4zkiYNHN7+G45YD7Nq0kBCq3dH
+t2wPCc6c8pQoI64dfprVqPkvzoe1WBpZNetkUTk20v08jNeRa7XdRbRR6we1s9VG
+/prp8Hs2mmHqEfLuI9lvTT0Dz+VMmfFI8Lf278r+w+qOtVloAkX7AOyoLEJlNS0B
+QW9YWdH9N5ctaUXMG6lLV2OAjs+W1smpKfpIpMCA1lPGlElu70hynon/nQQvBP77
+SfQpZVc0esM18jkZpr5LEKUCw+x6LaMsqmBHpAULfCffxn2r0uMBW4L4VaGg3W6F
+h6iuJwRfAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AFlcKTaU/Ug3Q0hr3P1UQ6dWyK4aVn9rs4jvVfFl0a0RnbBowqK2C+zQVUWYTcjo
+KHREVje65goj6VzRB6ko/9mAQ6PZP8jRuRhfCmvmvSQ/mWdgPzSRsUh9MwgEm9c2
+vNbqwaznEU8cYZnLpHiR9O5S7/qWWxehjYtxk5Eb4J006YglYfHnhrRFJvPbiqlf
+IOEivZ7gIVfvaOTbLjmN2kLOnzdlwpXGjxxg4Nu9ZhXOhfrplzUvRfmqvVsDiHXb
+USIdX+OFZZqr64IKG4drT4K4Bt2wupOEyX4ZFsUXXd+Hgq83SWmV4wzflcpmGkLC
+JZ3CEMu8/WA5uQBXdQUozlE=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/root.crl b/src/test/ssl/ssl/root.crl
new file mode 100644
index 0000000..e879cf2
--- /dev/null
+++ b/src/test/ssl/ssl/root.crl
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBhTBvMA0GCSqGSIb3DQEBCwUAMEAxPjA8BgNVBAMMNVRlc3Qgcm9vdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHN1aXRlFw0xODExMjcx
+MzQwNTVaFw00NjA0MTQxMzQwNTVaMA0GCSqGSIb3DQEBCwUAA4IBAQB8OSDym4/a
+qbZOrZvOOhmKrd7AJSTgAadtdK0CX3v58Ym3EmZK7gQFdBuFCXnvbue/x6avZHgz
+4pYFlJmL0IiD4QuTzsoo+LzifrmTzteO9oEJNLd2bjfEnpE5Wdaw6Yuy2Xb5edy5
+lQhNZdc8w3FiXhPOEUAi7EbdfDwn4G/fvEjpzyVb2wCujDUUePUGGayjKIM4PUu4
+pixM6gt9FFL27l47lQ3g0PbvB3TnU3oqcB3Y17FjbxjFc6AsGXholNetoEE2/49E
+PEYzOH7/PtxlZUtoCqZM+741LuI6Q7z4/P2X/IY33lMy6Iiyc41C94l/P7fCkMLG
+AlO+O0a4SpYS
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/root_ca.crt b/src/test/ssl/ssl/root_ca.crt
new file mode 100644
index 0000000..402d7da
--- /dev/null
+++ b/src/test/ssl/ssl/root_ca.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDHjCCAgagAwIBAgIUEAgXJ/ibw6TVTUoomlBsPMfVTlMwDQYJKoZIhvcNAQEL
+BQAwQDE+MDwGA1UEAww1VGVzdCByb290IENBIGZvciBQb3N0Z3JlU1FMIFNTTCBy
+ZWdyZXNzaW9uIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYwNDE0MTM0
+MDU0WjBAMT4wPAYDVQQDDDVUZXN0IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NM
+IHJlZ3Jlc3Npb24gdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALZ81vKKBJlxgjwuNoK67I4IE9zfSLb0eHbgZwZxDVzdmFejARrHlWk3
++MK7Nav7RLSJ990am33zb58CTHc7YYVlBp07+PwLXzypqWkhYfok1OYYjyjCrFDs
+sjcJI3hRCZNEz+wYsG+tdYWJ+gRPQOWfh0YfO2rFgXAIMLiF6lyWzf1eOM+OjYrF
+/eyzwbMaJkkGa/AyZKz3wZiPq0jTuYLVmH4MK7MBOsUfSmsBsn/ohyRCQzM+ol0v
+Qlsrulj8usponRPDh9ng4PB5OSgR79YimQZnASQzJxiUvMADrKL5L6KwLxJlzbqY
+R0b5mLh8KBzBQmSh3Aj2e2I7Z17hdaMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zAN
+BgkqhkiG9w0BAQsFAAOCAQEASzA7ApbuKn8lkC706gRL37a33yTZZ8rjZ4dnvCtq
+6OltlYDJ8IndotKbLH0SUEAxrvcaFnMt7AX9pRf2sGBKbY8zcxqPfsvzVehgx4Ea
+1RYksFW4h97jj1a1RKukTKuEOEEipbxwo0rLxfjvdaf2izqchJsLGtbocIZf0bD8
+djbE9jOLkx7saL08qC8ECrf9utsee+LJCsUYbNgYyIItEy6yVnmF/ICz93Utn1cI
+RfqZr1lM2Ia2LP9eDTmiuR9m+/MzkeRvvJHonNrRJHlcggtYHICvYioh9/jALBcm
+wZ+hTUePVqy4hOCBJ975CXjfKFN4MKQAdeB3EO5eBYAD3Q==
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/root_ca.key b/src/test/ssl/ssl/root_ca.key
new file mode 100644
index 0000000..aa5f243
--- /dev/null
+++ b/src/test/ssl/ssl/root_ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAtnzW8ooEmXGCPC42grrsjggT3N9ItvR4duBnBnENXN2YV6MB
+GseVaTf4wrs1q/tEtIn33RqbffNvnwJMdzthhWUGnTv4/AtfPKmpaSFh+iTU5hiP
+KMKsUOyyNwkjeFEJk0TP7Biwb611hYn6BE9A5Z+HRh87asWBcAgwuIXqXJbN/V44
+z46NisX97LPBsxomSQZr8DJkrPfBmI+rSNO5gtWYfgwrswE6xR9KawGyf+iHJEJD
+Mz6iXS9CWyu6WPy6ymidE8OH2eDg8Hk5KBHv1iKZBmcBJDMnGJS8wAOsovkvorAv
+EmXNuphHRvmYuHwoHMFCZKHcCPZ7YjtnXuF1owIDAQABAoIBAQCiCzsHhf1NkBi4
+fcTT006JVKzmnbNBGtb5oIx7kNnv06oab9lkQUPwec5AhOLFA8tfkX/y61SVxBwj
+E3R5D9aqECqOZpnSnfqEsJeJjiYlbJ1McRR2el9vQK+D5W6EwVkCV8FWAhpyIJJR
+8VJ8jy+udzk00Dj/t8AXjn5M7EVOzu7fu2CIjJ2csE4NpWnn4eaDqev/brEVaLSP
+DGFdMw4D29AmErByN42d90U5YE2c1UufYoFL480qoA4pW5Tw5+vrIDliEHhnTtSN
+aTHZiOCmHtBFieQzmWCRQqmtlJP+7Z/NqK0i91HpjFrU5AuyLOMbqJPl6TgncNA+
+MSXMXGQBAoGBANlsAQc3poc3MX18++qgRJGqJCBF3MVQNnZQxmO6swydikZmlunN
+kmslheb/JZbE9tkjEhx1RuUeZIvOCxURdODDPnvm9bk0C7LvPGXnYLWTbCknHEwR
+8yIvPGiLhZOuDGAdLpHzG5F1eHQLOWQpTNndptlveSz5Zc0a+B7qmWYBAoGBANbe
+Atvo8JI+ht2tiidwCo5WHR26ux0yA+iHPNyMAEaY5KFblyvjb4rAFziUu6cLzFNl
+N2pdv3ZpIHs82erJMkCSrIbp9RM3TWaTMFgWETDnZ6dNclEsEva/kRJquOw+N/Ag
+LFOn8omVRMHq99G/eFdPeSYc1mDRNZ0vDstOA4OjAoGAd9l/X5kfpN2Z3FCvFRCv
+e5RMQbYBEos62lGAaq0Z0dRtyoz2l38IPSP8Ae+Xqtp8MAmTDDjhkZ8FUcOMfFqZ
+EOTPZsFTpnm4ETSrGIlI2A6hyrWSdaRXX/ql1ANE6LlCfSDY8P8PrUkR0vX09u+F
+O3thY+5833vC0CMTrwcm9AECgYBmVktqTiH2pY06m+MHMZf1fxJTDJL+Lsopv+++
+43dmKIAMUkFICAUiQqdMrZpKz5W7yqOAJ7J/RUbRK4RnDPjARJujjl7JjjdxOX13
+FtuNPUnjJ0HhY2qM12TTLr1w15lw5wH1vjIIUW30JmNuJRG+E/4Rpv58EmjEupsD
+Pd7ynQKBgQC42hGdd3TGe7zYqnPIe/vJyNX05xErKXK1iqwj6ZQWOiurGiePbiIu
+Top5MZcqLetZ9872efPLQFlkB2elCP91yBKNdI+onBcha9rVcczjCdaQswsm5Ws3
+58Dyjci4NqyD8B19AOJLTl5gq8pmj5Nom8ip+Bm2EsQw777Dqq9YrA==
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-cn-and-alt-names.crt b/src/test/ssl/ssl/server-cn-and-alt-names.crt
new file mode 100644
index 0000000..2bb206e
--- /dev/null
+++ b/src/test/ssl/ssl/server-cn-and-alt-names.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDTjCCAjagAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0
+IENBIGZvciBQb3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNl
+cnRzMB4XDTE4MTEyNzEzNDA1NFoXDTQ2MDQxNDEzNDA1NFowRjEeMBwGA1UECwwV
+UG9zdGdyZVNRTCB0ZXN0IHN1aXRlMSQwIgYDVQQDDBtjb21tb24tbmFtZS5wZy1z
+c2x0ZXN0LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBURL6
+YPWJjVQEZY0uy4HEaTI4ZMjVf+xdwJRntos4aRcdhq2JRNwitI00BLnIK9ur8D8L
+U24PDn2etTZOK1wsHHkAiHPvgRX7G/+78a5fSC8nMNaH/oR4zMMhwksiruISA7x9
+/l+4DO7C42C5mRfnUmMGJdzau1+A8jcIxTWWoJtva9b1k3g+bvBGq9138X+bJKIW
+YsWwHgcuEIZk3z287hxuyU3j5isYoRwd5cZZFrG/qBJdukSBRil5/PP5AHsB6lTl
+pae2bdf4TXB7kActIpyTBR0G5Pm5iCZlxgD+QILj/1FLTaNOW7hV+t1J6YfC6jZR
+Dk4MnHMCFasSXcXhAgMBAAGjSzBJMEcGA1UdEQRAMD6CHWRuczEuYWx0LW5hbWUu
+cGctc3NsdGVzdC50ZXN0gh1kbnMyLmFsdC1uYW1lLnBnLXNzbHRlc3QudGVzdDAN
+BgkqhkiG9w0BAQsFAAOCAQEAQeKHXoyipubldf4HUDCXrcIk6KiEs9DMH1DXRk7L
+z2Hr0TljmKoGG5P6OrF4eP82bhXZlQmwHVclB7Pfo5DvoMYmYjSHxcEAeyJ7etxb
+pV11yEkMkCbQpBVtdMqyTpckXM49GTwqD9US5p1E350snq4Duj3O7fSpE4HMfSd8
+dCkYdaCHq2NWH4/MfEBRy096oOIFxqgm6tRCU95ZI8KeeK4WwPXiGV2mb2rHj1kv
+uBRC+sJGSnsLdbZzkpdAN1qnWrJoLezAMdhTmNRUJ7Cq8hAkroFIp+LE+JyxR9Nw
+m6jD3eEwCAQi0pPGLEn4Rq4B8kxzL5F/jTq7PONRvOAdIg==
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-cn-and-alt-names.key b/src/test/ssl/ssl/server-cn-and-alt-names.key
new file mode 100644
index 0000000..485e340
--- /dev/null
+++ b/src/test/ssl/ssl/server-cn-and-alt-names.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAwVES+mD1iY1UBGWNLsuBxGkyOGTI1X/sXcCUZ7aLOGkXHYat
+iUTcIrSNNAS5yCvbq/A/C1NuDw59nrU2TitcLBx5AIhz74EV+xv/u/GuX0gvJzDW
+h/6EeMzDIcJLIq7iEgO8ff5fuAzuwuNguZkX51JjBiXc2rtfgPI3CMU1lqCbb2vW
+9ZN4Pm7wRqvdd/F/mySiFmLFsB4HLhCGZN89vO4cbslN4+YrGKEcHeXGWRaxv6gS
+XbpEgUYpefzz+QB7AepU5aWntm3X+E1we5AHLSKckwUdBuT5uYgmZcYA/kCC4/9R
+S02jTlu4VfrdSemHwuo2UQ5ODJxzAhWrEl3F4QIDAQABAoIBADpFoQ3eKkVzV48X
+uW4QpCY7e4rqPmu06t/7zABTUzYG35Pj4+2L1zuS5zl17zZ6mfYDLk3QsU1SleVA
+RIVdpqQZVRQnDaN1atXNw9G4cVKBZM1QeGp3+yCawHstoQ5sXvMFM01bXykQpOwU
+NDTeBAmTmQviX+eDMa+h05sOLzAe5IfJd54au7jaDgX+J+OYoRcahXZLO3tco/kL
+Mo0OBj71ec8jrbhnViEXPwPUOBDoTJxfRotCZ2Sr0ozXT/sRBZvvK9OGzWf9mA2D
+M7UqbkKUL9AJxB+zTUILdM3+4buzifDZPUWe05dHyP6VAvtgSQJkdReFtUa868pm
+si+7Td0CgYEA+r4dxf880QW1hY/dpTfLXOcLKSHogIHv2Qt3Dinh4AthXZs91MQ9
+DMiT2x4RMGlk7zOu6Ua4HXjTT0s9CqUt9Cyga0zTn+XzNZxzcriRWYnw7pq0O77B
+3AODrK6/VajAjqdwiP3nQfBOyhz3G7YB2yXCpdnVVI179x8pbGnEP2MCgYEAxV64
+CaIW0hgwEZifT4PGINdGShk7ijQ0YhPw4bLJLV7gaPrKYG+qy8/R9AyhcFqz9MrF
+2E+jiD+fylNSLdkuR1/v6se1wWLjDiKip5F9molCAKTUBTkqD/8Ejh5+I7NAuFLA
+9QZYiaRLhIoVocWfzNIPHit7NZftaBtxTCtE8usCgYAmxbso4LzwvWdCTerCH4yM
+wxVQuPOQ24bRExrHz+YjlN7rcJPxEJ84GNP0MAQMbl+zNVS4sbzKoeJbApFf0gb3
+GOd9cBXRReeDxLt9Y9jl9ZSR8M4p5udnNAvqaeMgRcXwySd3p3tZEOW+DxiO6mgD
+ESW2K6b3OiGPJvxqzTgRbQKBgQDCvB/tMUY+6KqU0fdtpuCXio/JkHfUdomws2gZ
+6CLiZxgXvEptOABWs6e9mbC3gGbKAj+Om5UIW243XFpa7kvhFGFNTtqgAgdw7O97
+UeuRzBeZNwgSV0KPIdjGuINQig4zT0Me/rHgrH/uN6f8Q1bV6fQMmm4ohMwyydDR
+jGetHQKBgGLQf4MBNalhfnM7jnUCbA0ygrw7BuJRfwuamdcH9bdfOHMyrbOfZ+hS
+aKcOeaGi0HGOq+D2tIH1hmFYHD0klPgr/KWnNMoi2xTw+1GNKA2u9EZQQkK6XSRn
+Xb6zihNEqY8067K/um/658x1c9SbfvVmzjqo5OwgjSKygk6fXL8i
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-cn-only.crt b/src/test/ssl/ssl/server-cn-only.crt
new file mode 100644
index 0000000..67bf0b1
--- /dev/null
+++ b/src/test/ssl/ssl/server-cn-only.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC/DCCAeQCAQIwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNlcnZlciBjZXJ0czAe
+Fw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEYxHjAcBgNVBAsMFVBvc3Rn
+cmVTUUwgdGVzdCBzdWl0ZTEkMCIGA1UEAwwbY29tbW9uLW5hbWUucGctc3NsdGVz
+dC50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1bNU8yTuLl/5
+bR4Rp1ET5NMC2wgrTwKQsxSeOzvMmTGeebpEYFc/Hq8rcCQAiL7AbhiZeNg/ca4y
+JdouOdaHaTMFJ8hFDI1tNOGeFK7ecOMBWQ97GxKs/KIqKYW42AN+QZ7l1Apr0CDZ
+K5VTi931JjE4wCIgUgLi2zgwtZYl/kP896F1K5zR7kx773U2dvP3SeV2ziUe+4NH
+5oqdmVMeZyHfB+Fe/uU1AiYgHN/CXfop39tYHR8ARUWx7eJlaaKBoj/0UqH/9Yir
+jdM0vGfrw4JCjIx78caNkNH9fCjesTqODr+IDBJaJv3Jpt9g8puqrYagXLppiaYS
+q5oOAu5fuQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCTxkqpNNuO15osb+Lyw2aQ
+RikYZiSJ4uJcOIya6DqSYSNf8wrgGMJAKz9TkCGEG7SszLCASaSIS/s+sR1+bE19
+f6BxoBnppPW8uIkTtQvmGhhcWHO13zMUs8bmg9OY7MvFYJdQAmSqfYebUCYR73So
+OthALxV8h+boW5/xc2XM1NObpcuShQ9/uynm2dL3EbrNjvcoXOwu865FmVMffEn9
++zhE8xl4kMKObQvB3r2utCmlAmJLaU2ejADncS9Y4ZwRMa7x+vfvekF/FvLEXUal
+QcDlfrZ0xsw/HK7n0/UFXf5fUXq3hgUGcXEdWW7/yTA43qNxednfa+fMqlFztupt
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-cn-only.key b/src/test/ssl/ssl/server-cn-only.key
new file mode 100644
index 0000000..672d3f0
--- /dev/null
+++ b/src/test/ssl/ssl/server-cn-only.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA1bNU8yTuLl/5bR4Rp1ET5NMC2wgrTwKQsxSeOzvMmTGeebpE
+YFc/Hq8rcCQAiL7AbhiZeNg/ca4yJdouOdaHaTMFJ8hFDI1tNOGeFK7ecOMBWQ97
+GxKs/KIqKYW42AN+QZ7l1Apr0CDZK5VTi931JjE4wCIgUgLi2zgwtZYl/kP896F1
+K5zR7kx773U2dvP3SeV2ziUe+4NH5oqdmVMeZyHfB+Fe/uU1AiYgHN/CXfop39tY
+HR8ARUWx7eJlaaKBoj/0UqH/9YirjdM0vGfrw4JCjIx78caNkNH9fCjesTqODr+I
+DBJaJv3Jpt9g8puqrYagXLppiaYSq5oOAu5fuQIDAQABAoIBAELaJRsjVHehgpAG
+NhOXo5eUA3Kt7Y58CPRc4Ns669iI00DVaoqRAKgCuJ4ORTSCKATJIUnSrJZNnlaF
+GKzzVc0tLtGxLxisLZu7cQ6bXe8GtOc9lo9zmjY2LOZsdNTu0tKIePGKiQvFGust
+fcNlnkliYJSKmH3PdVSLEYHdBOmznMR+M5nif33OmuK+LIQ8Go+jpahvqXSG60ae
+QAKlJCO9DARjhJqpYw1GgtzXSxpiVWBkJzIwnemOecgBtm6W/5GDzYPq9GE5lY7N
+MTjP9BmnpMC1gPQjiDICrd9eWSUv6fuHAClCi5lMDrktWvZcEB0tpoxcQZf2d0/m
+vRZK7uECgYEA8fKpaDaZqPNktgLsrlo35wmHa3tkWR1jmI5DY5BHoO+N+Bm/ISwP
+HHLTObXmgzbycA5OEsIeUdb8ZmO79WINb9Z8aAmhft6bBzY7xZRNSouq0G/IgzZn
+m9D6f4ivBDXs8lZpJe3/SrvfCmnxPBO/vzezX6FqiPV24jSXNYcb+B0CgYEA4hyu
+bbO7Mfd1NmlJO+OWmAJBqJQKmFByP6uraUX9cgS2F+jexsyX12WGMXRoQM4CAo5u
+CN29U9NyokpZmifUbKq7cZ4Hni5ag+Wt9a/kuevmv8ysYEzVY07gjwg51z2uXV54
+wBA0nQsT28RVdNAv36hMhqgMM1ZTNa4AXGdxi00CgYEAzJRqKENaxKAhfUGVzYtd
+j47gIcLxQ+T0zQ8l7i8WUf+dJLbohO0TTfPNpROo+TRh5NxDqdrX9k15mD4mtUMW
+p4VOJk5WbsddgMib2+IdRLY6VgrfGgvLqdYXqfTyP/Y1B2iHeln2rsOSweR45Vqx
+nMdFdcwwH+SmhHkBjnJS9QUCgYBlmm/C+dVvMXwpFAyFbdI4wiLQ5p0QLm34MGLY
+7kth1b4hZlHc0QiWEJfJVz6ViDyc+3V0ZHdz2HsVdAVpYOZyYhHSjylrKfcgd6/A
+y+YiqV9J5mW67Cui8Um03ARptNzKNe5al62ct+KXiVTBJd+tR8oDZDX/R5Yic+rT
+muQJrQKBgDCc6inyAzBN6mwEcFJCj4JBoIBiTfcwX+Rruh4gR8+7KbiG3UqaXSiO
+prONCswe6sXs6s6bFCZSOwgsom/bYloBZRVtTPJv031VDTFUQBo4956/7dhIDdvC
+2ZDBwgHPeywPPK0OrGBuAXzfIS0YqMZeEXtpSdw8A3seQ2398/ir
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-crldir/a836cc2d.r0 b/src/test/ssl/ssl/server-crldir/a836cc2d.r0
new file mode 100644
index 0000000..717951c
--- /dev/null
+++ b/src/test/ssl/ssl/server-crldir/a836cc2d.r0
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/server-multiple-alt-names.crt b/src/test/ssl/ssl/server-multiple-alt-names.crt
new file mode 100644
index 0000000..158153d
--- /dev/null
+++ b/src/test/ssl/ssl/server-multiple-alt-names.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRDCCAiygAwIBAgIBBDANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0
+IENBIGZvciBQb3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNl
+cnRzMB4XDTE4MTEyNzEzNDA1NFoXDTQ2MDQxNDEzNDA1NFowIDEeMBwGA1UECwwV
+UG9zdGdyZVNRTCB0ZXN0IHN1aXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA10iQpfVf4nCqjkRcLXP9ONQqdhMPMdjHasKqmsFTx83SZLKUzKMOb56j
+3bg83stqGoId4MIxtqnDKaSg1+kseQ1HCi0cu/E3lHLEkPibl9dyVGhXVnPDBdOp
+eUQLCvPNgay3/ua4Mz0Nf7S9cgC9AZu/EEYjQIEzfO0cEANeVIWtgZfM3+2j0pmZ
+46AEYlEZJkmDT0/mnHk3YTj3I6qQhr34wZvqcrwouYRN5NiOVYJLpb6gPSoalm+P
+YXOKjP4+fWr18HdZLrzsa4xPRa9XcsDNyffjWvQTfptR/2vFKN8Ffv3XUqxUx6av
+VCyRKa8xAUS/pHVGnzFQY+oqWREn2wIDAQABo2cwZTBjBgNVHREEXDBagh1kbnMx
+LmFsdC1uYW1lLnBnLXNzbHRlc3QudGVzdIIdZG5zMi5hbHQtbmFtZS5wZy1zc2x0
+ZXN0LnRlc3SCGioud2lsZGNhcmQucGctc3NsdGVzdC50ZXN0MA0GCSqGSIb3DQEB
+CwUAA4IBAQAuV+4TNADB/AinkjQVyzPtmeWDWZJDByRSGIzGlrYtzzrJzdRkohlL
+svZi0QQWbYq3pkRoUncYXXp/JvS48Ft1jRi87RpLRiPRxJC9Eq77kMS5UKCIs86W
+0nuYQ2tNmgHb7gnLHEr2t9gFEXcLwUAnRfNJK56KVmCl/v3/4kcVDLlL6L+pL80r
+WGKGvixNy3bDCJ/YGJu6NH+H7NMlqFcg07nEWUHgMzETGGycTcPy3S6mY5P/1Ep1
+MCSTucUKoBIte2t5p9vM6bsFIioQDAYABhacmC62Z5xNW8evmNVtBDPLR1THsWhq
+UjzdIzjpDgv1KUCVEPc1uVrZ5eju+aoU
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-multiple-alt-names.key b/src/test/ssl/ssl/server-multiple-alt-names.key
new file mode 100644
index 0000000..57f3114
--- /dev/null
+++ b/src/test/ssl/ssl/server-multiple-alt-names.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA10iQpfVf4nCqjkRcLXP9ONQqdhMPMdjHasKqmsFTx83SZLKU
+zKMOb56j3bg83stqGoId4MIxtqnDKaSg1+kseQ1HCi0cu/E3lHLEkPibl9dyVGhX
+VnPDBdOpeUQLCvPNgay3/ua4Mz0Nf7S9cgC9AZu/EEYjQIEzfO0cEANeVIWtgZfM
+3+2j0pmZ46AEYlEZJkmDT0/mnHk3YTj3I6qQhr34wZvqcrwouYRN5NiOVYJLpb6g
+PSoalm+PYXOKjP4+fWr18HdZLrzsa4xPRa9XcsDNyffjWvQTfptR/2vFKN8Ffv3X
+UqxUx6avVCyRKa8xAUS/pHVGnzFQY+oqWREn2wIDAQABAoIBACtGhP03Y/zq1P4g
+M79XT5G65IYzspw8jWmilBTjw+moMCDZ3Rt9s4swgpQxUtseXMfTXBowLzoeygJ2
++3YrgysaRit/ggUtqhSHNYhG0VAmmO7qwpO4VX24XJrp2KZs9+SXSa1Nx71VCn+f
+X22pRFUsb63fy3pN/oGgUEHPy4iFsDm5K62lszzzwXmcWam30dcK2Ddw07FAwpSR
+2hW0veXpbZs33CX0p0js2imlSBwMLPbYIXriRT8Wpkkp+LvSy7/vDK3hWGhrKflT
+hXZsHINEBwGwfEP7uSgTUiTlm96Fwp8SXLC0A7NJL8uJ2ARxuDqniq0UbqTpvGgY
+RlgkZVECgYEA8rPoMuhJYHkejfh05qqycs3RYAdMIeOZ0wGzbELR+nI0FoAITHOB
+KsdMUaNrjICMKAJBNx7cl4Qb5IP35dcZSyR9pr6W6QDCwnRDYxGSCakn3gEtLgix
+5rcrf7r8QUyDUjCjasAZoql3rlew6q4HtSfBKciNuQ1wYnuaf5QdQAUCgYEA4xQU
+xvTbAYAhpmrDhIMprStBtAHEM/1N2RiV7jlw3WI939WBSRTwqLmDSJNc4he5m43w
+Dew2HPLFW6m/2jsXhYCXkACsgn1E2o5wPPcHIgnKe8eO26HuSIg75OsDaxAOGtMi
+RQbXelxtXDnRbsjiChYRucH13EhU0lsaffNXrl8CgYBEU2WhP0e5AyAY88NlVNTc
+ARlaoXNLbxnVD3uFlOIsUY5cbzrm2vWYJ3dS3GDgsyfB87CMZgHQHf8EPCrD5+RV
+BTbihHFTs0UhHT4DW+TzF04D7+zaMtRykUqLsQZnE7U8pDi9SstswazRxhomV0wQ
+Mdrtemp7mE71SrraA8agSQKBgQDSfC62LQlEXszSQWxyTFI5XjtM68Y+mrGqZouz
+gjMIQqQv8uwgHfTlsO/sOgyC1pMJiYvWm/mc47vkt3hKhTPMX+IdbUJ6wjssi5Om
+LyTBfGngSp41H+iL+xvpmZ5Vg1BPtR2y9iCOH1aPgliLZFGCH+rWUN/hDHrzcdcg
+oIvJ6QKBgQCnYc+oZqcdisoSYPg7IZSWsPz3mWsFtR0Xw54zQ0n+gMjEzSDjO57+
+8nMUpXwnspo/x8qbsrZ39YeZZvwXVTXlpQjywOOGkIua84+EQUnknK+osKBQN62m
+PWfPxXCTkWSBf8V6KKG/LFS6bZZu96h7+uWHkEwcD+bACS+2vGuyLw==
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-no-names.crt b/src/test/ssl/ssl/server-no-names.crt
new file mode 100644
index 0000000..97e1117
--- /dev/null
+++ b/src/test/ssl/ssl/server-no-names.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC1jCCAb4CAQUwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNlcnZlciBjZXJ0czAe
+Fw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMCAxHjAcBgNVBAsMFVBvc3Rn
+cmVTUUwgdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ85/vh52iDZAeQmWt47o0kR7VVlRLGf4sF4cfxPl+eIWIzhib1fajdcqFiy81LC
++t9bAyRqMyR3dve9RGK6IDFjMH/0DBf3tFSRnxN+5TdSAhKIJslmtUdOl8kS/smF
+4+BikCg509aq0U+ac79e/q42OyvH9X/cI6i9SPd4hzJDMCX54LZT1Of/90nSQX6E
+Oc5Hcj/d7psBugmMBW8uXYAGvJpq14e5RoK78F/mYbUNqtc1c8pi4/4quSMeEfQp
+Dgmzee7ts8SIbQT8mYJHjnaPvZYpv4+Ikc7F0wzLO1neTpsYaVvDrSMLBCdQkCU8
+vgb1T6WlVgbp/sfE5okSxx8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh+erODlf
++mEK2toZhaAmikNJ3Toj9P7I0C0Mo/tl2aVz8jQc/ft5t3blwZHfRzC9WmgnZLdY
+yiCVgUlf9Kwhi836Btbczj3cK6MrngQneFBzSnCzsj40CuQAw5TOI8XRFFGL+fpl
+o7ZnbmMZRhkPqDmNWXfpu7CYOFQyExkDoo0lTfqM+tF8zuKVTmsuWWvZpjuvqWFQ
+/L+XRXi0cvhh+DY9vJiKNRg4exF7/tSedTJmLA8skuaXgAVez4rqzX4k1XnQo6Vi
+YpAIQ4dGiijY24fDq2I/6pO3xlWtN+Lwu44Mnn2vWRtXijT69P5R12W8XS7+ciTU
+NXu/iOo8f7mNDA==
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-no-names.key b/src/test/ssl/ssl/server-no-names.key
new file mode 100644
index 0000000..2edea5c
--- /dev/null
+++ b/src/test/ssl/ssl/server-no-names.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAnzn++HnaINkB5CZa3jujSRHtVWVEsZ/iwXhx/E+X54hYjOGJ
+vV9qN1yoWLLzUsL631sDJGozJHd2971EYrogMWMwf/QMF/e0VJGfE37lN1ICEogm
+yWa1R06XyRL+yYXj4GKQKDnT1qrRT5pzv17+rjY7K8f1f9wjqL1I93iHMkMwJfng
+tlPU5//3SdJBfoQ5zkdyP93umwG6CYwFby5dgAa8mmrXh7lGgrvwX+ZhtQ2q1zVz
+ymLj/iq5Ix4R9CkOCbN57u2zxIhtBPyZgkeOdo+9lim/j4iRzsXTDMs7Wd5Omxhp
+W8OtIwsEJ1CQJTy+BvVPpaVWBun+x8TmiRLHHwIDAQABAoIBAAtkaeK7TSkGfcUm
+HWBDIharSrDOcxDGYMH47SbhRvwQ3E0QIfvDpOTbI0xdWV11h9+NMndbhdc5GPD2
+wLrTmFQQRbsR6f+ZAHUAikIp1RqVKoLK7QOB7rxwWhnP2xzuEHTQeIH4STjVte4d
+HeT2VgB+7tLeFqmURZTgHiVeoUWuPgl2/L7ABK8x7wk6/Ho/FyB6bQsX9ixfd99W
+lxAhKr46Sa6ceMygswvqzxUcFm0lCSfMt+VTscZTqtQnqiV8mMiJk5novBUgpS95
+JaLsAKsG2mYKHBaAs+EbIbgk0hBWnGB6DFTd8/62u7fJFWA5BvMiNBnde47wLRJL
+BAHzw7ECgYEA1DVbs4lN/GA8ol+ERGGIhZUa44jLgIFrE7kpYdKoi8AF8R8BaIjp
+xlI6z+sxLcp7Z/jccRToGH20OX1i+x4Vt8NGvzkEOdowX+BwMl92v7vSrr6PGdWg
+X5Nu6/ISVarIDWBSLGmdfqJ/szu+HRBh4CvFlrf+379COkZ9oc9Hh0kCgYEAwBWv
+6J4oi4nbxyzpDpI5YH8wu56A6uNJAD5z3pca7XaR6mOLiJhqhCQscthx901dV2fT
+tECOxX6/DEvI1LZejiyG0Y9LXfhH37ZpEsgY14SNC4SJOW3dzVld2JEcd/3+50A1
+86DXImZoWeZzbiavkAxecZFZ8zoTUifYeh9M0ycCgYAQHZE+PDIo9WIFbr2Lt+B3
+TJCDMRNLSgjIsaob3LSiEE4jNpiTyLoALqR6v8C3WoYuqi6Lg+vwWDOEnioTKgC6
+OOE5imnwvsonrdK3cJqDCw9/58bUTm3kdDzbPEH6MYMJyQPUjZzBTjPmd6YDbQgR
+zyEtRgHcGhk8dbf6vtQOyQKBgQCg0geDhNeBbJybt9gwoPB1AEh27RAWmNDH6YHt
+fSnIYxtr2Ig8hw+3LuogBWP1n8pkocM4CUz/wUyHKPQuU7n64wDFd2msdXEHtptm
+ZC2YU5wbZo3VjUzE3uuZpHTnabr/Nl11atZ0MLVxf2ZpdO5Mdm6kOwPKhncis8Wl
+CYuyxQKBgHPgMjy4OgNclXfZHkk8MrHYJrZsX4NYKCAQC9z5pkHP3Osakt5YPdPq
+Hti6rFMzagHlYY7k8tMx9F3j/kQZrBq4yfQIWsnx+OIr1A/A/0jbmTHMMqlQ8EBN
+p7nfoCzlvm0lHQV2nUb/9UfP/Wc5zDZZnnBm83zOTjBTBZ55twu6
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-password.key b/src/test/ssl/ssl/server-password.key
new file mode 100644
index 0000000..a8e383a
--- /dev/null
+++ b/src/test/ssl/ssl/server-password.key
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,B335CBE53A05F4FC5805FC038BA80BA0
+
+1U4+GwI8FGpcrk+9uzMlQU5UZ9xOJMOZb9xA3IYMw+2BLF7zVbAkYyyiqF2pKUmi
+doOYFOGIXNV1VhVwlw674SMN+PIg72b2F7DDrqEYlicLCU4o7eeGhoiIKzTksRTU
+YV3nYCCDZCEw7V+pFeGCUAc9fc+Y0BGMYIshLVdlTYgVjZScL5kHuD9t8xa6AaTS
+mQp3jInRnHjEJbRSZnFQ9CR1LUtmGE02TOcWzoGshFdwCdtO/lJzBmmMxoL/qV1R
+Cqc0PKSANsbgvTJMriZXYSFjpMYXmxBQXDYNuFfwq67bssAVIpTSvWu9SfcY/JwV
+OqERcb1zPgDmprDvd/L7Vh/cdEWWWewOVoUo89cT7CrLvMINHqE6smM2x1xv91BB
+AOpyoGJliPGAcLDVJINm9zC1ErEjSEcR/VumZKsgSTsBYgyYezTPQYAfe+h820rs
+eC4GMu+zr31U2TVLYcb4j2t19fTgaQBj/LH3OBse9+0quoJhzmDjKelS3O3BaF05
+DM20tJRHANM+1WQ9+aFinXa1ozcGsrLSUa99oFqL4vKgL7jd0+wmCzwxaSp3rHB3
+AFHCdUOayDAdPhnGwathhAZ0AjyEJyWnA47pEpWDr7SytpbiMwOoPcW8/oKid10e
+qBK7uGK1Zc7rtckjK3CrM1VFDbxzwGbF2aKHtFFyrJtUvJwfP0Y1V2DncOsiy5Nx
+gJ3vxfi11gxnhd9VmcoY3JVvTHOsw48xYNFrZXve/X3o9eUDqb9VRs/vV3t5w+xR
+RaUPdz9cdlp2AA4xW/IvIQ7XwuBWPaPVr/g9pUvI9iJ9Z4RdruvjqDAD+ICVx9MM
+8SuN7X3gmg4mF5FEL0ct5ZdP16U8/EYvl7Np7vN3kYqbqucwCJH15R8LckAfbzIH
+yYTXC1iik4GfyN9tTpQtZsZCvV2Uo+Fo3mxP/EzB6tNbfOi3LG/coverSwgZLQsA
+Q6+Kta4PT671xXdaGLT9tEMIai9SiW5acqcdhjYvcaP69J8ZtKpNpP6HTL7IZD8p
+SbMxE9jw+bYXILR3Ie0x98z4Z04Q28/bPbvPTbXK8nv6/YpjKgq4hrRG58psHdbX
+ggS3RNzcJJMDArBka+zvbWL4jfWZhllMyGqc7q/FuoEqC5JlMTUBpru3NTNp6ZgQ
+QXRV1Pc02ff8Dp1H8FP7B7bG3E2D9eTUqR60WvmGnuAqvXgA0+4rEaUKfxELH5qc
+dZgu/yiuMttCha835wMLnOxsOJmHILwrc6/uQWydx3vNEWFx0tbV3FzVBIvqdpME
+LA4iAAz5xqvLgA5ii23Hn18ycZGU7gTERK8RdiALRzPtBW6hPreQjiMTJnBaMhXA
+Xq9opGsNmH/rZgXuk2VZ79bbl9pKN+z9ssRGzbHCVlEckfaxlrYfANwzk8PbOrZJ
+6UW3Gf2PwRRNtiVEabf0upVng7V70KSRzjfC7KBHYwbRIL4nObgTG+vc1SjgNgrx
+Ue/e8h9qiDBmgdH0Uvqfqb19HF+QzmUNoP9TVQFj+4+DuW5zN0D8weF4TuBgyHr6
+Y+Rbmq0WJlIlc8KMwX87nACesmFNSJkI0ftSLDHrLuvXRtB8f7s2cw3hd81i+scE
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-revoked.crt b/src/test/ssl/ssl/server-revoked.crt
new file mode 100644
index 0000000..1ca5e6d
--- /dev/null
+++ b/src/test/ssl/ssl/server-revoked.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC/DCCAeQCAQYwDQYJKoZIhvcNAQELBQAwQjFAMD4GA1UEAww3VGVzdCBDQSBm
+b3IgUG9zdGdyZVNRTCBTU0wgcmVncmVzc2lvbiB0ZXN0IHNlcnZlciBjZXJ0czAe
+Fw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEYxHjAcBgNVBAsMFVBvc3Rn
+cmVTUUwgdGVzdCBzdWl0ZTEkMCIGA1UEAwwbY29tbW9uLW5hbWUucGctc3NsdGVz
+dC50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAooPO8lSz434p
+4PBYBbTN8jkLW3cHEpTCH4yvC0V40hzGEl30HPLp82e+kxr+Q0+gd82fvc4Yth5I
+PKINznp28GMs5/E9cUU3hMK4jFhKLMiOeIve3M/9ryHK874qpNjJoSxxPz7+s2eq
+WoFc2px0KFIamTTLfi7Ju9aPb/AMlZNsUnbRsj7fQc7EJ8rwOnezw2Wy5VK4soX+
+qpuJ0Nm44ApzT8YmjYX/kAX0yQxgQuYbpcBWr9cOQjegu3FAqHqRh9ye7d8jQzCv
+34Wg/ar4rkqyQDcokuWAE7KQbnk51t7omzhM8eswFOAL1pas/8jWBvy0VjYVU34P
+9aXxP8GiHQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAS9abT/PhJgwAnm46Rzu16
+lL7tDb3SeR1RL25xZLzCexHcYJFi7aDZix3QlLRvf6HPqqUPuPYRICTBF4+fieEh
+r5LotdAnadfYONwoB5GiYy2d93VGqlLosI27R6/tVvImXupviPpIYMDgBBRr1pZc
+ykQOjog6T+xk9TqsfFQDe2/VKF7a5RxOA/V77GZ5qge5Nlx9jSXQ/WUG9vDQj9BA
+d4nOwvjauKlcSqUU/3uVKntXQTNjmyq7S75eBitS920LLfjTL9LInLugDikFa/J/
+yPBkJLa/+rNMPikcnF3ci4Oi/XwLA8kGdGZAADuiIOeyORMuLFoTk7KpOYGKS5/U
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-revoked.key b/src/test/ssl/ssl/server-revoked.key
new file mode 100644
index 0000000..1787754
--- /dev/null
+++ b/src/test/ssl/ssl/server-revoked.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAooPO8lSz434p4PBYBbTN8jkLW3cHEpTCH4yvC0V40hzGEl30
+HPLp82e+kxr+Q0+gd82fvc4Yth5IPKINznp28GMs5/E9cUU3hMK4jFhKLMiOeIve
+3M/9ryHK874qpNjJoSxxPz7+s2eqWoFc2px0KFIamTTLfi7Ju9aPb/AMlZNsUnbR
+sj7fQc7EJ8rwOnezw2Wy5VK4soX+qpuJ0Nm44ApzT8YmjYX/kAX0yQxgQuYbpcBW
+r9cOQjegu3FAqHqRh9ye7d8jQzCv34Wg/ar4rkqyQDcokuWAE7KQbnk51t7omzhM
+8eswFOAL1pas/8jWBvy0VjYVU34P9aXxP8GiHQIDAQABAoIBABp1d0YBAGCzc8IJ
+n2seasFbBDxZ/q7JxWk5kG43W1pqEN2AqnPkIK7eXyq4JFl1J10Z/z35xhAwkfY9
+NB4/1gmBPBhvMF+2szlMMpu27CyqYnfB3gD5ZAYVbGOOvIamPP2erLltWi5/XD7r
+/OAixM6jv2zeKZtbpsCMSEIjRQk8+t4LXdT1ohrhm649QxmMpnYNjpXJ9U9uG0yP
+lr2+Lk2Xjv025kP765iGP3U5fW0/sONxXVM7uUyrvtnMJPhsKOdsNO84ratOVcnM
+BgzSEB0nldTcg7MUQyA+oOfDOXgoTQ5WZuXrx32sEDwN2ceCBg/qreaDwkC+KI7n
+nWazf0ECgYEA0ebcOCWwZlwvM/FNgC7Uqbxn6kjAkNvcETWxiwSaEf6MsTyytCJv
+RaVE7w5FsKKWxdu7ljft5LClNXTbscV5O5HuDMrLNSJFuhTm2dzYECZaUmXgN5gg
+JQAhhxevk3UBkGB/EYEDEBNtGjGWdWn0kFIsY4oN5l946cA27WXmsSUCgYEAxjTA
+XfGgM3+Q6hepN0J9XuVaebEkuTMlFmt82J4pMZxlam9zJDrDbzGVZ4kjCqLTh89v
+Tt+hE3xu+Df5D4Vb/uC+bu4EBpnvlqJRPNz4aQFxt+UILznS+oS4mLV1gK5PbIMA
+gh1+F58XJp3+NKxvUnjERpiUzZRgSh+9gtwWx5kCgYB3cfYzhU8CkMbTuicuIHgo
+NuyzZ78dL9/lczabM30xbDdHzJCs7UOA0HGP0AFcaMl/wnDXJPCdSOBasSsr2IIK
+ohpi8Sv+Coi/QZG0vHW/ivOvHAYh3NG9/HsX0yS4tsazEBZ/MXk6trNJSpqiKi9f
+yUM1SaRrSj0WV6lqIqjKeQKBgDw27nIb4/WBPb9AbPISyw+3UeNCg8uX1B6ZjRYq
+Bo3B27WYIjzRdWokgCUyLmkeynCp/kDSA5dt6DCUoJ+sfiRSlsgQmzx+K6Fxsohx
+AS61d5zMgc4HHSdqhsIt7oKncg2fRtpAp3v5owjiWsYZ1MATXF2uIRbLiu0581L8
+FheRAoGBANFH5W0DtT9kyzdiPddfBMFnrsUYYIPgejAao7PvCCW5tX8CVDcRkLhf
+tC9zZgA9WEm1irXZtbo9m3LYzH3yED8DvBcsfCdA20R/Ed/om2OiLKD7DDFl1W+C
+2NrwzcQlRlhHC8V2D8yRU+6YQ4Eu9dYzFnkGeCGSbiqaa9ZkPYx8
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-single-alt-name.crt b/src/test/ssl/ssl/server-single-alt-name.crt
new file mode 100644
index 0000000..e7403f3
--- /dev/null
+++ b/src/test/ssl/ssl/server-single-alt-name.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0
+IENBIGZvciBQb3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNl
+cnRzMB4XDTE4MTEyNzEzNDA1NFoXDTQ2MDQxNDEzNDA1NFowIDEeMBwGA1UECwwV
+UG9zdGdyZVNRTCB0ZXN0IHN1aXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxYocLWWuiDsDzJ7wLc0zfwkGJAEy4hlHjTA5GXSEnGPlOnx1fxejZOGL
+1HLff5h8zB+SQXrplHCcwwRrxVgGY7P59kXMXX1akTwXUJHc/EoTtqLO+6fHLygz
+F1d0i5NPO3xrk1wMt7bYLhiPbWpplWiHXzbJy8wf3dXgzCwtxXf8Z1UqjtCnA/Zk
+J/kPWuHJxzH5OvDJvZsq+Fbkl3catFpwUlAV9TKsC78W/K5I+afzppsmSvsIKAWW
+Dp7g71IVjvJeI6Aui2yhDn9iuJMuKe9RMYIwJLFqiX3urHcjaBSkJm6Lsf7gO30v
+kVwIyyGXRNTfZ2yPDoSXVZvOnq+gKwIDAQABoy4wLDAqBgNVHREEIzAhgh9zaW5n
+bGUuYWx0LW5hbWUucGctc3NsdGVzdC50ZXN0MA0GCSqGSIb3DQEBCwUAA4IBAQBU
+8wp8KZfS8vClx2gYSRlbXu3J1oAu4EBh45OuuRuLOJUhQZYcjFB3d/s0R1kcCQkB
+EekV9X1iQSzk/HQq4uWi6ViUzxTR67Q6TXEFo8iuqJ6Rag7R7G6fhRD1upf1lev+
+rz7F9GsoWLyLAg8//DUfq1kfQUyy6TxamoRs0vipZ4s0p4G8rbRCxKT1WTRLJFdd
+fSDVuMNuQQKTQXNdp6cYn+ikEhbUv/gG2S7Xiy2UM8oR7DR54nZBAKxgujWJZPfX
+/ieSwLxnLFyePwtwgk9xMmywFBjHWTxSdyI1UnJwWC917BSw4M00djsRv5COsBX7
+v/Co7oiMyTrCqyCsWOBu
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-single-alt-name.key b/src/test/ssl/ssl/server-single-alt-name.key
new file mode 100644
index 0000000..f719b0d
--- /dev/null
+++ b/src/test/ssl/ssl/server-single-alt-name.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAxYocLWWuiDsDzJ7wLc0zfwkGJAEy4hlHjTA5GXSEnGPlOnx1
+fxejZOGL1HLff5h8zB+SQXrplHCcwwRrxVgGY7P59kXMXX1akTwXUJHc/EoTtqLO
++6fHLygzF1d0i5NPO3xrk1wMt7bYLhiPbWpplWiHXzbJy8wf3dXgzCwtxXf8Z1Uq
+jtCnA/ZkJ/kPWuHJxzH5OvDJvZsq+Fbkl3catFpwUlAV9TKsC78W/K5I+afzppsm
+SvsIKAWWDp7g71IVjvJeI6Aui2yhDn9iuJMuKe9RMYIwJLFqiX3urHcjaBSkJm6L
+sf7gO30vkVwIyyGXRNTfZ2yPDoSXVZvOnq+gKwIDAQABAoIBAEtW0EZUKIuWjm1l
+FM8zGvfRVkE3H9PxtkNX5/8YXFdVFiEHRLyzJEMebnkZUrpUSwyC4gINQba2eGM8
+dWnvl4hBJQ1TM41YeMk5dN7qsrCaBAi88VozdBk9KLc3SKDPDwHuAw1RpxwOJUb3
+YQRm+FveYPrkZ3RNpr2xi6nzE4XjAH3LbF8EqBYC7LUm4GUxBl6Ke2rQiC8XwE0B
+0V0nvBvjkJ4tT4l9RTtInRr2vmqSWXp5bGVuuWqWxA/tBtTHhGbO+PG4i+C+u3NL
+qQgCbboqxyivPaMiMDdDhQL9TjAMCkItVxcwZlGdSA0+d5mraIXhs2ifF45soo4Y
+9vb4++kCgYEA6YpFAqYJnL0p5AIh14yxhWykLaE1YpKkw4P9SpxtGQIfwNDHyXme
+v/S66fLNvOjQyH6Y+gvGBGVHAwpM0RiPAHBADKAue6V9pbUITD0aQL9HOj9LEC+V
+8R2S5VSxNDpnMnd0DVdxiWGuNhzTG2McFXYduC3NpTLurK6ecPhVoI8CgYEA2ImC
+ZN2NS15AxWybddSgYYcL/44t9dfpEJ/4PJ1ISStIibHqpVWkq7vC4P7mMmS3DItr
+N3QDjBGltc1R4UfSCLakzSs5buC0LiO2uoMZFcOiZEd0r73iTLM8d9wOZRysYtHw
+T2tS1NvMrwK4TGZh+GWuUlSfuIbZ505PCQfYnKUCgYBdynoMpkIWAKJiP7j3qDlj
+LE6DRMr724jwPIHtBQWLlZ7LAQ47i+yFivPGIQ0fYSD4ZF9rjG7qNQJf5jMThpln
+w6z1ZR9F6SCc/Cdo9uEkP62LZv/ucC33t7jXATxpjUsEqZSiBwxB8EjW0py10wfk
+Vpt47Gw6fEn+b+KR3CoHYQKBgQDYKe4R41p6Ms1WSOWo62pv8fD4XWdkVPZFsmyN
+ljXjVWJEk2g7RRPunLIfClejVwelbkjKQvaHjdZvd1iWHKyAJlS+vLfJCGjW5rAz
+4UvZfkNO+EZ0aorPJt7miLeWGNm+jPXpUqqN9B6RV5XELzD+WAN+DRyliXlef75G
+tZ54QQKBgQCDXfap0mLGYXbFMLPF4Q1mnML5deVjyoGteAF+qky54rZvf0h2bWN2
+pi8hUOdwTtazgkd+rJp/a7eqQL/72nvCMonsb7vBNHmmNqZgaC9zyTV9AOE0Txc/
+vU6rvU+nQvt7esuTILS1O4SEeNI0JG22Dx01ebJQuKDcyOTOxv56vw==
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server-ss.crt b/src/test/ssl/ssl/server-ss.crt
new file mode 100644
index 0000000..d775e60
--- /dev/null
+++ b/src/test/ssl/ssl/server-ss.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDGDCCAgCgAwIBAgIUVR71MjsbvBO6T1gJQaL/6hMwhqQwDQYJKoZIhvcNAQEL
+BQAwRjEkMCIGA1UEAwwbY29tbW9uLW5hbWUucGctc3NsdGVzdC50ZXN0MR4wHAYD
+VQQLDBVQb3N0Z3JlU1FMIHRlc3Qgc3VpdGUwHhcNMTgxMTI3MTM0MDU0WhcNNDYw
+NDE0MTM0MDU0WjBGMSQwIgYDVQQDDBtjb21tb24tbmFtZS5wZy1zc2x0ZXN0LnRl
+c3QxHjAcBgNVBAsMFVBvc3RncmVTUUwgdGVzdCBzdWl0ZTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBANWzVPMk7i5f+W0eEadRE+TTAtsIK08CkLMUnjs7
+zJkxnnm6RGBXPx6vK3AkAIi+wG4YmXjYP3GuMiXaLjnWh2kzBSfIRQyNbTThnhSu
+3nDjAVkPexsSrPyiKimFuNgDfkGe5dQKa9Ag2SuVU4vd9SYxOMAiIFIC4ts4MLWW
+Jf5D/PehdSuc0e5Me+91Nnbz90nlds4lHvuDR+aKnZlTHmch3wfhXv7lNQImIBzf
+wl36Kd/bWB0fAEVFse3iZWmigaI/9FKh//WIq43TNLxn68OCQoyMe/HGjZDR/Xwo
+3rE6jg6/iAwSWib9yabfYPKbqq2GoFy6aYmmEquaDgLuX7kCAwEAATANBgkqhkiG
+9w0BAQsFAAOCAQEAtHR6o4UIO/aWEAzcmnJKsQDC999jbQGiqs9+v62mz5TvCk/1
+gL9/s/yfGY+pnDGW1ijI2xiL9KCJzjd8YB+F8iUViVQ6uHBxghxC1H2qOIr2UPFQ
+gQRu7d0DByQBsiXMOdw10luGo1oHhqMe5J7VyMVG/7aRpr6zYKrH7PzsB8ucvxzv
+Lm8ez0WBPebV69sim431iJcVcxxBbFd4qUJ9cHIc7VO2mSaazsIOzbd400POF/vk
+gfpDs48GfnZ+X3hgoQA4u7eudLqttI+j1xV+IHlCtaa1nDHymUrN/FhI1x+6c1SU
+V12eHqVatPMe0d+OCJPqIL9lbe+sGXlxDkMqAQ==
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server-ss.key b/src/test/ssl/ssl/server-ss.key
new file mode 100644
index 0000000..a5e7f4b
--- /dev/null
+++ b/src/test/ssl/ssl/server-ss.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAttI8Qu3wJgwp9RqLEqgO5GlYdA4bG+OyB4y+Bx4DQ7fhaJvJ
+vwBfY8ig+nPZU5WJNDyoaPtDg2uQwWbUq9WXkdktAxelrisQ/oJiCscPARlAIM6U
+XPOXai10XQ6QsMaaa6cXIGkMZVfhYEbuN0Q8TJSC1MbSQ/TtCnWxMRmktRv5xx8y
+2DgGbYRSiuBNE0vneQMjBJeRs19k/V8Alk49vOk8T8Ep0PFkAQglpUc7/LFueKry
+sVW+6ptdmqqHUZTdZhU/IojKEhUF8dtyGpGF9bE0kfjB7vXth8LKQ9Utik7VS1tQ
+E8fK2ttvxAqDf8s3MChnXbMN6QrzaGSS44oZKwIDAQABAoIBAQCsMhjQcYxgSdS7
+J+UWDXT5bsABj8e43R4yPj4+NeadQfTtss6zOIagVbhKLhPkxlQU/40gVIminw4Z
+G+H0d5nrpcLfxsYm5il7jxMJU7SuNDpSrEDRzB4xw952R+HAn0+TVi5SOJ+UVNHS
+/Pwi0gJ5nugbwakKmQcrcu8ScDTS34yFScMIRUYiKQ44TDiDtwyL07sc4ob1X/uY
+na1GnyOBjYEg+9nRwmV+QZwPjyP3Qe81rvH7saV2R2oc4uFU151KtoIT96V4FnpD
+CsFPGVul4i428zYDEguzEMWvPkOKrfFA63gfYl3JRbPYE9ISdZXU8UX6XEE3Y6sU
+VmeXK/IBAoGBAPLELsFdMqMhycXxrGuQ4HiH5/vQ2RhFcOf842a8qysopFC5kluf
+Y83dMy9GP8BLgt/NMseBDFcaGgaZPhD10kpW0BCg5GKdkcBfuIE5C/rfe4m82TqC
+VkriGimG8FkTCQS9ghGwbDWYZnMZbqyJ2iRt/+M9Lvfd1tYTCQtNuI/TAoGBAMDJ
+g/vS12j4uJ+SDy7QY6suSOjkQoGO8qonhx9W/2XJSH4KL1ubeOt4eOJksHnwueCW
+YD+2+T4+NDumMnmT7Rl8is1RfnnWNH91tylPB9I5Hyff/+PU5rUSoRfpmeckH3pc
+5EmfoaqT7V436hjkZF1uY1QJjDMopSyg3TSVmtJJAoGBAOAVAAdSDGSR0ppYuktL
+njcDU7mXjFwf9NjeD9UL/39F823j7NmPpWMnc5CGamAIE1SbJu0KDCb2G+HNX4Hu
+Nd6ShVlj+YuhYCDO+hKlYo597J016Nld52MVkwqT2JSPwnpSppXHYAqUkrRZXFP8
+ppOLyW+qUQlQBnbxeR6q7dorAoGAU/gxzYCDJIyY1Z/njwtjLg8l4JJzSTz7AxPe
+bc8VxL7MHWHQSMVKAL3jYTBcEXDBdUnqODY5D1xGoeh8uamtrtkpF860GNss2Its
+MMjkbjNFF7ggG5sCtcGceu7bguqf70sAf/TQlJyD2fLeuuLXuD45c0QJVcsRToPu
+dVXoLkkCgYEA5JkhCPE9a2ssrqi1ZFt3FAayulycM+r+wJY7zNIwv/ydzbE5D4Ar
+s8YOjhwyBoyorrEztcvIKF5XA89ZIwHiKZQxJTWGeFKq/PYTclzwlOXAimkdYNXn
+Nc/5RLjEeophXb4f3WPjMBliYGX0tOPhT+buHep+f0enxgO8Z2a4Omg=
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/ssl/server.crl b/src/test/ssl/ssl/server.crl
new file mode 100644
index 0000000..717951c
--- /dev/null
+++ b/src/test/ssl/ssl/server.crl
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBnjCBhzANBgkqhkiG9w0BAQsFADBCMUAwPgYDVQQDDDdUZXN0IENBIGZvciBQ
+b3N0Z3JlU1FMIFNTTCByZWdyZXNzaW9uIHRlc3Qgc2VydmVyIGNlcnRzFw0xODEx
+MjcxMzQwNTVaFw00NjA0MTQxMzQwNTVaMBQwEgIBBhcNMTgxMTI3MTM0MDU1WjAN
+BgkqhkiG9w0BAQsFAAOCAQEAbVuJXemxM6HLlIHGWlQvVmsmG4ZTQWiDnZjfmrND
+xB4XsvZNPXnFkjdBENDROrbDRwm60SJDW73AbDbfq1IXAzSpuEyuRz61IyYKo0wq
+nmObJtVdIu3bVlWIlDXaP5Emk3d7ouCj5f8Kyeb8gm4pL3N6e0eI63hCaS39hhE6
+RLGh9HU9ht1kKfgcTwmB5b2HTPb4M6z1AmSIaMVqZTjIspsUgNF2+GBm3fOnOaiZ
+SEXWtgjMRXiIHbtU0va3LhSH5OSW0mh+L9oGUQDYnyuudnWGpulhqIp4qVkJRDDu
+41HpD83dV2uRtBLvc25AFHj7kXBflbO3gvGZVPYf1zVghQ==
+-----END X509 CRL-----
diff --git a/src/test/ssl/ssl/server_ca.crt b/src/test/ssl/ssl/server_ca.crt
new file mode 100644
index 0000000..9f727bf
--- /dev/null
+++ b/src/test/ssl/ssl/server_ca.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIBATANBgkqhkiG9w0BAQsFADBAMT4wPAYDVQQDDDVUZXN0
+IHJvb3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzdWl0
+ZTAeFw0xODExMjcxMzQwNTRaFw00NjA0MTQxMzQwNTRaMEIxQDA+BgNVBAMMN1Rl
+c3QgQ0EgZm9yIFBvc3RncmVTUUwgU1NMIHJlZ3Jlc3Npb24gdGVzdCBzZXJ2ZXIg
+Y2VydHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiSnYZbmc9vpCt
+Ku1sKV9l663JCceubhMw8Gg16kV0hXEFf/TgGC4zkiYNHN7+G45YD7Nq0kBCq3dH
+t2wPCc6c8pQoI64dfprVqPkvzoe1WBpZNetkUTk20v08jNeRa7XdRbRR6we1s9VG
+/prp8Hs2mmHqEfLuI9lvTT0Dz+VMmfFI8Lf278r+w+qOtVloAkX7AOyoLEJlNS0B
+QW9YWdH9N5ctaUXMG6lLV2OAjs+W1smpKfpIpMCA1lPGlElu70hynon/nQQvBP77
+SfQpZVc0esM18jkZpr5LEKUCw+x6LaMsqmBHpAULfCffxn2r0uMBW4L4VaGg3W6F
+h6iuJwRfAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AFlcKTaU/Ug3Q0hr3P1UQ6dWyK4aVn9rs4jvVfFl0a0RnbBowqK2C+zQVUWYTcjo
+KHREVje65goj6VzRB6ko/9mAQ6PZP8jRuRhfCmvmvSQ/mWdgPzSRsUh9MwgEm9c2
+vNbqwaznEU8cYZnLpHiR9O5S7/qWWxehjYtxk5Eb4J006YglYfHnhrRFJvPbiqlf
+IOEivZ7gIVfvaOTbLjmN2kLOnzdlwpXGjxxg4Nu9ZhXOhfrplzUvRfmqvVsDiHXb
+USIdX+OFZZqr64IKG4drT4K4Bt2wupOEyX4ZFsUXXd+Hgq83SWmV4wzflcpmGkLC
+JZ3CEMu8/WA5uQBXdQUozlE=
+-----END CERTIFICATE-----
diff --git a/src/test/ssl/ssl/server_ca.key b/src/test/ssl/ssl/server_ca.key
new file mode 100644
index 0000000..0204dcf
--- /dev/null
+++ b/src/test/ssl/ssl/server_ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA4kp2GW5nPb6QrSrtbClfZeutyQnHrm4TMPBoNepFdIVxBX/0
+4BguM5ImDRze/huOWA+zatJAQqt3R7dsDwnOnPKUKCOuHX6a1aj5L86HtVgaWTXr
+ZFE5NtL9PIzXkWu13UW0UesHtbPVRv6a6fB7Npph6hHy7iPZb009A8/lTJnxSPC3
+9u/K/sPqjrVZaAJF+wDsqCxCZTUtAUFvWFnR/TeXLWlFzBupS1djgI7PltbJqSn6
+SKTAgNZTxpRJbu9Icp6J/50ELwT++0n0KWVXNHrDNfI5Gaa+SxClAsPsei2jLKpg
+R6QFC3wn38Z9q9LjAVuC+FWhoN1uhYeoricEXwIDAQABAoIBAG/c2Ua3Eegu5PwF
+hXp7dUI/4BfKcuBiX7BIl2tXlOAF+xn56AZDTcuGirLeu8knvBUCJfI/Xy7V7lAQ
+dyVz9qQVMnIpOTAxXr8SGaStVt6pX9UL14IuuLbGVBLzmLi1YyCwDXSVV6lV7a97
+uv68N1yFsrNwDgP0ys6/gtL4mWRkouFBbfJS9gDQjgSYTjWUx4wSkMw8h939RPkS
+ccmdXJxwhDBTP8iJIhVVR0FK7fCQvsQCuchsvYPTu5VCExTfNhO5A8oGZncnQRPH
+/RAAdPW2kAZV2oKkz5RAIDTnVkhXv1wQLty9E2PgjE04Fexe4Q7PCGmbrh7nBp73
+ARVuTRECgYEA/U3gwte+2pRzEciuoB4b+8Sod9eBxQGLhcQWOx2o0PAL2FIVWKxO
+exUC/ipmEX0mEwnAvVKGO1MTsOj6LUZELgbnygscLEQc1bNauKuQu/ChVfBgJ9ng
+IQR6z2BhrsOflfU8n01oMOjfVlVzZMdI5Nwy09OQgzu8tA125TUSkPkCgYEA5LL8
+bh5iykAlgXy7pA6WZmZXV9kaSTdnGGZ6GS4sbFJ8ZVw+tWi+xTUL9DES4keQTga7
+uneWu7q8wP7zdHCnKRhhBnbKFz1Voh4Z2VNSW9OjJHS4+lZfd94JZavOdwVMOQK9
+9Zjn2nsZalGb77pP/zDQSHnptwJOAKV9K5X5bhcCgYEA3wCODNtlogepWpHD8yEu
+37Nd4cvv6mIW1Fgyfi75baC3vOVe96cSnNd9wAfRvjngqEgg0Exz8oyMPGaPwgYn
+hiH8NGsdjXcVr6nsB8K7dEo/r2olLVBqOoc4G5Qty29b8uhpS5IZVV3fKaGnKqUr
+7phRgx2yD2crFZT5BId55fkCgYEA0pk39zeoBVL4trrkF/kO6pEHkW/s0stf9oo3
+mYR5h+6VesltPaSNOBDXRzEBkLoR2qg8q0OA3LLjKl4cVnd+l0tJ3af6BViHyNgr
+OYOO7dx/+Qw7Ytuy4jDnOmbxo4yPWlh6EPWTXA/LoaoxDJrnG7oZswQBAnPu3I2I
+LGDY5lUCgYEAp/utnKRE/mXDFryMHJL2/srlg6EffzeM3ncpXhzZDmaKeMUadjKo
+vNmhneHA7CSZM5LjUAiw4LfRx1V4hrKVtYmtizXKBbGYVZDD4CSh52T8w4nxNN6D
++uw478XrZzjjuCWODpdIKfngo9ip9+TysUZuFdmE3xKRitmDvW//aRE=
+-----END RSA PRIVATE KEY-----
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
new file mode 100644
index 0000000..8cdd0d2
--- /dev/null
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -0,0 +1,600 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+use File::Copy;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use SSLServer;
+
+if ($ENV{with_ssl} ne 'openssl')
+{
+ plan skip_all => 'OpenSSL not supported by this build';
+}
+else
+{
+ plan tests => 110;
+}
+
+#### Some configuration
+
+# This is the hostname used to connect to the server. This cannot be a
+# hostname, because the server certificate is always for the domain
+# postgresql-ssl-regression.test.
+my $SERVERHOSTADDR = '127.0.0.1';
+# This is the pattern to use in pg_hba.conf to match incoming connections.
+my $SERVERHOSTCIDR = '127.0.0.1/32';
+
+# Allocation of base connection string shared among multiple tests.
+my $common_connstr;
+
+# The client's private key must not be world-readable, so take a copy
+# of the key stored in the code tree and update its permissions.
+#
+# This changes ssl/client.key to ssl/client_tmp.key etc for the rest
+# of the tests.
+my @keys = (
+ "client", "client-revoked",
+ "client-der", "client-encrypted-pem",
+ "client-encrypted-der", "client-dn");
+foreach my $key (@keys)
+{
+ copy("ssl/${key}.key", "ssl/${key}_tmp.key")
+ or die
+ "couldn't copy ssl/${key}.key to ssl/${key}_tmp.key for permissions change: $!";
+ chmod 0600, "ssl/${key}_tmp.key"
+ or die "failed to change permissions on ssl/${key}_tmp.key: $!";
+}
+
+# Also make a copy of that explicitly world-readable. We can't
+# necessarily rely on the file in the source tree having those
+# permissions. Add it to @keys to include it in the final clean
+# up phase.
+copy("ssl/client.key", "ssl/client_wrongperms_tmp.key");
+chmod 0644, "ssl/client_wrongperms_tmp.key";
+push @keys, 'client_wrongperms';
+
+#### Set up the server.
+
+note "setting up data directory";
+my $node = get_new_node('primary');
+$node->init;
+
+# PGHOST is enforced here to set up the node, subsequent connections
+# will use a dedicated connection string.
+$ENV{PGHOST} = $node->host;
+$ENV{PGPORT} = $node->port;
+$node->start;
+
+# Run this before we lock down access below.
+my $result = $node->safe_psql('postgres', "SHOW ssl_library");
+is($result, 'OpenSSL', 'ssl_library parameter');
+
+configure_test_server_for_ssl($node, $SERVERHOSTADDR, $SERVERHOSTCIDR,
+ 'trust');
+
+note "testing password-protected keys";
+
+open my $sslconf, '>', $node->data_dir . "/sslconfig.conf";
+print $sslconf "ssl=on\n";
+print $sslconf "ssl_cert_file='server-cn-only.crt'\n";
+print $sslconf "ssl_key_file='server-password.key'\n";
+print $sslconf "ssl_passphrase_command='echo wrongpassword'\n";
+close $sslconf;
+
+command_fails(
+ [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
+ 'restart fails with password-protected key file with wrong password');
+$node->_update_pid(0);
+
+open $sslconf, '>', $node->data_dir . "/sslconfig.conf";
+print $sslconf "ssl=on\n";
+print $sslconf "ssl_cert_file='server-cn-only.crt'\n";
+print $sslconf "ssl_key_file='server-password.key'\n";
+print $sslconf "ssl_passphrase_command='echo secret1'\n";
+close $sslconf;
+
+command_ok(
+ [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
+ 'restart succeeds with password-protected key file');
+$node->_update_pid(1);
+
+# Test compatibility of SSL protocols.
+# TLSv1.1 is lower than TLSv1.2, so it won't work.
+$node->append_conf(
+ 'postgresql.conf',
+ qq{ssl_min_protocol_version='TLSv1.2'
+ssl_max_protocol_version='TLSv1.1'});
+command_fails(
+ [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
+ 'restart fails with incorrect SSL protocol bounds');
+# Go back to the defaults, this works.
+$node->append_conf(
+ 'postgresql.conf',
+ qq{ssl_min_protocol_version='TLSv1.2'
+ssl_max_protocol_version=''});
+command_ok(
+ [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ],
+ 'restart succeeds with correct SSL protocol bounds');
+
+### Run client-side tests.
+###
+### Test that libpq accepts/rejects the connection correctly, depending
+### on sslmode and whether the server's certificate looks correct. No
+### client certificate is used in these tests.
+
+note "running client tests";
+
+switch_server_cert($node, 'server-cn-only');
+
+# Set of default settings for SSL parameters in connection string. This
+# makes the tests protected against any defaults the environment may have
+# in ~/.postgresql/.
+my $default_ssl_connstr = "sslkey=invalid sslcert=invalid sslrootcert=invalid sslcrl=invalid sslcrldir=invalid";
+
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
+
+# The server should not accept non-SSL connections.
+$node->connect_fails(
+ "$common_connstr sslmode=disable",
+ "server doesn't accept non-SSL connections",
+ expected_stderr => qr/\Qno pg_hba.conf entry\E/);
+
+# Try without a root cert. In sslmode=require, this should work. In verify-ca
+# or verify-full mode it should fail.
+$node->connect_ok(
+ "$common_connstr sslrootcert=invalid sslmode=require",
+ "connect without server root cert sslmode=require");
+$node->connect_fails(
+ "$common_connstr sslrootcert=invalid sslmode=verify-ca",
+ "connect without server root cert sslmode=verify-ca",
+ expected_stderr => qr/root certificate file "invalid" does not exist/);
+$node->connect_fails(
+ "$common_connstr sslrootcert=invalid sslmode=verify-full",
+ "connect without server root cert sslmode=verify-full",
+ expected_stderr => qr/root certificate file "invalid" does not exist/);
+
+# Try with wrong root cert, should fail. (We're using the client CA as the
+# root, but the server's key is signed by the server CA.)
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=require",
+ "connect with wrong server root cert sslmode=require",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-ca",
+ "connect with wrong server root cert sslmode=verify-ca",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-full",
+ "connect with wrong server root cert sslmode=verify-full",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+
+# Try with just the server CA's cert. This fails because the root file
+# must contain the whole chain up to the root CA.
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/server_ca.crt sslmode=verify-ca",
+ "connect with server CA cert, without root CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+
+# And finally, with the correct root cert.
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require",
+ "connect with correct server CA cert file sslmode=require");
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
+ "connect with correct server CA cert file sslmode=verify-ca");
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-full",
+ "connect with correct server CA cert file sslmode=verify-full");
+
+# Test with cert root file that contains two certificates. The client should
+# be able to pick the right one, regardless of the order in the file.
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/both-cas-1.crt sslmode=verify-ca",
+ "cert root file that contains two certificates, order 1");
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/both-cas-2.crt sslmode=verify-ca",
+ "cert root file that contains two certificates, order 2");
+
+# CRL tests
+
+# Invalid CRL filename is the same as no CRL, succeeds
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=invalid",
+ "sslcrl option with invalid file name");
+
+# A CRL belonging to a different CA is not accepted, fails
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/client.crl",
+ "CRL belonging to a different CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+
+# The same for CRL directory. sslcrl='' is added here to override the
+# invalid default, so as this does not interfere with this case.
+$node->connect_fails(
+ "$common_connstr sslcrl='' sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/client-crldir",
+ "directory CRL belonging to a different CA",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+
+# With the correct CRL, succeeds (this cert is not revoked)
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
+ "CRL with a non-revoked cert");
+
+# The same for CRL directory
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
+ "directory CRL with a non-revoked cert");
+
+# Check that connecting with verify-full fails, when the hostname doesn't
+# match the hostname in the server's certificate.
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
+
+$node->connect_ok("$common_connstr sslmode=require host=wronghost.test",
+ "mismatch between host name and server certificate sslmode=require");
+$node->connect_ok(
+ "$common_connstr sslmode=verify-ca host=wronghost.test",
+ "mismatch between host name and server certificate sslmode=verify-ca");
+$node->connect_fails(
+ "$common_connstr sslmode=verify-full host=wronghost.test",
+ "mismatch between host name and server certificate sslmode=verify-full",
+ expected_stderr =>
+ qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E/
+);
+
+# Test Subject Alternative Names.
+switch_server_cert($node, 'server-multiple-alt-names');
+
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
+
+$node->connect_ok(
+ "$common_connstr host=dns1.alt-name.pg-ssltest.test",
+ "host name matching with X.509 Subject Alternative Names 1");
+$node->connect_ok(
+ "$common_connstr host=dns2.alt-name.pg-ssltest.test",
+ "host name matching with X.509 Subject Alternative Names 2");
+$node->connect_ok("$common_connstr host=foo.wildcard.pg-ssltest.test",
+ "host name matching with X.509 Subject Alternative Names wildcard");
+
+$node->connect_fails(
+ "$common_connstr host=wronghost.alt-name.pg-ssltest.test",
+ "host name not matching with X.509 Subject Alternative Names",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "wronghost.alt-name.pg-ssltest.test"\E/
+);
+$node->connect_fails(
+ "$common_connstr host=deep.subdomain.wildcard.pg-ssltest.test",
+ "host name not matching with X.509 Subject Alternative Names wildcard",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 2 other names) does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/
+);
+
+# Test certificate with a single Subject Alternative Name. (this gives a
+# slightly different error message, that's all)
+switch_server_cert($node, 'server-single-alt-name');
+
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
+
+$node->connect_ok(
+ "$common_connstr host=single.alt-name.pg-ssltest.test",
+ "host name matching with a single X.509 Subject Alternative Name");
+
+$node->connect_fails(
+ "$common_connstr host=wronghost.alt-name.pg-ssltest.test",
+ "host name not matching with a single X.509 Subject Alternative Name",
+ expected_stderr =>
+ qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E/
+);
+$node->connect_fails(
+ "$common_connstr host=deep.subdomain.wildcard.pg-ssltest.test",
+ "host name not matching with a single X.509 Subject Alternative Name wildcard",
+ expected_stderr =>
+ qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E/
+);
+
+# Test server certificate with a CN and SANs. Per RFCs 2818 and 6125, the CN
+# should be ignored when the certificate has both.
+switch_server_cert($node, 'server-cn-and-alt-names');
+
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full";
+
+$node->connect_ok("$common_connstr host=dns1.alt-name.pg-ssltest.test",
+ "certificate with both a CN and SANs 1");
+$node->connect_ok("$common_connstr host=dns2.alt-name.pg-ssltest.test",
+ "certificate with both a CN and SANs 2");
+$node->connect_fails(
+ "$common_connstr host=common-name.pg-ssltest.test",
+ "certificate with both a CN and SANs ignores CN",
+ expected_stderr =>
+ qr/\Qserver certificate for "dns1.alt-name.pg-ssltest.test" (and 1 other name) does not match host name "common-name.pg-ssltest.test"\E/
+);
+
+# Finally, test a server certificate that has no CN or SANs. Of course, that's
+# not a very sensible certificate, but libpq should handle it gracefully.
+switch_server_cert($node, 'server-no-names');
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR";
+
+$node->connect_ok(
+ "$common_connstr sslmode=verify-ca host=common-name.pg-ssltest.test",
+ "server certificate without CN or SANs sslmode=verify-ca");
+$node->connect_fails(
+ $common_connstr . " "
+ . "sslmode=verify-full host=common-name.pg-ssltest.test",
+ "server certificate without CN or SANs sslmode=verify-full",
+ expected_stderr =>
+ qr/could not get server's host name from server certificate/);
+
+# Test that the CRL works
+switch_server_cert($node, 'server-revoked');
+
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test";
+
+# Without the CRL, succeeds. With it, fails.
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca",
+ "connects without client-side CRL");
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl",
+ "does not connect with client-side CRL file",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+# sslcrl='' is added here to override the invalid default, so as this
+# does not interfere with this case.
+$node->connect_fails(
+ "$common_connstr sslcrl='' sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir",
+ "does not connect with client-side CRL directory",
+ expected_stderr => qr/SSL error: certificate verify failed/);
+
+# pg_stat_ssl
+command_like(
+ [
+ 'psql', '-X',
+ '-A', '-F',
+ ',', '-P',
+ 'null=_null_', '-d',
+ "$common_connstr sslrootcert=invalid", '-c',
+ "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()"
+ ],
+ qr{^pid,ssl,version,cipher,bits,client_dn,client_serial,issuer_dn\r?\n
+ ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,_null_,_null_,_null_\r?$}mx,
+ 'pg_stat_ssl view without client certificate');
+
+# Test min/max SSL protocol versions.
+$node->connect_ok(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=TLSv1.2 ssl_max_protocol_version=TLSv1.2",
+ "connection success with correct range of TLS protocol versions");
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=TLSv1.2 ssl_max_protocol_version=TLSv1.1",
+ "connection failure with incorrect range of TLS protocol versions",
+ expected_stderr => qr/invalid SSL protocol version range/);
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=incorrect_tls",
+ "connection failure with an incorrect SSL protocol minimum bound",
+ expected_stderr => qr/invalid ssl_min_protocol_version value/);
+$node->connect_fails(
+ "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_max_protocol_version=incorrect_tls",
+ "connection failure with an incorrect SSL protocol maximum bound",
+ expected_stderr => qr/invalid ssl_max_protocol_version value/);
+
+### Server-side tests.
+###
+### Test certificate authorization.
+
+note "running server tests";
+
+$common_connstr =
+ "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR host=localhost";
+
+# no client cert
+$node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=invalid",
+ "certificate authorization fails without client cert",
+ expected_stderr => qr/connection requires a valid client certificate/);
+
+# correct client cert in unencrypted PEM
+$node->connect_ok(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ "certificate authorization succeeds with correct client cert in PEM format"
+);
+
+# correct client cert in unencrypted DER
+$node->connect_ok(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-der_tmp.key",
+ "certificate authorization succeeds with correct client cert in DER format"
+);
+
+# correct client cert in encrypted PEM
+$node->connect_ok(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key sslpassword='dUmmyP^#+'",
+ "certificate authorization succeeds with correct client cert in encrypted PEM format"
+);
+
+# correct client cert in encrypted DER
+$node->connect_ok(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-der_tmp.key sslpassword='dUmmyP^#+'",
+ "certificate authorization succeeds with correct client cert in encrypted DER format"
+);
+
+# correct client cert in encrypted PEM with wrong password
+$node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key sslpassword='wrong'",
+ "certificate authorization fails with correct client cert and wrong password in encrypted PEM format",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": bad decrypt\E!
+);
+
+
+# correct client cert using whole DN
+my $dn_connstr = "$common_connstr dbname=certdb_dn";
+
+$node->connect_ok(
+ "$dn_connstr user=ssltestuser sslcert=ssl/client-dn.crt sslkey=ssl/client-dn_tmp.key",
+ "certificate authorization succeeds with DN mapping",
+ log_like => [
+ qr/connection authenticated: identity="CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG" method=cert/
+ ],);
+
+# same thing but with a regex
+$dn_connstr = "$common_connstr dbname=certdb_dn_re";
+
+$node->connect_ok(
+ "$dn_connstr user=ssltestuser sslcert=ssl/client-dn.crt sslkey=ssl/client-dn_tmp.key",
+ "certificate authorization succeeds with DN regex mapping");
+
+# same thing but using explicit CN
+$dn_connstr = "$common_connstr dbname=certdb_cn";
+
+$node->connect_ok(
+ "$dn_connstr user=ssltestuser sslcert=ssl/client-dn.crt sslkey=ssl/client-dn_tmp.key",
+ "certificate authorization succeeds with CN mapping",
+ # the full DN should still be used as the authenticated identity
+ log_like => [
+ qr/connection authenticated: identity="CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG" method=cert/
+ ],);
+
+
+
+TODO:
+{
+ # these tests are left here waiting on us to get better pty support
+ # so they don't hang. For now they are not performed.
+
+ todo_skip "Need Pty support", 4;
+
+ # correct client cert in encrypted PEM with empty password
+ $node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key sslpassword=''",
+ "certificate authorization fails with correct client cert and empty password in encrypted PEM format",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!
+ );
+
+ # correct client cert in encrypted PEM with no password
+ $node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client-encrypted-pem_tmp.key",
+ "certificate authorization fails with correct client cert and no password in encrypted PEM format",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client-encrypted-pem_tmp.key": processing error\E!
+ );
+
+}
+
+# pg_stat_ssl
+command_like(
+ [
+ 'psql',
+ '-X',
+ '-A',
+ '-F',
+ ',',
+ '-P',
+ 'null=_null_',
+ '-d',
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ '-c',
+ "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()"
+ ],
+ qr{^pid,ssl,version,cipher,bits,client_dn,client_serial,issuer_dn\r?\n
+ ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,/CN=ssltestuser,1,\Q/CN=Test CA for PostgreSQL SSL regression test client certs\E\r?$}mx,
+ 'pg_stat_ssl with client certificate');
+
+# client key with wrong permissions
+SKIP:
+{
+ skip "Permissions check not enforced on Windows", 2 if ($windows_os);
+
+ $node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_wrongperms_tmp.key",
+ "certificate authorization fails because of file permissions",
+ expected_stderr =>
+ qr!\Qprivate key file "ssl/client_wrongperms_tmp.key" has group or world access\E!
+ );
+}
+
+# client cert belonging to another user
+$node->connect_fails(
+ "$common_connstr user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ "certificate authorization fails with client cert belonging to another user",
+ expected_stderr =>
+ qr/certificate authentication failed for user "anotheruser"/,
+ # certificate authentication should be logged even on failure
+ log_like =>
+ [qr/connection authenticated: identity="CN=ssltestuser" method=cert/],);
+
+# revoked client cert
+$node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
+ "certificate authorization fails with revoked client cert",
+ expected_stderr => qr/SSL error: sslv3 alert certificate revoked/,
+ # revoked certificates should not authenticate the user
+ log_unlike => [qr/connection authenticated:/],);
+
+# Check that connecting with auth-option verify-full in pg_hba:
+# works, iff username matches Common Name
+# fails, iff username doesn't match Common Name.
+$common_connstr =
+ "$default_ssl_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=verifydb hostaddr=$SERVERHOSTADDR host=localhost";
+
+$node->connect_ok(
+ "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ "auth_option clientcert=verify-full succeeds with matching username and Common Name",
+ # verify-full does not provide authentication
+ log_unlike => [qr/connection authenticated:/],);
+
+$node->connect_fails(
+ "$common_connstr user=anotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ "auth_option clientcert=verify-full fails with mismatching username and Common Name",
+ expected_stderr =>
+ qr/FATAL: .* "trust" authentication failed for user "anotheruser"/,
+ # verify-full does not provide authentication
+ log_unlike => [qr/connection authenticated:/],);
+
+# Check that connecting with auth-optionverify-ca in pg_hba :
+# works, when username doesn't match Common Name
+$node->connect_ok(
+ "$common_connstr user=yetanotheruser sslcert=ssl/client.crt sslkey=ssl/client_tmp.key",
+ "auth_option clientcert=verify-ca succeeds with mismatching username and Common Name",
+ # verify-full does not provide authentication
+ log_unlike => [qr/connection authenticated:/],);
+
+# intermediate client_ca.crt is provided by client, and isn't in server's ssl_ca_file
+switch_server_cert($node, 'server-cn-only', 'root_ca');
+$common_connstr =
+ "$default_ssl_connstr user=ssltestuser dbname=certdb sslkey=ssl/client_tmp.key sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR host=localhost";
+
+$node->connect_ok(
+ "$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt",
+ "intermediate client certificate is provided by client");
+$node->connect_fails(
+ $common_connstr . " " . "sslmode=require sslcert=ssl/client.crt",
+ "intermediate client certificate is missing",
+ expected_stderr => qr/SSL error: tlsv1 alert unknown ca/);
+
+# test server-side CRL directory
+switch_server_cert($node, 'server-cn-only', undef, undef,
+ 'root+client-crldir');
+
+# revoked client cert
+$node->connect_fails(
+ "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=ssl/client-revoked_tmp.key",
+ "certificate authorization fails with revoked client cert with server-side CRL directory",
+ expected_stderr => qr/SSL error: sslv3 alert certificate revoked/);
+
+# clean up
+foreach my $key (@keys)
+{
+ unlink("ssl/${key}_tmp.key");
+}
diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl
new file mode 100644
index 0000000..a508bbd
--- /dev/null
+++ b/src/test/ssl/t/002_scram.pl
@@ -0,0 +1,119 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# Test SCRAM authentication and TLS channel binding types
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+use File::Copy;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use SSLServer;
+
+if ($ENV{with_ssl} ne 'openssl')
+{
+ plan skip_all => 'OpenSSL not supported by this build';
+}
+
+# This is the hostname used to connect to the server.
+my $SERVERHOSTADDR = '127.0.0.1';
+# This is the pattern to use in pg_hba.conf to match incoming connections.
+my $SERVERHOSTCIDR = '127.0.0.1/32';
+
+# Determine whether build supports tls-server-end-point.
+my $supports_tls_server_end_point =
+ check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1");
+
+my $number_of_tests = $supports_tls_server_end_point ? 11 : 12;
+
+# Allocation of base connection string shared among multiple tests.
+my $common_connstr;
+
+# Set up the server.
+
+note "setting up data directory";
+my $node = get_new_node('primary');
+$node->init;
+
+# PGHOST is enforced here to set up the node, subsequent connections
+# will use a dedicated connection string.
+$ENV{PGHOST} = $node->host;
+$ENV{PGPORT} = $node->port;
+$node->start;
+
+# Configure server for SSL connections, with password handling.
+configure_test_server_for_ssl($node, $SERVERHOSTADDR, $SERVERHOSTCIDR,
+ "scram-sha-256", "pass", "scram-sha-256");
+switch_server_cert($node, 'server-cn-only');
+$ENV{PGPASSWORD} = "pass";
+$common_connstr =
+ "dbname=trustdb sslmode=require sslcert=invalid sslrootcert=invalid hostaddr=$SERVERHOSTADDR host=localhost";
+
+# Default settings
+$node->connect_ok(
+ "$common_connstr user=ssltestuser",
+ "Basic SCRAM authentication with SSL");
+
+# Test channel_binding
+$node->connect_fails(
+ "$common_connstr user=ssltestuser channel_binding=invalid_value",
+ "SCRAM with SSL and channel_binding=invalid_value",
+ expected_stderr => qr/invalid channel_binding value: "invalid_value"/);
+$node->connect_ok("$common_connstr user=ssltestuser channel_binding=disable",
+ "SCRAM with SSL and channel_binding=disable");
+if ($supports_tls_server_end_point)
+{
+ $node->connect_ok(
+ "$common_connstr user=ssltestuser channel_binding=require",
+ "SCRAM with SSL and channel_binding=require");
+}
+else
+{
+ $node->connect_fails(
+ "$common_connstr user=ssltestuser channel_binding=require",
+ "SCRAM with SSL and channel_binding=require",
+ expected_stderr =>
+ qr/channel binding is required, but server did not offer an authentication method that supports channel binding/
+ );
+}
+
+# Now test when the user has an MD5-encrypted password; should fail
+$node->connect_fails(
+ "$common_connstr user=md5testuser channel_binding=require",
+ "MD5 with SSL and channel_binding=require",
+ expected_stderr =>
+ qr/channel binding required but not supported by server's authentication request/
+);
+
+# Now test with auth method 'cert' by connecting to 'certdb'. Should fail,
+# because channel binding is not performed. Note that ssl/client.key may
+# be used in a different test, so the name of this temporary client key
+# is chosen here to be unique.
+my $client_tmp_key = "ssl/client_scram_tmp.key";
+copy("ssl/client.key", $client_tmp_key);
+chmod 0600, $client_tmp_key;
+$node->connect_fails(
+ "sslcert=ssl/client.crt sslkey=$client_tmp_key sslrootcert=invalid hostaddr=$SERVERHOSTADDR host=localhost dbname=certdb user=ssltestuser channel_binding=require",
+ "Cert authentication and channel_binding=require",
+ expected_stderr =>
+ qr/channel binding required, but server authenticated client without channel binding/
+);
+
+# Certificate verification at the connection level should still work fine.
+$node->connect_ok(
+ "sslcert=ssl/client.crt sslkey=$client_tmp_key sslrootcert=invalid hostaddr=$SERVERHOSTADDR host=localhost dbname=verifydb user=ssltestuser",
+ "SCRAM with clientcert=verify-full",
+ log_like => [
+ qr/connection authenticated: identity="ssltestuser" method=scram-sha-256/
+ ]);
+
+# clean up
+unlink($client_tmp_key);
+
+done_testing($number_of_tests);
diff --git a/src/test/ssl/t/SSLServer.pm b/src/test/ssl/t/SSLServer.pm
new file mode 100644
index 0000000..804d008
--- /dev/null
+++ b/src/test/ssl/t/SSLServer.pm
@@ -0,0 +1,205 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+# This module sets up a test server, for the SSL regression tests.
+#
+# The server is configured as follows:
+#
+# - SSL enabled, with the server certificate specified by argument to
+# switch_server_cert function.
+# - ssl/root+client_ca.crt as the CA root for validating client certs.
+# - reject non-SSL connections
+# - a database called trustdb that lets anyone in
+# - another database called certdb that uses certificate authentication, ie.
+# the client must present a valid certificate signed by the client CA
+#
+# The server is configured to only accept connections from localhost. If you
+# want to run the client from another host, you'll have to configure that
+# manually.
+#
+# Note: Someone running these test could have key or certificate files
+# in their ~/.postgresql/, which would interfere with the tests. The
+# way to override that is to specify sslcert=invalid and/or
+# sslrootcert=invalid if no actual certificate is used for a
+# particular test. libpq will ignore specifications that name
+# nonexisting files. (sslkey and sslcrl do not need to specified
+# explicitly because an invalid sslcert or sslrootcert, respectively,
+# causes those to be ignored.)
+
+package SSLServer;
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use File::Basename;
+use File::Copy;
+use Test::More;
+
+use Exporter 'import';
+our @EXPORT = qw(
+ configure_test_server_for_ssl
+ switch_server_cert
+);
+
+# Copy a set of files, taking into account wildcards
+sub copy_files
+{
+ my $orig = shift;
+ my $dest = shift;
+
+ my @orig_files = glob $orig;
+ foreach my $orig_file (@orig_files)
+ {
+ my $base_file = basename($orig_file);
+ copy($orig_file, "$dest/$base_file")
+ or die "Could not copy $orig_file to $dest";
+ }
+ return;
+}
+
+# serverhost: what to put in listen_addresses, e.g. '127.0.0.1'
+# servercidr: what to put in pg_hba.conf, e.g. '127.0.0.1/32'
+sub configure_test_server_for_ssl
+{
+ my ($node, $serverhost, $servercidr, $authmethod, $password,
+ $password_enc) = @_;
+
+ my $pgdata = $node->data_dir;
+
+ # Create test users and databases
+ $node->psql('postgres', "CREATE USER ssltestuser");
+ $node->psql('postgres', "CREATE USER md5testuser");
+ $node->psql('postgres', "CREATE USER anotheruser");
+ $node->psql('postgres', "CREATE USER yetanotheruser");
+ $node->psql('postgres', "CREATE DATABASE trustdb");
+ $node->psql('postgres', "CREATE DATABASE certdb");
+ $node->psql('postgres', "CREATE DATABASE certdb_dn");
+ $node->psql('postgres', "CREATE DATABASE certdb_dn_re");
+ $node->psql('postgres', "CREATE DATABASE certdb_cn");
+ $node->psql('postgres', "CREATE DATABASE verifydb");
+
+ # Update password of each user as needed.
+ if (defined($password))
+ {
+ $node->psql('postgres',
+ "SET password_encryption='$password_enc'; ALTER USER ssltestuser PASSWORD '$password';"
+ );
+ # A special user that always has an md5-encrypted password
+ $node->psql('postgres',
+ "SET password_encryption='md5'; ALTER USER md5testuser PASSWORD '$password';"
+ );
+ $node->psql('postgres',
+ "SET password_encryption='$password_enc'; ALTER USER anotheruser PASSWORD '$password';"
+ );
+ }
+
+ # enable logging etc.
+ open my $conf, '>>', "$pgdata/postgresql.conf";
+ print $conf "fsync=off\n";
+ print $conf "log_connections=on\n";
+ print $conf "log_hostname=on\n";
+ print $conf "listen_addresses='$serverhost'\n";
+ print $conf "log_statement=all\n";
+
+ # enable SSL and set up server key
+ print $conf "include 'sslconfig.conf'\n";
+
+ close $conf;
+
+ # ssl configuration will be placed here
+ open my $sslconf, '>', "$pgdata/sslconfig.conf";
+ close $sslconf;
+
+ # Copy all server certificates and keys, and client root cert, to the data dir
+ copy_files("ssl/server-*.crt", $pgdata);
+ copy_files("ssl/server-*.key", $pgdata);
+ chmod(0600, glob "$pgdata/server-*.key") or die $!;
+ copy_files("ssl/root+client_ca.crt", $pgdata);
+ copy_files("ssl/root_ca.crt", $pgdata);
+ copy_files("ssl/root+client.crl", $pgdata);
+ mkdir("$pgdata/root+client-crldir");
+ copy_files("ssl/root+client-crldir/*", "$pgdata/root+client-crldir/");
+
+ # Stop and restart server to load new listen_addresses.
+ $node->restart;
+
+ # Change pg_hba after restart because hostssl requires ssl=on
+ configure_hba_for_ssl($node, $servercidr, $authmethod);
+
+ return;
+}
+
+# Change the configuration to use given server cert file, and reload
+# the server so that the configuration takes effect.
+sub switch_server_cert
+{
+ my $node = $_[0];
+ my $certfile = $_[1];
+ my $cafile = $_[2] || "root+client_ca";
+ my $crlfile = "root+client.crl";
+ my $crldir;
+ my $pgdata = $node->data_dir;
+
+ # defaults to use crl file
+ if (defined $_[3] || defined $_[4])
+ {
+ $crlfile = $_[3];
+ $crldir = $_[4];
+ }
+
+ open my $sslconf, '>', "$pgdata/sslconfig.conf";
+ print $sslconf "ssl=on\n";
+ print $sslconf "ssl_ca_file='$cafile.crt'\n";
+ print $sslconf "ssl_cert_file='$certfile.crt'\n";
+ print $sslconf "ssl_key_file='$certfile.key'\n";
+ print $sslconf "ssl_crl_file='$crlfile'\n" if defined $crlfile;
+ print $sslconf "ssl_crl_dir='$crldir'\n" if defined $crldir;
+ close $sslconf;
+
+ $node->restart;
+ return;
+}
+
+sub configure_hba_for_ssl
+{
+ my ($node, $servercidr, $authmethod) = @_;
+ my $pgdata = $node->data_dir;
+
+ # Only accept SSL connections from $servercidr. Our tests don't depend on this
+ # but seems best to keep it as narrow as possible for security reasons.
+ #
+ # When connecting to certdb, also check the client certificate.
+ open my $hba, '>', "$pgdata/pg_hba.conf";
+ print $hba
+ "# TYPE DATABASE USER ADDRESS METHOD OPTIONS\n";
+ print $hba
+ "hostssl trustdb md5testuser $servercidr md5\n";
+ print $hba
+ "hostssl trustdb all $servercidr $authmethod\n";
+ print $hba
+ "hostssl verifydb ssltestuser $servercidr $authmethod clientcert=verify-full\n";
+ print $hba
+ "hostssl verifydb anotheruser $servercidr $authmethod clientcert=verify-full\n";
+ print $hba
+ "hostssl verifydb yetanotheruser $servercidr $authmethod clientcert=verify-ca\n";
+ print $hba
+ "hostssl certdb all $servercidr cert\n";
+ print $hba
+ "hostssl certdb_dn all $servercidr cert clientname=DN map=dn\n",
+ "hostssl certdb_dn_re all $servercidr cert clientname=DN map=dnre\n",
+ "hostssl certdb_cn all $servercidr cert clientname=CN map=cn\n";
+ close $hba;
+
+ # Also set the ident maps. Note: fields with commas must be quoted
+ open my $map, ">", "$pgdata/pg_ident.conf";
+ print $map
+ "# MAPNAME SYSTEM-USERNAME PG-USERNAME\n",
+ "dn \"CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG\" ssltestuser\n",
+ "dnre \"/^.*OU=Testing,.*\$\" ssltestuser\n",
+ "cn ssltestuser-dn ssltestuser\n";
+
+ return;
+}
+
+1;