Skip to content

Commit 4dbbef9

Browse files
committed
JNI: always call wolfSSL_get1_session() inside native JNI getSession(), callers expect to always free returned pointer
1 parent 87b6c6a commit 4dbbef9

3 files changed

Lines changed: 78 additions & 38 deletions

File tree

.github/workflows/main.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,25 @@ jobs:
101101
jdk_version: ${{ matrix.jdk_version }}
102102
wolfssl_configure: ${{ matrix.wolfssl_configure }}
103103

104+
# -------------------- session cache variant sanity checks -----------------------
105+
# Only check one Linux and Mac JDK version as a sanity check.
106+
# Using Zulu, but this can be expanded if needed.
107+
linux-zulu-sesscache:
108+
strategy:
109+
matrix:
110+
os: [ 'ubuntu-latest', 'macos-latest' ]
111+
jdk_version: [ '11' ]
112+
wolfssl_configure: [
113+
'--enable-jni CFLAGS=-DNO_SESSION_CACHE_REF',
114+
]
115+
name: ${{ matrix.os }} (Zulu JDK ${{ matrix.jdk_version }}, ${{ matrix.wolfssl_configure}})
116+
uses: ./.github/workflows/linux-common.yml
117+
with:
118+
os: ${{ matrix.os }}
119+
jdk_distro: "zulu"
120+
jdk_version: ${{ matrix.jdk_version }}
121+
wolfssl_configure: ${{ matrix.wolfssl_configure }}
122+
104123
# ------------------ Facebook Infer static analysis -------------------
105124
# Run Facebook infer over PR code, only running on Linux with one
106125
# JDK/version for now.

native/com_wolfssl_WolfSSLSession.c

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,23 +1644,18 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
16441644
}
16451645
}
16461646
} while (err == SSL_ERROR_WANT_READ);
1647-
1648-
sess = wolfSSL_get_session(ssl);
1649-
hasTicket = wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)sess);
16501647
}
16511648

1652-
/* Only duplicate / save session if not TLS 1.3 (will be using normal
1653-
* session IDs), or is TLS 1.3 and we have a session ticket */
1654-
if (version != TLS1_3_VERSION || hasTicket == 1) {
1655-
1656-
/* wolfSSL checks ssl for NULL, returns pointer to new WOLFSSL_SESSION,
1657-
* Returns new duplicated WOLFSSL_SESSION. Needs to be freed with
1658-
* wolfSSL_SESSION_free() when finished with pointer. */
1659-
if (sess != NULL) {
1660-
/* Guarantee that we own the WOLFSSL_SESSION, make a copy */
1661-
dup = wolfSSL_SESSION_dup(sess);
1662-
}
1663-
}
1649+
/* Call wolfSSL_get1_session() to increase the ref count of the internal
1650+
* WOLFSSL_SESSION struct. This is needed in all build option cases,
1651+
* since Java callers of this function expect to explicitly free this
1652+
* pointer when finished with use. In some build cases, for example
1653+
* NO_CLIENT_CACHE or NO_SESSION_CACHE_REF, the poiner returned by
1654+
* wolfSSL_get_session() will be a pointer into the WOLFSSL struct, which
1655+
* will be freed with wolfSSL_free(). This can cause issues if the Java
1656+
* app expects to hold a valid session pointer for resumption and free
1657+
* later on. */
1658+
dup = wolfSSL_get1_session(ssl);
16641659

16651660
if (wc_UnLockMutex(jniSessLock) != 0) {
16661661
printf("Failed to unlock jniSessLock in get1Session()");

src/java/com/wolfssl/WolfSSLSession.java

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,15 +1358,25 @@ public int getError(int ret) throws IllegalStateException {
13581358
}
13591359

13601360
/**
1361-
* Sets the session to be used when the SSL object is used to create
1362-
* a SSL/TLS connection.
1363-
* For session resumption, before calling <code>shutdownSSL()</code>
1364-
* with your session object, an application should save the session ID
1365-
* from the object with a call to <code>getSession()</code>, which returns
1366-
* a pointer to the session. Later, the application should create a new
1367-
* SSL session object and assign the saved session with <code>
1368-
* setSession()</code>. At this point, the application may call <code>
1369-
* connect()</code> and wolfSSL will try to resume the session.
1361+
* Sets the session (native WOLFSSL_SESSION) to be used with this object
1362+
* for session resumption.
1363+
*
1364+
* The native WOLFSSL_SESSION pointed to contains all the necessary
1365+
* information required to perform a session resumption and reestablishment
1366+
* of the connection without a new handshake.
1367+
* <p>
1368+
* To do session resumption, before calling <code>shutdownSSL()</code>
1369+
* with your WolfSSLSession object, save the internal session state by
1370+
* calling <code>getSession()</code>, which returns a pointer to the
1371+
* native WOLFSSL_SESSION session structure. Later, when the application
1372+
* is ready to resume a session, it should create a new WolfSSLSession
1373+
* object and assign the previously-saved session pointer by passing it
1374+
* to the <code>setSession(long session)</code> method. This should be
1375+
* done before the handshake is started for the second/resumed time. After
1376+
* calling <code>setSession(long session)</code>, the application may call
1377+
* <code>connect()</code> and wolfSSL will try to resume the session. If
1378+
* the session cannot be resumed, a new fresh handshake will be
1379+
* established.
13701380
*
13711381
* @param session pointer to the native WOLFSSL_SESSION structure used
13721382
* to set the session for the SSL session object.
@@ -1411,25 +1421,35 @@ public int setSession(long session) throws IllegalStateException {
14111421
}
14121422

14131423
/**
1414-
* Returns a pointer to the current session used in the given SSL object.
1424+
* Returns a pointer to the current session (native WOLFSSL_SESSION)
1425+
* associated with this object, or null if not available.
1426+
*
14151427
* The native WOLFSSL_SESSION pointed to contains all the necessary
14161428
* information required to perform a session resumption and reestablishment
1417-
* the connection without a new handshake.
1429+
* of the connection without a new handshake.
1430+
* <p>
1431+
* To do session resumption, before calling <code>shutdownSSL()</code>
1432+
* with your WolfSSLSession object, save the internal session state by
1433+
* calling <code>getSession()</code>, which returns a pointer to the
1434+
* native WOLFSSL_SESSION session structure. Later, when the application
1435+
* is ready to resume a session, it should create a new WolfSSLSession
1436+
* object and assign the previously-saved session pointer by passing it
1437+
* to the <code>setSession(long session)</code> method. This should be
1438+
* done before the handshake is started for the second/resumed time. After
1439+
* calling <code>setSession(long session)</code>, the application may call
1440+
* <code>connect()</code> and wolfSSL will try to resume the session. If
1441+
* the session cannot be resumed, a new fresh handshake will be
1442+
* established.
1443+
* <p>
1444+
* <b>IMPORTANT:</b>
14181445
* <p>
1419-
* For session resumption, before calling <code>shutdownSSL()</code>
1420-
* with your session object, an application should save the session ID
1421-
* from the object with a call to <code>getSession()</code>, which returns
1422-
* a pointer to the session. Later, the application should create a new
1423-
* SSL object and assign the saved session with <code>setSession</code>.
1424-
* At this point, the application may call <code>connect()</code> and
1425-
* wolfSSL will try to resume the session.
1426-
*
14271446
* The pointer (WOLFSSL_SESSION) returned by this method needs to be freed
1428-
* when the application is finished with it, by calling
1429-
* <code>freeSession(long)</code>. This will release the underlying
1430-
* native memory associated with this WOLFSSL_SESSION.
1447+
* when the application is finished with it by calling
1448+
* <code>freeSession(long session)</code>. This will release the underlying
1449+
* native memory associated with this WOLFSSL_SESSION. Failing to free
1450+
* the session will result in a memory leak.
14311451
*
1432-
* @throws IllegalStateException WolfSSLContext has been freed
1452+
* @throws IllegalStateException this WolfSSLSession has been freed
14331453
* @return a pointer to the current SSL session object on success.
14341454
* <code>null</code> if <b>ssl</b> is <code>null</code>,
14351455
* the SSL session cache is disabled, wolfSSL doesn't have
@@ -1446,6 +1466,12 @@ public long getSession() throws IllegalStateException {
14461466
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
14471467
WolfSSLDebug.INFO, this.sslPtr, "entered getSession()");
14481468

1469+
/* Calling get1Session() here as an indication that the native
1470+
* JNI level should always return a session pointer that needs
1471+
* to be freed by the application. This behavior can change in
1472+
* native wolfSSL depending on build options
1473+
* (ex: NO_SESSION_CACHE_REF), so JNI layer here will make that
1474+
* behavior consistent to the JNI/JSSE callers. */
14491475
sessPtr = get1Session(this.sslPtr);
14501476

14511477
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,

0 commit comments

Comments
 (0)