Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 55 additions & 34 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,30 +160,17 @@ 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

# 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: Setup Perl environment
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.38.2'

- 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
Expand Down Expand Up @@ -211,37 +238,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 @@ -2641,7 +2641,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
16 changes: 16 additions & 0 deletions src/crl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,22 @@ WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl)
return ret;
}

int wolfSSL_X509_CRL_up_ref(WOLFSSL_X509_CRL* crl)
{
if (crl) {
int ret;
wolfSSL_RefInc(&crl->ref, &ret);
if (ret != 0) {
WOLFSSL_MSG("Failed to lock x509 mutex");
return WOLFSSL_FAILURE;
}

return WOLFSSL_SUCCESS;
}

return WOLFSSL_FAILURE;
}

/* 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 @@ -38616,6 +38616,41 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
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 @@ -38995,6 +39030,49 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
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 @@ -39039,6 +39117,23 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#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
25 changes: 23 additions & 2 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -12058,7 +12058,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 @@ -12069,7 +12070,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 @@ -14919,6 +14921,23 @@ 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)) {
ssl->ourCert = ssl->ctx->ourCert;
return ssl->ctx->ourCert;
}
}
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
return NULL;
Expand Down Expand Up @@ -20953,6 +20972,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
15 changes: 13 additions & 2 deletions src/ssl_sk.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,17 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
break;
}
break;
case STACK_TYPE_X509_CRL:
if (src->data.crl == NULL) {
break;
}
dst->data.crl = wolfSSL_X509_CRL_dup(src->data.crl);
if (dst->data.crl == NULL) {
WOLFSSL_MSG("wolfSSL_X509_CRL_dup error");
err = 1;
break;
}
break;
case STACK_TYPE_X509_OBJ:
#if defined(OPENSSL_ALL)
if (src->data.x509_obj == NULL) {
Expand Down Expand Up @@ -429,7 +440,6 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)
case STACK_TYPE_BY_DIR_entry:
case STACK_TYPE_BY_DIR_hash:
case STACK_TYPE_DIST_POINT:
case STACK_TYPE_X509_CRL:
default:
WOLFSSL_MSG("Unsupported stack type");
err = 1;
Expand All @@ -441,7 +451,8 @@ static int wolfssl_sk_dup_data(WOLFSSL_STACK* dst, WOLFSSL_STACK* src)

/* Duplicate the stack of nodes.
*
* TODO: OpenSSL does a shallow copy but we have wolfSSL_shallow_sk_dup().
* OpenSSL does a shallow copy but we map to wolfSSL_shallow_sk_dup()
* when we want a shallow copy.
*
* Data is copied/duplicated - deep copy.
*
Expand Down
Loading
Loading