From 61ece74ca43ce71cedffd46beac0906651bf8223 Mon Sep 17 00:00:00 2001 From: lijunlong Date: Sat, 21 Jun 2025 18:56:09 +0800 Subject: [PATCH] tests: update openssl to 3.5.0. --- .travis.yml | 48 ++-- t/cert/chain/chain.der | Bin 2635 -> 4303 bytes t/cert/chain/chain.pem | 476 ++++++++++++++++++++------------ t/cert/chain/gen-chain-der.sh | 5 + t/cert/chain/gen-chain.sh | 7 + t/cert/chain/gen-root-ca.sh | 41 +++ t/cert/chain/gen-signing-ca1.sh | 55 ++++ t/cert/chain/gen-signing-ca2.sh | 55 ++++ t/cert/chain/gen-test.com.sh | 57 ++++ t/cert/chain/root-ca.crt | 45 +-- t/cert/chain/test-com.key.der | Bin 633 -> 2348 bytes t/cert/chain/test-com.key.pem | 64 ++++- t/cert/gen-passphrase.sh | 2 + t/cert/test_passphrase.crt | 48 +++- t/cert/test_passphrase.key | 72 +++-- t/ssl.t | 2 +- t/stream/ssl.t | 3 +- 17 files changed, 715 insertions(+), 265 deletions(-) create mode 100755 t/cert/chain/gen-chain-der.sh create mode 100755 t/cert/chain/gen-chain.sh create mode 100755 t/cert/chain/gen-root-ca.sh create mode 100755 t/cert/chain/gen-signing-ca1.sh create mode 100755 t/cert/chain/gen-signing-ca2.sh create mode 100755 t/cert/chain/gen-test.com.sh create mode 100644 t/cert/gen-passphrase.sh diff --git a/.travis.yml b/.travis.yml index 8a66ff2cb..78c85296a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,10 @@ addons: - axel - luarocks - daemonize + - lsb-release + - wget + - gnupg + - ca-certificates cache: directories: @@ -33,15 +37,13 @@ env: - LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1 - LUA_INCLUDE_DIR=$LUAJIT_INC - LUA_CMODULE_DIR=/lib - - PCRE_VER=8.45 - - PCRE2_VER=10.37 - - PCRE_PREFIX=/opt/pcre - - PCRE2_PREFIX=/opt/pcre2 - - PCRE_LIB=$PCRE_PREFIX/lib + - PCRE2_VER=10.45 + #- PCRE2_PREFIX=/opt/pcre2 + - PCRE2_PREFIX=/usr/local/openresty/pcre2 - PCRE2_LIB=$PCRE2_PREFIX/lib - - PCRE_INC=$PCRE_PREFIX/include - PCRE2_INC=$PCRE2_PREFIX/include - - OPENSSL_PREFIX=/opt/ssl + #- OPENSSL_PREFIX=/opt/ssl3 + - OPENSSL_PREFIX=/usr/local/openresty/openssl3 - OPENSSL_LIB=$OPENSSL_PREFIX/lib - OPENSSL_INC=$OPENSSL_PREFIX/include - LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH @@ -49,8 +51,7 @@ env: - TEST_NGINX_RANDOMIZE=1 - LUACHECK_VER=0.21.1 matrix: - - NGINX_VERSION=1.27.1 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f USE_PCRE2=Y - - NGINX_VERSION=1.25.3 OPENSSL_VER=1.1.1w OPENSSL_PATCH_VER=1.1.1f + - NGINX_VERSION=1.27.1 OPENSSL_VER=3.5.0 OPENSSL_PATCH_VER=3.5.0 services: - memcache @@ -61,12 +62,15 @@ before_install: - '! grep -n -P ''(?<=.{80}).+'' --color `find . -name ''*.lua''` || (echo "ERROR: Found Lua source lines exceeding 80 columns." > /dev/stderr; exit 1)' - '! grep -n -P ''\t+'' --color `find . -name ''*.lua''` || (echo "ERROR: Cannot use tabs." > /dev/stderr; exit 1)' - cpanm --sudo --notest Test::Nginx IPC::Run > build.log 2>&1 || (cat build.log && exit 1) + - wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add - + - echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list + - sudo apt-get update + - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openresty-pcre2 openresty-openssl3 openresty-pcre2-dev openresty-openssl3-dev install: - if [ ! -d download-cache ]; then mkdir download-cache; fi - - if [ ! -f download-cache/openssl-$OPENSSL_VER.tar.gz ]; then wget -P download-cache https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz || wget -P download-cache https://www.openssl.org/source/old/${OPENSSL_VER//[a-z]/}/openssl-$OPENSSL_VER.tar.gz; fi - - if [ "$USE_PCRE2" != "Y" ] && [ ! -f download-cache/pcre-$PCRE_VER.tar.gz ]; then wget -P download-cache http://ftp.cs.stanford.edu/pub/exim/pcre/pcre-$PCRE_VER.tar.gz; fi - - if [ "$USE_PCRE2" = "Y" ] && [ ! -f download-cache/pcre2-$PCRE2_VER.tar.gz ]; then wget -P download-cache https://downloads.sourceforge.net/project/pcre/pcre2/${PCRE2_VER}/pcre2-${PCRE2_VER}.tar.gz; fi + #- if [ ! -f download-cache/openssl-$OPENSSL_VER.tar.gz ]; then wget -P download-cache https://www.openssl.org/source/openssl-$OPENSSL_VER.tar.gz || wget -P download-cache https://www.openssl.org/source/old/${OPENSSL_VER//[a-z]/}/openssl-$OPENSSL_VER.tar.gz; fi + #- if [ ! -f download-cache/pcre2-$PCRE2_VER.tar.gz ]; then wget -P download-cache https://downloads.sourceforge.net/project/pcre/pcre2/${PCRE2_VER}/pcre2-${PCRE2_VER}.tar.gz; fi - git clone https://github.com/openresty/openresty.git ../openresty - git clone https://github.com/openresty/openresty-devel-utils.git - git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module @@ -87,27 +91,15 @@ script: - sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1) - cd .. - cd lua-resty-lrucache && sudo make DESTDIR=$LUAJIT_PREFIX LUA_LIB_DIR=/share/lua/5.1 install && cd .. - - tar zxf download-cache/openssl-$OPENSSL_VER.tar.gz - - cd openssl-$OPENSSL_VER/ - - if [ -n "$OPENSSL_PATCH_VER" ]; then patch -p1 < ../../openresty/patches/openssl-$OPENSSL_PATCH_VER-sess_set_get_cb_yield.patch; fi - - ./config no-threads shared enable-ssl3 enable-ssl3-method -g --prefix=$OPENSSL_PREFIX -DPURIFY > build.log 2>&1 || (cat build.log && exit 1) - - make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1) - - sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1) - - cd ../mockeagain/ && make CC=$CC -j$JOBS && cd .. - - if [ "$USE_PCRE2" != "Y" ]; then tar zxf download-cache/pcre-$PCRE_VER.tar.gz; cd pcre-$PCRE_VER/; ./configure --prefix=$PCRE_PREFIX --enable-jit --enable-utf --enable-unicode-properties > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo PATH=$PATH make install > build.log 2>&1 || (cat build.log && exit 1); cd ..; fi - - if [ "$USE_PCRE2" = "Y" ]; then tar zxf download-cache/pcre2-$PCRE2_VER.tar.gz; cd pcre2-$PCRE2_VER/; ./configure --prefix=$PCRE2_PREFIX --enable-jit --enable-utf > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo PATH=$PATH make install > build.log 2>&1 || (cat build.log && exit 1); cd ..; fi + #- tar zxf download-cache/openssl-$OPENSSL_VER.tar.gz; cd openssl-$OPENSSL_VER/; if [ -n "$OPENSSL_PATCH_VER" ]; then patch -p1 < ../../openresty/patches/openssl-$OPENSSL_PATCH_VER-sess_set_get_cb_yield.patch; fi; ./config no-threads shared enable-ssl3 enable-ssl3-method -g --prefix=$OPENSSL_PREFIX -DPURIFY > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1); cd .. + - cd mockeagain/ && make CC=$CC -j$JOBS && cd .. + #- tar zxf download-cache/pcre2-$PCRE2_VER.tar.gz; cd pcre2-$PCRE2_VER/; ./configure --prefix=$PCRE2_PREFIX --enable-jit --enable-utf > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo PATH=$PATH make install > build.log 2>&1 || (cat build.log && exit 1); cd ..; - export PATH=$PWD/work/nginx/sbin:$PWD/openresty-devel-utils:$PATH - export LD_PRELOAD=$PWD/mockeagain/mockeagain.so - export LD_LIBRARY_PATH=$PWD/mockeagain:$LD_LIBRARY_PATH - export TEST_NGINX_RESOLVER=8.8.4.4 - export NGX_BUILD_CC=$CC - - export add_http3_module=--with-http_v3_module - - export disable_pcre2=--without-pcre2 - - answer=`util/ver-ge "$NGINX_VERSION" 1.25.1` - - if [ "$OPENSSL_VER" = "1.1.0l" ] || [ "$answer" = "N" ]; then add_http3_module=""; fi - - if [ "$answer" = "N" ] || [ "$USE_PCRE2" = "Y" ]; then disable_pcre2=""; fi - - if [ "$USE_PCRE2" = "Y" ]; then PCRE_INC=$PCRE2_INC; PCRE_LIB=$PCRE2_LIB; fi - - ngx-build $NGINX_VERSION $disable_pcre2 $add_http3_module --with-http_v2_module --with-http_realip_module --with-http_ssl_module --with-pcre-jit --with-cc-opt="-I$OPENSSL_INC -I$PCRE_INC" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB -L$PCRE_LIB -Wl,-rpath,$PCRE_LIB" --add-module=../ndk-nginx-module --add-module=../echo-nginx-module --add-module=../set-misc-nginx-module --add-module=../headers-more-nginx-module --add-module=../lua-nginx-module --with-debug --with-stream_ssl_module --with-stream --with-ipv6 --add-module=../stream-lua-nginx-module > build.log 2>&1 || (cat build.log && exit 1) + - ngx-build $NGINX_VERSION --with-http_v3_module --with-http_v2_module --with-http_realip_module --with-http_ssl_module --with-pcre-jit --with-cc-opt="-I$OPENSSL_INC -I$PCRE2_INC" --with-ld-opt="-L$OPENSSL_LIB -Wl,-rpath,$OPENSSL_LIB -L$PCRE2_LIB -Wl,-rpath,$PCRE2_LIB" --add-module=../ndk-nginx-module --add-module=../echo-nginx-module --add-module=../set-misc-nginx-module --add-module=../headers-more-nginx-module --add-module=../lua-nginx-module --with-debug --with-stream_ssl_module --with-stream --with-ipv6 --add-module=../stream-lua-nginx-module > build.log 2>&1 || (cat build.log && exit 1) - nginx -V - ldd `which nginx`|grep -E 'luajit|ssl|pcre' - prove -I. -Itest-nginx/lib -j$JOBS -r t diff --git a/t/cert/chain/chain.der b/t/cert/chain/chain.der index 3e7b4ba1029e2976ee5318d8031b6b6bc3bcfc3d..dbaa9533171d057adc6747e80e30a1c2d50f0ffd 100644 GIT binary patch delta 3716 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 chain.der + diff --git a/t/cert/chain/gen-chain.sh b/t/cert/chain/gen-chain.sh new file mode 100755 index 000000000..d49bf0295 --- /dev/null +++ b/t/cert/chain/gen-chain.sh @@ -0,0 +1,7 @@ +openssl x509 -in test.com.crt -text -noout > chain.pem +cat test.com.crt >> chain.pem +openssl x509 -in signing-ca-1.crt -text -noout >> chain.pem +cat signing-ca-1.crt >> chain.pem +openssl x509 -in signing-ca-2.crt -text -noout >> chain.pem +cat signing-ca-2.crt >> chain.pem + diff --git a/t/cert/chain/gen-root-ca.sh b/t/cert/chain/gen-root-ca.sh new file mode 100755 index 000000000..77d539fd0 --- /dev/null +++ b/t/cert/chain/gen-root-ca.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +CERT_NAME="root-ca" +DAYS_VALID=36500 +KEY_SIZE=4096 +COUNTRY="US" +STATE="California" +LOCALITY="San Francisco" +ORGANIZATION="OpenResty" +COMMON_NAME="Root CA" + +openssl genrsa -out ${CERT_NAME}.key ${KEY_SIZE} + +cat > ${CERT_NAME}.cnf < ${CERT_NAME}.cnf < ${CERT_NAME}.cnf < ${CERT_NAME}.cnf <D2v*2Hj`)6KD&Md$5;X+DM7AJD(v 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 Sp^5Vvr8T~vUY>NAHALa&AE06Y literal 633 zcmV-<0*3uCf&z5{0RS)!1_>&LNQUpUoe6KTLJ+90)c@5nnX908e98t zrNl(N)Jlt80eUjYm!QHFFzqYsY>Txg2K8s?Zl}0m6t@nTw;yLSK$qC#Mpv~2z@J0w zauGY?MF0XFCQfd+f8zAMqKwbB)_?J_3US4$tSWrW!){xH>2AOHn5vWxwl%RKA|`ws zDkc)D@j!f+v^$;0s{d60Rn-5Bk*XFRAIq>NZ=&1q}7QEE#dAP5d0px-FqXH zeC0n{%s@Bj>VBYc-G!JO^X!=VQ@#v^MoIvl4$=$Ux!0caY5mrxfOn-K%E6zvK^?`i9md5xBe3TK?VHd1I&iK0#0zm-D zmW!WvCh~m6(qlyI%7H&#CmO9UQpYd2Wq*EUozX^&`71RmA&O=%17cNdmDD-Ix;WLV zd>Ic`V{z95&6N)VK>)+&(7-I^Wts>d~s