Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return cached SNI request from Server side #238

Closed
wants to merge 7 commits into from
19 changes: 19 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ jobs:
jdk_version: ${{ matrix.jdk_version }}
wolfssl_configure: ${{ matrix.wolfssl_configure }}

# -------------------- session cache variant sanity checks -----------------------
# Only check one Linux and Mac JDK version as a sanity check.
# Using Zulu, but this can be expanded if needed.
linux-zulu-sesscache:
strategy:
matrix:
os: [ 'ubuntu-latest', 'macos-latest' ]
jdk_version: [ '11' ]
wolfssl_configure: [
'--enable-jni CFLAGS=-DNO_SESSION_CACHE_REF',
]
name: ${{ matrix.os }} (Zulu JDK ${{ matrix.jdk_version }}, ${{ matrix.wolfssl_configure}})
uses: ./.github/workflows/linux-common.yml
with:
os: ${{ matrix.os }}
jdk_distro: "zulu"
jdk_version: ${{ matrix.jdk_version }}
wolfssl_configure: ${{ matrix.wolfssl_configure }}

# ------------------ Facebook Infer static analysis -------------------
# Run Facebook infer over PR code, only running on Linux with one
# JDK/version for now.
Expand Down
25 changes: 10 additions & 15 deletions native/com_wolfssl_WolfSSLSession.c
Original file line number Diff line number Diff line change
Expand Up @@ -1644,23 +1644,18 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLSession_get1Session
}
}
} while (err == SSL_ERROR_WANT_READ);

sess = wolfSSL_get_session(ssl);
hasTicket = wolfSSL_SESSION_has_ticket((const WOLFSSL_SESSION*)sess);
}

/* Only duplicate / save session if not TLS 1.3 (will be using normal
* session IDs), or is TLS 1.3 and we have a session ticket */
if (version != TLS1_3_VERSION || hasTicket == 1) {

/* wolfSSL checks ssl for NULL, returns pointer to new WOLFSSL_SESSION,
* Returns new duplicated WOLFSSL_SESSION. Needs to be freed with
* wolfSSL_SESSION_free() when finished with pointer. */
if (sess != NULL) {
/* Guarantee that we own the WOLFSSL_SESSION, make a copy */
dup = wolfSSL_SESSION_dup(sess);
}
}
/* Call wolfSSL_get1_session() to increase the ref count of the internal
* WOLFSSL_SESSION struct. This is needed in all build option cases,
* since Java callers of this function expect to explicitly free this
* pointer when finished with use. In some build cases, for example
* NO_CLIENT_CACHE or NO_SESSION_CACHE_REF, the poiner returned by
* wolfSSL_get_session() will be a pointer into the WOLFSSL struct, which
* will be freed with wolfSSL_free(). This can cause issues if the Java
* app expects to hold a valid session pointer for resumption and free
* later on. */
dup = wolfSSL_get1_session(ssl);

if (wc_UnLockMutex(jniSessLock) != 0) {
printf("Failed to unlock jniSessLock in get1Session()");
Expand Down
2 changes: 2 additions & 0 deletions src/java/com/wolfssl/WolfSSLDebug.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ public class WolfSSLDebug {
* Will be used to determine what string gets put into log messages.
*/
public enum Component {
/** wolfSSL JNI component */
JNI("wolfJNI"),
/** wolfSSL JSSE component */
JSSE("wolfJSSE");

private final String componentString;
Expand Down
72 changes: 49 additions & 23 deletions src/java/com/wolfssl/WolfSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -1358,15 +1358,25 @@ public int getError(int ret) throws IllegalStateException {
}

/**
* Sets the session to be used when the SSL object is used to create
* a SSL/TLS connection.
* For session resumption, before calling <code>shutdownSSL()</code>
* with your session object, an application should save the session ID
* from the object with a call to <code>getSession()</code>, which returns
* a pointer to the session. Later, the application should create a new
* SSL session object and assign the saved session with <code>
* setSession()</code>. At this point, the application may call <code>
* connect()</code> and wolfSSL will try to resume the session.
* Sets the session (native WOLFSSL_SESSION) to be used with this object
* for session resumption.
*
* The native WOLFSSL_SESSION pointed to contains all the necessary
* information required to perform a session resumption and reestablishment
* of the connection without a new handshake.
* <p>
* To do session resumption, before calling <code>shutdownSSL()</code>
* with your WolfSSLSession object, save the internal session state by
* calling <code>getSession()</code>, which returns a pointer to the
* native WOLFSSL_SESSION session structure. Later, when the application
* is ready to resume a session, it should create a new WolfSSLSession
* object and assign the previously-saved session pointer by passing it
* to the <code>setSession(long session)</code> method. This should be
* done before the handshake is started for the second/resumed time. After
* calling <code>setSession(long session)</code>, the application may call
* <code>connect()</code> and wolfSSL will try to resume the session. If
* the session cannot be resumed, a new fresh handshake will be
* established.
*
* @param session pointer to the native WOLFSSL_SESSION structure used
* to set the session for the SSL session object.
Expand Down Expand Up @@ -1411,25 +1421,35 @@ public int setSession(long session) throws IllegalStateException {
}

/**
* Returns a pointer to the current session used in the given SSL object.
* Returns a pointer to the current session (native WOLFSSL_SESSION)
* associated with this object, or null if not available.
*
* The native WOLFSSL_SESSION pointed to contains all the necessary
* information required to perform a session resumption and reestablishment
* the connection without a new handshake.
* of the connection without a new handshake.
* <p>
* To do session resumption, before calling <code>shutdownSSL()</code>
* with your WolfSSLSession object, save the internal session state by
* calling <code>getSession()</code>, which returns a pointer to the
* native WOLFSSL_SESSION session structure. Later, when the application
* is ready to resume a session, it should create a new WolfSSLSession
* object and assign the previously-saved session pointer by passing it
* to the <code>setSession(long session)</code> method. This should be
* done before the handshake is started for the second/resumed time. After
* calling <code>setSession(long session)</code>, the application may call
* <code>connect()</code> and wolfSSL will try to resume the session. If
* the session cannot be resumed, a new fresh handshake will be
* established.
* <p>
* <b>IMPORTANT:</b>
* <p>
* For session resumption, before calling <code>shutdownSSL()</code>
* with your session object, an application should save the session ID
* from the object with a call to <code>getSession()</code>, which returns
* a pointer to the session. Later, the application should create a new
* SSL object and assign the saved session with <code>setSession</code>.
* At this point, the application may call <code>connect()</code> and
* wolfSSL will try to resume the session.
*
* The pointer (WOLFSSL_SESSION) returned by this method needs to be freed
* when the application is finished with it, by calling
* <code>freeSession(long)</code>. This will release the underlying
* native memory associated with this WOLFSSL_SESSION.
* when the application is finished with it by calling
* <code>freeSession(long session)</code>. This will release the underlying
* native memory associated with this WOLFSSL_SESSION. Failing to free
* the session will result in a memory leak.
*
* @throws IllegalStateException WolfSSLContext has been freed
* @throws IllegalStateException this WolfSSLSession has been freed
* @return a pointer to the current SSL session object on success.
* <code>null</code> if <b>ssl</b> is <code>null</code>,
* the SSL session cache is disabled, wolfSSL doesn't have
Expand All @@ -1446,6 +1466,12 @@ public long getSession() throws IllegalStateException {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.sslPtr, "entered getSession()");

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

WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
Expand Down
10 changes: 7 additions & 3 deletions src/java/com/wolfssl/provider/jsse/WolfSSLAuthStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ protected synchronized WolfSSLImplementSSLSession getSession(

/* Return new session if in server mode, or if host is null */
if (!clientMode || host == null) {
return this.getSession(ssl, clientMode);
return this.getSession(ssl, clientMode, host, port);
}

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
Expand Down Expand Up @@ -527,18 +527,22 @@ private void printSessionStoreStatus() {
}

/** Returns a new session, does not check/save for resumption
*
* @param ssl WOLFSSL class to reference with new session
* @param clientMode true if on client side, false if server
* @param host hostname of peer, or null if not available
* @param port port of peer
*
* @return a new SSLSession on success
*/
protected synchronized WolfSSLImplementSSLSession getSession(
WolfSSLSession ssl, boolean clientMode) {
WolfSSLSession ssl, boolean clientMode, String host, int port) {

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"creating new session");

WolfSSLImplementSSLSession ses =
new WolfSSLImplementSSLSession(ssl, this);
new WolfSSLImplementSSLSession(ssl, this, host, port);

ses.setValid(true);
ses.isFromTable = false;
Expand Down
4 changes: 2 additions & 2 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ public synchronized boolean isOutboundDone() {
public String[] getSupportedCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered getSupportedCipherSuites()");
return this.engineHelper.getAllCiphers();
return WolfSSLEngineHelper.getAllCiphers();
}

@Override
Expand All @@ -1415,7 +1415,7 @@ public synchronized void setEnabledCipherSuites(String[] suites) {
public String[] getSupportedProtocols() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered getSupportedProtocols()");
return this.engineHelper.getAllProtocols();
return WolfSSLEngineHelper.getAllProtocols();
}

@Override
Expand Down
13 changes: 10 additions & 3 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ protected synchronized WolfSSLImplementSSLSession getSession() {
*
* @return String array of all supported cipher suites
*/
protected synchronized String[] getAllCiphers() {
protected static synchronized String[] getAllCiphers() {
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana());
}

Expand Down Expand Up @@ -551,7 +551,7 @@ protected synchronized String[] getProtocols() {
*
* @return String array of supported protocols
*/
protected synchronized String[] getAllProtocols() {
protected static synchronized String[] getAllProtocols() {
return WolfSSLUtil.sanitizeProtocols(WolfSSL.getProtocols());
}

Expand Down Expand Up @@ -1262,6 +1262,7 @@ protected synchronized int doHandshake(int isSSLEngine, int timeout)
int ret, err;
byte[] serverId = null;
String hostAddress = null;
String sessCacheHostname = this.hostname;

if (!modeSet) {
throw new SSLException("setUseClientMode has not been called");
Expand Down Expand Up @@ -1293,7 +1294,13 @@ protected synchronized int doHandshake(int isSSLEngine, int timeout)

return WolfSSL.SSL_HANDSHAKE_FAILURE;
}
this.session = this.authStore.getSession(ssl, this.clientMode);

if (sessCacheHostname == null && this.peerAddr != null) {
sessCacheHostname = this.peerAddr.getHostAddress();
}

this.session = this.authStore.getSession(ssl, this.clientMode,
sessCacheHostname, this.port);
}

if (this.clientMode) {
Expand Down
35 changes: 29 additions & 6 deletions src/java/com/wolfssl/provider/jsse/WolfSSLImplementSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,14 @@ public WolfSSLImplementSSLSession (WolfSSLSession in, int port, String host,
*
* @param in WolfSSLSession to be used with this object
* @param params WolfSSLAuthStore for this session
* @param host hostname of peer, or null if not available
* @param port port of peer
*/
public WolfSSLImplementSSLSession (WolfSSLSession in,
WolfSSLAuthStore params) {
WolfSSLAuthStore params,
String host, int port) {
this.ssl = in;
this.port = -1;
this.host = null;
this.host = host;
this.authStore = params;
this.valid = false; /* flag if joining or resuming session is allowed */
this.peerCerts = null;
Expand All @@ -163,6 +165,12 @@ public WolfSSLImplementSSLSession (WolfSSLSession in,
creation = new Date();
accessed = new Date();

if (port > 0) {
this.port = port;
} else {
this.port = -1;
}

WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"created new session (no host/port yet)");
}
Expand Down Expand Up @@ -478,7 +486,9 @@ public synchronized Certificate[] getPeerCertificates()
X509Certificate exportCert;

if (ssl == null) {
throw new SSLPeerUnverifiedException("handshake not complete");
throw new SSLPeerUnverifiedException(
"internal WolfSSLSession null, handshake not complete or " +
"SSLSocket/Engine closed");
}

try {
Expand Down Expand Up @@ -927,7 +937,7 @@ public String[] getPeerSupportedSignatureAlgorithms() {
* Return a list of all SNI server names of the requested Server Name
* Indication (SNI) extension.
*
* @return non-null immutable List of SNIServerNames. List may be emtpy
* @return non-null immutable List of SNIServerNames. List may be empty
* if no SNI names were requested.
*/
@Override
Expand All @@ -942,7 +952,20 @@ public synchronized List<SNIServerName> getRequestedServerNames()
}

try {
sniRequestArr = this.ssl.getClientSNIRequest();
/* Return SNI name saved by Client
* or return cached request name from Server
* Currently WolfSSL.WOLFSSL_SNI_HOST_NAME is the only
* supported type */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"calling getRequestedServerNames (" +
this.getSideString() + ")");
if (this.ssl.getSide() == WolfSSL.WOLFSSL_CLIENT_END){
sniRequestArr = this.ssl.getClientSNIRequest();
} else {
sniRequestArr = this.ssl.getSNIRequest((byte)WolfSSL.
WOLFSSL_SNI_HOST_NAME).getBytes();
}

if (sniRequestArr != null) {
SNIHostName sniName = new SNIHostName(sniRequestArr);
sniNames.add(sniName);
Expand Down
Loading
Loading