From 315f5554e9779b0a38f55e157bc017a0875ba892 Mon Sep 17 00:00:00 2001 From: marci4 Date: Sun, 29 Mar 2020 20:00:11 +0200 Subject: [PATCH 1/4] Adjust path for keystore --- keystore.jks | Bin 2251 -> 0 bytes src/main/example/SSLClientExample.java | 2 +- ...SLServerCustomWebsocketFactoryExample.java | 2 +- src/main/example/SSLServerExample.java | 2 +- src/main/example/TwoWaySSLServerExample.java | 2 +- .../example/AutobahnSSLServerTest.java | 2 +- src/test/java/org/java_websocket/keystore.jks | Bin 2251 -> 2057 bytes 7 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 keystore.jks diff --git a/keystore.jks b/keystore.jks deleted file mode 100644 index 743add50e6fe50f8e00c182085024bab565743b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2251 zcmc&#_fr#y5>7%ANa&zIATd%^YC;K3kRsB9R4IZW<`~JyE{AI?(F_t`?&@H06;7U{_X5ugx@^E z{7EeAqH;Mn699k!FfrgG3=b482L*zGvLJpS5CQu|>lMdZZ4Q-QTUKZSkYw$? zMhlIp<#S^$aw%#k?oOW3TvBLh>NmuzM1x_YOXFjxij_r5{np@3eKpuSn7TT1+upaZCGT|jzX_htTF19C(MM`-S0n+AT20&jL2`mb?)vtmC18jWjK7Pb%j!Y z%Jha!+(57)YCfj4(Li{nbY)2HG~m%?<~P>>r#ibyyD`8_teman9=Il2y> z&_YZ6o_&%C1UL;9MNjEQSB&SE(~=_3)gHWc&_&ret;)>zIQfv|y`L(s8hEVZN`8;b zs}(Ix4c<%{)gi({3obJwIsW_#n~R%`It*$|$9XSVZ+-?0NGt;nS7!QV%%ST z{YjUl`0(?<2@msou^uhWt=xkIF8I8gUg9;y9e2;1pfjd`T)l<6(LSOQAN}e@dm`Q# zU@S~Mv-#YT*T-(pg))F2Mh#vTr)VclaeQ!*)!Nq%O$F7q>`p)EMym(HZ5<1!BSYy5 zI{7L@{|I-imza;J=ySC$k?S9Yi(HMS3QK!zI!x~4BGx}x>DLJ!it|HaJA6%EHF(Ym z=;!ft#A$lTg_e%B6i)4P%kV^hq^swb)Zadzjk=prrlS2#qqkblEsPdKE`xW=RlKz; zl$8^Q4?02K=fu+PTvOCMmqIdM-DA`U^d^_7(c^N^hlRX9lJ+Q**1Jbmf6;D^x!VqI zH7wuT@r{&8dO?3<7cZAqXV^l?cknZwYTC|>ax7skMk$?tSd4Bo_B)%s{<0tpmzkin zJ|T4iu+{fh{ESU^8x`#%4Ii<>GCTCV=;5I3F}szCR)ddrpX>MYenlhhUaG=M?T z@601y8*=98h{20eq^Qy}v8^aK={)Rw`nWO_DJwRcs4AqHUo(9{{F6Yv ze3xn5X5|W{2XkyFKxABX9;jdQ?#ET9X^jHC=9<_nFOr>y7b~6YkkXz0$8|uJG0= z7HcYvBp{PGs|8OPYEs2rs2c<&2UZq3UKGBHx~xHD{lA z#3(>baWKTbrih39khq?UnCz$P9X9R$2aqVWXsajLMK`_#7syT2U8~P_HY3jPI=#CDu-;A7IK}TCiZ@(`QU4ObupJt?(azZgVP5sMv{GJLrg7T zxSDSuHXs1_SR8}KpjZ<}@qmTECyF&ji`aQPnr_>!8S$=CG#7?XzWcX`tleUX2n5(W za#~a}ZQ@U4wM9bHa^d{-dG-BP@~Cor`mI_^BFgSCQ+HH7PGzsA5FMWOy-{zwu4r!X zHEEjjWI>@e?mbU~rugx&V7CJFJskF^Z*fp5+4{$7&n0G3xY{-T8FTiQPe;v;I)nCG zszQd8S)KBPb3|^TQo*SgsYjB#*{aLtW<@4fy?9&4XI4wV?0J}f5~_M3EN>!Yw`C*nWW|cSX@6q%Ld@#tynx__ z*y&0hL#pcsUb;_BgYqQBP4sFu*35LEo6qk#{-uh9F#dstrSXR8MPa6W`5#6NE-8V3 TbVxP^)z0WRV9e@BRsR14Jt){6 diff --git a/src/main/example/SSLClientExample.java b/src/main/example/SSLClientExample.java index 705bf9d1..b82a7e3f 100644 --- a/src/main/example/SSLClientExample.java +++ b/src/main/example/SSLClientExample.java @@ -83,7 +83,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = "keystore.jks"; + String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/SSLServerCustomWebsocketFactoryExample.java b/src/main/example/SSLServerCustomWebsocketFactoryExample.java index 8f5aecd4..1b62189b 100644 --- a/src/main/example/SSLServerCustomWebsocketFactoryExample.java +++ b/src/main/example/SSLServerCustomWebsocketFactoryExample.java @@ -52,7 +52,7 @@ public static void main(String[] args) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = "keystore.jks"; + String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/SSLServerExample.java b/src/main/example/SSLServerExample.java index 9d8d8565..0062fb05 100644 --- a/src/main/example/SSLServerExample.java +++ b/src/main/example/SSLServerExample.java @@ -48,7 +48,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = "keystore.jks"; + String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/TwoWaySSLServerExample.java b/src/main/example/TwoWaySSLServerExample.java index d3e1413c..e8a54841 100644 --- a/src/main/example/TwoWaySSLServerExample.java +++ b/src/main/example/TwoWaySSLServerExample.java @@ -51,7 +51,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = "keystore.jks"; + String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java b/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java index 6122fc8a..9d92c100 100644 --- a/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java +++ b/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java @@ -102,7 +102,7 @@ public static void main( String[] args ) throws UnknownHostException { try { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = "keystore.jks"; + String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/test/java/org/java_websocket/keystore.jks b/src/test/java/org/java_websocket/keystore.jks index 743add50e6fe50f8e00c182085024bab565743b2..2ff34420d7e2f3213c0f21ad5106bf01ca02cd98 100644 GIT binary patch delta 2049 zcmZvdc{J3I0>x)D_B~6omwlTh%1&h|Q5bu&OJtoesJ_NeBKj$5vhUN3NG1|eIW<`u z%VR_}Gqy?1L^2Jbc+T&i_s%=-kNd~H=iGnpAD=rcohJqCEblCXKp@DT!2d}2QhZp* zrKou9<-H_PLH^3=>sywr@ z=x?JMS)haram2i^l*fb}Q8i%|pZ$KZLpj5gXcD{WcCItb8s%=A%Tpz|R~a{7oO?8-(xN1^qp(_-3H(yH~wHyMwF!Km?n(U}r9_IKo56HA2N zxxXaY0uMCkgd=Z0s29_ zFJ(HO z{l*>c9JCF30Et2^fkN*G=jYXTd$U~Egdbn?z^h7chR!Nx&qV&-IDy?XeWsKeZM-=O z7hVy8jd6TQC{BH!43CPNRhP?EIub`?e|&^JLYr3n3zf&!r^En;ZiKQJtuV?rbQ8hj z&Lykx$kq%Q!OnS+)R|^BW}Tb&D$51 z>pkB0J2lWyJP3uw0QUnf`2F%&@gNJXK&||{44X8qM&zsCU-ZYnYQ4otl{@H zbagWUH4bw+|bM8sN18ZJELm)tcAYv;Zt2TC6H^%{{~aYCi{LCMGW ze_2-3V#HGUDy{Jux~3aVbzX{upIbN^%6t$xpV4O*VhbW~J!uva)VB|z0~xKkTn(SB zx$}w}XR&sb2Sg@V<`!%Tg+ggzA_OuH2<1!is!M%&*JSEn@#y1x+IkG3EJqmT#$8g&$DhD0Jw{T0N~|84(&?XEvu19+CYY&{i?wv@;wYL*oY-tsQC-Ym(N z>#;9Kb)8FULWArcUyGeEZ|w}_@WkXSf|m~YQcY5fqLmfCP9AfKX*y`zbr~o6bgPBU zb!Q+BbZfBlli>;B!VL>2t}6MT8c!Hy1?Y z08_)F=`?GD=h3QZ&dUUDC20q`I2vvx{Mf=)SNjxk%Z5a|Yx@iDn$diEM{KFjwYvf_ z=zDC{(*66$yzwydB}E~A;qpy9huFPrSo)<}x3owjomJPV9r5IKs2@W+X7`w3m9k~d zOV>+tCUOk*W2duK1pM@$i*z|mr#{xQ&g<+nk8Tb@(YKKyK=K0vz|Q{fAgvj@2R`B#raaDfb6! zR>W}+a}0+S19T>2bU)N87k^3|U}mM9`PO@RTq}jAg2sTAQq6U+77yCq{_Fx|MDmj9 zCXM38GK3UwAMb7Y1bR03N>#sL(kH#bc6qHo5;PfWDVY@(==1)F^@ciu)V6-j*oL1u zt^C{x$7GXUf@Rg##SrBJPnOqV-Przg9A2~AoHyI9Yb#cm&kt-Ec8`3r%Tl^Vn`6z^ bSN?zqQYbA-w$t__7njH{vr)3NGgAKs8^gNw literal 2251 zcmc&#_fr#y5>7%ANa&zIATd%^YC;K3kRsB9R4IZW<`~JyE{AI?(F_t`?&@H06;7U{_X5ugx@^E z{7EeAqH;Mn699k!FfrgG3=b482L*zGvLJpS5CQu|>lMdZZ4Q-QTUKZSkYw$? zMhlIp<#S^$aw%#k?oOW3TvBLh>NmuzM1x_YOXFjxij_r5{np@3eKpuSn7TT1+upaZCGT|jzX_htTF19C(MM`-S0n+AT20&jL2`mb?)vtmC18jWjK7Pb%j!Y z%Jha!+(57)YCfj4(Li{nbY)2HG~m%?<~P>>r#ibyyD`8_teman9=Il2y> z&_YZ6o_&%C1UL;9MNjEQSB&SE(~=_3)gHWc&_&ret;)>zIQfv|y`L(s8hEVZN`8;b zs}(Ix4c<%{)gi({3obJwIsW_#n~R%`It*$|$9XSVZ+-?0NGt;nS7!QV%%ST z{YjUl`0(?<2@msou^uhWt=xkIF8I8gUg9;y9e2;1pfjd`T)l<6(LSOQAN}e@dm`Q# zU@S~Mv-#YT*T-(pg))F2Mh#vTr)VclaeQ!*)!Nq%O$F7q>`p)EMym(HZ5<1!BSYy5 zI{7L@{|I-imza;J=ySC$k?S9Yi(HMS3QK!zI!x~4BGx}x>DLJ!it|HaJA6%EHF(Ym z=;!ft#A$lTg_e%B6i)4P%kV^hq^swb)Zadzjk=prrlS2#qqkblEsPdKE`xW=RlKz; zl$8^Q4?02K=fu+PTvOCMmqIdM-DA`U^d^_7(c^N^hlRX9lJ+Q**1Jbmf6;D^x!VqI zH7wuT@r{&8dO?3<7cZAqXV^l?cknZwYTC|>ax7skMk$?tSd4Bo_B)%s{<0tpmzkin zJ|T4iu+{fh{ESU^8x`#%4Ii<>GCTCV=;5I3F}szCR)ddrpX>MYenlhhUaG=M?T z@601y8*=98h{20eq^Qy}v8^aK={)Rw`nWO_DJwRcs4AqHUo(9{{F6Yv ze3xn5X5|W{2XkyFKxABX9;jdQ?#ET9X^jHC=9<_nFOr>y7b~6YkkXz0$8|uJG0= z7HcYvBp{PGs|8OPYEs2rs2c<&2UZq3UKGBHx~xHD{lA z#3(>baWKTbrih39khq?UnCz$P9X9R$2aqVWXsajLMK`_#7syT2U8~P_HY3jPI=#CDu-;A7IK}TCiZ@(`QU4ObupJt?(azZgVP5sMv{GJLrg7T zxSDSuHXs1_SR8}KpjZ<}@qmTECyF&ji`aQPnr_>!8S$=CG#7?XzWcX`tleUX2n5(W za#~a}ZQ@U4wM9bHa^d{-dG-BP@~Cor`mI_^BFgSCQ+HH7PGzsA5FMWOy-{zwu4r!X zHEEjjWI>@e?mbU~rugx&V7CJFJskF^Z*fp5+4{$7&n0G3xY{-T8FTiQPe;v;I)nCG zszQd8S)KBPb3|^TQo*SgsYjB#*{aLtW<@4fy?9&4XI4wV?0J}f5~_M3EN>!Yw`C*nWW|cSX@6q%Ld@#tynx__ z*y&0hL#pcsUb;_BgYqQBP4sFu*35LEo6qk#{-uh9F#dstrSXR8MPa6W`5#6NE-8V3 TbVxP^)z0WRV9e@BRsR14Jt){6 From 455d09e8ff5d4f5ed6e2fcfb5e5af23d396a464e Mon Sep 17 00:00:00 2001 From: marci4 Date: Sun, 29 Mar 2020 20:00:39 +0200 Subject: [PATCH 2/4] Add timeout for test --- src/test/java/org/java_websocket/issues/Issue962Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/java_websocket/issues/Issue962Test.java b/src/test/java/org/java_websocket/issues/Issue962Test.java index f5927b81..1cc9b298 100644 --- a/src/test/java/org/java_websocket/issues/Issue962Test.java +++ b/src/test/java/org/java_websocket/issues/Issue962Test.java @@ -85,7 +85,7 @@ public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throw } - @Test + @Test(timeout = 2000) public void testIssue() throws IOException, URISyntaxException, InterruptedException { int port = SocketUtil.getAvailablePort(); WebSocketClient client = new WebSocketClient(new URI("ws://127.0.0.1:" + port)) { @@ -103,7 +103,7 @@ public void onClose(int code, String reason, boolean remote) { @Override public void onError(Exception ex) { - Assert.fail(ex.toString() + " sould not occur"); + Assert.fail(ex.toString() + " should not occur"); } }; From 2dbe2d3c4a3ba63a0132a256ccefbfceb69531c9 Mon Sep 17 00:00:00 2001 From: marci4 Date: Mon, 13 Apr 2020 17:39:26 +0200 Subject: [PATCH 3/4] API for SSLParameters Enabled hostname validation by default --- .../client/WebSocketClient.java | 18 +- .../java_websocket/issues/Issue997Test.java | 174 ++++++++++++++++++ .../keystore_localhost_only.jks | Bin 0 -> 2036 bytes .../java_websocket/util/SSLContextUtil.java | 23 ++- 4 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/java_websocket/issues/Issue997Test.java create mode 100644 src/test/java/org/java_websocket/keystore_localhost_only.jks diff --git a/src/main/java/org/java_websocket/client/WebSocketClient.java b/src/main/java/org/java_websocket/client/WebSocketClient.java index 05b83976..651a5760 100644 --- a/src/main/java/org/java_websocket/client/WebSocketClient.java +++ b/src/main/java/org/java_websocket/client/WebSocketClient.java @@ -449,7 +449,6 @@ public void run() { } else if( socket == null ) { socket = new Socket( proxy ); isNewSocket = true; - } else if( socket.isClosed() ) { throw new IOException(); } @@ -464,13 +463,19 @@ public void run() { // if the socket is set by others we don't apply any TLS wrapper if (isNewSocket && "wss".equals( uri.getScheme())) { - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); SSLSocketFactory factory = sslContext.getSocketFactory(); socket = factory.createSocket(socket, uri.getHost(), getPort(), true); } + if (socket instanceof SSLSocket) { + SSLSocket sslSocket = (SSLSocket)socket; + SSLParameters sslParameters = sslSocket.getSSLParameters(); + onSetSSLParameters(sslParameters); + sslSocket.setSSLParameters(sslParameters); + } + istream = socket.getInputStream(); ostream = socket.getOutputStream(); @@ -511,6 +516,15 @@ public void run() { connectReadThread = null; } + /** + * Apply specific + * @param sslParameters the SSLParameters which will be used for the SSLSocket + */ + protected void onSetSSLParameters(SSLParameters sslParameters) { + // Make sure we perform hostname validation + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + } + /** * Extract the specified port * @return the specified port or the default port for the specific scheme diff --git a/src/test/java/org/java_websocket/issues/Issue997Test.java b/src/test/java/org/java_websocket/issues/Issue997Test.java new file mode 100644 index 00000000..43152969 --- /dev/null +++ b/src/test/java/org/java_websocket/issues/Issue997Test.java @@ -0,0 +1,174 @@ +package org.java_websocket.issues; + +/* + * Copyright (c) 2010-2020 Nathan Rajlich + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + +import org.java_websocket.WebSocket; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ClientHandshake; +import org.java_websocket.handshake.ServerHandshake; +import org.java_websocket.server.DefaultSSLWebSocketServerFactory; +import org.java_websocket.server.WebSocketServer; +import org.java_websocket.util.SSLContextUtil; +import org.java_websocket.util.SocketUtil; +import org.junit.Test; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLParameters; +import java.io.IOException; +import java.net.*; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.*; + +public class Issue997Test { + + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_Client127_CheckActive() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("127.0.0.1", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), "HTTPS"); + assertFalse(client.onOpen); + assertTrue(client.onSSLError); + } + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_Client127_CheckInactive() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("127.0.0.1", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), ""); + assertTrue(client.onOpen); + assertFalse(client.onSSLError); + } + + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_ClientLocalhost_CheckActive() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("localhost", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), "HTTPS"); + assertTrue(client.onOpen); + assertFalse(client.onSSLError); + } + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_ClientLocalhost_CheckInactive() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("localhost", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), ""); + assertTrue(client.onOpen); + assertFalse(client.onSSLError); + } + + + public SSLWebSocketClient testIssueWithLocalServer(String address, int port, SSLContext serverContext, SSLContext clientContext, String endpointIdentificationAlgorithm) throws IOException, URISyntaxException, InterruptedException { + CountDownLatch countServerDownLatch = new CountDownLatch(1); + SSLWebSocketClient client = new SSLWebSocketClient(address, port, endpointIdentificationAlgorithm); + WebSocketServer server = new SSLWebSocketServer(port, countServerDownLatch); + + server.setWebSocketFactory(new DefaultSSLWebSocketServerFactory(serverContext)); + if (clientContext != null) { + client.setSocketFactory(clientContext.getSocketFactory()); + } + server.start(); + countServerDownLatch.await(); + client.connectBlocking(1, TimeUnit.SECONDS); + return client; + } + + + private static class SSLWebSocketClient extends WebSocketClient { + private final String endpointIdentificationAlgorithm; + public boolean onSSLError = false; + public boolean onOpen = false; + + public SSLWebSocketClient(String address, int port, String endpointIdentificationAlgorithm) throws URISyntaxException { + super(new URI("wss://"+ address + ':' +port)); + this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; + } + + @Override + public void onOpen(ServerHandshake handshakedata) { + this.onOpen = true; + } + + @Override + public void onMessage(String message) { + } + + @Override + public void onClose(int code, String reason, boolean remote) { + } + + @Override + public void onError(Exception ex) { + if (ex instanceof SSLHandshakeException) { + this.onSSLError = true; + } + } + + @Override + protected void onSetSSLParameters(SSLParameters sslParameters) { + if (endpointIdentificationAlgorithm == null) { + super.onSetSSLParameters(sslParameters); + } else { + sslParameters.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm); + } + } + + }; + + + private static class SSLWebSocketServer extends WebSocketServer { + private final CountDownLatch countServerDownLatch; + + + public SSLWebSocketServer(int port, CountDownLatch countServerDownLatch) { + super(new InetSocketAddress(port)); + this.countServerDownLatch = countServerDownLatch; + } + + @Override + public void onOpen(WebSocket conn, ClientHandshake handshake) { + } + + @Override + public void onClose(WebSocket conn, int code, String reason, boolean remote) { + } + + @Override + public void onMessage(WebSocket conn, String message) { + + } + + @Override + public void onError(WebSocket conn, Exception ex) { + ex.printStackTrace(); + } + + @Override + public void onStart() { + countServerDownLatch.countDown(); + } + } +} diff --git a/src/test/java/org/java_websocket/keystore_localhost_only.jks b/src/test/java/org/java_websocket/keystore_localhost_only.jks new file mode 100644 index 0000000000000000000000000000000000000000..c18383b0b852a478610245c77297b62b69d737fa GIT binary patch literal 2036 zcmZ{kX*ARg8^-59V`m;@nMQU(5;Mr)HQ7z+K@lR$$l6Gn$53P)9$Sh?iLsMyo*J^u z$d;YZR1(w3PT6DZ+v_}E-oCsat`FCJ&V8TzT-Q0j!==L|5C{Z57VxjQZ~MEu-S+Vh zARJHd$cSrwAP_qkL1a5b{K3IknXHHlx`w{?@jQ%`Wk zR9UaYOj?KS5I$_^@d#`|Vwjh%|6Fv~mFcq})w8M@_QuqV>vJ(;K>|M&o}%}wOPG@M z*=gOs!dc7u5t*jJIi{A+^tg&|LK$c7pln?(nj~r4ALAqmA>@^E8i2M zl)}={TCtSNvNk732S-PAR_SHjp5RvO|4#Ai-67c?x%hpiIcZDTuVnPTDEK?i{v+NK z6MnCSTz{n;ZM2son2J-OyBJiaU-EFJGkKSjzn{St_g!dKJNb2Up?wGKX1oU7bncd9ii#pt}RF;=WyJ&isRR3l$N|+#fv?fCl!Z0^H3{Q zSnfL zhsr3c>Z8rMWwYpPmvZEnyd$`pC-v%T*9ZI}NClxfx9w8N!#MHL;9%sOlj4Bru;qTq z9@_v|**%?c5inB=DOnSBbXGbIgkTh>bAo=E@1j3Xr^FG5v=Q@`MXFeV{GE6l-#0TV z#4&{$L(e=|6TO=)L0vBTX@V=&QCZA)$GAoC?gnSf-raWZb=SYNp9t)5#B6BS8|_@FCl@4#!=C(RI4 zZ&iNWVl>Ln&^Z4yLwxOhS6AGf(pemq)AndDD+?8C=xY}YoAn{6m#-E}Xra8_O3KcB zw36PM3k=65Wmw8fMw3sm;C|Jhnljsx{*3~Ca{|ck(wfLoMLj3SdUI9vDG^5^=VNl6 z&gvQ~UObJ$q~m--{@O&N_QsSqN_j*Xx6pcF8)W?Dhq4fj+XJC<%Z z!19SvW)MueZrtT`J4|)Z+G$+Go`6G(-9movG_!d#<(Eh`8`D#1bu?}~coI;PJA+=IEj?RV zpyuT}S^8ccjCxrY3Qd!wGJ73F_Zzc#D|#6!?ne2C^TM%+YZ+-Rn7}K5wo|5s|C~Xv zD%@~I-e6$2CtjTa(}Ge~f-kt!4`_6Q$1k}+!p+Xl911Rr2%etES#oOCSDmW7UVhcJ z@QHbDaD}yfwOJ2VFCo60W+77(?i-0u4mXz&nmdmv7ULUk*r4J%7kH^iA>8b9Qr_2Q zGHXEd%DFGkgms6$ZqoLLHRI0eUoIbP7l$RbM&>UaWjCfiFy|E?la^}GMp8x%!u$k% zj=ZMdhsNA5)1`%>GM!6YG#`zT{K*z}X*HVi*-GI~`(J*j{P-7+?AKM#BXo{&S&ATn zix5O0DGve$z+g6)XhI|c%E7H1dogwk3IM$9AcQdT1VVrVV#@~M`yW&hk}#+`0->RS zL~3d3AT%9eP>tX1|Jfn}vcI1{rZ0pD@Pm#&-~kf>0JK-cwfv6@M@e8><)Rc0O3jA$H^e2LJFrGy074&D;%S{GEM&)`iz-L?AmvL0gKPo zK&dXp(kG2wUdLc_7*KQ0%fZiP`#4vL{g_p{Hs<^(Fi3Le{T4~hRC}|*u?B% zOP}jJwCOY3^>|G1k`CUEzqNDzAM(N_;~QPIpGfVxv@Zl?7Mhf*~4eE!7@6dpvvS&=#u3wCa0Oi~ANM_@??>GF{0}u}andCvJ z%$9@F!RKv9iFiE>4!kFZzvadVv*w!Z$vrb67d+Z*x}5LNo@e5s|LXgkJW%~9F6rhw zcGaZRWRwJHA|N3M8T4}LPAXvDCCyuTA!;Mt8rr`r+cFC8`Z_j}EY9Z3D9G;4nGo8$ z((9FcCp}5j&S*RK#)ic{OsUa^yr2`BJ^#4`k0L Date: Tue, 21 Apr 2020 22:34:52 +0200 Subject: [PATCH 4/4] Rework after review --- src/main/example/SSLClientExample.java | 3 ++- ...SSLServerCustomWebsocketFactoryExample.java | 3 ++- src/main/example/SSLServerExample.java | 3 ++- src/main/example/TwoWaySSLServerExample.java | 3 ++- .../java_websocket/client/WebSocketClient.java | 7 ++++--- .../example/AutobahnSSLServerTest.java | 3 ++- .../java_websocket/issues/Issue997Test.java | 18 +++++++++++++++--- .../java_websocket/util/SSLContextUtil.java | 5 +++-- 8 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/main/example/SSLClientExample.java b/src/main/example/SSLClientExample.java index b82a7e3f..d85fb85a 100644 --- a/src/main/example/SSLClientExample.java +++ b/src/main/example/SSLClientExample.java @@ -28,6 +28,7 @@ import java.io.FileInputStream; import java.io.InputStreamReader; import java.net.URI; +import java.nio.file.Paths; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; @@ -83,7 +84,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/SSLServerCustomWebsocketFactoryExample.java b/src/main/example/SSLServerCustomWebsocketFactoryExample.java index 1b62189b..3d834e02 100644 --- a/src/main/example/SSLServerCustomWebsocketFactoryExample.java +++ b/src/main/example/SSLServerCustomWebsocketFactoryExample.java @@ -32,6 +32,7 @@ import javax.net.ssl.TrustManagerFactory; import java.io.File; import java.io.FileInputStream; +import java.nio.file.Paths; import java.security.KeyStore; import java.util.ArrayList; import java.util.Arrays; @@ -52,7 +53,7 @@ public static void main(String[] args) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/SSLServerExample.java b/src/main/example/SSLServerExample.java index 0062fb05..a72f56b9 100644 --- a/src/main/example/SSLServerExample.java +++ b/src/main/example/SSLServerExample.java @@ -27,6 +27,7 @@ import java.io.File; import java.io.FileInputStream; +import java.nio.file.Paths; import java.security.KeyStore; import javax.net.ssl.KeyManagerFactory; @@ -48,7 +49,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/example/TwoWaySSLServerExample.java b/src/main/example/TwoWaySSLServerExample.java index e8a54841..694e43cd 100644 --- a/src/main/example/TwoWaySSLServerExample.java +++ b/src/main/example/TwoWaySSLServerExample.java @@ -33,6 +33,7 @@ import javax.net.ssl.TrustManagerFactory; import java.io.File; import java.io.FileInputStream; +import java.nio.file.Paths; import java.security.KeyStore; /** @@ -51,7 +52,7 @@ public static void main( String[] args ) throws Exception { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/main/java/org/java_websocket/client/WebSocketClient.java b/src/main/java/org/java_websocket/client/WebSocketClient.java index 651a5760..0bbcfe54 100644 --- a/src/main/java/org/java_websocket/client/WebSocketClient.java +++ b/src/main/java/org/java_websocket/client/WebSocketClient.java @@ -472,6 +472,8 @@ public void run() { if (socket instanceof SSLSocket) { SSLSocket sslSocket = (SSLSocket)socket; SSLParameters sslParameters = sslSocket.getSSLParameters(); + // Make sure we perform hostname validation + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); onSetSSLParameters(sslParameters); sslSocket.setSSLParameters(sslParameters); } @@ -517,12 +519,11 @@ public void run() { } /** - * Apply specific + * Apply specific SSLParameters + * * @param sslParameters the SSLParameters which will be used for the SSLSocket */ protected void onSetSSLParameters(SSLParameters sslParameters) { - // Make sure we perform hostname validation - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); } /** diff --git a/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java b/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java index 9d92c100..290b3f8d 100644 --- a/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java +++ b/src/test/java/org/java_websocket/example/AutobahnSSLServerTest.java @@ -43,6 +43,7 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.nio.file.Paths; import java.security.KeyStore; import java.security.spec.ECField; import java.util.Collections; @@ -102,7 +103,7 @@ public static void main( String[] args ) throws UnknownHostException { try { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; diff --git a/src/test/java/org/java_websocket/issues/Issue997Test.java b/src/test/java/org/java_websocket/issues/Issue997Test.java index 43152969..0fc81bc2 100644 --- a/src/test/java/org/java_websocket/issues/Issue997Test.java +++ b/src/test/java/org/java_websocket/issues/Issue997Test.java @@ -67,6 +67,13 @@ public void test_localServer_ServerLocalhost_Client127_CheckInactive() throws Ce assertFalse(client.onSSLError); } + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_Client127_CheckDefault() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("127.0.0.1", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), null); + assertFalse(client.onOpen); + assertTrue(client.onSSLError); + } + @Test(timeout=2000) public void test_localServer_ServerLocalhost_ClientLocalhost_CheckActive() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { SSLWebSocketClient client = testIssueWithLocalServer("localhost", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), "HTTPS"); @@ -80,6 +87,13 @@ public void test_localServer_ServerLocalhost_ClientLocalhost_CheckInactive() thr assertFalse(client.onSSLError); } + @Test(timeout=2000) + public void test_localServer_ServerLocalhost_ClientLocalhost_CheckDefault() throws CertificateException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, URISyntaxException, InterruptedException { + SSLWebSocketClient client = testIssueWithLocalServer("localhost", SocketUtil.getAvailablePort(), SSLContextUtil.getLocalhostOnlyContext(), SSLContextUtil.getLocalhostOnlyContext(), null); + assertTrue(client.onOpen); + assertFalse(client.onSSLError); + } + public SSLWebSocketClient testIssueWithLocalServer(String address, int port, SSLContext serverContext, SSLContext clientContext, String endpointIdentificationAlgorithm) throws IOException, URISyntaxException, InterruptedException { CountDownLatch countServerDownLatch = new CountDownLatch(1); @@ -129,9 +143,7 @@ public void onError(Exception ex) { @Override protected void onSetSSLParameters(SSLParameters sslParameters) { - if (endpointIdentificationAlgorithm == null) { - super.onSetSSLParameters(sslParameters); - } else { + if (endpointIdentificationAlgorithm != null) { sslParameters.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm); } } diff --git a/src/test/java/org/java_websocket/util/SSLContextUtil.java b/src/test/java/org/java_websocket/util/SSLContextUtil.java index 26c929c2..49caf0cb 100644 --- a/src/test/java/org/java_websocket/util/SSLContextUtil.java +++ b/src/test/java/org/java_websocket/util/SSLContextUtil.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Paths; import java.security.*; import java.security.cert.CertificateException; @@ -40,7 +41,7 @@ public class SSLContextUtil { public static SSLContext getContext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword"; @@ -62,7 +63,7 @@ public static SSLContext getContext() throws NoSuchAlgorithmException, KeyManage public static SSLContext getLocalhostOnlyContext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException { // load up the key store String STORETYPE = "JKS"; - String KEYSTORE = String.format("src%1$stest%1$1sjava%1$1sorg%1$1sjava_websocket%1$1skeystore_localhost_only.jks", File.separator); + String KEYSTORE = Paths.get("src", "test", "java", "org", "java_websocket", "keystore_localhost_only.jks").toString(); String STOREPASSWORD = "storepassword"; String KEYPASSWORD = "keypassword";