runtests: rewrite genserv.sh in Perl

To remove POSIX shell as an extra dependency for runtests.

Also fix to `chmod 0600` the `.pem` file (was: `.prm`), and apply it
_before_ writing the keys.

Follow-up to 44341e736a #16824
Closes #16858
This commit is contained in:
Viktor Szakats 2025-03-28 14:33:02 +01:00
parent ad99067d92
commit 7be2c421bf
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
6 changed files with 119 additions and 120 deletions

View file

@ -62,7 +62,6 @@ This release includes the following bugfixes:
o cmake: allow empty `IMPORT_LIB_SUFFIX`, add suffix collision detection [41]
o cmake: avoid `-Wnonnull` warning in `HAVE_FSETXATTR_5` detection [81]
o cmake: disable HTTPS-proxy as a feature if proxy is disabled [77]
o cmake: document `SH_EXECUTABLE` option [252]
o cmake: drop `CURL_DISABLE_TESTS` option [94]
o cmake: drop `HAVE_C_FLAG_Wno_long_double` logic for ancient Apple gcc [126]
o cmake: drop `HAVE_IN_ADDR_T` from pre-fill too
@ -603,7 +602,6 @@ References to bug reports and discussions on issues:
[249] = https://curl.se/bug/?i=16673
[250] = https://curl.se/bug/?i=16671
[251] = https://curl.se/bug/?i=16720
[252] = https://curl.se/bug/?i=16830
[253] = https://curl.se/bug/?i=16723
[254] = https://curl.se/bug/?i=16705
[255] = https://curl.se/bug/?i=16719

View file

@ -395,7 +395,6 @@ Details via CMake
- `CLANG_TIDY`: `clang-tidy` tool used with `CURL_CLANG_TIDY=ON`. Default: `clang-tidy`
- `PERL_EXECUTABLE`: Perl binary used throughout the build and tests.
- `SH_EXECUTABLE`: POSIX shell binary used throughout the build (for generating test certificates).
## Dependency options (libraries)

View file

@ -25,18 +25,12 @@
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
find_program(SH_EXECUTABLE "sh")
mark_as_advanced(SH_EXECUTABLE)
if(SH_EXECUTABLE)
string(REPLACE ";" " " _certconfigs "${CERTCONFIGS}")
add_custom_command(OUTPUT ${GENERATEDCERTS}
COMMAND ${SH_EXECUTABLE} -c "${CMAKE_CURRENT_SOURCE_DIR}/genserv.sh test ${_certconfigs}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/genserv.sh" ${CERTCONFIG_CA} ${CERTCONFIGS}
VERBATIM
)
add_custom_target(build-certs
DEPENDS ${GENERATEDCERTS})
endif()
add_custom_command(OUTPUT ${GENERATEDCERTS}
COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/genserv.pl" "test" ${CERTCONFIGS}
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/genserv.pl" ${CERTCONFIG_CA} ${CERTCONFIGS}
VERBATIM
)
add_custom_target(build-certs DEPENDS ${GENERATEDCERTS})
add_custom_target(clean-certs
COMMAND ${CMAKE_COMMAND} -E remove ${GENERATEDCERTS}

View file

@ -26,7 +26,7 @@ AUTOMAKE_OPTIONS = foreign
include Makefile.inc
EXTRA_DIST = $(CERTCONFIG_CA) $(CERTCONFIGS) $(SRPFILES) CMakeLists.txt \
genserv.sh
genserv.pl
DISTCLEANFILES = $(GENERATEDCERTS)
@ -45,6 +45,6 @@ clean-certs:
build-certs: test-ca.cacert
# Generate all certs in a single shot, but declare just a single target file
# to support GNU Make <4.3 without "grouped explicit targets" support.
test-ca.cacert: $(CERTCONFIG_CA) $(CERTCONFIGS) genserv.sh
$(srcdir)/genserv.sh test $(CERTCONFIGS)
# to support GNU Make <4.3 without the "grouped explicit targets" feature.
test-ca.cacert: $(CERTCONFIG_CA) $(CERTCONFIGS) genserv.pl
$(PERL) $(srcdir)/genserv.pl test $(CERTCONFIGS)

109
tests/certs/genserv.pl Executable file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env perl
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) EdelWeb for EdelKey and OpenEvidence
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
use strict;
use warnings;
use File::Basename;
my $OPENSSL = 'openssl';
if(-f '/usr/local/ssl/bin/openssl') {
$OPENSSL = '/usr/local/ssl/bin/openssl';
}
my $SRCDIR = dirname(__FILE__);
my $fh;
my $dev_null = $^O eq 'MSWin32' ? 'NUL' : '/dev/null';
my $KEYSIZE = 'prime256v1';
my $DURATION;
my $PREFIX;
my $CAPREFIX = shift @ARGV;
if(!$CAPREFIX) {
print "Usage: genserv.pl <caprefix> [<prefix> ...]\n";
exit 1;
} elsif(! -f "$CAPREFIX-ca.cacert" ||
! -f "$CAPREFIX-ca.key") {
system($^O eq 'MSWin32' ? 'which' : 'command -v' ." $OPENSSL");
system("$OPENSSL version");
$PREFIX = $CAPREFIX;
$DURATION = 6000;
system("$OPENSSL genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$KEYSIZE -pkeyopt ec_param_enc:named_curve " .
"-out $PREFIX-ca.key -pass pass:secret");
system("$OPENSSL req -config $SRCDIR/$PREFIX-ca.prm -new -key $PREFIX-ca.key -out $PREFIX-ca.csr -passin pass:secret 2>$dev_null");
system("$OPENSSL x509 -sha256 -extfile $SRCDIR/$PREFIX-ca.prm -days $DURATION " .
"-req -signkey $PREFIX-ca.key -in $PREFIX-ca.csr -out $PREFIX-ca.raw-cacert");
system("$OPENSSL x509 -in $PREFIX-ca.raw-cacert -text -nameopt multiline > $PREFIX-ca.cacert");
system("$OPENSSL x509 -in $PREFIX-ca.cacert -outform der -out $PREFIX-ca.der");
system("$OPENSSL x509 -in $PREFIX-ca.cacert -text -nameopt multiline > $PREFIX-ca.crt");
print "CA root generated: $PREFIX $DURATION days $KEYSIZE\n";
}
$DURATION = 300;
open($fh, '>>', "$CAPREFIX-ca.db") and close($fh); # for revoke server cert
while(@ARGV) {
$PREFIX = shift @ARGV;
$PREFIX =~ s/\.prm$//;
# pseudo-secrets
system("$OPENSSL genpkey -algorithm EC -pkeyopt ec_paramgen_curve:$KEYSIZE -pkeyopt ec_param_enc:named_curve " .
"-out $PREFIX.keyenc -pass pass:secret");
system("$OPENSSL req -config $SRCDIR/$PREFIX.prm -new -key $PREFIX.keyenc -out $PREFIX.csr -passin pass:secret 2>$dev_null");
system("$OPENSSL pkey -in $PREFIX.keyenc -out $PREFIX.key -passin pass:secret");
system("$OPENSSL pkey -in $PREFIX.key -pubout -outform DER -out $PREFIX.pub.der");
system("$OPENSSL pkey -in $PREFIX.key -pubout -outform PEM -out $PREFIX.pub.pem");
system("$OPENSSL x509 -sha256 -extfile $SRCDIR/$PREFIX.prm -days $DURATION " .
"-req -CA $CAPREFIX-ca.cacert -CAkey $CAPREFIX-ca.key -CAcreateserial -in $PREFIX.csr > $PREFIX.crt 2>$dev_null");
# revoke server cert
if(open($fh, '>', "$CAPREFIX-ca.cnt")) {
print $fh '01';
close($fh);
}
system("$OPENSSL ca -config $SRCDIR/$CAPREFIX-ca.cnf -revoke $PREFIX.crt 2>$dev_null");
# issue CRL
system("$OPENSSL ca -config $SRCDIR/$CAPREFIX-ca.cnf -gencrl -out $PREFIX.crl 2>$dev_null");
system("$OPENSSL x509 -in $PREFIX.crt -outform der -out $PREFIX.der");
# concatenate all together now
open($fh, '>', "$PREFIX.pem") and close($fh);
chmod 0600, "$PREFIX.pem";
if(open($fh, '>>', "$PREFIX.pem")) {
my $fi;
print $fh do { local $/; open $fi, '<', $_ and <$fi> } for("$SRCDIR/$PREFIX.prm", "$PREFIX.key", "$PREFIX.crt");
close($fh);
}
print "Certificate generated: CA=$CAPREFIX ${DURATION}days $KEYSIZE $PREFIX\n";
}

View file

@ -1,101 +0,0 @@
#!/bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) EdelWeb for EdelKey and OpenEvidence
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# exit on first fail
set -eu
OPENSSL=openssl
if [ -f /usr/local/ssl/bin/openssl ]; then
OPENSSL=/usr/local/ssl/bin/openssl
fi
USAGE='echo Usage is genserv.sh <caprefix> [<prefix> ...]'
SRCDIR="$(dirname "${0}")"
KEYSIZE=prime256v1
CAPREFIX="${1:-}"
shift
if [ -z "$CAPREFIX" ]; then
echo 'No CA prefix'
$USAGE
exit
elif [ ! -f "$CAPREFIX-ca.cacert" ] || \
[ ! -f "$CAPREFIX-ca.key" ]; then
command -v "$OPENSSL"
"$OPENSSL" version
# Generating CA root
PREFIX=$CAPREFIX
DURATION=6000
"$OPENSSL" genpkey -algorithm EC -pkeyopt ec_paramgen_curve:"$KEYSIZE" -pkeyopt ec_param_enc:named_curve \
-out "$PREFIX-ca.key" -pass 'pass:secret'
"$OPENSSL" req -config "$SRCDIR/$PREFIX-ca.prm" -new -key "$PREFIX-ca.key" -out "$PREFIX-ca.csr" -passin 'pass:secret' 2>/dev/null
"$OPENSSL" x509 -sha256 -extfile "$SRCDIR/$PREFIX-ca.prm" -days "$DURATION" \
-req -signkey "$PREFIX-ca.key" -in "$PREFIX-ca.csr" -out "$PREFIX-ca.raw-cacert"
"$OPENSSL" x509 -in "$PREFIX-ca.raw-cacert" -text -nameopt multiline > "$PREFIX-ca.cacert"
"$OPENSSL" x509 -in "$PREFIX-ca.cacert" -outform der -out "$PREFIX-ca.der"
"$OPENSSL" x509 -in "$PREFIX-ca.cacert" -text -nameopt multiline > "$PREFIX-ca.crt"
echo "CA root generated: $PREFIX ${DURATION}days $KEYSIZE"
fi
DURATION=300
while [ -n "${1:-}" ]; do
PREFIX="${1%.prm}"
shift
# pseudo-secrets
"$OPENSSL" genpkey -algorithm EC -pkeyopt ec_paramgen_curve:"$KEYSIZE" -pkeyopt ec_param_enc:named_curve \
-out "$PREFIX.keyenc" -pass 'pass:secret'
"$OPENSSL" req -config "$SRCDIR/$PREFIX.prm" -new -key "$PREFIX.keyenc" -out "$PREFIX.csr" -passin 'pass:secret' 2>/dev/null
"$OPENSSL" pkey -in "$PREFIX.keyenc" -out "$PREFIX.key" -passin 'pass:secret'
"$OPENSSL" pkey -in "$PREFIX.key" -pubout -outform DER -out "$PREFIX.pub.der"
"$OPENSSL" pkey -in "$PREFIX.key" -pubout -outform PEM -out "$PREFIX.pub.pem"
"$OPENSSL" x509 -sha256 -extfile "$SRCDIR/$PREFIX.prm" -days "$DURATION" \
-req -CA "$CAPREFIX-ca.cacert" -CAkey "$CAPREFIX-ca.key" -CAcreateserial -in "$PREFIX.csr" > "$PREFIX.crt" 2>/dev/null
# revoke server cert
touch "$CAPREFIX-ca.db"
echo 01 > "$CAPREFIX-ca.cnt"
"$OPENSSL" ca -config "$SRCDIR/$CAPREFIX-ca.cnf" -revoke "$PREFIX.crt" 2>/dev/null
# issue CRL
"$OPENSSL" ca -config "$SRCDIR/$CAPREFIX-ca.cnf" -gencrl -out "$PREFIX.crl" 2>/dev/null
"$OPENSSL" x509 -in "$PREFIX.crt" -outform der -out "$PREFIX.der"
# all together now
cat "$SRCDIR/$PREFIX.prm" "$PREFIX.key" "$PREFIX.crt" > "$PREFIX.pem"
chmod o-r "$SRCDIR/$PREFIX.prm"
echo "Certificate generated: CA=$CAPREFIX ${DURATION}days $KEYSIZE $PREFIX"
done