From db9befb049f8bc4d6c28937a2b47bf365fc368a7 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Mon, 8 Feb 2021 23:52:37 +0100 Subject: [PATCH v53 03/11] nss: Add NSS specific tests This adds the SSL/Backend/NSS which implements the setup and teardown required as well as adds the NSS configuration to the existing tests. The OpenSSL testfiles are reused by repackaging them into NSS databases in order for the tests to be cross-library. Additional testfiles are generated by using only the NSS toolchain as well as rudimentary tests using these. --- src/test/Makefile | 2 +- src/test/ssl/Makefile | 11 +- src/test/ssl/sslfiles.mk | 4 +- src/test/ssl/sslfiles_nss.mk | 268 +++++++++++++++ src/test/ssl/t/001_ssltests.pl | 458 ++++++++++++++++---------- src/test/ssl/t/002_scram.pl | 33 +- src/test/ssl/t/003_sslinfo.pl | 10 +- src/test/ssl/t/SSL/Backend/NSS.pm | 66 ++++ src/test/ssl/t/SSL/Backend/OpenSSL.pm | 24 +- src/test/ssl/t/SSL/Server.pm | 59 ++-- 10 files changed, 697 insertions(+), 238 deletions(-) create mode 100644 src/test/ssl/sslfiles_nss.mk create mode 100644 src/test/ssl/t/SSL/Backend/NSS.pm diff --git a/src/test/Makefile b/src/test/Makefile index 46275915ff..79246d59a4 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -27,7 +27,7 @@ ifneq (,$(filter ldap,$(PG_TEST_EXTRA))) SUBDIRS += ldap endif endif -ifeq ($(with_ssl),openssl) +ifneq (,$(filter $(with_ssl),openssl nss)) ifneq (,$(filter ssl,$(PG_TEST_EXTRA))) SUBDIRS += ssl endif diff --git a/src/test/ssl/Makefile b/src/test/ssl/Makefile index 12b02eb422..b22cb51556 100644 --- a/src/test/ssl/Makefile +++ b/src/test/ssl/Makefile @@ -18,14 +18,21 @@ include $(top_builddir)/src/Makefile.global export with_ssl # The sslfiles targets are separated into their own file due to interactions -# with settings in Makefile.global. +# with settings in Makefile.global. There is no library guard on with_ssl for +# the targets, as nssfiles rely on the openssl generated files and also the +# openssl toolchain to some degree. .PHONY: sslfiles sslfiles-clean sslfiles sslfiles-clean: - $(MAKE) -f $(srcdir)/sslfiles.mk $@ + MKDIR_P="$(MKDIR_P)" $(MAKE) -f $(srcdir)/sslfiles.mk $@ + +.PHONY: nssfiles nssfiles-clean +nssfiles nssfiles-clean: + MKDIR_P="$(MKDIR_P)" $(MAKE) -f $(srcdir)/sslfiles_nss.mk $@ clean distclean maintainer-clean: rm -rf tmp_check $(MAKE) -f $(srcdir)/sslfiles.mk $@ + $(MAKE) -f $(srcdir)/sslfiles_nss.mk $@ # Doesn't depend on sslfiles because we don't rebuild them by default check: diff --git a/src/test/ssl/sslfiles.mk b/src/test/ssl/sslfiles.mk index 7ed3a30f5c..065e08a104 100644 --- a/src/test/ssl/sslfiles.mk +++ b/src/test/ssl/sslfiles.mk @@ -185,7 +185,7 @@ ssl/%.csr: ssl/%.key conf/%.config # 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 $@ + $(MKDIR_P) $@ ssl/%-certindex: touch $@ @@ -225,7 +225,7 @@ ssl/client-crldir: ssl/client.crl crlhashfile = $(shell openssl crl -hash -noout -in $(1)).r0 ssl/%-crldir: - mkdir -p $@ + $(MKDIR_P) $@ rm -f $@/*.r0 $(foreach crl,$^,cp $(crl) $@/$(call crlhashfile,$(crl)) &&) true touch $@ diff --git a/src/test/ssl/sslfiles_nss.mk b/src/test/ssl/sslfiles_nss.mk new file mode 100644 index 0000000000..adb7363d63 --- /dev/null +++ b/src/test/ssl/sslfiles_nss.mk @@ -0,0 +1,268 @@ +#------------------------------------------------------------------------- +# +# Makefile for sslfiles using NSS +# +# The SSL test files are completely disjoint from the rest of the build; they +# don't rely on other targets or on Makefile.global. The targets in this +# file rely on the certificates and keys generated by the OpenSSL backend +# support. +# +# Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/test/ssl/sslfiles_nss.mk +# +#------------------------------------------------------------------------- + +# Even though we in practice could get away with far fewer NSS databases, they +# are generated to mimic the setup for the OpenSSL tests in order to ensure +# we isolate the same behavior between the backends. The database name should +# contain the files included for easier test suite code reading. +NSSFILES := ssl/nss/client_ca.crt.db \ + ssl/nss/server_ca.crt.db \ + ssl/nss/root+server_ca.crt.db \ + ssl/nss/root+client_ca.crt.db \ + ssl/nss/client.crt__client.key.db \ + ssl/nss/client-revoked.crt__client-revoked.key.db \ + ssl/nss/server-cn-only.crt__server-password.key.db \ + ssl/nss/server-cn-only.crt__server-cn-only.key.db \ + ssl/nss/server-cn-only.crt__server-cn-only.key.crldir.db \ + ssl/nss/root.crl \ + ssl/nss/server.crl \ + ssl/nss/client.crl \ + ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db \ + ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db \ + ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db \ + ssl/nss/server-no-names.crt__server-no-names.key.db \ + ssl/nss/server-revoked.crt__server-revoked.key.db \ + ssl/nss/root+client.crl \ + ssl/nss/client+client_ca.crt__client.key.db \ + ssl/nss/client.crt__client-encrypted-pem.key.db \ + ssl/nss/root+server_ca.crt__server.crl.db \ + ssl/nss/root+server_ca.crt__root+server.crl.db \ + ssl/nss/root+server_ca.crt__root+server.crldir.db \ + ssl/nss/native_ca-root.db \ + ssl/nss/native_server-root.db \ + ssl/nss/native_client-root.db + +nssfiles: $(NSSFILES) + +ssl/nss/%_ca.crt.db: ssl/%_ca.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n $*_ca.crt -i ssl/$*_ca.crt -t "CT,C,C" + +ssl/nss/root+server_ca.crt__server.crl.db: ssl/root+server_ca.crt ssl/nss/server.crl + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + crlutil -I -i ssl/nss/server.crl -d $@ -B + +ssl/nss/root+server_ca.crt__root+server.crl.db: ssl/root+server_ca.crt ssl/nss/root.crl ssl/nss/server.crl + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + crlutil -I -i ssl/nss/root.crl -d $@ -B + crlutil -I -i ssl/nss/server.crl -d $@ -B + +ssl/nss/root+server_ca.crt__root+server.crldir.db: ssl/root+server_ca.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + crlutil -I -i ssl/nss/root.crl -d $@ -B + for c in $(shell ls ssl/root+server-crldir) ; do \ + echo $${c} ; \ + openssl crl -in ssl/root+server-crldir/$${c} -outform der -out ssl/nss/$${c} ; \ + crlutil -I -i ssl/nss/$${c} -d $@ -B ; \ + done + +# pk12util won't preserve the password when importing the password protected +# key, the password must be set on the database *before* importing it as the +# password in the pkcs12 envelope will be dropped. +ssl/nss/server-cn-only.crt__server-password.key.db: ssl/server-cn-only.crt + $(MKDIR_P) $@ + echo "secret1" > password.txt + certutil -d "sql:$@" -N -f password.txt + certutil -d "sql:$@" -A -n ssl/server-cn-only.crt -i ssl/server-cn-only.crt -t "CT,C,C" -f password.txt + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" -f password.txt + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" -f password.txt + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" -f password.txt + openssl pkcs12 -export -out ssl/nss/server-password.pfx -inkey ssl/server-password.key -in ssl/server-cn-only.crt -certfile ssl/server_ca.crt -passin 'pass:secret1' -passout 'pass:secret1' + pk12util -i ssl/nss/server-password.pfx -d "sql:$@" -W 'secret1' -K 'secret1' + +ssl/nss/server-cn-only.crt__server-cn-only.key.db: ssl/server-cn-only.crt ssl/server-cn-only.key + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-cn-only.crt -i ssl/server-cn-only.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-cn-only.pfx -inkey ssl/server-cn-only.key -in ssl/server-cn-only.crt -certfile ssl/server_ca.crt -passout pass: + pk12util -i ssl/nss/server-cn-only.pfx -d "sql:$@" -W '' + +ssl/nss/server-cn-only.crt__server-cn-only.key.crldir.db: ssl/nss/server-cn-only.crt__server-cn-only.key.db + cp -R $< $@ + for c in $(shell ls ssl/root+client-crldir) ; do \ + echo $${c} ; \ + openssl crl -in ssl/root+client-crldir/$${c} -outform der -out ssl/nss/$${c} ; \ + crlutil -I -i ssl/nss/$${c} -d $@ -B ; \ + done + +ssl/nss/server-multiple-alt-names.crt__server-multiple-alt-names.key.db: ssl/server-multiple-alt-names.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-multiple-alt-names.crt -i ssl/server-multiple-alt-names.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-multiple-alt-names.pfx -inkey ssl/server-multiple-alt-names.key -in ssl/server-multiple-alt-names.crt -certfile ssl/server-multiple-alt-names.crt -passout pass: + pk12util -i ssl/nss/server-multiple-alt-names.pfx -d "sql:$@" -W '' + +ssl/nss/server-single-alt-name.crt__server-single-alt-name.key.db: ssl/server-single-alt-name.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-single-alt-name.crt -i ssl/server-single-alt-name.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-single-alt-name.pfx -inkey ssl/server-single-alt-name.key -in ssl/server-single-alt-name.crt -certfile ssl/server-single-alt-name.crt -passout pass: + pk12util -i ssl/nss/server-single-alt-name.pfx -d "sql:$@" -W '' + +ssl/nss/server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db: ssl/server-cn-and-alt-names.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-cn-and-alt-names.crt -i ssl/server-cn-and-alt-names.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-cn-and-alt-names.pfx -inkey ssl/server-cn-and-alt-names.key -in ssl/server-cn-and-alt-names.crt -certfile ssl/server-cn-and-alt-names.crt -passout pass: + pk12util -i ssl/nss/server-cn-and-alt-names.pfx -d $@ -W '' + +ssl/nss/server-no-names.crt__server-no-names.key.db: ssl/server-no-names.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-no-names.crt -i ssl/server-no-names.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-no-names.pfx -inkey ssl/server-no-names.key -in ssl/server-no-names.crt -certfile ssl/server-no-names.crt -passout pass: + pk12util -i ssl/nss/server-no-names.pfx -d "sql:$@" -W '' + +ssl/nss/server-revoked.crt__server-revoked.key.db: ssl/server-revoked.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/server-revoked.crt -i ssl/server-revoked.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n server_ca.crt -i ssl/server_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root_ca.crt -i ssl/root_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/server-revoked.pfx -inkey ssl/server-revoked.key -in ssl/server-revoked.crt -certfile ssl/server-revoked.crt -passout pass: + pk12util -i ssl/nss/server-revoked.pfx -d "sql:$@" -W '' + + +# Client certificate, signed by client CA +ssl/nss/client.crt__client.key.db: ssl/client.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/client.crt -i ssl/client.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/client.pfx -inkey ssl/client.key -in ssl/client.crt -certfile ssl/client_ca.crt -passout pass: + pk12util -i ssl/nss/client.pfx -d "sql:$@" -W '' + +# Client certificate with encrypted key, signed by client CA +ssl/nss/client.crt__client-encrypted-pem.key.db: ssl/client.crt + $(MKDIR_P) $@ + echo 'dUmmyP^#+' > $@.pass + certutil -d "sql:$@" -N -f $@.pass + certutil -d "sql:$@" -A -f $@.pass -n ssl/client.crt -i ssl/client.crt -t "CT,C,C" + certutil -d "sql:$@" -A -f $@.pass -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -f $@.pass -n root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/client-encrypted-pem.pfx -inkey ssl/client-encrypted-pem.key -in ssl/client.crt -certfile ssl/client_ca.crt -passin pass:'dUmmyP^#+' -passout pass:'dUmmyP^#+' + pk12util -i ssl/nss/client-encrypted-pem.pfx -d "sql:$@" -W 'dUmmyP^#+' -k $@.pass + +ssl/nss/client-revoked.crt__client-revoked.key.db: ssl/client-revoked.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/client-revoked.crt -i ssl/client-revoked.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n client_ca.crt -i ssl/client_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/client-revoked.pfx -inkey ssl/client-revoked.key -in ssl/client-revoked.crt -certfile ssl/client_ca.crt -passout pass: + pk12util -i ssl/nss/client-revoked.pfx -d "sql:$@" -W '' + +# Client certificate, signed by client CA +ssl/nss/client+client_ca.crt__client.key.db: ssl/client+client_ca.crt + $(MKDIR_P) $@ + certutil -d "sql:$@" -N --empty-password + certutil -d "sql:$@" -A -n ssl/client+client_ca.crt -i ssl/client+client_ca.crt -t "CT,C,C" + certutil -d "sql:$@" -A -n ssl/root+server_ca.crt -i ssl/root+server_ca.crt -t "CT,C,C" + openssl pkcs12 -export -out ssl/nss/client.pfx -inkey ssl/client.key -in ssl/client.crt -certfile ssl/client_ca.crt -passout pass: + pk12util -i ssl/nss/client.pfx -d "sql:$@" -W '' + +ssl/nss/client.crl: ssl/client.crl + openssl crl -in $^ -outform der -out $@ + +ssl/nss/server.crl: ssl/server.crl + openssl crl -in $^ -outform der -out $@ + +ssl/nss/root.crl: ssl/root.crl + openssl crl -in $^ -outform der -out $@ + +ssl/nss/root+client.crl: ssl/root+client.crl + openssl crl -in $^ -outform der -out $@ + +#### NSS specific certificates and keys + +ssl/nss/native_ca-%.db: + $(MKDIR_P) ssl/nss/native_ca-$*.db + certutil -N -d "sql:ssl/nss/native_ca-$*.db/" --empty-password + echo y > nss_ca_params.txt + echo 10 >> nss_ca_params.txt + echo y >> nss_ca_params.txt + cat nss_ca_params.txt | certutil -S -d "sql:ssl/nss/native_ca-$*.db/" -n ca-$* \ + -s "CN=Test CA for PostgreSQL SSL regression tests,OU=PostgreSQL test suite" \ + -x -k rsa -g 2048 -m 5432 -t CTu,CTu,CTu \ + --keyUsage certSigning -2 --nsCertType sslCA,smimeCA,objectSigningCA \ + -z Makefile -Z SHA256 + rm nss_ca_params.txt + +ssl/nss/native_ca-%.pem: ssl/nss/native_ca-%.db + certutil -L -d "sql:ssl/nss/native_ca-$*.db/" -n ca-$* -a > ssl/nss/native_ca-$*.pem + +# Create and sign a server certificate +ssl/nss/native_server-%.db: ssl/nss/native_ca-%.pem + $(MKDIR_P) ssl/nss/native_server-$*.db + certutil -N -d "sql:ssl/nss/native_server-$*.db/" --empty-password + certutil -R -d "sql:ssl/nss/native_server-$*.db/" \ + -s "CN=common-name.pg-ssltest.test,OU=PostgreSQL test suite" \ + -o ssl/nss/native_server-$*.csr -g 2048 -Z SHA256 -z Makefile + echo 1 > nss_server_params.txt + echo 9 >> nss_server_params.txt + cat nss_server_params.txt | certutil -C -d "sql:ssl/nss/native_ca-$*.db/" -c ca-root -i ssl/nss/native_server-$*.csr \ + -o ssl/nss/native_server_$*.der -m 5433 --keyUsage dataEncipherment,digitalSignature,keyEncipherment \ + --nsCertType sslServer --certVersion 1 -Z SHA256 + certutil -A -d "sql:ssl/nss/native_server-$*.db/" -n ca-$* -t CTu,CTu,CTu -a -i ssl/nss/native_ca-$*.pem + certutil -A -d "sql:ssl/nss/native_server-$*.db/" -n ssl/native_server-$*.crt -t CTu,CTu,CTu -i ssl/nss/native_server_$*.der + rm nss_server_params.txt + +# Create and sign a client certificate +ssl/nss/native_client-%.db: ssl/nss/native_ca-%.pem + $(MKDIR_P) ssl/nss/native_client-$*.db + certutil -N -d "sql:ssl/nss/native_client-$*.db/" --empty-password + certutil -R -d "sql:ssl/nss/native_client-$*.db/" -s "CN=ssltestuser,OU=PostgreSQL test suite" \ + -o ssl/nss/native_client-$*.csr -g 2048 -Z SHA256 -z Makefile + certutil -C -d "sql:ssl/nss/native_ca-$*.db/" -c ca-$* -i ssl/nss/native_client-$*.csr -o ssl/nss/native_client-$*.der \ + -m 5434 --keyUsage keyEncipherment,dataEncipherment,digitalSignature --nsCertType sslClient \ + --certVersion 1 -Z SHA256 + certutil -A -d "sql:ssl/nss/native_client-$*.db" -n ca-$* -t CTu,CTu,CTu -a -i ssl/nss/native_ca-$*.pem + certutil -A -d "sql:ssl/nss/native_client-$*.db" -n native_client-$* -t CTu,CTu,CTu -i ssl/nss/native_client-$*.der + +.PHONY: nssfiles-clean +nssfiles-clean: + rm -rf ssl/nss + +# The difference between the below clean targets and nssfiles-clean is that the +# clean targets will be run during a "standard" recursive clean run from the +# main build tree. The nssfiles-clean target must be run explicitly from this +# directory. +.PHONY: clean distclean maintainer-clean +clean distclean maintainer-clean: + rm -rf ssl/nss + diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index 8d6b9dfbdc..7dc1731e64 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -13,13 +13,22 @@ use lib $FindBin::RealBin; use SSL::Server; -if ($ENV{with_ssl} ne 'openssl') +my $openssl; +my $nss; + +if ($ENV{with_ssl} eq 'openssl') +{ + $openssl = 1; + plan tests => 112; +} +elsif ($ENV{with_ssl} eq 'nss') { - plan skip_all => 'OpenSSL not supported by this build'; + $nss = 1; + plan tests => 112; } else { - plan tests => 110; + plan skip_all => 'SSL not supported by this build'; } #### Some configuration @@ -55,19 +64,68 @@ configure_test_server_for_ssl($node, $SERVERHOSTADDR, $SERVERHOSTCIDR, note "testing password-protected keys"; -set_server_cert($node, 'server-cn-only', 'root+client_ca', - 'server-password', 'echo wrongpassword'); -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); +# Since the passphrase callbacks operate at different stages in OpenSSL and +# NSS we have two separate blocks for them +SKIP: +{ + skip "Certificate passphrases aren't checked on server restart in NSS", 2 + if ($nss); + + switch_server_cert($node, + certfile => 'server-cn-only', + cafile => 'root+client_ca', + keyfile => 'server-password', + nssdatabase => 'server-cn-only.crt__server-password.key.db', + passphrase_cmd => 'echo wrongpassword', + restart => 'no' ); + + 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); + + switch_server_cert($node, + certfile => 'server-cn-only', + cafile => 'root+client_ca', + keyfile => 'server-password', + nssdatabase => 'server-cn-only.crt__server-password.key.db', + passphrase_cmd => 'echo secret1', + restart => 'no'); + + command_ok( + [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ], + 'restart succeeds with password-protected key file'); + $node->_update_pid(1); +} -set_server_cert($node, 'server-cn-only', 'root+client_ca', - 'server-password', 'echo secret1'); -command_ok( - [ 'pg_ctl', '-D', $node->data_dir, '-l', $node->logfile, 'restart' ], - 'restart succeeds with password-protected key file'); -$node->_update_pid(1); +SKIP: +{ + skip "Certificate passphrases are checked on connection in NSS", 3 + if ($openssl); + + switch_server_cert($node, + certfile => 'server-cn-only', + cafile => 'root+client_ca', + keyfile => 'server-password', + nssdatabase => 'server-cn-only.crt__server-password.key.db', + passphrase_cmd => 'echo wrongpassword'); + + $node->connect_fails( + "user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test sslrootcert=invalid sslmode=require", + "connect to server with incorrect key password configured", + expected_stderr => qr/\QSSL error\E/); + + switch_server_cert($node, + certfile => 'server-cn-only', + cafile => 'root+client_ca', + keyfile => 'server-password', + nssdatabase => 'server-cn-only.crt__server-password.key.db', + passphrase_cmd => 'echo secret1'); + + $node->connect_ok( + "user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test sslrootcert=invalid sslmode=require", + "connect to server with correct key password configured"); +} # Test compatibility of SSL protocols. # TLSv1.1 is lower than TLSv1.2, so it won't work. @@ -95,7 +153,7 @@ command_ok( note "running client tests"; -switch_server_cert($node, 'server-cn-only'); +switch_server_cert($node, certfile => 'server-cn-only', nssdatabase => 'server-cn-only.crt__server-cn-only.key.db'); $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; @@ -114,87 +172,104 @@ $node->connect_ok( $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/); + expected_stderr => qr/root certificate file "invalid" does not exist|Peer's certificate issuer has been marked as not trusted by the user/); $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/); + expcted_stderr => qr/root certificate file "invalid" does not exist|Peer's certificate issuer has been marked as not trusted by the user/); # 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", + "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=require ssldatabase=ssl/nss/client_ca.crt.db", "connect with wrong server root cert sslmode=require", - expected_stderr => qr/SSL error: certificate verify failed/); + expected_stderr => qr/SSL error: certificate verify failed|Peer's certificate issuer has been marked as not trusted by the user/); $node->connect_fails( - "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-ca", + "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-ca ssldatabase=ssl/nss/client_ca.crt.db", "connect with wrong server root cert sslmode=verify-ca", - expected_stderr => qr/SSL error: certificate verify failed/); + expected_stderr => qr/SSL error: certificate verify failed|Peer's certificate issuer has been marked as not trusted by the user/); $node->connect_fails( - "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-full", + "$common_connstr sslrootcert=ssl/client_ca.crt sslmode=verify-full ssldatabase=ssl/nss/client_ca.crt.db", "connect with wrong server root cert sslmode=verify-full", - expected_stderr => qr/SSL error: certificate verify failed/); + expected_stderr => qr/SSL error: certificate verify failed|Peer's certificate issuer has been marked as not trusted by the user/); -# 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/); +SKIP: +{ + # NSS supports partial chain validation, so this test doesn't work there. + # This is similar to the OpenSSL option X509_V_FLAG_PARTIAL_CHAIN which + # we don't allow. + skip "NSS support partial chain validation", 2 if ($nss); + # 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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssldatabase=ssl/nss/root+server_ca.crt.db", "connect with correct server CA cert file sslmode=require"); $node->connect_ok( - "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca ssldatabase=ssl/nss/root+server_ca.crt.db", "connect with correct server CA cert file sslmode=verify-ca"); $node->connect_ok( - "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-full", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-full ssldatabase=ssl/nss/root+server_ca.crt.db", "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"); - +SKIP: +{ + skip "CA ordering is irrelevant in NSS databases", 2 if ($nss); + + # 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"); + + # How about import the both-file into a database? + $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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=invalid ssldatabase=ssl/nss/root+server_ca.crt.db", "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/); +SKIP: +{ + skip "CRL's are verified when adding to NSS database", 4 if ($nss); + # 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 -$node->connect_fails( - "$common_connstr 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/); + # The same for CRL directory + $node->connect_fails( + "$common_connstr 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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl ssldatabase=ssl/nss/root+server_ca.crt__root+server.crl.db", "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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir ssldatabase=ssl/nss/root+server_ca.crt__root+server.crldir.db", "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 = - "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; + "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/root+server_ca.crt.db"; $node->connect_ok("$common_connstr sslmode=require host=wronghost.test", "mismatch between host name and server certificate sslmode=require"); @@ -205,14 +280,14 @@ $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/ + qr/\Qserver certificate for "common-name.pg-ssltest.test" does not match host name "wronghost.test"\E|requested domain name does not match the server's certificate/ ); # Test Subject Alternative Names. -switch_server_cert($node, 'server-multiple-alt-names'); +switch_server_cert($node, certfile => 'server-multiple-alt-names', nssdatabase => 'server-multiple-alt-names.crt__server-multiple-alt-names.key.db'); $common_connstr = - "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; + "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full ssldatabase=ssl/nss/root+server_ca.crt.db"; $node->connect_ok( "$common_connstr host=dns1.alt-name.pg-ssltest.test", @@ -227,21 +302,22 @@ $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/ + 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|requested domain name does not match the server's certificate/ ); + $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/ + 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|requested domain name does not match the server's certificate/ ); # 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'); +switch_server_cert($node, certfile => 'server-single-alt-name', nssdatabase => 'server-single-alt-name.crt__server-single-alt-name.key.db'); $common_connstr = - "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; + "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full ssldatabase=ssl/nss/root+server_ca.crt.db"; $node->connect_ok( "$common_connstr host=single.alt-name.pg-ssltest.test", @@ -251,21 +327,21 @@ $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/ + qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "wronghost.alt-name.pg-ssltest.test"\E|requested domain name does not match the server's certificate/ ); $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/ + qr/\Qserver certificate for "single.alt-name.pg-ssltest.test" does not match host name "deep.subdomain.wildcard.pg-ssltest.test"\E|requested domain name does not match the server's certificate/, ); # 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'); +switch_server_cert($node, certfile => 'server-cn-and-alt-names', nssdatabase => 'server-cn-and-alt-names.crt__server-cn-and-alt-names.key.db'); $common_connstr = - "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full"; + "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR sslmode=verify-full ssldatabase=ssl/nss/root+server_ca.crt.db"; $node->connect_ok("$common_connstr host=dns1.alt-name.pg-ssltest.test", "certificate with both a CN and SANs 1"); @@ -275,43 +351,43 @@ $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/ + 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|requested domain name does not match the server's certificate/ ); # 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'); +switch_server_cert($node, certfile => 'server-no-names', nssdatabase => 'server-no-names.crt__server-no-names.key.db'); $common_connstr = - "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; + "user=ssltestuser dbname=trustdb sslcert=invalid sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/root+server_ca.crt.db"; $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", + . "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/); + qr/could not get server's host name from server certificate|requested domain name does not match the server's certificate./); # Test that the CRL works -switch_server_cert($node, 'server-revoked'); +switch_server_cert($node, certfile => 'server-revoked', nssdatabase => 'server-revoked.crt__server-revoked.key.db'); $common_connstr = "user=ssltestuser dbname=trustdb sslcert=invalid 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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca ssldatabase=ssl/nss/root+server_ca.crt.db", "connects without client-side CRL"); $node->connect_fails( - "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrl=ssl/root+server.crl ssldatabase=ssl/nss/root+server_ca.crt__root+server.crl.db", "does not connect with client-side CRL file", - expected_stderr => qr/SSL error: certificate verify failed/); + expected_stderr => qr/SSL error: certificate verify failed|SSL error: Peer's Certificate has been revoked/); $node->connect_fails( - "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=verify-ca sslcrldir=ssl/root+server-crldir ssldatabase=ssl/nss/root+server_ca.crt__root+server.crldir.db", "does not connect with client-side CRL directory", - expected_stderr => qr/SSL error: certificate verify failed/); + expected_stderr => qr/SSL error: certificate verify failed|SSL error: Peer's Certificate has been revoked/); # pg_stat_ssl command_like( @@ -329,29 +405,46 @@ command_like( # 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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=TLSv1.2 ssl_max_protocol_version=TLSv1.2 ssldatabase=ssl/nss/root+server_ca.crt.db", "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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=TLSv1.2 ssl_max_protocol_version=TLSv1.1 ssldatabase=ssl/nss/root+server_ca.crt.db", "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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_min_protocol_version=incorrect_tls ssldatabase=ssl/nss/root+server_ca.crt.db", "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", + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslmode=require ssl_max_protocol_version=incorrect_tls ssldatabase=ssl/nss/root+server_ca.crt.db", "connection failure with an incorrect SSL protocol maximum bound", expected_stderr => qr/invalid ssl_max_protocol_version value/); +# tests of NSS generated certificates/keys +SKIP: +{ + skip "NSS specific tests", 1 if ($openssl); + + switch_server_cert($node, certfile => 'native_server-root', cafile => 'native_ca-root', nssdatabase => 'native_server-root.db'); + $common_connstr = + "user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; + + $node->connect_ok( + "$common_connstr sslmode=require user=ssltestuser", + "NSS generated certificates" + ); +} + ### Server-side tests. ### ### Test certificate authorization. +switch_server_cert($node, certfile => 'server-revoked', nssdatabase => 'server-revoked.crt__server-revoked.key.db'); + note "running server tests"; $common_connstr = - "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR"; + "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client.crt__client.key.db"; # no client cert $node->connect_fails( @@ -361,66 +454,86 @@ $node->connect_fails( # correct client cert in unencrypted PEM $node->connect_ok( - "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=$key{'client.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client.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=$key{'client-der.key'}", - "certificate authorization succeeds with correct client cert in DER format" -); +SKIP: +{ + skip "Automatic certificate resolution is NSS specific", 1 if ($openssl); + # correct client cert in unencrypted PEM without a nickname (sslcert) + $node->connect_ok( + "$common_connstr user=ssltestuser", + "certificate authorization succeeds without correct client cert in connstring" + ); +} + +SKIP: +{ + skip "NSS database not implemented in the Makefile", 1 if ($nss); + # correct client cert in unencrypted DER + $node->connect_ok( + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-der.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=$key{'client-encrypted-pem.key'} sslpassword='dUmmyP^#+'", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-encrypted-pem.key') . " sslpassword='dUmmyP^#+' ssldatabase=ssl/nss/client.crt__client-encrypted-pem.key.db", "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=$key{'client-encrypted-der.key'} sslpassword='dUmmyP^#+'", - "certificate authorization succeeds with correct client cert in encrypted DER format" -); +SKIP: +{ + skip "NSS database not implemented in the Makefile", 1 if ($nss); + # correct client cert in encrypted DER + $node->connect_ok( + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-encrypted-der.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=$key{'client-encrypted-pem.key'} sslpassword='wrong'", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-encrypted-pem.key') . " sslpassword='wrong' ssldatabase=ssl/nss/client.crt__client-encrypted-pem.key.db", "certificate authorization fails with correct client cert and wrong password in encrypted PEM format", expected_stderr => - qr!\Qprivate key file "$key{'client-encrypted-pem.key'}": bad decrypt\E! + qr!connection requires a valid client certificate|private key file \".*/client-encrypted-pem\.key\": bad decrypt!, ); - -# 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=$key{'client-dn.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=$key{'client-dn.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=$key{'client-dn.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/ - ],); - - +SKIP: +{ + skip "DN mapping not implemented in NSS", 3 if ($nss); + + # 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('client-dn.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('client-dn.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/ + ],); + + # 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('client-dn.key'), + "certificate authorization succeeds with CN mapping"); +} TODO: { @@ -431,49 +544,52 @@ TODO: # correct client cert in encrypted PEM with empty password $node->connect_fails( - "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=$key{'client-encrypted-pem.key'} sslpassword=''", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-encrypted-pem.key') . " sslpassword=''", "certificate authorization fails with correct client cert and empty password in encrypted PEM format", expected_stderr => - qr!\Qprivate key file "$key{'client-encrypted-pem.key'}": processing error\E! + qr!\Qprivate key file ".*client-encrypted-pem.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=$key{'client-encrypted-pem.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client-encrypted-pem.key'), "certificate authorization fails with correct client cert and no password in encrypted PEM format", expected_stderr => - qr!\Qprivate key file "$key{'client-encrypted-pem.key'}": processing error\E! + qr!\Qprivate key file ".*client-encrypted-pem.key": processing error\E! ); } # pg_stat_ssl -my $serialno = `openssl x509 -serial -noout -in ssl/client.crt`; -if ($? == 0) +# If the serial number can't be extracted to match against, fall back to just +# checking for it being integer. +# TODO: figure put a corresponding command for NSS to extract the serial from +# the cert. +my $serialno = '\d+'; +if ($openssl) { - # OpenSSL prints serial numbers in hexadecimal and converting the serial - # from hex requires a 64-bit capable Perl as the serialnumber is based on - # the current timestamp. On 32-bit fall back to checking for it being an - # integer like how we do when grabbing the serial fails. - if ($Config{ivsize} == 8) + my $serialno = `openssl x509 -serial -noout -in ssl/client.crt`; + if ($? == 0) { - $serialno =~ s/^serial=//; - $serialno =~ s/\s+//g; - $serialno = hex($serialno); + # OpenSSL prints serial numbers in hexadecimal and converting the serial + # from hex requires a 64-bit capable Perl as the serialnumber is based on + # the current timestamp. On 32-bit fall back to checking for it being an + # integer like how we do when grabbing the serial fails. + if ($Config{ivsize} == 8) + { + $serialno =~ s/^serial=//; + $serialno =~ s/\s+//g; + $serialno = hex($serialno); + } } else { - $serialno = '\d+'; + # OpenSSL isn't functioning on the user's PATH. This probably isn't worth + # skipping the test over, so just fall back to a generic integer match. + warn 'couldn\'t run `openssl x509` to get client cert serialno'; } } -else -{ - # OpenSSL isn't functioning on the user's PATH. This probably isn't worth - # skipping the test over, so just fall back to a generic integer match. - warn 'couldn\'t run `openssl x509` to get client cert serialno'; - $serialno = '\d+'; -} command_like( [ @@ -485,42 +601,47 @@ command_like( '-P', 'null=_null_', '-d', - "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=$key{'client.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client.key') . " ssldatabase=ssl/nss/client.crt__client.key.db", '-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,$serialno,\Q/CN=Test CA for PostgreSQL SSL regression test client certs\E\r?$}mx, + ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,/?CN=ssltestuser,$serialno,/?\QCN=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); + skip "Key not on filesystem with NSS", 2 if ($nss); $node->connect_fails( - "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=$key{'client_wrongperms.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client_wrongperms.key'), "certificate authorization fails because of file permissions", expected_stderr => - qr!\Qprivate key file "$key{'client_wrongperms.key'}" has group or world access\E! + qr!private key file \".*client_wrongperms\.key\" has group or world access! ); } # client cert belonging to another user $node->connect_fails( - "$common_connstr user=anotheruser sslcert=ssl/client.crt sslkey=$key{'client.key'}", + "$common_connstr user=anotheruser sslcert=ssl/client.crt " . sslkey('client.key'), "certificate authorization fails with client cert belonging to another user", expected_stderr => - qr/certificate authentication failed for user "anotheruser"/, + qr/unable to verify certificate|certificate authentication failed for user "anotheruser"/, # certificate authentication should be logged even on failure log_like => [qr/connection authenticated: identity="CN=ssltestuser" method=cert/],); +$common_connstr = + "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=certdb hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client-revoked.crt__client-revoked.key.db"; + # revoked client cert $node->connect_fails( - "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=$key{'client-revoked.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " . sslkey('client-revoked.key'), "certificate authorization fails with revoked client cert", - expected_stderr => qr/SSL error: sslv3 alert certificate revoked/, + expected_stderr => + qr/SSL error: sslv3 alert certificate revoked|SSL error: Peer's certificate issuer has been marked as not trusted by the user/, # revoked certificates should not authenticate the user log_unlike => [qr/connection authenticated:/],); @@ -528,16 +649,16 @@ $node->connect_fails( # works, iff username matches Common Name # fails, iff username doesn't match Common Name. $common_connstr = - "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=verifydb hostaddr=$SERVERHOSTADDR"; + "sslrootcert=ssl/root+server_ca.crt sslmode=require dbname=verifydb hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client.crt__client.key.db"; $node->connect_ok( - "$common_connstr user=ssltestuser sslcert=ssl/client.crt sslkey=$key{'client.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client.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=$key{'client.key'}", + "$common_connstr user=anotheruser sslcert=ssl/client.crt " . sslkey('client.key'), "auth_option clientcert=verify-full fails with mismatching username and Common Name", expected_stderr => qr/FATAL: .* "trust" authentication failed for user "anotheruser"/, @@ -547,15 +668,15 @@ $node->connect_fails( # 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=$key{'client.key'}", + "$common_connstr user=yetanotheruser sslcert=ssl/client.crt " . sslkey('client.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'); +switch_server_cert($node, certfile => 'server-cn-only', cafile => 'root_ca', nssdatabase => 'server-cn-only.crt__server-cn-only.key.db'); $common_connstr = - "user=ssltestuser dbname=certdb sslkey=$key{'client.key'} sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR"; + "user=ssltestuser dbname=certdb " . sslkey('client.key') . " sslrootcert=ssl/root+server_ca.crt hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client+client_ca.crt__client.key.db"; $node->connect_ok( "$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt", @@ -563,14 +684,15 @@ $node->connect_ok( $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/); + expected_stderr => + qr/SSL error: tlsv1 alert unknown ca|connection requires a valid client certificate/); # test server-side CRL directory -switch_server_cert($node, 'server-cn-only', undef, undef, - 'root+client-crldir'); +switch_server_cert($node, certfile => 'server-cn-only', crldir => 'root+client-crldir', nssdatabase => 'server-cn-only.crt__server-cn-only.key.crldir.db'); # revoked client cert $node->connect_fails( - "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt sslkey=$key{'client-revoked.key'}", + "$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " . sslkey('client-revoked.key') . " ssldatabase=ssl/nss/client-revoked.crt__client-revoked.key.db", "certificate authorization fails with revoked client cert with server-side CRL directory", - expected_stderr => qr/SSL error: sslv3 alert certificate revoked/); + expected_stderr => + qr/SSL error: sslv3 alert certificate revoked|SSL peer rejected your certificate as revoked/); diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl index 56c5f88d5f..fd3c881040 100644 --- a/src/test/ssl/t/002_scram.pl +++ b/src/test/ssl/t/002_scram.pl @@ -16,7 +16,24 @@ use lib $FindBin::RealBin; use SSL::Server; -if ($ENV{with_ssl} ne 'openssl') +my $openssl; +my $nss; + +my $supports_tls_server_end_point; + +if ($ENV{with_ssl} eq 'openssl') +{ + $openssl = 1; + # Determine whether build supports tls-server-end-point. + $supports_tls_server_end_point = + check_pg_config("#define HAVE_X509_GET_SIGNATURE_NID 1"); +} +elsif ($ENV{with_ssl} eq 'nss') +{ + $nss = 1; + $supports_tls_server_end_point = 1; +} +else { plan skip_all => 'SSL not supported by this build'; } @@ -26,12 +43,6 @@ 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; @@ -50,7 +61,7 @@ $node->start; # Configure server for SSL connections, with password handling. configure_test_server_for_ssl($node, $SERVERHOSTADDR, $SERVERHOSTCIDR, "scram-sha-256", 'password' => "pass", 'password_enc' => "scram-sha-256"); -switch_server_cert($node, 'server-cn-only'); +switch_server_cert($node, certfile => 'server-cn-only', nssdatabase => 'server-cn-only.crt__server-cn-only.key.db'); $ENV{PGPASSWORD} = "pass"; $common_connstr = "dbname=trustdb sslmode=require sslcert=invalid sslrootcert=invalid hostaddr=$SERVERHOSTADDR"; @@ -104,7 +115,7 @@ chmod 0600, "$cert_tempdir/client_scram.key" or die "failed to change permissions on $cert_tempdir/client_scram.key: $!"; $client_tmp_key =~ s!\\!/!g if $PostgreSQL::Test::Utils::windows_os; $node->connect_fails( - "sslcert=ssl/client.crt sslkey=$client_tmp_key sslrootcert=invalid hostaddr=$SERVERHOSTADDR dbname=certdb user=ssltestuser channel_binding=require", + "sslcert=ssl/client.crt sslkey=$client_tmp_key sslrootcert=invalid hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client.crt__client.key.db 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/ @@ -112,10 +123,10 @@ $node->connect_fails( # 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 dbname=verifydb user=ssltestuser", + "sslcert=ssl/client.crt sslkey=$client_tmp_key sslrootcert=invalid hostaddr=$SERVERHOSTADDR ssldatabase=ssl/nss/client.crt__client.key.db dbname=verifydb user=ssltestuser", "SCRAM with clientcert=verify-full", log_like => [ qr/connection authenticated: identity="ssltestuser" method=scram-sha-256/ ]); -done_testing($number_of_tests); +done_testing(); diff --git a/src/test/ssl/t/003_sslinfo.pl b/src/test/ssl/t/003_sslinfo.pl index 6c733c8a75..4dc457e1b6 100644 --- a/src/test/ssl/t/003_sslinfo.pl +++ b/src/test/ssl/t/003_sslinfo.pl @@ -14,13 +14,17 @@ use lib $FindBin::RealBin; use SSL::Server; -if ($ENV{with_ssl} ne 'openssl') +if ($ENV{with_ssl} eq 'openssl') { - plan skip_all => 'OpenSSL not supported by this build'; + plan tests => 13; +} +elsif ($ENV{with_ssl} eq 'nss') +{ + plan skip_all => 'SSL not supported by this build'; } else { - plan tests => 13; + plan skip_all => 'SSL not supported by this build'; } #### Some configuration diff --git a/src/test/ssl/t/SSL/Backend/NSS.pm b/src/test/ssl/t/SSL/Backend/NSS.pm new file mode 100644 index 0000000000..e2b9b8cfc9 --- /dev/null +++ b/src/test/ssl/t/SSL/Backend/NSS.pm @@ -0,0 +1,66 @@ +package SSL::Backend::NSS; + +use strict; +use warnings; +use Exporter; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(get_new_nss_backend get_nss_key); + +sub new +{ + my ($class) = @_; + + my $self = { _library => 'NSS' }; + + bless $self, $class; + + return $self; +} + +sub get_new_nss_backend +{ + my $class = 'SSL::Backend::NSS'; + + return $class->new(); +} + +sub get_nss_key +{ + return " "; +} + +sub init +{ + # Make sure the certificate databases are in place? +} + +sub get_library +{ + my ($self) = @_; + + return $self->{_library}; +} + +sub set_server_cert +{ + my $self = $_[0]; + my $params = $_[1]; + + $params->{cafile} = 'root+client_ca' unless defined $params->{cafile}; + + my $sslconf = + "ssl_ca_file='$params->{cafile}.crt'\n" + . "ssl_cert_file='ssl/$params->{certfile}.crt'\n" + . "ssl_crl_file=''\n" + . "ssl_database='nss/$params->{nssdatabase}'\n"; + + return $sslconf; +} + +sub cleanup +{ + # Something? +} + +1; diff --git a/src/test/ssl/t/SSL/Backend/OpenSSL.pm b/src/test/ssl/t/SSL/Backend/OpenSSL.pm index 991953bf2c..7caa8f23ee 100644 --- a/src/test/ssl/t/SSL/Backend/OpenSSL.pm +++ b/src/test/ssl/t/SSL/Backend/OpenSSL.pm @@ -72,26 +72,28 @@ sub init sub get_openssl_key { - my $self = $_[0]; - my $keyfile = $_[1]; + my $keyfile = shift; - return $key{$keyfile}; + return " sslkey=$key{$keyfile}"; } # Change the configuration to use given server cert file, and reload # the server so that the configuration takes effect. sub set_server_cert { - my $self = $_[0]; - my $certfile = $_[1]; - my $cafile = $_[2] || "root+client_ca"; - my $keyfile = $_[3] || $certfile; + my $self = $_[0]; + my $params = $_[1]; + + $params->{cafile} = 'root+client_ca' unless defined $params->{cafile}; + $params->{crlfile} = 'root+client.crl' unless defined $params->{crlfile}; + $params->{keyfile} = $params->{certfile} unless defined $params->{keyfile}; my $sslconf = - "ssl_ca_file='$cafile.crt'\n" - . "ssl_cert_file='$certfile.crt'\n" - . "ssl_key_file='$keyfile.key'\n" - . "ssl_crl_file='root+client.crl'\n"; + "ssl_ca_file='$params->{cafile}.crt'\n" + . "ssl_cert_file='$params->{certfile}.crt'\n" + . "ssl_key_file='$params->{keyfile}.key'\n" + . "ssl_crl_file='$params->{crlfile}'\n"; + $sslconf .= "ssl_crl_dir='$params->{crldir}'\n" if defined $params->{crldir}; return $sslconf; } diff --git a/src/test/ssl/t/SSL/Server.pm b/src/test/ssl/t/SSL/Server.pm index 9275876250..ef7b17ed74 100644 --- a/src/test/ssl/t/SSL/Server.pm +++ b/src/test/ssl/t/SSL/Server.pm @@ -37,7 +37,7 @@ use File::Basename; use File::Copy; use Test::More; use SSL::Backend::OpenSSL qw(get_new_openssl_backend get_openssl_key); -use SSL::Backend::NSS qw(get_new_nss_backend); +use SSL::Backend::NSS qw(get_new_nss_backend get_nss_key); our ($openssl, $nss, $backend); @@ -58,9 +58,8 @@ elsif ($ENV{with_ssl} eq 'nss') use Exporter 'import'; our @EXPORT = qw( configure_test_server_for_ssl - set_server_cert switch_server_cert - key + sslkey ); # Copy a set of files, taking into account wildcards @@ -79,11 +78,12 @@ sub copy_files return; } -sub key +# Return a sslkey construct for use in a connection string. +sub sslkey { - my ($node, $keyfile) = @_; + my $keyfile = shift; - return get_openssl_key($keyfile) if (defined($openssl); + return get_openssl_key($keyfile) if (defined($openssl)); return get_nss_key($keyfile) if (defined($nss)); } @@ -168,7 +168,7 @@ sub configure_test_server_for_ssl } elsif (defined($nss)) { - RecursiveCopy::copypath("ssl/nss", $pgdata . "/nss") if -e "ssl/nss"; + PostgreSQL::Test::RecursiveCopy::copypath("ssl/nss", $pgdata . "/nss") if -e "ssl/nss"; } # Stop and restart server to load new listen_addresses. @@ -193,46 +193,25 @@ sub cleanup $backend->cleanup(); } -# Change the configuration to use given server cert file, -sub set_server_cert +# Change the configuration to use the given set of certificate, key, ca and +# CRL, and potentially reload the configuration by restarting the server so +# that the configuration takes effect. Restarting is the default, passing +# restart => 'no' opts out of it leaving the server running. +sub switch_server_cert { - my $node = $_[0]; - my $certfile = $_[1]; - my $cafile = $_[2] || "root+client_ca"; - my $keyfile = $_[3] || ''; - my $pwcmd = $_[4] || ''; - my $crlfile = "root+client.crl"; - my $crldir; + my $node = shift; + my %params = @_; my $pgdata = $node->data_dir; - $keyfile = $certfile if $keyfile eq ''; - - # 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 $backend->set_server_cert($certfile, $cafile, $keyfile); - print $sslconf "ssl_crl_file='$crlfile'\n" if defined $crlfile; - print $sslconf "ssl_crl_dir='$crldir'\n" if defined $crldir; - print $sslconf "ssl_passphrase_command='$pwcmd'\n" - unless $pwcmd eq ''; + print $sslconf $backend->set_server_cert(\%params); + print $sslconf "ssl_passphrase_command='" . $params{passphrase_cmd} . "'\n" + if defined $params{passphrase_cmd}; close $sslconf; - return; -} -# Change the configuration to use given server cert file, and reload -# the server so that the configuration takes effect. -# Takes the same arguments as set_server_cert, which it calls to do that -# piece of the work. -sub switch_server_cert -{ - my $node = $_[0]; - set_server_cert(@_); + return if (defined($params{restart}) && $params{restart} eq 'no'); + $node->restart; return; } -- 2.24.3 (Apple Git-128)