Make finding openssl program a configure or meson option
authorPeter Eisentraut <[email protected]>
Thu, 20 Oct 2022 19:01:05 +0000 (21:01 +0200)
committerPeter Eisentraut <[email protected]>
Thu, 20 Oct 2022 19:05:42 +0000 (21:05 +0200)
Various test suites use the "openssl" program as part of their setup.
There isn't a way to override which openssl program is to be used,
other than by fiddling with the path, perhaps.  This has gotten
increasingly problematic because different versions of openssl have
different capabilities and do different things by default.

This patch checks for an openssl binary in configure and meson setup,
with appropriate ways to override it.  This is similar to how "lz4"
and "zstd" are handled, for example.  The meson build system actually
already did this, but the result was only used in some places.  This
is now applied more uniformly.

Reviewed-by: Michael Paquier <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/dc638b75-a16a-007d-9e1c-d16ed6cf0ad2%40enterprisedb.com

16 files changed:
configure
configure.ac
doc/src/sgml/install-windows.sgml
meson.build
meson_options.txt
src/Makefile.global.in
src/test/ldap/Makefile
src/test/ldap/meson.build
src/test/ldap/t/001_auth.pl
src/test/modules/ssl_passphrase_callback/Makefile
src/test/modules/ssl_passphrase_callback/meson.build
src/test/ssl/Makefile
src/test/ssl/meson.build
src/test/ssl/sslfiles.mk
src/test/ssl/t/001_ssltests.pl
src/tools/msvc/vcregress.pl

index 5ea790d63803c814bd15846a58a595336ab6dc44..3966368b8d9f4d23bdd52a3602443e0452027d90 100755 (executable)
--- a/configure
+++ b/configure
@@ -648,6 +648,7 @@ PG_CRC32C_OBJS
 CFLAGS_ARMV8_CRC32C
 CFLAGS_SSE42
 LIBOBJS
+OPENSSL
 ZSTD
 LZ4
 UUID_LIBS
@@ -14112,6 +14113,60 @@ done
 
 fi
 
+if test -z "$OPENSSL"; then
+  for ac_prog in openssl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_OPENSSL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OPENSSL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OPENSSL="$OPENSSL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_OPENSSL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OPENSSL=$ac_cv_path_OPENSSL
+if test -n "$OPENSSL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL" >&5
+$as_echo "$OPENSSL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$OPENSSL" && break
+done
+
+else
+  # Report the value of OPENSSL in configure's output in all cases.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+$as_echo_n "checking for OPENSSL... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL" >&5
+$as_echo "$OPENSSL" >&6; }
+fi
+
 if test "$with_ssl" = openssl ; then
   ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
 if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
index d80cdb5ca25410c75e3000a9e76ab1da0091fefe..f76b7ee31fcb07a45b3986b501944cd14a00df8b 100644 (file)
@@ -1542,6 +1542,7 @@ if test "$with_gssapi" = yes ; then
    [AC_CHECK_HEADERS(gssapi.h, [], [AC_MSG_ERROR([gssapi.h header file is required for GSSAPI])])])
 fi
 
+PGAC_PATH_PROGS(OPENSSL, openssl)
 if test "$with_ssl" = openssl ; then
   AC_CHECK_HEADER(openssl/ssl.h, [], [AC_MSG_ERROR([header file <openssl/ssl.h> is required for OpenSSL])])
   AC_CHECK_HEADER(openssl/err.h, [], [AC_MSG_ERROR([header file <openssl/err.h> is required for OpenSSL])])
index 29d3294dc80a75ded89f4cd8c6f8267d86d421ea..a1013d12807928066dc8c02bfdfce0a8a07193d1 100644 (file)
@@ -541,6 +541,15 @@ $ENV{PROVE_TESTS}='t/020*.pl t/010*.pl'
      </para></listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><varname>OPENSSL</varname></term>
+     <listitem><para>
+      Path to a <application>openssl</application> command. The default is
+      <literal>openssl</literal>, which will search for a command by that
+      name in the configured <envar>PATH</envar>.
+     </para></listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><varname>TAR</varname></term>
      <listitem><para>
index 2d225f706d2ff881aa18c0c1bca4d4b41c50f109..bfacbdc0af69193ba709c285c3f693406bec3ab0 100644 (file)
@@ -328,6 +328,7 @@ tar = find_program(get_option('TAR'), native: true)
 gzip = find_program(get_option('GZIP'), native: true)
 program_lz4 = find_program(get_option('LZ4'), native: true, required: false)
 touch = find_program('touch', native: true)
+openssl = find_program(get_option('OPENSSL'), native: true, required: false)
 program_zstd = find_program(get_option('ZSTD'), native: true, required: false)
 dtrace = find_program(get_option('DTRACE'), native: true, required: get_option('dtrace'))
 missing = find_program('config/missing', native: true)
index b629cd8d6890e1cb03f21a0347bdca407e66fc33..c7ea57994dc78ae80f7c80128c7047b33bef3cb8 100644 (file)
@@ -157,6 +157,9 @@ option('GZIP', type : 'string', value: 'gzip',
 option('LZ4', type : 'string', value: 'lz4',
   description: 'path to lz4 binary')
 
+option('OPENSSL', type : 'string', value: 'openssl',
+  description: 'path to openssl binary')
+
 option('PERL', type : 'string', value: 'perl',
   description: 'path to perl binary')
 
index 99889167e18bf5371fd660a5af6f70c3be8717eb..e96bedd4e7b90e347233bccb07d18bbaf42abd1e 100644 (file)
@@ -343,6 +343,7 @@ LN_S    = @LN_S@
 MSGFMT  = @MSGFMT@
 MSGFMT_FLAGS = @MSGFMT_FLAGS@
 MSGMERGE = @MSGMERGE@
+OPENSSL    = @OPENSSL@
 PYTHON = @PYTHON@
 TAR    = @TAR@
 XGETTEXT = @XGETTEXT@
index e5fa3d86104c8092604de685860f411573664075..b1e4a7be677c58bfc4a66fd4a6c6d7b3aed9eb5b 100644 (file)
@@ -14,6 +14,7 @@ top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
 export with_ldap
+export OPENSSL
 
 check:
    $(prove_check)
index 2211bd5e3ecfaf63032d4abdc94c1d6e1f3df1cd..020f6e7f087b51a1fac5e1ba9cb5634a4dc63b70 100644 (file)
@@ -6,6 +6,9 @@ tests += {
     'tests': [
       't/001_auth.pl',
     ],
-    'env': {'with_ldap': ldap.found() ? 'yes' : 'no'},
+    'env': {
+      'with_ldap': ldap.found() ? 'yes' : 'no',
+      'OPENSSL': openssl.path(),
+    },
   },
 }
index 2f064f6944069aadfea7058f11763f87f9d9d2c5..fd90832b755a7dadc3f9c0774a297f0bde241277 100644 (file)
@@ -113,13 +113,15 @@ append_to_file(
 mkdir $ldap_datadir or die;
 mkdir $slapd_certs  or die;
 
-system_or_bail "openssl", "req", "-new", "-nodes", "-keyout",
+my $openssl = $ENV{OPENSSL};
+
+system_or_bail $openssl, "req", "-new", "-nodes", "-keyout",
   "$slapd_certs/ca.key", "-x509", "-out", "$slapd_certs/ca.crt", "-subj",
   "/CN=CA";
-system_or_bail "openssl", "req", "-new", "-nodes", "-keyout",
+system_or_bail $openssl, "req", "-new", "-nodes", "-keyout",
   "$slapd_certs/server.key", "-out", "$slapd_certs/server.csr", "-subj",
   "/CN=server";
-system_or_bail "openssl", "x509", "-req", "-in", "$slapd_certs/server.csr",
+system_or_bail $openssl, "x509", "-req", "-in", "$slapd_certs/server.csr",
   "-CA", "$slapd_certs/ca.crt", "-CAkey", "$slapd_certs/ca.key",
   "-CAcreateserial", "-out", "$slapd_certs/server.crt";
 
index a34d7ea46a3c4683889f3b07c1aeb417cb756563..922f0ee078649ffaa7e9683275a6b8563fe1fa94 100644 (file)
@@ -31,9 +31,9 @@ PASS = FooBaR1
 .PHONY: ssl-files ssl-files-clean
 
 ssl-files:
-   openssl req -new -x509 -days 10000 -nodes -out server.crt \
+   $(OPENSSL) req -new -x509 -days 10000 -nodes -out server.crt \
        -keyout server.ckey -subj "/CN=localhost"
-   openssl rsa -aes256 -in server.ckey -out server.key -passout pass:$(PASS)
+   $(OPENSSL) rsa -aes256 -in server.ckey -out server.key -passout pass:$(PASS)
    rm server.ckey
 
 ssl-files-clean:
index a9eb4c564dae7ca88ecbf4436f0de04cd05dae86..1c9f009af3738cd243b61d3e320e0201aa80e35b 100644 (file)
@@ -25,8 +25,6 @@ testprep_targets += ssl_passphrase_callback
 # Targets to generate or remove the ssl certificate and key. Need to be copied
 # to the source afterwards. Normally not needed.
 
-openssl = find_program('openssl', native: true, required: false)
-
 if openssl.found()
   cert = custom_target('server.crt',
     output: ['server.crt', 'server.ckey'],
index 12b02eb422bf353afba7de7bdc86c10da651796e..2885c7c269323f8e83c55ebd02c3d8c140427753 100644 (file)
@@ -15,7 +15,7 @@ subdir = src/test/ssl
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-export with_ssl
+export OPENSSL with_ssl
 
 # The sslfiles targets are separated into their own file due to interactions
 # with settings in Makefile.global.
index e2f021d884a32c79786f22b8301dc1ffbf10b9f6..1e02bf9ed0c5de737c1f95f145ec2177c686284b 100644 (file)
@@ -3,7 +3,10 @@ tests += {
   'sd': meson.current_source_dir(),
   'bd': meson.current_build_dir(),
   'tap': {
-    'env': {'with_ssl': get_option('ssl')},
+    'env': {
+      'with_ssl': get_option('ssl'),
+      'OPENSSL': openssl.path(),
+    },
     'tests': [
       't/001_ssltests.pl',
       't/002_scram.pl',
index a843a21d42e9bb18c3062d717c21d19306f9c007..54ada01d466190f4631b2b3734419c13813b994b 100644 (file)
@@ -84,7 +84,7 @@ sslfiles: $(SSLFILES) $(SSLDIRS)
 
 # Root CA is self-signed.
 ssl/root_ca.crt: ssl/root_ca.key conf/root_ca.config
-   openssl req -new -x509 -config conf/root_ca.config -days 10000 -key $< -out $@
+   $(OPENSSL) req -new -x509 -config conf/root_ca.config -days 10000 -key $< -out $@
 
 #
 # Special-case keys
@@ -94,20 +94,20 @@ ssl/root_ca.crt: ssl/root_ca.key conf/root_ca.config
 
 # 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'
+   $(OPENSSL) rsa -aes256 -in $< -out $@ -passout 'pass:secret1'
 
 # DER-encoded version of client.key
 ssl/client-der.key: ssl/client.key
-   openssl rsa -in $< -outform DER -out $@
+   $(OPENSSL) rsa -in $< -outform DER -out $@
 
 # Convert client.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 $< -outform PEM -aes128 -passout 'pass:dUmmyP^#+' -out $@
+   $(OPENSSL) rsa -in $< -outform PEM -aes128 -passout 'pass:dUmmyP^#+' -out $@
 # TODO Explicitly choosing -aes128 generates a key unusable to PostgreSQL with
 # OpenSSL 3.0.0, so fall back on the default for now.
 ssl/client-encrypted-der.key: ssl/client.key
-   openssl rsa -in $< -outform DER -passout 'pass:dUmmyP^#+' -out $@
+   $(OPENSSL) rsa -in $< -outform DER -passout 'pass:dUmmyP^#+' -out $@
 
 #
 # Combined files
@@ -145,7 +145,7 @@ $(COMBINATIONS):
 #
 
 $(STANDARD_KEYS):
-   openssl genrsa -out $@ 2048
+   $(OPENSSL) genrsa -out $@ 2048
    chmod 0600 $@
 
 #
@@ -165,18 +165,18 @@ client_ca_state_files := ssl/client_ca-certindex ssl/client_ca-certindex.attr ss
 # parallel processes, so we must mark the entire Makefile .NOTPARALLEL.
 .NOTPARALLEL:
 $(CA_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/root_ca.crt | ssl/new_certs_dir $(root_ca_state_files)
-   openssl ca -batch -config conf/cas.config -name root_ca   -notext -in $< -out $@
+   $(OPENSSL) ca -batch -config conf/cas.config -name root_ca   -notext -in $< -out $@
 
 $(SERVER_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/server_ca.crt | ssl/new_certs_dir $(server_ca_state_files)
-   openssl ca -batch -config conf/cas.config -name server_ca -notext -in $< -out $@
+   $(OPENSSL) ca -batch -config conf/cas.config -name server_ca -notext -in $< -out $@
 
 $(CLIENT_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/client_ca.crt | ssl/new_certs_dir $(client_ca_state_files)
-   openssl ca -batch -config conf/cas.config -name client_ca -notext -in $< -out $@
+   $(OPENSSL) ca -batch -config conf/cas.config -name client_ca -notext -in $< -out $@
 
 # The CSRs don't need to persist after a build.
 .INTERMEDIATE: $(CERTIFICATES:%=ssl/%.csr)
 ssl/%.csr: ssl/%.key conf/%.config
-   openssl req -new -utf8 -key $< -out $@ -config conf/$*.config
+   $(OPENSSL) req -new -utf8 -key $< -out $@ -config conf/$*.config
 
 #
 # CA State
@@ -210,16 +210,16 @@ ssl/%.srl:
 #
 
 ssl/root.crl: ssl/root_ca.crt | $(root_ca_state_files)
-   openssl ca -config conf/cas.config -name root_ca   -gencrl -out $@
+   $(OPENSSL) ca -config conf/cas.config -name root_ca   -gencrl -out $@
 
 ssl/server.crl: ssl/server-revoked.crt ssl/server_ca.crt | $(server_ca_state_files)
-   openssl ca -config conf/cas.config -name server_ca -revoke $<
-   openssl ca -config conf/cas.config -name server_ca -gencrl -out $@
+   $(OPENSSL) ca -config conf/cas.config -name server_ca -revoke $<
+   $(OPENSSL) ca -config conf/cas.config -name server_ca -gencrl -out $@
 
 ssl/client.crl: ssl/client-revoked.crt ssl/client-revoked-utf8.crt ssl/client_ca.crt | $(client_ca_state_files)
-   openssl ca -config conf/cas.config -name client_ca -revoke ssl/client-revoked.crt
-   openssl ca -config conf/cas.config -name client_ca -revoke ssl/client-revoked-utf8.crt
-   openssl ca -config conf/cas.config -name client_ca -gencrl -out $@
+   $(OPENSSL) ca -config conf/cas.config -name client_ca -revoke ssl/client-revoked.crt
+   $(OPENSSL) ca -config conf/cas.config -name client_ca -revoke ssl/client-revoked-utf8.crt
+   $(OPENSSL) ca -config conf/cas.config -name client_ca -gencrl -out $@
 
 #
 # CRL hash directories
@@ -230,7 +230,7 @@ ssl/root+client-crldir: ssl/client.crl ssl/root.crl
 ssl/server-crldir: ssl/server.crl
 ssl/client-crldir: ssl/client.crl
 
-crlhashfile = $(shell openssl crl -hash -noout -in $(1)).r0
+crlhashfile = $(shell $(OPENSSL) crl -hash -noout -in $(1)).r0
 
 ssl/%-crldir:
    mkdir -p $@
index efe5634fff2626035000f49c7549daaea43cf729..fe42161a0fa3896b475c4005be91a557ea9dad13 100644 (file)
@@ -611,7 +611,7 @@ TODO:
 
 # pg_stat_ssl
 
-my $serialno = `openssl x509 -serial -noout -in ssl/client.crt`;
+my $serialno = `$ENV{OPENSSL} x509 -serial -noout -in ssl/client.crt`;
 if ($? == 0)
 {
    # OpenSSL prints serial numbers in hexadecimal and converting the serial
@@ -633,7 +633,7 @@ 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';
+   warn "couldn't run \"$ENV{OPENSSL} x509\" to get client cert serialno";
    $serialno = '\d+';
 }
 
index 5182721eb79f8deed2ac88f4d5393b3775697082..1d86cd650f932ec41d325b6df157f45dfd6aa010 100644 (file)
@@ -146,6 +146,7 @@ sub set_command_env
 {
    set_single_env('GZIP_PROGRAM', 'gzip');
    set_single_env('LZ4',          'lz4');
+   set_single_env('OPENSSL',      'openssl');
    set_single_env('ZSTD',         'zstd');
 }