1 /*
2 * Copyright 2014 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.handler.ssl;
17
18 import io.netty.buffer.ByteBufAllocator;
19
20 import javax.net.ssl.SSLEngine;
21
22 /**
23 * The {@link JdkApplicationProtocolNegotiator} to use if you need ALPN and are using {@link SslProvider#JDK}.
24 *
25 * @deprecated use {@link ApplicationProtocolConfig}.
26 */
27 @Deprecated
28 public final class JdkAlpnApplicationProtocolNegotiator extends JdkBaseApplicationProtocolNegotiator {
29 private static final boolean AVAILABLE = Conscrypt.isAvailable() ||
30 JdkAlpnSslUtils.supportsAlpn() ||
31 JettyAlpnSslEngine.isAvailable();
32
33 private static final SslEngineWrapperFactory ALPN_WRAPPER = AVAILABLE ? new AlpnWrapper() : new FailureWrapper();
34
35 /**
36 * Create a new instance.
37 * @param protocols The order of iteration determines the preference of support for protocols.
38 */
39 public JdkAlpnApplicationProtocolNegotiator(Iterable<String> protocols) {
40 this(false, protocols);
41 }
42
43 /**
44 * Create a new instance.
45 * @param protocols The order of iteration determines the preference of support for protocols.
46 */
47 public JdkAlpnApplicationProtocolNegotiator(String... protocols) {
48 this(false, protocols);
49 }
50
51 /**
52 * Create a new instance.
53 * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected.
54 * @param protocols The order of iteration determines the preference of support for protocols.
55 */
56 public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, Iterable<String> protocols) {
57 this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols);
58 }
59
60 /**
61 * Create a new instance.
62 * @param failIfNoCommonProtocols Fail with a fatal alert if not common protocols are detected.
63 * @param protocols The order of iteration determines the preference of support for protocols.
64 */
65 public JdkAlpnApplicationProtocolNegotiator(boolean failIfNoCommonProtocols, String... protocols) {
66 this(failIfNoCommonProtocols, failIfNoCommonProtocols, protocols);
67 }
68
69 /**
70 * Create a new instance.
71 * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected.
72 * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected.
73 * @param protocols The order of iteration determines the preference of support for protocols.
74 */
75 public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols,
76 boolean serverFailIfNoCommonProtocols, Iterable<String> protocols) {
77 this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY,
78 clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY,
79 protocols);
80 }
81
82 /**
83 * Create a new instance.
84 * @param clientFailIfNoCommonProtocols Client side fail with a fatal alert if not common protocols are detected.
85 * @param serverFailIfNoCommonProtocols Server side fail with a fatal alert if not common protocols are detected.
86 * @param protocols The order of iteration determines the preference of support for protocols.
87 */
88 public JdkAlpnApplicationProtocolNegotiator(boolean clientFailIfNoCommonProtocols,
89 boolean serverFailIfNoCommonProtocols, String... protocols) {
90 this(serverFailIfNoCommonProtocols ? FAIL_SELECTOR_FACTORY : NO_FAIL_SELECTOR_FACTORY,
91 clientFailIfNoCommonProtocols ? FAIL_SELECTION_LISTENER_FACTORY : NO_FAIL_SELECTION_LISTENER_FACTORY,
92 protocols);
93 }
94
95 /**
96 * Create a new instance.
97 * @param selectorFactory The factory which provides classes responsible for selecting the protocol.
98 * @param listenerFactory The factory which provides to be notified of which protocol was selected.
99 * @param protocols The order of iteration determines the preference of support for protocols.
100 */
101 public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory,
102 ProtocolSelectionListenerFactory listenerFactory, Iterable<String> protocols) {
103 super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols);
104 }
105
106 /**
107 * Create a new instance.
108 * @param selectorFactory The factory which provides classes responsible for selecting the protocol.
109 * @param listenerFactory The factory which provides to be notified of which protocol was selected.
110 * @param protocols The order of iteration determines the preference of support for protocols.
111 */
112 public JdkAlpnApplicationProtocolNegotiator(ProtocolSelectorFactory selectorFactory,
113 ProtocolSelectionListenerFactory listenerFactory, String... protocols) {
114 super(ALPN_WRAPPER, selectorFactory, listenerFactory, protocols);
115 }
116
117 private static final class FailureWrapper extends AllocatorAwareSslEngineWrapperFactory {
118 @Override
119 public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
120 JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
121 throw new RuntimeException("ALPN unsupported. Is your classpath configured correctly?"
122 + " For Conscrypt, add the appropriate Conscrypt JAR to classpath and set the security provider."
123 + " For Jetty-ALPN, see "
124 + "http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-starting");
125 }
126 }
127
128 private static final class AlpnWrapper extends AllocatorAwareSslEngineWrapperFactory {
129 @Override
130 public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc,
131 JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
132 if (Conscrypt.isEngineSupported(engine)) {
133 return isServer ? ConscryptAlpnSslEngine.newServerEngine(engine, alloc, applicationNegotiator)
134 : ConscryptAlpnSslEngine.newClientEngine(engine, alloc, applicationNegotiator);
135 }
136 // ALPN support was recently backported to Java8 as
137 // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8230977.
138 // Because of this lets not do a Java version runtime check but just depend on if the required methods are
139 // present
140 if (JdkAlpnSslUtils.supportsAlpn()) {
141 return new JdkAlpnSslEngine(engine, applicationNegotiator, isServer);
142 }
143 if (JettyAlpnSslEngine.isAvailable()) {
144 return isServer ? JettyAlpnSslEngine.newServerEngine(engine, applicationNegotiator)
145 : JettyAlpnSslEngine.newClientEngine(engine, applicationNegotiator);
146 }
147 throw new UnsupportedOperationException("ALPN not supported. Unable to wrap SSLEngine of type '"
148 + engine.getClass().getName() + "')");
149 }
150 }
151
152 static boolean isAlpnSupported() {
153 return AVAILABLE;
154 }
155 }
156