Skip to content

Commit fe362d6

Browse files
committed
Merged branch 'fix/jetty-12.0.x/12428/bouncy-castle-alpn' into 'jetty-12.0.x'.
2 parents df41467 + c093dfe commit fe362d6

File tree

16 files changed

+655
-4
lines changed

16 files changed

+655
-4
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>org.eclipse.jetty</groupId>
8+
<artifactId>jetty-alpn</artifactId>
9+
<version>12.0.17-SNAPSHOT</version>
10+
</parent>
11+
<artifactId>jetty-alpn-bouncycastle-client</artifactId>
12+
<name>Core :: ALPN :: Bouncy Castle Client</name>
13+
14+
<properties>
15+
<bundle-symbolic-name>${project.groupId}.alpn.bouncycastle.client</bundle-symbolic-name>
16+
</properties>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.eclipse.jetty</groupId>
21+
<artifactId>jetty-alpn-client</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.slf4j</groupId>
25+
<artifactId>slf4j-api</artifactId>
26+
</dependency>
27+
28+
<dependency>
29+
<groupId>org.bouncycastle</groupId>
30+
<artifactId>bctls-jdk18on</artifactId>
31+
<version>${bouncycastle.version}</version>
32+
<scope>test</scope>
33+
</dependency>
34+
<dependency>
35+
<groupId>org.eclipse.jetty</groupId>
36+
<artifactId>jetty-slf4j-impl</artifactId>
37+
<scope>test</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.eclipse.jetty.http2</groupId>
41+
<artifactId>jetty-http2-client</artifactId>
42+
<scope>test</scope>
43+
</dependency>
44+
</dependencies>
45+
46+
<build>
47+
<plugins>
48+
<plugin>
49+
<groupId>org.apache.felix</groupId>
50+
<artifactId>maven-bundle-plugin</artifactId>
51+
<extensions>true</extensions>
52+
<configuration>
53+
<instructions>
54+
<Bundle-Description>Bouncy Castle Client ALPN</Bundle-Description>
55+
<Import-Package>${osgi.slf4j.import.packages},org.bouncycastle;version="${bouncycastle.version}",*</Import-Package>
56+
<Export-Package>*</Export-Package>
57+
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
58+
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Client</Provide-Capability>
59+
<_nouses>true</_nouses>
60+
</instructions>
61+
</configuration>
62+
</plugin>
63+
</plugins>
64+
</build>
65+
66+
</project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
import org.eclipse.jetty.alpn.bouncycastle.client.BouncyCastleClientALPNProcessor;
15+
16+
module org.eclipse.jetty.alpn.bouncycastle.client
17+
{
18+
requires org.slf4j;
19+
20+
requires transitive org.eclipse.jetty.alpn.client;
21+
22+
provides org.eclipse.jetty.io.ssl.ALPNProcessor.Client with
23+
BouncyCastleClientALPNProcessor;
24+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
package org.eclipse.jetty.alpn.bouncycastle.client;
15+
16+
import java.util.List;
17+
import javax.net.ssl.SSLEngine;
18+
import javax.net.ssl.SSLParameters;
19+
20+
import org.eclipse.jetty.alpn.client.ALPNClientConnection;
21+
import org.eclipse.jetty.io.Connection;
22+
import org.eclipse.jetty.io.ssl.ALPNProcessor;
23+
import org.eclipse.jetty.io.ssl.SslConnection.SslEndPoint;
24+
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
public class BouncyCastleClientALPNProcessor implements ALPNProcessor.Client
29+
{
30+
private static final Logger LOG = LoggerFactory.getLogger(BouncyCastleClientALPNProcessor.class);
31+
32+
@Override
33+
public boolean appliesTo(SSLEngine sslEngine)
34+
{
35+
return sslEngine.getClass().getName().startsWith("org.bouncycastle.jsse.provider.");
36+
}
37+
38+
@Override
39+
public void configure(SSLEngine sslEngine, Connection connection)
40+
{
41+
try
42+
{
43+
ALPNClientConnection alpn = (ALPNClientConnection)connection;
44+
SSLParameters sslParameters = sslEngine.getSSLParameters();
45+
List<String> protocols = alpn.getProtocols();
46+
sslParameters.setApplicationProtocols(protocols.toArray(new String[0]));
47+
sslEngine.setSSLParameters(sslParameters);
48+
SslEndPoint sslEndPoint = (SslEndPoint)connection.getEndPoint();
49+
sslEndPoint.getSslConnection().addHandshakeListener(new ALPNListener(alpn));
50+
}
51+
catch (RuntimeException x)
52+
{
53+
throw x;
54+
}
55+
catch (Exception x)
56+
{
57+
throw new RuntimeException(x);
58+
}
59+
}
60+
61+
private final class ALPNListener implements SslHandshakeListener
62+
{
63+
private final ALPNClientConnection alpnConnection;
64+
65+
private ALPNListener(ALPNClientConnection connection)
66+
{
67+
alpnConnection = connection;
68+
}
69+
70+
@Override
71+
public void handshakeSucceeded(Event event)
72+
{
73+
try
74+
{
75+
SSLEngine sslEngine = alpnConnection.getSSLEngine();
76+
String protocol = sslEngine.getApplicationProtocol();
77+
if (LOG.isDebugEnabled())
78+
LOG.debug("Selected {} for {}", protocol, alpnConnection);
79+
alpnConnection.selected(protocol);
80+
}
81+
catch (Throwable e)
82+
{
83+
LOG.warn("Unable to process BouncyCastle ApplicationProtocol for {}", alpnConnection, e);
84+
alpnConnection.selected(null);
85+
}
86+
}
87+
}
88+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.eclipse.jetty.alpn.bouncycastle.client.BouncyCastleClientALPNProcessor
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//
2+
// ========================================================================
3+
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
4+
//
5+
// This program and the accompanying materials are made available under the
6+
// terms of the Eclipse Public License v. 2.0 which is available at
7+
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
//
10+
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
// ========================================================================
12+
//
13+
14+
package org.eclipse.jetty.alpn.bouncycastle.client;
15+
16+
import java.net.InetSocketAddress;
17+
import java.net.Socket;
18+
import java.security.Security;
19+
import java.util.concurrent.CountDownLatch;
20+
import java.util.concurrent.TimeUnit;
21+
22+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
23+
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
24+
import org.eclipse.jetty.http.HttpFields;
25+
import org.eclipse.jetty.http.HttpURI;
26+
import org.eclipse.jetty.http.HttpVersion;
27+
import org.eclipse.jetty.http.MetaData;
28+
import org.eclipse.jetty.http2.api.Session;
29+
import org.eclipse.jetty.http2.api.Stream;
30+
import org.eclipse.jetty.http2.client.HTTP2Client;
31+
import org.eclipse.jetty.http2.frames.HeadersFrame;
32+
import org.eclipse.jetty.util.FuturePromise;
33+
import org.eclipse.jetty.util.Jetty;
34+
import org.eclipse.jetty.util.Promise;
35+
import org.eclipse.jetty.util.ssl.SslContextFactory;
36+
import org.junit.jupiter.api.Assumptions;
37+
import org.junit.jupiter.api.Tag;
38+
import org.junit.jupiter.api.Test;
39+
40+
import static org.junit.jupiter.api.Assertions.assertTrue;
41+
42+
public class BouncyCastleHTTP2ClientTest
43+
{
44+
@Tag("external")
45+
@Test
46+
public void testBouncyCastleHTTP2Client() throws Exception
47+
{
48+
String host = "webtide.com";
49+
int port = 443;
50+
51+
Assumptions.assumeTrue(canConnectTo(host, port));
52+
53+
// Required to provide a SecureRandom with name "DEFAULT" used by the BC JSSE provider.
54+
Security.insertProviderAt(new BouncyCastleProvider(), 1);
55+
Security.insertProviderAt(new BouncyCastleJsseProvider(), 2);
56+
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
57+
sslContextFactory.setProvider(BouncyCastleJsseProvider.PROVIDER_NAME);
58+
59+
try (HTTP2Client client = new HTTP2Client())
60+
{
61+
client.addBean(sslContextFactory);
62+
client.start();
63+
64+
FuturePromise<Session> sessionPromise = new FuturePromise<>();
65+
client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener() {}, sessionPromise);
66+
Session session = sessionPromise.get(15, TimeUnit.SECONDS);
67+
68+
HttpFields requestFields = HttpFields.build().put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
69+
MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields);
70+
HeadersFrame headersFrame = new HeadersFrame(metaData, null, true);
71+
CountDownLatch latch = new CountDownLatch(1);
72+
session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener()
73+
{
74+
@Override
75+
public void onHeaders(Stream stream, HeadersFrame frame)
76+
{
77+
System.err.println(frame);
78+
if (frame.isEndStream())
79+
latch.countDown();
80+
stream.demand();
81+
}
82+
83+
@Override
84+
public void onDataAvailable(Stream stream)
85+
{
86+
Stream.Data data = stream.readData();
87+
System.err.println(data);
88+
data.release();
89+
if (data.frame().isEndStream())
90+
latch.countDown();
91+
else
92+
stream.demand();
93+
}
94+
});
95+
96+
assertTrue(latch.await(15, TimeUnit.SECONDS));
97+
}
98+
}
99+
100+
private boolean canConnectTo(String host, int port)
101+
{
102+
try
103+
{
104+
new Socket(host, port).close();
105+
return true;
106+
}
107+
catch (Throwable x)
108+
{
109+
return false;
110+
}
111+
}
112+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Jetty Logging using jetty-slf4j-impl
2+
#org.eclipse.jetty.LEVEL=DEBUG
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.eclipse.jetty</groupId>
7+
<artifactId>jetty-alpn</artifactId>
8+
<version>12.0.17-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>jetty-alpn-bouncycastle-server</artifactId>
11+
<name>Core :: ALPN :: Bouncy Castle Server</name>
12+
13+
<properties>
14+
<bundle-symbolic-name>${project.groupId}.alpn.bouncycastle.server</bundle-symbolic-name>
15+
</properties>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>org.eclipse.jetty</groupId>
20+
<artifactId>jetty-alpn-server</artifactId>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.eclipse.jetty</groupId>
24+
<artifactId>jetty-io</artifactId>
25+
</dependency>
26+
<dependency>
27+
<groupId>org.slf4j</groupId>
28+
<artifactId>slf4j-api</artifactId>
29+
</dependency>
30+
31+
<dependency>
32+
<groupId>org.bouncycastle</groupId>
33+
<artifactId>bctls-jdk18on</artifactId>
34+
<version>${bouncycastle.version}</version>
35+
<scope>test</scope>
36+
</dependency>
37+
<dependency>
38+
<groupId>org.eclipse.jetty</groupId>
39+
<artifactId>jetty-alpn-bouncycastle-client</artifactId>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.eclipse.jetty</groupId>
44+
<artifactId>jetty-client</artifactId>
45+
<scope>test</scope>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.eclipse.jetty</groupId>
49+
<artifactId>jetty-slf4j-impl</artifactId>
50+
<scope>test</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.eclipse.jetty.http2</groupId>
54+
<artifactId>jetty-http2-client</artifactId>
55+
<scope>test</scope>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.eclipse.jetty.http2</groupId>
59+
<artifactId>jetty-http2-client-transport</artifactId>
60+
<scope>test</scope>
61+
</dependency>
62+
<dependency>
63+
<groupId>org.eclipse.jetty.http2</groupId>
64+
<artifactId>jetty-http2-server</artifactId>
65+
<scope>test</scope>
66+
</dependency>
67+
</dependencies>
68+
69+
<build>
70+
<plugins>
71+
<plugin>
72+
<groupId>org.apache.felix</groupId>
73+
<artifactId>maven-bundle-plugin</artifactId>
74+
<extensions>true</extensions>
75+
<configuration>
76+
<instructions>
77+
<Bundle-Description>Bouncy Castle ALPN</Bundle-Description>
78+
<Import-Package>${osgi.slf4j.import.packages},org.bouncycastle;version="${bouncycastle.version}",*</Import-Package>
79+
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)";resolution:=optional</Require-Capability>
80+
<Provide-Capability>osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.io.ssl.ALPNProcessor$Server</Provide-Capability>
81+
<_nouses>true</_nouses>
82+
</instructions>
83+
</configuration>
84+
</plugin>
85+
<plugin>
86+
<artifactId>maven-surefire-plugin</artifactId>
87+
<configuration>
88+
<argLine>@{argLine} ${jetty.surefire.argLine} --add-reads org.eclipse.jetty.alpn.bouncycastle.server=org.eclipse.jetty.server</argLine>
89+
</configuration>
90+
</plugin>
91+
</plugins>
92+
</build>
93+
</project>

0 commit comments

Comments
 (0)