Skip to content
Draft
89 changes: 57 additions & 32 deletions .github/workflows/nginx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ concurrency:
cancel-in-progress: true
# END OF COMMON SECTION

# clang has better sanitizer support
env:
CC: clang

jobs:
build_wolfssl:
name: Build wolfSSL
Expand All @@ -31,7 +35,8 @@ jobs:
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: --enable-nginx ${{ env.wolf_debug_flags }}
configure: >-
--enable-nginx --enable-curve25519 --enable-ed25519 ${{ env.wolf_debug_flags }}
install: true

- name: tar build-dir
Expand All @@ -50,6 +55,41 @@ jobs:
matrix:
include:
# in general we want to pass all tests that match *ssl*
- ref: 1.28.1
test-ref: 0fccfcef1278263416043e0bbb3e0116b84026e4
# Following tests pass with sanitizer on
sanitize-ok: >-
h2_ssl_proxy_cache.t h2_ssl.t h2_ssl_variables.t
h2_ssl_verify_client.t mail_imap_ssl.t mail_ssl_session_reuse.t
mail_ssl.t proxy_ssl_certificate_cache.t
proxy_ssl_certificate_empty.t proxy_ssl_certificate.t
proxy_ssl_certificate_vars.t proxy_ssl_name.t ssl_cache_reload.t
ssl_certificate_aux.t ssl_certificate_cache.t
ssl_certificate_chain.t ssl_certificates.t ssl_certificate.t
ssl_client_escaped_cert.t ssl_crl.t ssl_curve.t ssl_ocsp.t
ssl_password_file.t ssl_proxy_upgrade.t ssl_reject_handshake.t
ssl_session_reuse.t ssl_session_ticket_key.t ssl_sni_protocols.t
ssl_sni_reneg.t ssl_sni_sessions.t ssl_sni.t ssl_stapling.t ssl.t
ssl_verify_client.t ssl_verify_client_trusted.t ssl_verify_depth.t
stream_proxy_ssl_certificate_cache.t stream_proxy_ssl_certificate.t
stream_proxy_ssl_certificate_vars.t
stream_proxy_ssl_name_complex.t stream_proxy_ssl_name.t
stream_ssl_alpn.t stream_ssl_certificate_cache.t
stream_ssl_certificate.t stream_ssl_ocsp.t stream_ssl_preread_alpn.t
stream_ssl_preread_protocol.t stream_ssl_preread.t
stream_ssl_reject_handshake.t stream_ssl_session_reuse.t
stream_ssl_sni_protocols.t stream_ssl_stapling.t stream_ssl.t
stream_ssl_variables.t stream_ssl_verify_client.t
stream_upstream_zone_ssl.t upstream_zone_ssl.t
uwsgi_ssl_certificate.t uwsgi_ssl_certificate_vars.t
# Following tests do not pass with sanitizer on (with OpenSSL too)
sanitize-not-ok: >-
grpc_ssl.t h2_proxy_request_buffering_ssl.t h2_proxy_ssl.t
proxy_request_buffering_ssl.t proxy_ssl_conf_command.t
proxy_ssl_keepalive.t proxy_ssl.t proxy_ssl_verify.t ssl_cache.t
stream_proxy_protocol_ssl.t stream_proxy_ssl_conf_command.t
stream_proxy_ssl.t stream_proxy_ssl_verify.t

- ref: 1.25.0
test-ref: 5b2894ea1afd01a26c589ce11f310df118e42592
# Following tests pass with sanitizer on
Expand Down Expand Up @@ -120,35 +160,26 @@ jobs:
- name: untar build-dir
run: tar -xf build-dir.tgz

- name: Install dependencies
run: |
sudo cpan -iT Proc::Find
- name: Openssl version
run: openssl version -a

# Locking in the version of SSLeay used with testing
- name: Download and install Net::SSLeay 1.94 manually
run: |
curl -LO https://www.cpan.org/modules/by-module/Net/CHRISN/Net-SSLeay-1.94.tar.gz
tar -xzf Net-SSLeay-1.94.tar.gz
cd Net-SSLeay-1.94
perl Makefile.PL
make
sudo make install
- name: Setup Perl environment
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.38.2'

# SSL version 2.091 changes '' return to undef causing test case to fail.
# Locking in the test version to use as 2.090
- name: Download and install IO::Socket::SSL 2.090 manually
- name: Install dependencies
run: |
curl -LO https://www.cpan.org/modules/by-module/IO/IO-Socket-SSL-2.090.tar.gz
tar -xzf IO-Socket-SSL-2.090.tar.gz
cd IO-Socket-SSL-2.090
perl Makefile.PL
make
sudo make install
cpanm --notest Proc::Find Net::SSLeay@1.94 IO::Socket::SSL@2.090

- name: Checkout wolfssl-nginx
uses: actions/checkout@v4
with:
repository: wolfssl/wolfssl-nginx
# TODO fix this
repository: julek-wolfssl/wolfssl-nginx
ref: 1.28.0
path: wolfssl-nginx

- name: Checkout nginx
Expand Down Expand Up @@ -211,37 +242,31 @@ jobs:
run: |
echo "nginx_c_flags=-O0" >> $GITHUB_ENV

- name: workaround high-entropy ASLR
# not needed after either an update to llvm or runner is done
run: sudo sysctl vm.mmap_rnd_bits=28

- name: Build nginx with sanitizer
working-directory: nginx
run: |
./auto/configure --with-wolfssl=$GITHUB_WORKSPACE/build-dir --with-http_ssl_module \
--with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \
--with-http_v2_module --with-mail --with-mail_ssl_module \
--with-cc-opt='-fsanitize=address -DNGX_DEBUG_PALLOC=1 -g3 ${{ env.nginx_c_flags }}' \
--with-cc-opt='-fsanitize=address -DNGX_DEBUG_PALLOC=1 -g3 \
${{ env.nginx_c_flags }}' \
--with-ld-opt='-fsanitize=address ${{ env.nginx_c_flags }}'
make -j

- name: Confirm nginx built with wolfSSL
working-directory: nginx
run: ldd objs/nginx | grep wolfssl

- if: ${{ runner.debug }}
name: Run nginx-tests with sanitizer (debug)
- name: Create LSAN suppression file
working-directory: nginx-tests
run: |
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_VERBOSE=y TEST_NGINX_CATLOG=y \
TEST_NGINX_BINARY=../nginx/objs/nginx prove -v ${{ matrix.sanitize-ok }}
echo "leak:ngx_worker_process_init" > lsan.supp

- if: ${{ !runner.debug }}
name: Run nginx-tests with sanitizer
working-directory: nginx-tests
run: |
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib \
LSAN_OPTIONS=suppressions=$GITHUB_WORKSPACE/nginx-tests/lsan.supp \
TMPDIR=$GITHUB_WORKSPACE TEST_NGINX_BINARY=../nginx/objs/nginx \
prove ${{ matrix.sanitize-ok }}

3 changes: 2 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2652,7 +2652,8 @@ if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || \
test "$ENABLED_OPENRESTY" = "yes" || test "$ENABLED_RSYSLOG" = "yes" || \
test "$ENABLED_KRB" = "yes" || test "$ENABLED_CHRONY" = "yes" || \
test "$ENABLED_FFMPEG" = "yes" || test "$ENABLED_STRONGSWAN" = "yes" || \
test "$ENABLED_OPENLDAP" = "yes" || test "x$ENABLED_MOSQUITTO" = "xyes" || test "$ENABLED_HITCH" = "yes"
test "$ENABLED_OPENLDAP" = "yes" || test "x$ENABLED_MOSQUITTO" = "xyes" || \
test "$ENABLED_HITCH" = "yes" || test "$ENABLED_NGINX" = "yes"
then
ENABLED_OPENSSLALL="yes"
fi
Expand Down
20 changes: 20 additions & 0 deletions src/crl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,26 @@ WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl)
return ret;
}

int wolfSSL_X509_CRL_up_ref(WOLFSSL_X509_CRL* crl)
{
int ret;

if (crl == NULL)
return WOLFSSL_FAILURE;

wolfSSL_RefInc(&crl->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret != 0) {
WOLFSSL_MSG("Failed to lock x509 mutex");
return WOLFSSL_FAILURE;
}
#else
(void)ret;
#endif

return WOLFSSL_SUCCESS;
}

/* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */
int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
{
Expand Down
95 changes: 95 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38893,6 +38893,41 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
XMEMCPY(it->sessionCtx, ssl->sessionCtx, ID_LEN);
#endif

#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
/* Store peer certificate in ticket for session resumption.
* Try ssl->peerCert first, then ssl->session->chain as fallback. */
{
const byte* certDer = NULL;
word32 certDerSz = 0;

if (ssl->peerCert.derCert != NULL &&
ssl->peerCert.derCert->length > 0) {
/* Use current peer certificate */
certDer = ssl->peerCert.derCert->buffer;
certDerSz = ssl->peerCert.derCert->length;
}
#ifdef SESSION_CERTS
else if (ssl->session->chain.count > 0) {
/* Use peer certificate from session chain */
certDer = ssl->session->chain.certs[0].buffer;
certDerSz = ssl->session->chain.certs[0].length;
}
#endif

if (certDer != NULL && certDerSz > 0 &&
certDerSz <= MAX_TICKET_PEER_CERT_SZ) {
c16toa((word16)certDerSz, it->peerCertLen);
XMEMCPY(it->peerCert, certDer, certDerSz);
}
else {
if (certDerSz > MAX_TICKET_PEER_CERT_SZ)
WOLFSSL_MSG("Peer cert too large for ticket, skipping");
c16toa(0, it->peerCertLen);
}
}
#endif

#ifdef WOLFSSL_TICKET_HAVE_ID
{
const byte* id = NULL;
Expand Down Expand Up @@ -39272,6 +39307,49 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
ato16(it->namedGroup, &ssl->session->namedGroup);
#endif
}

#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
/* Restore peer certificate from ticket to session chain and peerCert */
{
word16 peerCertLen = 0;
ato16(it->peerCertLen, &peerCertLen);

if (peerCertLen > 0 && peerCertLen <= MAX_TICKET_PEER_CERT_SZ) {
#ifdef SESSION_CERTS
/* Clear existing chain and add the peer certificate */
ssl->session->chain.count = 0;
AddSessionCertToChain(&ssl->session->chain,
it->peerCert, peerCertLen);
#endif
/* Also decode into ssl->peerCert for direct access */
{
int ret;
DecodedCert* dCert;

dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
DYNAMIC_TYPE_DCERT);
if (dCert != NULL) {
InitDecodedCert(dCert, it->peerCert, peerCertLen, ssl->heap);
ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL);
if (ret == 0) {
FreeX509(&ssl->peerCert);
InitX509(&ssl->peerCert, 0, ssl->heap);
ret = CopyDecodedToX509(&ssl->peerCert, dCert);
if (ret != 0) {
/* Failed to copy - clear peerCert */
FreeX509(&ssl->peerCert);
InitX509(&ssl->peerCert, 0, ssl->heap);
}
}
FreeDecodedCert(dCert);
XFREE(dCert, ssl->heap, DYNAMIC_TYPE_DCERT);
}
}
}
}
#endif

ssl->version.minor = it->pv.minor;
}

Expand Down Expand Up @@ -39316,6 +39394,23 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#ifdef OPENSSL_EXTRA
it->sessionCtxSz = sess->sessionCtxSz;
XMEMCPY(it->sessionCtx, sess->sessionCtx, sess->sessionCtxSz);
#endif
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
defined(SESSION_CERTS) && !defined(NO_CERT_IN_TICKET)
/* Store peer certificate from session chain */
if (sess->chain.count > 0) {
word32 certLen = sess->chain.certs[0].length;
if (certLen <= MAX_TICKET_PEER_CERT_SZ) {
c16toa((word16)certLen, it->peerCertLen);
XMEMCPY(it->peerCert, sess->chain.certs[0].buffer, certLen);
}
else {
c16toa(0, it->peerCertLen);
}
}
else {
c16toa(0, it->peerCertLen);
}
#endif
}

Expand Down
24 changes: 22 additions & 2 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -12127,7 +12127,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl)

if (ssl->buffers.weOwnKey) {
WOLFSSL_MSG("Unloading key");
ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
if (ssl->buffers.key != NULL && ssl->buffers.key->buffer != NULL)
ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
Expand All @@ -12138,7 +12139,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->buffers.weOwnAltKey) {
WOLFSSL_MSG("Unloading alt key");
ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
if (ssl->buffers.altKey != NULL && ssl->buffers.altKey->buffer != NULL)
ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
Expand Down Expand Up @@ -14989,6 +14991,22 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)

if (ssl->buffers.weOwnCert) {
if (ssl->ourCert == NULL) {
/* Check if ctx has ourCert set - if so, use it instead of creating
* a new X509. This maintains pointer compatibility with
* applications (like nginx OCSP stapling) that use the X509 pointer
* from SSL_CTX_use_certificate as a lookup key. */
if (ssl->ctx != NULL && ssl->ctx->ourCert != NULL) {
/* Compare cert buffers to make sure they are the same */
if (ssl->buffers.certificate == NULL ||
ssl->buffers.certificate->buffer == NULL ||
(ssl->buffers.certificate->length ==
ssl->ctx->certificate->length &&
XMEMCMP(ssl->buffers.certificate->buffer,
ssl->ctx->certificate->buffer,
ssl->buffers.certificate->length) == 0)) {
return ssl->ctx->ourCert;
}
}
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
return NULL;
Expand Down Expand Up @@ -21032,6 +21050,8 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
ssl->buffers.weOwnKey = 1;
}
else {
if (ssl->buffers.key != NULL && ssl->buffers.weOwnKey)
FreeDer(&ssl->buffers.key);
ssl->buffers.key = ctx->privateKey;
}
#else
Expand Down
5 changes: 5 additions & 0 deletions src/ssl_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ static int wolfssl_file_len(XFILE fp, long* fileSz)
/* Get file offset at end of file. */
curr = (long)XFTELL(fp);
if (curr < 0) {
if (errno == ESPIPE) {
WOLFSSL_ERROR_MSG("wolfssl_file_len: file is a pipe");
*fileSz = 0;
return 0;
}
ret = WOLFSSL_BAD_FILE;
}
}
Expand Down
Loading
Loading