|
|
|
@ -1,305 +0,0 @@
|
|
|
|
|
// ========================================================================
|
|
|
|
|
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
|
|
|
|
// ========================================================================
|
|
|
|
|
// All rights reserved. This program and the accompanying materials
|
|
|
|
|
// are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
|
// and Apache License v2.0 which accompanies this distribution.
|
|
|
|
|
//
|
|
|
|
|
// The Eclipse Public License is available at
|
|
|
|
|
// http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
|
//
|
|
|
|
|
// The Apache License v2.0 is available at
|
|
|
|
|
// http://www.opensource.org/licenses/apache2.0.php
|
|
|
|
|
//
|
|
|
|
|
// You may elect to redistribute this code under either of these licenses.
|
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
|
|
How to build NPN
|
|
|
|
|
================
|
|
|
|
|
|
|
|
|
|
[[npn]]
|
|
|
|
|
=
|
|
|
|
|
|
|
|
|
|
[[npn-introduction]]
|
|
|
|
|
== Configuring NPN
|
|
|
|
|
|
|
|
|
|
The Jetty project provides an implementation of the Transport Layer
|
|
|
|
|
Security (TLS) extension for Next Protocol Negotiation (NPN) for OpenJDK
|
|
|
|
|
7 (but not for OpenJDK 8 or greater - see xref:alpn-chapter[] for
|
|
|
|
|
using a TLS protocol negotiation extension with OpenJDK 8 or greater).
|
|
|
|
|
NPN allows the application layer to negotiate which protocol to use over
|
|
|
|
|
the secure connection.
|
|
|
|
|
|
|
|
|
|
NPN currently negotiates using SPDY as an application level protocol on
|
|
|
|
|
port 443, and also negotiates the SPDY version. However, NPN is not
|
|
|
|
|
SPDY-specific in any way. Jetty's NPN implementation, although hosted
|
|
|
|
|
under the umbrella of the Jetty project, is independent of Jetty (the
|
|
|
|
|
servlet container); you can use it in any other Java network server.
|
|
|
|
|
|
|
|
|
|
[[npn-starting]]
|
|
|
|
|
== Starting the JVM
|
|
|
|
|
|
|
|
|
|
To enable NPN support, start the JVM as follows:
|
|
|
|
|
|
|
|
|
|
[source, plain, subs="{sub-order}"]
|
|
|
|
|
----
|
|
|
|
|
java -Xbootclasspath/p:<path_to_npn_boot_jar> ...
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
where `path_to_npn_boot_jar` is the path on the file system for the NPN
|
|
|
|
|
Boot Jar file, for example, one at the Maven coordinates
|
|
|
|
|
org.mortbay.jetty.npn:npn-boot.
|
|
|
|
|
|
|
|
|
|
Be aware that the current versions of the npn packages no longer align
|
|
|
|
|
with Jetty versions. Look at the dates in those file paths before
|
|
|
|
|
looking at the version number.
|
|
|
|
|
|
|
|
|
|
[[npn-osgi]]
|
|
|
|
|
=== Starting in OSGi
|
|
|
|
|
|
|
|
|
|
To use NPN in an OSGi environment, in addition to putting the NPN jar on
|
|
|
|
|
the boot classpath for the container, you will also need to deploy the
|
|
|
|
|
jetty-osgi-npn jar. This jar contains a Fragment-Host directive that
|
|
|
|
|
ensures the NPN classes will be available from the system bundle.
|
|
|
|
|
|
|
|
|
|
You can download the jetty-osgi-npn jar from maven central:
|
|
|
|
|
http://central.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-npn/
|
|
|
|
|
|
|
|
|
|
[[npn-understanding]]
|
|
|
|
|
== Understanding the NPN API
|
|
|
|
|
|
|
|
|
|
Applications need to interact with NPN TLS extension protocol
|
|
|
|
|
negotiations. For example, server applications need to know whether the
|
|
|
|
|
client supports NPN, and client applications needs to know the list of
|
|
|
|
|
protocols the server supports, and so on.
|
|
|
|
|
|
|
|
|
|
To implement this interaction, Jetty's NPN implementation provides an
|
|
|
|
|
API to applications, hosted at Maven coordinates
|
|
|
|
|
org.eclipse.jetty.npn:npn-api. You need to declare this dependency as
|
|
|
|
|
provided, because the npn-boot Jar already includes it (see the previous
|
|
|
|
|
section), and it is therefore available in the boot classpath.
|
|
|
|
|
|
|
|
|
|
The API consists of a single class,
|
|
|
|
|
`org.eclipse.jetty.npn.NextProtoNego`, and applications need to register
|
|
|
|
|
instances of SSLSocket or SSLEngine with a ClientProvider or
|
|
|
|
|
ServerProvider (depending on whether the application is a client or
|
|
|
|
|
server application). Refer to NextProtoNego Javadocs and to the examples
|
|
|
|
|
below for further details about client and server provider methods.
|
|
|
|
|
|
|
|
|
|
[[client-example]]
|
|
|
|
|
== Client Example
|
|
|
|
|
|
|
|
|
|
[source, java, subs="{sub-order}"]
|
|
|
|
|
----
|
|
|
|
|
SSLContext sslContext = ...;
|
|
|
|
|
final SSLSocket sslSocket = (SSLSocket)context.getSocketFactory().createSocket("localhost", server.getLocalPort());
|
|
|
|
|
|
|
|
|
|
NextProtoNego.put(sslSocket, new NextProtoNego.ClientProvider()
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public boolean supports()
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void unsupported()
|
|
|
|
|
{
|
|
|
|
|
NextProtoNego.remove(sslSocket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String selectProtocol(List<String> protocols)
|
|
|
|
|
{
|
|
|
|
|
NextProtoNego.remove(sslSocket);
|
|
|
|
|
return protocols.get(0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
The NPN implementation calls `NextProtoNego.ClientProvider` methods
|
|
|
|
|
`supports()`, `unsupported()` and `selectProtocol(List<String>)`, so
|
|
|
|
|
that the client application can:
|
|
|
|
|
|
|
|
|
|
* decide whether to support NPN.
|
|
|
|
|
* know whether the server supports NPN.
|
|
|
|
|
* select one of the protocols the server supports.
|
|
|
|
|
|
|
|
|
|
[[server-example]]
|
|
|
|
|
== Server Example
|
|
|
|
|
|
|
|
|
|
The example for SSLEngine is identical, and you just need to replace the
|
|
|
|
|
SSLSocket instance with an SSLEngine instance.
|
|
|
|
|
|
|
|
|
|
[source, java, subs="{sub-order}"]
|
|
|
|
|
----
|
|
|
|
|
final SSLSocket sslSocket = ...;
|
|
|
|
|
NextProtoNego.put(sslSocket, new NextProtoNego.ServerProvider()
|
|
|
|
|
{
|
|
|
|
|
@Override
|
|
|
|
|
public void unsupported()
|
|
|
|
|
{
|
|
|
|
|
NextProtoNego.remove(sslSocket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<String> protocols()
|
|
|
|
|
{
|
|
|
|
|
return Arrays.asList("http/1.1");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void protocolSelected(String protocol)
|
|
|
|
|
{
|
|
|
|
|
NextProtoNego.remove(sslSocket);
|
|
|
|
|
System.out.println("Protocol Selected is: " + protocol);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
The NPN implementation calls `NextProtoNego.ServerProvider` methods
|
|
|
|
|
`unsupported()`, `protocols()` and `protocolSelected(String),` so that
|
|
|
|
|
the server application can:
|
|
|
|
|
|
|
|
|
|
* know whether the client supports NPN.
|
|
|
|
|
* provide the list of protocols the server supports.
|
|
|
|
|
* know which protocol the client chooses.
|
|
|
|
|
|
|
|
|
|
[[npn-implementation]]
|
|
|
|
|
== Implementation Details
|
|
|
|
|
|
|
|
|
|
It is common that the NextProtoNego.ServerProvider and the
|
|
|
|
|
NextProtoNego.ClientProvider are implemented as (anonymous) inner
|
|
|
|
|
classes, and that their methods' implementations require references to
|
|
|
|
|
the the sslSocket (or sslEngine), either directly or indirectly.
|
|
|
|
|
|
|
|
|
|
Since the NextProtoNego class holds [sslSocket/sslEngine, provider]
|
|
|
|
|
pairs in a `WeakHashMap`, if the value (that is, the provider
|
|
|
|
|
implementation) holds a strong (even indirect) reference to the key,
|
|
|
|
|
then the `WeakHashMap` entries are never removed, leading to a memory
|
|
|
|
|
leak.
|
|
|
|
|
|
|
|
|
|
It is important that implementations of `NextProtoNego.ServerProvider`
|
|
|
|
|
and `NextProtoNego.ClientProvider` remove the `sslSocket` or `sslEngine`
|
|
|
|
|
when the negotiation is complete, like shown in the examples above.
|
|
|
|
|
|
|
|
|
|
Be aware that declaring the SslConnection as a final local variable and
|
|
|
|
|
referencing it from within the anonymous NextProtoNego.ServerProvider
|
|
|
|
|
class generates a hidden field in the anonymous inner class, that may
|
|
|
|
|
cause a memory leak if the implementation does not call
|
|
|
|
|
`NextProtoNego.remove()`.
|
|
|
|
|
|
|
|
|
|
[[npn-tests]]
|
|
|
|
|
== Unit Tests
|
|
|
|
|
|
|
|
|
|
You can write and run unit tests that use the NPN implementation. The
|
|
|
|
|
solution that we use with Maven is to specify an additional command line
|
|
|
|
|
argument to the Surefire plugin:
|
|
|
|
|
|
|
|
|
|
[source, xml, subs="{sub-order}"]
|
|
|
|
|
----
|
|
|
|
|
<project>
|
|
|
|
|
|
|
|
|
|
<properties>
|
|
|
|
|
<npn-version>1.1.1.v20121030</npn-version>
|
|
|
|
|
</properties>
|
|
|
|
|
|
|
|
|
|
<build>
|
|
|
|
|
<plugins>
|
|
|
|
|
<plugin>
|
|
|
|
|
<artifactId>maven-surefire-plugin</artifactId>
|
|
|
|
|
<configuration>
|
|
|
|
|
<argLine>
|
|
|
|
|
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn-version}/npn-boot-${npn-version}.jar
|
|
|
|
|
</argLine>
|
|
|
|
|
</configuration>
|
|
|
|
|
</plugin>
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
</plugins>
|
|
|
|
|
</build>
|
|
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
</project>
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
[[npn-debugging]]
|
|
|
|
|
== Debugging
|
|
|
|
|
|
|
|
|
|
You can enable debug logging for the NPN implementation in this way:
|
|
|
|
|
|
|
|
|
|
....
|
|
|
|
|
NextProtoNego.debug = true;
|
|
|
|
|
....
|
|
|
|
|
|
|
|
|
|
Since the NextProtoNego class is in the boot classpath, we chose not to
|
|
|
|
|
use logging libraries because we do not want to override application
|
|
|
|
|
logging library choices; therefore the logging is performed directly on
|
|
|
|
|
`System.err.`
|
|
|
|
|
|
|
|
|
|
[[npn-license-details]]
|
|
|
|
|
== License Details
|
|
|
|
|
|
|
|
|
|
The NPN implementation relies on modification of a few OpenJDK classes
|
|
|
|
|
and on a few new classes that need to live in the `sun.security.ssl`
|
|
|
|
|
package. These classes are released under the same GPLv2+exception
|
|
|
|
|
license of OpenJDK.
|
|
|
|
|
|
|
|
|
|
The NextProtoNego class is released under same license as the classes of
|
|
|
|
|
the Jetty project.
|
|
|
|
|
|
|
|
|
|
[[npn-versions]]
|
|
|
|
|
== Versions
|
|
|
|
|
|
|
|
|
|
The NPN implementation, relying on modifications of OpenJDK classes,
|
|
|
|
|
updates every time there are updates to the modified OpenJDK classes.
|
|
|
|
|
|
|
|
|
|
.NPN vs. OpenJDK versions
|
|
|
|
|
[cols=",",options="header",]
|
|
|
|
|
|==========================================================
|
|
|
|
|
|NPN version |OpenJDK version
|
|
|
|
|
|1.0.0.v20120402 |1.7.0 - 1.7.0u2 - 1.7.0u3
|
|
|
|
|
|1.1.0.v20120525 |1.7.0u4 - 1.7.0u5
|
|
|
|
|
|1.1.1.v20121030 |1.7.0u6 - 1.7.0u7
|
|
|
|
|
|1.1.3.v20130313 |1.7.0u9 - 1.7.0u10 - 1.7.0u11
|
|
|
|
|
|1.1.4.v20130313 |1.7.0u13
|
|
|
|
|
|1.1.5.v20130313 |1.7.0u15 - 1.7.0u17 - 1.7.0u21 - 1.7.0u25
|
|
|
|
|
|1.1.6.v20130911 |1.7.0u40 - 1.7.0u45 - 1.7.0u51
|
|
|
|
|
|1.1.8.v20141013 |1.7.0u55 - 1.7.0u60 - 1.7.0u65 - 1.7.0u67
|
|
|
|
|
|1.1.9.v20141016 |1.7.0u71 - 1.7.0u72
|
|
|
|
|
|1.1.10.v20150130 |1.7.0u75 - 1.7.0u76 - 1.7.0u79
|
|
|
|
|
|1.1.11.v20150415 |1.7.0u80
|
|
|
|
|
|==========================================================
|
|
|
|
|
|
|
|
|
|
[[npn-build]]
|
|
|
|
|
== How to build NPN
|
|
|
|
|
|
|
|
|
|
This section is for Jetty developers that need to update the NPN
|
|
|
|
|
implementation with the OpenJDK versions.
|
|
|
|
|
|
|
|
|
|
Clone the OpenJDK repository with the following command:
|
|
|
|
|
|
|
|
|
|
[source, screen, subs="{sub-order}"]
|
|
|
|
|
....
|
|
|
|
|
$ hg clone http://hg.openjdk.java.net/jdk7u/jdk7u jdk7u
|
|
|
|
|
$ cd jdk7u
|
|
|
|
|
$ ./get_source.sh
|
|
|
|
|
|
|
|
|
|
....
|
|
|
|
|
|
|
|
|
|
To update the source to a specific tag, use the following command:
|
|
|
|
|
|
|
|
|
|
[source, screen, subs="{sub-order}"]
|
|
|
|
|
....
|
|
|
|
|
$ ./make/scripts/hgforest.sh update <tag-name>
|
|
|
|
|
|
|
|
|
|
....
|
|
|
|
|
|
|
|
|
|
The list of OpenJDK tags can be obtained from
|
|
|
|
|
http://hg.openjdk.java.net/jdk7u/jdk7u/tags[this page].
|
|
|
|
|
|
|
|
|
|
Then you need to compare and incorporate the OpenJDK source changes into
|
|
|
|
|
the modified OpenJDK classes at the
|
|
|
|
|
https://github.com/jetty-project/jetty-npn[NPN GitHub Repository].
|