Skip to content

Commit 9709433

Browse files
authored
Provide a way to access the SSLSession of a websocket instance (#893)
Provide a way to access the SSLSession of a websocket instance
2 parents 8fcd4d1 + 3e3d91d commit 9709433

File tree

11 files changed

+365
-40
lines changed

11 files changed

+365
-40
lines changed

src/main/java/org/java_websocket/SSLSocketChannel.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.java_websocket;
2727

28+
import org.java_websocket.interfaces.ISSLChannel;
2829
import org.java_websocket.util.ByteBufferUtils;
2930
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
@@ -62,7 +63,7 @@
6263
* <p>
6364
* Permission for usage recieved at May 25, 2017 by Alex Karnezis
6465
*/
65-
public class SSLSocketChannel implements WrappedByteChannel, ByteChannel {
66+
public class SSLSocketChannel implements WrappedByteChannel, ByteChannel, ISSLChannel {
6667

6768
/**
6869
* Logger instance
@@ -512,4 +513,9 @@ public boolean isOpen() {
512513
public void close() throws IOException {
513514
closeConnection();
514515
}
516+
517+
@Override
518+
public SSLEngine getSSLEngine() {
519+
return engine;
520+
}
515521
}

src/main/java/org/java_websocket/SSLSocketChannel2.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package org.java_websocket;
2626

27+
import org.java_websocket.interfaces.ISSLChannel;
2728
import org.slf4j.Logger;
2829
import org.slf4j.LoggerFactory;
2930

@@ -52,7 +53,7 @@
5253
/**
5354
* Implements the relevant portions of the SocketChannel interface with the SSLEngine wrapper.
5455
*/
55-
public class SSLSocketChannel2 implements ByteChannel, WrappedByteChannel {
56+
public class SSLSocketChannel2 implements ByteChannel, WrappedByteChannel, ISSLChannel {
5657

5758
/**
5859
* Logger instance
@@ -425,4 +426,8 @@ public boolean isBlocking() {
425426
return socketChannel.isBlocking();
426427
}
427428

429+
@Override
430+
public SSLEngine getSSLEngine() {
431+
return sslEngine;
432+
}
428433
}

src/main/java/org/java_websocket/WebSocket.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import org.java_websocket.exceptions.WebsocketNotConnectedException;
3636
import org.java_websocket.framing.Framedata;
3737

38+
import javax.net.ssl.SSLSession;
39+
3840
public interface WebSocket {
3941

4042
/**
@@ -207,4 +209,19 @@ public interface WebSocket {
207209
* @since 1.3.7
208210
**/
209211
<T> T getAttachment();
212+
213+
/**
214+
* Does this websocket use an encrypted (wss/ssl) or unencrypted (ws) connection
215+
* @return true, if the websocket does use wss and therefore has a SSLSession
216+
* @since 1.4.1
217+
*/
218+
boolean hasSSLSupport();
219+
220+
/**
221+
* Returns the ssl session of websocket, if ssl/wss is used for this instance.
222+
* @return the ssl session of this websocket instance
223+
* @throws IllegalArgumentException the underlying channel does not use ssl (use hasSSLSupport() to check)
224+
* @since 1.4.1
225+
*/
226+
SSLSession getSSLSession() throws IllegalArgumentException;
210227
}

src/main/java/org/java_websocket/WebSocketImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
package org.java_websocket;
2727

28+
import org.java_websocket.interfaces.ISSLChannel;
2829
import org.java_websocket.drafts.Draft;
2930
import org.java_websocket.drafts.Draft_6455;
3031
import org.java_websocket.enums.*;
@@ -51,6 +52,8 @@
5152
import org.slf4j.Logger;
5253
import org.slf4j.LoggerFactory;
5354

55+
import javax.net.ssl.SSLSession;
56+
5457
/**
5558
* Represents one end (client or server) of a single WebSocketImpl connection.
5659
* Takes care of the "handshake" phase, then allows for easy sending of
@@ -820,6 +823,19 @@ public <T> T getAttachment() {
820823
return (T) attachment;
821824
}
822825

826+
@Override
827+
public boolean hasSSLSupport() {
828+
return channel instanceof ISSLChannel;
829+
}
830+
831+
@Override
832+
public SSLSession getSSLSession() {
833+
if (!hasSSLSupport()) {
834+
throw new IllegalArgumentException("This websocket uses ws instead of wss. No SSLSession available.");
835+
}
836+
return ((ISSLChannel) channel).getSSLEngine().getSession();
837+
}
838+
823839
@Override
824840
public <T> void setAttachment(T attachment) {
825841
this.attachment = attachment;

src/main/java/org/java_websocket/client/WebSocketClient.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@
4444
import java.util.concurrent.TimeUnit;
4545

4646
import javax.net.SocketFactory;
47-
import javax.net.ssl.SSLContext;
48-
import javax.net.ssl.SSLException;
49-
import javax.net.ssl.SSLSocketFactory;
47+
import javax.net.ssl.*;
5048

5149
import org.java_websocket.AbstractWebSocket;
5250
import org.java_websocket.WebSocket;
@@ -888,6 +886,15 @@ public String getResourceDescriptor() {
888886
return uri.getPath();
889887
}
890888

889+
@Override
890+
public boolean hasSSLSupport() {
891+
return engine.hasSSLSupport();
892+
}
893+
894+
@Override
895+
public SSLSession getSSLSession() {
896+
return engine.getSSLSession();
897+
}
891898

892899
/**
893900
* Method to give some additional info for specific IOExceptions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2010-2019 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*
25+
*/
26+
27+
package org.java_websocket.interfaces;
28+
29+
import javax.net.ssl.SSLEngine;
30+
31+
/**
32+
* Interface which specifies all required methods a SSLSocketChannel has to make public.
33+
*
34+
* @since 1.4.1
35+
*/
36+
public interface ISSLChannel {
37+
38+
/**
39+
* Get the ssl engine used for the de- and encryption of the communication.
40+
* @return the ssl engine of this channel
41+
*/
42+
SSLEngine getSSLEngine();
43+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2010-2019 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*
25+
*/
26+
27+
/**
28+
* This package encapsulates all new interfaces.
29+
*/
30+
package org.java_websocket.interfaces;

src/test/java/org/java_websocket/issues/Issue764Test.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.java_websocket.handshake.ServerHandshake;
3333
import org.java_websocket.server.DefaultSSLWebSocketServerFactory;
3434
import org.java_websocket.server.WebSocketServer;
35+
import org.java_websocket.util.SSLContextUtil;
3536
import org.java_websocket.util.SocketUtil;
3637
import org.junit.Test;
3738

@@ -76,24 +77,7 @@ public void onError(Exception ex) {
7677
};
7778
WebSocketServer server = new MyWebSocketServer(port, webSocket, countServerDownLatch);
7879

79-
// load up the key store
80-
String STORETYPE = "JKS";
81-
String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator);
82-
String STOREPASSWORD = "storepassword";
83-
String KEYPASSWORD = "keypassword";
84-
85-
KeyStore ks = KeyStore.getInstance(STORETYPE);
86-
File kf = new File(KEYSTORE);
87-
ks.load(new FileInputStream(kf), STOREPASSWORD.toCharArray());
88-
89-
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
90-
kmf.init(ks, KEYPASSWORD.toCharArray());
91-
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
92-
tmf.init(ks);
93-
94-
SSLContext sslContext = null;
95-
sslContext = SSLContext.getInstance("TLS");
96-
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
80+
SSLContext sslContext = SSLContextUtil.getContext();
9781

9882
server.setWebSocketFactory(new DefaultSSLWebSocketServerFactory(sslContext));
9983
webSocket.setSocketFactory(sslContext.getSocketFactory());

src/test/java/org/java_websocket/issues/Issue825Test.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.java_websocket.handshake.ServerHandshake;
3333
import org.java_websocket.server.DefaultSSLWebSocketServerFactory;
3434
import org.java_websocket.server.WebSocketServer;
35+
import org.java_websocket.util.SSLContextUtil;
3536
import org.java_websocket.util.SocketUtil;
3637
import org.junit.Test;
3738

@@ -78,23 +79,7 @@ public void onError(Exception ex) {
7879
WebSocketServer server = new MyWebSocketServer(port, countServerDownLatch, countClientMessageLatch);
7980

8081
// load up the key store
81-
String STORETYPE = "JKS";
82-
String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator);
83-
String STOREPASSWORD = "storepassword";
84-
String KEYPASSWORD = "keypassword";
85-
86-
KeyStore ks = KeyStore.getInstance(STORETYPE);
87-
File kf = new File(KEYSTORE);
88-
ks.load(new FileInputStream(kf), STOREPASSWORD.toCharArray());
89-
90-
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
91-
kmf.init(ks, KEYPASSWORD.toCharArray());
92-
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
93-
tmf.init(ks);
94-
95-
SSLContext sslContext = null;
96-
sslContext = SSLContext.getInstance("TLS");
97-
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
82+
SSLContext sslContext = SSLContextUtil.getContext();
9883

9984
server.setWebSocketFactory(new DefaultSSLWebSocketServerFactory(sslContext));
10085
webSocket.setSocketFactory(sslContext.getSocketFactory());

0 commit comments

Comments
 (0)