Skip to content

Commit 7873712

Browse files
authored
Merge pull request #336 from jtesta/docker_test_update
Docker test system update
2 parents 771e01a + d796ac7 commit 7873712

File tree

18 files changed

+831
-537
lines changed

18 files changed

+831
-537
lines changed

docker_test.sh

Lines changed: 29 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,20 @@
11
#!/bin/bash
22

33
#
4-
# Copyright (C) 2019-2020 Joe Testa <[email protected]>
4+
# Copyright (C) 2019-2025 Joe Testa <[email protected]>
55
#
6-
# This script (adapted from the ssh-audit project) will set up a docker image with
7-
# multiple SSL/TLS servers. They are each executed one at a time, and sslscan is run
8-
# against them. The output of sslscan is compared against the expected output. If
9-
# they match, the test passes; otherwise the test fails.
6+
# This script (adapted from the ssh-audit project) will set up a docker image with multiple SSL/TLS servers. They are each executed one at a time, and sslscan is run against them. The output of sslscan is compared against the expected output. If they match, the test passes; otherwise the test fails.
107
#
8+
# Running this script with no arguments causes it to build the docker image (if it doesn't yet exist), then run all tests.
119
#
12-
# For debugging purposes, here is a cheat sheet for manually running the docker image:
13-
#
14-
# docker run -p 4443:443 --security-opt seccomp:unconfined -it sslscan-test:3 /bin/bash
10+
# Running the script with a test number argument (i.e.: './docker_test.sh 2') will run the docker image for test #2 only (in the background) and do nothing else. This allows the test itself to be debugged.
1511
#
1612

17-
#
18-
# Running this script with no arguments causes it to build the docker image (if it
19-
# doesn't yet exist), then run all tests.
20-
#
21-
# Running the script with a test number argument (i.e.: './docker_test.sh 2') will
22-
# run the docker image for test #2 only (in the background) and do nothing else. This
23-
# allows the test itself to be debugged.
24-
#
2513

14+
# This is the docker tag for the image. If this tag doesn't exist, then we assume the image is out of date, and generate a new one with this tag.
15+
IMAGE_VERSION=4
2616

27-
# This is the docker tag for the image. If this tag doesn't exist, then we assume the
28-
# image is out of date, and generate a new one with this tag.
29-
IMAGE_VERSION=3
30-
31-
# This is the name of our docker image.
17+
# This is the name of our test image.
3218
IMAGE_NAME=sslscan-test
3319

3420

@@ -44,190 +30,12 @@ GREENB="\033[1;32m" # Green + bold
4430
all_passed=1
4531

4632

47-
# Number of processors on this system (used to compile parallel builds).
48-
NUM_PROCS=`/usr/bin/nproc --all 2> /dev/null`
49-
if [[ $NUM_PROCS == '' ]]; then
50-
NUM_PROCS=4
51-
fi
52-
53-
5433
# Returns 0 if current docker image exists.
5534
function check_if_docker_image_exists {
5635
images=`docker image ls | grep -E "$IMAGE_NAME[[:space:]]+$IMAGE_VERSION"`
5736
}
5837

5938

60-
# Compile all version of GnuTLS.
61-
function compile_gnutls_all {
62-
compile_gnutls '3.6.11.1'
63-
}
64-
65-
66-
# Compile all versions of OpenSSL.
67-
function compile_openssl_all {
68-
compile_openssl '1.0.0'
69-
compile_openssl '1.0.2'
70-
compile_openssl '1.1.1'
71-
}
72-
73-
74-
# Compile a specific version of OpenSSL.
75-
function compile_openssl {
76-
version=$1
77-
78-
git_tag=
79-
compile_args=
80-
precompile_command=
81-
output_dir=
82-
compile_num_procs=$NUM_PROCS
83-
if [[ $version == '1.0.0' ]]; then
84-
git_tag="OpenSSL_1_0_0-stable"
85-
compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib no-shared"
86-
precompile_command="make depend"
87-
output_dir="openssl_v1.0.0_dir"
88-
compile_num_procs=1 # Compilation randomly fails when done in parallel.
89-
elif [[ $version == '1.0.2' ]]; then
90-
git_tag="OpenSSL_1_0_2-stable"
91-
compile_args="enable-weak-ssl-ciphers enable-ssl2 zlib"
92-
precompile_command="make depend"
93-
output_dir="openssl_v1.0.2_dir"
94-
elif [[ $version == '1.1.1' ]]; then
95-
git_tag="OpenSSL_1_1_1-stable"
96-
compile_args="enable-weak-ssl-ciphers no-shared zlib"
97-
output_dir="openssl_v1.1.1_dir"
98-
else
99-
echo -e "${REDB}Error: OpenSSL v${version} is unknown!${CLR}"
100-
exit 1
101-
fi
102-
103-
# Download OpenSSL from github.
104-
echo -e "\n${YELLOWB}Downloading OpenSSL v${version}...${CLR}\n"
105-
git clone --depth 1 -b $git_tag https://github.com/openssl/openssl/ $output_dir
106-
107-
# Configure and compile it.
108-
echo -e "\n\n${YELLOWB}Compiling OpenSSL v${version} with \"-j ${compile_num_procs}\"...${CLR}"
109-
pushd $output_dir
110-
./config $compile_args
111-
if [[ $precompile_command != '' ]]; then $precompile_command; fi
112-
make -j $compile_num_procs
113-
114-
# Ensure that the 'openssl' command-line tool was built.
115-
if [[ ! -f "apps/openssl" ]]; then
116-
echo -e "${REDB}Error: compilation failed! apps/openssl not found.${CLR}\n\nStrangely, sometimes OpenSSL v1.0.0 fails for no reason; simply running this script again and changing nothing fixes the problem.\n\n"
117-
exit 1
118-
fi
119-
120-
# Copy the 'openssl' app to the top-level docker building dir as, e.g. 'openssl_prog_v1.0.0'. Then we can delete the source code directory and move on.
121-
cp "apps/openssl" "../openssl_prog_v${version}"
122-
popd
123-
124-
# Delete the source code directory now that we built the 'openssl' tool and moved it out.
125-
rm -rf $output_dir
126-
echo -e "\n\n${YELLOWB}Compilation of v${version} finished.${CLR}\n\n"
127-
}
128-
129-
130-
# Compile a specific version of GnuTLS.
131-
function compile_gnutls {
132-
gnutls_version=$1
133-
134-
gnutls_url=
135-
nettle_url=
136-
gnutls_expected_sha256=
137-
nettle_expected_sha256=
138-
gnutls_filename=
139-
nettle_filename=
140-
gnutls_source_dir=
141-
nettle_source_dir=
142-
nettle_version=
143-
compile_num_procs=$NUM_PROCS
144-
compile_nettle=0
145-
if [[ $gnutls_version == '3.6.11.1' ]]; then
146-
gnutls_url=https://www.gnupg.org/ftp/gcrypt/gnutls/v3.6/gnutls-3.6.11.1.tar.xz
147-
gnutls_expected_sha256=fbba12f3db9a55dbf027e14111755817ec44b57eabec3e8089aac8ac6f533cf8
148-
gnutls_filename=gnutls-3.6.11.1.tar.xz
149-
gnutls_source_dir=gnutls-3.6.11.1
150-
nettle_version=3.5.1
151-
nettle_url=https://ftp.gnu.org/gnu/nettle/nettle-3.5.1.tar.gz
152-
nettle_expected_sha256=75cca1998761b02e16f2db56da52992aef622bf55a3b45ec538bc2eedadc9419
153-
nettle_filename=nettle-3.5.1.tar.gz
154-
nettle_source_dir=nettle-3.5.1
155-
compile_nettle=1
156-
else
157-
echo -e "${REDB}Error: GnuTLS v${gnutls_version} is unknown!${CLR}"
158-
exit 1
159-
fi
160-
161-
# Download GnuTLS.
162-
echo -e "\n${YELLOWB}Downloading GnuTLS v${gnutls_version}...${CLR}\n"
163-
wget $gnutls_url
164-
165-
# Download nettle.
166-
echo -e "\n${YELLOWB}Downloading nettle library v${nettle_version}...${CLR}\n"
167-
wget $nettle_url
168-
169-
# Check the SHA256 hashes.
170-
gnutls_actual_sha256=`sha256sum ${gnutls_filename} | cut -f1 -d" "`
171-
nettle_actual_sha256=`sha256sum ${nettle_filename} | cut -f1 -d" "`
172-
173-
if [[ ($gnutls_actual_sha256 != $gnutls_expected_sha256) || ($nettle_actual_sha256 != $nettle_expected_sha256) ]]; then
174-
echo -e "${REDB}GnuTLS/nettle actual hashes differ from expected hashes! ${CLR}\n"
175-
echo -e "\tGnuTLS expected hash: ${gnutls_expected_sha256}\n"
176-
echo -e "\tGnuTLS actual hash: ${gnutls_actual_sha256}\n"
177-
echo -e "\tnettle expected hash: ${nettle_expected_sha256}\n"
178-
echo -e "\tnettle actual hash: ${nettle_actual_sha256}\n\n"
179-
exit 1
180-
else
181-
echo -e "${GREEN}Hashes verified.${CLR}\n"
182-
fi
183-
184-
tar xJf $gnutls_filename
185-
186-
if [[ $compile_nettle == 1 ]]; then
187-
tar xzf $nettle_filename
188-
mv $nettle_source_dir nettle
189-
190-
# Configure and compile nettle.
191-
echo -e "\n\n${YELLOWB}Compiling nettle v${nettle_version} with \"-j ${compile_num_procs}\"...${CLR}"
192-
pushd nettle
193-
./configure && make -j $compile_num_procs
194-
195-
if [[ ! -f libnettle.so || ! -f libhogweed.so ]]; then
196-
echo -e "${REDB}Error: compilation failed! libnettle.so and/or libhogweed.so not found.${CLR}"
197-
exit 1
198-
fi
199-
popd
200-
fi
201-
202-
# Configure and compile GnuTLS.
203-
echo -e "\n\n${YELLOWB}Compiling GnuTLS v${gnutls_version} with \"-j ${compile_num_procs}\"...${CLR}"
204-
pushd $gnutls_source_dir
205-
nettle_source_dir_abs=`readlink -m ../nettle`
206-
nettle_parent_dir=`readlink -m ..`
207-
NETTLE_CFLAGS=-I${nettle_parent_dir} NETTLE_LIBS="-L${nettle_source_dir_abs} -lnettle" HOGWEED_CFLAGS=-I${nettle_parent_dir} HOGWEED_LIBS="-L${nettle_source_dir_abs} -lhogweed" ./configure --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-guile
208-
make CFLAGS=-I${nettle_parent_dir} LDFLAGS="-L${nettle_source_dir_abs} -lhogweed -lnettle" -j $compile_num_procs
209-
210-
# Ensure that the gnutls-serv and gnutls-cli tools were built
211-
if [[ (! -f "src/.libs/gnutls-cli") || (! -f "src/.libs/gnutls-serv") ]]; then
212-
echo -e "${REDB}Error: compilation failed! gnutls-cli and/or gnutls-serv not found.${CLR}\n"
213-
exit 1
214-
fi
215-
216-
# Copy the gnutls-cli and gnutls-serv apps to the top-level docker building dir as, e.g. 'gnutls-cli-v3.6.11.1'. Then we can delete the source code directory and move on.
217-
cp "lib/.libs/libgnutls.so" "../libgnutls.so.30"
218-
cp "src/.libs/gnutls-cli" "../gnutls-cli-v${gnutls_version}"
219-
cp "src/.libs/gnutls-serv" "../gnutls-serv-v${gnutls_version}"
220-
cp "${nettle_source_dir_abs}/libhogweed.so" "../libhogweed.so.5"
221-
cp "${nettle_source_dir_abs}/libnettle.so" "../libnettle.so.7"
222-
popd
223-
224-
225-
# Delete the source code directory now that we built the tools and moved them out.
226-
rm -rf ${gnutls_source_dir}
227-
echo -e "\n\n${YELLOWB}Compilation of GnuTLS v${gnutls_version} finished.${CLR}\n\n"
228-
}
229-
230-
23139
# Creates a new docker image.
23240
function create_docker_image {
23341
# Create a new temporary directory.
@@ -240,12 +48,6 @@ function create_docker_image {
24048
# process.
24149
pushd $TMP_DIR > /dev/null
24250

243-
# Compile the versions of OpenSSL.
244-
compile_openssl_all
245-
246-
# Compile the versions of GnuTLS.
247-
compile_gnutls_all
248-
24951
# Now build the docker image!
25052
echo -e "${YELLOWB}Creating docker image...$IMAGE_NAME:$IMAGE_VERSION ${CLR}"
25153
docker build --tag $IMAGE_NAME:$IMAGE_VERSION .
@@ -276,6 +78,8 @@ function run_tests {
27678
run_test_16 "0"
27779
run_test_17 "0"
27880
run_test_18 "0"
81+
run_test_19 "0"
82+
#run_test_20 "0" # Unique GnuTLS algorithms that sslscan does not currently detect. Disabled until they are implemented.
27983
}
28084

28185

@@ -327,17 +131,15 @@ function run_test_8 {
327131
}
328132

329133

330-
# Runs nginx with client certificate checking (signed by the CA in docker_test/ca_cert.pem). sslscan will connect and make an HTTP request (--http). The HTTP response code should be 200 to signify that the certificate was accepted. Otherwise, nginx returns HTTP code 400 if no client certificates were presented.
134+
# OpenSSL v3.5.0, TLSv1.3 only, with all supported groups.
331135
function run_test_9 {
332-
#run_test $1 '9' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --certs=docker_test/cert_3072.crt --pk=docker_test/key_3072.pem --http"
333-
echo "Test #9 skipped."
136+
run_test $1 '9' "/openssl_v3.5.0/openssl s_server -accept 443 -key /etc/ssl/key_3072.pem -cert /etc/ssl/cert_3072.crt -tls1_3 -groups secp256r1:secp384r1:secp521r1:x25519:x448:brainpoolP256r1tls13:brainpoolP384r1tls13:brainpoolP512r1tls13:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192:MLKEM512:MLKEM768:MLKEM1024:SecP256r1MLKEM768:X25519MLKEM768:SecP384r1MLKEM1024" ""
334137
}
335138

336139

337-
# Runs nginx with client certificate checking, just as above. Except this time, we connect with no certificate. The HTTP response code should be "400 Bad Request".
140+
# GnuTLS v3.8.9, TLSv1.3 only, with all supported groups.
338141
function run_test_10 {
339-
#run_test $1 '10' "/usr/sbin/nginx -c /etc/nginx/nginx_test9.conf" "--no-fallback --no-renegotiation --no-compression --no-heartbleed --http"
340-
echo "Test #10 skipped."
142+
run_test $1 '10' "/gnutls-3.8.9/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem --priority=NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:-VERS-TLS1.0:+GROUP-SECP192R1:+GROUP-SECP224R1:+GROUP-SECP256R1:+GROUP-SECP384R1:+GROUP-SECP521R1:+GROUP-X25519:+GROUP-GC256B:+GROUP-GC512A:+GROUP-X448:+GROUP-FFDHE2048:+GROUP-FFDHE3072:+GROUP-FFDHE4096:+GROUP-FFDHE6144:+GROUP-FFDHE8192" ""
341143
}
342144

343145

@@ -353,7 +155,7 @@ function run_test_12 {
353155
}
354156

355157

356-
# Default GnuTLS.
158+
# GnuTLS 3.6.11.1, default options.
357159
function run_test_13 {
358160
run_test $1 '13' "/gnutls-3.6.11.1/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_3072.crt --x509keyfile=/etc/ssl/key_3072.pem" ""
359161
}
@@ -389,9 +191,19 @@ function run_test_18 {
389191
}
390192

391193

392-
# Run a test. Set the first argument to '1' to enable test debugging.
393-
# Second argument is the test number to run. Third argument is the executable and
394-
# its args to be run inside the container..
194+
# Mbed TLS, default settings.
195+
function run_test_19 {
196+
run_test $1 '19' "/mbedtls_v3.6.3.1/ssl_server2 server_port=443 crt_file=/etc/ssl/cert_3072.crt key_file=/etc/ssl/key_3072.pem" ""
197+
}
198+
199+
200+
# Many unique algorithms only present in GnuTLS.
201+
function run_test_20 {
202+
run_test $1 '20' "/gnutls-3.8.9/gnutls-serv -p 443 --x509certfile=/etc/ssl/cert_ecdsa_prime256v1.crt --x509keyfile=/etc/ssl/key_ecdsa_prime256v1.pem --priority=NORMAL:+GOST28147-TC26Z-CFB:+GOST28147-CPA-CFB:+GOST28147-CPB-CFB:+GOST28147-CPC-CFB:+GOST28147-CPD-CFB:+AES-128-XTS:+AES-256-XTS:+AES-128-SIV:+AES-256-SIV:+AES-128-SIV-GCM:+AES-256-SIV-GCM:+GOST28147-TC26Z-CNT:+MAGMA-CTR-ACPKM:+KUZNYECHIK-CTR-ACPKM:+GOSTR341194:+STREEBOG-256:+STREEBOG-512:+VKO-GOST-12:+RSA-EXPORT:+GROUP-GC256B:+GROUP-GC512A:+SIGN-ECDSA-SHA3-224:+SIGN-ECDSA-SHA3-256:+SIGN-ECDSA-SHA3-384:+SIGN-ECDSA-SHA3-512:+SIGN-RSA-SHA3-224:+SIGN-RSA-SHA3-256:+SIGN-RSA-SHA3-384:+SIGN-RSA-SHA3-512:+SIGN-DSA-SHA3-224:+SIGN-DSA-SHA3-256:+SIGN-DSA-SHA3-384:+SIGN-DSA-SHA3-512:+SIGN-RSA-RAW:+SIGN-GOSTR341012-512:+SIGN-GOSTR341012-256:+SIGN-GOSTR341001:+SIGN-DSA-SHA384:+SIGN-DSA-SHA512" ""
203+
}
204+
205+
206+
# Run a test. Set the first argument to '1' to enable test debugging. Second argument is the test number to run. Third argument is the executable and its args to be run inside the container.
395207
function run_test {
396208
debug=$1
397209
test_number=$2
@@ -417,9 +229,7 @@ function run_test {
417229
# Wait 250ms to ensure that the services in the container are fully initialized.
418230
sleep 0.25
419231

420-
# Run sslscan and cut out the first two lines. Those contain the version number
421-
# and local version of OpenSSL, which can change over time (and when they do, this
422-
# would break the test if they were left in).
232+
# Run sslscan and cut out the first two lines. Those contain the version number and local version of OpenSSL, which can change over time (and when they do, this would break the test if they were left in).
423233
./sslscan $sslscan_additional_args 127.0.0.1:4443 | tail -n +3 > $test_result_stdout
424234
if [[ $? != 0 ]]; then
425235
echo -e "${REDB}Failed to run sslscan! (exit code: $?)${CLR}"
@@ -454,8 +264,7 @@ function run_test {
454264
}
455265

456266

457-
# Instead of spinning up a docker instance, this will run a test using a host on the
458-
# public Internet.
267+
# Instead of spinning up a docker instance, this will run a test using a host on the public Internet.
459268
function run_test_internet {
460269
test_number=$1
461270
command=$2

docker_test/Dockerfile

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
1-
FROM ubuntu:22.04
1+
# This is the Dockerfile to build the test image (which contains target servers to check sslscan's output against).
22

3-
# Copy OpenSSL's 'openssl' tools.
4-
COPY openssl_prog_v1.0.0 /openssl_v1.0.0/openssl
5-
COPY openssl_prog_v1.0.2 /openssl_v1.0.2/openssl
6-
COPY openssl_prog_v1.1.1 /openssl_v1.1.1/openssl
3+
FROM ubuntu:24.04 AS builder
74

8-
# Copy GnuTLS client & server tools, along with their required libraries.
9-
COPY gnutls-cli-v3.6.11.1 /gnutls-3.6.11.1/gnutls-cli
10-
COPY gnutls-serv-v3.6.11.1 /gnutls-3.6.11.1/gnutls-serv
11-
COPY libhogweed.so.5 /usr/lib/
12-
COPY libnettle.so.7 /usr/lib/
13-
COPY libgnutls.so.30 /usr/lib/x86_64-linux-gnu/
5+
COPY build_test_apps.sh /build/build_test_apps.sh
6+
7+
# Update base image and install prerequisites for building.
8+
RUN apt update; apt install -y build-essential zlib1g zlib1g-dev nettle-dev git wget m4 pkg-config python3 python3-pip python3-virtualenv python3-venv
9+
10+
# Build all applications.
11+
RUN /bin/bash /build/build_test_apps.sh
12+
13+
14+
# Starting from a fresh image, copy over the built applications from the prior stage.
15+
FROM ubuntu:24.04
16+
17+
COPY --from=builder /build/libhogweed.so.5 /usr/lib/libhogweed.so.5
18+
COPY --from=builder /build/libnettle.so.7 /usr/lib/libnettle.so.7
19+
20+
COPY --from=builder /build/gnutls-cli-v3.6.11.1 /gnutls-3.6.11.1/gnutls-cli
21+
COPY --from=builder /build/gnutls-serv-v3.6.11.1 /gnutls-3.6.11.1/gnutls-serv
22+
23+
COPY --from=builder /build/gnutls-cli-v3.8.9 /gnutls-3.8.9/gnutls-cli
24+
COPY --from=builder /build/gnutls-serv-v3.8.9 /gnutls-3.8.9/gnutls-serv
25+
26+
COPY --from=builder /build/openssl_prog_v1.0.0 /openssl_v1.0.0/openssl
27+
COPY --from=builder /build/openssl_prog_v1.0.2 /openssl_v1.0.2/openssl
28+
COPY --from=builder /build/openssl_prog_v1.1.1 /openssl_v1.1.1/openssl
29+
COPY --from=builder /build/openssl_prog_v3.5.0 /openssl_v3.5.0/openssl
30+
31+
COPY --from=builder /build/mbedtls_ssl_server2_v3.6.3.1 /mbedtls_v3.6.3.1/ssl_server2
1432

1533
# Copy certificates, keys, and DH parameters.
1634
COPY *.pem /etc/ssl/
1735
COPY *.crt /etc/ssl/
1836

19-
# Copy nginx site configurations & modules.
20-
COPY nginx_site_client_cert_required /etc/nginx/sites-available/
21-
COPY nginx_test9.conf /etc/nginx/
22-
23-
# Install nginx for some tests.
24-
# Install strace for potential debugging, and rsyslog to enable system log gathering.
25-
RUN apt update 2> /dev/null
26-
RUN apt install -y nginx strace rsyslog ca-certificates 2> /dev/null
27-
RUN apt clean 2> /dev/null
28-
29-
RUN update-ca-certificates
37+
# This config file seems to tell GnuTLS to not allow TLSv1.0 or TLSv1.1, which we need for testing.
38+
RUN rm -f /etc/gnutls/config
3039

3140
EXPOSE 443

0 commit comments

Comments
 (0)